93 lines
1.7 KiB
Go
93 lines
1.7 KiB
Go
package mt19937
|
|
|
|
type MT19937 struct {
|
|
state []uint64
|
|
index int
|
|
}
|
|
|
|
func New() *MT19937 {
|
|
mt := &MT19937{
|
|
state: make([]uint64, n),
|
|
index: n,
|
|
}
|
|
mt.Seed(5489)
|
|
return mt
|
|
}
|
|
|
|
func (mt *MT19937) Seed(seed uint64) {
|
|
x := mt.state
|
|
x[0] = seed
|
|
for i := 1; i < n; i++ {
|
|
x[i] = f*(x[i-1]^(x[i-1]>>(w-2))) + uint64(i)
|
|
}
|
|
}
|
|
|
|
func (mt *MT19937) Random() uint64 {
|
|
x := mt.state
|
|
if mt.index == n {
|
|
mt.twist()
|
|
}
|
|
var z uint64 = x[mt.index]
|
|
|
|
mt.index++
|
|
|
|
z ^= ((z >> u) & d)
|
|
z ^= ((z << s) & b)
|
|
z ^= ((z << t) & c)
|
|
z ^= (z >> l)
|
|
return z
|
|
}
|
|
|
|
const (
|
|
// The variables used in the algorithm are as follows:
|
|
// w: length (in bits)
|
|
// n: recursion length
|
|
// m: period parameter, used as the offset of the third stage
|
|
// r: low-order mask / low-order bits to be extracted
|
|
// a: the parameters of the rotation matrix
|
|
// b,c: TGFSR mask
|
|
// s, t: the displacement of TGFSR
|
|
// u,d,l: mask and displacement required for additional mason rotation
|
|
// f: Initialize the required parameters of the Mason rotating chain
|
|
|
|
w = 64
|
|
n = 312
|
|
m = 156
|
|
r = 31
|
|
|
|
a = 0xb5026f5aa96619e9
|
|
|
|
u = 29
|
|
d = 0x5555555555555555
|
|
|
|
s = 17
|
|
b = 0x71d67fffeda60000
|
|
|
|
t = 37
|
|
c = 0xfff7eee000000000
|
|
|
|
l = 43
|
|
|
|
f = 6364136223846793005
|
|
)
|
|
|
|
func (mt *MT19937) twist() {
|
|
x := mt.state
|
|
const lower_mask uint64 = 1<<r - 1
|
|
const upper_mask uint64 = ^lower_mask
|
|
|
|
for j := 0; j < n-m; j++ {
|
|
var y uint64 = (x[j] & upper_mask) | (x[j+1] & lower_mask)
|
|
x[j] = x[j+m] ^ (y >> 1) ^ ((x[j+1] & 1) * a)
|
|
}
|
|
|
|
for j := n - m; j < n-1; j++ {
|
|
var y uint64 = (x[j] & upper_mask) | (x[j+1] & lower_mask)
|
|
x[j] = x[j-(n-m)] ^ (y >> 1) ^ ((x[j+1] & 1) * a)
|
|
}
|
|
|
|
var y uint64 = (x[n-1] & upper_mask) | (x[0] & lower_mask)
|
|
x[n-1] = x[m-1] ^ (y >> 1) ^ ((x[0] & 1) * a)
|
|
mt.index = 0
|
|
}
|