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
}
}