summaryrefslogtreecommitdiff
path: root/noncore/games/sfcave-sdl/random.cpp
Unidiff
Diffstat (limited to 'noncore/games/sfcave-sdl/random.cpp') (more/less context) (show whitespace changes)
-rw-r--r--noncore/games/sfcave-sdl/random.cpp189
1 files changed, 189 insertions, 0 deletions
diff --git a/noncore/games/sfcave-sdl/random.cpp b/noncore/games/sfcave-sdl/random.cpp
new file mode 100644
index 0000000..9f716f2
--- a/dev/null
+++ b/noncore/games/sfcave-sdl/random.cpp
@@ -0,0 +1,189 @@
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
38#define __RANDOM_CPP
39#include "random.h"
40
41#define MODULUS 2147483647 /* DON'T CHANGE THIS VALUE */
42#define MULTIPLIER 48271 /* DON'T CHANGE THIS VALUE */
43#define CHECK 399268537 /* DON'T CHANGE THIS VALUE */
44#define STREAMS 256 /* # of streams, DON'T CHANGE THIS VALUE */
45#define A256 22925 /* jump multiplier, DON'T CHANGE THIS VALUE */
46#define DEFAULT 123456789 /* initial seed, use 0 < DEFAULT < MODULUS */
47
48static long seed[STREAMS] = {DEFAULT}; /* current state of each stream */
49static int stream = 0; /* stream index, 0 is the default */
50static int initialized = 0; /* test for stream initialization */
51
52
53 double Random(void)
54/* ----------------------------------------------------------------
55 * Random returns a pseudo-random real number uniformly distributed
56 * between 0.0 and 1.0.
57 * ----------------------------------------------------------------
58 */
59{
60 const long Q = MODULUS / MULTIPLIER;
61 const long R = MODULUS % MULTIPLIER;
62 long t;
63
64 t = MULTIPLIER * (seed[stream] % Q) - R * (seed[stream] / Q);
65 if (t > 0)
66 seed[stream] = t;
67 else
68 seed[stream] = t + MODULUS;
69 return ((double) seed[stream] / MODULUS);
70}
71
72
73 void PlantSeeds(long x)
74/* ---------------------------------------------------------------------
75 * Use this function to set the state of all the random number generator
76 * streams by "planting" a sequence of states (seeds), one per stream,
77 * with all states dictated by the state of the default stream.
78 * The sequence of planted states is separated one from the next by
79 * 8,367,782 calls to Random().
80 * ---------------------------------------------------------------------
81 */
82{
83 const long Q = MODULUS / A256;
84 const long R = MODULUS % A256;
85 int j;
86 int s;
87
88 initialized = 1;
89 s = stream; /* remember the current stream */
90 SelectStream(0); /* change to stream 0 */
91 PutSeed(x); /* set seed[0] */
92 stream = s; /* reset the current stream */
93 for (j = 1; j < STREAMS; j++) {
94 x = A256 * (seed[j - 1] % Q) - R * (seed[j - 1] / Q);
95 if (x > 0)
96 seed[j] = x;
97 else
98 seed[j] = x + MODULUS;
99 }
100}
101
102
103int nextInteger( int range,const char *file, int line )
104{
105 int val = (int)(Random( ) * range);
106 //printf( "nextInt() called from %s line %d - returning %d\n", file, line, val );
107
108 return val;
109
110}
111 void PutSeed(long x)
112/* ---------------------------------------------------------------
113 * Use this function to set the state of the current random number
114 * generator stream according to the following conventions:
115 * if x > 0 then x is the state (unless too large)
116 * if x < 0 then the state is obtained from the system clock
117 * if x = 0 then the state is to be supplied interactively
118 * ---------------------------------------------------------------
119 */
120{
121 char ok = 0;
122
123 if (x > 0)
124 x = x % MODULUS; /* correct if x is too large */
125 if (x < 0)
126 x = ((unsigned long) time((time_t *) NULL)) % MODULUS;
127 if (x == 0)
128 while (!ok) {
129 printf("\nEnter a positive integer seed (9 digits or less) >> ");
130 scanf("%ld", &x);
131 ok = (0 < x) && (x < MODULUS);
132 if (!ok)
133 printf("\nInput out of range ... try again\n");
134 }
135 seed[stream] = x;
136}
137
138
139 void GetSeed(long *x)
140/* ---------------------------------------------------------------
141 * Use this function to get the state of the current random number
142 * generator stream.
143 * ---------------------------------------------------------------
144 */
145{
146 *x = seed[stream];
147}
148
149
150 void SelectStream(int index)
151/* ------------------------------------------------------------------
152 * Use this function to set the current random number generator
153 * stream -- that stream from which the next random number will come.
154 * ------------------------------------------------------------------
155 */
156{
157 stream = ((unsigned int) index) % STREAMS;
158 if ((initialized == 0) && (stream != 0)) /* protect against */
159 PlantSeeds(DEFAULT); /* un-initialized streams */
160}
161
162
163 void TestRandom(void)
164/* ------------------------------------------------------------------
165 * Use this (optional) function to test for a correct implementation.
166 * ------------------------------------------------------------------
167 */
168{
169 long i;
170 long x;
171 double u;
172 char ok = 0;
173
174 SelectStream(0); /* select the default stream */
175 PutSeed(1); /* and set the state to 1 */
176 for(i = 0; i < 10000; i++)
177 u = Random();
178 GetSeed(&x); /* get the new state value */
179 ok = (x == CHECK); /* and check for correctness */
180
181 SelectStream(1); /* select stream 1 */
182 PlantSeeds(1); /* set the state of all streams */
183 GetSeed(&x); /* get the state of stream 1 */
184 ok = ok && (x == A256); /* x should be the jump multiplier */
185 if (ok)
186 printf("\n The implementation of rngs.c is correct.\n\n");
187 else
188 printf("\n\a ERROR -- the implementation of rngs.c is not correct.\n\n");
189}