00001 // $Id: mtrand.h 751 2006-03-31 15:43:49Z alex $ 00002 #ifndef MTRAND_H 00003 #define MTRAND_H 00004 00005 /* @@tag:xara-cn-tp@@ THIRD PARTY COPYRIGHT */ 00006 // Mersenne Twister random number generator -- a C++ class MTRand 00007 // Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus 00008 // Richard J. Wagner v1.0 15 May 2003 rjwagner@writeme.com 00009 00010 // The Mersenne Twister is an algorithm for generating random numbers. It 00011 // was designed with consideration of the flaws in various other generators. 00012 // The period, 2^19937-1, and the order of equidistribution, 623 dimensions, 00013 // are far greater. The generator is also fast; it avoids multiplication and 00014 // division, and it benefits from caches and pipelines. For more information 00015 // see the inventors' web page at http://www.math.keio.ac.jp/~matumoto/emt.html 00016 00017 // Reference 00018 // M. Matsumoto and T. Nishimura, "Mersenne Twister: A 623-Dimensionally 00019 // Equidistributed Uniform Pseudo-Random Number Generator", ACM Transactions on 00020 // Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3-30. 00021 00022 // Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, 00023 // Copyright (C) 2000 - 2003, Richard J. Wagner 00024 // All rights reserved. 00025 // 00026 // Redistribution and use in source and binary forms, with or without 00027 // modification, are permitted provided that the following conditions 00028 // are met: 00029 // 00030 // 1. Redistributions of source code must retain the above copyright 00031 // notice, this list of conditions and the following disclaimer. 00032 // 00033 // 2. Redistributions in binary form must reproduce the above copyright 00034 // notice, this list of conditions and the following disclaimer in the 00035 // documentation and/or other materials provided with the distribution. 00036 // 00037 // 3. The names of its contributors may not be used to endorse or promote 00038 // products derived from this software without specific prior written 00039 // permission. 00040 // 00041 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00042 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00043 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00044 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 00045 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00046 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00047 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00048 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00049 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00050 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00051 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00052 00053 // The original code included the following notice: 00054 // 00055 // When you use this, send an email to: matumoto@math.keio.ac.jp 00056 // with an appropriate reference to your work. 00057 // 00058 // It would be nice to CC: rjwagner@writeme.com and Cokus@math.washington.edu 00059 // when you write. 00060 00061 // Not thread safe (unless auto-initialization is avoided and each thread has 00062 // its own MTRand object) 00063 00064 /******************************************************************************************** 00065 00066 > class MTRand 00067 00068 Author: Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com> (adapted from original - see above) 00069 Created: 04/11/2005 00070 00071 Purpose: This is the ``Mersenne Twister'' random number generator MT19937, which 00072 generates pseudorandom integers uniformly distributed in 0..(2^32 - 1) 00073 starting from any odd seed in 0..(2^32 - 1). 00074 00075 SeeAlso: http://www.math.keio.ac.jp/~matumoto/emt.html is the homepage where you can find 00076 out all about this algorithm. This particular adaptation is taken from the recode 00077 by Martin Hinsche http://www.usf.uos.de/~mhinsch/index.en.html. 00078 00079 ********************************************************************************************/ 00080 00081 // Two constants for GetNextRandomNumberScaled 00082 // Latter casting suppresses compiler warnings - the sign does not actually matter as 00083 // it's only used for UINT32 & UINT32 subtraction 00084 #define MTRAND_MAX 4294967296.0 00085 #define MTRAND_MED ((UINT32)(2147483648ULL)) 00086 00087 class MTRand : public CCObject 00088 { 00089 // Data 00090 protected: 00091 enum { N = 624 }; // length of state vector 00092 enum { M = 397 }; // period parameter 00093 00094 UINT32 state[N]; // internal state 00095 UINT32 *pNext; // next value to get from state 00096 INT32 left; // number of values left before reload needed 00097 00098 static UINT32 lastSeed; 00099 00100 //Methods 00101 public: 00102 MTRand( const UINT32& oneSeed ); // initialize with a simple uint32 00103 MTRand(); // auto-initialize with /dev/urandom or time() and clock() 00104 00105 // Do NOT use for CRYPTOGRAPHY without securely hashing several returned 00106 // values together, otherwise the generator state can be learned after 00107 // reading 624 consecutive values. 00108 00109 UINT32 rand(); // integer in [0,2^32-1] 00110 UINT32 operator()() { return rand(); } // same as rand() 00111 00112 // Re-seeding functions with same behavior as initializers 00113 void seed( const UINT32 oneSeed ); 00114 00115 // returns the next random number scaled so it is between the values given 00116 UINT32 GetNextRandomNumberScaled(UINT32 MaxValue, UINT32 MinValue); 00117 00118 UINT32 GetNextRandomNumberScaled(UINT32 MaxValue, UINT32 MinValue, UINT32 Median); 00119 00120 protected: 00121 void initialize( const UINT32 oneSeed ); 00122 void reload(); 00123 UINT32 hiBit( const UINT32& u ) const { return u & 0x80000000UL; } 00124 UINT32 loBit( const UINT32& u ) const { return u & 0x00000001UL; } 00125 UINT32 loBits( const UINT32& u ) const { return u & 0x7fffffffUL; } 00126 UINT32 mixBits( const UINT32& u, const UINT32& v ) const 00127 { return hiBit(u) | loBits(v); } 00128 UINT32 twist( const UINT32& m, const UINT32& s0, const UINT32& s1 ) const 00129 { return m ^ (mixBits(s0,s1)>>1) ^ (-(INT32)loBit(s1) & 0x9908b0dfUL); } 00130 }; 00131 00132 00133 inline MTRand::MTRand( const UINT32& oneSeed ) 00134 { seed(lastSeed = oneSeed); } 00135 00136 inline MTRand::MTRand() 00137 { seed(lastSeed += 2); } 00138 00139 00140 inline UINT32 MTRand::rand() 00141 { 00142 // Pull a 32-bit integer from the generator state 00143 // Every other access function simply transforms the numbers extracted here 00144 00145 if( left == 0 ) reload(); 00146 --left; 00147 00148 register UINT32 s1; 00149 s1 = *pNext++; 00150 s1 ^= (s1 >> 11); 00151 s1 ^= (s1 << 7) & 0x9d2c5680UL; 00152 s1 ^= (s1 << 15) & 0xefc60000UL; 00153 return ( s1 ^ (s1 >> 18) ); 00154 } 00155 00156 00157 inline void MTRand::seed( const UINT32 oneSeed ) 00158 { 00159 // Seed the generator with a simple UINT32 00160 initialize(oneSeed); 00161 reload(); 00162 } 00163 00164 00165 inline void MTRand::initialize( const UINT32 seed ) 00166 { 00167 // Initialize generator state with seed 00168 // See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier. 00169 // In previous versions, most significant bits (MSBs) of the seed affect 00170 // only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto. 00171 // register UINT32 *s = state; 00172 // register UINT32 *r = state; 00173 // register INT32 i = 1; 00174 // *s++ = seed & 0xffffffffUL; 00175 // for( ; i < N; ++i ) 00176 // { 00177 // *s++ = ( 1812433253UL * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffUL; 00178 // r++; 00179 // } 00180 00181 // This is the original seeding code to ensure that the number sequences are the same 00182 register UINT32 x = (seed | 1U) & 0xFFFFFFFFU, *s = state; 00183 register INT32 j; 00184 00185 for(left=0, *s++=x, j=N; --j; 00186 *s++ = (x*=69069U) & 0xFFFFFFFFU); 00187 } 00188 00189 00190 inline void MTRand::reload() 00191 { 00192 // Generate N new values in state 00193 // Made clearer and faster by Matthew Bellew (matthew.bellew@home.com) 00194 register UINT32 *p = state; 00195 register INT32 i; 00196 for( i = N - M; i--; ++p ) 00197 *p = twist( p[M], p[0], p[1] ); 00198 for( i = M; --i; ++p ) 00199 *p = twist( p[M-N], p[0], p[1] ); 00200 *p = twist( p[M-N], p[0], state[0] ); 00201 00202 left = N, pNext = state; 00203 } 00204 00205 #endif // MTRAND_H