Bridge++  Version 1.4.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 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, "Error at %s: 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  read_file(filename);
55 }
56 
57 
58 //====================================================================
59 void RandomNumbers_MT19937::read_file(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, "Error at %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, "Error at %s: 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, "Error at %s: 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::write_file(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, "Error at %s: 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::reset(unsigned long seed)
123 {
124  return init(seed);
125 }
126 
127 
128 //====================================================================
129 void RandomNumbers_MT19937::init(unsigned long s)
130 {
131  m_state[0] = s & 0xffffffffUL;
132  for (int j = 1; j < N; ++j) {
133  m_state[j] = (1812433253UL * (m_state[j - 1] ^ (m_state[j - 1] >> 30)) + j);
134  m_state[j] &= 0xffffffffUL;
135  }
136 }
137 
138 
139 void RandomNumbers_MT19937::init(unsigned long s, vector<unsigned long>& key)
140 {
141  init(s);
142  int i = 1;
143  int j = 0;
144  int key_length = key.size();
145 
146  for (int k = N > key_length ? N : key_length; k; --k) {
147  // non linear
148  m_state[i]
149  = (m_state[i] ^ ((m_state[i - 1] ^ (m_state[i - 1] >> 30)) * 1664525UL)) + key[j] + j;
150  // for WORDSIZE > 32 machines
151  m_state[i] &= 0xffffffffUL;
152 
153  ++i;
154  ++j;
155  if (i >= N) {
156  m_state[0] = m_state[N - 1];
157  i = 1;
158  }
159  if (j >= key_length) j = 0;
160  }
161 
162  for (int k = N - 1; k; --k) {
163  // non linear
164  m_state[i] = (m_state[i] ^ ((m_state[i - 1] ^ (m_state[i - 1] >> 30)) * 1566083941UL)) - i;
165  m_state[i] &= 0xffffffffUL; // for WORDSIZE > 32 machines
166  i++;
167  if (i >= N) {
168  m_state[0] = m_state[N - 1];
169  i = 1;
170  }
171  }
172  // MSB is 1; assuring non-zero initial array
173  m_state[0] = 0x80000000UL;
174 }
175 
176 
177 //====================================================================
179 {
180  unsigned long *p = m_state;
181 
182  m_left = N;
183  m_next = m_state;
184  for (int j = N - M + 1; --j; ++p) {
185  *p = p[M] ^ twist(p[0], p[1]);
186  }
187  for (int j = M; --j; ++p) {
188  *p = p[M - N] ^ twist(p[0], p[1]);
189  }
190 
191  *p = p[M - N] ^ twist(p[0], m_state[0]);
192 }
193 
194 
195 unsigned long
196 RandomNumbers_MT19937::twist(unsigned long u, unsigned long v) const
197 {
198  // Period parameters
199  const unsigned long mtrx_a = 0x9908b0dfUL; // constant vector a
200  const unsigned long umask = 0x80000000UL; // most significant w-r bits
201  const unsigned long lmask = 0x7fffffffUL; // least significant r bits
202 
203  unsigned long maxbits = (u & umask) | (v & lmask);
204 
205  return (maxbits >> 1) ^ (v & 1UL ? mtrx_a : 0UL);
206 }
207 
208 
209 //====================================================================
210 // generates a random number on [0,0xffffffff]
211 unsigned long RandomNumbers_MT19937::randInt32() const
212 {
213  if (--m_left == 0) nextState();
214  unsigned long y = *m_next++;
215 
216  // Tempering
217  y ^= (y >> 11);
218  y ^= (y << 7) & 0x9d2c5680UL;
219  y ^= (y << 15) & 0xefc60000UL;
220  y ^= (y >> 18);
221  return y;
222 }
223 
224 
225 //generates a random number on [0,0x7fffffff]
227 {
228  return (long)(randInt32() >> 1);
229 }
230 
231 
232 //====================================================================
233 //generates a random number on [0,1] double number
235 {
236  static const double factor = 1.0 / 4294967295.0;
237 
238  return static_cast<double>(randInt32() * factor);
239 }
240 
241 
242 //generates a random number on [0,1) double number
244 {
245  static const double factor = 1.0 / 4294967296.0;
246 
247  return static_cast<double>(randInt32() * factor);
248 }
249 
250 
251 // generates a random number on (0,1) double number
253 {
254  static const double factor = 1.0 / 4294967296.0;
255 
256  return static_cast<double>((randInt32() + 0.5) * factor);
257 }
258 
259 
260 // generates a random number on [0,1) with 53-bit resolution
262 {
263  unsigned long a = randInt32() >> 5;
264  unsigned long b = randInt32() >> 6;
265  static const double factor = 1.0 / 9007199254740992.0;
266 
267  return (a * 67108864.0 + b) * factor;
268 }
269 
270 
271 //====================================================================
272 //============================================================END=====
BridgeIO vout
Definition: bridgeIO.cpp:495
void detailed(const char *format,...)
Definition: bridgeIO.cpp:212
static const std::string class_name
void general(const char *format,...)
Definition: bridgeIO.cpp:195
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:42
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.