init
This commit is contained in:
+74
@@ -0,0 +1,74 @@
|
||||
// Package rng provides a small deterministic PRNG (xoshiro256**) seeded via
|
||||
// splitmix64. Streams are derived from a seed plus labels so that independent
|
||||
// parts of the simulation never share (and thus never perturb) each other's
|
||||
// random sequence.
|
||||
package rng
|
||||
|
||||
import (
|
||||
"math/bits"
|
||||
|
||||
"wh/fixed"
|
||||
)
|
||||
|
||||
type R struct{ s [4]uint64 }
|
||||
|
||||
func splitmix(x *uint64) uint64 {
|
||||
*x += 0x9e3779b97f4a7c15
|
||||
z := *x
|
||||
z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9
|
||||
z = (z ^ (z >> 27)) * 0x94d049bb133111eb
|
||||
return z ^ (z >> 31)
|
||||
}
|
||||
|
||||
// New returns a generator for the given seed.
|
||||
func New(seed uint64) *R {
|
||||
r := &R{}
|
||||
for i := range r.s {
|
||||
r.s[i] = splitmix(&seed)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// Derive returns a generator for an independent stream identified by seed and
|
||||
// labels, e.g. Derive(worldSeed, day, shipID).
|
||||
func Derive(seed uint64, labels ...uint64) *R {
|
||||
h := seed
|
||||
for _, l := range labels {
|
||||
h ^= l + 0x9e3779b97f4a7c15 + (h << 6) + (h >> 2)
|
||||
splitmix(&h)
|
||||
}
|
||||
return New(h)
|
||||
}
|
||||
|
||||
func (r *R) Uint64() uint64 {
|
||||
s := &r.s
|
||||
res := bits.RotateLeft64(s[1]*5, 7) * 9
|
||||
t := s[1] << 17
|
||||
s[2] ^= s[0]
|
||||
s[3] ^= s[1]
|
||||
s[1] ^= s[2]
|
||||
s[0] ^= s[3]
|
||||
s[2] ^= t
|
||||
s[3] = bits.RotateLeft64(s[3], 45)
|
||||
return res
|
||||
}
|
||||
|
||||
// Intn returns a uniform value in [0, n). n must be > 0.
|
||||
func (r *R) Intn(n uint64) uint64 {
|
||||
hi, lo := bits.Mul64(r.Uint64(), n)
|
||||
if lo < n {
|
||||
thresh := -n % n
|
||||
for lo < thresh {
|
||||
hi, lo = bits.Mul64(r.Uint64(), n)
|
||||
}
|
||||
}
|
||||
return hi
|
||||
}
|
||||
|
||||
// Fixed returns a uniform value in [0, 1).
|
||||
func (r *R) Fixed() fixed.F { return fixed.F(r.Uint64() >> 32) }
|
||||
|
||||
// FixedRange returns a uniform value in [lo, hi).
|
||||
func (r *R) FixedRange(lo, hi fixed.F) fixed.F {
|
||||
return lo + r.Fixed().Mul(hi-lo)
|
||||
}
|
||||
Reference in New Issue
Block a user