Rev 1221 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
289 | werner | 1 | // MersenneTwister.h |
2 | // Mersenne Twister random number generator -- a C++ class MTRand |
||
3 | // Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus |
||
4 | // Richard J. Wagner v1.1 28 September 2009 wagnerr@umich.edu |
||
5 | |||
6 | // The Mersenne Twister is an algorithm for generating random numbers. It |
||
7 | // was designed with consideration of the flaws in various other generators. |
||
8 | // The period, 2^19937-1, and the order of equidistribution, 623 dimensions, |
||
9 | // are far greater. The generator is also fast; it avoids multiplication and |
||
10 | // division, and it benefits from caches and pipelines. For more information |
||
11 | // see the inventors' web page at |
||
12 | // http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html |
||
13 | |||
14 | // Reference |
||
15 | // M. Matsumoto and T. Nishimura, "Mersenne Twister: A 623-Dimensionally |
||
16 | // Equidistributed Uniform Pseudo-Random Number Generator", ACM Transactions on |
||
17 | // Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3-30. |
||
18 | |||
19 | // Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, |
||
20 | // Copyright (C) 2000 - 2009, Richard J. Wagner |
||
21 | // All rights reserved. |
||
22 | // |
||
23 | // Redistribution and use in source and binary forms, with or without |
||
24 | // modification, are permitted provided that the following conditions |
||
25 | // are met: |
||
26 | // |
||
27 | // 1. Redistributions of source code must retain the above copyright |
||
28 | // notice, this list of conditions and the following disclaimer. |
||
29 | // |
||
30 | // 2. Redistributions in binary form must reproduce the above copyright |
||
31 | // notice, this list of conditions and the following disclaimer in the |
||
32 | // documentation and/or other materials provided with the distribution. |
||
33 | // |
||
34 | // 3. The names of its contributors may not be used to endorse or promote |
||
35 | // products derived from this software without specific prior written |
||
36 | // permission. |
||
37 | // |
||
38 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||
39 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||
40 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||
41 | // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
||
42 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||
43 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||
44 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||
45 | // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||
46 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||
47 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||
48 | // POSSIBILITY OF SUCH DAMAGE. |
||
49 | |||
50 | // The original code included the following notice: |
||
51 | // |
||
52 | // When you use this, send an email to: m-mat@math.sci.hiroshima-u.ac.jp |
||
53 | // with an appropriate reference to your work. |
||
54 | // |
||
55 | // It would be nice to CC: wagnerr@umich.edu and Cokus@math.washington.edu |
||
56 | // when you write. |
||
57 | |||
58 | #ifndef MERSENNETWISTER_H |
||
59 | #define MERSENNETWISTER_H |
||
60 | |||
61 | // Not thread safe (unless auto-initialization is avoided and each thread has |
||
62 | // its own MTRand object) |
||
63 | |||
64 | #include <iostream> |
||
65 | #include <climits> |
||
66 | #include <cstdio> |
||
67 | #include <ctime> |
||
68 | #include <cmath> |
||
69 | |||
70 | class MTRand { |
||
71 | // Data |
||
72 | public: |
||
73 | typedef unsigned long uint32; // unsigned integer type, at least 32 bits |
||
74 | |||
75 | enum { N = 624 }; // length of state vector |
||
76 | enum { SAVE = N + 1 }; // length of array for save() |
||
77 | |||
78 | protected: |
||
79 | enum { M = 397 }; // period parameter |
||
80 | |||
81 | uint32 state[N]; // internal state |
||
82 | uint32 *pNext; // next value to get from state |
||
83 | int left; // number of values left before reload needed |
||
84 | |||
85 | // Methods |
||
86 | public: |
||
87 | MTRand( const uint32 oneSeed ); // initialize with a simple uint32 |
||
88 | MTRand( uint32 *const bigSeed, uint32 const seedLength = N ); // or array |
||
89 | MTRand(); // auto-initialize with /dev/urandom or time() and clock() |
||
90 | MTRand( const MTRand& o ); // copy |
||
91 | |||
92 | // Do NOT use for CRYPTOGRAPHY without securely hashing several returned |
||
93 | // values together, otherwise the generator state can be learned after |
||
94 | // reading 624 consecutive values. |
||
95 | |||
96 | // Access to 32-bit random numbers |
||
97 | uint32 randInt(); // integer in [0,2^32-1] |
||
98 | uint32 randInt( const uint32 n ); // integer in [0,n] for n < 2^32 |
||
99 | double rand(); // real number in [0,1] |
||
100 | double rand( const double n ); // real number in [0,n] |
||
101 | double randExc(); // real number in [0,1) |
||
102 | double randExc( const double n ); // real number in [0,n) |
||
103 | double randDblExc(); // real number in (0,1) |
||
104 | double randDblExc( const double n ); // real number in (0,n) |
||
105 | double operator()(); // same as rand() |
||
106 | |||
107 | // Access to 53-bit random numbers (capacity of IEEE double precision) |
||
108 | double rand53(); // real number in [0,1) |
||
109 | |||
110 | // Access to nonuniform random number distributions |
||
111 | double randNorm( const double mean = 0.0, const double stddev = 1.0 ); |
||
112 | |||
113 | // Re-seeding functions with same behavior as initializers |
||
114 | void seed( const uint32 oneSeed ); |
||
115 | void seed( uint32 *const bigSeed, const uint32 seedLength = N ); |
||
116 | void seed(); |
||
117 | |||
118 | // Saving and loading generator state |
||
119 | void save( uint32* saveArray ) const; // to array of size SAVE |
||
120 | void load( uint32 *const loadArray ); // from such array |
||
121 | friend std::ostream& operator<<( std::ostream& os, const MTRand& mtrand ); |
||
122 | friend std::istream& operator>>( std::istream& is, MTRand& mtrand ); |
||
123 | MTRand& operator=( const MTRand& o ); |
||
124 | |||
125 | protected: |
||
126 | void initialize( const uint32 oneSeed ); |
||
127 | void reload(); |
||
128 | uint32 hiBit( const uint32 u ) const { return u & 0x80000000UL; } |
||
129 | uint32 loBit( const uint32 u ) const { return u & 0x00000001UL; } |
||
130 | uint32 loBits( const uint32 u ) const { return u & 0x7fffffffUL; } |
||
131 | uint32 mixBits( const uint32 u, const uint32 v ) const |
||
132 | { return hiBit(u) | loBits(v); } |
||
133 | uint32 magic( const uint32 u ) const |
||
134 | { return loBit(u) ? 0x9908b0dfUL : 0x0UL; } |
||
135 | uint32 twist( const uint32 m, const uint32 s0, const uint32 s1 ) const |
||
136 | { return m ^ (mixBits(s0,s1)>>1) ^ magic(s1); } |
||
137 | static uint32 hash( time_t t, clock_t c ); |
||
138 | }; |
||
139 | |||
140 | // Functions are defined in order of usage to assist inlining |
||
141 | |||
142 | inline MTRand::uint32 MTRand::hash( time_t t, clock_t c ) |
||
143 | { |
||
144 | // Get a uint32 from t and c |
||
145 | // Better than uint32(x) in case x is floating point in [0,1] |
||
146 | // Based on code by Lawrence Kirby (fred@genesis.demon.co.uk) |
||
147 | |||
148 | static uint32 differ = 0; // guarantee time-based seeds will change |
||
149 | |||
150 | uint32 h1 = 0; |
||
151 | unsigned char *p = (unsigned char *) &t; |
||
152 | for( size_t i = 0; i < sizeof(t); ++i ) |
||
153 | { |
||
154 | h1 *= UCHAR_MAX + 2U; |
||
155 | h1 += p[i]; |
||
156 | } |
||
157 | uint32 h2 = 0; |
||
158 | p = (unsigned char *) &c; |
||
159 | for( size_t j = 0; j < sizeof(c); ++j ) |
||
160 | { |
||
161 | h2 *= UCHAR_MAX + 2U; |
||
162 | h2 += p[j]; |
||
163 | } |
||
164 | return ( h1 + differ++ ) ^ h2; |
||
165 | } |
||
166 | |||
167 | inline void MTRand::initialize( const uint32 seed ) |
||
168 | { |
||
169 | // Initialize generator state with seed |
||
170 | // See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier. |
||
171 | // In previous versions, most significant bits (MSBs) of the seed affect |
||
172 | // only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto. |
||
173 | register uint32 *s = state; |
||
174 | register uint32 *r = state; |
||
175 | register int i = 1; |
||
176 | *s++ = seed & 0xffffffffUL; |
||
177 | for( ; i < N; ++i ) |
||
178 | { |
||
179 | *s++ = ( 1812433253UL * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffUL; |
||
180 | r++; |
||
181 | } |
||
182 | } |
||
183 | |||
184 | inline void MTRand::reload() |
||
185 | { |
||
186 | // Generate N new values in state |
||
187 | // Made clearer and faster by Matthew Bellew (matthew.bellew@home.com) |
||
188 | static const int MmN = int(M) - int(N); // in case enums are unsigned |
||
189 | register uint32 *p = state; |
||
190 | register int i; |
||
191 | for( i = N - M; i--; ++p ) |
||
192 | *p = twist( p[M], p[0], p[1] ); |
||
193 | for( i = M; --i; ++p ) |
||
194 | *p = twist( p[MmN], p[0], p[1] ); |
||
195 | *p = twist( p[MmN], p[0], state[0] ); |
||
196 | |||
197 | left = N, pNext = state; |
||
198 | } |
||
199 | |||
200 | inline void MTRand::seed( const uint32 oneSeed ) |
||
201 | { |
||
202 | // Seed the generator with a simple uint32 |
||
203 | initialize(oneSeed); |
||
204 | reload(); |
||
205 | } |
||
206 | |||
207 | inline void MTRand::seed( uint32 *const bigSeed, const uint32 seedLength ) |
||
208 | { |
||
209 | // Seed the generator with an array of uint32's |
||
210 | // There are 2^19937-1 possible initial states. This function allows |
||
211 | // all of those to be accessed by providing at least 19937 bits (with a |
||
212 | // default seed length of N = 624 uint32's). Any bits above the lower 32 |
||
213 | // in each element are discarded. |
||
214 | // Just call seed() if you want to get array from /dev/urandom |
||
215 | initialize(19650218UL); |
||
216 | register int i = 1; |
||
217 | register uint32 j = 0; |
||
777 | werner | 218 | // orig: register int k = ( N > seedLength ? N : seedLength ); |
219 | register int k = ( uint32(N) > seedLength ? uint32(N) : seedLength ); |
||
289 | werner | 220 | for( ; k; --k ) |
221 | { |
||
222 | state[i] = |
||
223 | state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1664525UL ); |
||
224 | state[i] += ( bigSeed[j] & 0xffffffffUL ) + j; |
||
225 | state[i] &= 0xffffffffUL; |
||
226 | ++i; ++j; |
||
227 | if( i >= N ) { state[0] = state[N-1]; i = 1; } |
||
228 | if( j >= seedLength ) j = 0; |
||
229 | } |
||
230 | for( k = N - 1; k; --k ) |
||
231 | { |
||
232 | state[i] = |
||
233 | state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1566083941UL ); |
||
234 | state[i] -= i; |
||
235 | state[i] &= 0xffffffffUL; |
||
236 | ++i; |
||
237 | if( i >= N ) { state[0] = state[N-1]; i = 1; } |
||
238 | } |
||
239 | state[0] = 0x80000000UL; // MSB is 1, assuring non-zero initial array |
||
240 | reload(); |
||
241 | } |
||
242 | |||
243 | inline void MTRand::seed() |
||
244 | { |
||
245 | // Seed the generator with an array from /dev/urandom if available |
||
246 | // Otherwise use a hash of time() and clock() values |
||
247 | |||
248 | // First try getting an array from /dev/urandom |
||
1035 | werner | 249 | #if defined(Q_CC_INTEL) || defined(Q_CC_GNU) |
983 | werner | 250 | FILE* urandom = fopen( "/dev/urandom", "rb" ); |
251 | #else |
||
780 | werner | 252 | FILE* urandom; |
253 | fopen_s(&urandom, "/dev/urandom", "rb" ); |
||
983 | werner | 254 | #endif |
289 | werner | 255 | if( urandom ) |
256 | { |
||
257 | uint32 bigSeed[N]; |
||
258 | register uint32 *s = bigSeed; |
||
259 | register int i = N; |
||
260 | register bool success = true; |
||
261 | while( success && i-- ) |
||
262 | success = fread( s++, sizeof(uint32), 1, urandom ); |
||
263 | fclose(urandom); |
||
264 | if( success ) { seed( bigSeed, N ); return; } |
||
265 | } |
||
266 | |||
267 | // Was not successful, so use time() and clock() instead |
||
268 | seed( hash( time(NULL), clock() ) ); |
||
269 | } |
||
270 | |||
271 | inline MTRand::MTRand( const uint32 oneSeed ) |
||
272 | { seed(oneSeed); } |
||
273 | |||
274 | inline MTRand::MTRand( uint32 *const bigSeed, const uint32 seedLength ) |
||
275 | { seed(bigSeed,seedLength); } |
||
276 | |||
277 | inline MTRand::MTRand() |
||
278 | { seed(); } |
||
279 | |||
280 | inline MTRand::MTRand( const MTRand& o ) |
||
281 | { |
||
282 | register const uint32 *t = o.state; |
||
283 | register uint32 *s = state; |
||
284 | register int i = N; |
||
285 | for( ; i--; *s++ = *t++ ) {} |
||
286 | left = o.left; |
||
287 | pNext = &state[N-left]; |
||
288 | } |
||
289 | |||
290 | inline MTRand::uint32 MTRand::randInt() |
||
291 | { |
||
292 | // Pull a 32-bit integer from the generator state |
||
293 | // Every other access function simply transforms the numbers extracted here |
||
294 | |||
295 | if( left == 0 ) reload(); |
||
296 | --left; |
||
297 | |||
298 | register uint32 s1; |
||
299 | s1 = *pNext++; |
||
300 | s1 ^= (s1 >> 11); |
||
301 | s1 ^= (s1 << 7) & 0x9d2c5680UL; |
||
302 | s1 ^= (s1 << 15) & 0xefc60000UL; |
||
303 | return ( s1 ^ (s1 >> 18) ); |
||
304 | } |
||
305 | |||
306 | inline MTRand::uint32 MTRand::randInt( const uint32 n ) |
||
307 | { |
||
308 | // Find which bits are used in n |
||
309 | // Optimized by Magnus Jonsson (magnus@smartelectronix.com) |
||
310 | uint32 used = n; |
||
311 | used |= used >> 1; |
||
312 | used |= used >> 2; |
||
313 | used |= used >> 4; |
||
314 | used |= used >> 8; |
||
315 | used |= used >> 16; |
||
316 | |||
317 | // Draw numbers until one is found in [0,n] |
||
318 | uint32 i; |
||
319 | do |
||
320 | i = randInt() & used; // toss unused bits to shorten search |
||
321 | while( i > n ); |
||
322 | return i; |
||
323 | } |
||
324 | |||
325 | inline double MTRand::rand() |
||
326 | { return double(randInt()) * (1.0/4294967295.0); } |
||
327 | |||
328 | inline double MTRand::rand( const double n ) |
||
329 | { return rand() * n; } |
||
330 | |||
331 | inline double MTRand::randExc() |
||
332 | { return double(randInt()) * (1.0/4294967296.0); } |
||
333 | |||
334 | inline double MTRand::randExc( const double n ) |
||
335 | { return randExc() * n; } |
||
336 | |||
337 | inline double MTRand::randDblExc() |
||
338 | { return ( double(randInt()) + 0.5 ) * (1.0/4294967296.0); } |
||
339 | |||
340 | inline double MTRand::randDblExc( const double n ) |
||
341 | { return randDblExc() * n; } |
||
342 | |||
343 | inline double MTRand::rand53() |
||
344 | { |
||
345 | uint32 a = randInt() >> 5, b = randInt() >> 6; |
||
346 | return ( a * 67108864.0 + b ) * (1.0/9007199254740992.0); // by Isaku Wada |
||
347 | } |
||
348 | |||
349 | inline double MTRand::randNorm( const double mean, const double stddev ) |
||
350 | { |
||
351 | // Return a real number from a normal (Gaussian) distribution with given |
||
352 | // mean and standard deviation by polar form of Box-Muller transformation |
||
353 | double x, y, r; |
||
354 | do |
||
355 | { |
||
356 | x = 2.0 * rand() - 1.0; |
||
357 | y = 2.0 * rand() - 1.0; |
||
358 | r = x * x + y * y; |
||
359 | } |
||
360 | while ( r >= 1.0 || r == 0.0 ); |
||
361 | double s = sqrt( -2.0 * log(r) / r ); |
||
362 | return mean + x * s * stddev; |
||
363 | } |
||
364 | |||
365 | inline double MTRand::operator()() |
||
366 | { |
||
367 | return rand(); |
||
368 | } |
||
369 | |||
370 | inline void MTRand::save( uint32* saveArray ) const |
||
371 | { |
||
372 | register const uint32 *s = state; |
||
373 | register uint32 *sa = saveArray; |
||
374 | register int i = N; |
||
375 | for( ; i--; *sa++ = *s++ ) {} |
||
376 | *sa = left; |
||
377 | } |
||
378 | |||
379 | inline void MTRand::load( uint32 *const loadArray ) |
||
380 | { |
||
381 | register uint32 *s = state; |
||
382 | register uint32 *la = loadArray; |
||
383 | register int i = N; |
||
384 | for( ; i--; *s++ = *la++ ) {} |
||
385 | left = *la; |
||
386 | pNext = &state[N-left]; |
||
387 | } |
||
388 | |||
389 | inline std::ostream& operator<<( std::ostream& os, const MTRand& mtrand ) |
||
390 | { |
||
391 | register const MTRand::uint32 *s = mtrand.state; |
||
392 | register int i = mtrand.N; |
||
393 | for( ; i--; os << *s++ << "\t" ) {} |
||
394 | return os << mtrand.left; |
||
395 | } |
||
396 | |||
397 | inline std::istream& operator>>( std::istream& is, MTRand& mtrand ) |
||
398 | { |
||
399 | register MTRand::uint32 *s = mtrand.state; |
||
400 | register int i = mtrand.N; |
||
401 | for( ; i--; is >> *s++ ) {} |
||
402 | is >> mtrand.left; |
||
403 | mtrand.pNext = &mtrand.state[mtrand.N-mtrand.left]; |
||
404 | return is; |
||
405 | } |
||
406 | |||
407 | inline MTRand& MTRand::operator=( const MTRand& o ) |
||
408 | { |
||
409 | if( this == &o ) return (*this); |
||
410 | register const uint32 *t = o.state; |
||
411 | register uint32 *s = state; |
||
412 | register int i = N; |
||
413 | for( ; i--; *s++ = *t++ ) {} |
||
414 | left = o.left; |
||
415 | pNext = &state[N-left]; |
||
416 | return (*this); |
||
417 | } |
||
418 | |||
419 | #endif // MERSENNETWISTER_H |
||
420 | |||
421 | // Change log: |
||
422 | // |
||
423 | // v0.1 - First release on 15 May 2000 |
||
424 | // - Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus |
||
425 | // - Translated from C to C++ |
||
426 | // - Made completely ANSI compliant |
||
427 | // - Designed convenient interface for initialization, seeding, and |
||
428 | // obtaining numbers in default or user-defined ranges |
||
429 | // - Added automatic seeding from /dev/urandom or time() and clock() |
||
430 | // - Provided functions for saving and loading generator state |
||
431 | // |
||
432 | // v0.2 - Fixed bug which reloaded generator one step too late |
||
433 | // |
||
434 | // v0.3 - Switched to clearer, faster reload() code from Matthew Bellew |
||
435 | // |
||
436 | // v0.4 - Removed trailing newline in saved generator format to be consistent |
||
437 | // with output format of built-in types |
||
438 | // |
||
439 | // v0.5 - Improved portability by replacing static const int's with enum's and |
||
440 | // clarifying return values in seed(); suggested by Eric Heimburg |
||
441 | // - Removed MAXINT constant; use 0xffffffffUL instead |
||
442 | // |
||
443 | // v0.6 - Eliminated seed overflow when uint32 is larger than 32 bits |
||
444 | // - Changed integer [0,n] generator to give better uniformity |
||
445 | // |
||
446 | // v0.7 - Fixed operator precedence ambiguity in reload() |
||
447 | // - Added access for real numbers in (0,1) and (0,n) |
||
448 | // |
||
449 | // v0.8 - Included time.h header to properly support time_t and clock_t |
||
450 | // |
||
451 | // v1.0 - Revised seeding to match 26 Jan 2002 update of Nishimura and Matsumoto |
||
452 | // - Allowed for seeding with arrays of any length |
||
453 | // - Added access for real numbers in [0,1) with 53-bit resolution |
||
454 | // - Added access for real numbers from normal (Gaussian) distributions |
||
455 | // - Increased overall speed by optimizing twist() |
||
456 | // - Doubled speed of integer [0,n] generation |
||
457 | // - Fixed out-of-range number generation on 64-bit machines |
||
458 | // - Improved portability by substituting literal constants for long enum's |
||
459 | // - Changed license from GNU LGPL to BSD |
||
460 | // |
||
461 | // v1.1 - Corrected parameter label in randNorm from "variance" to "stddev" |
||
462 | // - Changed randNorm algorithm from basic to polar form for efficiency |
||
463 | // - Updated includes from deprecated <xxxx.h> to standard <cxxxx> forms |
||
464 | // - Cleaned declarations and definitions to please Intel compiler |
||
465 | // - Revised twist() operator to work on ones'-complement machines |
||
466 | // - Fixed reload() function to work when N and M are unsigned |
||
467 | // - Added copy constructor and copy operator from Salvador Espana |