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 }