83 lines
1.5 KiB
Go
83 lines
1.5 KiB
Go
package gen
|
|
|
|
import (
|
|
"crypto/md5"
|
|
"encoding/binary"
|
|
)
|
|
|
|
func rotl64(x uint64, b uint8) uint64 {
|
|
return (x << b) | (x >> (64 - b))
|
|
}
|
|
|
|
type Xoroshiro struct {
|
|
L uint64
|
|
H uint64
|
|
}
|
|
|
|
func (x *Xoroshiro) Next() uint64 {
|
|
l := x.L
|
|
h := x.H
|
|
n := rotl64(l+h, 17) + l
|
|
h ^= l
|
|
x.L = rotl64(l, 49) ^ h ^ (h << 21)
|
|
x.H = rotl64(h, 28)
|
|
return n
|
|
}
|
|
|
|
func (x *Xoroshiro) NextBound(n uint32) int32 {
|
|
r := (x.Next() & 0xFFFFFFFF) * uint64(n)
|
|
if uint32(r) < n {
|
|
for uint32(r) < (^n+1)%n {
|
|
r = (x.Next() & 0xFFFFFFFF) * uint64(n)
|
|
}
|
|
}
|
|
return int32(r >> 32)
|
|
}
|
|
|
|
func (x *Xoroshiro) NextFloat() float32 {
|
|
return float32(x.Next()>>(64-24)) * 5.9604645e-8
|
|
}
|
|
|
|
func (x *Xoroshiro) NextFloat64() float64 {
|
|
return float64(x.Next()>>(64-53)) * 1.1102230246251565e-16
|
|
}
|
|
|
|
func XoroshiroFromString(s string) (x Xoroshiro) {
|
|
sum := md5.Sum([]byte(s))
|
|
x.L = binary.BigEndian.Uint64(sum[:8])
|
|
x.H = binary.BigEndian.Uint64(sum[8:])
|
|
return
|
|
}
|
|
|
|
func XoroshiroFromSeed(seed int64) (x Xoroshiro) {
|
|
x.L = uint64(seed) ^ 0x6a09e667f3bcc909
|
|
x.H = x.L + 0x9e3779b97f4a7c15
|
|
return
|
|
}
|
|
|
|
func mixStafford13(s uint64) uint64 {
|
|
s = (s ^ (s >> 30)) * 0xbf58476d1ce4e5b9
|
|
s = (s ^ (s >> 27)) * 0x94d049bb133111eb
|
|
return s ^ (s >> 31)
|
|
}
|
|
|
|
func (x *Xoroshiro) Mix() {
|
|
x.L = mixStafford13(x.L)
|
|
x.H = mixStafford13(x.H)
|
|
}
|
|
|
|
func (x *Xoroshiro) Xor(x2 Xoroshiro) {
|
|
x.L ^= x2.L
|
|
x.H ^= x2.H
|
|
}
|
|
|
|
func (x *Xoroshiro) XorString(s string) {
|
|
x.Xor(XoroshiroFromString(s))
|
|
}
|
|
|
|
func (x *Xoroshiro) Split() (x2 Xoroshiro) {
|
|
x2.L = x.Next()
|
|
x2.H = x.Next()
|
|
return
|
|
}
|