Bridge++  Ver. 1.3.x
randomNumbers_MT19937.cpp
Go to the documentation of this file.
1 
14 #include "randomNumbers_MT19937.h"
15 
16 const std::string RandomNumbers_MT19937::class_name = "RandomNumbers_MT19937";
17 
18 //====================================================================
20  : m_left(1)
21 {
22  if (s < 0) {
23  vout.crucial(m_vl, "%s: error: seed must be positive.\n", class_name.c_str());
24  exit(EXIT_FAILURE);
25  }
26  vout.general(m_vl, "%s: seed = %d\n", class_name.c_str(), s);
27  init(s);
28 }
29 
30 
32  : m_left(1)
33 {
34  vout.general(m_vl, "%s: seed = %ul\n", class_name.c_str(), s);
35  init(s);
36 }
37 
38 
39 RandomNumbers_MT19937::RandomNumbers_MT19937(vector<unsigned long>& key)
40  : m_left(1)
41 {
42  vout.general(m_vl, "%s: seeds = (", class_name.c_str());
43  for (int i = 0; i < key.size(); ++i) {
44  vout.general(m_vl, "%ul, ", key[i]);
45  }
46  vout.general(m_vl, ")\n");
47 
48  init(19650218UL, key);
49 }
50 
51 
53 {
54  readfile(filename);
55 }
56 
57 
58 //====================================================================
59 void RandomNumbers_MT19937::readfile(const string& filename)
60 {
61  vout.detailed(m_vl, "%s: read from file %s\n", class_name.c_str(), filename.c_str());
62 
64  std::ifstream in_file(filename.c_str());
65  if (!in_file) {
66  vout.crucial(m_vl, "%s: error: unable to open input file.\n", class_name.c_str());
67  exit(EXIT_FAILURE);
68  }
69 
70  unsigned long int n;
71  for (int i = 0; i < N; ++i) {
72  if (in_file >> n) {
73  m_state[i] = n;
74  } else {
75  vout.crucial(m_vl, "%s: error: seed data in input file is missing.\n", class_name.c_str());
76  exit(EXIT_FAILURE);
77  }
78  }
79 
80  if (in_file >> n) {
81  m_left = n;
82  } else {
83  vout.crucial(m_vl, "%s: error: counter data in input file is missing.\n", class_name.c_str());
84  exit(EXIT_FAILURE);
85  }
86 
87  in_file.close();
88  }
89 
90  Communicator::Base::broadcast(sizeof(int), &m_left, 0);
91  Communicator::Base::broadcast(sizeof(unsigned long) * N, m_state, 0);
92 
93  m_next = m_state + N - m_left + 1;
94 }
95 
96 
97 //====================================================================
98 void RandomNumbers_MT19937::writefile(const string& filename)
99 {
100  vout.detailed(m_vl, "%s: save random number state to file %s\n", class_name.c_str(), filename.c_str());
101 
102  if (Communicator::is_primary()) {
103  std::ofstream out_file(filename.c_str());
104 
105  if (!out_file) {
106  vout.crucial(m_vl, "%s: error: unable to open output file.\n", class_name.c_str());
107  exit(EXIT_FAILURE);
108  }
109 
110  for (int i = 0; i < N; ++i) {
111  out_file << m_state[i] << std::endl;
112  }
113 
114  out_file << m_left << std::endl;
115 
116  out_file.close();
117  }
118 }
119 
120 
121 //====================================================================
122 void RandomNumbers_MT19937::init(unsigned long s)
123 {
124  m_state[0] = s & 0xffffffffUL;
125  for (int j = 1; j < N; ++j) {
126  m_state[j] = (1812433253UL * (m_state[j - 1] ^ (m_state[j - 1] >> 30)) + j);
127  m_state[j] &= 0xffffffffUL;
128  }
129 }
130 
131 
132 void RandomNumbers_MT19937::init(unsigned long s, vector<unsigned long>& key)
133 {
134  init(s);
135  int i = 1;
136  int j = 0;
137  int key_length = key.size();
138 
139  for (int k = N > key_length ? N : key_length; k; --k) {
140  // non linear
141  m_state[i]
142  = (m_state[i] ^ ((m_state[i - 1] ^ (m_state[i - 1] >> 30)) * 1664525UL)) + key[j] + j;
143  // for WORDSIZE > 32 machines
144  m_state[i] &= 0xffffffffUL;
145 
146  ++i;
147  ++j;
148  if (i >= N) {
149  m_state[0] = m_state[N - 1];
150  i = 1;
151  }
152  if (j >= key_length) j = 0;
153  }
154 
155  for (int k = N - 1; k; --k) {
156  // non linear
157  m_state[i] = (m_state[i] ^ ((m_state[i - 1] ^ (m_state[i - 1] >> 30)) * 1566083941UL)) - i;
158  m_state[i] &= 0xffffffffUL; // for WORDSIZE > 32 machines
159  i++;
160  if (i >= N) {
161  m_state[0] = m_state[N - 1];
162  i = 1;
163  }
164  }
165  // MSB is 1; assuring non-zero initial array
166  m_state[0] = 0x80000000UL;
167 }
168 
169 
170 //====================================================================
172 {
173  unsigned long *p = m_state;
174 
175  m_left = N;
176  m_next = m_state;
177  for (int j = N - M + 1; --j; ++p) {
178  *p = p[M] ^ twist(p[0], p[1]);
179  }
180  for (int j = M; --j; ++p) {
181  *p = p[M - N] ^ twist(p[0], p[1]);
182  }
183 
184  *p = p[M - N] ^ twist(p[0], m_state[0]);
185 }
186 
187 
188 unsigned long
189 RandomNumbers_MT19937::twist(unsigned long u, unsigned long v) const
190 {
191  // Period parameters
192  const unsigned long mtrx_a = 0x9908b0dfUL; // constant vector a
193  const unsigned long umask = 0x80000000UL; // most significant w-r bits
194  const unsigned long lmask = 0x7fffffffUL; // least significant r bits
195 
196  unsigned long maxbits = (u & umask) | (v & lmask);
197 
198  return (maxbits >> 1) ^ (v & 1UL ? mtrx_a : 0UL);
199 }
200 
201 
202 //====================================================================
203 // generates a random number on [0,0xffffffff]
204 unsigned long RandomNumbers_MT19937::randInt32() const
205 {
206  if (--m_left == 0) nextState();
207  unsigned long y = *m_next++;
208 
209  // Tempering
210  y ^= (y >> 11);
211  y ^= (y << 7) & 0x9d2c5680UL;
212  y ^= (y << 15) & 0xefc60000UL;
213  y ^= (y >> 18);
214  return y;
215 }
216 
217 
218 //generates a random number on [0,0x7fffffff]
220 {
221  return (long)(randInt32() >> 1);
222 }
223 
224 
225 //====================================================================
226 //generates a random number on [0,1] double number
228 {
229  static const double factor = 1.0 / 4294967295.0;
230 
231  return static_cast<double>(randInt32() * factor);
232 }
233 
234 
235 //generates a random number on [0,1) double number
237 {
238  static const double factor = 1.0 / 4294967296.0;
239 
240  return static_cast<double>(randInt32() * factor);
241 }
242 
243 
244 // generates a random number on (0,1) double number
246 {
247  static const double factor = 1.0 / 4294967296.0;
248 
249  return static_cast<double>((randInt32() + 0.5) * factor);
250 }
251 
252 
253 // generates a random number on [0,1) with 53-bit resolution
255 {
256  unsigned long a = randInt32() >> 5;
257  unsigned long b = randInt32() >> 6;
258  static const double factor = 1.0 / 9007199254740992.0;
259 
260  return (a * 67108864.0 + b) * factor;
261 }
262 
263 
264 //====================================================================
265 //============================================================END=====
BridgeIO vout
Definition: bridgeIO.cpp:278
void writefile(const std::string &)
void detailed(const char *format,...)
Definition: bridgeIO.cpp:82
static const std::string class_name
void general(const char *format,...)
Definition: bridgeIO.cpp:65
unsigned long twist(unsigned long u, unsigned long v) const
void readfile(const std::string &)
static int broadcast(size_t size, void *data, int sender)
Bridge::VerboseLevel m_vl
Definition: randomNumbers.h:45
void init(unsigned long s)
unsigned long randInt32() const
void crucial(const char *format,...)
Definition: bridgeIO.cpp:48
static bool is_primary()
check if the present node is primary in small communicator.