Atoms Crowd  7.0.0
ImathRandom.h
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_ATOMSMATHRANDOM_H
19 #define INCLUDED_ATOMSMATHRANDOM_H
20 
21 #include <AtomsMath/ImathExport.h>
22 #include <AtomsMath/ImathNamespace.h>
23 
24 #include <math.h>
25 #include <stdlib.h>
26 
27 ATOMSMATH_INTERNAL_NAMESPACE_HEADER_ENTER
28 
32 class ATOMSMATH_EXPORT Rand32
33 {
34  public:
35 
37  ATOMSMATH_HOSTDEVICE Rand32 (unsigned long int seed = 0);
38 
40  ATOMSMATH_HOSTDEVICE void init (unsigned long int seed);
41 
43  ATOMSMATH_HOSTDEVICE bool nextb();
44 
46  ATOMSMATH_HOSTDEVICE unsigned long int nexti();
47 
49  ATOMSMATH_HOSTDEVICE float nextf();
50 
52  ATOMSMATH_HOSTDEVICE float nextf (float rangeMin, float rangeMax);
53 
54  private:
55  ATOMSMATH_HOSTDEVICE void next();
56 
57  unsigned long int _state;
58 };
59 
63 class Rand48
64 {
65  public:
66 
68  ATOMSMATH_HOSTDEVICE Rand48 (unsigned long int seed = 0);
69 
71  ATOMSMATH_HOSTDEVICE void init (unsigned long int seed);
72 
74  ATOMSMATH_HOSTDEVICE bool nextb();
75 
77  ATOMSMATH_HOSTDEVICE long int nexti();
78 
80  ATOMSMATH_HOSTDEVICE double nextf();
81 
83  ATOMSMATH_HOSTDEVICE double nextf (double rangeMin, double rangeMax);
84 
85  private:
86  unsigned short int _state[3];
87 };
88 
91 template <class Vec, class Rand> ATOMSMATH_HOSTDEVICE Vec solidSphereRand (Rand& rand);
92 
95 template <class Vec, class Rand> ATOMSMATH_HOSTDEVICE Vec hollowSphereRand (Rand& rand);
96 
99 template <class Rand> ATOMSMATH_HOSTDEVICE float gaussRand (Rand& rand);
100 
104 template <class Vec, class Rand> ATOMSMATH_HOSTDEVICE Vec gaussSphereRand (Rand& rand);
105 
106 //---------------------------------
107 // erand48(), nrand48() and friends
108 //---------------------------------
109 
111 #ifndef __APPLE__
112 ATOMSMATH_HOSTDEVICE ATOMSMATH_EXPORT double erand48 (unsigned short state[3]);
113 ATOMSMATH_HOSTDEVICE ATOMSMATH_EXPORT double drand48();
114 ATOMSMATH_HOSTDEVICE ATOMSMATH_EXPORT long int nrand48 (unsigned short state[3]);
115 ATOMSMATH_HOSTDEVICE ATOMSMATH_EXPORT long int lrand48();
116 ATOMSMATH_HOSTDEVICE ATOMSMATH_EXPORT void srand48 (long int seed);
117 #endif
119 
120 //---------------
121 // Implementation
122 //---------------
123 
124 inline void
125 Rand32::init (unsigned long int seed)
126 {
127  _state = (seed * 0xa5a573a5L) ^ 0x5a5a5a5aL;
128 }
129 
130 inline Rand32::Rand32 (unsigned long int seed)
131 {
132  init (seed);
133 }
134 
135 inline void
136 Rand32::next()
137 {
138  _state = 1664525L * _state + 1013904223L;
139 }
140 
141 inline bool
143 {
144  next();
145  // Return the 31st (most significant) bit, by and-ing with 2 ^ 31.
146  return !!(_state & 2147483648UL);
147 }
148 
149 inline unsigned long int
151 {
152  next();
153  return _state & 0xffffffff;
154 }
155 
156 inline float
157 Rand32::nextf (float rangeMin, float rangeMax)
158 {
159  float f = nextf();
160  return rangeMin * (1 - f) + rangeMax * f;
161 }
162 
163 inline void
164 Rand48::init (unsigned long int seed)
165 {
166  seed = (seed * 0xa5a573a5L) ^ 0x5a5a5a5aL;
167 
168  _state[0] = (unsigned short int) (seed & 0xFFFF);
169  _state[1] = (unsigned short int) ((seed >> 16) & 0xFFFF);
170  _state[2] = (unsigned short int) (seed & 0xFFFF);
171 }
172 
173 inline Rand48::Rand48 (unsigned long int seed)
174 {
175  init (seed);
176 }
177 
178 inline bool
180 {
181  return nrand48 (_state) & 1;
182 }
183 
184 inline long int
186 {
187  return nrand48 (_state);
188 }
189 
190 inline double
192 {
193  return erand48 (_state);
194 }
195 
196 inline double
197 Rand48::nextf (double rangeMin, double rangeMax)
198 {
199  double f = nextf();
200  return rangeMin * (1 - f) + rangeMax * f;
201 }
202 
203 template <class Vec, class Rand>
204 Vec
205 solidSphereRand (Rand& rand)
206 {
207  Vec v;
208 
209  do
210  {
211  for (unsigned int i = 0; i < Vec::dimensions(); i++)
212  v[i] = (typename Vec::BaseType) rand.nextf (-1, 1);
213  } while (v.length2() > 1);
214 
215  return v;
216 }
217 
218 template <class Vec, class Rand>
219 Vec
220 hollowSphereRand (Rand& rand)
221 {
222  Vec v;
223  typename Vec::BaseType length;
224 
225  do
226  {
227  for (unsigned int i = 0; i < Vec::dimensions(); i++)
228  v[i] = (typename Vec::BaseType) rand.nextf (-1, 1);
229 
230  length = v.length();
231  } while (length > 1 || length == 0);
232 
233  return v / length;
234 }
235 
236 template <class Rand>
237 float
238 gaussRand (Rand& rand)
239 {
240  float x; // Note: to avoid numerical problems with very small
241  float y; // numbers, we make these variables singe-precision
242  float length2; // floats, but later we call the double-precision log()
243  // and sqrt() functions instead of logf() and sqrtf().
244  do
245  {
246  x = float (rand.nextf (-1, 1));
247  y = float (rand.nextf (-1, 1));
248  length2 = x * x + y * y;
249  } while (length2 >= 1 || length2 == 0);
250 
251  return x * sqrt (-2 * log (double (length2)) / length2);
252 }
253 
254 template <class Vec, class Rand>
255 Vec
256 gaussSphereRand (Rand& rand)
257 {
258  return hollowSphereRand<Vec> (rand) * gaussRand (rand);
259 }
260 
261 ATOMSMATH_INTERNAL_NAMESPACE_HEADER_EXIT
262 
263 #endif // INCLUDED_ATOMSMATHRANDOM_H
Definition: ImathRandom.h:33
ATOMSMATH_HOSTDEVICE unsigned long int nexti()
Get the next value in the sequence (range: [0 ... 0xffffffff])
Definition: ImathRandom.h:150
ATOMSMATH_HOSTDEVICE bool nextb()
Get the next value in the sequence (range: [false, true])
Definition: ImathRandom.h:142
ATOMSMATH_HOSTDEVICE Rand32(unsigned long int seed=0)
Constructor, given a seed.
Definition: ImathRandom.h:130
ATOMSMATH_HOSTDEVICE float nextf()
Get the next value in the sequence (range: [0 ... 1[)
ATOMSMATH_HOSTDEVICE void init(unsigned long int seed)
Re-initialize with a given seed.
Definition: ImathRandom.h:125
Definition: ImathRandom.h:64
ATOMSMATH_HOSTDEVICE long int nexti()
Get the next value in the sequence (range: [0 ... 0x7fffffff])
Definition: ImathRandom.h:185
ATOMSMATH_HOSTDEVICE void init(unsigned long int seed)
Re-initialize with a given seed.
Definition: ImathRandom.h:164
ATOMSMATH_HOSTDEVICE double nextf()
Get the next value in the sequence (range: [0 ... 1[)
Definition: ImathRandom.h:191
ATOMSMATH_HOSTDEVICE Rand48(unsigned long int seed=0)
Constructor.
Definition: ImathRandom.h:173
ATOMSMATH_HOSTDEVICE bool nextb()
Get the next value in the sequence (range: [false, true])
Definition: ImathRandom.h:179