mtrand.h

Go to the documentation of this file.
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

Generated on Sat Nov 10 03:48:40 2007 for Camelot by  doxygen 1.4.4