00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "Random.h"
00014
00015 Random::Random()
00016 {
00017 #ifdef USESPRNG
00018 stream = 0;
00019 #endif
00020 }
00021
00022 Random::Random(long seed)
00023 {
00024 #ifdef USESPRNG
00025 stream = 0;
00026 #endif
00027 initialize(seed,0);
00028 }
00029
00030 Random::Random(const Random & rhs)
00031 {
00032 start = rhs.start;
00033 current = rhs.current;
00034
00035 #ifdef USESPRNG
00036
00037 stream = rhs.stream;
00038 #endif
00039
00040 iy = rhs.iy;
00041 for(int i=0; i<NTAB; i++)
00042 iv[i] = rhs.iv[i];
00043 }
00044
00045 Random::~Random()
00046 {
00047 #ifdef USESPRNG
00048 if(stream != 0)
00049 stream->free_sprng();
00050 #endif
00051 }
00052
00053 void Random::initialize(long seed, int rank)
00054 {
00055 if(seed == 0)
00056 {
00057 srand( time(NULL) );
00058 current = -rand();
00059 seed = intdev();
00060 reset();
00061
00062 clog << "Using iseed = -" << seed << endl;
00063 }
00064
00065 #ifdef USESPRNG
00066 int sprng_seed = (int)(seed);
00067
00068
00069 if(sprng_seed < 0)
00070 sprng_seed *= -1;
00071 start = (long)(sprng_seed);
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093 if(stream == 0)
00094 stream = SelectType(0);
00095
00096 int numStreams = 1;
00097
00098 #ifdef PARALLEL
00099 MPI_Comm_size(MPI_COMM_WORLD, &numStreams);
00100 #endif
00101
00102 clog << "Segment fault next line? Something is wrong with SPRNG\n";
00103 if(! stream->init_sprng(rank,numStreams,sprng_seed,SPRNG_DEFAULT) )
00104 {
00105 cerr << "Error: SPRNG initialization failed\n";
00106 exit(0);
00107 }
00108
00109 #else
00110
00111 if(seed > 0) seed *= -1;
00112 start = seed;
00113 current = seed;
00114
00115 int my_seed = current;
00116 for(int i=0; i<rank; i++)
00117 my_seed = intdev();
00118 current = -1*abs(my_seed);
00119 reset();
00120 #endif
00121 }
00122
00123 void Random::reset()
00124 {
00125 #ifdef USESPRNG
00126
00127 #else
00128
00129 iy = 0;
00130 for(int i=0; i<NTAB; i++)
00131 iv[i] = 0;
00132 #endif
00133 }
00134 void Random::printStream(ostream & strm)
00135 {
00136 strm << "Random stream info:" << endl;
00137 #ifdef USESPRNG
00138
00139 stream->print_sprng();
00140 #else
00141 strm << "current ran1 seed = " << current << endl;
00142 #endif
00143 }
00144
00145 void Random::writeXML(ostream & strm)
00146 {
00147 #ifdef USESPRNG
00148 char * buffer;
00149 int bytes_required = stream->pack_sprng(&buffer);
00150 strm << "<sprng>\n" << *buffer << "\n</sprng>" << endl;
00151 #else
00152
00153 strm << "<iseed>\n" << current << "\n</iseed>" << endl;
00154 strm << "<internal>\n";
00155 strm << iy << " ";
00156 for(int i=0; i<NTAB; i++)
00157 strm << iv[i] << " ";
00158 strm << "\n</internal>" << endl;
00159 #endif
00160 }
00161
00162 bool Random::readXML(istream & strm)
00163 {
00164 #ifdef USESPRNG
00165 clog << "readXML in Random.cpp needs to be debugged!\n";
00166 int size;
00167 strm >> size;
00168 char temp[size];
00169
00170 strm >> temp;
00171 if (temp != "<sprng>")
00172 return false;
00173 strm >> temp;
00174 if(! stream->unpack_sprng(temp) )
00175 {
00176 cerr << "Error: Unpacking SPRNG stream failed\n";
00177 exit(0);
00178 }
00179 strm >> temp;
00180 if (temp != "</sprng>")
00181 return false;
00182
00183 return true;
00184
00185 #else
00186
00187 string temp;
00188 strm >> temp;
00189 if (temp != "<iseed>")
00190 return false;
00191 strm >> temp;
00192 long iseed = atoi( temp.c_str() );
00193 current = iseed;
00194
00195 strm >> temp;
00196 if (temp != "</iseed>")
00197 return false;
00198
00199 strm >> temp;
00200 strm >> iy;
00201 for(int i=0; i<NTAB; i++)
00202 strm >> iv[i];
00203 strm >> temp;
00204 if(temp != "</internal>")
00205 return false;
00206
00207 return true;
00208
00209 #endif
00210 }
00211
00212 int Random::intdev()
00213 {
00214 #ifdef USESPRNG
00215 return stream->isprng();
00216 #else
00217 double temp = ran1(¤t);
00218 int val = (int)(INT_MAX*temp);
00219 return val;
00220 #endif
00221 }
00222 double Random::unidev()
00223 {
00224 #ifdef USESPRNG
00225 return stream->sprng();
00226 #else
00227 return ran1(¤t);
00228 #endif
00229 }
00230
00231 double Random::gasdev()
00232 {
00233 static int iset=0;
00234 static double gset;
00235 double fac,rsq,v1,v2;
00236
00237 if (current < 0) iset=0;
00238 if (iset == 0)
00239 {
00240 do
00241 {
00242 v1=2.0*unidev()-1.0;
00243 v2=2.0*unidev()-1.0;
00244 rsq=v1*v1+v2*v2;
00245 }
00246 while (rsq >= 1.0 || rsq == 0.0);
00247 fac=sqrt(-2.0*log(rsq)/rsq);
00248 gset=v1*fac;
00249 iset=1;
00250 return v2*fac;
00251 }
00252 else
00253 {
00254 iset=0;
00255 return gset;
00256 }
00257 }
00258
00259 double Random::expdev()
00260 {
00261 return -log(1.0-unidev());
00262 }
00263
00264 double Random::sindev()
00265 {
00266 return acos(1.0-2.0*unidev());
00267 }
00268
00269 double Random::sindev(double u)
00270 {
00271 double scale = 1.0;
00272 if(u < 3.14159265359 * 0.5)
00273 scale = sin(u);
00274
00275 while(true)
00276 {
00277 double x = u*unidev();
00278 if( unidev() < sin(x)/scale )
00279 return x;
00280 }
00281 }
00282
00283 double Random::randomDistribution1()
00284 {
00285 while(true)
00286 {
00287 double x = expdev()/0.4;
00288
00289 if( unidev() < ( 0.5*x*x*exp(-x) )/( 0.8*exp(-0.4*x) ) )
00290 {
00291 return x;
00292 }
00293 }
00294 }
00295
00296 double Random::pdf2(double a, double zeta, double x)
00297 {
00298 return fabs((1.0+a*x)*exp(-zeta * x) * sqrt(x));
00299 }
00300
00301 double Random::randomDistribution2(double a, double zeta, double l, double r)
00302 {
00303 #ifdef QMC_DEBUG
00304 if(l > r){
00305 cout << "Error: lower bound (" << l << ") is higher than upper bound (" << r << ")" << endl;
00306 }
00307 #endif
00308
00309 double scale = 1.0;
00310 if(fabs(a) < 1e-50)
00311 {
00312 double root1 = 0.5 / zeta;
00313 double vroot1 = pdf2(a, zeta, root1);
00314 scale = vroot1;
00315
00316
00317
00318
00319
00320 } else if(fabs(zeta) < 1e-50){
00321 double root1 = -1.0 / (3.0*a);
00322 double vroot1 = pdf2(a, zeta, root1);
00323 scale = vroot1;
00324
00325
00326
00327
00328
00329 } else {
00330 double root1 = (3.0*a - 2.0*zeta + sqrt(9.0*a*a - 4.0*a*zeta + 4.0*zeta*zeta))/(4.0*a*zeta);
00331 double root2 = (3.0*a - 2.0*zeta - sqrt(9.0*a*a - 4.0*a*zeta + 4.0*zeta*zeta))/(4.0*a*zeta);
00332 double vroot1 = pdf2(a, zeta, root1);
00333 double vroot2 = pdf2(a, zeta, root2);
00334 scale = max(vroot1,vroot2);
00335
00336
00337
00338
00339
00340 }
00341
00342 double vl = pdf2(a, zeta, l);
00343 double vr = pdf2(a, zeta, r);
00344 scale = max(scale,vl);
00345 scale = max(scale,vr);
00346
00347
00348
00349
00350
00351
00352 while(true)
00353 {
00354 double x = (r-l)*unidev() + l;
00355 if( unidev() < pdf2(a, zeta, x)/ scale )
00356 {
00357 return x;
00358 }
00359 }
00360 }
00361
00362 double Random::randomDistribution3(double F)
00363 {
00364
00365 #ifdef QMC_DEBUG
00366 if(F <= 0.0){
00367 cout << "Error: why is F = " << F << " negative?" << endl;
00368 }
00369 #endif
00370 double scale = 1.0 + F;
00371 while(true)
00372 {
00373 double x = 2.0*3.14159265359*unidev();
00374 if( unidev() < (1.0 + F*cos(x))/ scale )
00375 {
00376 return x;
00377 }
00378 }
00379 }
00380
00381
00382 #define IA 16807
00383 #define IM 2147483647
00384 #define AM (1.0/IM)
00385 #define IQ 127773
00386 #define IR 2836
00387 #define NDIV (1+(IM-1)/NTAB)
00388 #define EPS 1.2e-7
00389 #define RNMX (1.0-EPS)
00390
00391 double Random::ran1(long *idum)
00392 {
00393 int j;
00394 long k;
00395 double temp;
00396
00397 if (*idum <= 0 || !iy)
00398 {
00399 if (-(*idum) < 1) *idum=1;
00400 else *idum = -(*idum);
00401 for (j=NTAB+7;j>=0;j--)
00402 {
00403 k=(*idum)/IQ;
00404 *idum=IA*(*idum-k*IQ)-IR*k;
00405 if (*idum < 0) *idum += IM;
00406 if (j < NTAB) iv[j] = *idum;
00407 }
00408 iy=iv[0];
00409 }
00410 k=(*idum)/IQ;
00411 *idum=IA*(*idum-k*IQ)-IR*k;
00412 if (*idum < 0) *idum += IM;
00413 j=iy/NDIV;
00414 iy=iv[j];
00415 iv[j] = *idum;
00416 if ((temp=AM*iy) > RNMX) return RNMX;
00417 else return temp;
00418 }
00419 #undef IA
00420 #undef IM
00421 #undef AM
00422 #undef IQ
00423 #undef IR
00424 #undef NTAB
00425 #undef NDIV
00426 #undef EPS
00427 #undef RNMX
00428
00429