/* ------------------------------------------------------------------------- * This is an ANSI C library for random number generation. The use of this * library is recommended as a replacement for the ANSI C rand() and srand() * functions, particularly in simulation applications where the statistical * 'goodness' of the random number generator is important. * * The generator used in this library is a so-called 'Lehmer random number * generator' which returns a pseudo-random number uniformly distributed * 0.0 and 1.0. The period is (m - 1) where m = 2,147,483,647 and the * smallest and largest possible values are (1 / m) and 1 - (1 / m) * respectively. For more details see: * * "Random Number Generators: Good Ones Are Hard To Find" * Steve Park and Keith Miller * Communications of the ACM, October 1988 * * Note that as of 7-11-90 the multiplier used in this library has changed * from the previous "minimal standard" 16807 to a new value of 48271. To * use this library in its old (16807) form change the constants MULTIPLIER * and CHECK as indicated in the comments. * * Name : rng.c (Random Number Generation - Single Stream) * Authors : Steve Park & Dave Geyer * Language : ANSI C * Latest Revision : 09-11-98 * ------------------------------------------------------------------------- */ #include #include #include "rng.h" #define MODULUS 2147483647L /* DON'T CHANGE THIS VALUE */ #define MULTIPLIER 48271L /* use 16807 for the "minimal standard" */ #define CHECK 399268537L /* use 1043616065 for the "minimal standard" */ #define DEFAULT 123456789L /* initial seed, use 0 < DEFAULT < MODULUS */ static long seed = DEFAULT; /* seed is the state of the generator */ double Random(void) /* --------------------------------------------------------------------- * Random is a Lehmer generator that returns a pseudo-random real number * uniformly distributed between 0.0 and 1.0. The period is (m - 1) * where m = 2,147,483,647 amd the smallest and largest possible values * are (1 / m) and 1 - (1 / m) respectively. * --------------------------------------------------------------------- */ { const long Q = MODULUS / MULTIPLIER; const long R = MODULUS % MULTIPLIER; long t; t = MULTIPLIER * (seed % Q) - R * (seed / Q); if (t > 0) seed = t; else seed = t + MODULUS; return ((double) seed / MODULUS); } void PutSeed(long x) /* ------------------------------------------------------------------- * Use this (optional) procedure to initialize or reset the state of * the random number generator according to the following conventions: * if x > 0 then x is the initial seed (unless too large) * if x < 0 then the initial seed is obtained from the system clock * if x = 0 then the initial seed is to be supplied interactively * -------------------------------------------------------------------- */ { char ok = 0; if (x > 0L) x = x % MODULUS; /* correct if x is too large */ if (x < 0L) x = ((unsigned long) time((time_t *) NULL)) % MODULUS; if (x == 0L) while (!ok) { printf("\nEnter a positive integer seed (9 digits or less) >> "); scanf("%ld", &x); ok = (0L < x) && (x < MODULUS); if (!ok) printf("\nInput out of range ... try again\n"); } seed = x; } void GetSeed(long *x) /* -------------------------------------------------------------------- * Use this (optional) procedure to get the current state of the random * number generator. * -------------------------------------------------------------------- */ { *x = seed; } void TestRandom(void) /* ------------------------------------------------------------------- * Use this (optional) procedure to test for a correct implementation. * ------------------------------------------------------------------- */ { long i; long x; double u; PutSeed(1); /* set initial state to 1 */ for(i = 0; i < 10000; i++) u = Random(); GetSeed(&x); /* get the new state */ if (x == CHECK) printf("\n The implementation of Random is correct\n"); else printf("\n\a ERROR - the implementation of Random is not correct\n"); }