github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/gnovm/stdlibs/testing/random.gno (about)

     1  package testing
     2  
     3  import (
     4  	"math"
     5  	"time"
     6  )
     7  
     8  // Internal state for the random number generator.
     9  var x uint64 = 42
    10  
    11  // UniformRand generates a uniformly distributed random number.
    12  // It uses the linear congrential generator method to produce the random number.
    13  // and the result is in the range from 0 to m-1. here, m is 32768.
    14  // To produce random number in [0, m-1], repeat this method as many times as needed.
    15  // [1] https://en.wikipedia.org/wiki/Linear_congruential_generator
    16  func UniformRand() uint64 {
    17  	var a uint64 = 950213
    18  	var c uint64 = 12345
    19  	var m uint64 = 32768
    20  	x = x*a + c
    21  	return (x >> 16) % m
    22  }
    23  
    24  // _srand function sets the seed for the random number generator.
    25  // This function provides an initial starting point for the sequence of random numbers.
    26  func _srand(seed int64) {
    27  	x = uint64(seed)
    28  }
    29  
    30  // nrand function generates a number approximating a normal distribution[1].
    31  // It uses the Central Limit Theorem[2] by summing multiple uniformly distributed random numbers
    32  // to approximate a normal distribution.
    33  //
    34  // y = Sum(k=1, K) (x_k - K/2) / sqrt(K/12)
    35  //
    36  // Here, K is some integer ans x_k are uniformly distributed numbers,
    37  // even for K as small as 10, the approximation is quite good.
    38  // [1] https://en.wikipedia.org/wiki/Normal_distribution
    39  // [2] https://en.wikipedia.org/wiki/Central_limit_theorem
    40  func nrand() float64 {
    41  	var i, K uint64 = 0, 10
    42  	var m uint64 = 32768
    43  	var y float64 = 0
    44  
    45  	for i = 0; i < K; i++ {
    46  		y += float64(UniformRand()) / float64(m)
    47  	}
    48  	y = (y - float64(K)/2) / math.Sqrt(float64(K)/12)
    49  	return y
    50  }
    51  
    52  // randRange generates a random integer between min and max (inclusive).
    53  // This function leverages the UniformRand function to generate a random number in a specified range.
    54  // Note: max should be greater than min.
    55  func randRange(min, max int) uint64 {
    56  	_min := uint64(min)
    57  	_max := uint64(max)
    58  	if _min >= _max {
    59  		return _min
    60  	}
    61  
    62  	rangeSize := _max - _min + 1
    63  	// adjust UniformRand to fit into our range.
    64  	return _min + (UniformRand() % rangeSize)
    65  }
    66  
    67  func GenerateRandomBool(bias float64) bool {
    68  	// Modify to use fuzz's random function for generating boolean with bias
    69  	if bias < 0 || bias > 1 {
    70  		panic("bias should be in the range [0, 1]")
    71  	}
    72  	// Convert fuzz's normalized range random float [-1, 1] to [0, 1]
    73  	res := (nrand() + 1) / 2
    74  	return res > bias
    75  }