SST/macro
rng.h
Go to the documentation of this file.
1 /*
2  * This file is part of SST/macroscale:
3  * The macroscale architecture simulator from the SST suite.
4  * Copyright (c) 2009 Sandia Corporation.
5  * This software is distributed under the BSD License.
6  * Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
7  * the U.S. Government retains certain rights in this software.
8  * For more information, see the LICENSE file in the top
9  * SST/macroscale directory.
10  */
11 
12 #ifndef SSTMAC_COMMON_RNG_H_INCLUDED
13 #define SSTMAC_COMMON_RNG_H_INCLUDED
14 
15 #include <stdint.h>
16 #include <limits>
17 #include <vector>
18 #include <string>
19 
20 namespace RNG {
21 
22 typedef uint32_t rngint_t;
23 
24 /** This is a base class for random number generators that return
25  an integer uniformly distributed in a range. */
27 {
28  public:
29  virtual
31 
32  virtual rngint_t
33  value() = 0;
34 
35  rngint_t
36  value_in_range(rngint_t range) {
37  return value() % range;
38  }
39 
40  virtual void
41  vec_reseed(const std::vector<rngint_t> &seeds) = 0;
42 
43  virtual int
44  nseed()= 0;
45 
46  /// Return a random value in the interval [0,1], (0,1], [0,1), or (0,1)
47  virtual double
48  realvalue(bool include_zero = true, bool include_one = true) {
49  rngint_t v = this->value();
50  // Total precision of 64-bit double is 53 bits --
51  // avoid oddball rounding errors.
52  double scaling = std::numeric_limits<rngint_t>::max();
53  if (sizeof(rngint_t) > 6) {
54  int shiftbits = 8 * int(sizeof(rngint_t)) - 53;
55  v >>= shiftbits;
56  scaling = 9007199254740992.0; // 2**53
57  }
58  if (!include_zero) {
59  v = (v >> 1) + 1;
60  scaling = scaling / 2.0 + 1.0;
61  }
62  if (include_one) {
63  scaling -= 1.0;
64  }
65  return v / scaling;
66  }
67 
68  void
69  reseed();
70 
71  void
72  reseed(rngint_t);
73 
74  void
75  reseed(rngint_t, rngint_t);
76 
77  void
78  reseed(rngint_t, rngint_t, rngint_t);
79 
80  void
81  reseed(rngint_t, rngint_t, rngint_t, rngint_t);
82 };
83 
84 /** The multiple-with-carry random number generator by
85  George Marsaglia (1999; internet posting).
86 
87  This RNG is fast and has a low memory footprint.
88  Here is an excerpt from the posting describing this generator:
89  <i>The MWC generator concatenates two 16-bit multiply-with-carry
90  generators, x(n)=36969x(n-1)+carry, y(n)=18000y(n-1)+carry mod
91  2<sup>16</sup>, has period about 2<sup>60</sup> and seems to pass all tests of
92  randomness. A favorite stand-alone generator---faster than
93  KISS, which contains it.</i>
94  */
95 class MWC : public UniformInteger
96 {
97  private:
98  static const rngint_t default_z, default_w;
99  rngint_t z, w;
100 
101  rngint_t
102  znew() {
103  return ((z = 36969 * (z & 65535) + (z >> 16)) << 16);
104  }
105 
106  rngint_t
107  wnew() {
108  return ((w = 18000 * (w & 65535) + (w >> 16)) & 65535);
109  }
110 
111  protected:
112  MWC();
113 
114  public:
115  virtual std::string
116  to_string() const {
117  return "MWC";
118  }
119 
120  static MWC*
121  construct();
122 
123  static MWC*
124  construct(const std::vector<rngint_t> &);
125 
126  static MWC*
127  construct(rngint_t zarg);
128 
129  static MWC*
130  construct(rngint_t zarg, rngint_t warg);
131 
132  ~MWC();
133 
134  rngint_t
135  value() {
136  return (znew() + wnew());
137  }
138 
139  void
140  vec_reseed(const std::vector<rngint_t> &seeds);
141 
142  int
143  nseed();
144 };
145 
146 /** The 3-shift-register random number generator by George
147  Marsaglia (1999; internet posting).
148 
149  This RNG is fast and has a very low memory footprint.
150  Here is an excerpt from the posting describing this generator:
151  <i>SHR3 is a 3-shift-register generator with period 2<sup>32</sup>-1. It
152  uses y(n)=y(n-1)(I+L17)(I+R13)(I+L5), with the y's viewed as
153  binary vectors, L the 32x32 binary matrix that shifts a vector
154  left 1, and R its transpose. SHR3 seems to pass all except
155  the binary rank test, since 32 successive values, as binary
156  vectors, must be linearly independent, while 32 successive
157  truly random 32-bit integers, viewed as binary vectors, will
158  be linearly independent only about 29% of the time.</i>
159  */
160 class SHR3 : public UniformInteger
161 {
162  private:
163  rngint_t jsr;
164 
165  protected:
166  SHR3();
167 
168  public:
169  virtual std::string
170  to_string() const {
171  return "SHR3";
172  }
173 
174  static SHR3*
175  construct();
176 
177  static SHR3*
178  construct(const std::vector<rngint_t>&);
179 
180  static SHR3*
181  construct(rngint_t jsrarg);
182 
183  ~SHR3();
184 
185  rngint_t value();
186 
187  void
188  vec_reseed(const std::vector<rngint_t> &seeds);
189 
190  int
191  nseed();
192 };
193 
195 {
196  private:
198 
199  double lambda_;
200 
201  public:
202  ExponentialDistribution(double lambda) :
203  lambda_(lambda)
204  {
205  rngint_t seed = time(NULL);
206  rand_ = SHR3::construct(seed);
207  }
208 
209  double value();
210 
211  std::string
212  to_string() const;
213 
214 };
215 
217 {
218  private:
220 
221  double mean_;
222 
223  double stdev_;
224 
225  double maxZ_;
226 
227  bool reuse_;
228 
229  double Y_;
230 
231  public:
232  NormalDistribution(double mean, double stdev,
233  double maxZ = 2.0, rngint_t seed = 0);
234 
236 
237  double value();
238 
239  std::string
240  to_string() const;
241 
242 };
243 
244 /** The congruential random number generator by George Marsaglia
245  (1999; internet posting).
246 
247  This RNG is fast and has a very low memory footprint.
248  Here is an excerpt from the posting describing this generator:
249  <i>CONG is a congruential generator with the widely used 69069
250  as multiplier: x(n)=69069x(n-1)+1234567. It has period 2<sup>32</sup>.
251  The leading half of its 32 bits seem to pass all tests, but
252  bits in the last half are too regular.</i>
253  */
254 class CONG : public UniformInteger
255 {
256  private:
257  rngint_t jcong;
258 
259  public:
260  virtual std::string
261  to_string() const {
262  return "CONG";
263  }
264 
265  static CONG*
266  construct();
267 
268  static CONG*
269  construct(const std::vector<rngint_t>&);
270 
271  static CONG*
272  construct(rngint_t jcongarg);
273 
274  ~CONG();
275 
276  rngint_t
277  value() {
278  return (jcong = 69069 * jcong + 1234567);
279  }
280 
281  void
282  vec_reseed(const std::vector<rngint_t> &seeds);
283 
284  int
285  nseed();
286 
287  protected:
288  CONG();
289 
290  CONG(const std::vector<rngint_t>&);
291 
292  CONG(rngint_t jcongarg);
293 };
294 
295 /** A simple random generator using MWC, CONG, and SHR3 by
296  George Marsaglia (1999; internet posting).
297 
298  Here is an excerpt from the posting describing this generator:
299  <i>The KISS generator, (Keep It Simple Stupid), is designed to
300  combine the two multiply-with-carry generators in MWC with the
301  3-shift register SHR3 and the congruential generator CONG,
302  using addition and exclusive-or. Period about 2<sup>123</sup>. It is one
303  of my favorite generators.</i>
304  */
306 {
307  private:
311 
312  public:
313  virtual std::string
314  to_string() const {
315  return "SimpleCombo";
316  }
317 
318  static SimpleCombo*
319  construct();
320 
321  static SimpleCombo*
322  construct(const std::vector<rngint_t> &);
323 
324  static SimpleCombo*
325  construct(rngint_t zarg);
326 
327  static SimpleCombo*
328  construct(rngint_t zarg, rngint_t warg);
329 
330  static SimpleCombo*
331  construct(rngint_t zarg, rngint_t warg, rngint_t jsrarg);
332 
333  static SimpleCombo*
334  construct(rngint_t zarg, rngint_t warg, rngint_t jsrarg, rngint_t jcongarg);
335 
336  ~SimpleCombo();
337 
338  // value is written in this way to make it possible to inline
339  // the MWC, CONG, and SHR3 value calls.
340  rngint_t
341  value() {
342  return (mwc_->MWC::value() ^ cong_->CONG::value()) + shr3_->SHR3::value();
343  }
344 
345  void
346  vec_reseed(const std::vector<rngint_t> &seeds);
347 
348  int
349  nseed();
350 
351  protected:
352  SimpleCombo();
353 };
354 
355 /** A base class for random number generators using a table of 256 32-bit integers. */
356 class Table256 : public UniformInteger
357 {
358  public:
359  ~Table256();
360 
361  void
362  vec_reseed(const std::vector<rngint_t> &seeds);
363 
364  int
365  nseed();
366 
367  protected:
369 
370  rngint_t t[256];
371 
372  unsigned char c;
373 
374  Table256();
375 
376 };
377 
378 /**
379  A lagged Fibonacci random number generator by George Marsaglia
380  (1999; internet posting).
381 
382  Here is an excerpt from the posting describing this generator:
383  <i>LFIB4 is an extension of the class that I have previously
384  defined as lagged Fibonacci generators: x(n)=x(n-r) op x(n-s),
385  with the x's in a finite set over which there is a binary
386  operation op, such as +,- on integers mod 232, * on odd such
387  integers, exclusive-or (xor) on binary vectors. Except for
388  those using multiplication, lagged Fibonacci generators fail
389  various tests of randomness, unless the lags are very long. To
390  see if more than two lags would serve to overcome the problems
391  of 2- lag generators using +,- or xor, I have developed the
392  4-lag generator LFIB4: x(n)=x(n-256)+x(n-179)+x(n-119)+x(n-55)
393  mod 232. Its period is 2<sup>31</sup>*(2<sup>256</sup>-1), about 2<sup>287</sup>, and it seems
394  to pass all tests---in particular, those of the kind for which
395  2-lag generators using +,-,xor seem to fail. For even more
396  confidence in its suitability, LFIB4 can be combined with KISS,
397  with a resulting period of about 2<sup>410</sup>: just use (KISS+LFIB4) in
398  any C expression.</i>
399  */
400 class LFIB4 : public Table256
401 {
402  protected:
403  LFIB4();
404 
405  public:
406  virtual std::string
407  to_string() const {
408  return "LFIB4";
409  }
410 
411  static LFIB4*
412  construct();
413 
414  static LFIB4*
415  construct(const std::vector<rngint_t> &seeds);
416 
417  rngint_t
418  value() {
419  unsigned char i1, i2, i3, i4;
420  i1 = c;
421  i2 = c + 58;
422  i3 = c + 119;
423  i4 = ++c + 178;
424  return (t[i1] = t[i1] + t[i2] + t[i3] + t[i4]);
425  }
426 
427  ~LFIB4();
428 
429  void
430  vec_reseed(const std::vector<rngint_t> &seeds);
431 
432  int
433  nseed();
434 };
435 
436 /**
437  A subtract with borrow random number generator by George
438  Marsaglia (1999; internet posting).
439 
440  Here is an excerpt from the posting describing this generator:
441  <i>SWB is a subtract-with-borrow generator that I developed to
442  give a simple method for producing extremely long periods:
443  x(n)=x(n-222)-x(n-237)-borrow mod 2<sup>32</sup>. The 'borrow' is 0
444  unless set to 1 if computing x(n-1) caused overflow in 32-bit
445  integer arithmetic. This generator has a very long period,
446  2<sup>7098</sup>(2<sup>480</sup>-1), about 2<sup>7578</sup>. It seems to pass all tests of
447  randomness, but, suspicious of a generator so simple and fast
448  (62 nanosecs at 300MHz), I would suggest combining SWB with
449  KISS, MWC, SHR3, or CONG.</i>
450  */
451 class SWB : public Table256
452 {
453  private:
454  rngint_t x, y;
455 
456  protected:
457  SWB();
458 
459  public:
460  virtual std::string
461  to_string() const {
462  return "SWB";
463  }
464 
465  static SWB*
466  construct();
467 
468  static SWB*
469  construct(const std::vector<rngint_t>&);
470 
471  rngint_t
472  value();
473 
474  ~SWB();
475 
476  void
477  vec_reseed(const std::vector<rngint_t> &seeds);
478 
479  int
480  nseed();
481 };
482 
483 /**
484  A random number generator combining several techniques by
485  George Marsaglia (1999; internet posting).
486 
487  Here is an excerpt from the posting describing this generator:
488  <i>For the super cautious, (KISS+SWB) in an expression would
489  provide a random 32-bit integer from a sequence with period >
490  2<sup>7700</sup>, and would only add some 300 nanoseconds to the computing
491  time for that expression.</i>
492  */
493 
494 class Combo : public UniformInteger
495 {
496  public:
497  virtual std::string
498  to_string() const {
499  return "Combo";
500  }
501 
502  static Combo*
503  construct();
504 
505  static Combo*
506  construct(const std::vector<rngint_t>&);
507 
508  rngint_t
509  value() {
510  rngint_t kresult = simplecombo_->SimpleCombo::value();
511  rngint_t sresult = swb_->SWB::value();
512  return kresult + sresult;
513  }
514 
515  ~Combo();
516 
517  void
518  vec_reseed(const std::vector<rngint_t> &seeds);
519 
520  int
521  nseed();
522 
523  private:
526 
527  protected:
528  Combo();
529 
530 };
531 
532 /** Converts a shared* to a RNG to a functor. */
534 {
536 
537  public:
539  p_(p) {
540  }
541 
542  rngint_t
544  return p_->value();
545  }
546 
547  rngint_t
548  operator()(rngint_t range) {
549  return p_->value_in_range(range);
550  }
551 };
552 
553 }
554 
555 #endif
556 
static const rngint_t default_z
Definition: rng.h:98
rngint_t operator()(rngint_t range)
Definition: rng.h:548
rngint_t value()
Definition: rng.h:277
virtual double realvalue(bool include_zero=true, bool include_one=true)
Return a random value in the interval [0,1], (0,1], [0,1), or (0,1)
Definition: rng.h:48
rngint_t jsr
Definition: rng.h:163
virtual int nseed()=0
SWB * swb_
Definition: rng.h:524
static SHR3 * construct()
rngint_t wnew()
Definition: rng.h:107
rngint_t znew()
Definition: rng.h:102
A base class for random number generators using a table of 256 32-bit integers.
Definition: rng.h:356
Converts a shared* to a RNG to a functor.
Definition: rng.h:533
virtual std::string to_string() const
Definition: rng.h:407
rngint_t value()
Definition: rng.h:418
This is a base class for random number generators that return an integer uniformly distributed in a r...
Definition: rng.h:26
UniformInteger * p_
Definition: rng.h:535
virtual std::string to_string() const
Definition: rng.h:170
SHR3 * shr3_
Definition: rng.h:310
rngint_t operator()()
Definition: rng.h:543
virtual std::string to_string() const
Definition: rng.h:116
rngint_t z
Definition: rng.h:99
rngint_t value()
Definition: rng.h:341
rngint_t value_in_range(rngint_t range)
Definition: rng.h:36
The multiple-with-carry random number generator by George Marsaglia (1999; internet posting)...
Definition: rng.h:95
rngint_t value()
Definition: rng.h:509
rngint_t y
Definition: rng.h:454
virtual std::string to_string() const
Definition: rng.h:314
UniformInteger_functor(UniformInteger *p)
Definition: rng.h:538
SimpleCombo * simplecombo_
Definition: rng.h:525
virtual rngint_t value()=0
The congruential random number generator by George Marsaglia (1999; internet posting).
Definition: rng.h:254
The 3-shift-register random number generator by George Marsaglia (1999; internet posting).
Definition: rng.h:160
virtual std::string to_string() const
Definition: rng.h:498
uint32_t rngint_t
Definition: rng.h:22
ExponentialDistribution(double lambda)
Definition: rng.h:202
CONG * cong_
Definition: rng.h:309
unsigned char c
Definition: rng.h:372
virtual ~UniformInteger()
UniformInteger * seeder_
Definition: rng.h:368
MWC * mwc_
Definition: rng.h:308
virtual std::string to_string() const
Definition: rng.h:461
rngint_t jcong
Definition: rng.h:257
virtual void vec_reseed(const std::vector< rngint_t > &seeds)=0
A lagged Fibonacci random number generator by George Marsaglia (1999; internet posting).
Definition: rng.h:400
rngint_t value()
Definition: rng.h:135
A simple random generator using MWC, CONG, and SHR3 by George Marsaglia (1999; internet posting)...
Definition: rng.h:305
virtual std::string to_string() const
Definition: rng.h:261
A subtract with borrow random number generator by George Marsaglia (1999; internet posting)...
Definition: rng.h:451
A random number generator combining several techniques by George Marsaglia (1999; internet posting)...
Definition: rng.h:494