LevelS C++ support library  3.82
planck_rng.h
Go to the documentation of this file.
1 /*
2  * This file is part of libcxxsupport.
3  *
4  * libcxxsupport is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * libcxxsupport is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with libcxxsupport; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 /*
20  * libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
21  * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
22  * (DLR).
23  */
24 
25 /*! \file planck_rng.h
26  * This file contains the random number generator
27  * used by the Planck LevelS package.
28  * The generator is a C++ port of the xorshift generator xor128() described
29  * in Marsaglia, Journal of Statistical Software 2003, vol 8.
30  * It has a period of 2^128 - 1.
31  *
32  * Copyright (C) 2003, 2004, 2005 Max-Planck-Society
33  * \author Martin Reinecke
34  */
35 
36 #ifndef PLANCK_RNG_H
37 #define PLANCK_RNG_H
38 
39 #include <cmath>
40 #include "error_handling.h"
41 
42 /*! C++ port of the xorshift generator xor128() described in Marsaglia,
43  Journal of Statistical Software 2003, vol 8.
44  It has a period of 2^128 - 1. */
46  {
47  private:
48  unsigned int x,y,z,w;
49  double small, gset;
50  bool empty;
51 
52  void twiddle (unsigned int &v)
53  {
54  for (int i=0; i<9; ++i)
55  {
56  v ^= v<<13;
57  v ^= v>>17;
58  v ^= v<<5;
59  }
60  }
61 
62  void init_rng ()
63  {
64  // avoid zero seeds
65  if (x==0) x = 123456789;
66  if (y==0) y = 362436069;
67  if (z==0) z = 521288629;
68  if (w==0) w = 88675123;
69 
70  // shuffle the bits of the seeds
71  twiddle(x); twiddle(y); twiddle(z); twiddle(w);
72 
73  // burn in the RNG
74  for (int i=0; i<16; ++i)
75  int_rand_uni();
76  }
77 
78  public:
79  /*! Initializes the generator with 0 to 4 seed values. */
80  planck_rng (unsigned int x1=123456789, unsigned int y1=362436069,
81  unsigned int z1=521288629, unsigned int w1=88675123)
82  : x(x1), y(y1), z(z1), w(w1),
83  small(1./(1.+double(0xFFFFFFFF))), gset(0.), empty(true)
84  {
85  planck_assert (sizeof(unsigned int)==4, "wrong integer size for RNG");
86  init_rng();
87  }
88 
89  /*! Re-initializes the generator with 0 to 4 seed values. */
90  void seed (unsigned int x1=123456789, unsigned int y1=362436069,
91  unsigned int z1=521288629, unsigned int w1=88675123)
92  {
93  x = x1; y = y1; z = z1; w = w1;
94  empty = true;
95  init_rng();
96  }
97 
98  /*! Returns uniformly distributed random integer numbers from the
99  interval [0;0xFFFFFFFF]. */
100  unsigned int int_rand_uni()
101  {
102  unsigned int t = x^(x<<11);
103  x = y;
104  y = z;
105  z = w;
106 
107  return w=(w^(w>>19))^(t^(t>>8));
108  }
109 
110  //! Returns uniformly distributed random numbers from the interval [0;1[.
111  double rand_uni()
112  {
113  return small*int_rand_uni();
114  }
115 
116  //! Returns random numbers with Gaussian distribution (mean=0, sigma=1).
117  /*! Uses rand_uni() internally. */
118  double rand_gauss()
119  {
120  using namespace std;
121  if (empty)
122  {
123  double v1,v2,rsq;
124  do
125  {
126  v1=2*rand_uni()-1.;
127  v2=2*rand_uni()-1.;
128  rsq=v1*v1+v2*v2;
129  }
130  while ((rsq>=1) || (rsq==0));
131  double fac=sqrt(-2*log(rsq)/rsq);
132  gset=v1*fac;
133  empty=false;
134  return v2*fac;
135  }
136  else
137  {
138  empty=true;
139  return gset;
140  }
141  }
142 
143  //! Returns exponentially distributed random numbers (mean=1, nonnegative)
144  /*! Uses rand_uni() internally. */
145  double rand_exp()
146  {
147  using namespace std;
148  double val=rand_uni();
149  if (val==0.) val=1.;
150  return -log(val);
151  }
152  };
153 
154 #endif
double rand_gauss()
Returns random numbers with Gaussian distribution (mean=0, sigma=1).
Definition: planck_rng.h:118
unsigned int int_rand_uni()
Definition: planck_rng.h:100
void seed(unsigned int x1=123456789, unsigned int y1=362436069, unsigned int z1=521288629, unsigned int w1=88675123)
Definition: planck_rng.h:90
double rand_uni()
Returns uniformly distributed random numbers from the interval [0;1[.
Definition: planck_rng.h:111
#define planck_assert(testval, msg)
double rand_exp()
Returns exponentially distributed random numbers (mean=1, nonnegative)
Definition: planck_rng.h:145
planck_rng(unsigned int x1=123456789, unsigned int y1=362436069, unsigned int z1=521288629, unsigned int w1=88675123)
Definition: planck_rng.h:80

Generated on Thu Jul 28 2022 17:32:06 for LevelS C++ support library