dynare/dynare++/kord/mersenne_twister.hweb

142 lines
3.4 KiB
Plaintext

@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"
#include <cstring>
@<|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.