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  }