using System; namespace Orthogonal.Common { /// /// Managed code implementation of the Mersenne Twister random number generator algorithm by /// Makoto Matsumoto and Takuji Nishimura. /// /// See /// Mersenne Twister Home Page.. A good technical summary can be found on /// John Savard's Mersenne Twister page. [CLSCompliant(false)] public sealed class RandMT { const int N = 624; const int M = 397; const uint MATRIX_A = 0x9908b0dfU; /* constant vector a */ const uint UPPER_MASK = 0x80000000U; /* most significant w-r bits */ const uint LOWER_MASK = 0x7fffffffU; /* least significant r bits */ static uint[] mt = new uint[N]; /* the array for the state vector */ static uint mti = N+1; /* mti==N+1 means mt[N] is not initialized */ static uint[] mag01 = { 0x0U, MATRIX_A }; /// /// Creates a random number generator seeded with the current time milliseconds. /// public RandMT() { init_genrand((uint)DateTime.Now.Millisecond); } /// /// Creates a random number generator seeded with a specified integer. /// /// The seed number for the generator. public RandMT(uint seed) { init_genrand(seed); } /// /// Creates a rand number generator seeded with a specified integer array. /// /// The seed integer array for the generator. public RandMT(uint[] seeds) { init_by_array(seeds,(uint)seeds.Length); } #region Initializers /// /// initializes mt[N] with a seed /// /// private void init_genrand(uint s) { mt[0] = s & 0xffffffffU; for (mti=1; mti> 30)) + mti); /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ /* In the previous versions, MSBs of the seed affect */ /* only MSBs of the array mt[]. */ /* 2002/01/09 modified by Makoto Matsumoto */ mt[mti] &= 0xffffffffU; /* for >32 bit machines */ } } /// /// initialize by an array with array-length /// init_key is the array for initializing keys /// key_length is its length /// slight change for C++, 2004/2/26 /// private void init_by_array(uint[] init_key, uint key_length) { uint i, j, k; init_genrand(19650218U); i=1; j=0; k = (N>key_length ? N : key_length); for (; k!=0; k--) //?? k>=0 { mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525U)) + init_key[j] + j; /* non linear */ mt[i] &= 0xffffffffU; /* for WORDSIZE > 32 machines */ i++; j++; if (i>=N) { mt[0] = mt[N-1]; i=1; } if (j>=key_length) j=0; } for (k=N-1; k!=0; k--) //?? k>=0 { mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941U)) - i; /* non linear */ mt[i] &= 0xffffffffU; /* for WORDSIZE > 32 machines */ i++; if (i>=N) { mt[0] = mt[N-1]; i=1; } } mt[0] = 0x80000000U; /* MSB is 1; assuring non-zero initial array */ } #endregion #region Standard Random Mockups /// /// Generates a random positive signed integer in the interval [0,0x7fffffff]. The value /// is created by simply dropping the high-order sign bit of the raw unsigned value. /// /// A random positive signed integer in the interval [0,0x7fffffff]. public int Next() { return RandInt31(); } /// /// Generates a random positive integer in the interval [0,maxValue). The value will be /// GE zero and LT maxValue. /// /// The maximum value ceiling. /// A random positive integer in the interval [0,maxValue). public int Next(int maxValue) { return Next(0,maxValue); } /// /// Generates a random positive integer in the interval [minValue,maxValue). The value will /// be GE minValue and LT maxValue. /// /// The minimum value floor. /// The maximum value ceiling. /// A random positive integer in the interval [minValue,maxValue). /// Thrown if the range is invalid. public int Next(int minValue, int maxValue) { if (minValue >= maxValue) throw new ArgumentException(string.Format("Next({0},{1}) sequence error",minValue,maxValue)); double d = (maxValue - minValue) * RandDouble2() + minValue; return (int)d; } /// /// Generates a random real number in the range [0,1). The value will be GE zero and LT 1.0. /// /// A random real number in the range [0,1). public double NextDouble() { return RandDouble2(); } #endregion #region Original C Functions /// /// Generates a random unsigned integer in the interval [0,0xffffffff]. /// /// This is the core method that is used to generate other random numbers in /// different normalized ranges. /// A random unsigned integer in the range [0,0xffffffff]. public uint RandUint32() { uint y; if (mti >= N) { /* generate N words at one time */ int kk; if (mti == N+1) /* if init_genrand() has not been called, */ init_genrand(5489U); /* a default initial seed is used */ for (kk=0;kk> 1) ^ mag01[y & 0x1U]; } for (;kk> 1) ^ mag01[y & 0x1U]; } y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1U]; mti = 0; } y = mt[mti++]; /* Tempering */ y ^= (y >> 11); y ^= (y << 7) & 0x9d2c5680U; y ^= (y << 15) & 0xefc60000U; y ^= (y >> 18); return y; } /// /// Generates a random signed integer in the range [0,0x7fffffff]. /// public int RandInt31() { return (int)(RandUint32()>>1); } /// /// Generates a random double in the real interval [0,1]. /// public double RandDouble1() { return RandUint32()*(1.0/4294967295.0); /* divided by 2^32-1 */ } /// /// Generates a random double in the real interval [0,1). /// public double RandDouble2() { return RandUint32()*(1.0/4294967296.0); /* divided by 2^32 */ } /// /// Generates a random double in the real interval (0,1). /// public double RandDouble3() { return (((double)RandUint32()) + 0.5)*(1.0/4294967296.0); /* divided by 2^32 */ } /// /// Generates a random number in the real interval [0,1) with 53-bit resolution. /// public double RandDouble53() { uint a=RandUint32()>>5, b=RandUint32()>>6; return(a*67108864.0+b)*(1.0/9007199254740992.0); } #endregion } }