• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

Rand.cpp

Go to the documentation of this file.
00001 
00040 #include <stdio.h>
00041 #include <stdlib.h>
00042 #include <string.h>
00043 #include "Rand.h"
00044 
00045 //
00046 // uint32 must be an unsigned integer type capable of holding at least 32
00047 // bits; exactly 32 should be fastest, but 64 is better on an Alpha with
00048 // GCC at -O3 optimization so try your options and see what's best for you
00049 //
00050 
00051 //typedef unsigned int uint32;
00052 
00053 #define N        (624)       // length of state vector
00054 #define M        (397)       // a period parameter
00055 #define K        (0x9908B0DFU)      // a magic constant
00056 #define hiBit(u)       ((u) & 0x80000000U)   // mask all but highest   bit of u
00057 #define loBit(u)       ((u) & 0x00000001U)   // mask all but lowest    bit of u
00058 #define loBits(u)      ((u) & 0x7FFFFFFFU)   // mask  the highest   bit of u
00059 #define mixBits(u, v)  (hiBit(u)|loBits(v))  // move hi bit of u to hi bit of v
00060 
00061 static unsigned int _state[ N + 1 ];     // state vector + 1 extra to not violate ANSI C
00062 static unsigned int *_next;        // next random value is computed from here
00063 static int _left = -1; // can *next++ this many times before reloading
00064 
00065 void seedMT( unsigned int seed, unsigned int *state, unsigned int *&next, int &left );
00066 unsigned int reloadMT( unsigned int *state, unsigned int *&next, int &left );
00067 unsigned int randomMT( unsigned int *state, unsigned int *&next, int &left );
00068 void fillBufferMT( void *buffer, unsigned int bytes, unsigned int *state, unsigned int *&next, int &left );
00069 float frandomMT( unsigned int *state, unsigned int *&next, int &left );
00070 
00071 // Uses global vars
00072 void seedMT( unsigned int seed )
00073 {
00074         seedMT(seed, _state, _next, _left);
00075 }
00076 unsigned int reloadMT( void )
00077 {
00078         return reloadMT(_state, _next, _left);
00079 }
00080 unsigned int randomMT( void )
00081 {
00082         return randomMT(_state, _next, _left);
00083 }
00084 float frandomMT( void )
00085 {
00086         return frandomMT(_state, _next, _left);
00087 }
00088 void fillBufferMT( void *buffer, unsigned int bytes )
00089 {
00090         fillBufferMT(buffer, bytes, _state, _next, _left);
00091 }
00092 
00093 void seedMT( unsigned int seed, unsigned int *state, unsigned int *&next, int &left )   // Defined in cokus_c.c
00094 {
00095         (void) next;
00096 
00097         //
00098         // We initialize state[0..(N-1)] via the generator
00099         //
00100         //  x_new = (69069 * x_old) mod 2^32
00101         //
00102         // from Line 15 of Table 1, p. 106, Sec. 3.3.4 of Knuth's
00103         // _The Art of Computer Programming_, Volume 2, 3rd ed.
00104         //
00105         // Notes (SJC): I do not know what the initial state requirements
00106         // of the Mersenne Twister are, but it seems this seeding generator
00107         // could be better.  It achieves the maximum period for its modulus
00108         // (2^30) iff x_initial is odd (p. 20-21, Sec. 3.2.1.2, Knuth); if
00109         // x_initial can be even, you have sequences like 0, 0, 0, ...;
00110         // 2^31, 2^31, 2^31, ...; 2^30, 2^30, 2^30, ...; 2^29, 2^29 + 2^31,
00111         // 2^29, 2^29 + 2^31, ..., etc. so I force seed to be odd below.
00112         //
00113         // Even if x_initial is odd, if x_initial is 1 mod 4 then
00114         //
00115         //  the   lowest bit of x is always 1,
00116         //  the  next-to-lowest bit of x is always 0,
00117         //  the 2nd-from-lowest bit of x alternates   ... 0 1 0 1 0 1 0 1 ... ,
00118         //  the 3rd-from-lowest bit of x 4-cycles   ... 0 1 1 0 0 1 1 0 ... ,
00119         //  the 4th-from-lowest bit of x has the 8-cycle ... 0 0 0 1 1 1 1 0 ... ,
00120         //   ...
00121         //
00122         // and if x_initial is 3 mod 4 then
00123         //
00124         //  the   lowest bit of x is always 1,
00125         //  the  next-to-lowest bit of x is always 1,
00126         //  the 2nd-from-lowest bit of x alternates   ... 0 1 0 1 0 1 0 1 ... ,
00127         //  the 3rd-from-lowest bit of x 4-cycles   ... 0 0 1 1 0 0 1 1 ... ,
00128         //  the 4th-from-lowest bit of x has the 8-cycle ... 0 0 1 1 1 1 0 0 ... ,
00129         //   ...
00130         //
00131         // The generator's potency (min. s>=0 with (69069-1)^s = 0 mod 2^32) is
00132         // 16, which seems to be alright by p. 25, Sec. 3.2.1.3 of Knuth.  It
00133         // also does well in the dimension 2..5 spectral tests, but it could be
00134         // better in dimension 6 (Line 15, Table 1, p. 106, Sec. 3.3.4, Knuth).
00135         //
00136         // Note that the random number user does not see the values generated
00137         // here directly since reloadMT() will always munge them first, so maybe
00138         // none of all of this matters.  In fact, the seed values made here could
00139         // even be extra-special desirable if the Mersenne Twister theory says
00140         // so-- that's why the only change I made is to restrict to odd seeds.
00141         //
00142 
00143         register unsigned int x = ( seed | 1U ) & 0xFFFFFFFFU, *s = state;
00144         register int j;
00145 
00146         for ( left = 0, *s++ = x, j = N; --j;
00147                 *s++ = ( x *= 69069U ) & 0xFFFFFFFFU )
00148 
00149                 ;
00150 }
00151 
00152 
00153 unsigned int reloadMT( unsigned int *state, unsigned int *&next, int &left )
00154 {
00155         register unsigned int * p0 = state, *p2 = state + 2, *pM = state + M, s0, s1;
00156         register int j;
00157 
00158         if ( left < -1 )
00159                 seedMT( 4357U );
00160 
00161         left = N - 1, next = state + 1;
00162 
00163         for ( s0 = state[ 0 ], s1 = state[ 1 ], j = N - M + 1; --j; s0 = s1, s1 = *p2++ )
00164                 * p0++ = *pM++ ^ ( mixBits( s0, s1 ) >> 1 ) ^ ( loBit( s1 ) ? K : 0U );
00165 
00166         for ( pM = state, j = M; --j; s0 = s1, s1 = *p2++ )
00167                 * p0++ = *pM++ ^ ( mixBits( s0, s1 ) >> 1 ) ^ ( loBit( s1 ) ? K : 0U );
00168 
00169         s1 = state[ 0 ], *p0 = *pM ^ ( mixBits( s0, s1 ) >> 1 ) ^ ( loBit( s1 ) ? K : 0U );
00170 
00171         s1 ^= ( s1 >> 11 );
00172 
00173         s1 ^= ( s1 << 7 ) & 0x9D2C5680U;
00174 
00175         s1 ^= ( s1 << 15 ) & 0xEFC60000U;
00176 
00177         return ( s1 ^ ( s1 >> 18 ) );
00178 }
00179 
00180 
00181 unsigned int randomMT( unsigned int *state, unsigned int *&next, int &left )
00182 {
00183         unsigned int y;
00184 
00185         if ( --left < 0 )
00186                 return ( reloadMT(state, next, left) );
00187 
00188         y = *next++;
00189 
00190         y ^= ( y >> 11 );
00191 
00192         y ^= ( y << 7 ) & 0x9D2C5680U;
00193 
00194         y ^= ( y << 15 ) & 0xEFC60000U;
00195 
00196         return ( y ^ ( y >> 18 ) );
00197 
00198         // This change made so the value returned is in the same range as what rand() returns
00199         // return(y ^ (y >> 18)) % 32767;
00200 }
00201 
00202 void fillBufferMT( void *buffer, unsigned int bytes, unsigned int *state, unsigned int *&next, int &left )
00203 {
00204         unsigned int offset=0;
00205         unsigned int r;
00206         while (bytes-offset>=sizeof(r))
00207         {
00208                 r = randomMT();
00209                 memcpy((char*)buffer+offset, &r, sizeof(r));
00210                 offset+=sizeof(r);
00211         }
00212 
00213         r = randomMT(state, next, left);
00214         memcpy((char*)buffer+offset, &r, bytes-offset);
00215 }
00216 
00217 float frandomMT( unsigned int *state, unsigned int *&next, int &left )
00218 {
00219         return ( float ) ( ( double ) randomMT(state, next, left) / 4294967296.0 );
00220 }
00221 RakNetRandom::RakNetRandom()
00222 {
00223         left=-1;
00224 }
00225 RakNetRandom::~RakNetRandom()
00226 {
00227 }
00228 void RakNetRandom::SeedMT( unsigned int seed )
00229 {
00230         seedMT(seed, state, next, left);
00231 }
00232 
00233 unsigned int RakNetRandom::ReloadMT( void )
00234 {
00235         return reloadMT(state, next, left);
00236 }
00237 
00238 unsigned int RakNetRandom::RandomMT( void )
00239 {
00240         return randomMT(state, next, left);
00241 }
00242 
00243 float RakNetRandom::FrandomMT( void )
00244 {
00245         return frandomMT(state, next, left);
00246 }
00247 
00248 void RakNetRandom::FillBufferMT( void *buffer, unsigned int bytes )
00249 {
00250         fillBufferMT(buffer, bytes, state, next, left);
00251 }
00252 
00253 /*
00254 int main(void)
00255 {
00256 int j;
00257 
00258 // you can seed with any uint32, but the best are odds in 0..(2^32 - 1)
00259 
00260 seedMT(4357U);
00261 
00262 // print the first 2,002 random numbers seven to a line as an example
00263 
00264 for(j=0; j<2002; j++)
00265 RAKNET_DEBUG_PRINTF(" %10lu%s", (unsigned int) randomMT(), (j%7)==6 ? "\n" : "");
00266 
00267 return(EXIT_SUCCESS);
00268 }
00269 
00270 */
00271 

Generated on Thu Sep 30 2010 01:27:27 for RakNet by  doxygen 1.7.1