Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

random.cpp

Go to the documentation of this file.
00001 /* -------------------------------------------------------------------------
00002  * This is an ANSI C library for multi-stream random number generation.  
00003  * The use of this library is recommended as a replacement for the ANSI C 
00004  * rand() and srand() functions, particularly in simulation applications 
00005  * where the statistical 'goodness' of the random number generator is 
00006  * important.  The library supplies 256 streams of random numbers; use 
00007  * SelectStream(s) to switch between streams indexed s = 0,1,...,255.
00008  *
00009  * The streams must be initialized.  The recommended way to do this is by
00010  * using the function PlantSeeds(x) with the value of x used to initialize 
00011  * the default stream and all other streams initialized automatically with
00012  * values dependent on the value of x.  The following convention is used 
00013  * to initialize the default stream:
00014  *    if x > 0 then x is the state
00015  *    if x < 0 then the state is obtained from the system clock
00016  *    if x = 0 then the state is to be supplied interactively.
00017  *
00018  * The generator used in this library is a so-called 'Lehmer random number
00019  * generator' which returns a pseudo-random number uniformly distributed
00020  * 0.0 and 1.0.  The period is (m - 1) where m = 2,147,483,647 and the
00021  * smallest and largest possible values are (1 / m) and 1 - (1 / m)
00022  * respectively.  For more details see:
00023  * 
00024  *       "Random Number Generators: Good Ones Are Hard To Find"
00025  *                   Steve Park and Keith Miller
00026  *              Communications of the ACM, October 1988
00027  *
00028  * Name            : rngs.c  (Random Number Generation - Multiple Streams)
00029  * Authors         : Steve Park & Dave Geyer
00030  * Language        : ANSI C
00031  * Latest Revision : 09-22-98
00032  * ------------------------------------------------------------------------- 
00033  */
00034 
00035 #include <stdio.h>
00036 #include <time.h>
00037 
00038 #define __RANDOM_CPP
00039 #include "random.h"
00040 
00041 #define MODULUS    2147483647 /* DON'T CHANGE THIS VALUE                  */
00042 #define MULTIPLIER 48271      /* DON'T CHANGE THIS VALUE                  */
00043 #define CHECK      399268537  /* DON'T CHANGE THIS VALUE                  */
00044 #define STREAMS    256        /* # of streams, DON'T CHANGE THIS VALUE    */
00045 #define A256       22925      /* jump multiplier, DON'T CHANGE THIS VALUE */
00046 #define DEFAULT    123456789  /* initial seed, use 0 < DEFAULT < MODULUS  */
00047       
00048 static long seed[STREAMS] = {DEFAULT};  /* current state of each stream   */
00049 static int  stream        = 0;          /* stream index, 0 is the default */
00050 static int  initialized   = 0;          /* test for stream initialization */
00051 
00052 
00053    double Random(void)
00054 /* ----------------------------------------------------------------
00055  * Random returns a pseudo-random real number uniformly distributed 
00056  * between 0.0 and 1.0. 
00057  * ----------------------------------------------------------------
00058  */
00059 {
00060   const long Q = MODULUS / MULTIPLIER;
00061   const long R = MODULUS % MULTIPLIER;
00062         long t;
00063 
00064   t = MULTIPLIER * (seed[stream] % Q) - R * (seed[stream] / Q);
00065   if (t > 0) 
00066     seed[stream] = t;
00067   else 
00068     seed[stream] = t + MODULUS;
00069   return ((double) seed[stream] / MODULUS);
00070 }
00071 
00072 
00073    void PlantSeeds(long x)
00074 /* ---------------------------------------------------------------------
00075  * Use this function to set the state of all the random number generator 
00076  * streams by "planting" a sequence of states (seeds), one per stream, 
00077  * with all states dictated by the state of the default stream. 
00078  * The sequence of planted states is separated one from the next by 
00079  * 8,367,782 calls to Random().
00080  * ---------------------------------------------------------------------
00081  */
00082 {
00083   const long Q = MODULUS / A256;
00084   const long R = MODULUS % A256;
00085         int  j;
00086         int  s;
00087 
00088   initialized = 1;
00089   s = stream;                            /* remember the current stream */
00090   SelectStream(0);                       /* change to stream 0          */
00091   PutSeed(x);                            /* set seed[0]                 */
00092   stream = s;                            /* reset the current stream    */
00093   for (j = 1; j < STREAMS; j++) {
00094     x = A256 * (seed[j - 1] % Q) - R * (seed[j - 1] / Q);
00095     if (x > 0)
00096       seed[j] = x;
00097     else
00098       seed[j] = x + MODULUS;
00099    }
00100 }
00101 
00102 
00103 int nextInteger( int range,const char *file, int line )
00104 {
00105     int val = (int)(Random( ) * range);
00106 //      printf( "nextInt() called from %s line %d - returning %d\n", file, line, val );
00107 
00108     return val;
00109     
00110 }
00111    void PutSeed(long x)
00112 /* ---------------------------------------------------------------
00113  * Use this function to set the state of the current random number 
00114  * generator stream according to the following conventions:
00115  *    if x > 0 then x is the state (unless too large)
00116  *    if x < 0 then the state is obtained from the system clock
00117  *    if x = 0 then the state is to be supplied interactively
00118  * ---------------------------------------------------------------
00119  */
00120 {
00121   char ok = 0;
00122 
00123   if (x > 0)
00124     x = x % MODULUS;                       /* correct if x is too large  */
00125   if (x < 0)                                 
00126     x = ((unsigned long) time((time_t *) NULL)) % MODULUS;              
00127   if (x == 0)                                
00128     while (!ok) {
00129       printf("\nEnter a positive integer seed (9 digits or less) >> ");
00130       scanf("%ld", &x);
00131       ok = (0 < x) && (x < MODULUS);
00132       if (!ok)
00133         printf("\nInput out of range ... try again\n");
00134     }
00135   seed[stream] = x;
00136 }
00137 
00138 
00139    void GetSeed(long *x)
00140 /* ---------------------------------------------------------------
00141  * Use this function to get the state of the current random number 
00142  * generator stream.                                                   
00143  * ---------------------------------------------------------------
00144  */
00145 {
00146   *x = seed[stream];
00147 }
00148 
00149 
00150    void SelectStream(int index)
00151 /* ------------------------------------------------------------------
00152  * Use this function to set the current random number generator
00153  * stream -- that stream from which the next random number will come.
00154  * ------------------------------------------------------------------
00155  */
00156 {
00157   stream = ((unsigned int) index) % STREAMS;
00158   if ((initialized == 0) && (stream != 0))   /* protect against        */
00159     PlantSeeds(DEFAULT);                     /* un-initialized streams */
00160 }
00161 
00162 
00163    void TestRandom(void)
00164 /* ------------------------------------------------------------------
00165  * Use this (optional) function to test for a correct implementation.
00166  * ------------------------------------------------------------------    
00167  */
00168 {
00169   long   i;
00170   long   x;
00171   double u;
00172   char   ok = 0;  
00173 
00174   SelectStream(0);                  /* select the default stream */
00175   PutSeed(1);                       /* and set the state to 1    */
00176   for(i = 0; i < 10000; i++)
00177     u = Random();
00178   GetSeed(&x);                      /* get the new state value   */
00179   ok = (x == CHECK);                /* and check for correctness */
00180 
00181   SelectStream(1);                  /* select stream 1                 */ 
00182   PlantSeeds(1);                    /* set the state of all streams    */
00183   GetSeed(&x);                      /* get the state of stream 1       */
00184   ok = ok && (x == A256);           /* x should be the jump multiplier */    
00185   if (ok)
00186     printf("\n The implementation of rngs.c is correct.\n\n");
00187   else
00188     printf("\n\a ERROR -- the implementation of rngs.c is not correct.\n\n");
00189 }

Generated on Sat Nov 5 16:17:25 2005 for OPIE by  doxygen 1.4.2