#pragma once
#include <cassert>
#using <mscorlib.dll>
using namespace System;
using namespace std;

__gc class RandomStream {
private:
	static unsigned __int64 MODLUS = 2147483647;
	static unsigned __int64 MULT = 630360016;
	static UInt64 seeds[] = {1973272912, 281629770, 20006270, 1280689831, 209673239, 1933576050, 2367210574, 3826401784, 1231243453};
	UInt16 stream;
protected:
	Double rand() {
		UInt64 aux = seeds[stream];
		seeds[stream] = (seeds[stream] * MULT) % MODLUS;
		return aux / 2147483647.0;
	}
public:
	RandomStream(UInt16 str): stream(str) {
		//cout << "o str" << str << "\n";
		assert(str >= 0 && str < seeds->Length);
	}
	UInt64 next() {
		UInt64 aux = seeds[stream];
		seeds[stream] = (seeds[stream] * MULT) % MODLUS;
		return aux;
	}
	Double exponential(Double mean) {
		return - mean * System::Math::Log(rand());
	}
	Double uniform(Double min, Double max) {
		assert(max > min);

		return min + rand() * (max - min);
	}
};
