/*
The Mersenne Twister
The Mersenne Twister is a random number generator, invented/discovered in 1996 by Matsumora and Nishimura.
MT is a twisted GFSR(624,397), similar in spirit to R250 and in speed to R250. MT has an period of 2^19937-1.
It is a very good random number generator.
*/
#include <cstdlib>
#include <ctime>
#include <fstream>
#include "cMTRandom.h"
/*
Constants
*/
const unsigned long UPPER_MASK = 0x80000000;
const unsigned long LOWER_MASK = 0x7FFFFFFF;
const unsigned long MATRIX = 0x9908B0DF;
const unsigned long MANGLE_A = 0x9D2C5680;
const unsigned long MANGLE_B = 0xEFC60000;
/*
Variables
*/
cMTRandom::cMTRandom(void)
{
/*
On linux we can use /dev/urandom to get our starting seed, as it's
less predictable then time() or srand()/rand() seeded from a specific
time.
On other systems just use time() since it's just as random as srand()/
rand() seeded at time(), and a quicker.
*/
#ifdef __linux__
std::ifstream entropy("/dev/urandom", std::ios::in | std::ios::binary);
entropy.read((char*)(&MT[0]), sizeof(MT[0]));
entropy.close();
#else
MT[0] = time(0);
#endif
// now initialize the generator
for (int i = 1; i < 624; i++)
MT[i] = (69069 * MT[i-1]);
// generate the initial set of numbers
GenerateNumbers();
index = 0;
}
cMTRandom::cMTRandom(unsigned long seed)
{
// now initialize the generator
MT[0] = seed;
for (int i = 1; i < 624; i++)
MT[i] = (69069 * MT[i-1]);
// generate the initial set of numbers
GenerateNumbers();
index = 0;
}
void cMTRandom::GenerateNumbers(void)
{
int y;
for (int i = 0; i < 623; i++)
{
y = (MT[i] & UPPER_MASK) + (MT[i+1] & LOWER_MASK);
if (y & 1 == 0)
MT[i] = MT[(i + 397) % 624] ^ (y >> 1);
else
MT[i] = MT[(i + 397) % 624] ^ (y >> 1) ^ MATRIX;
}
y = (MT[623] & UPPER_MASK) + (MT[0] & LOWER_MASK);
if ( y & 1 == 0)
MT[623] = MT[396] ^ (y >> 1);
else
MT[623] = MT[396] ^ (y >> 1) ^ MATRIX;
}
unsigned long cMTRandom::Rand(void)
{
if (index == 624)
{
index = 0;
GenerateNumbers();
}
unsigned long x = ((MT[index] & 0xFFFF0000) & MANGLE_A) ^ (MT[index] << 16);
unsigned long y = ((MT[index] & 0x0000FFFF) & MANGLE_B) ^ (MT[index] >> 16);
index++;
return (x ^ y);
}
|