NAMD
Public Member Functions | List of all members
Random Class Reference

#include <Random.h>

Public Member Functions

 Random (void)
 
 Random (unsigned long seed)
 
void init (unsigned long seed)
 
void skip (void)
 
void split (int iStream, int numStreams)
 
BigReal uniform (void)
 
BigReal gaussian (void)
 
BigReal sum_of_squared_gaussians (int64_t num_gaussians)
 Return the sum of i.i.d. squared Gaussians. More...
 
Vector gaussian_vector (void)
 
long integer (void)
 
template<class Elem >
void reorder (Elem *a, int n)
 
void uniform_array_f (float *a, int n)
 
void gaussian_array_f (float *a, int n)
 

Detailed Description

Definition at line 37 of file Random.h.

Constructor & Destructor Documentation

◆ Random() [1/2]

Random::Random ( void  )
inline

Definition at line 50 of file Random.h.

References init(), and RAND48_SEED.

50  {
51  init(0);
52  rand48_seed = RAND48_SEED;
53  }
void init(unsigned long seed)
Definition: Random.h:61
#define RAND48_SEED
Definition: Random.h:32

◆ Random() [2/2]

Random::Random ( unsigned long  seed)
inline

Definition at line 56 of file Random.h.

References init().

56  {
57  init(seed);
58  }
void init(unsigned long seed)
Definition: Random.h:61

Member Function Documentation

◆ gaussian()

BigReal Random::gaussian ( void  )
inline

Definition at line 116 of file Random.h.

References uniform().

Referenced by Controller::adaptTempUpdate(), gaussian_array_f(), gaussian_vector(), Controller::langevinPiston1(), Controller::langevinPiston2(), colvarproxy_namd::rand_gaussian(), Controller::stochRescaleCoefficient(), and sum_of_squared_gaussians().

116  {
117 #ifdef DEBUG_RANDOM
118  static int count = 0;
119 #endif
120  BigReal fac, r, v1, v2;
121 
122  if (second_gaussian_waiting) {
123  second_gaussian_waiting = 0;
124 #ifdef DEBUG_RANDOM
125  count++;
126  fprintf(stderr, "RANDOM %6d %12.9f\n", count, second_gaussian);
127 #endif
128  return second_gaussian;
129  } else {
130  r = 2.; // r >= 1.523e-8 ensures abs result < 6
131  while (r >=1. || r < 1.523e-8) { // make sure we are within unit circle
132  v1 = 2.0 * uniform() - 1.0;
133  v2 = 2.0 * uniform() - 1.0;
134  r = v1*v1 + v2*v2;
135  }
136  fac = sqrt(-2.0 * log(r)/r);
137  // now make the Box-Muller transformation to get two normally
138  // distributed random numbers. Save one and return the other.
139  second_gaussian_waiting = 1;
140  second_gaussian = v1 * fac;
141 #ifdef DEBUG_RANDOM
142  count++;
143  fprintf(stderr, "RANDOM %6d %12.9f\n", count, v2 * fac);
144 #endif
145  return v2 * fac;
146  }
147  }
BigReal uniform(void)
Definition: Random.h:109
double BigReal
Definition: common.h:123

◆ gaussian_array_f()

void Random::gaussian_array_f ( float *  a,
int  n 
)
inline

Fill length n array from standard Gaussian distribution.

Definition at line 255 of file Random.h.

References gaussian().

Referenced by Sequencer::langevinVelocitiesBBK2_SOA().

255  {
256  // for now just call gaussian()
257  // ultimately we will provide faster implementation
258  for (int i=0; i < n; i++) {
259  a[i] = (float)gaussian();
260  }
261  }
BigReal gaussian(void)
Definition: Random.h:116

◆ gaussian_vector()

Vector Random::gaussian_vector ( void  )
inline

◆ init()

void Random::init ( unsigned long  seed)
inline

Definition at line 61 of file Random.h.

References RAND48_ADD, RAND48_MULT, RAND48_SEED, and UINT64_LITERAL.

Referenced by Random().

61  {
62  second_gaussian = 0;
63  second_gaussian_waiting = 0;
64  rand48_seed = seed & UINT64_LITERAL(0x00000000ffffffff);
65  rand48_seed = rand48_seed << 16;
66  rand48_seed |= RAND48_SEED & UINT64_LITERAL(0x0000ffff);
67  rand48_mult = RAND48_MULT;
68  rand48_add = RAND48_ADD;
69  }
#define RAND48_ADD
Definition: Random.h:34
#define RAND48_SEED
Definition: Random.h:32
#define RAND48_MULT
Definition: Random.h:33
#define UINT64_LITERAL(X)
Definition: Random.h:29

◆ integer()

long Random::integer ( void  )
inline

Definition at line 225 of file Random.h.

References skip(), and UINT64_LITERAL.

Referenced by reorder().

225  {
226  skip();
227  return ( ( rand48_seed >> 17 ) & UINT64_LITERAL(0x000000007fffffff) );
228  }
void skip(void)
Definition: Random.h:72
#define UINT64_LITERAL(X)
Definition: Random.h:29

◆ reorder()

template<class Elem >
void Random::reorder ( Elem *  a,
int  n 
)
inline

Definition at line 231 of file Random.h.

References integer().

Referenced by WorkDistrib::buildNodeAwarePeOrdering(), ComputePmeMgr::initialize(), ComputePmeMgr::initialize_pencils(), PmePencil< CBase_PmeZPencil >::order_init(), HomePatch::registerProxy(), and ParallelIOMgr::sendAtomsToHomePatchProcs().

231  {
232  for ( int i = 0; i < (n-1); ++i ) {
233  int ie = i + ( integer() % (n-i) );
234  if ( ie == i ) continue;
235  const Elem e = a[ie];
236  a[ie] = a[i];
237  a[i] = e;
238  }
239  }
long integer(void)
Definition: Random.h:225

◆ skip()

void Random::skip ( void  )
inline

Definition at line 72 of file Random.h.

References RAND48_MASK.

Referenced by integer(), split(), and uniform().

72  {
73  rand48_seed = ( rand48_seed * rand48_mult + rand48_add ) & RAND48_MASK;
74  }
#define RAND48_MASK
Definition: Random.h:35

◆ split()

void Random::split ( int  iStream,
int  numStreams 
)
inline

Definition at line 77 of file Random.h.

References skip().

Referenced by Controller::Controller(), Sequencer::Sequencer(), and Node::startup().

77  {
78 
79  int i;
80 
81  // make sure that numStreams is odd to ensure maximum period
82  numStreams |= 1;
83 
84  // iterate to get to the correct stream
85  for ( i = 0; i < iStream; ++i ) skip();
86 
87  // save seed and add so we can use skip() for our calculations
88  uint64_t save_seed = rand48_seed;
89 
90  // calculate c *= ( 1 + a + ... + a^(numStreams-1) )
91  rand48_seed = rand48_add;
92  for ( i = 1; i < numStreams; ++i ) skip();
93  uint64_t new_add = rand48_seed;
94 
95  // calculate a = a^numStreams
96  rand48_seed = rand48_mult;
97  rand48_add = 0;
98  for ( i = 1; i < numStreams; ++i ) skip();
99  rand48_mult = rand48_seed;
100 
101  rand48_add = new_add;
102  rand48_seed = save_seed;
103 
104  second_gaussian = 0;
105  second_gaussian_waiting = 0;
106  }
void skip(void)
Definition: Random.h:72

◆ sum_of_squared_gaussians()

BigReal Random::sum_of_squared_gaussians ( int64_t  num_gaussians)
inline

Return the sum of i.i.d. squared Gaussians.

The sum of k squared standard normal random variables is equivalent to drawing a value from a chi-squared distribution with the shape given as the number of Gaussians. That is,

X ~ sum_n=1^k N(0, 1)^2 ~ chi^2(k).

This is in turn a special case of the Gamma distribution with shape k/2 and scale 2 (we could also use rate = 1/scale)

X ~ chi^2(k) ~ Gamma(k/2, 2) ~ 2*Gamma(k/2, 1).

The second relation follows from the scaling property of the Gamma distribution. Furthermore, when a Gamma distribution has unit scale and a large shape, it can be well-approximated by a normal distribution with mean and variance equal to the shape. Thus,

X ~ 2*Gamma(k/2, 1) ~= 2*N(k/2, sqrt(k/2)).

A quick numerical test shows that the mean integrated square error for this approximation is <10^-5 for shape >30 and <10^-6 for shape >100. We'll be conservative and use the latter cutoff.

We thus have three cases for k Gaussians:

0 < k <= 2 - just brute force generate and sum the Gaussians 2 < k <= 200 - use a (slightly modified) version of the Gamma distribution algorithm from Marsaglia and Tsang that is implemented in the GNU Science Library (GSL) else - use a single Gaussian distribution

The brute force method is almost certainly the slowest method, even for k = 3. The rigorous method takes about 150% as long as the approximate method (but this is invariant to the value of k).

Parameters
num_gaussiansA positive integer number of Gaussians
Returns
a random variable equal to the sum of num_gaussians squared standard normal variables

Definition at line 189 of file Random.h.

References gaussian(), and uniform().

Referenced by Controller::stochRescaleCoefficient().

189  {
190  BigReal z, u, v;
191 
192  if (num_gaussians <= 2) {
193  v = 0.0;
194  for(int i=0; i<num_gaussians; ++i) {
195  z = gaussian();
196  v += z*z;
197  }
198  return v;
199  } else if (2 < num_gaussians && num_gaussians <= 200) {
200  const BigReal d = 0.5*num_gaussians - 1./3;
201  const BigReal c = 1. / (3*sqrt(d));
202  const BigReal zmin = -1. / c;
203  do {
204  do {
205  z = gaussian();
206  }
207  while(z <= zmin);
208  u = uniform();
209  v = (1 + c*z); v = v*v*v; // v = (1 + c*z)^3
210  }
211  while(log(u) >= (0.5*z*z + d*(1 - v + log(v))));
212  return 2*d*v;
213  } else {
214  return num_gaussians + sqrt(2*num_gaussians)*gaussian();
215  }
216  }
BigReal uniform(void)
Definition: Random.h:109
BigReal gaussian(void)
Definition: Random.h:116
double BigReal
Definition: common.h:123

◆ uniform()

BigReal Random::uniform ( void  )
inline

Definition at line 109 of file Random.h.

References skip(), and UINT64_LITERAL.

Referenced by Controller::adaptTempUpdate(), gaussian(), Controller::monteCarloPressure_accept(), Controller::monteCarloPressure_prepare(), sum_of_squared_gaussians(), and uniform_array_f().

109  {
110  skip();
111  const double exp48 = ( 1.0 / (double)(UINT64_LITERAL(1) << 48) );
112  return ( (double) rand48_seed * exp48 );
113  }
void skip(void)
Definition: Random.h:72
#define UINT64_LITERAL(X)
Definition: Random.h:29

◆ uniform_array_f()

void Random::uniform_array_f ( float *  a,
int  n 
)
inline

Fill length n array from uniform distribution.

Definition at line 244 of file Random.h.

References uniform().

244  {
245  // for now just call uniform()
246  // ultimately we will provide faster implementation
247  for (int i=0; i < n; i++) {
248  a[i] = (float)uniform();
249  }
250  }
BigReal uniform(void)
Definition: Random.h:109

The documentation for this class was generated from the following file: