2009-09-08 15:55:19 +02:00
|
|
|
@q $Id: mersenne_twister.hweb 1490 2007-12-19 14:29:46Z kamenik $ @>
|
|
|
|
@q Copyright 2007, Ondra Kamenik @>
|
|
|
|
|
|
|
|
@*2 Mersenne Twister PRNG. Start of {\tt mersenne\_twister.h} file.
|
|
|
|
|
|
|
|
This file provides a class for generating random numbers with
|
|
|
|
encapsulated state. It is based on the work of Makoto Matsumoto and
|
|
|
|
Takuji Nishimura, implementation inspired by code of Richard Wagner
|
|
|
|
and Geoff Kuenning.
|
|
|
|
|
|
|
|
@s uint32 int
|
|
|
|
@s MersenneTwister int
|
|
|
|
|
|
|
|
@c
|
|
|
|
#ifndef MERSENNE_TWISTER_H
|
|
|
|
#define MERSENNE_TWISTER_H
|
|
|
|
|
|
|
|
#include "random.h"
|
2009-11-03 15:16:18 +01:00
|
|
|
#include <cstring>
|
2009-09-08 15:55:19 +02:00
|
|
|
|
|
|
|
@<|MersenneTwister| class declaration@>;
|
|
|
|
@<|MersenneTwister| inline method definitions@>;
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
@
|
|
|
|
@<|MersenneTwister| class declaration@>=
|
|
|
|
class MersenneTwister : public RandomGenerator {
|
|
|
|
protected:@;
|
|
|
|
typedef unsigned int uint32;
|
|
|
|
enum {STATE_SIZE = 624};
|
|
|
|
enum {RECUR_OFFSET = 397};
|
|
|
|
uint32 statevec[STATE_SIZE];
|
|
|
|
int stateptr;
|
|
|
|
public:@;
|
|
|
|
MersenneTwister(uint32 iseed);
|
|
|
|
MersenneTwister(const MersenneTwister& mt);
|
|
|
|
virtual ~MersenneTwister() {}
|
|
|
|
uint32 lrand();
|
|
|
|
double drand();
|
|
|
|
double uniform()
|
|
|
|
{@+return drand();@+}
|
|
|
|
protected:@;
|
|
|
|
void seed(uint32 iseed);
|
|
|
|
void refresh();
|
|
|
|
private:@;
|
|
|
|
@<|MersenneTwister| static inline methods@>;
|
|
|
|
};
|
|
|
|
|
|
|
|
@
|
|
|
|
@<|MersenneTwister| static inline methods@>=
|
|
|
|
static uint32 hibit(uint32 u)
|
|
|
|
{return u & 0x80000000UL;}
|
|
|
|
static uint32 lobit(uint32 u)
|
|
|
|
{return u & 0x00000001UL;}
|
|
|
|
static uint32 lobits(uint32 u)
|
|
|
|
{return u & 0x7fffffffUL;}
|
|
|
|
static uint32 mixbits(uint32 u, uint32 v)
|
|
|
|
{return hibit(u) | lobits(v);}
|
|
|
|
static uint32 twist(uint32 m, uint32 s0, uint32 s1)
|
|
|
|
{return m ^ (mixbits(s0,s1)>>1) ^ (-lobit(s1) & 0x9908b0dfUL);}
|
|
|
|
|
|
|
|
|
|
|
|
@
|
|
|
|
@<|MersenneTwister| inline method definitions@>=
|
|
|
|
@<|MersenneTwister| constructor code@>;
|
|
|
|
@<|MersenneTwister| copy constructor code@>;
|
|
|
|
@<|MersenneTwister::lrand| code@>;
|
|
|
|
@<|MersenneTwister::drand| code@>;
|
|
|
|
@<|MersenneTwister::seed| code@>;
|
|
|
|
@<|MersenneTwister::refresh| code@>;
|
|
|
|
|
|
|
|
@
|
|
|
|
@<|MersenneTwister| constructor code@>=
|
|
|
|
inline MersenneTwister::MersenneTwister(uint32 iseed)
|
|
|
|
{
|
|
|
|
seed(iseed);
|
|
|
|
}
|
|
|
|
|
|
|
|
@
|
|
|
|
@<|MersenneTwister| copy constructor code@>=
|
|
|
|
inline MersenneTwister::MersenneTwister(const MersenneTwister& mt)
|
|
|
|
: stateptr(mt.stateptr)
|
|
|
|
{
|
|
|
|
memcpy(statevec, mt.statevec, sizeof(uint32)*STATE_SIZE);
|
|
|
|
}
|
|
|
|
|
|
|
|
@
|
|
|
|
@<|MersenneTwister::lrand| code@>=
|
|
|
|
inline MersenneTwister::uint32 MersenneTwister::lrand()
|
|
|
|
{
|
|
|
|
if (stateptr >= STATE_SIZE)
|
|
|
|
refresh();
|
|
|
|
|
|
|
|
register uint32 v = statevec[stateptr++];
|
|
|
|
v ^= v >> 11;
|
|
|
|
v ^= (v << 7) & 0x9d2c5680;
|
|
|
|
v ^= (v << 15) & 0xefc60000;
|
|
|
|
return (v ^ (v >> 18));
|
|
|
|
}
|
|
|
|
|
|
|
|
@
|
|
|
|
@<|MersenneTwister::drand| code@>=
|
|
|
|
inline double MersenneTwister::drand()
|
|
|
|
{
|
|
|
|
uint32 a = lrand() >> 5;
|
|
|
|
uint32 b = lrand() >> 6;
|
|
|
|
return (a*67108864.0+b) * (1.0/9007199254740992.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
@ PRNG of D. Knuth
|
|
|
|
@<|MersenneTwister::seed| code@>=
|
|
|
|
inline void MersenneTwister::seed(uint32 iseed)
|
|
|
|
{
|
|
|
|
statevec[0] = iseed & 0xffffffffUL;
|
|
|
|
for (int i = 1; i < STATE_SIZE; i++) {
|
|
|
|
register uint32 val = statevec[i-1] >> 30;
|
|
|
|
val ^= statevec[i-1];
|
|
|
|
val *= 1812433253ul;
|
|
|
|
val += i;
|
|
|
|
statevec[i] = val & 0xffffffffUL;
|
|
|
|
}
|
|
|
|
|
|
|
|
refresh();
|
|
|
|
}
|
|
|
|
|
|
|
|
@
|
|
|
|
@<|MersenneTwister::refresh| code@>=
|
|
|
|
inline void MersenneTwister::refresh()
|
|
|
|
{
|
|
|
|
register uint32* p = statevec;
|
|
|
|
for (int i = STATE_SIZE-RECUR_OFFSET; i--; ++p)
|
|
|
|
*p = twist(p[RECUR_OFFSET], p[0], p[1]);
|
|
|
|
for (int i = RECUR_OFFSET; --i; ++p)
|
|
|
|
*p = twist(p[RECUR_OFFSET-STATE_SIZE], p[0], p[1]);
|
|
|
|
*p = twist(p[RECUR_OFFSET-STATE_SIZE], p[0], statevec[0]);
|
|
|
|
|
|
|
|
stateptr = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
@ End of {\tt mersenne\_twister.h} file.
|