-
Notifications
You must be signed in to change notification settings - Fork 0
/
mt19937.go
93 lines (73 loc) · 1.55 KB
/
mt19937.go
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
89
90
91
92
93
package set3
const (
// coefficients for MT19937
w = 32 // wordsize
n = 624 // degree of recurrance
m = 397 // middle word
r = 31 // seperation point of one word
a = 0x9908B0DF // coefficients of the rational normal form twist matrix
// TGFSR(r) - tempering bit masks
b = 0x9D2C5680
c = 0xEFC60000
// TGFSR(r) - tempering bit shifts
s = 7
t = 15
// Mersenne Twister tempering bit shifts/masks
u = 11
d = 0xFFFFFFFF
l = 18
// constant for MT19937 (not sure why!)
f = 1812433253
)
var (
// masks for MT19937
lower uint32 = (1 << r) - 1
upper uint32 = (1 << r) // & 0x7fffffff
)
type mt19937 struct {
state []uint32
index int
}
func (mt *mt19937) seed(seed uint32) {
state := make([]uint32, n)
state[0] = seed
for i := 1; i < n; i++ {
state[i] = f*(state[i-1]^(state[i-1]>>(w-2))) + uint32(i)
}
mt.state = state
// force a twist first time we generate a random number.
// since state0 can't be used to generate random numbers
mt.index = n
}
func (mt *mt19937) twist() {
for cur := 0; cur < n; cur++ {
next := (cur + 1) % n
temp := (mt.state[cur] & upper) + (mt.state[next] & lower)
shifted := temp >> 1
if temp%2 != 0 {
shifted = shifted ^ a
}
mt.state[cur] = mt.state[(cur+m)%n] ^ shifted
}
mt.index = 0
}
func (mt *mt19937) Rand() uint32 {
if mt.index >= n {
mt.twist()
}
y := mt.state[mt.index]
y ^= (y >> u)
y ^= (y << s) & b
y ^= (y << t) & c
y ^= (y >> l)
mt.index += 1
return y
}
func NewMT19937(seed uint32) *mt19937 {
if seed <= 0 {
seed = 5489
}
m := mt19937{}
m.seed(seed)
return &m
}