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