87 lines
1.6 KiB
Go
87 lines
1.6 KiB
Go
package kjv
|
|
|
|
// MT19937 seeded with init_by_array from one integer, and a choice made by
|
|
// rejection sampling over its bits, so the verse of the day for any given date
|
|
// never changes.
|
|
|
|
type mtRandom struct {
|
|
mt [624]uint32
|
|
idx int
|
|
}
|
|
|
|
func newMTRandom(seed uint32) *mtRandom {
|
|
r := &mtRandom{}
|
|
r.initGenrand(19650218)
|
|
key := []uint32{seed}
|
|
i, j := 1, 0
|
|
k := max(624, len(key))
|
|
for ; k > 0; k-- {
|
|
r.mt[i] = (r.mt[i] ^ ((r.mt[i-1] ^ (r.mt[i-1] >> 30)) * 1664525)) + key[j] + uint32(j)
|
|
i++
|
|
j++
|
|
if i >= 624 {
|
|
r.mt[0] = r.mt[623]
|
|
i = 1
|
|
}
|
|
if j >= len(key) {
|
|
j = 0
|
|
}
|
|
}
|
|
for k = 623; k > 0; k-- {
|
|
r.mt[i] = (r.mt[i] ^ ((r.mt[i-1] ^ (r.mt[i-1] >> 30)) * 1566083941)) - uint32(i)
|
|
i++
|
|
if i >= 624 {
|
|
r.mt[0] = r.mt[623]
|
|
i = 1
|
|
}
|
|
}
|
|
r.mt[0] = 0x80000000
|
|
r.idx = 624
|
|
return r
|
|
}
|
|
|
|
func (r *mtRandom) initGenrand(s uint32) {
|
|
r.mt[0] = s
|
|
for i := 1; i < 624; i++ {
|
|
r.mt[i] = 1812433253*(r.mt[i-1]^(r.mt[i-1]>>30)) + uint32(i)
|
|
}
|
|
r.idx = 624
|
|
}
|
|
|
|
func (r *mtRandom) next() uint32 {
|
|
if r.idx >= 624 {
|
|
for k := 0; k < 624; k++ {
|
|
y := (r.mt[k] & 0x80000000) | (r.mt[(k+1)%624] & 0x7fffffff)
|
|
v := r.mt[(k+397)%624] ^ (y >> 1)
|
|
if y&1 != 0 {
|
|
v ^= 0x9908b0df
|
|
}
|
|
r.mt[k] = v
|
|
}
|
|
r.idx = 0
|
|
}
|
|
y := r.mt[r.idx]
|
|
r.idx++
|
|
y ^= y >> 11
|
|
y ^= (y << 7) & 0x9d2c5680
|
|
y ^= (y << 15) & 0xefc60000
|
|
y ^= y >> 18
|
|
return y
|
|
}
|
|
|
|
// choiceIndex is random.choice's _randbelow(n) for n < 2**32.
|
|
func (r *mtRandom) choiceIndex(n int) int {
|
|
if n <= 0 {
|
|
return 0
|
|
}
|
|
k := 0
|
|
for v := n; v > 0; v >>= 1 {
|
|
k++
|
|
}
|
|
for {
|
|
if x := int(r.next() >> (32 - k)); x < n {
|
|
return x
|
|
}
|
|
}
|
|
}
|