Main Page   Class Hierarchy   Data Structures   File List   Data Fields   Globals  

randinter.C

Go to the documentation of this file.
00001 
00002 //  randinter.C: generates "random" numbers within an interval [a,b]
00003 //.............................................................................
00004 //    version 1:  May 1989   Piet Hut               email: piet@iassns.bitnet
00005 //                           Institute for Advanced Study, Princeton, NJ, USA
00006 //    version 2:  Dec 1992   Piet Hut  --  adopted to the new C++-based starlab
00007 //    version 3:  Mar 1994   Steve McMillan, adapted Numerical Recipes routines
00008 //.............................................................................
00009 //  non-local functions: 
00010 //    randinter, srandinter
00011 //.............................................................................
00012 //
00013 //     The results are reproducible if a seed > 0 is specified to start up the
00014 //  random number generator. Note that the generator can be started up with a
00015 //  seed = 0, which is converted to a "random" seed (taken from the clock,
00016 //  expressed in seconds).
00017 //     The "randunit" version is copied after UNIX calls to  rand() , which
00018 //  are unfortunately not very random. An improved version should be used for
00019 //  serious applications.
00020 //     The ran0, ran1 and ran2 routines are said to be better. In particular,
00021 // ran2 is claimed to be "perfect"!
00022 //
00023 //     Note that ran1 and ran2 maintain a table of numbers in order to deal
00024 //  with sequential correntations in their output. This makes it more difficult
00025 //  to reproduce random numbers at an arbitrary point within the sequence,
00026 //  so we must maintain some history information about calls to randinter.
00027 //
00028 //.............................................................................
00029 //     Compiled with cc -DTOOLBOX , randinter # will model # throws of dice.
00030 //.............................................................................
00031 
00032 
00039 
00040 
00041 #include <time.h>
00042 #include "stdinc.h"
00043 
00044 #ifndef TOOLBOX
00045 
00046 //------------------------------------------------------------------------
00047 //
00048 // Initialization:
00049 // --------------
00050 
00051 // The internal random seed:
00052 
00053 static int randx = 0;
00054 
00055 // The initial seed used to start the current sequence:
00056 
00057 static int initial_seed = 0;
00058 
00059 // The number of times the current sequence has been called:
00060 
00061 static int n_rand = 0;
00062 
00063 // srandinter:  Accept a seed to start up randunit.
00064 //              note:
00065 //                  if seed = 0, then a positive number is chosen, which
00066 //                  is unique if no other call to srandinter is made within
00067 //                  2.0 seconds of the current call (the UNIX clock is used,
00068 //                  which returns the time in seconds).
00069 //                  The return value is the actual value of the seed (either
00070 //                  the specified non-zero value, or the clock time).
00071 
00072 int  srandinter(int seed, int iter) {
00073 
00074     if (seed == 0)               // no particular positive seed provided?
00075         seed = (int) time(NULL); // then give a random value,
00076                                  // different every second.
00077 
00078     initial_seed = abs(seed);
00079     n_rand = 0;
00080 
00081     randx = -initial_seed;       // randx < 0 ==> initialize ran1 or ran2
00082 
00083     for (int i = 0; i < iter; i++) randinter(0,1);
00084 
00085     return initial_seed;   // to enable the user to verify the actual value of
00086                            // the initialization for randx.
00087 }
00088 
00089 // get_initial_seed:  Return the initial seed for the current sequence
00090 
00091 int get_initial_seed() {
00092 
00093     return initial_seed;
00094 }
00095 
00096 // get_rand_seed:  Return the current value of the random seed
00097 
00098 int get_rand_seed() {
00099 
00100     return abs(randx);
00101 }
00102 
00103 // get_current_seed:  Lookalike for get_rand_seed
00104 
00105 int get_current_seed() {
00106 
00107     return abs(randx);
00108 }
00109 
00110 // get_n_rand:  Return the number of invocations of the current sequence
00111 
00112 int get_n_rand() {
00113 
00114     return n_rand;
00115 }
00116 
00117 //------------------------------------------------------------------------
00118 // Random number generators:
00119 // ------------------------
00120 
00121 // randunit:  Return a random real number within the unit interval
00122 //                note: based on      @(#)rand.c   4.1 (Berkeley) 12/21/80,
00123 //                      but returning a positive number smaller than unity.
00124 
00125 #define  MAXNUM 2147483647.0    // the maximum value which rand() can return
00126 
00127 real  randunit() {
00128 
00129     if (randx < 0) randx *= -1; // for compatibility with ran1, ran2
00130     randx &= 0x7fffffff;        // to mimic 32-bit int on a Cray
00131 
00132     return (real)((randx = randx * 1103515245 + 12345) & 0x7fffffff)/MAXNUM;
00133 }
00134 
00135 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00136 
00137 // nr_rand: Three congruential random-number generators from Numerical Recipes.
00138 //          Converted to C++ and 64-bit real precision by Steve McMillan
00139 
00140 // Each routine takes a int random seed and returns a random number
00141 // uniformly distributed between 0 and 1. The seed is modified on return,
00142 // ready for the next call.
00143 
00144 // Note: This package uses "int" to mean "long int". Starlab users on 16-bit
00145 //       machines beware!!
00146 
00147 #define IA 16807
00148 #define IM 2147483647
00149 #define AM (1.0/IM)
00150 #define IQ 127773
00151 #define IR 2836
00152 #define MASK 123459876
00153 
00154 real ran0(int& idum)
00155 {
00156     int k;
00157     real ans;
00158 
00159     if (idum < 0) idum *= -1;   // for compatibility with ran1, ran2
00160     
00161     idum ^= MASK;
00162     k = (idum)/IQ;
00163     idum = IA*(idum-k*IQ) - IR*k;
00164     if (idum < 0) idum += IM;
00165     ans = AM*(idum);
00166     idum ^= MASK;
00167     
00168     return ans;
00169 }
00170 
00171 #undef IA
00172 #undef IM
00173 #undef AM
00174 #undef IQ
00175 #undef IR
00176 #undef MASK
00177 
00178 #define IA 16807
00179 #define IM 2147483647
00180 #define AM (1.0/IM)
00181 #define IQ 127773
00182 #define IR 2836
00183 #define NTAB 32
00184 #define NDIV (1+(IM-1)/NTAB)
00185 #define EPS 1.e-14
00186 #define RNMX (1.0-EPS)
00187 
00188 real ran1(int& idum)
00189 {
00190     int j;
00191     int k;
00192     static int iy = 0;
00193     static int iv[NTAB];
00194     real temp;
00195 
00196     if (idum <= 0 || !iy) {     // idum < 0 ==> initialize
00197         if (-(idum) < 1)
00198             idum = 1;
00199         else
00200             idum = -(idum);
00201         for (j = NTAB+7; j >= 0; j--) {
00202             k = (idum)/IQ;
00203             idum = IA*(idum-k*IQ) - IR*k;
00204             if (idum < 0) idum += IM;
00205             if (j < NTAB) iv[j] = idum;
00206         }
00207         iy = iv[0];
00208     }
00209     
00210     k = (idum)/IQ;
00211     idum = IA*(idum-k*IQ) - IR*k;
00212     if (idum < 0) idum += IM;
00213 
00214     j = iy/NDIV;
00215     iy = iv[j];
00216     iv[j] = idum;
00217     
00218     if ((temp = AM*iy) > RNMX)
00219         return RNMX;
00220     else
00221         return temp;
00222 }
00223 
00224 #undef IA
00225 #undef IM
00226 #undef AM
00227 #undef IQ
00228 #undef IR
00229 #undef NTAB
00230 #undef NDIV
00231 #undef EPS
00232 #undef RNMX
00233 
00234 #define IM1 2147483563
00235 #define IM2 2147483399
00236 #define AM (1.0/IM1)
00237 #define IMM1 (IM1-1)
00238 #define IA1 40014
00239 #define IA2 40692
00240 #define IQ1 53668
00241 #define IQ2 52774
00242 #define IR1 12211
00243 #define IR2 3791
00244 #define NTAB 32
00245 #define NDIV (1+IMM1/NTAB)
00246 #define EPS 1.e-14
00247 #define RNMX (1.0-EPS)
00248 
00249 real ran2(int& idum)
00250 {
00251     int j;
00252     int k;
00253     static int idum2 = 123456789;
00254     static int iy = 0;
00255     static int iv[NTAB];
00256     real temp;
00257 
00258     if (idum <= 0) {            // idum < 0 ==> initialize
00259         if (-(idum) < 1)
00260             idum = 1;
00261         else
00262             idum = -(idum);
00263         idum2 = (idum);
00264 
00265         for (j = NTAB+7; j >= 0; j--) {
00266             k = (idum)/IQ1;
00267             idum = IA1*(idum-k*IQ1) - k*IR1;
00268             if (idum < 0) idum += IM1;
00269             if (j < NTAB) iv[j] = idum;
00270         }
00271         iy = iv[0];
00272     }
00273     k = (idum)/IQ1;
00274     idum = IA1*(idum-k*IQ1) - k*IR1;
00275     if (idum < 0) idum += IM1;
00276 
00277     k = idum2/IQ2;
00278     idum2 = IA2*(idum2-k*IQ2)-k*IR2;
00279     if (idum2 < 0) idum2 += IM2;
00280 
00281     j = iy/NDIV;
00282     iy = iv[j] - idum2;
00283     iv[j] = idum;
00284     if (iy < 1) iy += IMM1;
00285 
00286     if ((temp = AM*iy) > RNMX)
00287         return RNMX;
00288     else
00289         return temp;
00290 }
00291 
00292 #undef IM1
00293 #undef IM2
00294 #undef AM
00295 #undef IMM1
00296 #undef IA1
00297 #undef IA2
00298 #undef IQ1
00299 #undef IQ2
00300 #undef IR1
00301 #undef IR2
00302 #undef NTAB
00303 #undef NDIV
00304 #undef EPS
00305 #undef RNMX
00306 
00307 //------------------------------------------------------------------------
00308 
00309 // randinter:  Return a random real number within an interval [a,b]
00310 //             by invoking a standard random number generator.
00311 
00312 real randinter(real a, real b) {
00313 
00314     n_rand++;
00315 
00316 //  Old Starlab:
00317 //
00318 //    return a + (b-a)*randunit();
00319 
00320 //  New Starlab:
00321 //
00322     return a + (b-a)*ran2(randx);
00323 
00324 }
00325 
00326 // gausrand: Return a random number distributed according to a Gaussian
00327 //           distribution with specified mean and standard deviation.
00328 
00329 #define BIG 10
00330 
00331 real gausrand(real mean, real sdev)
00332 {
00333     // Select a number with zero mean and unit variance using the
00334     // rejection method (see Numerical Recipes).
00335 
00336     for(;;) {
00337         real x = randinter(-BIG, BIG);
00338         if (randinter(0,1) < exp(-0.5*x*x)) return mean + x*sdev;
00339     }
00340 }
00341 
00342 //------------------------------------------------------------------------
00343 
00344 #else
00345 
00346 // main:  Driver to test  randinter() . It also emulates N throws of dice,
00347 //        when given the command  "randinter N" . If no second argument
00348 //        is given, a random seed is used; otherwise the second argument
00349 //        is used as the seed for the random number generator.
00350 
00351 main(int argc, char **argv) {
00352 
00353     check_help();
00354     if (argc < 2)
00355         err_exit("randinter N [S] (for N throws of dice, from seed S)");
00356 
00357     int seed;
00358     if (argc == 2)
00359         seed = srandinter(0);                   // "random" seed
00360     else
00361         seed = srandinter(atoi(argv[2]));
00362 
00363     cout.precision(8);
00364     int i;
00365     for (i = 1; i <= atoi(argv[1]); i++) {
00366         real x = randinter(0,1);
00367         cout << randinter(0, 1) << " ";
00368         if (i%5 == 0) cout << endl;
00369     }
00370     if ((i-1)%5 != 0) cout << endl;
00371 }
00372 #endif

Generated at Sun Feb 24 09:57:12 2002 for STARLAB by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001