forked from edrosten/threeB
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mt19937.h
141 lines (115 loc) · 2.54 KB
/
mt19937.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#ifndef MT19937_H
#define MT19937_H
#include "randomc.h"
#include <iostream>
#include <sstream>
#include <string>
#include <cmath>
#include <iomanip>
///Useful wrapper for MT19937 random number generator class.
///@ingroup gUtility
struct MT19937
{
///Null struct thrown if attempting to load
///state from stream yields a parse error.
struct ParseError{};
///Underlying RNG.
CRandomMersenne rng;
public:
MT19937()
:rng(0)
{}
///Seed state with a simple RNG
///@param seed
void simple_seed(int seed)
{
rng.RandomInit(seed);
}
///Duplicate RNG state
///@param r RNG to duplicate
void copy_state(const MT19937& r)
{
rng = r.rng;
}
///Generate a double
double operator()()
{
return rng.Random();
}
///Generate an int
uint32_t rand_int()
{
return rng.BRandom();
}
///Generate a Gaussian variate
double gaussian()
{
double x1, x2, w;
do {
x1 = 2.0 * (*this)() - 1.0;
x2 = 2.0 * (*this)() - 1.0;
w = x1 * x1 + x2 * x2;
} while ( w >= 1.0 );
w = std::sqrt( (-2.0 * std::log( w ) ) / w );
return x1 * w;
//spare so we don't have to save that one extra bit of state y2 = x2 * w;
}
///Serialise state
///@param o Stream to serialise to
void write(std::ostream& o)
{
using namespace std;
char f = o.fill();
ios_base::fmtflags fl = o.flags();
o << "MT19937 " << hex << setfill('0') << setw(3) << rng.get_index();
for(int i=0; i < MERS_N; i++)
o << " " << hex << setw(8) << rng.get_state()[i];
o << setfill(f) << setiosflags(fl);
}
///De serialise state
///param is Stream to de-serialise from
void read(std::istream& is)
{
using namespace std;
string ls;
getline(is, ls);
if(ls.size() != 5627)
{
cerr << "MT19937: Expected string of length 5627. Got " << ls.size() << endl;
throw ParseError();
}
istringstream l(ls);
string s;
uint32_t i;
l >> s;
if(s != "MT19937")
{
cerr << "MT19937: Expected MT19937. Got " << s << endl;
throw ParseError();
}
for(int n=0; n < MERS_N + 1; n++)
{
l >> hex >> i;
if(l.bad())
{
cerr << "MT19937: Expected hex number. Got ";
if(l.eof())
cerr << "EOF" << endl;
else
{
cerr << l.get() << endl;
}
throw ParseError();
}
if(n==0)
rng.get_index() = i;
else
rng.get_state()[n-1]=i;
}
}
private:
/// Disallow copying, since one almost never wants to do this.
/// Copying has to be explicit via MT19937::copy_state().
MT19937(const MT19937&);
};
#endif