blob: c85d58408dde53864482dfa26da5f41a568b4fdf [file] [log] [blame]
// Copyright 2014 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.
// Test that random number sequences generated by a specific seed
// do not change from version to version.
//
// Do NOT make changes to the golden outputs. If bugs need to be fixed
// in the underlying code, find ways to fix them that do not affect the
// outputs.
package rand_test
import (
"bytes"
"flag"
"fmt"
"go/format"
"io"
. "math/rand/v2"
"os"
"reflect"
"strings"
"testing"
)
var update = flag.Bool("update", false, "update golden results for regression test")
func TestRegress(t *testing.T) {
var int32s = []int32{1, 10, 32, 1 << 20, 1<<20 + 1, 1000000000, 1 << 30, 1<<31 - 2, 1<<31 - 1}
var uint32s = []uint32{1, 10, 32, 1 << 20, 1<<20 + 1, 1000000000, 1 << 30, 1<<31 - 2, 1<<31 - 1, 1<<32 - 2, 1<<32 - 1}
var int64s = []int64{1, 10, 32, 1 << 20, 1<<20 + 1, 1000000000, 1 << 30, 1<<31 - 2, 1<<31 - 1, 1000000000000000000, 1 << 60, 1<<63 - 2, 1<<63 - 1}
var uint64s = []uint64{1, 10, 32, 1 << 20, 1<<20 + 1, 1000000000, 1 << 30, 1<<31 - 2, 1<<31 - 1, 1000000000000000000, 1 << 60, 1<<63 - 2, 1<<63 - 1, 1<<64 - 2, 1<<64 - 1}
var permSizes = []int{0, 1, 5, 8, 9, 10, 16}
n := reflect.TypeOf(New(NewPCG(1, 2))).NumMethod()
p := 0
var buf bytes.Buffer
if *update {
fmt.Fprintf(&buf, "var regressGolden = []any{\n")
}
for i := 0; i < n; i++ {
if *update && i > 0 {
fmt.Fprintf(&buf, "\n")
}
r := New(NewPCG(1, 2))
rv := reflect.ValueOf(r)
m := rv.Type().Method(i)
mv := rv.Method(i)
mt := mv.Type()
if mt.NumOut() == 0 {
continue
}
for repeat := 0; repeat < 20; repeat++ {
var args []reflect.Value
var argstr string
if mt.NumIn() == 1 {
var x any
switch mt.In(0).Kind() {
default:
t.Fatalf("unexpected argument type for r.%s", m.Name)
case reflect.Int:
if m.Name == "Perm" {
x = permSizes[repeat%len(permSizes)]
break
}
big := int64s[repeat%len(int64s)]
if int64(int(big)) != big {
// On 32-bit machine.
// Consume an Int64 like on a 64-bit machine,
// to keep the golden data the same on different architectures.
r.Int64N(big)
if *update {
t.Fatalf("must run -update on 64-bit machine")
}
p++
continue
}
x = int(big)
case reflect.Uint:
big := uint64s[repeat%len(uint64s)]
if uint64(uint(big)) != big {
r.Uint64N(big) // what would happen on 64-bit machine, to keep stream in sync
if *update {
t.Fatalf("must run -update on 64-bit machine")
}
p++
continue
}
x = uint(big)
case reflect.Int32:
x = int32s[repeat%len(int32s)]
case reflect.Int64:
x = int64s[repeat%len(int64s)]
case reflect.Uint32:
x = uint32s[repeat%len(uint32s)]
case reflect.Uint64:
x = uint64s[repeat%len(uint64s)]
}
argstr = fmt.Sprint(x)
args = append(args, reflect.ValueOf(x))
}
var out any
out = mv.Call(args)[0].Interface()
if m.Name == "Int" || m.Name == "IntN" {
out = int64(out.(int))
}
if m.Name == "Uint" || m.Name == "UintN" {
out = uint64(out.(uint))
}
if *update {
var val string
big := int64(1 << 60)
if int64(int(big)) != big && (m.Name == "Int" || m.Name == "IntN") {
// 32-bit machine cannot print 64-bit results
val = "truncated"
} else if reflect.TypeOf(out).Kind() == reflect.Slice {
val = fmt.Sprintf("%#v", out)
} else {
val = fmt.Sprintf("%T(%v)", out, out)
}
fmt.Fprintf(&buf, "\t%s, // %s(%s)\n", val, m.Name, argstr)
} else if p >= len(regressGolden) {
t.Errorf("r.%s(%s) = %v, missing golden value", m.Name, argstr, out)
} else {
want := regressGolden[p]
if m.Name == "Int" {
want = int64(int(uint(want.(int64)) << 1 >> 1))
}
if !reflect.DeepEqual(out, want) {
t.Errorf("r.%s(%s) = %v, want %v", m.Name, argstr, out, want)
}
}
p++
}
}
if *update {
replace(t, "regress_test.go", buf.Bytes())
}
}
func TestUpdateExample(t *testing.T) {
if !*update {
t.Skip("-update not given")
}
oldStdout := os.Stdout
defer func() {
os.Stdout = oldStdout
}()
r, w, err := os.Pipe()
if err != nil {
t.Fatal(err)
}
defer r.Close()
defer w.Close()
go func() {
os.Stdout = w
Example_rand()
os.Stdout = oldStdout
w.Close()
}()
out, err := io.ReadAll(r)
if err != nil {
t.Fatal(err)
}
var buf bytes.Buffer
fmt.Fprintf(&buf, "\t// Output:\n")
for _, line := range strings.Split(string(out), "\n") {
if line != "" {
fmt.Fprintf(&buf, "\t// %s\n", line)
}
}
replace(t, "example_test.go", buf.Bytes())
// Exit so that Example_rand cannot fail.
fmt.Printf("UPDATED; ignore non-zero exit status\n")
os.Exit(1)
}
// replace substitutes the definition text from new into the content of file.
// The text in new is of the form
//
// var whatever = T{
// ...
// }
//
// Replace searches file for an exact match for the text of the first line,
// finds the closing brace, and then substitutes new for what used to be in the file.
// This lets us update the regressGolden table during go test -update.
func replace(t *testing.T, file string, new []byte) {
first, _, _ := bytes.Cut(new, []byte("\n"))
first = append(append([]byte("\n"), first...), '\n')
data, err := os.ReadFile(file)
if err != nil {
t.Fatal(err)
}
i := bytes.Index(data, first)
if i < 0 {
t.Fatalf("cannot find %q in %s", first, file)
}
j := bytes.Index(data[i+1:], []byte("\n}\n"))
if j < 0 {
t.Fatalf("cannot find end in %s", file)
}
data = append(append(data[:i+1:i+1], new...), data[i+1+j+1:]...)
data, err = format.Source(data)
if err != nil {
t.Fatal(err)
}
if err := os.WriteFile(file, data, 0666); err != nil {
t.Fatal(err)
}
}
var regressGolden = []any{
float64(0.5931317151369719), // ExpFloat64()
float64(0.0680034588807843), // ExpFloat64()
float64(0.036496967459790364), // ExpFloat64()
float64(2.460335459645379), // ExpFloat64()
float64(1.5792300208419903), // ExpFloat64()
float64(0.9149501499404387), // ExpFloat64()
float64(0.43463410545541104), // ExpFloat64()
float64(0.5513632046504593), // ExpFloat64()
float64(0.7426404617374481), // ExpFloat64()
float64(1.2334925132631804), // ExpFloat64()
float64(0.892529142200442), // ExpFloat64()
float64(0.21508763681487764), // ExpFloat64()
float64(1.0208588200798545), // ExpFloat64()
float64(0.7650739736831382), // ExpFloat64()
float64(0.7772788529257701), // ExpFloat64()
float64(1.102732861281323), // ExpFloat64()
float64(0.6982243043885805), // ExpFloat64()
float64(0.4981788638202421), // ExpFloat64()
float64(0.15806532306947937), // ExpFloat64()
float64(0.9419163802459202), // ExpFloat64()
float32(0.95955694), // Float32()
float32(0.8076733), // Float32()
float32(0.8135684), // Float32()
float32(0.92872405), // Float32()
float32(0.97472525), // Float32()
float32(0.5485458), // Float32()
float32(0.97740936), // Float32()
float32(0.042272687), // Float32()
float32(0.99663067), // Float32()
float32(0.035181105), // Float32()
float32(0.45059562), // Float32()
float32(0.86597633), // Float32()
float32(0.8954844), // Float32()
float32(0.090798736), // Float32()
float32(0.46218646), // Float32()
float32(0.5955118), // Float32()
float32(0.08985227), // Float32()
float32(0.19820237), // Float32()
float32(0.7443699), // Float32()
float32(0.56461), // Float32()
float64(0.6764556596678251), // Float64()
float64(0.4613862177205994), // Float64()
float64(0.5085473976760264), // Float64()
float64(0.4297927436037299), // Float64()
float64(0.797802349388613), // Float64()
float64(0.3883664855410056), // Float64()
float64(0.8192750264193612), // Float64()
float64(0.3381816951746133), // Float64()
float64(0.9730458047755973), // Float64()
float64(0.281449117585586), // Float64()
float64(0.6047654075331631), // Float64()
float64(0.9278107175107462), // Float64()
float64(0.16387541502137226), // Float64()
float64(0.7263900707339023), // Float64()
float64(0.6974917552729882), // Float64()
float64(0.7640946923790318), // Float64()
float64(0.7188183661358182), // Float64()
float64(0.5856191500346635), // Float64()
float64(0.9549597149363428), // Float64()
float64(0.5168804691962643), // Float64()
int64(4969059760275911952), // Int()
int64(2147869220224756844), // Int()
int64(5246770554000605320), // Int()
int64(5471241176507662746), // Int()
int64(4321634407747778896), // Int()
int64(760102831717374652), // Int()
int64(9221744211007427193), // Int()
int64(8289669384274456462), // Int()
int64(2449715415482412441), // Int()
int64(3389241988064777392), // Int()
int64(2986830195847294191), // Int()
int64(8204908297817606218), // Int()
int64(8134976985547166651), // Int()
int64(2240328155279531677), // Int()
int64(7311121042813227358), // Int()
int64(5231057920893523323), // Int()
int64(4257872588489500903), // Int()
int64(158397175702351138), // Int()
int64(1350674201389090105), // Int()
int64(6093522341581845358), // Int()
int32(1652216515), // Int32()
int32(1323786710), // Int32()
int32(1684546306), // Int32()
int32(1710678126), // Int32()
int32(503104460), // Int32()
int32(88487615), // Int32()
int32(1073552320), // Int32()
int32(965044529), // Int32()
int32(285184408), // Int32()
int32(394559696), // Int32()
int32(1421454622), // Int32()
int32(955177040), // Int32()
int32(2020777787), // Int32()
int32(260808523), // Int32()
int32(851126509), // Int32()
int32(1682717115), // Int32()
int32(1569423431), // Int32()
int32(1092181682), // Int32()
int32(157239171), // Int32()
int32(709379364), // Int32()
int32(0), // Int32N(1)
int32(6), // Int32N(10)
int32(8), // Int32N(32)
int32(704922), // Int32N(1048576)
int32(245656), // Int32N(1048577)
int32(41205257), // Int32N(1000000000)
int32(43831929), // Int32N(1073741824)
int32(965044528), // Int32N(2147483646)
int32(285184408), // Int32N(2147483647)
int32(0), // Int32N(1)
int32(6), // Int32N(10)
int32(10), // Int32N(32)
int32(283579), // Int32N(1048576)
int32(127348), // Int32N(1048577)
int32(396336665), // Int32N(1000000000)
int32(911873403), // Int32N(1073741824)
int32(1569423430), // Int32N(2147483646)
int32(1092181681), // Int32N(2147483647)
int32(0), // Int32N(1)
int32(3), // Int32N(10)
int64(4969059760275911952), // Int64()
int64(2147869220224756844), // Int64()
int64(5246770554000605320), // Int64()
int64(5471241176507662746), // Int64()
int64(4321634407747778896), // Int64()
int64(760102831717374652), // Int64()
int64(9221744211007427193), // Int64()
int64(8289669384274456462), // Int64()
int64(2449715415482412441), // Int64()
int64(3389241988064777392), // Int64()
int64(2986830195847294191), // Int64()
int64(8204908297817606218), // Int64()
int64(8134976985547166651), // Int64()
int64(2240328155279531677), // Int64()
int64(7311121042813227358), // Int64()
int64(5231057920893523323), // Int64()
int64(4257872588489500903), // Int64()
int64(158397175702351138), // Int64()
int64(1350674201389090105), // Int64()
int64(6093522341581845358), // Int64()
int64(0), // Int64N(1)
int64(6), // Int64N(10)
int64(8), // Int64N(32)
int64(704922), // Int64N(1048576)
int64(245656), // Int64N(1048577)
int64(41205257), // Int64N(1000000000)
int64(43831929), // Int64N(1073741824)
int64(965044528), // Int64N(2147483646)
int64(285184408), // Int64N(2147483647)
int64(183731176326946086), // Int64N(1000000000000000000)
int64(680987186633600239), // Int64N(1152921504606846976)
int64(4102454148908803108), // Int64N(9223372036854775806)
int64(8679174511200971228), // Int64N(9223372036854775807)
int64(0), // Int64N(1)
int64(3), // Int64N(10)
int64(27), // Int64N(32)
int64(665831), // Int64N(1048576)
int64(533292), // Int64N(1048577)
int64(73220195), // Int64N(1000000000)
int64(686060398), // Int64N(1073741824)
int64(0), // IntN(1)
int64(6), // IntN(10)
int64(8), // IntN(32)
int64(704922), // IntN(1048576)
int64(245656), // IntN(1048577)
int64(41205257), // IntN(1000000000)
int64(43831929), // IntN(1073741824)
int64(965044528), // IntN(2147483646)
int64(285184408), // IntN(2147483647)
int64(183731176326946086), // IntN(1000000000000000000)
int64(680987186633600239), // IntN(1152921504606846976)
int64(4102454148908803108), // IntN(9223372036854775806)
int64(8679174511200971228), // IntN(9223372036854775807)
int64(0), // IntN(1)
int64(3), // IntN(10)
int64(27), // IntN(32)
int64(665831), // IntN(1048576)
int64(533292), // IntN(1048577)
int64(73220195), // IntN(1000000000)
int64(686060398), // IntN(1073741824)
float64(0.37944549835531083), // NormFloat64()
float64(0.07473804659119399), // NormFloat64()
float64(0.20006841200604142), // NormFloat64()
float64(-1.1253144115495104), // NormFloat64()
float64(-0.4005883316435388), // NormFloat64()
float64(-3.0853771402394736), // NormFloat64()
float64(1.932330243076978), // NormFloat64()
float64(1.726131393719264), // NormFloat64()
float64(-0.11707238034168332), // NormFloat64()
float64(-0.9303318111676635), // NormFloat64()
float64(-0.04750789419852852), // NormFloat64()
float64(0.22248301107582735), // NormFloat64()
float64(-1.83630520614272), // NormFloat64()
float64(0.7259521217919809), // NormFloat64()
float64(0.8806882871913041), // NormFloat64()
float64(-1.5022903484270484), // NormFloat64()
float64(0.5972577266810571), // NormFloat64()
float64(1.5631937339973658), // NormFloat64()
float64(-0.3841235370075905), // NormFloat64()
float64(-0.2967295854430667), // NormFloat64()
[]int{}, // Perm(0)
[]int{0}, // Perm(1)
[]int{1, 4, 2, 0, 3}, // Perm(5)
[]int{4, 3, 6, 1, 5, 2, 7, 0}, // Perm(8)
[]int{6, 5, 1, 8, 7, 2, 0, 3, 4}, // Perm(9)
[]int{9, 4, 2, 5, 6, 8, 1, 7, 0, 3}, // Perm(10)
[]int{5, 9, 3, 1, 4, 2, 10, 7, 15, 11, 0, 14, 13, 8, 6, 12}, // Perm(16)
[]int{}, // Perm(0)
[]int{0}, // Perm(1)
[]int{4, 2, 1, 3, 0}, // Perm(5)
[]int{0, 2, 3, 1, 5, 4, 6, 7}, // Perm(8)
[]int{2, 0, 8, 3, 4, 7, 6, 5, 1}, // Perm(9)
[]int{0, 6, 5, 3, 8, 4, 1, 2, 9, 7}, // Perm(10)
[]int{9, 14, 4, 11, 13, 8, 0, 6, 2, 12, 3, 7, 1, 10, 5, 15}, // Perm(16)
[]int{}, // Perm(0)
[]int{0}, // Perm(1)
[]int{2, 4, 0, 3, 1}, // Perm(5)
[]int{3, 2, 1, 0, 7, 5, 4, 6}, // Perm(8)
[]int{1, 3, 4, 5, 0, 2, 7, 8, 6}, // Perm(9)
[]int{1, 8, 4, 7, 2, 6, 5, 9, 0, 3}, // Perm(10)
uint32(3304433030), // Uint32()
uint32(2647573421), // Uint32()
uint32(3369092613), // Uint32()
uint32(3421356252), // Uint32()
uint32(1006208920), // Uint32()
uint32(176975231), // Uint32()
uint32(2147104640), // Uint32()
uint32(1930089058), // Uint32()
uint32(570368816), // Uint32()
uint32(789119393), // Uint32()
uint32(2842909244), // Uint32()
uint32(1910354080), // Uint32()
uint32(4041555575), // Uint32()
uint32(521617046), // Uint32()
uint32(1702253018), // Uint32()
uint32(3365434230), // Uint32()
uint32(3138846863), // Uint32()
uint32(2184363364), // Uint32()
uint32(314478343), // Uint32()
uint32(1418758728), // Uint32()
uint32(0), // Uint32N(1)
uint32(6), // Uint32N(10)
uint32(8), // Uint32N(32)
uint32(704922), // Uint32N(1048576)
uint32(245656), // Uint32N(1048577)
uint32(41205257), // Uint32N(1000000000)
uint32(43831929), // Uint32N(1073741824)
uint32(965044528), // Uint32N(2147483646)
uint32(285184408), // Uint32N(2147483647)
uint32(789119393), // Uint32N(4294967294)
uint32(2842909244), // Uint32N(4294967295)
uint32(0), // Uint32N(1)
uint32(9), // Uint32N(10)
uint32(29), // Uint32N(32)
uint32(266590), // Uint32N(1048576)
uint32(821640), // Uint32N(1048577)
uint32(730819735), // Uint32N(1000000000)
uint32(522841378), // Uint32N(1073741824)
uint32(157239171), // Uint32N(2147483646)
uint32(709379364), // Uint32N(2147483647)
uint64(14192431797130687760), // Uint64()
uint64(11371241257079532652), // Uint64()
uint64(14470142590855381128), // Uint64()
uint64(14694613213362438554), // Uint64()
uint64(4321634407747778896), // Uint64()
uint64(760102831717374652), // Uint64()
uint64(9221744211007427193), // Uint64()
uint64(8289669384274456462), // Uint64()
uint64(2449715415482412441), // Uint64()
uint64(3389241988064777392), // Uint64()
uint64(12210202232702069999), // Uint64()
uint64(8204908297817606218), // Uint64()
uint64(17358349022401942459), // Uint64()
uint64(2240328155279531677), // Uint64()
uint64(7311121042813227358), // Uint64()
uint64(14454429957748299131), // Uint64()
uint64(13481244625344276711), // Uint64()
uint64(9381769212557126946), // Uint64()
uint64(1350674201389090105), // Uint64()
uint64(6093522341581845358), // Uint64()
uint64(0), // Uint64N(1)
uint64(6), // Uint64N(10)
uint64(8), // Uint64N(32)
uint64(704922), // Uint64N(1048576)
uint64(245656), // Uint64N(1048577)
uint64(41205257), // Uint64N(1000000000)
uint64(43831929), // Uint64N(1073741824)
uint64(965044528), // Uint64N(2147483646)
uint64(285184408), // Uint64N(2147483647)
uint64(183731176326946086), // Uint64N(1000000000000000000)
uint64(680987186633600239), // Uint64N(1152921504606846976)
uint64(4102454148908803108), // Uint64N(9223372036854775806)
uint64(8679174511200971228), // Uint64N(9223372036854775807)
uint64(2240328155279531676), // Uint64N(18446744073709551614)
uint64(7311121042813227357), // Uint64N(18446744073709551615)
uint64(0), // Uint64N(1)
uint64(7), // Uint64N(10)
uint64(2), // Uint64N(32)
uint64(312633), // Uint64N(1048576)
uint64(346376), // Uint64N(1048577)
uint64(0), // UintN(1)
uint64(6), // UintN(10)
uint64(8), // UintN(32)
uint64(704922), // UintN(1048576)
uint64(245656), // UintN(1048577)
uint64(41205257), // UintN(1000000000)
uint64(43831929), // UintN(1073741824)
uint64(965044528), // UintN(2147483646)
uint64(285184408), // UintN(2147483647)
uint64(183731176326946086), // UintN(1000000000000000000)
uint64(680987186633600239), // UintN(1152921504606846976)
uint64(4102454148908803108), // UintN(9223372036854775806)
uint64(8679174511200971228), // UintN(9223372036854775807)
uint64(2240328155279531676), // UintN(18446744073709551614)
uint64(7311121042813227357), // UintN(18446744073709551615)
uint64(0), // UintN(1)
uint64(7), // UintN(10)
uint64(2), // UintN(32)
uint64(312633), // UintN(1048576)
uint64(346376), // UintN(1048577)
}