github.com/CAFxX/fastrand@v0.1.0/xoshiro256.go (about) 1 package fastrand 2 3 import "math/bits" 4 5 // Xoshiro256StarStar implements the Xoshiro256** PRNG. 6 // 7 // This generator is not safe for concurrent use by multiple goroutines. 8 // The zero value is not a valid state: Seed() must be called 9 // before generating random numbers. 10 type Xoshiro256StarStar struct { 11 state [4]uint64 12 } 13 14 // Uint64 returns a random uint64. 15 // 16 // This function is not safe for concurrent use by multiple goroutines. 17 func (r *Xoshiro256StarStar) Uint64() uint64 { 18 // TODO: this function has, unfortunately, an inline cost of 81. 19 // It would be ideal, especially for the sharded variant, if it was inlineable. 20 21 result := bits.RotateLeft64(r.state[1]*5, 7) * 9 22 23 t := r.state[1] << 17 24 25 r.state[2] ^= r.state[0] 26 r.state[3] ^= r.state[1] 27 r.state[1] ^= r.state[2] 28 r.state[0] ^= r.state[3] 29 30 r.state[2] ^= t 31 32 r.state[3] = bits.RotateLeft64(r.state[3], 45) 33 34 return result 35 } 36 37 // Seed sets the seed for the generator. 38 // 39 // The seed should not be all zeros (i.e. at least one of the four 40 // uint64 should be non-zero). 41 // This function is not safe for concurrent use by multiple goroutines. 42 func (r *Xoshiro256StarStar) Seed(s0, s1, s2, s3 uint64) { 43 r.state[0] = s0 44 r.state[1] = s1 45 r.state[2] = s2 46 r.state[3] = s3 47 } 48 49 func (r *Xoshiro256StarStar) safeSeed() { 50 retry: 51 a, b, c, d := Seed(), Seed(), Seed(), Seed() 52 if a == 0 && b == 0 && c == 0 && d == 0 { 53 goto retry 54 } 55 r.Seed(a, b, c, d) 56 }