HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ImathRandom.h
Go to the documentation of this file.
1 //
2 // SPDX-License-Identifier: BSD-3-Clause
3 // Copyright Contributors to the OpenEXR Project.
4 //
5 
6 //
7 // Generators for uniformly distributed pseudo-random numbers and
8 // functions that use those generators to generate numbers with
9 // non-uniform distributions
10 //
11 // Note: class Rand48() calls erand48() and nrand48(), which are not
12 // available on all operating systems. For compatibility we include
13 // our own versions of erand48() and nrand48(). Our functions
14 // have been reverse-engineered from the corresponding Unix/Linux
15 // man page.
16 //
17 
18 #ifndef INCLUDED_IMATHRANDOM_H
19 #define INCLUDED_IMATHRANDOM_H
20 
21 #include "ImathExport.h"
22 #include "ImathNamespace.h"
23 
24 #include <math.h>
25 #include <stdlib.h>
26 
27 IMATH_INTERNAL_NAMESPACE_HEADER_ENTER
28 
29 /// Fast random-number generator that generates
30 /// a uniformly distributed sequence with a period
31 /// length of 2^32.
33 {
34  public:
35 
36  /// Constructor, given a seed
37  IMATH_HOSTDEVICE Rand32 (unsigned long int seed = 0);
38 
39  /// Re-initialize with a given seed
40  IMATH_HOSTDEVICE void init (unsigned long int seed);
41 
42  /// Get the next value in the sequence (range: [false, true])
43  IMATH_HOSTDEVICE bool nextb();
44 
45  /// Get the next value in the sequence (range: [0 ... 0xffffffff])
46  IMATH_HOSTDEVICE unsigned long int nexti();
47 
48  /// Get the next value in the sequence (range: [0 ... 1[)
49  IMATH_HOSTDEVICE float nextf();
50 
51  /// Get the next value in the sequence (range [rangeMin ... rangeMax[)
52  IMATH_HOSTDEVICE float nextf (float rangeMin, float rangeMax);
53 
54  private:
55  IMATH_HOSTDEVICE void next();
56 
57  unsigned long int _state;
58 };
59 
60 /// Random-number generator based on the C Standard Library
61 /// functions erand48(), nrand48() & company; generates a
62 /// uniformly distributed sequence.
63 class Rand48
64 {
65  public:
66 
67  /// Constructor
68  IMATH_HOSTDEVICE Rand48 (unsigned long int seed = 0);
69 
70  /// Re-initialize with a given seed
71  IMATH_HOSTDEVICE void init (unsigned long int seed);
72 
73  /// Get the next value in the sequence (range: [false, true])
74  IMATH_HOSTDEVICE bool nextb();
75 
76  /// Get the next value in the sequence (range: [0 ... 0x7fffffff])
77  IMATH_HOSTDEVICE long int nexti();
78 
79  /// Get the next value in the sequence (range: [0 ... 1[)
80  IMATH_HOSTDEVICE double nextf();
81 
82  /// Get the next value in the sequence (range [rangeMin ... rangeMax[)
83  IMATH_HOSTDEVICE double nextf (double rangeMin, double rangeMax);
84 
85  private:
86  unsigned short int _state[3];
87 };
88 
89 /// Return random points uniformly distributed in a sphere with
90 /// radius 1 around the origin (distance from origin <= 1).
91 template <class Vec, class Rand> IMATH_HOSTDEVICE Vec solidSphereRand (Rand& rand);
92 
93 /// Return random points uniformly distributed on the surface of
94 /// a sphere with radius 1 around the origin.
95 template <class Vec, class Rand> IMATH_HOSTDEVICE Vec hollowSphereRand (Rand& rand);
96 
97 /// Return random numbers with a normal (Gaussian)
98 /// distribution with zero mean and unit variance.
99 template <class Rand> IMATH_HOSTDEVICE float gaussRand (Rand& rand);
100 
101 /// Return random points whose distance from the origin
102 /// has a normal (Gaussian) distribution with zero mean
103 /// and unit variance.
104 template <class Vec, class Rand> IMATH_HOSTDEVICE Vec gaussSphereRand (Rand& rand);
105 
106 //---------------------------------
107 // erand48(), nrand48() and friends
108 //---------------------------------
109 
110 /// @cond Doxygen_Suppress
111 IMATH_HOSTDEVICE IMATH_EXPORT double erand48 (unsigned short state[3]);
113 IMATH_HOSTDEVICE IMATH_EXPORT long int nrand48 (unsigned short state[3]);
114 IMATH_HOSTDEVICE IMATH_EXPORT long int lrand48();
115 IMATH_HOSTDEVICE IMATH_EXPORT void srand48 (long int seed);
116 /// @endcond
117 
118 //---------------
119 // Implementation
120 //---------------
121 
122 IMATH_HOSTDEVICE inline void
123 Rand32::init (unsigned long int seed)
124 {
125  _state = (seed * 0xa5a573a5L) ^ 0x5a5a5a5aL;
126 }
127 
128 IMATH_HOSTDEVICE inline Rand32::Rand32 (unsigned long int seed)
129 {
130  init (seed);
131 }
132 
133 IMATH_HOSTDEVICE inline void
134 Rand32::next()
135 {
136  _state = 1664525L * _state + 1013904223L;
137 }
138 
139 IMATH_HOSTDEVICE inline bool
141 {
142  next();
143  // Return the 31st (most significant) bit, by and-ing with 2 ^ 31.
144  return !!(_state & 2147483648UL);
145 }
146 
147 IMATH_HOSTDEVICE inline unsigned long int
149 {
150  next();
151  return _state & 0xffffffff;
152 }
153 
154 IMATH_HOSTDEVICE inline float
155 Rand32::nextf (float rangeMin, float rangeMax)
156 {
157  float f = nextf();
158  return rangeMin * (1 - f) + rangeMax * f;
159 }
160 
161 IMATH_HOSTDEVICE inline void
162 Rand48::init (unsigned long int seed)
163 {
164  seed = (seed * 0xa5a573a5L) ^ 0x5a5a5a5aL;
165 
166  _state[0] = (unsigned short int) (seed & 0xFFFF);
167  _state[1] = (unsigned short int) ((seed >> 16) & 0xFFFF);
168  _state[2] = (unsigned short int) (seed & 0xFFFF);
169 }
170 
171 IMATH_HOSTDEVICE inline Rand48::Rand48 (unsigned long int seed)
172 {
173  init (seed);
174 }
175 
176 IMATH_HOSTDEVICE inline bool
178 {
179  return nrand48 (_state) & 1;
180 }
181 
182 IMATH_HOSTDEVICE inline long int
184 {
185  return nrand48 (_state);
186 }
187 
188 IMATH_HOSTDEVICE inline double
190 {
191  return erand48 (_state);
192 }
193 
194 IMATH_HOSTDEVICE inline double
195 Rand48::nextf (double rangeMin, double rangeMax)
196 {
197  double f = nextf();
198  return rangeMin * (1 - f) + rangeMax * f;
199 }
200 
201 template <class Vec, class Rand>
203 solidSphereRand (Rand& rand)
204 {
205  Vec v;
206 
207  do
208  {
209  for (unsigned int i = 0; i < Vec::dimensions(); i++)
210  v[i] = (typename Vec::BaseType) rand.nextf (-1, 1);
211  } while (v.length2() > 1);
212 
213  return v;
214 }
215 
216 template <class Vec, class Rand>
218 hollowSphereRand (Rand& rand)
219 {
220  Vec v;
221  typename Vec::BaseType length;
222 
223  do
224  {
225  for (unsigned int i = 0; i < Vec::dimensions(); i++)
226  v[i] = (typename Vec::BaseType) rand.nextf (-1, 1);
227 
228  length = v.length();
229  } while (length > 1 || length == 0);
230 
231  return v / length;
232 }
233 
234 template <class Rand>
235 IMATH_HOSTDEVICE float
236 gaussRand (Rand& rand)
237 {
238  float x; // Note: to avoid numerical problems with very small
239  float y; // numbers, we make these variables singe-precision
240  float length2; // floats, but later we call the double-precision log()
241  // and sqrt() functions instead of logf() and sqrtf().
242  do
243  {
244  x = float (rand.nextf (-1, 1));
245  y = float (rand.nextf (-1, 1));
246  length2 = x * x + y * y;
247  } while (length2 >= 1 || length2 == 0);
248 
249  return x * sqrt (-2 * log (double (length2)) / length2);
250 }
251 
252 template <class Vec, class Rand>
254 gaussSphereRand (Rand& rand)
255 {
256  return hollowSphereRand<Vec> (rand) * gaussRand (rand);
257 }
258 
259 IMATH_INTERNAL_NAMESPACE_HEADER_EXIT
260 
261 #endif // INCLUDED_IMATHRANDOM_H
typedef int(APIENTRYP RE_PFNGLXSWAPINTERVALSGIPROC)(int)
IMATH_HOSTDEVICE Vec gaussSphereRand(Rand &rand)
Definition: ImathRandom.h:254
const GLdouble * v
Definition: glcorearb.h:837
IMATH_HOSTDEVICE float nextf()
Get the next value in the sequence (range: [0 ... 1[)
vfloat4 sqrt(const vfloat4 &a)
Definition: simd.h:7481
GLuint GLsizei GLsizei * length
Definition: glcorearb.h:795
GLint y
Definition: glcorearb.h:103
IMATH_HOSTDEVICE void init(unsigned long int seed)
Re-initialize with a given seed.
Definition: ImathRandom.h:123
#define IMATH_HOSTDEVICE
Definition: ImathConfig.h:102
IMATH_HOSTDEVICE long int nexti()
Get the next value in the sequence (range: [0 ... 0x7fffffff])
Definition: ImathRandom.h:183
GLfloat f
Definition: glcorearb.h:1926
#define srand48(X)
Definition: SYS_Math.h:166
IMATH_NAMESPACE::V2f float
IMATH_HOSTDEVICE unsigned long int nexti()
Get the next value in the sequence (range: [0 ... 0xffffffff])
Definition: ImathRandom.h:148
IMATH_HOSTDEVICE float gaussRand(Rand &rand)
Definition: ImathRandom.h:236
IMATH_HOSTDEVICE Rand32(unsigned long int seed=0)
Constructor, given a seed.
Definition: ImathRandom.h:128
IMATH_HOSTDEVICE bool nextb()
Get the next value in the sequence (range: [false, true])
Definition: ImathRandom.h:140
IMATH_HOSTDEVICE bool nextb()
Get the next value in the sequence (range: [false, true])
Definition: ImathRandom.h:177
IMATH_HOSTDEVICE void init(unsigned long int seed)
Re-initialize with a given seed.
Definition: ImathRandom.h:162
GLint GLenum GLint x
Definition: glcorearb.h:409
#define IMATH_EXPORT
Definition: ImathExport.h:47
IMATH_HOSTDEVICE Vec hollowSphereRand(Rand &rand)
Definition: ImathRandom.h:218
IMATH_HOSTDEVICE Vec solidSphereRand(Rand &rand)
Definition: ImathRandom.h:203
OIIO_FORCEINLINE T log(const T &v)
Definition: simd.h:7688
IMATH_HOSTDEVICE double nextf()
Get the next value in the sequence (range: [0 ... 1[)
Definition: ImathRandom.h:189
IMATH_HOSTDEVICE Rand48(unsigned long int seed=0)
Constructor.
Definition: ImathRandom.h:171
#define drand48(X)
Definition: SYS_Math.h:167