Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
15
randomread(void *, ulong)
16
{
17
	return 0;
18
}
19
 
20
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
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
72
srand(long seed)
73
{
74
	isrand(seed);
75
}
76
 
77
long
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
}