Skip to content

Instantly share code, notes, and snippets.

@ryuukk
Created March 8, 2022 06:02
Show Gist options
  • Save ryuukk/a8215379f23bd3e7813843738a51c918 to your computer and use it in GitHub Desktop.
Save ryuukk/a8215379f23bd3e7813843738a51c918 to your computer and use it in GitHub Desktop.
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