module utils.Random; import std.random; import std.date; /// Global Random Generator Singleton PrivateRandomGenerator randomGenerator; static this(){ randomGenerator=new PrivateRandomGenerator(rand()); } /// Class beeing a private Random Generator. class PrivateRandomGenerator{ private{ /* Period parameters */ const uint N = 624; const uint M = 397; const uint MATRIX_A = 0x9908b0df; /* constant vector a */ const uint UPPER_MASK = 0x80000000; /* most significant w-r bits */ const uint LOWER_MASK = 0x7fffffff; /* least significant r bits */ uint[N] mt; /* the array for the state vector */ uint mti=mt.length+1; /* mti==mt.length+1 means mt[] is not initialized */ uint vLastRand; /* The most recent random uint returned. */ } /** When useing simple constructor: before using, initialize the state by using seedInit or arrayInit. However, if you do not a seed is generated based on the current date-time of the system. */ this(){} /// initializes generator with a seed this(uint s, bool pAddEntropy = false){ seedInit(s,pAddEntropy); } /// initialize by an array with array-length init_key is the array for initializing keys this(uint[] init_key, bool pAddEntropy = false){ arrayInit(init_key,pAddEntropy); } /** initializes generator with a seed */ void seedInit(uint s, bool pAddEntropy = false) { mt[0]= (s + (pAddEntropy ? vLastRand + std.date.getUTCtime(): 0))& 0xffffffffUL; for (mti=1; mti> 30)) + mti); mt[mti] &= 0xffffffffUL; } } /** initialize by an array with array-length init_key is the array for initializing keys */ void arrayInit(uint[] init_key, bool pAddEntropy = false){ int i, j, k; seedInit( 19650218UL, pAddEntropy); i=1; j=0; for (k = (mt.length > init_key.length ? mt.length : init_key.length); k; k--) { mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL))+ init_key[j] + j; mt[i] &= 0xffffffffUL; i++; j++; if (i >= mt.length) { mt[0] = mt[mt.length-1]; i=1; } if (j >= init_key.length) j=0; } for (k=mt.length-1; k; k--) { mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL))- i; mt[i] &= 0xffffffffUL; i++; if (i>=mt.length) { mt[0] = mt[mt.length-1]; i=1; } } mt[0] |= 0x80000000UL; mti=0; } /// generates a random number on [0,0xffffffff]-interval uint getInt(bool pAddEntropy = false){ uint y; static uint mag01[2] =[0, MATRIX_A]; if (mti >= mt.length) { int kk; if (pAddEntropy || mti > mt.length) { seedInit( 5489UL, pAddEntropy ); } for (kk=0;kk> 1) ^ mag01[y & 1UL]; } for (;kk> 1) ^ mag01[y & 1UL]; } y = (mt[mt.length-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); mt[mt.length-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 1UL]; mti = 0; } y = mt[mti++]; y ^= (y >> 11); y ^= (y << 7) & 0x9d2c5680UL; y ^= (y << 15) & 0xefc60000UL; y ^= (y >> 18); vLastRand = y; return y; } /** generates a random number on [0,0x7fffffff]-interval */ long getInt31(){ return cast(long)(getInt()>>1); } /** generates a random number on [0,1]-real-interval */ double getReal(){ return getInt()*(1.0/cast(double)uint.max); } /** generates a random number on [0,1)-real-interval */ double getReal1(){ return getInt()*(1.0/(cast(double)uint.max+1.0)); } /** generates a random number on (0,1)-real-interval */ double getReal2(){ return ((cast(double)getInt()) + 0.5)*(1.0/(cast(double)uint.max+1.0)); } /** generates a random number on [0,1) with 53-bit resolution*/ double getRes53() { uint a=getInt()>>5, b=getInt()>>6; return(a*67108864.0+b)*(1.0/9007199254740992.0); } }