mantaflow  0.10
A framework for fluid simulation
randomstream.h
Go to the documentation of this file.
1 
2 /******************************************************************************
3  *
4  * MantaFlow fluid solver framework
5  * Copyright 2011 Tobias Pfaff, Nils Thuerey
6  *
7  * This program is free software, distributed under the terms of the
8  * GNU General Public License (GPL)
9  * http://www.gnu.org/licenses
10  *
11  * Random numbers
12  *
13  * Based on GPL code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
14  * Richard J. Wagner v0.5 7 November 2000 rjwagner@writeme.com
15  *
16  ******************************************************************************/
17 
18 #ifndef _RANDOMSTREAM_H
19 #define _RANDOMSTREAM_H
20 
21 namespace Manta {
22 
23 #include <iostream>
24 #include <stdio.h>
25 #include <time.h>
26 #include "vectorbase.h"
27 
28 class MTRand {
29  // Data
30  public:
31  typedef unsigned long uint32; // unsigned integer type, at least 32 bits
32 
33  enum { N = 624 }; // length of state vector
34  enum { SAVE = N + 1 }; // length of array for save()
35 
36  protected:
37  enum { M = 397 }; // period parameter
38 
39  uint32 state[N]; // internal state
40  uint32 *pNext; // next value to get from state
41  int left; // number of values left before reload needed
42 
43 
44  //Methods
45  public:
46  MTRand( const uint32& oneSeed ); // initialize with a simple uint32
47  MTRand( uint32 *const bigSeed, uint32 const seedLength = N ); // or an array
48  MTRand(); // auto-initialize with /dev/urandom or time() and clock()
49 
50  // Do NOT use for CRYPTOGRAPHY without securely hashing several returned
51  // values together, otherwise the generator state can be learned after
52  // reading 624 consecutive values.
53 
54  // Access to 32-bit random numbers
55  double rand(); // real number in [0,1]
56  double rand( const double& n ); // real number in [0,n]
57  double randExc(); // real number in [0,1)
58  double randExc( const double& n ); // real number in [0,n)
59  double randDblExc(); // real number in (0,1)
60  double randDblExc( const double& n ); // real number in (0,n)
61  uint32 randInt(); // integer in [0,2^32-1]
62  uint32 randInt( const uint32& n ); // integer in [0,n] for n < 2^32
63  double operator()() { return rand(); } // same as rand()
64 
65  // Access to 53-bit random numbers (capacity of IEEE double precision)
66  double rand53(); // real number in [0,1)
67 
68  // Access to nonuniform random number distributions
69  double randNorm( const double& mean = 0.0, const double& variance = 1.0 );
70 
71  // Re-seeding functions with same behavior as initializers
72  void seed( const uint32 oneSeed );
73  void seed( uint32 *const bigSeed, const uint32 seedLength = N );
74  void seed();
75 
76  // Saving and loading generator state
77  void save( uint32* saveArray ) const; // to array of size SAVE
78  void load( uint32 *const loadArray ); // from such array
79  friend std::ostream& operator<<( std::ostream& os, const MTRand& mtrand );
80  friend std::istream& operator>>( std::istream& is, MTRand& mtrand );
81 
82  protected:
83  void initialize( const uint32 oneSeed );
84  void reload();
85  uint32 hiBit( const uint32& u ) const { return u & 0x80000000UL; }
86  uint32 loBit( const uint32& u ) const { return u & 0x00000001UL; }
87  uint32 loBits( const uint32& u ) const { return u & 0x7fffffffUL; }
88  uint32 mixBits( const uint32& u, const uint32& v ) const {
89  return hiBit(u) | loBits(v);
90  }
91  uint32 twist( const uint32& m, const uint32& s0, const uint32& s1 ) const {
92  return m ^ (mixBits(s0,s1)>>1) ^ (-loBit(s1) & 0x9908b0dfUL);
93  }
94  static uint32 hash( time_t t, clock_t c );
95 };
96 
97 
98 inline MTRand::MTRand( const uint32& oneSeed )
99  { seed(oneSeed); }
100 
101 inline MTRand::MTRand( uint32 *const bigSeed, const uint32 seedLength )
102  { seed(bigSeed,seedLength); }
103 
104 inline MTRand::MTRand()
105  { seed(); }
106 
107 inline double MTRand::rand()
108  { return double(randInt()) * (1.0/4294967295.0); }
109 
110 inline double MTRand::rand( const double& n )
111  { return rand() * n; }
112 
113 inline double MTRand::randExc()
114  { return double(randInt()) * (1.0/4294967296.0); }
115 
116 inline double MTRand::randExc( const double& n )
117  { return randExc() * n; }
118 
119 inline double MTRand::randDblExc()
120  { return ( double(randInt()) + 0.5 ) * (1.0/4294967296.0); }
122 inline double MTRand::randDblExc( const double& n )
123  { return randDblExc() * n; }
124 
125 inline double MTRand::rand53()
126 {
127  uint32 a = randInt() >> 5, b = randInt() >> 6;
128  return ( a * 67108864.0 + b ) * (1.0/9007199254740992.0); // by Isaku Wada
129 }
130 
131 inline double MTRand::randNorm( const double& mean, const double& variance )
132 {
133  // Return a real number from a normal (Gaussian) distribution with given
134  // mean and variance by Box-Muller method
135  double r = sqrt( -2.0 * log( 1.0-randDblExc()) ) * variance;
136  double phi = 2.0 * 3.14159265358979323846264338328 * randExc();
137  return mean + r * cos(phi);
138 }
139 
140 inline MTRand::uint32 MTRand::randInt()
141 {
142  // Pull a 32-bit integer from the generator state
143  // Every other access function simply transforms the numbers extracted here
144 
145  if( left == 0 ) reload();
146  --left;
147 
148  uint32 s1;
149  s1 = *pNext++;
150  s1 ^= (s1 >> 11);
151  s1 ^= (s1 << 7) & 0x9d2c5680UL;
152  s1 ^= (s1 << 15) & 0xefc60000UL;
153  return ( s1 ^ (s1 >> 18) );
154 }
155 
156 inline MTRand::uint32 MTRand::randInt( const uint32& n )
157 {
158  // Find which bits are used in n
159  // Optimized by Magnus Jonsson (magnus@smartelectronix.com)
160  uint32 used = n;
161  used |= used >> 1;
162  used |= used >> 2;
163  used |= used >> 4;
164  used |= used >> 8;
165  used |= used >> 16;
166 
167  // Draw numbers until one is found in [0,n]
168  uint32 i;
169  do
170  i = randInt() & used; // toss unused bits to shorten search
171  while( i > n );
172  return i;
173 }
174 
175 
176 inline void MTRand::seed( const uint32 oneSeed )
177 {
178  // Seed the generator with a simple uint32
179  initialize(oneSeed);
180  reload();
181 }
183 
184 inline void MTRand::seed( uint32 *const bigSeed, const uint32 seedLength )
185 {
186  // Seed the generator with an array of uint32's
187  // There are 2^19937-1 possible initial states. This function allows
188  // all of those to be accessed by providing at least 19937 bits (with a
189  // default seed length of N = 624 uint32's). Any bits above the lower 32
190  // in each element are discarded.
191  // Just call seed() if you want to get array from /dev/urandom
192  initialize(19650218UL);
193  const unsigned int Nenum = N;
194  int i = 1;
195  uint32 j = 0;
196  int k = ( Nenum > seedLength ? Nenum : seedLength );
197  for( ; k; --k )
198  {
199  state[i] =
200  state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1664525UL );
201  state[i] += ( bigSeed[j] & 0xffffffffUL ) + j;
202  state[i] &= 0xffffffffUL;
203  ++i; ++j;
204  if( i >= N ) { state[0] = state[N-1]; i = 1; }
205  if( j >= seedLength ) j = 0;
206  }
207  for( k = N - 1; k; --k )
208  {
209  state[i] =
210  state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1566083941UL );
211  state[i] -= i;
212  state[i] &= 0xffffffffUL;
213  ++i;
214  if( i >= N ) { state[0] = state[N-1]; i = 1; }
215  }
216  state[0] = 0x80000000UL; // MSB is 1, assuring non-zero initial array
217  reload();
218 }
219 
220 
221 inline void MTRand::seed()
222 {
223  // Seed the generator with an array from /dev/urandom if available
224  // Otherwise use a hash of time() and clock() values
225 
226  // First try getting an array from /dev/urandom
227  FILE* urandom = fopen( "/dev/urandom", "rb" );
228  if( urandom )
229  {
230  uint32 bigSeed[N];
231  uint32 *s = bigSeed;
232  int i = N;
233  bool success = true;
234  while( success && i-- )
235  success = fread( s++, sizeof(uint32), 1, urandom );
236  fclose(urandom);
237  if( success ) { seed( bigSeed, N ); return; }
238  }
239 
240  // Was not successful, so use time() and clock() instead
241  seed( hash( time(NULL), clock() ) );
242 }
244 
245 inline void MTRand::initialize( const uint32 intseed )
246 {
247  // Initialize generator state with seed
248  // See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier.
249  // In previous versions, most significant bits (MSBs) of the seed affect
250  // only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto.
251  uint32 *s = state;
252  uint32 *r = state;
253  int i = 1;
254  *s++ = intseed & 0xffffffffUL;
255  for( ; i < N; ++i )
256  {
257  *s++ = ( 1812433253UL * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffUL;
258  r++;
259  }
260 }
261 
262 
263 inline void MTRand::reload()
264 {
265  // Generate N new values in state
266  // Made clearer and faster by Matthew Bellew (matthew.bellew@home.com)
267  uint32 *p = state;
268  int i;
269  for( i = N - M; i--; ++p )
270  *p = twist( p[M], p[0], p[1] );
271  for( i = M; --i; ++p )
272  *p = twist( p[M-N], p[0], p[1] );
273  *p = twist( p[M-N], p[0], state[0] );
274 
275  left = N, pNext = state;
276 }
277 
278 
279 inline MTRand::uint32 MTRand::hash( time_t t, clock_t c )
280 {
281  // Get a uint32 from t and c
282  // Better than uint32(x) in case x is floating point in [0,1]
283  // Based on code by Lawrence Kirby (fred@genesis.demon.co.uk)
284 
285  static uint32 differ = 0; // guarantee time-based seeds will change
286 
287  uint32 h1 = 0;
288  unsigned char *p = (unsigned char *) &t;
289  for( size_t i = 0; i < sizeof(t); ++i )
290  {
291  h1 *= std::numeric_limits<unsigned char>::max() + 2U;
292  h1 += p[i];
293  }
294  uint32 h2 = 0;
295  p = (unsigned char *) &c;
296  for( size_t j = 0; j < sizeof(c); ++j )
297  {
298  h2 *= std::numeric_limits<unsigned char>::max() + 2U;
299  h2 += p[j];
300  }
301  return ( h1 + differ++ ) ^ h2;
302 }
303 
304 
305 inline void MTRand::save( uint32* saveArray ) const
306 {
307  uint32 *sa = saveArray;
308  const uint32 *s = state;
309  int i = N;
310  for( ; i--; *sa++ = *s++ ) {}
311  *sa = left;
312 }
314 
315 inline void MTRand::load( uint32 *const loadArray )
316 {
317  uint32 *s = state;
318  uint32 *la = loadArray;
319  int i = N;
320  for( ; i--; *s++ = *la++ ) {}
321  left = *la;
322  pNext = &state[N-left];
323 }
324 
326 inline std::ostream& operator<<( std::ostream& os, const MTRand& mtrand )
327 {
328  const MTRand::uint32 *s = mtrand.state;
329  int i = mtrand.N;
330  for( ; i--; os << *s++ << "\t" ) {}
331  return os << mtrand.left;
332 }
333 
334 
335 inline std::istream& operator>>( std::istream& is, MTRand& mtrand )
336 {
337  MTRand::uint32 *s = mtrand.state;
338  int i = mtrand.N;
339  for( ; i--; is >> *s++ ) {}
340  is >> mtrand.left;
341  mtrand.pNext = &mtrand.state[mtrand.N-mtrand.left];
342  return is;
343 }
344 
345 // simple interface to mersenne twister
347 {
348 public:
349  inline RandomStream(long seed) : mtr(seed) {} ;
350  ~RandomStream() {}
351 
353  inline double getDouble( void ) { return mtr.rand(); };
354  inline float getFloat ( void ) { return (float)mtr.rand(); };
355 
356  inline float getFloat( float min, float max ) { return mtr.rand(max-min) + min; };
357  inline float getRandNorm( float mean, float var) { return mtr.randNorm(mean, var); };
358 
359  #if FLOATINGPOINT_PRECISION==1
360  inline Real getReal() { return getFloat(); }
361 
362  #else
363  inline Real getReal() { return getDouble(); }
364  #endif
365 
366  inline Vec3 getVec3 () { Real a=getReal(), b=getReal(), c=getReal(); return Vec3(a,b,c); }
367  inline Vec3 getVec3Norm () { Vec3 a=getVec3(); normalize(a); return a; }
368 
369 private:
370  MTRand mtr;
371 };
373 
374 } // namespace
375 
376 #endif
377 
378 
Definition: commonkernels.h:22
double getDouble(void)
Definition: randomstream.h:353
Definition: randomstream.h:346
Definition: randomstream.h:28
S normalize(Vector3D< S > &v)
Compute the norm of the vector and normalize it.
Definition: randomstream.h:408