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