@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.
