planck_rng.h
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #ifndef PLANCK_RNG_H
00037 #define PLANCK_RNG_H
00038
00039 #include <cmath>
00040 #include "error_handling.h"
00041
00042
00043
00044
00045 class planck_rng
00046 {
00047 private:
00048 unsigned int x,y,z,w;
00049 double small, gset;
00050 bool empty;
00051
00052 void twiddle (unsigned int &v)
00053 {
00054 for (int i=0; i<9; ++i)
00055 {
00056 v ^= v<<13;
00057 v ^= v>>17;
00058 v ^= v<<5;
00059 }
00060 }
00061
00062 void init_rng ()
00063 {
00064
00065 if (x==0) x = 123456789;
00066 if (y==0) y = 362436069;
00067 if (z==0) z = 521288629;
00068 if (w==0) w = 88675123;
00069
00070
00071 twiddle(x); twiddle(y); twiddle(z); twiddle(w);
00072
00073
00074 for (int i=0; i<16; ++i)
00075 int_rand_uni();
00076 }
00077
00078 public:
00079
00080 planck_rng (unsigned int x1=123456789, unsigned int y1=362436069,
00081 unsigned int z1=521288629, unsigned int w1=88675123)
00082 : x(x1), y(y1), z(z1), w(w1),
00083 small(1./(1.+double(0xFFFFFFFF))), gset(0.), empty(true)
00084 {
00085 planck_assert (sizeof(unsigned int)==4, "wrong integer size for RNG");
00086 init_rng();
00087 }
00088
00089
00090 void seed (unsigned int x1=123456789, unsigned int y1=362436069,
00091 unsigned int z1=521288629, unsigned int w1=88675123)
00092 {
00093 x = x1; y = y1; z = z1; w = w1;
00094 empty = true;
00095 init_rng();
00096 }
00097
00098
00099
00100 unsigned int int_rand_uni()
00101 {
00102 unsigned int t = x^(x<<11);
00103 x = y;
00104 y = z;
00105 z = w;
00106
00107 return w=(w^(w>>19))^(t^(t>>8));
00108 }
00109
00110
00111 double rand_uni()
00112 {
00113 return small*int_rand_uni();
00114 }
00115
00116
00117
00118 double rand_gauss()
00119 {
00120 using namespace std;
00121 if (empty)
00122 {
00123 double v1,v2,rsq;
00124 do
00125 {
00126 v1=2*rand_uni()-1.;
00127 v2=2*rand_uni()-1.;
00128 rsq=v1*v1+v2*v2;
00129 }
00130 while ((rsq>=1) || (rsq==0));
00131 double fac=sqrt(-2*log(rsq)/rsq);
00132 gset=v1*fac;
00133 empty=false;
00134 return v2*fac;
00135 }
00136 else
00137 {
00138 empty=true;
00139 return gset;
00140 }
00141 }
00142
00143
00144
00145 double rand_exp()
00146 {
00147 using namespace std;
00148 double val=rand_uni();
00149 if (val==0.) val=1.;
00150 return -log(val);
00151 }
00152 };
00153
00154 #endif