00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 #ifndef MERSENNETWISTER_H
00044 #define MERSENNETWISTER_H
00045 
00046 
00047 
00048 
00049 #include <iostream>
00050 #include <limits.h>
00051 #include <stdio.h>
00052 
00053 class MTRand {
00054 
00055 public:
00056         typedef unsigned long uint32;  
00057         
00058         enum { N = 624 };              
00059         enum { SAVE = N + 1 };         
00060 
00061 protected:
00062         enum { M = 397 };              
00063         enum { MAGIC = 0x9908b0dfU };  
00064         
00065         uint32 state[N];  
00066         uint32 *pNext;    
00067         int left;         
00068 
00069 
00070 
00071 public:
00072         MTRand( const uint32& oneSeed );  
00073         MTRand( uint32 *const bigSeed );  
00074         MTRand();  
00075         
00076         
00077         
00078         
00079         
00080         inline double rand();                          
00081         double rand( const double& n );         
00082         double randExc();                       
00083         double randExc( const double& n );      
00084         double randDblExc();                    
00085         double randDblExc( const double& n );   
00086         inline uint32 randInt();                       
00087         uint32 randInt( const uint32& n );      
00088         double operator()() { return rand(); }  
00089         
00090         
00091         inline void seed( uint32 oneSeed );
00092         inline void seed( uint32 *const bigSeed );
00093         inline void seed();
00094         
00095         
00096         void save( uint32* saveArray ) const;  
00097         void load( uint32 *const loadArray );  
00098         friend std::ostream& operator<<( std::ostream& os, const MTRand& mtrand );
00099         friend std::istream& operator>>( std::istream& is, MTRand& mtrand );
00100 
00101 protected:
00102         inline void reload();
00103         uint32 hiBit( const uint32& u ) const { return u & 0x80000000U; }
00104         uint32 loBit( const uint32& u ) const { return u & 0x00000001U; }
00105         uint32 loBits( const uint32& u ) const { return u & 0x7fffffffU; }
00106         uint32 mixBits( const uint32& u, const uint32& v ) const
00107                 { return hiBit(u) | loBits(v); }
00108         uint32 twist( const uint32& m, const uint32& s0, const uint32& s1 ) const
00109                 { return m ^ (mixBits(s0,s1)>>1) ^ (loBit(s1) ? MAGIC : 0U); }
00110         inline static uint32 hash( time_t t, clock_t c );
00111 };
00112 
00113 
00114 inline MTRand::MTRand( const uint32& oneSeed )
00115         { seed(oneSeed); }
00116 
00117 inline MTRand::MTRand( uint32 *const bigSeed )
00118         { seed(bigSeed); }
00119 
00120 inline MTRand::MTRand()
00121         { seed(); }
00122 
00123 inline double MTRand::rand()
00124     { return double(randInt()) * 2.3283064370807974e-10; }
00125 
00126 inline double MTRand::rand( const double& n )
00127         { return rand() * n; }
00128 
00129 inline double MTRand::randExc()
00130         { return double(randInt()) * 2.3283064365386963e-10; }
00131 
00132 inline double MTRand::randExc( const double& n )
00133         { return randExc() * n; }
00134 
00135 inline double MTRand::randDblExc()
00136         { return double( 1.0 + randInt() ) * 2.3283064359965952e-10; }
00137 
00138 inline double MTRand::randDblExc( const double& n )
00139         { return randDblExc() * n; }
00140 
00141 inline MTRand::uint32 MTRand::randInt()
00142 {
00143         if( left == 0 ) reload();
00144         --left;
00145                 
00146         register uint32 s1;
00147         s1 = *pNext++;
00148         s1 ^= (s1 >> 11);
00149         s1 ^= (s1 <<  7) & 0x9d2c5680U;
00150         s1 ^= (s1 << 15) & 0xefc60000U;
00151         return ( s1 ^ (s1 >> 18) );
00152 }
00153 
00154 
00155 inline MTRand::uint32 MTRand::randInt( const uint32& n )
00156 {
00157         
00158         uint32 used = ~0;
00159         for( uint32 m = n; m; used <<= 1, m >>= 1 ) {}
00160         used = ~used;
00161         
00162         
00163         uint32 i;
00164         do
00165                 i = randInt() & used;  
00166         while( i > n );
00167         return i;
00168 }
00169 
00170 
00171 inline void MTRand::seed( uint32 oneSeed )
00172 {
00173         
00174         register uint32 *s;
00175         register int i;
00176         for( i = N, s = state;
00177              i--;
00178                  *s    = oneSeed & 0xffff0000,
00179                  *s++ |= ( (oneSeed *= 69069U)++ & 0xffff0000 ) >> 16,
00180                  (oneSeed *= 69069U)++ ) {}  
00181         reload();
00182 }
00183 
00184 
00185 inline void MTRand::seed( uint32 *const bigSeed )
00186 {
00187         
00188         
00189         
00190         
00191         
00192         
00193         
00194         register uint32 *s = state, *b = bigSeed;
00195         register int i = N;
00196         for( ; i--; *s++ = *b++ & 0xffffffff ) {}
00197         reload();
00198 }
00199 
00200 
00201 inline void MTRand::seed()
00202 {
00203         
00204         
00205         
00206         
00207         FILE* urandom = fopen( "/dev/urandom", "rb" );
00208         if( urandom )
00209         {
00210                 register uint32 *s = state;
00211                 register int i = N;
00212                 register bool success = true;
00213                 while( success && i-- )
00214                 {
00215                         success = fread( s, sizeof(uint32), 1, urandom );
00216                         *s++ &= 0xffffffff;  
00217                 }
00218                 fclose(urandom);
00219                 if( success )
00220                 {
00221                         
00222                         
00223                         
00224                         reload();
00225                         return;
00226                 }
00227         }
00228         
00229         
00230         seed( hash( time(NULL), clock() ) );
00231 }
00232 
00233 
00234 inline void MTRand::reload()
00235 {
00236         
00237         
00238         register uint32 *p = state;
00239         register int i;
00240         for( i = N - M; i--; ++p )
00241                 *p = twist( p[M], p[0], p[1] );
00242         for( i = M; --i; ++p )
00243                 *p = twist( p[M-N], p[0], p[1] );
00244         *p = twist( p[M-N], p[0], state[0] );
00245 
00246         left = N, pNext = state;
00247 }
00248 
00249 
00250 inline MTRand::uint32 MTRand::hash( time_t t, clock_t c )
00251 {
00252         
00253         
00254         
00255 
00256         static uint32 differ = 0;  
00257 
00258         uint32 h1 = 0;
00259         unsigned char *p = (unsigned char *) &t;
00260         for( size_t i = 0; i < sizeof(t); ++i )
00261         {
00262                 h1 *= UCHAR_MAX + 2U;
00263                 h1 += p[i];
00264         }
00265         uint32 h2 = 0;
00266         p = (unsigned char *) &c;
00267         for( size_t j = 0; j < sizeof(c); ++j )
00268         {
00269                 h2 *= UCHAR_MAX + 2U;
00270                 h2 += p[j];
00271         }
00272         return ( h1 + differ++ ) ^ h2;
00273 }
00274 
00275 
00276 inline void MTRand::save( uint32* saveArray ) const
00277 {
00278         register uint32 *sa = saveArray;
00279         register const uint32 *s = state;
00280         register int i = N;
00281         for( ; i--; *sa++ = *s++ ) {}
00282         *sa = left;
00283 }
00284 
00285 
00286 inline void MTRand::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 
00297 inline std::ostream& operator<<( std::ostream& os, const MTRand& mtrand )
00298 {
00299         register const MTRand::uint32 *s = mtrand.state;
00300         register int i = mtrand.N;
00301         for( ; i--; os << *s++ << "\t" ) {}
00302         return os << mtrand.left;
00303 }
00304 
00305 
00306 inline std::istream& operator>>( std::istream& is, MTRand& mtrand )
00307 {
00308         register MTRand::uint32 *s = mtrand.state;
00309         register int i = mtrand.N;
00310         for( ; i--; is >> *s++ ) {}
00311         is >> mtrand.left;
00312         mtrand.pNext = &mtrand.state[mtrand.N-mtrand.left];
00313         return is;
00314 }
00315 
00316 #endif  //MERSENNETWISTER_H
00317 
00318 
00319 
00320 
00321 
00322 
00323 
00324 
00325 
00326 
00327 
00328 
00329 
00330 
00331 
00332 
00333 
00334 
00335 
00336 
00337 
00338 
00339 
00340 
00341 
00342 
00343 
00344