#include "MersenneTwister.h"

namespace PsimagLite {

MersenneTwister::MersenneTwister(unsigned s)
    : index_(0)
{
	seed(s);
}

MersenneTwister::MersenneTwister(unsigned s, int rank, int)
: index_(0)
{
	seed(s);
	int news = random();
	for (int i = 1; i < rank; ++i) {
		news = random();
	}

	seed(news);
}

void
MersenneTwister::seed(unsigned s)
{
	index_ = 0;
	state_[0] = s;
	for (unsigned i = 1; i < N_; ++i) {
		unsigned tmp = state_[i-1]^(state_[i-1]>>30);	
		state_[i] =  keepLast32BitMask_ &
		        (1812433253 * (tmp + i));
	}
}

void
MersenneTwister::generate()
{
	for (unsigned i = 0; i < N_; ++i) {
		unsigned y = (state_[i] & 0x80000000) +
		        (state_[(i+1)%N_] & 0x7fffffff);
		state_[i] = state_[(i+397)%N_] ^ (y >> 1);
		if (y%2 != 0)
			state_[i] ^= 2567483615;
	}
}

unsigned
MersenneTwister::random()
{
	if (index_ == 0)
		generate();

	unsigned y = state_[index_];
	y ^= (y >> 11);
	y ^= (y << 07) & 2636928640;
	y ^= (y << 15) & 4022730752;
	y ^= (y >> 18);

	index_ = (index_+1)%N_;

	return y;
}

double
MersenneTwister::operator() ()
{
	unsigned r = random();
	return (static_cast<double>(r)/keepLast32BitMask_);
}

} // namespace PsimagLite

