type Rand struct {
src Source
s64 Source64 // non-nil if src is source64
-
- // readVal contains remainder of 63-bit integer used for bytes
- // generation during most recent Read call.
- // It is saved so next Read call can start where the previous
- // one finished.
- readVal int64
- // readPos indicates the number of low-order bytes of readVal
- // that are still valid.
- readPos int8
}
// New returns a new Rand that uses random values from src
// Seed should not be called concurrently with any other Rand method.
func (r *Rand) Seed(seed int64) {
if lk, ok := r.src.(*lockedSource); ok {
- lk.seedPos(seed, &r.readPos)
+ lk.Seed(seed)
return
}
-
r.src.Seed(seed)
- r.readPos = 0
}
// Int64 returns a non-negative pseudo-random 63-bit integer as an int64.
}
}
-// Read generates len(p) random bytes and writes them into p. It
-// always returns len(p) and a nil error.
-// Read should not be called concurrently with any other Rand method.
-func (r *Rand) Read(p []byte) (n int, err error) {
- switch src := r.src.(type) {
- case *lockedSource:
- return src.read(p, &r.readVal, &r.readPos)
- case *fastSource:
- return src.read(p, &r.readVal, &r.readPos)
- }
- return read(p, r.src, &r.readVal, &r.readPos)
-}
-
-func read(p []byte, src Source, readVal *int64, readPos *int8) (n int, err error) {
- pos := *readPos
- val := *readVal
- rng, _ := src.(*rngSource)
- for n = 0; n < len(p); n++ {
- if pos == 0 {
- if rng != nil {
- val = rng.Int64()
- } else {
- val = src.Int64()
- }
- pos = 7
- }
- p[n] = byte(val)
- val >>= 8
- pos--
- }
- *readPos = pos
- *readVal = val
- return
-}
-
/*
* Top-level convenience functions
*/
//go:linkname fastrand64
func fastrand64() uint64
-// fastSource is an implementation of Source64 that uses the runtime
-// fastrand functions.
-type fastSource struct {
- // The mutex is used to avoid race conditions in Read.
- mu sync.Mutex
-}
+// fastSource is a Source that uses the runtime fastrand functions.
+type fastSource struct{}
func (*fastSource) Int64() int64 {
return int64(fastrand64() & rngMask)
return fastrand64()
}
-func (fs *fastSource) read(p []byte, readVal *int64, readPos *int8) (n int, err error) {
- fs.mu.Lock()
- n, err = read(p, fs, readVal, readPos)
- fs.mu.Unlock()
- return
-}
-
// Seed uses the provided seed value to initialize the default Source to a
// deterministic state. Seed values that have the same remainder when
// divided by 2³¹-1 generate the same pseudo-random sequence.
// swap swaps the elements with indexes i and j.
func Shuffle(n int, swap func(i, j int)) { globalRand().Shuffle(n, swap) }
-// Read generates len(p) random bytes from the default Source and
-// writes them into p. It always returns len(p) and a nil error.
-// Read, unlike the Rand.Read method, is safe for concurrent use.
-//
-// Deprecated: For almost all use cases, crypto/rand.Read is more appropriate.
-func Read(p []byte) (n int, err error) { return globalRand().Read(p) }
-
// NormFloat64 returns a normally distributed float64 in the range
// [-math.MaxFloat64, +math.MaxFloat64] with
// standard normal distribution (mean = 0, stddev = 1)
r.lk.Unlock()
}
-// seedPos implements Seed for a lockedSource without a race condition.
-func (r *lockedSource) seedPos(seed int64, readPos *int8) {
- r.lk.Lock()
- r.seed(seed)
- *readPos = 0
- r.lk.Unlock()
-}
-
// seed seeds the underlying source.
// The caller must have locked r.lk.
func (r *lockedSource) seed(seed int64) {
r.s.Seed(seed)
}
}
-
-// read implements Read for a lockedSource without a race condition.
-func (r *lockedSource) read(p []byte, readVal *int64, readPos *int8) (n int, err error) {
- r.lk.Lock()
- n, err = read(p, r.s, readVal, readPos)
- r.lk.Unlock()
- return
-}
package rand_test
import (
- "bytes"
"errors"
"fmt"
"internal/testenv"
- "io"
"math"
. "math/rand/v2"
"os"
"runtime"
"sync"
"testing"
- "testing/iotest"
)
const (
}
}
-func testReadUniformity(t *testing.T, n int, seed int64) {
- r := New(NewSource(seed))
- buf := make([]byte, n)
- nRead, err := r.Read(buf)
- if err != nil {
- t.Errorf("Read err %v", err)
- }
- if nRead != n {
- t.Errorf("Read returned unexpected n; %d != %d", nRead, n)
- }
-
- // Expect a uniform distribution of byte values, which lie in [0, 255].
- var (
- mean = 255.0 / 2
- stddev = 256.0 / math.Sqrt(12.0)
- errorScale = stddev / math.Sqrt(float64(n))
- )
-
- expected := &statsResults{mean, stddev, 0.10 * errorScale, 0.08 * errorScale}
-
- // Cast bytes as floats to use the common distribution-validity checks.
- samples := make([]float64, n)
- for i, val := range buf {
- samples[i] = float64(val)
- }
- // Make sure that the entire set matches the expected distribution.
- checkSampleDistribution(t, samples, expected)
-}
-
-func TestReadUniformity(t *testing.T) {
- testBufferSizes := []int{
- 2, 4, 7, 64, 1024, 1 << 16, 1 << 20,
- }
- for _, seed := range testSeeds {
- for _, n := range testBufferSizes {
- testReadUniformity(t, n, seed)
- }
- }
-}
-
-func TestReadEmpty(t *testing.T) {
- r := New(NewSource(1))
- buf := make([]byte, 0)
- n, err := r.Read(buf)
- if err != nil {
- t.Errorf("Read err into empty buffer; %v", err)
- }
- if n != 0 {
- t.Errorf("Read into empty buffer returned unexpected n of %d", n)
- }
-}
-
-func TestReadByOneByte(t *testing.T) {
- r := New(NewSource(1))
- b1 := make([]byte, 100)
- _, err := io.ReadFull(iotest.OneByteReader(r), b1)
- if err != nil {
- t.Errorf("read by one byte: %v", err)
- }
- r = New(NewSource(1))
- b2 := make([]byte, 100)
- _, err = r.Read(b2)
- if err != nil {
- t.Errorf("read: %v", err)
- }
- if !bytes.Equal(b1, b2) {
- t.Errorf("read by one byte vs single read:\n%x\n%x", b1, b2)
- }
-}
-
-func TestReadSeedReset(t *testing.T) {
- r := New(NewSource(42))
- b1 := make([]byte, 128)
- _, err := r.Read(b1)
- if err != nil {
- t.Errorf("read: %v", err)
- }
- r.Seed(42)
- b2 := make([]byte, 128)
- _, err = r.Read(b2)
- if err != nil {
- t.Errorf("read: %v", err)
- }
- if !bytes.Equal(b1, b2) {
- t.Errorf("mismatch after re-seed:\n%x\n%x", b1, b2)
- }
-}
-
func TestShuffleSmall(t *testing.T) {
// Check that Shuffle allows n=0 and n=1, but that swap is never called for them.
r := New(NewSource(1))
}
}
-func BenchmarkRead3(b *testing.B) {
- r := New(NewSource(1))
- buf := make([]byte, 3)
- b.ResetTimer()
- for n := b.N; n > 0; n-- {
- r.Read(buf)
- }
-}
-
-func BenchmarkRead64(b *testing.B) {
- r := New(NewSource(1))
- buf := make([]byte, 64)
- b.ResetTimer()
- for n := b.N; n > 0; n-- {
- r.Read(buf)
- }
-}
-
-func BenchmarkRead1000(b *testing.B) {
- r := New(NewSource(1))
- buf := make([]byte, 1000)
- b.ResetTimer()
- for n := b.N; n > 0; n-- {
- r.Read(buf)
- }
-}
-
func BenchmarkConcurrent(b *testing.B) {
const goroutines = 4
var wg sync.WaitGroup
[]int{2, 1, 7, 0, 6, 3, 4, 5}, // Perm(8)
[]int{8, 7, 5, 3, 4, 6, 0, 1, 2}, // Perm(9)
[]int{1, 0, 2, 5, 7, 6, 9, 8, 3, 4}, // Perm(10)
- []byte{0x1}, // Read([0])
- []byte{0x94, 0xfd, 0xc2, 0xfa, 0x2f, 0xfc, 0xc0}, // Read([0 0 0 0 0 0 0])
- []byte{0x41, 0xd3, 0xff, 0x12, 0x4, 0x5b, 0x73, 0xc8}, // Read([0 0 0 0 0 0 0 0])
- []byte{0x6e, 0x4f, 0xf9, 0x5f, 0xf6, 0x62, 0xa5, 0xee, 0xe8}, // Read([0 0 0 0 0 0 0 0 0])
- []byte{0x2a, 0xbd, 0xf4, 0x4a, 0x2d, 0xb, 0x75, 0xfb, 0x18, 0xd}, // Read([0 0 0 0 0 0 0 0 0 0])
- []byte{0xaf}, // Read([0])
- []byte{0x48, 0xa7, 0x9e, 0xe0, 0xb1, 0xd, 0x39}, // Read([0 0 0 0 0 0 0])
- []byte{0x46, 0x51, 0x85, 0xf, 0xd4, 0xa1, 0x78, 0x89}, // Read([0 0 0 0 0 0 0 0])
- []byte{0x2e, 0xe2, 0x85, 0xec, 0xe1, 0x51, 0x14, 0x55, 0x78}, // Read([0 0 0 0 0 0 0 0 0])
- []byte{0x8, 0x75, 0xd6, 0x4e, 0xe2, 0xd3, 0xd0, 0xd0, 0xde, 0x6b}, // Read([0 0 0 0 0 0 0 0 0 0])
- []byte{0xf8}, // Read([0])
- []byte{0xf9, 0xb4, 0x4c, 0xe8, 0x5f, 0xf0, 0x44}, // Read([0 0 0 0 0 0 0])
- []byte{0xc6, 0xb1, 0xf8, 0x3b, 0x8e, 0x88, 0x3b, 0xbf}, // Read([0 0 0 0 0 0 0 0])
- []byte{0x85, 0x7a, 0xab, 0x99, 0xc5, 0xb2, 0x52, 0xc7, 0x42}, // Read([0 0 0 0 0 0 0 0 0])
- []byte{0x9c, 0x32, 0xf3, 0xa8, 0xae, 0xb7, 0x9e, 0xf8, 0x56, 0xf6}, // Read([0 0 0 0 0 0 0 0 0 0])
- []byte{0x59}, // Read([0])
- []byte{0xc1, 0x8f, 0xd, 0xce, 0xcc, 0x77, 0xc7}, // Read([0 0 0 0 0 0 0])
- []byte{0x5e, 0x7a, 0x81, 0xbf, 0xde, 0x27, 0x5f, 0x67}, // Read([0 0 0 0 0 0 0 0])
- []byte{0xcf, 0xe2, 0x42, 0xcf, 0x3c, 0xc3, 0x54, 0xf3, 0xed}, // Read([0 0 0 0 0 0 0 0 0])
- []byte{0xe2, 0xd6, 0xbe, 0xcc, 0x4e, 0xa3, 0xae, 0x5e, 0x88, 0x52}, // Read([0 0 0 0 0 0 0 0 0 0])
- uint32(4059586549), // Uint32()
- uint32(1052117029), // Uint32()
- uint32(2817310706), // Uint32()
- uint32(233405013), // Uint32()
- uint32(1578775030), // Uint32()
- uint32(1243308993), // Uint32()
- uint32(826517535), // Uint32()
- uint32(2814630155), // Uint32()
- uint32(3853314576), // Uint32()
- uint32(718781857), // Uint32()
- uint32(1239465936), // Uint32()
- uint32(3876658295), // Uint32()
- uint32(3649778518), // Uint32()
- uint32(1172727096), // Uint32()
- uint32(2615979505), // Uint32()
- uint32(1089444252), // Uint32()
- uint32(3327114623), // Uint32()
- uint32(75079301), // Uint32()
- uint32(3380456901), // Uint32()
- uint32(3433369789), // Uint32()
- uint64(8717895732742165505), // Uint64()
- uint64(2259404117704393152), // Uint64()
- uint64(6050128673802995827), // Uint64()
- uint64(9724605487393973602), // Uint64()
- uint64(12613765599614152010), // Uint64()
- uint64(11893357769247901871), // Uint64()
- uint64(1774932891286980153), // Uint64()
- uint64(15267744271532198264), // Uint64()
- uint64(17498302081433670737), // Uint64()
- uint64(1543572285742637646), // Uint64()
- uint64(11885104867954719224), // Uint64()
- uint64(17548432336275752516), // Uint64()
- uint64(7837839688282259259), // Uint64()
- uint64(2518412263346885298), // Uint64()
- uint64(5617773211005988520), // Uint64()
- uint64(11562935753659892057), // Uint64()
- uint64(16368296284793757383), // Uint64()
- uint64(161231572858529631), // Uint64()
- uint64(16482847956365694147), // Uint64()
- uint64(16596477517051940556), // Uint64()
+ uint32(4059586549), // Uint32()
+ uint32(1052117029), // Uint32()
+ uint32(2817310706), // Uint32()
+ uint32(233405013), // Uint32()
+ uint32(1578775030), // Uint32()
+ uint32(1243308993), // Uint32()
+ uint32(826517535), // Uint32()
+ uint32(2814630155), // Uint32()
+ uint32(3853314576), // Uint32()
+ uint32(718781857), // Uint32()
+ uint32(1239465936), // Uint32()
+ uint32(3876658295), // Uint32()
+ uint32(3649778518), // Uint32()
+ uint32(1172727096), // Uint32()
+ uint32(2615979505), // Uint32()
+ uint32(1089444252), // Uint32()
+ uint32(3327114623), // Uint32()
+ uint32(75079301), // Uint32()
+ uint32(3380456901), // Uint32()
+ uint32(3433369789), // Uint32()
+ uint64(8717895732742165505), // Uint64()
+ uint64(2259404117704393152), // Uint64()
+ uint64(6050128673802995827), // Uint64()
+ uint64(9724605487393973602), // Uint64()
+ uint64(12613765599614152010), // Uint64()
+ uint64(11893357769247901871), // Uint64()
+ uint64(1774932891286980153), // Uint64()
+ uint64(15267744271532198264), // Uint64()
+ uint64(17498302081433670737), // Uint64()
+ uint64(1543572285742637646), // Uint64()
+ uint64(11885104867954719224), // Uint64()
+ uint64(17548432336275752516), // Uint64()
+ uint64(7837839688282259259), // Uint64()
+ uint64(2518412263346885298), // Uint64()
+ uint64(5617773211005988520), // Uint64()
+ uint64(11562935753659892057), // Uint64()
+ uint64(16368296284793757383), // Uint64()
+ uint64(161231572858529631), // Uint64()
+ uint64(16482847956365694147), // Uint64()
+ uint64(16596477517051940556), // Uint64()
}