github.com/MeteorsLiu/rand@v0.0.0-20230523094032-b55484ce1d5d/rand.go (about)

     1  package rand
     2  
     3  import (
     4  	"math"
     5  	r "math/rand"
     6  	"strings"
     7  	"sync"
     8  	"sync/atomic"
     9  
    10  	"github.com/MeteorsLiu/wyhash"
    11  )
    12  
    13  var (
    14  	NV_MAGICCONST = 4 * math.Exp(-0.5) / math.Sqrt(2.0)
    15  )
    16  
    17  const (
    18  	UNLOCK int32 = iota
    19  	LOCKED
    20  )
    21  
    22  type lockfreeRNG struct {
    23  	Rng     *r.Rand
    24  	grabbed int32
    25  }
    26  
    27  func newlockfreeRng() *lockfreeRNG {
    28  	return &lockfreeRNG{
    29  		Rng: r.New(r.NewSource(int64(rng.Uint64()))),
    30  	}
    31  }
    32  
    33  func (l *lockfreeRNG) Grab() bool {
    34  	if l.grabbed == LOCKED {
    35  		return false
    36  	}
    37  	return atomic.CompareAndSwapInt32(&l.grabbed, UNLOCK, LOCKED)
    38  }
    39  
    40  func (l *lockfreeRNG) Release() {
    41  	atomic.StoreInt32(&l.grabbed, UNLOCK)
    42  }
    43  
    44  var (
    45  	// pesudo RNG seed generator
    46  	rng       wyhash.SRNG
    47  	globalRng = newlockfreeRng()
    48  	// lock free rand pool
    49  	defaultRandPool = sync.Pool{
    50  		New: func() any {
    51  			return r.New(r.NewSource(int64(rng.Uint64())))
    52  		},
    53  	}
    54  
    55  	safeRng = r.New(newInternalRNG())
    56  )
    57  
    58  func step(s ...int) int {
    59  	defaultStep := 1
    60  	if len(s) > 0 {
    61  		if s[0] > 0 {
    62  			defaultStep = s[0]
    63  		}
    64  	}
    65  	return defaultStep
    66  }
    67  
    68  func ExpFloat64() float64 {
    69  	return safeRng.ExpFloat64()
    70  }
    71  func Float32() float32 {
    72  	return safeRng.Float32()
    73  }
    74  func Float64() float64 {
    75  	return safeRng.Float64()
    76  }
    77  func Int() int {
    78  	return safeRng.Int()
    79  }
    80  func Int31() int32 {
    81  	return safeRng.Int31()
    82  }
    83  func Int31n(n int32) int32 {
    84  	return int32(fastrandn(uint32(n)))
    85  }
    86  func Int63() int64 {
    87  	return safeRng.Int63()
    88  }
    89  func Int63n(n int64) int64 {
    90  	return safeRng.Int63n(n)
    91  }
    92  func Intn(n int) int {
    93  	return safeRng.Intn(n)
    94  }
    95  func NormFloat64() float64 {
    96  	return safeRng.NormFloat64()
    97  }
    98  func Perm(n int) []int {
    99  	return safeRng.Perm(n)
   100  }
   101  func Read(p []byte) (n int, err error) {
   102  	var pos int8
   103  	var val uint64
   104  	for n = 0; n < len(p); n++ {
   105  		if pos == 0 {
   106  			val = fastrand64()
   107  			pos = 7
   108  		}
   109  		p[n] = byte(val)
   110  		val >>= 8
   111  		pos--
   112  	}
   113  	return
   114  }
   115  
   116  func ReadN(p []byte, min, max int) (n int) {
   117  	var pos int8
   118  	var val uint64
   119  	width := byte(max - min)
   120  	minN := byte(min)
   121  	wsub := width - 1
   122  	isPowerofTwo := width&wsub == 0
   123  	for n = 0; n < len(p); n++ {
   124  		if pos == 0 {
   125  			val = fastrand64()
   126  			pos = 7
   127  		}
   128  		if isPowerofTwo {
   129  			p[n] = byte(val)&wsub + minN
   130  		} else {
   131  			p[n] = byte(val)%width + minN
   132  		}
   133  		val >>= 8
   134  		pos--
   135  	}
   136  	return
   137  }
   138  
   139  func ReadNU(p []byte, min, max int) (n int) {
   140  	width := uint32(max - min)
   141  	minN := uint32(min)
   142  	for n = 0; n < len(p); n++ {
   143  		p[n] = byte(fastrandn(width) + minN)
   144  	}
   145  	return
   146  }
   147  func Seed(seed int64) {
   148  	return
   149  }
   150  func Shuffle(n int, swap func(i, j int)) {
   151  	safeRng.Shuffle(n, swap)
   152  }
   153  func Uint32() uint32 {
   154  	return safeRng.Uint32()
   155  }
   156  func Uint64() uint64 {
   157  	return safeRng.Uint64()
   158  }
   159  
   160  func Do(f func(*r.Rand)) {
   161  	if globalRng.Grab() {
   162  		f(globalRng.Rng)
   163  		globalRng.Release()
   164  		return
   165  	}
   166  	rd := defaultRandPool.Get().(*r.Rand)
   167  	f(rd)
   168  	defaultRandPool.Put(rd)
   169  }
   170  func Intrange(from, to int, _step ...int) int {
   171  	stp := step(_step...)
   172  	width := to - from
   173  	switch {
   174  	case stp == 1:
   175  		return from + Intn(width)
   176  	case stp > 0:
   177  		n := (width + stp - 1) / stp
   178  		return from + stp*Intn(n)
   179  	case stp < 0:
   180  		n := (width + stp + 1) / stp
   181  		return from + stp*Intn(n)
   182  	default:
   183  		panic("error step")
   184  	}
   185  }
   186  
   187  func Int63range(from, to int64, _step ...int) int64 {
   188  	stp := int64(step(_step...))
   189  	width := to - from
   190  	switch {
   191  	case stp == 1:
   192  		return from + Int63n(width)
   193  	case stp > 0:
   194  		n := (width + stp - 1) / stp
   195  		return from + stp*Int63n(n)
   196  	case stp < 0:
   197  		n := (width + stp + 1) / stp
   198  		return from + stp*Int63n(n)
   199  	default:
   200  		panic("error step")
   201  	}
   202  }
   203  
   204  func Int31range(from, to int32, _step ...int) int32 {
   205  	stp := int32(step(_step...))
   206  	width := to - from
   207  	switch {
   208  	case stp == 1:
   209  		return from + Int31n(width)
   210  	case stp > 0:
   211  		n := (width + stp - 1) / stp
   212  		return from + stp*Int31n(n)
   213  	case stp < 0:
   214  		n := (width + stp + 1) / stp
   215  		return from + stp*Int31n(n)
   216  	default:
   217  		panic("error step")
   218  	}
   219  }
   220  
   221  func RandBytes(n int) []byte {
   222  	if n <= 0 {
   223  		return nil
   224  	}
   225  	b := make([]byte, n)
   226  	Read(b)
   227  	return b
   228  }
   229  
   230  func ChoiceString(a string) byte {
   231  	if len(a) == 0 {
   232  		return byte(0)
   233  	}
   234  	return a[Intn(len(a))]
   235  }
   236  
   237  func SampleString(s string, n int) string {
   238  	if len(s) == 0 || n >= len(s) {
   239  		return s
   240  	}
   241  	if n == 0 {
   242  		return ""
   243  	}
   244  	var sb strings.Builder
   245  	sb.Grow(n)
   246  	for i := 0; i < n; i++ {
   247  		sb.WriteByte(s[Intn(len(s))])
   248  	}
   249  	return sb.String()
   250  }
   251  func Choice[T any](a []T) (r T) {
   252  	if len(a) == 0 {
   253  		return
   254  	}
   255  	r = a[Intn(len(a))]
   256  	return
   257  }
   258  
   259  func Sample[T any](p []T, n int) []T {
   260  	if len(p) == 0 || n >= len(p) {
   261  		return p
   262  	}
   263  
   264  	if n == 0 {
   265  		return p[:0]
   266  	}
   267  	new := make([]T, n)
   268  	for i := 0; i < n; i++ {
   269  		new[i] = p[Intn(len(p))]
   270  	}
   271  	return new
   272  }
   273  
   274  func Uniform32(a, b float32) float32 {
   275  	return a + (b-a)*Float32()
   276  }
   277  func Uniform64(a, b float64) float64 {
   278  	return a + (b-a)*Float64()
   279  }
   280  
   281  func Triangular(low, high float64, mode ...float64) float64 {
   282  	c := 0.5
   283  	if len(mode) > 0 {
   284  		if high-low == 0 {
   285  			return 0
   286  		}
   287  		c = (mode[0] - low) / (high - low)
   288  	}
   289  	u := Float64()
   290  	if u > c {
   291  		u = 1.0 - u
   292  		c = 1.0 - c
   293  		low, high = high, low
   294  	}
   295  	return low + (high-low)*math.Sqrt(u*c)
   296  }
   297  func Normalvariate(mu, sigma float64) float64 {
   298  	var z float64
   299  	for {
   300  		u1 := Float64()
   301  		u2 := 1.0 - Float64()
   302  		z = NV_MAGICCONST * (u1 - 0.5) / u2
   303  		zz := z * z / 4.0
   304  		if zz <= math.Log(u2) {
   305  			break
   306  		}
   307  	}
   308  	return mu + z*sigma
   309  }
   310  
   311  func Gauss(mu, sigma float64) float64 {
   312  	x2pi := Float64() * 2 * math.Pi
   313  	g2rad := math.Sqrt(-2.0 * math.Log(1.0-Float64()))
   314  	z := math.Cos(x2pi) * g2rad
   315  	return mu + z*sigma
   316  }
   317  
   318  func Lognormvariate(mu, sigma float64) float64 {
   319  	return math.Exp(Normalvariate(mu, sigma))
   320  }
   321  
   322  func Expovariate(lambd float64) float64 {
   323  	if lambd == 0 {
   324  		lambd = 1
   325  	}
   326  	return math.Log(1-Float64()) / lambd
   327  }
   328  
   329  func Vonmisesvariate(mu, kappa float64) float64 {
   330  	if kappa <= 1e-6 {
   331  		return 2 * math.Pi * Float64()
   332  	}
   333  	s := 0.5 / kappa
   334  	r := s + math.Sqrt(1.0+s*s)
   335  	var z float64
   336  	for {
   337  		u1 := Float64()
   338  		z = math.Cos(math.Pi * u1)
   339  		d := z / (r + z)
   340  		u2 := Float64()
   341  		if u2 < 1.0-d*d || u2 <= (1.0-d)*math.Exp(d) {
   342  			break
   343  		}
   344  	}
   345  	q := 1.0 / r
   346  	f := (q + z) / (1.0 + q*z)
   347  	u3 := Float64()
   348  	var theta float64
   349  	if u3 > 0.5 {
   350  		theta = math.Mod(mu+math.Acos(f), 2*math.Pi)
   351  	} else {
   352  		theta = math.Mod(mu-math.Acos(f), 2*math.Pi)
   353  	}
   354  
   355  	return theta
   356  }
   357  
   358  func Gammavariate(alpha, beta float64) float64 {
   359  	if alpha <= 0.0 || beta <= 0.0 {
   360  		return 0
   361  	}
   362  	if alpha > 1 {
   363  		ainv := math.Sqrt(2.0*alpha - 1.0)
   364  		bbb := alpha - math.Log(4)
   365  		ccc := alpha + ainv
   366  		SG_MAGICCONST := 1.0 + math.Log(4.5)
   367  		for {
   368  			u1 := Float64()
   369  			if 1e-7 < u1 && u1 < 0.9999999 {
   370  				continue
   371  			}
   372  			u2 := 1.0 - Float64()
   373  			v := math.Log(u1/(1.0-u1)) / ainv
   374  			x := alpha * math.Exp(v)
   375  			z := u1 * u1 * u2
   376  			r := bbb + ccc*v - x
   377  			if r+SG_MAGICCONST-4.5*z >= 0.0 || r >= math.Log(z) {
   378  				return x * beta
   379  			}
   380  		}
   381  	} else if alpha == 1 {
   382  		return -math.Log(1.0-Float64()) * beta
   383  	}
   384  	var x float64
   385  	for {
   386  		u := Float64()
   387  		b := (math.E + alpha) / math.E
   388  		p := b * u
   389  		if p <= 1.0 {
   390  			x = math.Pow(p, 1.0/alpha)
   391  		} else {
   392  			x = -math.Log((b - p) / alpha)
   393  		}
   394  		u1 := Float64()
   395  		if p > 1.0 {
   396  			if u1 <= math.Pow(x, alpha-1.0) {
   397  				break
   398  			}
   399  		} else if u1 <= math.Exp(-x) {
   400  			break
   401  		}
   402  	}
   403  	return x * beta
   404  }
   405  func Betavariate(alpha, beta float64) float64 {
   406  	y := Gammavariate(alpha, 1.0)
   407  	if y > 0 {
   408  		return y / (y + Gammavariate(beta, 1.0))
   409  	}
   410  	return 0.0
   411  }
   412  
   413  // TODO
   414  // func Binomialvariate(n, p float64) float64
   415  
   416  func Paretovariate(alpha float64) float64 {
   417  	u := 1.0 - Float64()
   418  	return math.Pow(u, -1.0/alpha)
   419  }
   420  
   421  func Weibullvariate(alpha, beta float64) float64 {
   422  	u := 1.0 - Float64()
   423  	return alpha * math.Pow(-math.Log(u), 1.0/beta)
   424  }