1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
/*
** longrand() -- generate 2**31-2 random numbers
**
** public domain by Ray Gardner
**
** based on "Random Number Generators: Good Ones Are Hard to Find",
** S.K. Park and K.W. Miller, Communications of the ACM 31:10 (Oct 1988),
** and "Two Fast Implementations of the 'Minimal Standard' Random
** Number Generator", David G. Carta, Comm. ACM 33, 1 (Jan 1990), p. 87-88
**
** linear congruential generator f(z) = 16807 z mod (2 ** 31 - 1)
**
** uses L. Schrage's method to avoid overflow problems
*/
#define a 16807 /* multiplier */
#define m 2147483647L /* 2**31 - 1 */
#define q 127773L /* m div a */
#define r 2836 /* m mod a */
long nextlongrand(long seed)
{
unsigned long lo, hi;
lo = a * (long)(seed & 0xFFFF);
hi = a * (long)((unsigned long)seed >> 16);
lo += (hi & 0x7FFF) << 16;
if (lo > m)
{
lo &= m;
++lo;
}
lo += hi >> 15;
if (lo > m)
{
lo &= m;
++lo;
}
return (long)lo;
}
static long randomnum = 1;
long longrand(void) /* return next random long */
{
randomnum = nextlongrand(randomnum);
return randomnum;
}
void slongrand(unsigned long seed) /* to seed it */
{
randomnum = seed ? (seed & m) : 1; /* nonzero seed */
}
#ifdef TEST
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
long reps, k, num;
unsigned long seed;
reps = 10000;
seed = 1;
/*
** correctness test: after 10000 reps starting with seed 1,
** result should be 1043618065
*/
if (argc > 1)
reps = atol(argv[1]);
if (argc > 2)
seed = atol(argv[2]);
printf("seed %ld for %ld reps...\n", seed, reps);
slongrand(seed);
for (k = 0; k < reps; ++k)
num = longrand();
printf("%ld\n", num);
return 0;
}
#endif
|