29 lines
772 B
Go
29 lines
772 B
Go
|
// Package random implements the XORShift PRNG and a way to derive random state
|
||
|
// from an AnnounceRequest.
|
||
|
package random
|
||
|
|
||
|
// GenerateAndAdvance applies XORShift128Plus on s0 and s1, returning
|
||
|
// the new states newS0, newS1 and a pseudo-random number v.
|
||
|
func GenerateAndAdvance(s0, s1 uint64) (v, newS0, newS1 uint64) {
|
||
|
v = s0 + s1
|
||
|
newS0 = s1
|
||
|
s0 ^= (s0 << 23)
|
||
|
newS1 = s0 ^ s1 ^ (s0 >> 18) ^ (s1 >> 5)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Intn generates an int k that satisfies k >= 0 && k < n.
|
||
|
// n must be > 0.
|
||
|
// It returns the generated k and the new state of the generator.
|
||
|
func Intn(s0, s1 uint64, n int) (int, uint64, uint64) {
|
||
|
if n <= 0 {
|
||
|
panic("invalid n <= 0")
|
||
|
}
|
||
|
v, newS0, newS1 := GenerateAndAdvance(s0, s1)
|
||
|
k := int(v)
|
||
|
if k < 0 {
|
||
|
k = -k
|
||
|
}
|
||
|
return k % n, newS0, newS1
|
||
|
}
|