|
STK++ 1.0
|
00001 // MersenneTwister.h 00002 // Mersenne Twister random number generator -- a C++ class MTRand 00003 // Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus 00004 // Richard J. Wagner v1.0 15 May 2003 rjwagner@writeme.com 00005 00006 // Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, 00007 // Copyright (C) 2000 - 2003, Richard J. Wagner 00008 // Copyright (C) 2005 - 2008, Serge Iovleff 00009 // All rights reserved. 00010 // 00011 // Redistribution and use in source and binary forms, with or without 00012 // modification, are permitted provided that the following conditions 00013 // are met: 00014 // 00015 // 1. Redistributions of source code must retain the above copyright 00016 // notice, this list of conditions and the following disclaimer. 00017 // 00018 // 2. Redistributions in binary form must reproduce the above copyright 00019 // notice, this list of conditions and the following disclaimer in 00020 // the documentation and/or other materials provided with the 00021 // distribution. 00022 // 00023 // 3. The names of its contributors may not be used to endorse or 00024 // promote products derived from this software without specific prior 00025 // written permission. 00026 // 00027 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00028 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00029 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00030 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00031 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00032 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00033 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00034 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00035 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00036 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00037 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00038 00039 // The original code included the following notice: 00040 // 00041 // When you use this, send an email to: matumoto@math.keio.ac.jp 00042 // with an appropriate reference to your work. 00043 // 00044 // It would be nice to CC: rjwagner@writeme.com 00045 // and Cokus@math.washington.edu 00046 // when you write. 00047 // 00048 // Also it would be nice to cc to serge.iovleff@stkpp.org 00049 // if you are using this code. 00050 // 00051 #ifndef MERSENNETWISTER_H 00052 #define MERSENNETWISTER_H 00053 00054 #include <iostream> 00055 #include <limits.h> 00056 #include <stdio.h> 00057 #include <time.h> 00058 #include <math.h> 00059 00060 #include "STK_Const_Math.h" // for _2PI_ 00061 00087 class MTRand 00088 { 00089 // Data 00090 public: 00092 typedef unsigned long uint32; 00093 00094 enum { N = 624 }; 00095 enum { SAVE = N + 1 }; 00096 00097 protected: 00098 enum { M = 397 }; 00099 00100 uint32 state[N]; 00101 uint32 *pNext; 00102 int left; 00103 00104 //Methods 00105 public: 00107 inline MTRand( const uint32& oneSeed ) 00108 { seed(oneSeed); } 00109 00111 inline MTRand( uint32 *const bigSeed, uint32 const seedLength = N ) 00112 { seed(bigSeed,seedLength); } 00113 00115 inline MTRand() 00116 { seed(); } 00117 00119 inline double rand() 00120 { return double(randInt()) * (1.0/4294967295.0); } 00121 00123 inline double rand( const double& n ) 00124 { return rand() * n; } 00125 00127 inline double randExc() 00128 { return double(randInt()) * (1.0/4294967296.0); } 00129 00131 inline double randExc( const double& n ) 00132 { return randExc() * n; } 00133 00135 inline double randDblExc() 00136 { return ( double(randInt()) + 0.5 ) * (1.0/4294967296.0); } 00137 00139 inline double randDblExc( const double& n ) 00140 { return randDblExc() * n; } 00141 00143 inline uint32 randInt() 00144 { 00145 // Pull a 32-bit integer from the generator state 00146 // Every other access function simply transforms the numbers 00147 // extracted here 00148 if( left == 0 ) reload(); 00149 --left; 00150 00151 register uint32 s1; 00152 s1 = *pNext++; 00153 s1 ^= (s1 >> 11); 00154 s1 ^= (s1 << 7) & 0x9d2c5680UL; 00155 s1 ^= (s1 << 15) & 0xefc60000UL; 00156 return ( s1 ^ (s1 >> 18) ); 00157 } 00159 inline double operator()() { return rand(); } 00160 00162 inline uint32 randInt( const uint32& n ) 00163 { 00164 // Find which bits are used in n 00165 // Optimized by Magnus Jonsson (magnus@smartelectronix.com) 00166 uint32 used = n; 00167 used |= used >> 1; 00168 used |= used >> 2; 00169 used |= used >> 4; 00170 used |= used >> 8; 00171 used |= used >> 16; 00172 00173 // Draw numbers until one is found in [0,n] 00174 uint32 i; 00175 do 00176 i = randInt() & used; // toss unused bits to shorten search 00177 while( i > n ); 00178 return i; 00179 } 00180 00185 inline double rand53() 00186 { 00187 uint32 a = randInt() >> 5, b = randInt() >> 6; 00188 // by Isaku Wada 00189 return ( a * 67108864.0 + b ) * (1.0/9007199254740992.0); 00190 } 00191 00195 inline double randNorm( const double& mean, const double& variance ) 00196 { 00197 double r = sqrt( -2.0 * log( 1.0-randDblExc()) ) * variance; 00198 double phi = STK::Const::_2PI_ * randExc(); 00199 return mean + r * cos(phi); 00200 } 00201 00204 inline void seed( const uint32 oneSeed ) 00205 { 00206 initialize(oneSeed); 00207 reload(); 00208 } 00209 00218 inline void seed( uint32 *const bigSeed, const uint32 seedLength ) 00219 { 00220 initialize(19650218UL); 00221 register int i = 1; 00222 register uint32 j = 0; 00223 register int k = ( N > seedLength ? N : seedLength ); 00224 for( ; k; --k ) 00225 { 00226 state[i] = 00227 state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1664525UL ); 00228 state[i] += ( bigSeed[j] & 0xffffffffUL ) + j; 00229 state[i] &= 0xffffffffUL; 00230 ++i; ++j; 00231 if( i >= N ) { state[0] = state[N-1]; i = 1; } 00232 if( j >= seedLength ) j = 0; 00233 } 00234 for( k = N - 1; k; --k ) 00235 { 00236 state[i] = 00237 state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1566083941UL ); 00238 state[i] -= i; 00239 state[i] &= 0xffffffffUL; 00240 ++i; 00241 if( i >= N ) { state[0] = state[N-1]; i = 1; } 00242 } 00243 state[0] = 0x80000000UL;// MSB is 1, assuring non-zero initial array 00244 reload(); 00245 } 00246 00251 inline void seed() 00252 { 00253 // First try getting an array from /dev/urandom 00254 FILE* urandom = fopen( "/dev/urandom", "rb" ); 00255 if( urandom ) 00256 { 00257 uint32 bigSeed[N]; 00258 register uint32 *s = bigSeed; 00259 register int i = N; 00260 register bool success = true; 00261 while( success && i-- ) 00262 success = fread( s++, sizeof(uint32), 1, urandom ); 00263 fclose(urandom); 00264 if( success ) { seed( bigSeed, N ); return; } 00265 } 00266 00267 // Was not successful, so use time() and clock() instead 00268 seed( hash( time(NULL), clock() ) ); 00269 } 00270 00274 inline void save( uint32* saveArray ) const 00275 { 00276 register uint32 *sa = saveArray; 00277 register const uint32 *s = state; 00278 register int i = N; 00279 for( ; i--; *sa++ = *s++ ) {} 00280 *sa = left; 00281 } 00282 00286 inline void load( uint32 *const loadArray ) 00287 { 00288 register uint32 *s = state; 00289 register uint32 *la = loadArray; 00290 register int i = N; 00291 for( ; i--; *s++ = *la++ ) {} 00292 left = *la; 00293 pNext = &state[N-left]; 00294 } 00295 00296 friend std::ostream& operator<<( std::ostream& os 00297 , const MTRand& mtrand ); 00298 friend std::istream& operator>>( std::istream& is 00299 , MTRand& mtrand ); 00300 00301 protected: 00308 inline void initialize( const uint32 seed ) 00309 { 00310 register uint32 *s = state; 00311 register uint32 *r = state; 00312 register int i = 1; 00313 *s++ = seed & 0xffffffffUL; 00314 for( ; i < N; ++i ) 00315 { 00316 *s++ = ( 1812433253UL * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffUL; 00317 r++; 00318 } 00319 } 00320 00325 inline void reload() 00326 { 00327 register uint32 *p = state; 00328 register int i; 00329 for( i = N - M; i--; ++p ) 00330 *p = twist( p[M], p[0], p[1] ); 00331 for( i = M; --i; ++p ) 00332 *p = twist( p[M-N], p[0], p[1] ); 00333 *p = twist( p[M-N], p[0], state[0] ); 00334 00335 left = N, pNext = state; 00336 } 00338 inline uint32 hiBit( const uint32& u ) const 00339 { return u & 0x80000000UL; } 00340 00342 inline uint32 loBit( const uint32& u ) const 00343 { return u & 0x00000001UL; } 00344 00346 inline uint32 loBits( const uint32& u ) const 00347 { return u & 0x7fffffffUL; } 00348 00350 inline uint32 mixBits( const uint32& u, const uint32& v ) const 00351 { return hiBit(u) | loBits(v); } 00352 00354 inline uint32 twist( const uint32& m, const uint32& s0, const uint32& s1 ) const 00355 { return m ^ (mixBits(s0,s1)>>1) ^ (-loBit(s1) & 0x9908b0dfUL); } 00356 00361 static inline uint32 hash( time_t t, clock_t c ) 00362 { 00363 static uint32 differ = 0; // guarantee time-based seeds will change 00364 00365 uint32 h1 = 0; 00366 unsigned char *p = (unsigned char *) &t; 00367 for( size_t i = 0; i < sizeof(t); ++i ) 00368 { 00369 h1 *= UCHAR_MAX + 2U; 00370 h1 += p[i]; 00371 } 00372 uint32 h2 = 0; 00373 p = (unsigned char *) &c; 00374 for( size_t j = 0; j < sizeof(c); ++j ) 00375 { 00376 h2 *= UCHAR_MAX + 2U; 00377 h2 += p[j]; 00378 } 00379 return ( h1 + differ++ ) ^ h2; 00380 } 00381 }; 00382 00383 inline std::ostream& operator<<( std::ostream& os, const MTRand& mtrand ) 00384 { 00385 register const MTRand::uint32 *s = mtrand.state; 00386 register int i = mtrand.N; 00387 for( ; i--; os << *s++ << "\t" ) {} 00388 return os << mtrand.left; 00389 } 00390 00391 00392 inline std::istream& operator>>( std::istream& is, MTRand& mtrand ) 00393 { 00394 register MTRand::uint32 *s = mtrand.state; 00395 register int i = mtrand.N; 00396 for( ; i--; is >> *s++ ) {} 00397 is >> mtrand.left; 00398 mtrand.pNext = &mtrand.state[mtrand.N-mtrand.left]; 00399 return is; 00400 } 00401 00402 #endif // MERSENNETWISTER_H