summaryrefslogtreecommitdiff
path: root/noncore/games/sfcave/random.cpp
Unidiff
Diffstat (limited to 'noncore/games/sfcave/random.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/games/sfcave/random.cpp179
1 files changed, 179 insertions, 0 deletions
diff --git a/noncore/games/sfcave/random.cpp b/noncore/games/sfcave/random.cpp
new file mode 100644
index 0000000..c4c10bb
--- a/dev/null
+++ b/noncore/games/sfcave/random.cpp
@@ -0,0 +1,179 @@
1/* -------------------------------------------------------------------------
2 * This is an ANSI C library for multi-stream random number generation.
3 * The use of this library is recommended as a replacement for the ANSI C
4 * rand() and srand() functions, particularly in simulation applications
5 * where the statistical 'goodness' of the random number generator is
6 * important. The library supplies 256 streams of random numbers; use
7 * SelectStream(s) to switch between streams indexed s = 0,1,...,255.
8 *
9 * The streams must be initialized. The recommended way to do this is by
10 * using the function PlantSeeds(x) with the value of x used to initialize
11 * the default stream and all other streams initialized automatically with
12 * values dependent on the value of x. The following convention is used
13 * to initialize the default stream:
14 * if x > 0 then x is the state
15 * if x < 0 then the state is obtained from the system clock
16 * if x = 0 then the state is to be supplied interactively.
17 *
18 * The generator used in this library is a so-called 'Lehmer random number
19 * generator' which returns a pseudo-random number uniformly distributed
20 * 0.0 and 1.0. The period is (m - 1) where m = 2,147,483,647 and the
21 * smallest and largest possible values are (1 / m) and 1 - (1 / m)
22 * respectively. For more details see:
23 *
24 * "Random Number Generators: Good Ones Are Hard To Find"
25 * Steve Park and Keith Miller
26 * Communications of the ACM, October 1988
27 *
28 * Name : rngs.c (Random Number Generation - Multiple Streams)
29 * Authors : Steve Park & Dave Geyer
30 * Language : ANSI C
31 * Latest Revision : 09-22-98
32 * -------------------------------------------------------------------------
33 */
34
35#include <stdio.h>
36#include <time.h>
37#include "random.h"
38
39#define MODULUS 2147483647 /* DON'T CHANGE THIS VALUE */
40#define MULTIPLIER 48271 /* DON'T CHANGE THIS VALUE */
41#define CHECK 399268537 /* DON'T CHANGE THIS VALUE */
42#define STREAMS 256 /* # of streams, DON'T CHANGE THIS VALUE */
43#define A256 22925 /* jump multiplier, DON'T CHANGE THIS VALUE */
44#define DEFAULT 123456789 /* initial seed, use 0 < DEFAULT < MODULUS */
45
46static long seed[STREAMS] = {DEFAULT}; /* current state of each stream */
47static int stream = 0; /* stream index, 0 is the default */
48static int initialized = 0; /* test for stream initialization */
49
50
51 double Random(void)
52/* ----------------------------------------------------------------
53 * Random returns a pseudo-random real number uniformly distributed
54 * between 0.0 and 1.0.
55 * ----------------------------------------------------------------
56 */
57{
58 const long Q = MODULUS / MULTIPLIER;
59 const long R = MODULUS % MULTIPLIER;
60 long t;
61
62 t = MULTIPLIER * (seed[stream] % Q) - R * (seed[stream] / Q);
63 if (t > 0)
64 seed[stream] = t;
65 else
66 seed[stream] = t + MODULUS;
67 return ((double) seed[stream] / MODULUS);
68}
69
70
71 void PlantSeeds(long x)
72/* ---------------------------------------------------------------------
73 * Use this function to set the state of all the random number generator
74 * streams by "planting" a sequence of states (seeds), one per stream,
75 * with all states dictated by the state of the default stream.
76 * The sequence of planted states is separated one from the next by
77 * 8,367,782 calls to Random().
78 * ---------------------------------------------------------------------
79 */
80{
81 const long Q = MODULUS / A256;
82 const long R = MODULUS % A256;
83 int j;
84 int s;
85
86 initialized = 1;
87 s = stream; /* remember the current stream */
88 SelectStream(0); /* change to stream 0 */
89 PutSeed(x); /* set seed[0] */
90 stream = s; /* reset the current stream */
91 for (j = 1; j < STREAMS; j++) {
92 x = A256 * (seed[j - 1] % Q) - R * (seed[j - 1] / Q);
93 if (x > 0)
94 seed[j] = x;
95 else
96 seed[j] = x + MODULUS;
97 }
98}
99
100
101 void PutSeed(long x)
102/* ---------------------------------------------------------------
103 * Use this function to set the state of the current random number
104 * generator stream according to the following conventions:
105 * if x > 0 then x is the state (unless too large)
106 * if x < 0 then the state is obtained from the system clock
107 * if x = 0 then the state is to be supplied interactively
108 * ---------------------------------------------------------------
109 */
110{
111 char ok = 0;
112
113 if (x > 0)
114 x = x % MODULUS; /* correct if x is too large */
115 if (x < 0)
116 x = ((unsigned long) time((time_t *) NULL)) % MODULUS;
117 if (x == 0)
118 while (!ok) {
119 printf("\nEnter a positive integer seed (9 digits or less) >> ");
120 scanf("%ld", &x);
121 ok = (0 < x) && (x < MODULUS);
122 if (!ok)
123 printf("\nInput out of range ... try again\n");
124 }
125 seed[stream] = x;
126}
127
128
129 void GetSeed(long *x)
130/* ---------------------------------------------------------------
131 * Use this function to get the state of the current random number
132 * generator stream.
133 * ---------------------------------------------------------------
134 */
135{
136 *x = seed[stream];
137}
138
139
140 void SelectStream(int index)
141/* ------------------------------------------------------------------
142 * Use this function to set the current random number generator
143 * stream -- that stream from which the next random number will come.
144 * ------------------------------------------------------------------
145 */
146{
147 stream = ((unsigned int) index) % STREAMS;
148 if ((initialized == 0) && (stream != 0)) /* protect against */
149 PlantSeeds(DEFAULT); /* un-initialized streams */
150}
151
152
153 void TestRandom(void)
154/* ------------------------------------------------------------------
155 * Use this (optional) function to test for a correct implementation.
156 * ------------------------------------------------------------------
157 */
158{
159 long i;
160 long x;
161 double u;
162 char ok = 0;
163
164 SelectStream(0); /* select the default stream */
165 PutSeed(1); /* and set the state to 1 */
166 for(i = 0; i < 10000; i++)
167 u = Random();
168 GetSeed(&x); /* get the new state value */
169 ok = (x == CHECK); /* and check for correctness */
170
171 SelectStream(1); /* select stream 1 */
172 PlantSeeds(1); /* set the state of all streams */
173 GetSeed(&x); /* get the state of stream 1 */
174 ok = ok && (x == A256); /* x should be the jump multiplier */
175 if (ok)
176 printf("\n The implementation of rngs.c is correct.\n\n");
177 else
178 printf("\n\a ERROR -- the implementation of rngs.c is not correct.\n\n");
179}