mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
Move ChaCha8 code into internal/chacha8rand and use it to implement runtime.rand, which is used for the unseeded global source for both math/rand and math/rand/v2. This also affects the calculation of the start point for iteration over very very large maps (when the 32-bit fastrand is not big enough). The benefit is that misuse of the global random number generators in math/rand and math/rand/v2 in contexts where non-predictable randomness is important for security reasons is no longer a security problem, removing a common mistake among programmers who are unaware of the different kinds of randomness. The cost is an extra 304 bytes per thread stored in the m struct plus 2-3ns more per random uint64 due to the more sophisticated algorithm. Using PCG looks like it would cost about the same, although I haven't benchmarked that. Before this, the math/rand and math/rand/v2 global generator was wyrand (https://github.com/wangyi-fudan/wyhash). For math/rand, using wyrand instead of the Mitchell/Reeds/Thompson ALFG was justifiable, since the latter was not any better. But for math/rand/v2, the global generator really should be at least as good as one of the well-studied, specific algorithms provided directly by the package, and it's not. (Wyrand is still reasonable for scheduling and cache decisions.) Good randomness does have a cost: about twice wyrand. Also rationalize the various runtime rand references. goos: linux goarch: amd64 pkg: math/rand/v2 cpu: AMD Ryzen 9 7950X 16-Core Processor │ bbb48afeb7.amd64 │ 5cf807d1ea.amd64 │ │ sec/op │ sec/op vs base │ ChaCha8-32 1.862n ± 2% 1.861n ± 2% ~ (p=0.825 n=20) PCG_DXSM-32 1.471n ± 1% 1.460n ± 2% ~ (p=0.153 n=20) SourceUint64-32 1.636n ± 2% 1.582n ± 1% -3.30% (p=0.000 n=20) GlobalInt64-32 2.087n ± 1% 3.663n ± 1% +75.54% (p=0.000 n=20) GlobalInt64Parallel-32 0.1042n ± 1% 0.2026n ± 1% +94.48% (p=0.000 n=20) GlobalUint64-32 2.263n ± 2% 3.724n ± 1% +64.57% (p=0.000 n=20) GlobalUint64Parallel-32 0.1019n ± 1% 0.1973n ± 1% +93.67% (p=0.000 n=20) Int64-32 1.771n ± 1% 1.774n ± 1% ~ (p=0.449 n=20) Uint64-32 1.863n ± 2% 1.866n ± 1% ~ (p=0.364 n=20) GlobalIntN1000-32 3.134n ± 3% 4.730n ± 2% +50.95% (p=0.000 n=20) IntN1000-32 2.489n ± 1% 2.489n ± 1% ~ (p=0.683 n=20) Int64N1000-32 2.521n ± 1% 2.516n ± 1% ~ (p=0.394 n=20) Int64N1e8-32 2.479n ± 1% 2.478n ± 2% ~ (p=0.743 n=20) Int64N1e9-32 2.530n ± 2% 2.514n ± 2% ~ (p=0.193 n=20) Int64N2e9-32 2.501n ± 1% 2.494n ± 1% ~ (p=0.616 n=20) Int64N1e18-32 3.227n ± 1% 3.205n ± 1% ~ (p=0.101 n=20) Int64N2e18-32 3.647n ± 1% 3.599n ± 1% ~ (p=0.019 n=20) Int64N4e18-32 5.135n ± 1% 5.069n ± 2% ~ (p=0.034 n=20) Int32N1000-32 2.657n ± 1% 2.637n ± 1% ~ (p=0.180 n=20) Int32N1e8-32 2.636n ± 1% 2.636n ± 1% ~ (p=0.763 n=20) Int32N1e9-32 2.660n ± 2% 2.638n ± 1% ~ (p=0.358 n=20) Int32N2e9-32 2.662n ± 2% 2.618n ± 2% ~ (p=0.064 n=20) Float32-32 2.272n ± 2% 2.239n ± 2% ~ (p=0.194 n=20) Float64-32 2.272n ± 1% 2.286n ± 2% ~ (p=0.763 n=20) ExpFloat64-32 3.762n ± 1% 3.744n ± 1% ~ (p=0.171 n=20) NormFloat64-32 3.706n ± 1% 3.655n ± 2% ~ (p=0.066 n=20) Perm3-32 32.93n ± 3% 34.62n ± 1% +5.13% (p=0.000 n=20) Perm30-32 202.9n ± 1% 204.0n ± 1% ~ (p=0.482 n=20) Perm30ViaShuffle-32 115.0n ± 1% 114.9n ± 1% ~ (p=0.358 n=20) ShuffleOverhead-32 112.8n ± 1% 112.7n ± 1% ~ (p=0.692 n=20) Concurrent-32 2.107n ± 0% 3.725n ± 1% +76.75% (p=0.000 n=20) goos: darwin goarch: arm64 pkg: math/rand/v2 │ bbb48afeb7.arm64 │ 5cf807d1ea.arm64 │ │ sec/op │ sec/op vs base │ ChaCha8-8 2.480n ± 0% 2.429n ± 0% -2.04% (p=0.000 n=20) PCG_DXSM-8 2.531n ± 0% 2.530n ± 0% ~ (p=0.877 n=20) SourceUint64-8 2.534n ± 0% 2.533n ± 0% ~ (p=0.732 n=20) GlobalInt64-8 2.172n ± 1% 4.794n ± 0% +120.67% (p=0.000 n=20) GlobalInt64Parallel-8 0.4320n ± 0% 0.9605n ± 0% +122.32% (p=0.000 n=20) GlobalUint64-8 2.182n ± 0% 4.770n ± 0% +118.58% (p=0.000 n=20) GlobalUint64Parallel-8 0.4307n ± 0% 0.9583n ± 0% +122.51% (p=0.000 n=20) Int64-8 4.107n ± 0% 4.104n ± 0% ~ (p=0.416 n=20) Uint64-8 4.080n ± 0% 4.080n ± 0% ~ (p=0.052 n=20) GlobalIntN1000-8 2.814n ± 2% 5.643n ± 0% +100.50% (p=0.000 n=20) IntN1000-8 4.141n ± 0% 4.139n ± 0% ~ (p=0.140 n=20) Int64N1000-8 4.140n ± 0% 4.140n ± 0% ~ (p=0.313 n=20) Int64N1e8-8 4.140n ± 0% 4.139n ± 0% ~ (p=0.103 n=20) Int64N1e9-8 4.139n ± 0% 4.140n ± 0% ~ (p=0.761 n=20) Int64N2e9-8 4.140n ± 0% 4.140n ± 0% ~ (p=0.636 n=20) Int64N1e18-8 5.266n ± 0% 5.326n ± 1% +1.14% (p=0.001 n=20) Int64N2e18-8 6.052n ± 0% 6.167n ± 0% +1.90% (p=0.000 n=20) Int64N4e18-8 8.826n ± 0% 9.051n ± 0% +2.55% (p=0.000 n=20) Int32N1000-8 4.127n ± 0% 4.132n ± 0% +0.12% (p=0.000 n=20) Int32N1e8-8 4.126n ± 0% 4.131n ± 0% +0.12% (p=0.000 n=20) Int32N1e9-8 4.127n ± 0% 4.132n ± 0% +0.12% (p=0.000 n=20) Int32N2e9-8 4.132n ± 0% 4.131n ± 0% ~ (p=0.017 n=20) Float32-8 4.109n ± 0% 4.105n ± 0% ~ (p=0.379 n=20) Float64-8 4.107n ± 0% 4.106n ± 0% ~ (p=0.867 n=20) ExpFloat64-8 5.339n ± 0% 5.383n ± 0% +0.82% (p=0.000 n=20) NormFloat64-8 5.735n ± 0% 5.737n ± 1% ~ (p=0.856 n=20) Perm3-8 26.65n ± 0% 26.80n ± 1% +0.58% (p=0.000 n=20) Perm30-8 194.8n ± 1% 197.0n ± 0% +1.18% (p=0.000 n=20) Perm30ViaShuffle-8 156.6n ± 0% 157.6n ± 1% +0.61% (p=0.000 n=20) ShuffleOverhead-8 124.9n ± 0% 125.5n ± 0% +0.52% (p=0.000 n=20) Concurrent-8 2.434n ± 3% 5.066n ± 0% +108.09% (p=0.000 n=20) goos: linux goarch: 386 pkg: math/rand/v2 cpu: AMD Ryzen 9 7950X 16-Core Processor │ bbb48afeb7.386 │ 5cf807d1ea.386 │ │ sec/op │ sec/op vs base │ ChaCha8-32 11.295n ± 1% 4.748n ± 2% -57.96% (p=0.000 n=20) PCG_DXSM-32 7.693n ± 1% 7.738n ± 2% ~ (p=0.542 n=20) SourceUint64-32 7.658n ± 2% 7.622n ± 2% ~ (p=0.344 n=20) GlobalInt64-32 3.473n ± 2% 7.526n ± 2% +116.73% (p=0.000 n=20) GlobalInt64Parallel-32 0.3198n ± 0% 0.5444n ± 0% +70.22% (p=0.000 n=20) GlobalUint64-32 3.612n ± 0% 7.575n ± 1% +109.69% (p=0.000 n=20) GlobalUint64Parallel-32 0.3168n ± 0% 0.5403n ± 0% +70.51% (p=0.000 n=20) Int64-32 7.673n ± 2% 7.789n ± 1% ~ (p=0.122 n=20) Uint64-32 7.773n ± 1% 7.827n ± 2% ~ (p=0.920 n=20) GlobalIntN1000-32 6.268n ± 1% 9.581n ± 1% +52.87% (p=0.000 n=20) IntN1000-32 10.33n ± 2% 10.45n ± 1% ~ (p=0.233 n=20) Int64N1000-32 10.98n ± 2% 11.01n ± 1% ~ (p=0.401 n=20) Int64N1e8-32 11.19n ± 2% 10.97n ± 1% ~ (p=0.033 n=20) Int64N1e9-32 11.06n ± 1% 11.08n ± 1% ~ (p=0.498 n=20) Int64N2e9-32 11.10n ± 1% 11.01n ± 2% ~ (p=0.995 n=20) Int64N1e18-32 15.23n ± 2% 15.04n ± 1% ~ (p=0.973 n=20) Int64N2e18-32 15.89n ± 1% 15.85n ± 1% ~ (p=0.409 n=20) Int64N4e18-32 18.96n ± 2% 19.34n ± 2% ~ (p=0.048 n=20) Int32N1000-32 10.46n ± 2% 10.44n ± 2% ~ (p=0.480 n=20) Int32N1e8-32 10.46n ± 2% 10.49n ± 2% ~ (p=0.951 n=20) Int32N1e9-32 10.28n ± 2% 10.26n ± 1% ~ (p=0.431 n=20) Int32N2e9-32 10.50n ± 2% 10.44n ± 2% ~ (p=0.249 n=20) Float32-32 13.80n ± 2% 13.80n ± 2% ~ (p=0.751 n=20) Float64-32 23.55n ± 2% 23.87n ± 0% ~ (p=0.408 n=20) ExpFloat64-32 15.36n ± 1% 15.29n ± 2% ~ (p=0.316 n=20) NormFloat64-32 13.57n ± 1% 13.79n ± 1% +1.66% (p=0.005 n=20) Perm3-32 45.70n ± 2% 46.99n ± 2% +2.81% (p=0.001 n=20) Perm30-32 399.0n ± 1% 403.8n ± 1% +1.19% (p=0.006 n=20) Perm30ViaShuffle-32 349.0n ± 1% 350.4n ± 1% ~ (p=0.909 n=20) ShuffleOverhead-32 322.3n ± 1% 323.8n ± 1% ~ (p=0.410 n=20) Concurrent-32 3.331n ± 1% 7.312n ± 1% +119.50% (p=0.000 n=20) For #61716. Change-Id: Ibdddeed85c34d9ae397289dc899e04d4845f9ed2 Reviewed-on: https://go-review.googlesource.com/c/go/+/516860 Reviewed-by: Michael Pratt <mpratt@google.com> Reviewed-by: Filippo Valsorda <filippo@golang.org> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
363 lines
13 KiB
Go
363 lines
13 KiB
Go
// Copyright 2009 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// Package rand implements pseudo-random number generators suitable for tasks
|
|
// such as simulation, but it should not be used for security-sensitive work.
|
|
//
|
|
// Random numbers are generated by a [Source], usually wrapped in a [Rand].
|
|
// Both types should be used by a single goroutine at a time: sharing among
|
|
// multiple goroutines requires some kind of synchronization.
|
|
//
|
|
// Top-level functions, such as [Float64] and [Int],
|
|
// are safe for concurrent use by multiple goroutines.
|
|
//
|
|
// This package's outputs might be easily predictable regardless of how it's
|
|
// seeded. For random numbers suitable for security-sensitive work, see the
|
|
// crypto/rand package.
|
|
package rand
|
|
|
|
import (
|
|
"math/bits"
|
|
_ "unsafe" // for go:linkname
|
|
)
|
|
|
|
// A Source is a source of uniformly-distributed
|
|
// pseudo-random uint64 values in the range [0, 1<<64).
|
|
//
|
|
// A Source is not safe for concurrent use by multiple goroutines.
|
|
type Source interface {
|
|
Uint64() uint64
|
|
}
|
|
|
|
// A Rand is a source of random numbers.
|
|
type Rand struct {
|
|
src Source
|
|
}
|
|
|
|
// New returns a new Rand that uses random values from src
|
|
// to generate other random values.
|
|
func New(src Source) *Rand {
|
|
return &Rand{src: src}
|
|
}
|
|
|
|
// Int64 returns a non-negative pseudo-random 63-bit integer as an int64.
|
|
func (r *Rand) Int64() int64 { return int64(r.src.Uint64() &^ (1 << 63)) }
|
|
|
|
// Uint32 returns a pseudo-random 32-bit value as a uint32.
|
|
func (r *Rand) Uint32() uint32 { return uint32(r.src.Uint64() >> 32) }
|
|
|
|
// Uint64 returns a pseudo-random 64-bit value as a uint64.
|
|
func (r *Rand) Uint64() uint64 { return r.src.Uint64() }
|
|
|
|
// Int32 returns a non-negative pseudo-random 31-bit integer as an int32.
|
|
func (r *Rand) Int32() int32 { return int32(r.src.Uint64() >> 33) }
|
|
|
|
// Int returns a non-negative pseudo-random int.
|
|
func (r *Rand) Int() int { return int(uint(r.src.Uint64()) << 1 >> 1) }
|
|
|
|
// Int64N returns, as an int64, a non-negative pseudo-random number in the half-open interval [0,n).
|
|
// It panics if n <= 0.
|
|
func (r *Rand) Int64N(n int64) int64 {
|
|
if n <= 0 {
|
|
panic("invalid argument to Int64N")
|
|
}
|
|
return int64(r.uint64n(uint64(n)))
|
|
}
|
|
|
|
// Uint64N returns, as a uint64, a non-negative pseudo-random number in the half-open interval [0,n).
|
|
// It panics if n == 0.
|
|
func (r *Rand) Uint64N(n uint64) uint64 {
|
|
if n == 0 {
|
|
panic("invalid argument to Uint64N")
|
|
}
|
|
return r.uint64n(n)
|
|
}
|
|
|
|
// uint64n is the no-bounds-checks version of Uint64N.
|
|
func (r *Rand) uint64n(n uint64) uint64 {
|
|
if is32bit && uint64(uint32(n)) == n {
|
|
return uint64(r.uint32n(uint32(n)))
|
|
}
|
|
if n&(n-1) == 0 { // n is power of two, can mask
|
|
return r.Uint64() & (n - 1)
|
|
}
|
|
|
|
// Suppose we have a uint64 x uniform in the range [0,2⁶⁴)
|
|
// and want to reduce it to the range [0,n) preserving exact uniformity.
|
|
// We can simulate a scaling arbitrary precision x * (n/2⁶⁴) by
|
|
// the high bits of a double-width multiply of x*n, meaning (x*n)/2⁶⁴.
|
|
// Since there are 2⁶⁴ possible inputs x and only n possible outputs,
|
|
// the output is necessarily biased if n does not divide 2⁶⁴.
|
|
// In general (x*n)/2⁶⁴ = k for x*n in [k*2⁶⁴,(k+1)*2⁶⁴).
|
|
// There are either floor(2⁶⁴/n) or ceil(2⁶⁴/n) possible products
|
|
// in that range, depending on k.
|
|
// But suppose we reject the sample and try again when
|
|
// x*n is in [k*2⁶⁴, k*2⁶⁴+(2⁶⁴%n)), meaning rejecting fewer than n possible
|
|
// outcomes out of the 2⁶⁴.
|
|
// Now there are exactly floor(2⁶⁴/n) possible ways to produce
|
|
// each output value k, so we've restored uniformity.
|
|
// To get valid uint64 math, 2⁶⁴ % n = (2⁶⁴ - n) % n = -n % n,
|
|
// so the direct implementation of this algorithm would be:
|
|
//
|
|
// hi, lo := bits.Mul64(r.Uint64(), n)
|
|
// thresh := -n % n
|
|
// for lo < thresh {
|
|
// hi, lo = bits.Mul64(r.Uint64(), n)
|
|
// }
|
|
//
|
|
// That still leaves an expensive 64-bit division that we would rather avoid.
|
|
// We know that thresh < n, and n is usually much less than 2⁶⁴, so we can
|
|
// avoid the last four lines unless lo < n.
|
|
//
|
|
// See also:
|
|
// https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction
|
|
// https://lemire.me/blog/2016/06/30/fast-random-shuffling
|
|
hi, lo := bits.Mul64(r.Uint64(), n)
|
|
if lo < n {
|
|
thresh := -n % n
|
|
for lo < thresh {
|
|
hi, lo = bits.Mul64(r.Uint64(), n)
|
|
}
|
|
}
|
|
return hi
|
|
}
|
|
|
|
// uint32n is an identical computation to uint64n
|
|
// but optimized for 32-bit systems.
|
|
func (r *Rand) uint32n(n uint32) uint32 {
|
|
if n&(n-1) == 0 { // n is power of two, can mask
|
|
return uint32(r.Uint64()) & (n - 1)
|
|
}
|
|
// On 64-bit systems we still use the uint64 code below because
|
|
// the probability of a random uint64 lo being < a uint32 n is near zero,
|
|
// meaning the unbiasing loop almost never runs.
|
|
// On 32-bit systems, here we need to implement that same logic in 32-bit math,
|
|
// both to preserve the exact output sequence observed on 64-bit machines
|
|
// and to preserve the optimization that the unbiasing loop almost never runs.
|
|
//
|
|
// We want to compute
|
|
// hi, lo := bits.Mul64(r.Uint64(), n)
|
|
// In terms of 32-bit halves, this is:
|
|
// x1:x0 := r.Uint64()
|
|
// 0:hi, lo1:lo0 := bits.Mul64(x1:x0, 0:n)
|
|
// Writing out the multiplication in terms of bits.Mul32 allows
|
|
// using direct hardware instructions and avoiding
|
|
// the computations involving these zeros.
|
|
x := r.Uint64()
|
|
lo1a, lo0 := bits.Mul32(uint32(x), n)
|
|
hi, lo1b := bits.Mul32(uint32(x>>32), n)
|
|
lo1, c := bits.Add32(lo1a, lo1b, 0)
|
|
hi += c
|
|
if lo1 == 0 && lo0 < uint32(n) {
|
|
n64 := uint64(n)
|
|
thresh := uint32(-n64 % n64)
|
|
for lo1 == 0 && lo0 < thresh {
|
|
x := r.Uint64()
|
|
lo1a, lo0 = bits.Mul32(uint32(x), n)
|
|
hi, lo1b = bits.Mul32(uint32(x>>32), n)
|
|
lo1, c = bits.Add32(lo1a, lo1b, 0)
|
|
hi += c
|
|
}
|
|
}
|
|
return hi
|
|
}
|
|
|
|
// Int32N returns, as an int32, a non-negative pseudo-random number in the half-open interval [0,n).
|
|
// It panics if n <= 0.
|
|
func (r *Rand) Int32N(n int32) int32 {
|
|
if n <= 0 {
|
|
panic("invalid argument to Int32N")
|
|
}
|
|
return int32(r.uint64n(uint64(n)))
|
|
}
|
|
|
|
// Uint32N returns, as a uint32, a non-negative pseudo-random number in the half-open interval [0,n).
|
|
// It panics if n == 0.
|
|
func (r *Rand) Uint32N(n uint32) uint32 {
|
|
if n == 0 {
|
|
panic("invalid argument to Uint32N")
|
|
}
|
|
return uint32(r.uint64n(uint64(n)))
|
|
}
|
|
|
|
const is32bit = ^uint(0)>>32 == 0
|
|
|
|
// IntN returns, as an int, a non-negative pseudo-random number in the half-open interval [0,n).
|
|
// It panics if n <= 0.
|
|
func (r *Rand) IntN(n int) int {
|
|
if n <= 0 {
|
|
panic("invalid argument to IntN")
|
|
}
|
|
return int(r.uint64n(uint64(n)))
|
|
}
|
|
|
|
// UintN returns, as a uint, a non-negative pseudo-random number in the half-open interval [0,n).
|
|
// It panics if n == 0.
|
|
func (r *Rand) UintN(n uint) uint {
|
|
if n == 0 {
|
|
panic("invalid argument to UintN")
|
|
}
|
|
return uint(r.uint64n(uint64(n)))
|
|
}
|
|
|
|
// Float64 returns, as a float64, a pseudo-random number in the half-open interval [0.0,1.0).
|
|
func (r *Rand) Float64() float64 {
|
|
// There are exactly 1<<53 float64s in [0,1). Use Intn(1<<53) / (1<<53).
|
|
return float64(r.Uint64()<<11>>11) / (1 << 53)
|
|
}
|
|
|
|
// Float32 returns, as a float32, a pseudo-random number in the half-open interval [0.0,1.0).
|
|
func (r *Rand) Float32() float32 {
|
|
// There are exactly 1<<24 float32s in [0,1). Use Intn(1<<24) / (1<<24).
|
|
return float32(r.Uint32()<<8>>8) / (1 << 24)
|
|
}
|
|
|
|
// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers
|
|
// in the half-open interval [0,n).
|
|
func (r *Rand) Perm(n int) []int {
|
|
p := make([]int, n)
|
|
for i := range p {
|
|
p[i] = i
|
|
}
|
|
r.Shuffle(len(p), func(i, j int) { p[i], p[j] = p[j], p[i] })
|
|
return p
|
|
}
|
|
|
|
// Shuffle pseudo-randomizes the order of elements.
|
|
// n is the number of elements. Shuffle panics if n < 0.
|
|
// swap swaps the elements with indexes i and j.
|
|
func (r *Rand) Shuffle(n int, swap func(i, j int)) {
|
|
if n < 0 {
|
|
panic("invalid argument to Shuffle")
|
|
}
|
|
|
|
// Fisher-Yates shuffle: https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
|
|
// Shuffle really ought not be called with n that doesn't fit in 32 bits.
|
|
// Not only will it take a very long time, but with 2³¹! possible permutations,
|
|
// there's no way that any PRNG can have a big enough internal state to
|
|
// generate even a minuscule percentage of the possible permutations.
|
|
// Nevertheless, the right API signature accepts an int n, so handle it as best we can.
|
|
for i := n - 1; i > 0; i-- {
|
|
j := int(r.uint64n(uint64(i + 1)))
|
|
swap(i, j)
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Top-level convenience functions
|
|
*/
|
|
|
|
// globalRand is the source of random numbers for the top-level
|
|
// convenience functions.
|
|
var globalRand = &Rand{src: &runtimeSource{}}
|
|
|
|
//go:linkname runtime_rand runtime.rand
|
|
func runtime_rand() uint64
|
|
|
|
// runtimeSource is a Source that uses the runtime fastrand functions.
|
|
type runtimeSource struct{}
|
|
|
|
func (*runtimeSource) Uint64() uint64 {
|
|
return runtime_rand()
|
|
}
|
|
|
|
// Int64 returns a non-negative pseudo-random 63-bit integer as an int64
|
|
// from the default Source.
|
|
func Int64() int64 { return globalRand.Int64() }
|
|
|
|
// Uint32 returns a pseudo-random 32-bit value as a uint32
|
|
// from the default Source.
|
|
func Uint32() uint32 { return globalRand.Uint32() }
|
|
|
|
// Uint64N returns, as a uint64, a pseudo-random number in the half-open interval [0,n)
|
|
// from the default Source.
|
|
// It panics if n <= 0.
|
|
func Uint64N(n uint64) uint64 { return globalRand.Uint64N(n) }
|
|
|
|
// Uint32N returns, as a uint32, a pseudo-random number in the half-open interval [0,n)
|
|
// from the default Source.
|
|
// It panics if n <= 0.
|
|
func Uint32N(n uint32) uint32 { return globalRand.Uint32N(n) }
|
|
|
|
// Uint64 returns a pseudo-random 64-bit value as a uint64
|
|
// from the default Source.
|
|
func Uint64() uint64 { return globalRand.Uint64() }
|
|
|
|
// Int32 returns a non-negative pseudo-random 31-bit integer as an int32
|
|
// from the default Source.
|
|
func Int32() int32 { return globalRand.Int32() }
|
|
|
|
// Int returns a non-negative pseudo-random int from the default Source.
|
|
func Int() int { return globalRand.Int() }
|
|
|
|
// Int64N returns, as an int64, a pseudo-random number in the half-open interval [0,n)
|
|
// from the default Source.
|
|
// It panics if n <= 0.
|
|
func Int64N(n int64) int64 { return globalRand.Int64N(n) }
|
|
|
|
// Int32N returns, as an int32, a pseudo-random number in the half-open interval [0,n)
|
|
// from the default Source.
|
|
// It panics if n <= 0.
|
|
func Int32N(n int32) int32 { return globalRand.Int32N(n) }
|
|
|
|
// IntN returns, as an int, a pseudo-random number in the half-open interval [0,n)
|
|
// from the default Source.
|
|
// It panics if n <= 0.
|
|
func IntN(n int) int { return globalRand.IntN(n) }
|
|
|
|
// UintN returns, as a uint, a pseudo-random number in the half-open interval [0,n)
|
|
// from the default Source.
|
|
// It panics if n <= 0.
|
|
func UintN(n uint) uint { return globalRand.UintN(n) }
|
|
|
|
// N returns a pseudo-random number in the half-open interval [0,n) from the default Source.
|
|
// The type parameter Int can be any integer type.
|
|
// It panics if n <= 0.
|
|
func N[Int intType](n Int) Int {
|
|
if n <= 0 {
|
|
panic("invalid argument to N")
|
|
}
|
|
return Int(globalRand.uint64n(uint64(n)))
|
|
}
|
|
|
|
type intType interface {
|
|
~int | ~int8 | ~int16 | ~int32 | ~int64 |
|
|
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
|
|
}
|
|
|
|
// Float64 returns, as a float64, a pseudo-random number in the half-open interval [0.0,1.0)
|
|
// from the default Source.
|
|
func Float64() float64 { return globalRand.Float64() }
|
|
|
|
// Float32 returns, as a float32, a pseudo-random number in the half-open interval [0.0,1.0)
|
|
// from the default Source.
|
|
func Float32() float32 { return globalRand.Float32() }
|
|
|
|
// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers
|
|
// in the half-open interval [0,n) from the default Source.
|
|
func Perm(n int) []int { return globalRand.Perm(n) }
|
|
|
|
// Shuffle pseudo-randomizes the order of elements using the default Source.
|
|
// n is the number of elements. Shuffle panics if n < 0.
|
|
// swap swaps the elements with indexes i and j.
|
|
func Shuffle(n int, swap func(i, j int)) { globalRand.Shuffle(n, swap) }
|
|
|
|
// NormFloat64 returns a normally distributed float64 in the range
|
|
// [-math.MaxFloat64, +math.MaxFloat64] with
|
|
// standard normal distribution (mean = 0, stddev = 1)
|
|
// from the default Source.
|
|
// To produce a different normal distribution, callers can
|
|
// adjust the output using:
|
|
//
|
|
// sample = NormFloat64() * desiredStdDev + desiredMean
|
|
func NormFloat64() float64 { return globalRand.NormFloat64() }
|
|
|
|
// ExpFloat64 returns an exponentially distributed float64 in the range
|
|
// (0, +math.MaxFloat64] with an exponential distribution whose rate parameter
|
|
// (lambda) is 1 and whose mean is 1/lambda (1) from the default Source.
|
|
// To produce a distribution with a different rate parameter,
|
|
// callers can adjust the output using:
|
|
//
|
|
// sample = ExpFloat64() / desiredRateParameter
|
|
func ExpFloat64() float64 { return globalRand.ExpFloat64() }
|