Created
March 8, 2022 06:02
-
-
Save ryuukk/a8215379f23bd3e7813843738a51c918 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module rt.rand; | |
int rand_range(int min, int max) | |
{ | |
return (min == max) ? min : (min + (gen_rand_uint(&_r) % (max+1 - min))); | |
} | |
double rand_range(double min, double max) | |
{ | |
return min + ((max - min) * gen_rand_double(&_r)); | |
} | |
int next_int() | |
{ | |
return gen_rand_int(&_r); | |
} | |
double next_double() | |
{ | |
return gen_rand_double(&_r); | |
} | |
// MTwister | |
struct MTRand | |
{ | |
uint[STATE_VECTOR_LENGTH] mt; | |
int index; | |
} | |
package: | |
enum UPPER_MASK = 0x80000000UL; | |
enum LOWER_MASK = 0x7fffffffUL; | |
enum TEMPERING_MASK_B = 0x9d2c5680UL; | |
enum TEMPERING_MASK_C = 0xefc60000UL; | |
enum STATE_VECTOR_LENGTH = 624; | |
enum STATE_VECTOR_M = 397; /* changes to STATE_VECTOR_LENGTH also require changes to this */ | |
__gshared MTRand _r = create(__LINE__); | |
void m_seedRand(MTRand* rand, uint seed) { | |
/* set initial seeds to mt[STATE_VECTOR_LENGTH] using the generator | |
* from Line 25 of Table 1 in: Donald Knuth, "The Art of Computer | |
* Programming," Vol. 2 (2nd Ed.) pp.102. | |
*/ | |
rand.mt[0] = seed & 0xffffffff; | |
for(rand.index=1; rand.index<STATE_VECTOR_LENGTH; rand.index++) { | |
rand.mt[rand.index] = (6069 * rand.mt[rand.index-1]) & 0xffffffff; | |
} | |
} | |
// Creates a new random number generator from a given seed. | |
MTRand create(uint seed) { | |
MTRand rand; | |
m_seedRand(&rand, seed); | |
return rand; | |
} | |
/** | |
* Generates a pseudo-randomly generated long. | |
*/ | |
uint gen_rand_uint(MTRand* rand) { | |
uint y; | |
static uint[2] mag = [0x0, 0x9908b0df]; /* mag[x] = x * 0x9908b0df for x = 0,1 */ | |
if(rand.index >= STATE_VECTOR_LENGTH || rand.index < 0) { | |
/* generate STATE_VECTOR_LENGTH words at a time */ | |
int kk; | |
if(rand.index >= STATE_VECTOR_LENGTH+1 || rand.index < 0) { | |
m_seedRand(rand, 4357); | |
} | |
for(kk=0; kk<STATE_VECTOR_LENGTH-STATE_VECTOR_M; kk++) { | |
y = (rand.mt[kk] & UPPER_MASK) | (rand.mt[kk+1] & LOWER_MASK); | |
rand.mt[kk] = rand.mt[kk+STATE_VECTOR_M] ^ (y >> 1) ^ mag[y & 0x1]; | |
} | |
for(; kk<STATE_VECTOR_LENGTH-1; kk++) { | |
y = (rand.mt[kk] & UPPER_MASK) | (rand.mt[kk+1] & LOWER_MASK); | |
rand.mt[kk] = rand.mt[kk+(STATE_VECTOR_M-STATE_VECTOR_LENGTH)] ^ (y >> 1) ^ mag[y & 0x1]; | |
} | |
y = (rand.mt[STATE_VECTOR_LENGTH-1] & UPPER_MASK) | (rand.mt[0] & LOWER_MASK); | |
rand.mt[STATE_VECTOR_LENGTH-1] = rand.mt[STATE_VECTOR_M-1] ^ (y >> 1) ^ mag[y & 0x1]; | |
rand.index = 0; | |
} | |
y = rand.mt[rand.index++]; | |
y ^= (y >> 11); | |
y ^= (y << 7) & TEMPERING_MASK_B; | |
y ^= (y << 15) & TEMPERING_MASK_C; | |
y ^= (y >> 18); | |
return y; | |
} | |
int gen_rand_int(MTRand* rand) | |
{ | |
return cast(int)(gen_rand_uint(rand)>>1); | |
} | |
// Generates a pseudo-randomly generated double in the range [0, 1]. | |
double gen_rand_double(MTRand* rand) { | |
return(cast(double)gen_rand_uint(rand) / cast(uint)0xffffffff); | |
} | |
// generates a random number on [0,0x7fffffff]-interval */ | |
int genrand_int31(MTRand* rand) | |
{ | |
return cast(int)(gen_rand_uint(rand)>>1); | |
} | |
// generates a random number on [0,1]-real-interval */ | |
double genrand_real1(MTRand* rand) | |
{ | |
return gen_rand_uint(rand)*(1.0/4294967295.0); | |
/* divided by 2^32-1 */ | |
} | |
/* generates a random number on [0,1)-real-interval */ | |
double genrand_real2(MTRand* rand) | |
{ | |
return gen_rand_uint(rand)*(1.0/4294967296.0); | |
/* divided by 2^32 */ | |
} | |
// generates a random number on (0,1)-real-interval */ | |
double genrand_real3(MTRand* rand) | |
{ | |
return ((cast(double)gen_rand_uint(rand)) + 0.5)*(1.0/4294967296.0); | |
/* divided by 2^32 */ | |
} | |
// generates a random number on [0,1) with 53-bit resolution*/ | |
double genrand_res53(MTRand* rand) | |
{ | |
uint a=gen_rand_uint(rand)>>5, b=gen_rand_uint(rand)>>6; | |
return(a*67108864.0+b)*(1.0/9007199254740992.0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment