github.com/xaionaro-go/rand@v0.0.0-20191005105903-aba1befc54a5/mathrand/uint64.go (about) 1 package mathrand 2 3 const ( 4 primeNumber64bit0 = 15396334245663786197 5 primeNumber64bit1 = 8963315421273233617 6 7 mswsSeed = 0xb5ad4eceda1ce2a9 8 ) 9 10 func rotateLeft64(x uint64, k int) uint64 { 11 return x<<k | x>>(64-k) 12 } 13 14 // Uint64AddRotateMultiply is a fast analog of `math/rand.Uint64`. 15 // 16 // The reliability on statistical tests of this method is unknown. This is 17 // improved LCG method, so see also Uint64MultiplyAdd. 18 func (prng *PRNG) Uint64AddRotateMultiply() uint64 { 19 // This is my own method. I did not find how it should be called. 20 prng.state64[0] += primeNumber64bit1 21 prng.state64[0] = rotateLeft64(prng.state64[0], 32) 22 prng.state64[0] *= primeNumber64bit0 23 return prng.state64[0] 24 } 25 26 // Uint64AddNRotateMultiply is a fast analog of `math/rand.Uint64`. 27 // 28 // The reliability on statistical tests of this method is unknown. This is 29 // improved LCG method, so see also Uint64MultiplyAdd. 30 func (prng *PRNG) Uint64AddNRotateMultiply() uint64 { 31 // This is my own method. I did not find how it should be called. 32 prng.state64[0] += primeNumber64bit1 33 r := 28 + int(prng.state64[0]&0x7) 34 prng.state64[0] = rotateLeft64(prng.state64[0], r) 35 prng.state64[0] *= primeNumber64bit0 36 return prng.state64[0] 37 } 38 39 // Uint64MultiplyAdd is a fast (but week) analog of `math/rand.Uint64`. 40 // 41 // See also: https://en.wikipedia.org/wiki/Linear_congruential_generator 42 func (prng *PRNG) Uint64MultiplyAdd() uint64 { 43 prng.state64[0] *= primeNumber64bit0 44 prng.state64[0] += primeNumber64bit1 45 return prng.state64[0] 46 } 47 48 // Uint64AddRotate is a very fast (but weak) analog of `math/rand.Uint64`. 49 func (prng *PRNG) Uint64AddRotate() uint64 { 50 prng.state64[0] += primeNumber64bit1 51 prng.state64[0] = rotateLeft64(prng.state64[0], 32) 52 return prng.state64[0] 53 } 54 55 // Uint64AddIfShiftXOR is a very fast (but weak) analog of `math/rand.Uint64`. 56 func (prng *PRNG) Uint64AddIfShiftXOR() uint64 { 57 prng.state64[0] += primeNumber64bit1 58 if prng.state64[0]&0x02 == 0 { 59 prng.state64[0] ^= prng.state64[0] >> 32 60 } 61 return prng.state64[0] 62 } 63 64 // Uint64Xorshift is a very fast (but weak) analog of `math/rand.Uint64`. 65 // 66 // See also: https://en.wikipedia.org/wiki/Xorshift 67 func (prng *PRNG) Uint64Xorshift() uint64 { 68 prng.state64[0] ^= prng.state64[0] << 13 69 prng.state64[0] ^= prng.state64[0] >> 7 70 prng.state64[0] ^= prng.state64[0] << 17 71 return prng.state64[0] 72 } 73 74 // See also: https://en.wikipedia.org/wiki/Xorshift#xoshiro_and_xoroshiro 75 func (prng *PRNG) Uint64Xoshiro256() (result uint64) { 76 result = rotateLeft64(prng.state64[1]*5, 7) * 9 77 t := prng.state64[1] << 17 78 prng.state64[2] ^= prng.state64[0] 79 prng.state64[3] ^= prng.state64[1] 80 prng.state64[1] ^= prng.state64[2] 81 prng.state64[0] ^= prng.state64[3] 82 prng.state64[2] ^= t 83 prng.state64[3] ^= rotateLeft64(prng.state64[3], 45) 84 return 85 } 86 87 // See also: https://en.wikipedia.org/wiki/Middle-square_method 88 func (prng *PRNG) Uint64MSWS() uint64 { 89 prng.state64[0] *= prng.state64[0] 90 prng.state64[1] += mswsSeed 91 prng.state64[0] += prng.state64[1] 92 prng.state64[0] = rotateLeft64(prng.state64[0], 32) 93 return prng.state64[0] 94 }