Biorithm  1.1
 All Classes Functions Variables Typedefs Friends
Mersennetwister.h
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  v0.7  12 July 2001  rjwagner@writeme.com
00005 
00006 // The Mersenne Twister is an algorithm for generating random numbers.  It
00007 // was designed with consideration of the flaws in various other generators.
00008 // The period, 2^19937-1, and the order of equidistribution, 623 dimensions,
00009 // are far greater.  The generator is also fast; it avoids multiplication and
00010 // division, and it benefits from caches and pipelines.  For more information
00011 // see the inventors' web page at http://www.math.keio.ac.jp/~matumoto/emt.html
00012 
00013 // Reference
00014 // M. Matsumoto and T. Nishimura, "Mersenne Twister: A 623-Dimensionally
00015 // Equidistributed Uniform Pseudo-Random Number Generator", ACM Transactions on
00016 // Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3-30.
00017 
00018 // Copyright (C) 2001  Richard J. Wagner
00019 // 
00020 // This library is free software; you can redistribute it and/or
00021 // modify it under the terms of the GNU Lesser General Public
00022 // License as published by the Free Software Foundation; either
00023 // version 2.1 of the License, or (at your option) any later version.
00024 // 
00025 // This library is distributed in the hope that it will be useful,
00026 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00027 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00028 // Lesser General Public License for more details.
00029 // 
00030 // You should have received a copy of the GNU Lesser General Public
00031 // License along with this library; if not, write to the Free Software
00032 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00033 
00034 // The original code included the following notice:
00035 //
00036 //     Copyright (C) 1997, 1999 Makoto Matsumoto and Takuji Nishimura.
00037 //     When you use this, send an email to: matumoto@math.keio.ac.jp
00038 //     with an appropriate reference to your work.
00039 //
00040 // It would be nice to CC: rjwagner@writeme.com and Cokus@math.washington.edu
00041 // when you write.
00042 
00043 #ifndef MERSENNETWISTER_H
00044 #define MERSENNETWISTER_H
00045 
00046 // Not thread safe (unless auto-initialization is avoided and each thread has
00047 // its own MTRand object)
00048 
00049 #include <iostream>
00050 #include <limits.h>
00051 #include <stdio.h>
00052 
00053 class MTRand {
00054 // Data
00055 public:
00056         typedef unsigned long uint32;  // unsigned integer type, at least 32 bits
00057         
00058         enum { N = 624 };              // length of state vector
00059         enum { SAVE = N + 1 };         // length of array for save()
00060 
00061 protected:
00062         enum { M = 397 };              // period parameter
00063         enum { MAGIC = 0x9908b0dfU };  // magic constant
00064         
00065         uint32 state[N];  // internal state
00066         uint32 *pNext;    // next value to get from state
00067         int left;         // number of values left before reload needed
00068 
00069 
00070 //Methods
00071 public:
00072         MTRand( const uint32& oneSeed );  // initialize with a simple uint32
00073         MTRand( uint32 *const bigSeed );  // initialize with an array of N uint32's
00074         MTRand();  // auto-initialize with /dev/urandom or time() and clock()
00075         
00076         // Access to 32-bit random numbers
00077         // Do NOT use for CRYPTOGRAPHY without securely hashing several returned
00078         // values together, otherwise the generator state can be learned after
00079         // reading 624 consecutive values.
00080         inline double rand();                          // real number in [0,1]
00081         double rand( const double& n );         // real number in [0,n]
00082         double randExc();                       // real number in [0,1)
00083         double randExc( const double& n );      // real number in [0,n)
00084         double randDblExc();                    // real number in (0,1)
00085         double randDblExc( const double& n );   // real number in (0,n)
00086         inline uint32 randInt();                       // integer in [0,2^32-1]
00087         uint32 randInt( const uint32& n );      // integer in [0,n] for n < 2^32
00088         double operator()() { return rand(); }  // same as rand()
00089         
00090         // Re-seeding functions with same behavior as initializers
00091         inline void seed( uint32 oneSeed );
00092         inline void seed( uint32 *const bigSeed );
00093         inline void seed();
00094         
00095         // Saving and loading generator state
00096         void save( uint32* saveArray ) const;  // to array of size SAVE
00097         void load( uint32 *const loadArray );  // from such array
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         // Find which bits are used in n
00158         uint32 used = ~0;
00159         for( uint32 m = n; m; used <<= 1, m >>= 1 ) {}
00160         used = ~used;
00161         
00162         // Draw numbers until one is found in [0,n]
00163         uint32 i;
00164         do
00165                 i = randInt() & used;  // toss unused bits to shorten search
00166         while( i > n );
00167         return i;
00168 }
00169 
00170 
00171 inline void MTRand::seed( uint32 oneSeed )
00172 {
00173         // Seed the generator with a simple uint32
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)++ ) {}  // hard to read, but fast
00181         reload();
00182 }
00183 
00184 
00185 inline void MTRand::seed( uint32 *const bigSeed )
00186 {
00187         // Seed the generator with an array of 624 uint32's
00188         // There are 2^19937-1 possible initial states.  This function allows
00189         // any one of those to be chosen by providing 19937 bits.  The lower
00190         // 31 bits of the first element, bigSeed[0], are discarded.  Any bits
00191         // above the lower 32 in each element are also discarded.  Theoretically,
00192         // the rest of the array can contain any values except all zeroes.
00193         // Just call seed() if you want to get array from /dev/urandom
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         // Seed the generator with an array from /dev/urandom if available
00204         // Otherwise use a hash of time() and clock() values
00205         
00206         // First try getting an array from /dev/urandom
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;  // filter in case uint32 > 32 bits
00217                 }
00218                 fclose(urandom);
00219                 if( success )
00220                 {
00221                         // There is a 1 in 2^19937 chance that a working urandom gave
00222                         // 19937 consecutive zeroes and will make the generator fail
00223                         // Ignore that case and continue with initialization
00224                         reload();
00225                         return;
00226                 }
00227         }
00228         
00229         // Was not successful, so use time() and clock() instead
00230         seed( hash( time(NULL), clock() ) );
00231 }
00232 
00233 
00234 inline void MTRand::reload()
00235 {
00236         // Generate N new values in state
00237         // Made clearer and faster by Matthew Bellew (matthew.bellew@home.com)
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         // Get a uint32 from t and c
00253         // Better than uint32(x) in case x is floating point in [0,1]
00254         // Based on code by Lawrence Kirby (fred@genesis.demon.co.uk)
00255 
00256         static uint32 differ = 0;  // guarantee time-based seeds will change
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 // Change log:
00319 //
00320 // v0.1 - First release on 15 May 2000
00321 //      - Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
00322 //      - Translated from C to C++
00323 //      - Made completely ANSI compliant
00324 //      - Designed convenient interface for initialization, seeding, and
00325 //        obtaining numbers in default or user-defined ranges
00326 //      - Added automatic seeding from /dev/urandom or time() and clock()
00327 //      - Provided functions for saving and loading generator state
00328 //
00329 // v0.2 - Fixed bug which reloaded generator one step too late
00330 //
00331 // v0.3 - Switched to clearer, faster reload() code from Matthew Bellew
00332 //
00333 // v0.4 - Removed trailing newline in saved generator format to be consistent
00334 //        with output format of built-in types
00335 //
00336 // v0.5 - Improved portability by replacing static const int's with enum's and
00337 //        clarifying return values in seed(); suggested by Eric Heimburg
00338 //      - Removed MAXINT constant; use 0xffffffff instead
00339 //
00340 // v0.6 - Eliminated seed overflow when uint32 is larger than 32 bits
00341 //      - Changed integer [0,n] generator to give better uniformity
00342 //
00343 // v0.7 - Fixed operator precedence ambiguity in reload()
00344 //      - Added access for real numbers in (0,1) and (0,n)
 All Classes Functions Variables Typedefs Friends