/src/FreeImage/Source/OpenEXR/Imath/ImathRandom.h

https://bitbucket.org/cabalistic/ogredeps/ · C++ Header · 398 lines · 166 code · 109 blank · 123 comment · 9 complexity · 710dd10f26c39a4f75993eb2e053e107 MD5 · raw file

  1. ///////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
  4. // Digital Ltd. LLC
  5. //
  6. // All rights reserved.
  7. //
  8. // Redistribution and use in source and binary forms, with or without
  9. // modification, are permitted provided that the following conditions are
  10. // met:
  11. // * Redistributions of source code must retain the above copyright
  12. // notice, this list of conditions and the following disclaimer.
  13. // * Redistributions in binary form must reproduce the above
  14. // copyright notice, this list of conditions and the following disclaimer
  15. // in the documentation and/or other materials provided with the
  16. // distribution.
  17. // * Neither the name of Industrial Light & Magic nor the names of
  18. // its contributors may be used to endorse or promote products derived
  19. // from this software without specific prior written permission.
  20. //
  21. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  24. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  25. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  26. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  27. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  28. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  29. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  31. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. //
  33. ///////////////////////////////////////////////////////////////////////////
  34. #ifndef INCLUDED_IMATHRANDOM_H
  35. #define INCLUDED_IMATHRANDOM_H
  36. //-----------------------------------------------------------------------------
  37. //
  38. // Generators for uniformly distributed pseudo-random numbers and
  39. // functions that use those generators to generate numbers with
  40. // non-uniform distributions:
  41. //
  42. // class Rand32
  43. // class Rand48
  44. // solidSphereRand()
  45. // hollowSphereRand()
  46. // gaussRand()
  47. // gaussSphereRand()
  48. //
  49. // Note: class Rand48() calls erand48() and nrand48(), which are not
  50. // available on all operating systems. For compatibility we include
  51. // our own versions of erand48() and nrand48(). Our functions have
  52. // been reverse-engineered from the corresponding Unix/Linux man page.
  53. //
  54. //-----------------------------------------------------------------------------
  55. #include <stdlib.h>
  56. #include <math.h>
  57. namespace Imath {
  58. //-----------------------------------------------
  59. // Fast random-number generator that generates
  60. // a uniformly distributed sequence with a period
  61. // length of 2^32.
  62. //-----------------------------------------------
  63. class Rand32
  64. {
  65. public:
  66. //------------
  67. // Constructor
  68. //------------
  69. Rand32 (unsigned long int seed = 0);
  70. //--------------------------------
  71. // Re-initialize with a given seed
  72. //--------------------------------
  73. void init (unsigned long int seed);
  74. //----------------------------------------------------------
  75. // Get the next value in the sequence (range: [false, true])
  76. //----------------------------------------------------------
  77. bool nextb ();
  78. //---------------------------------------------------------------
  79. // Get the next value in the sequence (range: [0 ... 0xffffffff])
  80. //---------------------------------------------------------------
  81. unsigned long int nexti ();
  82. //------------------------------------------------------
  83. // Get the next value in the sequence (range: [0 ... 1[)
  84. //------------------------------------------------------
  85. float nextf ();
  86. //-------------------------------------------------------------------
  87. // Get the next value in the sequence (range [rangeMin ... rangeMax[)
  88. //-------------------------------------------------------------------
  89. float nextf (float rangeMin, float rangeMax);
  90. private:
  91. void next ();
  92. unsigned long int _state;
  93. };
  94. //--------------------------------------------------------
  95. // Random-number generator based on the C Standard Library
  96. // functions erand48(), nrand48() & company; generates a
  97. // uniformly distributed sequence.
  98. //--------------------------------------------------------
  99. class Rand48
  100. {
  101. public:
  102. //------------
  103. // Constructor
  104. //------------
  105. Rand48 (unsigned long int seed = 0);
  106. //--------------------------------
  107. // Re-initialize with a given seed
  108. //--------------------------------
  109. void init (unsigned long int seed);
  110. //----------------------------------------------------------
  111. // Get the next value in the sequence (range: [false, true])
  112. //----------------------------------------------------------
  113. bool nextb ();
  114. //---------------------------------------------------------------
  115. // Get the next value in the sequence (range: [0 ... 0x7fffffff])
  116. //---------------------------------------------------------------
  117. long int nexti ();
  118. //------------------------------------------------------
  119. // Get the next value in the sequence (range: [0 ... 1[)
  120. //------------------------------------------------------
  121. double nextf ();
  122. //-------------------------------------------------------------------
  123. // Get the next value in the sequence (range [rangeMin ... rangeMax[)
  124. //-------------------------------------------------------------------
  125. double nextf (double rangeMin, double rangeMax);
  126. private:
  127. unsigned short int _state[3];
  128. };
  129. //------------------------------------------------------------
  130. // Return random points uniformly distributed in a sphere with
  131. // radius 1 around the origin (distance from origin <= 1).
  132. //------------------------------------------------------------
  133. template <class Vec, class Rand>
  134. Vec
  135. solidSphereRand (Rand &rand);
  136. //-------------------------------------------------------------
  137. // Return random points uniformly distributed on the surface of
  138. // a sphere with radius 1 around the origin.
  139. //-------------------------------------------------------------
  140. template <class Vec, class Rand>
  141. Vec
  142. hollowSphereRand (Rand &rand);
  143. //-----------------------------------------------
  144. // Return random numbers with a normal (Gaussian)
  145. // distribution with zero mean and unit variance.
  146. //-----------------------------------------------
  147. template <class Rand>
  148. float
  149. gaussRand (Rand &rand);
  150. //----------------------------------------------------
  151. // Return random points whose distance from the origin
  152. // has a normal (Gaussian) distribution with zero mean
  153. // and unit variance.
  154. //----------------------------------------------------
  155. template <class Vec, class Rand>
  156. Vec
  157. gaussSphereRand (Rand &rand);
  158. //---------------------------------
  159. // erand48(), nrand48() and friends
  160. //---------------------------------
  161. double erand48 (unsigned short state[3]);
  162. double drand48 ();
  163. long int nrand48 (unsigned short state[3]);
  164. long int lrand48 ();
  165. void srand48 (long int seed);
  166. //---------------
  167. // Implementation
  168. //---------------
  169. inline void
  170. Rand32::init (unsigned long int seed)
  171. {
  172. _state = (seed * 0xa5a573a5L) ^ 0x5a5a5a5aL;
  173. }
  174. inline
  175. Rand32::Rand32 (unsigned long int seed)
  176. {
  177. init (seed);
  178. }
  179. inline void
  180. Rand32::next ()
  181. {
  182. _state = 1664525L * _state + 1013904223L;
  183. }
  184. inline bool
  185. Rand32::nextb ()
  186. {
  187. next ();
  188. // Return the 31st (most significant) bit, by and-ing with 2 ^ 31.
  189. return !!(_state & 2147483648UL);
  190. }
  191. inline unsigned long int
  192. Rand32::nexti ()
  193. {
  194. next ();
  195. return _state & 0xffffffff;
  196. }
  197. inline float
  198. Rand32::nextf (float rangeMin, float rangeMax)
  199. {
  200. float f = nextf();
  201. return rangeMin * (1 - f) + rangeMax * f;
  202. }
  203. inline void
  204. Rand48::init (unsigned long int seed)
  205. {
  206. seed = (seed * 0xa5a573a5L) ^ 0x5a5a5a5aL;
  207. _state[0] = (unsigned short int) (seed & 0xFFFF);
  208. _state[1] = (unsigned short int) ((seed >> 16) & 0xFFFF);
  209. _state[2] = (unsigned short int) (seed & 0xFFFF);
  210. }
  211. inline
  212. Rand48::Rand48 (unsigned long int seed)
  213. {
  214. init (seed);
  215. }
  216. inline bool
  217. Rand48::nextb ()
  218. {
  219. return Imath::nrand48 (_state) & 1;
  220. }
  221. inline long int
  222. Rand48::nexti ()
  223. {
  224. return Imath::nrand48 (_state);
  225. }
  226. inline double
  227. Rand48::nextf ()
  228. {
  229. return Imath::erand48 (_state);
  230. }
  231. inline double
  232. Rand48::nextf (double rangeMin, double rangeMax)
  233. {
  234. double f = nextf();
  235. return rangeMin * (1 - f) + rangeMax * f;
  236. }
  237. template <class Vec, class Rand>
  238. Vec
  239. solidSphereRand (Rand &rand)
  240. {
  241. Vec v;
  242. do
  243. {
  244. for (unsigned int i = 0; i < Vec::dimensions(); i++)
  245. v[i] = (typename Vec::BaseType) rand.nextf (-1, 1);
  246. }
  247. while (v.length2() > 1);
  248. return v;
  249. }
  250. template <class Vec, class Rand>
  251. Vec
  252. hollowSphereRand (Rand &rand)
  253. {
  254. Vec v;
  255. typename Vec::BaseType length;
  256. do
  257. {
  258. for (unsigned int i = 0; i < Vec::dimensions(); i++)
  259. v[i] = (typename Vec::BaseType) rand.nextf (-1, 1);
  260. length = v.length();
  261. }
  262. while (length > 1 || length == 0);
  263. return v / length;
  264. }
  265. template <class Rand>
  266. float
  267. gaussRand (Rand &rand)
  268. {
  269. float x; // Note: to avoid numerical problems with very small
  270. float y; // numbers, we make these variables singe-precision
  271. float length2; // floats, but later we call the double-precision log()
  272. // and sqrt() functions instead of logf() and sqrtf().
  273. do
  274. {
  275. x = float (rand.nextf (-1, 1));
  276. y = float (rand.nextf (-1, 1));
  277. length2 = x * x + y * y;
  278. }
  279. while (length2 >= 1 || length2 == 0);
  280. return x * sqrt (-2 * log (double (length2)) / length2);
  281. }
  282. template <class Vec, class Rand>
  283. Vec
  284. gaussSphereRand (Rand &rand)
  285. {
  286. return hollowSphereRand <Vec> (rand) * gaussRand (rand);
  287. }
  288. } // namespace Imath
  289. #endif