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  }