pixelcity/Random.cpp

94 lines
2.9 KiB
C++

/*-----------------------------------------------------------------------------
r a n d o m
-----------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------
The Mersenne Twister by Matsumoto and Nishimura <matumoto@math.keio.ac.jp>.
It sets new standards for the period, quality and speed of random number
generators. The incredible period is 2^19937 - 1, a number with about 6000
digits; the 32-bit random numbers exhibit best possible equidistribution
properties in dimensions up to 623; and it's fast, very fast.
-----------------------------------------------------------------------------*/
#define LOWER_MASK 0x7fffffff
#define M 397
#define MATRIX_A 0x9908b0df
#define N 624
#define TEMPERING_MASK_B 0x9d2c5680
#define TEMPERING_MASK_C 0xefc60000
#define TEMPERING_SHIFT_L(y) (y >> 18)
#define TEMPERING_SHIFT_S(y) (y << 7)
#define TEMPERING_SHIFT_T(y) (y << 15)
#define TEMPERING_SHIFT_U(y) (y >> 11)
#define UPPER_MASK 0x80000000
#include <memory.h>
#include "random.h"
static int k = 1;
static unsigned long mag01[2] = {0x0, MATRIX_A};
static unsigned long ptgfsr[N];
/*-----------------------------------------------------------------------------
-----------------------------------------------------------------------------*/
unsigned long RandomVal (void)
{
int kk;
unsigned long y;
if (k == N) {
for (kk = 0; kk < N - M; kk++) {
y = (ptgfsr[kk] & UPPER_MASK) | (ptgfsr[kk + 1] & LOWER_MASK);
ptgfsr[kk] = ptgfsr[kk + M] ^ (y >> 1) ^ mag01[y & 0x1];
}
for (; kk < N - 1; kk++) {
y = (ptgfsr[kk] & UPPER_MASK) | (ptgfsr[kk + 1] & LOWER_MASK);
ptgfsr[kk] = ptgfsr[kk + (M - N)] ^ (y >> 1) ^ mag01[y & 0x1];
}
y = (ptgfsr[N - 1] & UPPER_MASK) | (ptgfsr[0] & LOWER_MASK);
ptgfsr[N - 1] = ptgfsr[M - 1] ^ (y >> 1) ^ mag01[y & 0x1];
k = 0;
}
y = ptgfsr[k++];
y ^= TEMPERING_SHIFT_U (y);
y ^= TEMPERING_SHIFT_S (y) & TEMPERING_MASK_B;
y ^= TEMPERING_SHIFT_T (y) & TEMPERING_MASK_C;
return y ^= TEMPERING_SHIFT_L (y);
}
/*-----------------------------------------------------------------------------
-----------------------------------------------------------------------------*/
unsigned long RandomVal (int range)
{
return range ? (RandomVal () % range) : 0;
}
/*-----------------------------------------------------------------------------
-----------------------------------------------------------------------------*/
void RandomInit (unsigned long seed)
{
//int k;
//memset (ptgfsr, 0, sizeof (ptgfsr));
//mag01[0] = 0x0;
//mag01[1] = MATRIX_A;
ptgfsr[0] = seed;
for (k = 1; k < N; k++)
ptgfsr[k] = 69069 * ptgfsr[k - 1];
k = 1;
}