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 #include "random.h"
00038 
00039 #define MODULUS    2147483647 /* DON'T CHANGE THIS VALUE                  */
00040 #define MULTIPLIER 48271      /* DON'T CHANGE THIS VALUE                  */
00041 #define CHECK      399268537  /* DON'T CHANGE THIS VALUE                  */
00042 #define STREAMS    256        /* # of streams, DON'T CHANGE THIS VALUE    */
00043 #define A256       22925      /* jump multiplier, DON'T CHANGE THIS VALUE */
00044 #define DEFAULT    123456789  /* initial seed, use 0 < DEFAULT < MODULUS  */
00045       
00046 static long seed[STREAMS] = {DEFAULT};  /* current state of each stream   */
00047 static int  stream        = 0;          /* stream index, 0 is the default */
00048 static int  initialized   = 0;          /* test for stream initialization */
00049 
00050 
00051    double Random(void)
00052 /* ----------------------------------------------------------------
00053  * Random returns a pseudo-random real number uniformly distributed 
00054  * between 0.0 and 1.0. 
00055  * ----------------------------------------------------------------
00056  */
00057 {
00058   const long Q = MODULUS / MULTIPLIER;
00059   const long R = MODULUS % MULTIPLIER;
00060         long t;
00061 
00062   t = MULTIPLIER * (seed[stream] % Q) - R * (seed[stream] / Q);
00063   if (t > 0) 
00064     seed[stream] = t;
00065   else 
00066     seed[stream] = t + MODULUS;
00067   return ((double) seed[stream] / MODULUS);
00068 }
00069 
00070 
00071    void PlantSeeds(long x)
00072 /* ---------------------------------------------------------------------
00073  * Use this function to set the state of all the random number generator 
00074  * streams by "planting" a sequence of states (seeds), one per stream, 
00075  * with all states dictated by the state of the default stream. 
00076  * The sequence of planted states is separated one from the next by 
00077  * 8,367,782 calls to Random().
00078  * ---------------------------------------------------------------------
00079  */
00080 {
00081   const long Q = MODULUS / A256;
00082   const long R = MODULUS % A256;
00083         int  j;
00084         int  s;
00085 
00086   initialized = 1;
00087   s = stream;                            /* remember the current stream */
00088   SelectStream(0);                       /* change to stream 0          */
00089   PutSeed(x);                            /* set seed[0]                 */
00090   stream = s;                            /* reset the current stream    */
00091   for (j = 1; j < STREAMS; j++) {
00092     x = A256 * (seed[j - 1] % Q) - R * (seed[j - 1] / Q);
00093     if (x > 0)
00094       seed[j] = x;
00095     else
00096       seed[j] = x + MODULUS;
00097    }
00098 }
00099 
00100 
00101    void PutSeed(long x)
00102 /* ---------------------------------------------------------------
00103  * Use this function to set the state of the current random number 
00104  * generator stream according to the following conventions:
00105  *    if x > 0 then x is the state (unless too large)
00106  *    if x < 0 then the state is obtained from the system clock
00107  *    if x = 0 then the state is to be supplied interactively
00108  * ---------------------------------------------------------------
00109  */
00110 {
00111   char ok = 0;
00112 
00113   if (x > 0)
00114     x = x % MODULUS;                       /* correct if x is too large  */
00115   if (x < 0)                                 
00116     x = ((unsigned long) time((time_t *) NULL)) % MODULUS;              
00117   if (x == 0)                                
00118     while (!ok) {
00119       printf("\nEnter a positive integer seed (9 digits or less) >> ");
00120       scanf("%ld", &x);
00121       ok = (0 < x) && (x < MODULUS);
00122       if (!ok)
00123         printf("\nInput out of range ... try again\n");
00124     }
00125   seed[stream] = x;
00126 }
00127 
00128 
00129    void GetSeed(long *x)
00130 /* ---------------------------------------------------------------
00131  * Use this function to get the state of the current random number 
00132  * generator stream.                                                   
00133  * ---------------------------------------------------------------
00134  */
00135 {
00136   *x = seed[stream];
00137 }
00138 
00139 
00140    void SelectStream(int index)
00141 /* ------------------------------------------------------------------
00142  * Use this function to set the current random number generator
00143  * stream -- that stream from which the next random number will come.
00144  * ------------------------------------------------------------------
00145  */
00146 {
00147   stream = ((unsigned int) index) % STREAMS;
00148   if ((initialized == 0) && (stream != 0))   /* protect against        */
00149     PlantSeeds(DEFAULT);                     /* un-initialized streams */
00150 }
00151 
00152 
00153    void TestRandom(void)
00154 /* ------------------------------------------------------------------
00155  * Use this (optional) function to test for a correct implementation.
00156  * ------------------------------------------------------------------    
00157  */
00158 {
00159   long   i;
00160   long   x;
00161   double u;
00162   char   ok = 0;  
00163 
00164   SelectStream(0);                  /* select the default stream */
00165   PutSeed(1);                       /* and set the state to 1    */
00166   for(i = 0; i < 10000; i++)
00167     u = Random();
00168   GetSeed(&x);                      /* get the new state value   */
00169   ok = (x == CHECK);                /* and check for correctness */
00170 
00171   SelectStream(1);                  /* select stream 1                 */ 
00172   PlantSeeds(1);                    /* set the state of all streams    */
00173   GetSeed(&x);                      /* get the state of stream 1       */
00174   ok = ok && (x == A256);           /* x should be the jump multiplier */    
00175   if (ok)
00176     printf("\n The implementation of rngs.c is correct.\n\n");
00177   else
00178     printf("\n\a ERROR -- the implementation of rngs.c is not correct.\n\n");
00179 }

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