github.com/insolar/vanilla@v0.0.0-20201023172447-248fdf805322/fastrand/fastrand.go (about) 1 // Copyright 2020 Insolar Network Ltd. 2 // All rights reserved. 3 // This material is licensed under the Insolar License version 1.0, 4 // available at https://github.com/insolar/assured-ledger/blob/master/LICENSE.md. 5 6 // Based on Go runtime 7 8 package fastrand 9 10 import ( 11 "os" 12 "sync/atomic" 13 "time" 14 ) 15 16 var seed uint64 // atomic 17 18 func init() { 19 pidrand := 1597334677 * uint32(os.Getpid()) 20 21 nano := uint64(time.Now().UnixNano()) 22 cputicks := nano ^ (nano >> 32) 23 24 seed = uint64(pidrand) | cputicks<<32 25 if seed == 0 { 26 seed = 1 << 32 27 } 28 } 29 30 func Uint32() uint32 { 31 // Implement xorshift64+: 2 32-bit xorshift sequences added together. 32 // Shift triplet [17,7,16] was calculated as indicated in Marsaglia's 33 // Xorshift paper: https://www.jstatsoft.org/article/view/v008i14/xorshift.pdf 34 // This generator passes the SmallCrush suite, part of TestU01 framework: 35 // http://simul.iro.umontreal.ca/testu01/tu01.html 36 s := atomic.LoadUint64(&seed) 37 s1, s0 := uint32(s), uint32(s>>32) 38 s1 ^= s1 << 17 39 s1 = s1 ^ s0 ^ s1>>7 ^ s0>>16 40 atomic.StoreUint64(&seed, uint64(s0)|uint64(s1)<<32) 41 return s0 + s1 42 } 43 44 func Intn(n uint32) uint32 { 45 // This is similar to Uint32() % n, but faster. 46 // See https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/ 47 return uint32(uint64(Uint32()) * uint64(n) >> 32) 48 }