-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathrng.d
58 lines (46 loc) · 1.57 KB
/
rng.d
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
module lehmer.rng;
class Lehmer {
public:
pure nothrow @safe this(long s = 1, long a = A, long m = M) {
state = s;
modulus = m;
multiplier = a;
quotient = modulus / multiplier;
remainder = modulus % multiplier;
}
pure nothrow @safe double random() {
long t = multiplier * (state % quotient) - remainder * (state / quotient);
state = t > 0 ? t : t + modulus;
return cast(double)state / cast(double)modulus;
}
static pure nothrow @safe bool isModCompatible(in long a, in long m) {
return m % a < m / a;
}
pure nothrow @safe @property long state() const { return mstate; }
pure nothrow @safe @property void state(long s) { mstate = s; }
pure nothrow @safe @property long m() const { return modulus; }
static const long M = 2147483647;
static const long A = 48271;
private:
// Simply a prime number, this is the upper bound (exclusive) of the stream
// generated
long modulus;
// Any full-period, modulus-compatible number to generate the sequence of
// random numbers
long multiplier;
// This "state" is the seed, it picks the starting point of the stream.
long mstate;
long quotient;
long remainder;
}
// From the book:
// If multiplier is set to 48271, and initial value of state is 1, then
// after 10,000 calls to random() state should be 399268537
unittest {
Lehmer rand = new Lehmer();
assert(rand.state == 1);
for(int i = 0; i < 10000; i++) {
rand.random();
}
assert(rand.state == 399268537);
}