github.com/xaionaro-go/rand@v0.0.0-20191005105903-aba1befc54a5/mathrand/uint32.go (about)

     1  package mathrand
     2  
     3  const (
     4  	primeNumber32bit0 = 3948558707
     5  	primeNumber32bit1 = 1948560947
     6  
     7  	pcgMultiplier = 6364136223846793005 // see https://en.wikipedia.org/wiki/Permuted_congruential_generator
     8  	pcgIncrement  = 1442695040888963407 // see https://en.wikipedia.org/wiki/Permuted_congruential_generator
     9  )
    10  
    11  func rotateLeft32(x uint32, k int) uint32 {
    12  	return x<<k | x>>(32-k)
    13  }
    14  func rotateRight32(x uint32, k int) uint32 {
    15  	return x>>k | x<<(32-k)
    16  }
    17  
    18  // Uint32AddRotateMultiply is a fast analog of `math/rand.Uint32`.
    19  //
    20  // The reliability on statistical tests of this method is unknown. This is
    21  // improved LCG method, so see also Uint32MultiplyAdd.
    22  func (prng *PRNG) Uint32AddRotateMultiply() uint32 {
    23  	prng.state32[0] += primeNumber32bit1
    24  	prng.state32[0] = rotateLeft32(prng.state32[0], 32)
    25  	prng.state32[0] *= primeNumber32bit0
    26  	return prng.state32[0]
    27  }
    28  
    29  // Uint32MultiplyAdd is a fast (but week) analog of `math/rand.Uint32`.
    30  //
    31  // See also: https://en.wikipedia.org/wiki/Linear_congruential_generator
    32  func (prng *PRNG) Uint32MultiplyAdd() uint32 {
    33  	prng.state32[0] *= primeNumber32bit0
    34  	prng.state32[0] += primeNumber32bit1
    35  	return prng.state32[0]
    36  }
    37  
    38  // Uint32AddRotate is a very fast (but weak) analog of `math/rand.Uint32`.
    39  func (prng *PRNG) Uint32AddRotate() uint32 {
    40  	prng.state32[0] += primeNumber32bit0
    41  	prng.state32[0] = rotateLeft32(prng.state32[0], 32)
    42  	return prng.state32[0]
    43  }
    44  
    45  // Uint32AddIfShiftXOR is a very fast (but weak) analog of `math/rand.Uint32`.
    46  func (prng *PRNG) Uint32AddIfShiftXOR() uint32 {
    47  	prng.state32[0] += primeNumber32bit1
    48  	if prng.state32[0]&0x02 == 0 {
    49  		prng.state32[0] ^= prng.state32[0] >> 16
    50  	}
    51  	return prng.state32[0]
    52  }
    53  
    54  // Uint32Xorshift is a very fast (but weak) analog of `math/rand.Uint32`.
    55  //
    56  // See also: https://en.wikipedia.org/wiki/Xorshift
    57  func (prng *PRNG) Uint32Xorshift() uint32 {
    58  	prng.state32[0] ^= prng.state32[0] << 13
    59  	prng.state32[0] ^= prng.state32[0] >> 17
    60  	prng.state32[0] ^= prng.state32[0] << 5
    61  	return prng.state32[0]
    62  }
    63  
    64  // See also: https://en.wikipedia.org/wiki/Permuted_congruential_generator
    65  func (prng *PRNG) Uint32PCG() uint32 {
    66  	x := prng.pcgState
    67  	count := int(x >> 59)
    68  	prng.pcgState = x*pcgMultiplier + pcgIncrement
    69  	x ^= x >> 18
    70  	return rotateRight32(uint32(x>>27), count)
    71  }