xref: /plan9/sys/src/9/pcboot/rand.c (revision 25210b069a6ed8c047fa67220cf1dff32812f121)
1 /*
2  * libc pseudo-random number generators, but without locks.
3  */
4 #include	"u.h"
5 #include	"../port/lib.h"
6 #include	"mem.h"
7 #include	"dat.h"
8 #include	"fns.h"
9 #include	"io.h"
10 #include	"ureg.h"
11 #include	"pool.h"
12 
13 /* stubs to emulate random.c */
14 ulong
randomread(void *,ulong)15 randomread(void *, ulong)
16 {
17 	return 0;
18 }
19 
20 void
randominit(void)21 randominit(void)
22 {
23 }
24 
25 /*
26  *	algorithm by
27  *	D. P. Mitchell & J. A. Reeds
28  */
29 
30 #define	LEN	607
31 #define	TAP	273
32 #define	MASK	0x7fffffffL
33 #define	A	48271
34 #define	M	2147483647
35 #define	Q	44488
36 #define	R	3399
37 #define	NORM	(1.0/(1.0+MASK))
38 
39 static	ulong	rng_vec[LEN];
40 static	ulong*	rng_tap = rng_vec;
41 static	ulong*	rng_feed = 0;
42 
43 static void
isrand(long seed)44 isrand(long seed)
45 {
46 	long lo, hi, x;
47 	int i;
48 
49 	rng_tap = rng_vec;
50 	rng_feed = rng_vec+LEN-TAP;
51 	seed = seed%M;
52 	if(seed < 0)
53 		seed += M;
54 	if(seed == 0)
55 		seed = 89482311;
56 	x = seed;
57 	/*
58 	 *	Initialize by x[n+1] = 48271 * x[n] mod (2**31 - 1)
59 	 */
60 	for(i = -20; i < LEN; i++) {
61 		hi = x / Q;
62 		lo = x % Q;
63 		x = A*lo - R*hi;
64 		if(x < 0)
65 			x += M;
66 		if(i >= 0)
67 			rng_vec[i] = x;
68 	}
69 }
70 
71 void
srand(long seed)72 srand(long seed)
73 {
74 	isrand(seed);
75 }
76 
77 long
lrand(void)78 lrand(void)
79 {
80 	ulong x;
81 
82 	rng_tap--;
83 	if(rng_tap < rng_vec) {
84 		if(rng_feed == 0) {
85 			isrand(1);
86 			rng_tap--;
87 		}
88 		rng_tap += LEN;
89 	}
90 	rng_feed--;
91 	if(rng_feed < rng_vec)
92 		rng_feed += LEN;
93 	x = (*rng_feed + *rng_tap) & MASK;
94 	*rng_feed = x;
95 	return x;
96 }
97