CoMD
A Mini-app for Co-Design of Classical Molecular Dynamics.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
random.c
Go to the documentation of this file.
1 /// \file
2 /// Simple random number generators for uniform and Gaussian
3 /// distributions. The generator in lcg61 and the hash in mkSeed aren't
4 /// really industrial strength, but they're more than good enough for
5 /// present purposes.
6 
7 #include "random.h"
8 
9 #include <math.h>
10 
11 /// \details
12 /// Use the Box-Muller method to sample a Gaussian distribution with
13 /// zero mean and unit variance. To ensure the same input seed always
14 /// generates the same returned value we do not use the standard
15 /// technique of saving one of the two generated randoms for the next
16 /// call.
17 ///
18 /// \param [in,out] seed Seed for generator.
19 ///
20 /// \return A pseudo-random number in the interval (-infinity, infinity).
21 real_t gasdev(uint64_t* seed)
22 {
23  real_t rsq,v1,v2;
24  do
25  {
26  v1 = 2.0*lcg61(seed)-1.0;
27  v2 = 2.0*lcg61(seed)-1.0;
28  rsq = v1*v1+v2*v2;
29  } while (rsq >= 1.0 || rsq == 0.0);
30 
31  return v2 * sqrt(-2.0*log(rsq)/rsq);
32 }
33 
34 /// \details
35 /// A 61-bit prime modulus linear congruential generator with
36 /// modulus = 2^61 -1.
37 ///
38 /// \param [in,out] seed Seed for generator.
39 ///
40 /// \return A pseudo-random number in the interval [0, 1].
41 double lcg61(uint64_t* seed)
42 {
43  static const double convertToDouble = 1.0/UINT64_C(2305843009213693951);
44 
45  *seed *= UINT64_C(437799614237992725);
46  *seed %= UINT64_C(2305843009213693951);
47 
48  return *seed*convertToDouble;
49 }
50 
51 /// \details
52 /// Forms a 64-bit seed for lcg61 from the combination of 2 32-bit Knuth
53 /// multiplicative hashes, then runs off 10 values to pass up the worst
54 /// of the early low-bit correlations.
55 ///
56 /// \param [in] id An id number such as an atom gid that is unique to
57 /// each entity that requires random numbers.
58 ///
59 /// \param [in] callSite A unique number for each call site in the code
60 /// that needs to generate random seeds. Using a different value for
61 /// callSite allows different parts of the code to obtain different
62 /// random streams for the same id.
63 ///
64 /// \return A 64-bit seed that is unique to the id and call site.
65 uint64_t mkSeed(uint32_t id, uint32_t callSite)
66 {
67  uint32_t s1 = id * UINT32_C(2654435761);
68  uint32_t s2 = (id+callSite) * UINT32_C(2654435761);
69 
70  uint64_t iSeed = (UINT64_C(0x100000000) * s1) + s2;
71  for (unsigned jj=0; jj<10; ++jj)
72  lcg61(&iSeed);
73 
74  return iSeed;
75 }