]> Cypherpunks.ru repositories - gostls13.git/commitdiff
math/rand/v2: start of new API
authorRuss Cox <rsc@golang.org>
Tue, 6 Jun 2023 12:46:45 +0000 (08:46 -0400)
committerGopher Robot <gobot@golang.org>
Mon, 30 Oct 2023 14:29:30 +0000 (14:29 +0000)
This is the beginning of the math/rand/v2 package from proposal #61716.
Start by copying old API. This CL copies math/rand/* to math/rand/v2
and updates references to math/rand to add v2 throughout.
Later CLs will make the v2 changes.

For #61716.

Change-Id: I1624ccffae3dfa442d4ba2461942decbd076e11b
Reviewed-on: https://go-review.googlesource.com/c/go/+/502495
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Russ Cox <rsc@golang.org>
Reviewed-by: Rob Pike <r@golang.org>
16 files changed:
api/next/61716.txt [new file with mode: 0644]
src/go/build/deps_test.go
src/math/rand/v2/auto_test.go [new file with mode: 0644]
src/math/rand/v2/default_test.go [new file with mode: 0644]
src/math/rand/v2/example_test.go [new file with mode: 0644]
src/math/rand/v2/exp.go [new file with mode: 0644]
src/math/rand/v2/export_test.go [new file with mode: 0644]
src/math/rand/v2/gen_cooked.go [new file with mode: 0644]
src/math/rand/v2/normal.go [new file with mode: 0644]
src/math/rand/v2/race_test.go [new file with mode: 0644]
src/math/rand/v2/rand.go [new file with mode: 0644]
src/math/rand/v2/rand_test.go [new file with mode: 0644]
src/math/rand/v2/regress_test.go [new file with mode: 0644]
src/math/rand/v2/rng.go [new file with mode: 0644]
src/math/rand/v2/zipf.go [new file with mode: 0644]
src/runtime/stubs.go

diff --git a/api/next/61716.txt b/api/next/61716.txt
new file mode 100644 (file)
index 0000000..d552934
--- /dev/null
@@ -0,0 +1,47 @@
+pkg math/rand/v2, func ExpFloat64() float64 #61716
+pkg math/rand/v2, func Float32() float32 #61716
+pkg math/rand/v2, func Float64() float64 #61716
+pkg math/rand/v2, func Int() int #61716
+pkg math/rand/v2, func Int31() int32 #61716
+pkg math/rand/v2, func Int31n(int32) int32 #61716
+pkg math/rand/v2, func Int63() int64 #61716
+pkg math/rand/v2, func Int63n(int64) int64 #61716
+pkg math/rand/v2, func Intn(int) int #61716
+pkg math/rand/v2, func New(Source) *Rand #61716
+pkg math/rand/v2, func NewSource(int64) Source #61716
+pkg math/rand/v2, func NewZipf(*Rand, float64, float64, uint64) *Zipf #61716
+pkg math/rand/v2, func NormFloat64() float64 #61716
+pkg math/rand/v2, func Perm(int) []int #61716
+pkg math/rand/v2, func Read //deprecated #61716
+pkg math/rand/v2, func Read([]uint8) (int, error) #61716
+pkg math/rand/v2, func Seed //deprecated #61716
+pkg math/rand/v2, func Seed(int64) #61716
+pkg math/rand/v2, func Shuffle(int, func(int, int)) #61716
+pkg math/rand/v2, func Uint32() uint32 #61716
+pkg math/rand/v2, func Uint64() uint64 #61716
+pkg math/rand/v2, method (*Rand) ExpFloat64() float64 #61716
+pkg math/rand/v2, method (*Rand) Float32() float32 #61716
+pkg math/rand/v2, method (*Rand) Float64() float64 #61716
+pkg math/rand/v2, method (*Rand) Int() int #61716
+pkg math/rand/v2, method (*Rand) Int31() int32 #61716
+pkg math/rand/v2, method (*Rand) Int31n(int32) int32 #61716
+pkg math/rand/v2, method (*Rand) Int63() int64 #61716
+pkg math/rand/v2, method (*Rand) Int63n(int64) int64 #61716
+pkg math/rand/v2, method (*Rand) Intn(int) int #61716
+pkg math/rand/v2, method (*Rand) NormFloat64() float64 #61716
+pkg math/rand/v2, method (*Rand) Perm(int) []int #61716
+pkg math/rand/v2, method (*Rand) Read([]uint8) (int, error) #61716
+pkg math/rand/v2, method (*Rand) Seed(int64) #61716
+pkg math/rand/v2, method (*Rand) Shuffle(int, func(int, int)) #61716
+pkg math/rand/v2, method (*Rand) Uint32() uint32 #61716
+pkg math/rand/v2, method (*Rand) Uint64() uint64 #61716
+pkg math/rand/v2, method (*Zipf) Uint64() uint64 #61716
+pkg math/rand/v2, type Rand struct #61716
+pkg math/rand/v2, type Source interface { Int63, Seed } #61716
+pkg math/rand/v2, type Source interface, Int63() int64 #61716
+pkg math/rand/v2, type Source interface, Seed(int64) #61716
+pkg math/rand/v2, type Source64 interface { Int63, Seed, Uint64 } #61716
+pkg math/rand/v2, type Source64 interface, Int63() int64 #61716
+pkg math/rand/v2, type Source64 interface, Seed(int64) #61716
+pkg math/rand/v2, type Source64 interface, Uint64() uint64 #61716
+pkg math/rand/v2, type Zipf struct #61716
index fcd5e939980f520aaeb9f026f33ed6739976cf66..a686bb78502e6a2278c651db99756fe8e5e68e72 100644 (file)
@@ -131,7 +131,7 @@ var depsRules = `
        < math/cmplx;
 
        MATH
-       < math/rand;
+       < math/rand, math/rand/v2;
 
        MATH
        < runtime/metrics;
diff --git a/src/math/rand/v2/auto_test.go b/src/math/rand/v2/auto_test.go
new file mode 100644 (file)
index 0000000..92217ab
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright 2022 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_test
+
+import (
+       . "math/rand/v2"
+       "testing"
+)
+
+// This test is first, in its own file with an alphabetically early name,
+// to try to make sure that it runs early. It has the best chance of
+// detecting deterministic seeding if it's the first test that runs.
+
+func TestAuto(t *testing.T) {
+       // Pull out 10 int64s from the global source
+       // and then check that they don't appear in that
+       // order in the deterministic Seed(1) result.
+       var out []int64
+       for i := 0; i < 10; i++ {
+               out = append(out, Int63())
+       }
+
+       // Look for out in Seed(1)'s output.
+       // Strictly speaking, we should look for them in order,
+       // but this is good enough and not significantly more
+       // likely to have a false positive.
+       Seed(1)
+       found := 0
+       for i := 0; i < 1000; i++ {
+               x := Int63()
+               if x == out[found] {
+                       found++
+                       if found == len(out) {
+                               t.Fatalf("found unseeded output in Seed(1) output")
+                       }
+               }
+       }
+}
diff --git a/src/math/rand/v2/default_test.go b/src/math/rand/v2/default_test.go
new file mode 100644 (file)
index 0000000..6b42e2e
--- /dev/null
@@ -0,0 +1,148 @@
+// Copyright 2023 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_test
+
+import (
+       "fmt"
+       "internal/race"
+       "internal/testenv"
+       . "math/rand/v2"
+       "os"
+       "runtime"
+       "strconv"
+       "sync"
+       "testing"
+)
+
+// Test that racy access to the default functions behaves reasonably.
+func TestDefaultRace(t *testing.T) {
+       // Skip the test in short mode, but even in short mode run
+       // the test if we are using the race detector, because part
+       // of this is to see whether the race detector reports any problems.
+       if testing.Short() && !race.Enabled {
+               t.Skip("skipping starting another executable in short mode")
+       }
+
+       const env = "GO_RAND_TEST_HELPER_CODE"
+       if v := os.Getenv(env); v != "" {
+               doDefaultTest(t, v)
+               return
+       }
+
+       t.Parallel()
+
+       for i := 0; i < 6; i++ {
+               i := i
+               t.Run(strconv.Itoa(i), func(t *testing.T) {
+                       t.Parallel()
+                       exe, err := os.Executable()
+                       if err != nil {
+                               exe = os.Args[0]
+                       }
+                       cmd := testenv.Command(t, exe, "-test.run=TestDefaultRace")
+                       cmd = testenv.CleanCmdEnv(cmd)
+                       cmd.Env = append(cmd.Env, fmt.Sprintf("GO_RAND_TEST_HELPER_CODE=%d", i/2))
+                       if i%2 != 0 {
+                               cmd.Env = append(cmd.Env, "GODEBUG=randautoseed=0")
+                       }
+                       out, err := cmd.CombinedOutput()
+                       if len(out) > 0 {
+                               t.Logf("%s", out)
+                       }
+                       if err != nil {
+                               t.Error(err)
+                       }
+               })
+       }
+}
+
+// doDefaultTest should be run before there have been any calls to the
+// top-level math/rand functions. Make sure that we can make concurrent
+// calls to top-level functions and to Seed without any duplicate values.
+// This will also give the race detector a change to report any problems.
+func doDefaultTest(t *testing.T, v string) {
+       code, err := strconv.Atoi(v)
+       if err != nil {
+               t.Fatalf("internal error: unrecognized code %q", v)
+       }
+
+       goroutines := runtime.GOMAXPROCS(0)
+       if goroutines < 4 {
+               goroutines = 4
+       }
+
+       ch := make(chan uint64, goroutines*3)
+       var wg sync.WaitGroup
+
+       // The various tests below should not cause race detector reports
+       // and should not produce duplicate results.
+       //
+       // Note: these tests can theoretically fail when using fastrand64
+       // in that it is possible to coincidentally get the same random
+       // number twice. That could happen something like 1 / 2**64 times,
+       // which is rare enough that it may never happen. We don't worry
+       // about that case.
+
+       switch code {
+       case 0:
+               // Call Seed and Uint64 concurrently.
+               wg.Add(goroutines)
+               for i := 0; i < goroutines; i++ {
+                       go func(s int64) {
+                               defer wg.Done()
+                               Seed(s)
+                       }(int64(i) + 100)
+               }
+               wg.Add(goroutines)
+               for i := 0; i < goroutines; i++ {
+                       go func() {
+                               defer wg.Done()
+                               ch <- Uint64()
+                       }()
+               }
+       case 1:
+               // Call Uint64 concurrently with no Seed.
+               wg.Add(goroutines)
+               for i := 0; i < goroutines; i++ {
+                       go func() {
+                               defer wg.Done()
+                               ch <- Uint64()
+                       }()
+               }
+       case 2:
+               // Start with Uint64 to pick the fast source, then call
+               // Seed and Uint64 concurrently.
+               ch <- Uint64()
+               wg.Add(goroutines)
+               for i := 0; i < goroutines; i++ {
+                       go func(s int64) {
+                               defer wg.Done()
+                               Seed(s)
+                       }(int64(i) + 100)
+               }
+               wg.Add(goroutines)
+               for i := 0; i < goroutines; i++ {
+                       go func() {
+                               defer wg.Done()
+                               ch <- Uint64()
+                       }()
+               }
+       default:
+               t.Fatalf("internal error: unrecognized code %d", code)
+       }
+
+       go func() {
+               wg.Wait()
+               close(ch)
+       }()
+
+       m := make(map[uint64]bool)
+       for i := range ch {
+               if m[i] {
+                       t.Errorf("saw %d twice", i)
+               }
+               m[i] = true
+       }
+}
diff --git a/src/math/rand/v2/example_test.go b/src/math/rand/v2/example_test.go
new file mode 100644 (file)
index 0000000..03bbe32
--- /dev/null
@@ -0,0 +1,133 @@
+// Copyright 2012 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_test
+
+import (
+       "fmt"
+       "math/rand/v2"
+       "os"
+       "strings"
+       "text/tabwriter"
+)
+
+// These tests serve as an example but also make sure we don't change
+// the output of the random number generator when given a fixed seed.
+
+func Example() {
+       answers := []string{
+               "It is certain",
+               "It is decidedly so",
+               "Without a doubt",
+               "Yes definitely",
+               "You may rely on it",
+               "As I see it yes",
+               "Most likely",
+               "Outlook good",
+               "Yes",
+               "Signs point to yes",
+               "Reply hazy try again",
+               "Ask again later",
+               "Better not tell you now",
+               "Cannot predict now",
+               "Concentrate and ask again",
+               "Don't count on it",
+               "My reply is no",
+               "My sources say no",
+               "Outlook not so good",
+               "Very doubtful",
+       }
+       fmt.Println("Magic 8-Ball says:", answers[rand.Intn(len(answers))])
+}
+
+// This example shows the use of each of the methods on a *Rand.
+// The use of the global functions is the same, without the receiver.
+func Example_rand() {
+       // Create and seed the generator.
+       // Typically a non-fixed seed should be used, such as time.Now().UnixNano().
+       // Using a fixed seed will produce the same output on every run.
+       r := rand.New(rand.NewSource(99))
+
+       // The tabwriter here helps us generate aligned output.
+       w := tabwriter.NewWriter(os.Stdout, 1, 1, 1, ' ', 0)
+       defer w.Flush()
+       show := func(name string, v1, v2, v3 any) {
+               fmt.Fprintf(w, "%s\t%v\t%v\t%v\n", name, v1, v2, v3)
+       }
+
+       // Float32 and Float64 values are in [0, 1).
+       show("Float32", r.Float32(), r.Float32(), r.Float32())
+       show("Float64", r.Float64(), r.Float64(), r.Float64())
+
+       // ExpFloat64 values have an average of 1 but decay exponentially.
+       show("ExpFloat64", r.ExpFloat64(), r.ExpFloat64(), r.ExpFloat64())
+
+       // NormFloat64 values have an average of 0 and a standard deviation of 1.
+       show("NormFloat64", r.NormFloat64(), r.NormFloat64(), r.NormFloat64())
+
+       // Int31, Int63, and Uint32 generate values of the given width.
+       // The Int method (not shown) is like either Int31 or Int63
+       // depending on the size of 'int'.
+       show("Int31", r.Int31(), r.Int31(), r.Int31())
+       show("Int63", r.Int63(), r.Int63(), r.Int63())
+       show("Uint32", r.Uint32(), r.Uint32(), r.Uint32())
+
+       // Intn, Int31n, and Int63n limit their output to be < n.
+       // They do so more carefully than using r.Int()%n.
+       show("Intn(10)", r.Intn(10), r.Intn(10), r.Intn(10))
+       show("Int31n(10)", r.Int31n(10), r.Int31n(10), r.Int31n(10))
+       show("Int63n(10)", r.Int63n(10), r.Int63n(10), r.Int63n(10))
+
+       // Perm generates a random permutation of the numbers [0, n).
+       show("Perm", r.Perm(5), r.Perm(5), r.Perm(5))
+       // Output:
+       // Float32     0.2635776           0.6358173           0.6718283
+       // Float64     0.628605430454327   0.4504798828572669  0.9562755949377957
+       // ExpFloat64  0.3362240648200941  1.4256072328483647  0.24354758816173044
+       // NormFloat64 0.17233959114940064 1.577014951434847   0.04259129641113857
+       // Int31       1501292890          1486668269          182840835
+       // Int63       3546343826724305832 5724354148158589552 5239846799706671610
+       // Uint32      2760229429          296659907           1922395059
+       // Intn(10)    1                   2                   5
+       // Int31n(10)  4                   7                   8
+       // Int63n(10)  7                   6                   3
+       // Perm        [1 4 2 3 0]         [4 2 1 3 0]         [1 2 4 0 3]
+}
+
+func ExamplePerm() {
+       for _, value := range rand.Perm(3) {
+               fmt.Println(value)
+       }
+
+       // Unordered output: 1
+       // 2
+       // 0
+}
+
+func ExampleShuffle() {
+       words := strings.Fields("ink runs from the corners of my mouth")
+       rand.Shuffle(len(words), func(i, j int) {
+               words[i], words[j] = words[j], words[i]
+       })
+       fmt.Println(words)
+}
+
+func ExampleShuffle_slicesInUnison() {
+       numbers := []byte("12345")
+       letters := []byte("ABCDE")
+       // Shuffle numbers, swapping corresponding entries in letters at the same time.
+       rand.Shuffle(len(numbers), func(i, j int) {
+               numbers[i], numbers[j] = numbers[j], numbers[i]
+               letters[i], letters[j] = letters[j], letters[i]
+       })
+       for i := range numbers {
+               fmt.Printf("%c: %c\n", letters[i], numbers[i])
+       }
+}
+
+func ExampleIntn() {
+       fmt.Println(rand.Intn(100))
+       fmt.Println(rand.Intn(100))
+       fmt.Println(rand.Intn(100))
+}
diff --git a/src/math/rand/v2/exp.go b/src/math/rand/v2/exp.go
new file mode 100644 (file)
index 0000000..c1162c1
--- /dev/null
@@ -0,0 +1,221 @@
+// 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
+
+import (
+       "math"
+)
+
+/*
+ * Exponential distribution
+ *
+ * See "The Ziggurat Method for Generating Random Variables"
+ * (Marsaglia & Tsang, 2000)
+ * https://www.jstatsoft.org/v05/i08/paper [pdf]
+ */
+
+const (
+       re = 7.69711747013104972
+)
+
+// 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).
+// To produce a distribution with a different rate parameter,
+// callers can adjust the output using:
+//
+//     sample = ExpFloat64() / desiredRateParameter
+func (r *Rand) ExpFloat64() float64 {
+       for {
+               j := r.Uint32()
+               i := j & 0xFF
+               x := float64(j) * float64(we[i])
+               if j < ke[i] {
+                       return x
+               }
+               if i == 0 {
+                       return re - math.Log(r.Float64())
+               }
+               if fe[i]+float32(r.Float64())*(fe[i-1]-fe[i]) < float32(math.Exp(-x)) {
+                       return x
+               }
+       }
+}
+
+var ke = [256]uint32{
+       0xe290a139, 0x0, 0x9beadebc, 0xc377ac71, 0xd4ddb990,
+       0xde893fb8, 0xe4a8e87c, 0xe8dff16a, 0xebf2deab, 0xee49a6e8,
+       0xf0204efd, 0xf19bdb8e, 0xf2d458bb, 0xf3da104b, 0xf4b86d78,
+       0xf577ad8a, 0xf61de83d, 0xf6afb784, 0xf730a573, 0xf7a37651,
+       0xf80a5bb6, 0xf867189d, 0xf8bb1b4f, 0xf9079062, 0xf94d70ca,
+       0xf98d8c7d, 0xf9c8928a, 0xf9ff175b, 0xfa319996, 0xfa6085f8,
+       0xfa8c3a62, 0xfab5084e, 0xfadb36c8, 0xfaff0410, 0xfb20a6ea,
+       0xfb404fb4, 0xfb5e2951, 0xfb7a59e9, 0xfb95038c, 0xfbae44ba,
+       0xfbc638d8, 0xfbdcf892, 0xfbf29a30, 0xfc0731df, 0xfc1ad1ed,
+       0xfc2d8b02, 0xfc3f6c4d, 0xfc5083ac, 0xfc60ddd1, 0xfc708662,
+       0xfc7f8810, 0xfc8decb4, 0xfc9bbd62, 0xfca9027c, 0xfcb5c3c3,
+       0xfcc20864, 0xfccdd70a, 0xfcd935e3, 0xfce42ab0, 0xfceebace,
+       0xfcf8eb3b, 0xfd02c0a0, 0xfd0c3f59, 0xfd156b7b, 0xfd1e48d6,
+       0xfd26daff, 0xfd2f2552, 0xfd372af7, 0xfd3eeee5, 0xfd4673e7,
+       0xfd4dbc9e, 0xfd54cb85, 0xfd5ba2f2, 0xfd62451b, 0xfd68b415,
+       0xfd6ef1da, 0xfd750047, 0xfd7ae120, 0xfd809612, 0xfd8620b4,
+       0xfd8b8285, 0xfd90bcf5, 0xfd95d15e, 0xfd9ac10b, 0xfd9f8d36,
+       0xfda43708, 0xfda8bf9e, 0xfdad2806, 0xfdb17141, 0xfdb59c46,
+       0xfdb9a9fd, 0xfdbd9b46, 0xfdc170f6, 0xfdc52bd8, 0xfdc8ccac,
+       0xfdcc542d, 0xfdcfc30b, 0xfdd319ef, 0xfdd6597a, 0xfdd98245,
+       0xfddc94e5, 0xfddf91e6, 0xfde279ce, 0xfde54d1f, 0xfde80c52,
+       0xfdeab7de, 0xfded5034, 0xfdefd5be, 0xfdf248e3, 0xfdf4aa06,
+       0xfdf6f984, 0xfdf937b6, 0xfdfb64f4, 0xfdfd818d, 0xfdff8dd0,
+       0xfe018a08, 0xfe03767a, 0xfe05536c, 0xfe07211c, 0xfe08dfc9,
+       0xfe0a8fab, 0xfe0c30fb, 0xfe0dc3ec, 0xfe0f48b1, 0xfe10bf76,
+       0xfe122869, 0xfe1383b4, 0xfe14d17c, 0xfe1611e7, 0xfe174516,
+       0xfe186b2a, 0xfe19843e, 0xfe1a9070, 0xfe1b8fd6, 0xfe1c8289,
+       0xfe1d689b, 0xfe1e4220, 0xfe1f0f26, 0xfe1fcfbc, 0xfe2083ed,
+       0xfe212bc3, 0xfe21c745, 0xfe225678, 0xfe22d95f, 0xfe234ffb,
+       0xfe23ba4a, 0xfe241849, 0xfe2469f2, 0xfe24af3c, 0xfe24e81e,
+       0xfe25148b, 0xfe253474, 0xfe2547c7, 0xfe254e70, 0xfe25485a,
+       0xfe25356a, 0xfe251586, 0xfe24e88f, 0xfe24ae64, 0xfe2466e1,
+       0xfe2411df, 0xfe23af34, 0xfe233eb4, 0xfe22c02c, 0xfe22336b,
+       0xfe219838, 0xfe20ee58, 0xfe20358c, 0xfe1f6d92, 0xfe1e9621,
+       0xfe1daef0, 0xfe1cb7ac, 0xfe1bb002, 0xfe1a9798, 0xfe196e0d,
+       0xfe1832fd, 0xfe16e5fe, 0xfe15869d, 0xfe141464, 0xfe128ed3,
+       0xfe10f565, 0xfe0f478c, 0xfe0d84b1, 0xfe0bac36, 0xfe09bd73,
+       0xfe07b7b5, 0xfe059a40, 0xfe03644c, 0xfe011504, 0xfdfeab88,
+       0xfdfc26e9, 0xfdf98629, 0xfdf6c83b, 0xfdf3ec01, 0xfdf0f04a,
+       0xfdedd3d1, 0xfdea953d, 0xfde7331e, 0xfde3abe9, 0xfddffdfb,
+       0xfddc2791, 0xfdd826cd, 0xfdd3f9a8, 0xfdcf9dfc, 0xfdcb1176,
+       0xfdc65198, 0xfdc15bb3, 0xfdbc2ce2, 0xfdb6c206, 0xfdb117be,
+       0xfdab2a63, 0xfda4f5fd, 0xfd9e7640, 0xfd97a67a, 0xfd908192,
+       0xfd8901f2, 0xfd812182, 0xfd78d98e, 0xfd7022bb, 0xfd66f4ed,
+       0xfd5d4732, 0xfd530f9c, 0xfd48432b, 0xfd3cd59a, 0xfd30b936,
+       0xfd23dea4, 0xfd16349e, 0xfd07a7a3, 0xfcf8219b, 0xfce7895b,
+       0xfcd5c220, 0xfcc2aadb, 0xfcae1d5e, 0xfc97ed4e, 0xfc7fe6d4,
+       0xfc65ccf3, 0xfc495762, 0xfc2a2fc8, 0xfc07ee19, 0xfbe213c1,
+       0xfbb8051a, 0xfb890078, 0xfb5411a5, 0xfb180005, 0xfad33482,
+       0xfa839276, 0xfa263b32, 0xf9b72d1c, 0xf930a1a2, 0xf889f023,
+       0xf7b577d2, 0xf69c650c, 0xf51530f0, 0xf2cb0e3c, 0xeeefb15d,
+       0xe6da6ecf,
+}
+var we = [256]float32{
+       2.0249555e-09, 1.486674e-11, 2.4409617e-11, 3.1968806e-11,
+       3.844677e-11, 4.4228204e-11, 4.9516443e-11, 5.443359e-11,
+       5.905944e-11, 6.344942e-11, 6.7643814e-11, 7.1672945e-11,
+       7.556032e-11, 7.932458e-11, 8.298079e-11, 8.654132e-11,
+       9.0016515e-11, 9.3415074e-11, 9.674443e-11, 1.0001099e-10,
+       1.03220314e-10, 1.06377254e-10, 1.09486115e-10, 1.1255068e-10,
+       1.1557435e-10, 1.1856015e-10, 1.2151083e-10, 1.2442886e-10,
+       1.2731648e-10, 1.3017575e-10, 1.3300853e-10, 1.3581657e-10,
+       1.3860142e-10, 1.4136457e-10, 1.4410738e-10, 1.4683108e-10,
+       1.4953687e-10, 1.5222583e-10, 1.54899e-10, 1.5755733e-10,
+       1.6020171e-10, 1.6283301e-10, 1.6545203e-10, 1.6805951e-10,
+       1.7065617e-10, 1.732427e-10, 1.7581973e-10, 1.7838787e-10,
+       1.8094774e-10, 1.8349985e-10, 1.8604476e-10, 1.8858298e-10,
+       1.9111498e-10, 1.9364126e-10, 1.9616223e-10, 1.9867835e-10,
+       2.0119004e-10, 2.0369768e-10, 2.0620168e-10, 2.087024e-10,
+       2.1120022e-10, 2.136955e-10, 2.1618855e-10, 2.1867974e-10,
+       2.2116936e-10, 2.2365775e-10, 2.261452e-10, 2.2863202e-10,
+       2.311185e-10, 2.3360494e-10, 2.360916e-10, 2.3857874e-10,
+       2.4106667e-10, 2.4355562e-10, 2.4604588e-10, 2.485377e-10,
+       2.5103128e-10, 2.5352695e-10, 2.560249e-10, 2.585254e-10,
+       2.6102867e-10, 2.6353494e-10, 2.6604446e-10, 2.6855745e-10,
+       2.7107416e-10, 2.7359479e-10, 2.761196e-10, 2.7864877e-10,
+       2.8118255e-10, 2.8372119e-10, 2.8626485e-10, 2.888138e-10,
+       2.9136826e-10, 2.939284e-10, 2.9649452e-10, 2.9906677e-10,
+       3.016454e-10, 3.0423064e-10, 3.0682268e-10, 3.0942177e-10,
+       3.1202813e-10, 3.1464195e-10, 3.1726352e-10, 3.19893e-10,
+       3.2253064e-10, 3.251767e-10, 3.2783135e-10, 3.3049485e-10,
+       3.3316744e-10, 3.3584938e-10, 3.3854083e-10, 3.4124212e-10,
+       3.4395342e-10, 3.46675e-10, 3.4940711e-10, 3.5215003e-10,
+       3.5490397e-10, 3.5766917e-10, 3.6044595e-10, 3.6323455e-10,
+       3.660352e-10, 3.6884823e-10, 3.7167386e-10, 3.745124e-10,
+       3.773641e-10, 3.802293e-10, 3.8310827e-10, 3.860013e-10,
+       3.8890866e-10, 3.918307e-10, 3.9476775e-10, 3.9772008e-10,
+       4.0068804e-10, 4.0367196e-10, 4.0667217e-10, 4.09689e-10,
+       4.1272286e-10, 4.1577405e-10, 4.1884296e-10, 4.2192994e-10,
+       4.250354e-10, 4.281597e-10, 4.313033e-10, 4.3446652e-10,
+       4.3764986e-10, 4.408537e-10, 4.4407847e-10, 4.4732465e-10,
+       4.5059267e-10, 4.5388301e-10, 4.571962e-10, 4.6053267e-10,
+       4.6389292e-10, 4.6727755e-10, 4.70687e-10, 4.741219e-10,
+       4.7758275e-10, 4.810702e-10, 4.845848e-10, 4.8812715e-10,
+       4.9169796e-10, 4.9529775e-10, 4.989273e-10, 5.0258725e-10,
+       5.0627835e-10, 5.100013e-10, 5.1375687e-10, 5.1754584e-10,
+       5.21369e-10, 5.2522725e-10, 5.2912136e-10, 5.330522e-10,
+       5.370208e-10, 5.4102806e-10, 5.45075e-10, 5.491625e-10,
+       5.532918e-10, 5.5746385e-10, 5.616799e-10, 5.6594107e-10,
+       5.7024857e-10, 5.746037e-10, 5.7900773e-10, 5.834621e-10,
+       5.8796823e-10, 5.925276e-10, 5.971417e-10, 6.018122e-10,
+       6.065408e-10, 6.113292e-10, 6.1617933e-10, 6.2109295e-10,
+       6.260722e-10, 6.3111916e-10, 6.3623595e-10, 6.4142497e-10,
+       6.4668854e-10, 6.5202926e-10, 6.5744976e-10, 6.6295286e-10,
+       6.6854156e-10, 6.742188e-10, 6.79988e-10, 6.858526e-10,
+       6.9181616e-10, 6.978826e-10, 7.04056e-10, 7.103407e-10,
+       7.167412e-10, 7.2326256e-10, 7.2990985e-10, 7.366886e-10,
+       7.4360473e-10, 7.5066453e-10, 7.5787476e-10, 7.6524265e-10,
+       7.7277595e-10, 7.80483e-10, 7.883728e-10, 7.9645507e-10,
+       8.047402e-10, 8.1323964e-10, 8.219657e-10, 8.309319e-10,
+       8.401528e-10, 8.496445e-10, 8.594247e-10, 8.6951274e-10,
+       8.799301e-10, 8.9070046e-10, 9.018503e-10, 9.134092e-10,
+       9.254101e-10, 9.378904e-10, 9.508923e-10, 9.644638e-10,
+       9.786603e-10, 9.935448e-10, 1.0091913e-09, 1.025686e-09,
+       1.0431306e-09, 1.0616465e-09, 1.08138e-09, 1.1025096e-09,
+       1.1252564e-09, 1.1498986e-09, 1.1767932e-09, 1.206409e-09,
+       1.2393786e-09, 1.276585e-09, 1.3193139e-09, 1.3695435e-09,
+       1.4305498e-09, 1.508365e-09, 1.6160854e-09, 1.7921248e-09,
+}
+var fe = [256]float32{
+       1, 0.9381437, 0.90046996, 0.87170434, 0.8477855, 0.8269933,
+       0.8084217, 0.7915276, 0.77595687, 0.7614634, 0.7478686,
+       0.7350381, 0.72286767, 0.71127474, 0.70019263, 0.6895665,
+       0.67935055, 0.6695063, 0.66000086, 0.65080583, 0.6418967,
+       0.63325197, 0.6248527, 0.6166822, 0.60872537, 0.60096896,
+       0.5934009, 0.58601034, 0.5787874, 0.57172304, 0.5648092,
+       0.5580383, 0.5514034, 0.5448982, 0.5385169, 0.53225386,
+       0.5261042, 0.52006316, 0.5141264, 0.50828975, 0.5025495,
+       0.496902, 0.49134386, 0.485872, 0.48048335, 0.4751752,
+       0.46994483, 0.46478975, 0.45970762, 0.45469615, 0.44975325,
+       0.44487688, 0.44006512, 0.43531612, 0.43062815, 0.42599955,
+       0.42142874, 0.4169142, 0.41245446, 0.40804818, 0.403694,
+       0.3993907, 0.39513698, 0.39093173, 0.38677382, 0.38266218,
+       0.37859577, 0.37457356, 0.37059465, 0.3666581, 0.362763,
+       0.35890847, 0.35509375, 0.351318, 0.3475805, 0.34388044,
+       0.34021714, 0.3365899, 0.33299807, 0.32944095, 0.32591796,
+       0.3224285, 0.3189719, 0.31554767, 0.31215525, 0.30879408,
+       0.3054636, 0.3021634, 0.29889292, 0.2956517, 0.29243928,
+       0.28925523, 0.28609908, 0.28297043, 0.27986884, 0.27679393,
+       0.2737453, 0.2707226, 0.2677254, 0.26475343, 0.26180625,
+       0.25888354, 0.25598502, 0.2531103, 0.25025907, 0.24743107,
+       0.24462597, 0.24184346, 0.23908329, 0.23634516, 0.23362878,
+       0.23093392, 0.2282603, 0.22560766, 0.22297576, 0.22036438,
+       0.21777324, 0.21520215, 0.21265087, 0.21011916, 0.20760682,
+       0.20511365, 0.20263945, 0.20018397, 0.19774707, 0.19532852,
+       0.19292815, 0.19054577, 0.1881812, 0.18583426, 0.18350479,
+       0.1811926, 0.17889754, 0.17661946, 0.17435817, 0.17211354,
+       0.1698854, 0.16767362, 0.16547804, 0.16329853, 0.16113494,
+       0.15898713, 0.15685499, 0.15473837, 0.15263714, 0.15055119,
+       0.14848037, 0.14642459, 0.14438373, 0.14235765, 0.14034624,
+       0.13834943, 0.13636707, 0.13439907, 0.13244532, 0.13050574,
+       0.1285802, 0.12666863, 0.12477092, 0.12288698, 0.12101672,
+       0.119160056, 0.1173169, 0.115487166, 0.11367077, 0.11186763,
+       0.11007768, 0.10830083, 0.10653701, 0.10478614, 0.10304816,
+       0.101323, 0.09961058, 0.09791085, 0.09622374, 0.09454919,
+       0.09288713, 0.091237515, 0.08960028, 0.087975375, 0.08636274,
+       0.08476233, 0.083174095, 0.081597984, 0.08003395, 0.07848195,
+       0.076941945, 0.07541389, 0.07389775, 0.072393484, 0.07090106,
+       0.069420435, 0.06795159, 0.066494495, 0.06504912, 0.063615434,
+       0.062193416, 0.060783047, 0.059384305, 0.057997175,
+       0.05662164, 0.05525769, 0.053905312, 0.052564494, 0.051235236,
+       0.049917534, 0.048611384, 0.047316793, 0.046033762, 0.0447623,
+       0.043502413, 0.042254124, 0.041017443, 0.039792392,
+       0.038578995, 0.037377283, 0.036187284, 0.035009038,
+       0.033842582, 0.032687962, 0.031545233, 0.030414443, 0.02929566,
+       0.02818895, 0.027094385, 0.026012046, 0.024942026, 0.023884421,
+       0.022839336, 0.021806888, 0.020787204, 0.019780423, 0.0187867,
+       0.0178062, 0.016839107, 0.015885621, 0.014945968, 0.014020392,
+       0.013109165, 0.012212592, 0.011331013, 0.01046481, 0.009614414,
+       0.008780315, 0.007963077, 0.0071633533, 0.006381906,
+       0.0056196423, 0.0048776558, 0.004157295, 0.0034602648,
+       0.0027887989, 0.0021459677, 0.0015362998, 0.0009672693,
+       0.00045413437,
+}
diff --git a/src/math/rand/v2/export_test.go b/src/math/rand/v2/export_test.go
new file mode 100644 (file)
index 0000000..560010b
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2021 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
+
+func Int31nForTest(r *Rand, n int32) int32 {
+       return r.int31n(n)
+}
+
+func GetNormalDistributionParameters() (float64, [128]uint32, [128]float32, [128]float32) {
+       return rn, kn, wn, fn
+}
+
+func GetExponentialDistributionParameters() (float64, [256]uint32, [256]float32, [256]float32) {
+       return re, ke, we, fe
+}
diff --git a/src/math/rand/v2/gen_cooked.go b/src/math/rand/v2/gen_cooked.go
new file mode 100644 (file)
index 0000000..782bb66
--- /dev/null
@@ -0,0 +1,89 @@
+// 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.
+
+//go:build ignore
+
+// This program computes the value of rngCooked in rng.go,
+// which is used for seeding all instances of rand.Source.
+// a 64bit and a 63bit version of the array is printed to
+// the standard output.
+
+package main
+
+import "fmt"
+
+const (
+       length = 607
+       tap    = 273
+       mask   = (1 << 63) - 1
+       a      = 48271
+       m      = (1 << 31) - 1
+       q      = 44488
+       r      = 3399
+)
+
+var (
+       rngVec          [length]int64
+       rngTap, rngFeed int
+)
+
+func seedrand(x int32) int32 {
+       hi := x / q
+       lo := x % q
+       x = a*lo - r*hi
+       if x < 0 {
+               x += m
+       }
+       return x
+}
+
+func srand(seed int32) {
+       rngTap = 0
+       rngFeed = length - tap
+       seed %= m
+       if seed < 0 {
+               seed += m
+       } else if seed == 0 {
+               seed = 89482311
+       }
+       x := seed
+       for i := -20; i < length; i++ {
+               x = seedrand(x)
+               if i >= 0 {
+                       var u int64
+                       u = int64(x) << 20
+                       x = seedrand(x)
+                       u ^= int64(x) << 10
+                       x = seedrand(x)
+                       u ^= int64(x)
+                       rngVec[i] = u
+               }
+       }
+}
+
+func vrand() int64 {
+       rngTap--
+       if rngTap < 0 {
+               rngTap += length
+       }
+       rngFeed--
+       if rngFeed < 0 {
+               rngFeed += length
+       }
+       x := (rngVec[rngFeed] + rngVec[rngTap])
+       rngVec[rngFeed] = x
+       return x
+}
+
+func main() {
+       srand(1)
+       for i := uint64(0); i < 7.8e12; i++ {
+               vrand()
+       }
+       fmt.Printf("rngVec after 7.8e12 calls to vrand:\n%#v\n", rngVec)
+       for i := range rngVec {
+               rngVec[i] &= mask
+       }
+       fmt.Printf("lower 63bit of rngVec after 7.8e12 calls to vrand:\n%#v\n", rngVec)
+}
diff --git a/src/math/rand/v2/normal.go b/src/math/rand/v2/normal.go
new file mode 100644 (file)
index 0000000..6654479
--- /dev/null
@@ -0,0 +1,156 @@
+// 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
+
+import (
+       "math"
+)
+
+/*
+ * Normal distribution
+ *
+ * See "The Ziggurat Method for Generating Random Variables"
+ * (Marsaglia & Tsang, 2000)
+ * http://www.jstatsoft.org/v05/i08/paper [pdf]
+ */
+
+const (
+       rn = 3.442619855899
+)
+
+func absInt32(i int32) uint32 {
+       if i < 0 {
+               return uint32(-i)
+       }
+       return uint32(i)
+}
+
+// NormFloat64 returns a normally distributed float64 in
+// the range -math.MaxFloat64 through +math.MaxFloat64 inclusive,
+// with standard normal distribution (mean = 0, stddev = 1).
+// To produce a different normal distribution, callers can
+// adjust the output using:
+//
+//     sample = NormFloat64() * desiredStdDev + desiredMean
+func (r *Rand) NormFloat64() float64 {
+       for {
+               j := int32(r.Uint32()) // Possibly negative
+               i := j & 0x7F
+               x := float64(j) * float64(wn[i])
+               if absInt32(j) < kn[i] {
+                       // This case should be hit better than 99% of the time.
+                       return x
+               }
+
+               if i == 0 {
+                       // This extra work is only required for the base strip.
+                       for {
+                               x = -math.Log(r.Float64()) * (1.0 / rn)
+                               y := -math.Log(r.Float64())
+                               if y+y >= x*x {
+                                       break
+                               }
+                       }
+                       if j > 0 {
+                               return rn + x
+                       }
+                       return -rn - x
+               }
+               if fn[i]+float32(r.Float64())*(fn[i-1]-fn[i]) < float32(math.Exp(-.5*x*x)) {
+                       return x
+               }
+       }
+}
+
+var kn = [128]uint32{
+       0x76ad2212, 0x0, 0x600f1b53, 0x6ce447a6, 0x725b46a2,
+       0x7560051d, 0x774921eb, 0x789a25bd, 0x799045c3, 0x7a4bce5d,
+       0x7adf629f, 0x7b5682a6, 0x7bb8a8c6, 0x7c0ae722, 0x7c50cce7,
+       0x7c8cec5b, 0x7cc12cd6, 0x7ceefed2, 0x7d177e0b, 0x7d3b8883,
+       0x7d5bce6c, 0x7d78dd64, 0x7d932886, 0x7dab0e57, 0x7dc0dd30,
+       0x7dd4d688, 0x7de73185, 0x7df81cea, 0x7e07c0a3, 0x7e163efa,
+       0x7e23b587, 0x7e303dfd, 0x7e3beec2, 0x7e46db77, 0x7e51155d,
+       0x7e5aabb3, 0x7e63abf7, 0x7e6c222c, 0x7e741906, 0x7e7b9a18,
+       0x7e82adfa, 0x7e895c63, 0x7e8fac4b, 0x7e95a3fb, 0x7e9b4924,
+       0x7ea0a0ef, 0x7ea5b00d, 0x7eaa7ac3, 0x7eaf04f3, 0x7eb3522a,
+       0x7eb765a5, 0x7ebb4259, 0x7ebeeafd, 0x7ec2620a, 0x7ec5a9c4,
+       0x7ec8c441, 0x7ecbb365, 0x7ece78ed, 0x7ed11671, 0x7ed38d62,
+       0x7ed5df12, 0x7ed80cb4, 0x7eda175c, 0x7edc0005, 0x7eddc78e,
+       0x7edf6ebf, 0x7ee0f647, 0x7ee25ebe, 0x7ee3a8a9, 0x7ee4d473,
+       0x7ee5e276, 0x7ee6d2f5, 0x7ee7a620, 0x7ee85c10, 0x7ee8f4cd,
+       0x7ee97047, 0x7ee9ce59, 0x7eea0eca, 0x7eea3147, 0x7eea3568,
+       0x7eea1aab, 0x7ee9e071, 0x7ee98602, 0x7ee90a88, 0x7ee86d08,
+       0x7ee7ac6a, 0x7ee6c769, 0x7ee5bc9c, 0x7ee48a67, 0x7ee32efc,
+       0x7ee1a857, 0x7edff42f, 0x7ede0ffa, 0x7edbf8d9, 0x7ed9ab94,
+       0x7ed7248d, 0x7ed45fae, 0x7ed1585c, 0x7ece095f, 0x7eca6ccb,
+       0x7ec67be2, 0x7ec22eee, 0x7ebd7d1a, 0x7eb85c35, 0x7eb2c075,
+       0x7eac9c20, 0x7ea5df27, 0x7e9e769f, 0x7e964c16, 0x7e8d44ba,
+       0x7e834033, 0x7e781728, 0x7e6b9933, 0x7e5d8a1a, 0x7e4d9ded,
+       0x7e3b737a, 0x7e268c2f, 0x7e0e3ff5, 0x7df1aa5d, 0x7dcf8c72,
+       0x7da61a1e, 0x7d72a0fb, 0x7d30e097, 0x7cd9b4ab, 0x7c600f1a,
+       0x7ba90bdc, 0x7a722176, 0x77d664e5,
+}
+var wn = [128]float32{
+       1.7290405e-09, 1.2680929e-10, 1.6897518e-10, 1.9862688e-10,
+       2.2232431e-10, 2.4244937e-10, 2.601613e-10, 2.7611988e-10,
+       2.9073963e-10, 3.042997e-10, 3.1699796e-10, 3.289802e-10,
+       3.4035738e-10, 3.5121603e-10, 3.616251e-10, 3.7164058e-10,
+       3.8130857e-10, 3.9066758e-10, 3.9975012e-10, 4.08584e-10,
+       4.1719309e-10, 4.2559822e-10, 4.338176e-10, 4.418672e-10,
+       4.497613e-10, 4.5751258e-10, 4.651324e-10, 4.7263105e-10,
+       4.8001775e-10, 4.87301e-10, 4.944885e-10, 5.015873e-10,
+       5.0860405e-10, 5.155446e-10, 5.2241467e-10, 5.2921934e-10,
+       5.359635e-10, 5.426517e-10, 5.4928817e-10, 5.5587696e-10,
+       5.624219e-10, 5.6892646e-10, 5.753941e-10, 5.818282e-10,
+       5.882317e-10, 5.946077e-10, 6.00959e-10, 6.072884e-10,
+       6.135985e-10, 6.19892e-10, 6.2617134e-10, 6.3243905e-10,
+       6.386974e-10, 6.449488e-10, 6.511956e-10, 6.5744005e-10,
+       6.6368433e-10, 6.699307e-10, 6.7618144e-10, 6.824387e-10,
+       6.8870465e-10, 6.949815e-10, 7.012715e-10, 7.075768e-10,
+       7.1389966e-10, 7.202424e-10, 7.266073e-10, 7.329966e-10,
+       7.394128e-10, 7.4585826e-10, 7.5233547e-10, 7.58847e-10,
+       7.653954e-10, 7.719835e-10, 7.7861395e-10, 7.852897e-10,
+       7.920138e-10, 7.987892e-10, 8.0561924e-10, 8.125073e-10,
+       8.194569e-10, 8.2647167e-10, 8.3355556e-10, 8.407127e-10,
+       8.479473e-10, 8.55264e-10, 8.6266755e-10, 8.7016316e-10,
+       8.777562e-10, 8.8545243e-10, 8.932582e-10, 9.0117996e-10,
+       9.09225e-10, 9.174008e-10, 9.2571584e-10, 9.341788e-10,
+       9.427997e-10, 9.515889e-10, 9.605579e-10, 9.697193e-10,
+       9.790869e-10, 9.88676e-10, 9.985036e-10, 1.0085882e-09,
+       1.0189509e-09, 1.0296151e-09, 1.0406069e-09, 1.0519566e-09,
+       1.063698e-09, 1.0758702e-09, 1.0885183e-09, 1.1016947e-09,
+       1.1154611e-09, 1.1298902e-09, 1.1450696e-09, 1.1611052e-09,
+       1.1781276e-09, 1.1962995e-09, 1.2158287e-09, 1.2369856e-09,
+       1.2601323e-09, 1.2857697e-09, 1.3146202e-09, 1.347784e-09,
+       1.3870636e-09, 1.4357403e-09, 1.5008659e-09, 1.6030948e-09,
+}
+var fn = [128]float32{
+       1, 0.9635997, 0.9362827, 0.9130436, 0.89228165, 0.87324303,
+       0.8555006, 0.8387836, 0.8229072, 0.8077383, 0.793177,
+       0.7791461, 0.7655842, 0.7524416, 0.73967725, 0.7272569,
+       0.7151515, 0.7033361, 0.69178915, 0.68049186, 0.6694277,
+       0.658582, 0.6479418, 0.63749546, 0.6272325, 0.6171434,
+       0.6072195, 0.5974532, 0.58783704, 0.5783647, 0.56903,
+       0.5598274, 0.5507518, 0.54179835, 0.5329627, 0.52424055,
+       0.5156282, 0.50712204, 0.49871865, 0.49041483, 0.48220766,
+       0.4740943, 0.46607214, 0.4581387, 0.45029163, 0.44252872,
+       0.43484783, 0.427247, 0.41972435, 0.41227803, 0.40490642,
+       0.39760786, 0.3903808, 0.3832238, 0.37613547, 0.36911446,
+       0.3621595, 0.35526937, 0.34844297, 0.34167916, 0.33497685,
+       0.3283351, 0.3217529, 0.3152294, 0.30876362, 0.30235484,
+       0.29600215, 0.28970486, 0.2834622, 0.2772735, 0.27113807,
+       0.2650553, 0.25902456, 0.2530453, 0.24711695, 0.241239,
+       0.23541094, 0.22963232, 0.2239027, 0.21822165, 0.21258877,
+       0.20700371, 0.20146611, 0.19597565, 0.19053204, 0.18513499,
+       0.17978427, 0.17447963, 0.1692209, 0.16400786, 0.15884037,
+       0.15371831, 0.14864157, 0.14361008, 0.13862377, 0.13368265,
+       0.12878671, 0.12393598, 0.119130544, 0.11437051, 0.10965602,
+       0.104987256, 0.10036444, 0.095787846, 0.0912578, 0.08677467,
+       0.0823389, 0.077950984, 0.073611505, 0.06932112, 0.06508058,
+       0.06089077, 0.056752663, 0.0526674, 0.048636295, 0.044660863,
+       0.040742867, 0.03688439, 0.033087887, 0.029356318,
+       0.025693292, 0.022103304, 0.018592102, 0.015167298,
+       0.011839478, 0.008624485, 0.005548995, 0.0026696292,
+}
diff --git a/src/math/rand/v2/race_test.go b/src/math/rand/v2/race_test.go
new file mode 100644 (file)
index 0000000..d164e7b
--- /dev/null
@@ -0,0 +1,49 @@
+// Copyright 2016 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_test
+
+import (
+       . "math/rand/v2"
+       "sync"
+       "testing"
+)
+
+// TestConcurrent exercises the rand API concurrently, triggering situations
+// where the race detector is likely to detect issues.
+func TestConcurrent(t *testing.T) {
+       const (
+               numRoutines = 10
+               numCycles   = 10
+       )
+       var wg sync.WaitGroup
+       defer wg.Wait()
+       wg.Add(numRoutines)
+       for i := 0; i < numRoutines; i++ {
+               go func(i int) {
+                       defer wg.Done()
+                       buf := make([]byte, 997)
+                       for j := 0; j < numCycles; j++ {
+                               var seed int64
+                               seed += int64(ExpFloat64())
+                               seed += int64(Float32())
+                               seed += int64(Float64())
+                               seed += int64(Intn(Int()))
+                               seed += int64(Int31n(Int31()))
+                               seed += int64(Int63n(Int63()))
+                               seed += int64(NormFloat64())
+                               seed += int64(Uint32())
+                               seed += int64(Uint64())
+                               for _, p := range Perm(10) {
+                                       seed += int64(p)
+                               }
+                               Read(buf)
+                               for _, b := range buf {
+                                       seed += int64(b)
+                               }
+                               Seed(int64(i*j) * seed)
+                       }
+               }(i)
+       }
+}
diff --git a/src/math/rand/v2/rand.go b/src/math/rand/v2/rand.go
new file mode 100644 (file)
index 0000000..8979f68
--- /dev/null
@@ -0,0 +1,547 @@
+// 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 (
+       "internal/godebug"
+       "sync"
+       "sync/atomic"
+       _ "unsafe" // for go:linkname
+)
+
+// A Source represents a source of uniformly-distributed
+// pseudo-random int64 values in the range [0, 1<<63).
+//
+// A Source is not safe for concurrent use by multiple goroutines.
+type Source interface {
+       Int63() int64
+       Seed(seed int64)
+}
+
+// A Source64 is a Source that can also generate
+// uniformly-distributed pseudo-random uint64 values in
+// the range [0, 1<<64) directly.
+// If a Rand r's underlying Source s implements Source64,
+// then r.Uint64 returns the result of one call to s.Uint64
+// instead of making two calls to s.Int63.
+type Source64 interface {
+       Source
+       Uint64() uint64
+}
+
+// NewSource returns a new pseudo-random Source seeded with the given value.
+// Unlike the default Source used by top-level functions, this source is not
+// safe for concurrent use by multiple goroutines.
+// The returned Source implements Source64.
+func NewSource(seed int64) Source {
+       return newSource(seed)
+}
+
+func newSource(seed int64) *rngSource {
+       var rng rngSource
+       rng.Seed(seed)
+       return &rng
+}
+
+// A Rand is a source of random numbers.
+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
+// to generate other random values.
+func New(src Source) *Rand {
+       s64, _ := src.(Source64)
+       return &Rand{src: src, s64: s64}
+}
+
+// Seed uses the provided seed value to initialize the generator to a deterministic state.
+// 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)
+               return
+       }
+
+       r.src.Seed(seed)
+       r.readPos = 0
+}
+
+// Int63 returns a non-negative pseudo-random 63-bit integer as an int64.
+func (r *Rand) Int63() int64 { return r.src.Int63() }
+
+// Uint32 returns a pseudo-random 32-bit value as a uint32.
+func (r *Rand) Uint32() uint32 { return uint32(r.Int63() >> 31) }
+
+// Uint64 returns a pseudo-random 64-bit value as a uint64.
+func (r *Rand) Uint64() uint64 {
+       if r.s64 != nil {
+               return r.s64.Uint64()
+       }
+       return uint64(r.Int63())>>31 | uint64(r.Int63())<<32
+}
+
+// Int31 returns a non-negative pseudo-random 31-bit integer as an int32.
+func (r *Rand) Int31() int32 { return int32(r.Int63() >> 32) }
+
+// Int returns a non-negative pseudo-random int.
+func (r *Rand) Int() int {
+       u := uint(r.Int63())
+       return int(u << 1 >> 1) // clear sign bit if int == int32
+}
+
+// Int63n 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) Int63n(n int64) int64 {
+       if n <= 0 {
+               panic("invalid argument to Int63n")
+       }
+       if n&(n-1) == 0 { // n is power of two, can mask
+               return r.Int63() & (n - 1)
+       }
+       max := int64((1 << 63) - 1 - (1<<63)%uint64(n))
+       v := r.Int63()
+       for v > max {
+               v = r.Int63()
+       }
+       return v % n
+}
+
+// Int31n 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) Int31n(n int32) int32 {
+       if n <= 0 {
+               panic("invalid argument to Int31n")
+       }
+       if n&(n-1) == 0 { // n is power of two, can mask
+               return r.Int31() & (n - 1)
+       }
+       max := int32((1 << 31) - 1 - (1<<31)%uint32(n))
+       v := r.Int31()
+       for v > max {
+               v = r.Int31()
+       }
+       return v % n
+}
+
+// int31n returns, as an int32, a non-negative pseudo-random number in the half-open interval [0,n).
+// n must be > 0, but int31n does not check this; the caller must ensure it.
+// int31n exists because Int31n is inefficient, but Go 1 compatibility
+// requires that the stream of values produced by math/rand/v2 remain unchanged.
+// int31n can thus only be used internally, by newly introduced APIs.
+//
+// For implementation details, see:
+// https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction
+// https://lemire.me/blog/2016/06/30/fast-random-shuffling
+func (r *Rand) int31n(n int32) int32 {
+       v := r.Uint32()
+       prod := uint64(v) * uint64(n)
+       low := uint32(prod)
+       if low < uint32(n) {
+               thresh := uint32(-n) % uint32(n)
+               for low < thresh {
+                       v = r.Uint32()
+                       prod = uint64(v) * uint64(n)
+                       low = uint32(prod)
+               }
+       }
+       return int32(prod >> 32)
+}
+
+// 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")
+       }
+       if n <= 1<<31-1 {
+               return int(r.Int31n(int32(n)))
+       }
+       return int(r.Int63n(int64(n)))
+}
+
+// Float64 returns, as a float64, a pseudo-random number in the half-open interval [0.0,1.0).
+func (r *Rand) Float64() float64 {
+       // A clearer, simpler implementation would be:
+       //      return float64(r.Int63n(1<<53)) / (1<<53)
+       // However, Go 1 shipped with
+       //      return float64(r.Int63()) / (1 << 63)
+       // and we want to preserve that value stream.
+       //
+       // There is one bug in the value stream: r.Int63() may be so close
+       // to 1<<63 that the division rounds up to 1.0, and we've guaranteed
+       // that the result is always less than 1.0.
+       //
+       // We tried to fix this by mapping 1.0 back to 0.0, but since float64
+       // values near 0 are much denser than near 1, mapping 1 to 0 caused
+       // a theoretically significant overshoot in the probability of returning 0.
+       // Instead of that, if we round up to 1, just try again.
+       // Getting 1 only happens 1/2⁵³ of the time, so most clients
+       // will not observe it anyway.
+again:
+       f := float64(r.Int63()) / (1 << 63)
+       if f == 1 {
+               goto again // resample; this branch is taken O(never)
+       }
+       return f
+}
+
+// Float32 returns, as a float32, a pseudo-random number in the half-open interval [0.0,1.0).
+func (r *Rand) Float32() float32 {
+       // Same rationale as in Float64: we want to preserve the Go 1 value
+       // stream except we want to fix it not to return 1.0
+       // This only happens 1/2²⁴ of the time (plus the 1/2⁵³ of the time in Float64).
+again:
+       f := float32(r.Float64())
+       if f == 1 {
+               goto again // resample; this branch is taken O(very rarely)
+       }
+       return f
+}
+
+// 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 {
+       m := make([]int, n)
+       // In the following loop, the iteration when i=0 always swaps m[0] with m[0].
+       // A change to remove this useless iteration is to assign 1 to i in the init
+       // statement. But Perm also effects r. Making this change will affect
+       // the final state of r. So this change can't be made for compatibility
+       // reasons for Go 1.
+       for i := 0; i < n; i++ {
+               j := r.Intn(i + 1)
+               m[i] = m[j]
+               m[j] = i
+       }
+       return m
+}
+
+// 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.
+       i := n - 1
+       for ; i > 1<<31-1-1; i-- {
+               j := int(r.Int63n(int64(i + 1)))
+               swap(i, j)
+       }
+       for ; i > 0; i-- {
+               j := int(r.int31n(int32(i + 1)))
+               swap(i, j)
+       }
+}
+
+// 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.Int63()
+                       } else {
+                               val = src.Int63()
+                       }
+                       pos = 7
+               }
+               p[n] = byte(val)
+               val >>= 8
+               pos--
+       }
+       *readPos = pos
+       *readVal = val
+       return
+}
+
+/*
+ * Top-level convenience functions
+ */
+
+// globalRandGenerator is the source of random numbers for the top-level
+// convenience functions. When possible it uses the runtime fastrand64
+// function to avoid locking. This is not possible if the user called Seed,
+// either explicitly or implicitly via GODEBUG=randautoseed=0.
+var globalRandGenerator atomic.Pointer[Rand]
+
+var randautoseed = godebug.New("randautoseed")
+
+// globalRand returns the generator to use for the top-level convenience
+// functions.
+func globalRand() *Rand {
+       if r := globalRandGenerator.Load(); r != nil {
+               return r
+       }
+
+       // This is the first call. Initialize based on GODEBUG.
+       var r *Rand
+       if randautoseed.Value() == "0" {
+               randautoseed.IncNonDefault()
+               r = New(new(lockedSource))
+               r.Seed(1)
+       } else {
+               r = &Rand{
+                       src: &fastSource{},
+                       s64: &fastSource{},
+               }
+       }
+
+       if !globalRandGenerator.CompareAndSwap(nil, r) {
+               // Two different goroutines called some top-level
+               // function at the same time. While the results in
+               // that case are unpredictable, if we just use r here,
+               // and we are using a seed, we will most likely return
+               // the same value for both calls. That doesn't seem ideal.
+               // Just use the first one to get in.
+               return globalRandGenerator.Load()
+       }
+
+       return r
+}
+
+//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
+}
+
+func (*fastSource) Int63() int64 {
+       return int64(fastrand64() & rngMask)
+}
+
+func (*fastSource) Seed(int64) {
+       panic("internal error: call to fastSource.Seed")
+}
+
+func (*fastSource) Uint64() uint64 {
+       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.
+// Seed, unlike the Rand.Seed method, is safe for concurrent use.
+//
+// If Seed is not called, the generator is seeded randomly at program startup.
+//
+// Prior to Go 1.20, the generator was seeded like Seed(1) at program startup.
+// To force the old behavior, call Seed(1) at program startup.
+// Alternately, set GODEBUG=randautoseed=0 in the environment
+// before making any calls to functions in this package.
+//
+// Deprecated: As of Go 1.20 there is no reason to call Seed with
+// a random value. Programs that call Seed with a known value to get
+// a specific sequence of results should use New(NewSource(seed)) to
+// obtain a local random generator.
+func Seed(seed int64) {
+       orig := globalRandGenerator.Load()
+
+       // If we are already using a lockedSource, we can just re-seed it.
+       if orig != nil {
+               if _, ok := orig.src.(*lockedSource); ok {
+                       orig.Seed(seed)
+                       return
+               }
+       }
+
+       // Otherwise either
+       // 1) orig == nil, which is the normal case when Seed is the first
+       // top-level function to be called, or
+       // 2) orig is already a fastSource, in which case we need to change
+       // to a lockedSource.
+       // Either way we do the same thing.
+
+       r := New(new(lockedSource))
+       r.Seed(seed)
+
+       if !globalRandGenerator.CompareAndSwap(orig, r) {
+               // Something changed underfoot. Retry to be safe.
+               Seed(seed)
+       }
+}
+
+// Int63 returns a non-negative pseudo-random 63-bit integer as an int64
+// from the default Source.
+func Int63() int64 { return globalRand().Int63() }
+
+// Uint32 returns a pseudo-random 32-bit value as a uint32
+// from the default Source.
+func Uint32() uint32 { return globalRand().Uint32() }
+
+// Uint64 returns a pseudo-random 64-bit value as a uint64
+// from the default Source.
+func Uint64() uint64 { return globalRand().Uint64() }
+
+// Int31 returns a non-negative pseudo-random 31-bit integer as an int32
+// from the default Source.
+func Int31() int32 { return globalRand().Int31() }
+
+// Int returns a non-negative pseudo-random int from the default Source.
+func Int() int { return globalRand().Int() }
+
+// Int63n returns, as an int64, a non-negative pseudo-random number in the half-open interval [0,n)
+// from the default Source.
+// It panics if n <= 0.
+func Int63n(n int64) int64 { return globalRand().Int63n(n) }
+
+// Int31n returns, as an int32, a non-negative pseudo-random number in the half-open interval [0,n)
+// from the default Source.
+// It panics if n <= 0.
+func Int31n(n int32) int32 { return globalRand().Int31n(n) }
+
+// Intn returns, as an int, a non-negative 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) }
+
+// 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) }
+
+// 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)
+// 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() }
+
+type lockedSource struct {
+       lk sync.Mutex
+       s  *rngSource
+}
+
+func (r *lockedSource) Int63() (n int64) {
+       r.lk.Lock()
+       n = r.s.Int63()
+       r.lk.Unlock()
+       return
+}
+
+func (r *lockedSource) Uint64() (n uint64) {
+       r.lk.Lock()
+       n = r.s.Uint64()
+       r.lk.Unlock()
+       return
+}
+
+func (r *lockedSource) Seed(seed int64) {
+       r.lk.Lock()
+       r.seed(seed)
+       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) {
+       if r.s == nil {
+               r.s = newSource(seed)
+       } else {
+               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
+}
diff --git a/src/math/rand/v2/rand_test.go b/src/math/rand/v2/rand_test.go
new file mode 100644 (file)
index 0000000..2736871
--- /dev/null
@@ -0,0 +1,701 @@
+// 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_test
+
+import (
+       "bytes"
+       "errors"
+       "fmt"
+       "internal/testenv"
+       "io"
+       "math"
+       . "math/rand/v2"
+       "os"
+       "runtime"
+       "sync"
+       "testing"
+       "testing/iotest"
+)
+
+const (
+       numTestSamples = 10000
+)
+
+var rn, kn, wn, fn = GetNormalDistributionParameters()
+var re, ke, we, fe = GetExponentialDistributionParameters()
+
+type statsResults struct {
+       mean        float64
+       stddev      float64
+       closeEnough float64
+       maxError    float64
+}
+
+func max(a, b float64) float64 {
+       if a > b {
+               return a
+       }
+       return b
+}
+
+func nearEqual(a, b, closeEnough, maxError float64) bool {
+       absDiff := math.Abs(a - b)
+       if absDiff < closeEnough { // Necessary when one value is zero and one value is close to zero.
+               return true
+       }
+       return absDiff/max(math.Abs(a), math.Abs(b)) < maxError
+}
+
+var testSeeds = []int64{1, 1754801282, 1698661970, 1550503961}
+
+// checkSimilarDistribution returns success if the mean and stddev of the
+// two statsResults are similar.
+func (this *statsResults) checkSimilarDistribution(expected *statsResults) error {
+       if !nearEqual(this.mean, expected.mean, expected.closeEnough, expected.maxError) {
+               s := fmt.Sprintf("mean %v != %v (allowed error %v, %v)", this.mean, expected.mean, expected.closeEnough, expected.maxError)
+               fmt.Println(s)
+               return errors.New(s)
+       }
+       if !nearEqual(this.stddev, expected.stddev, expected.closeEnough, expected.maxError) {
+               s := fmt.Sprintf("stddev %v != %v (allowed error %v, %v)", this.stddev, expected.stddev, expected.closeEnough, expected.maxError)
+               fmt.Println(s)
+               return errors.New(s)
+       }
+       return nil
+}
+
+func getStatsResults(samples []float64) *statsResults {
+       res := new(statsResults)
+       var sum, squaresum float64
+       for _, s := range samples {
+               sum += s
+               squaresum += s * s
+       }
+       res.mean = sum / float64(len(samples))
+       res.stddev = math.Sqrt(squaresum/float64(len(samples)) - res.mean*res.mean)
+       return res
+}
+
+func checkSampleDistribution(t *testing.T, samples []float64, expected *statsResults) {
+       t.Helper()
+       actual := getStatsResults(samples)
+       err := actual.checkSimilarDistribution(expected)
+       if err != nil {
+               t.Errorf(err.Error())
+       }
+}
+
+func checkSampleSliceDistributions(t *testing.T, samples []float64, nslices int, expected *statsResults) {
+       t.Helper()
+       chunk := len(samples) / nslices
+       for i := 0; i < nslices; i++ {
+               low := i * chunk
+               var high int
+               if i == nslices-1 {
+                       high = len(samples) - 1
+               } else {
+                       high = (i + 1) * chunk
+               }
+               checkSampleDistribution(t, samples[low:high], expected)
+       }
+}
+
+//
+// Normal distribution tests
+//
+
+func generateNormalSamples(nsamples int, mean, stddev float64, seed int64) []float64 {
+       r := New(NewSource(seed))
+       samples := make([]float64, nsamples)
+       for i := range samples {
+               samples[i] = r.NormFloat64()*stddev + mean
+       }
+       return samples
+}
+
+func testNormalDistribution(t *testing.T, nsamples int, mean, stddev float64, seed int64) {
+       //fmt.Printf("testing nsamples=%v mean=%v stddev=%v seed=%v\n", nsamples, mean, stddev, seed);
+
+       samples := generateNormalSamples(nsamples, mean, stddev, seed)
+       errorScale := max(1.0, stddev) // Error scales with stddev
+       expected := &statsResults{mean, stddev, 0.10 * errorScale, 0.08 * errorScale}
+
+       // Make sure that the entire set matches the expected distribution.
+       checkSampleDistribution(t, samples, expected)
+
+       // Make sure that each half of the set matches the expected distribution.
+       checkSampleSliceDistributions(t, samples, 2, expected)
+
+       // Make sure that each 7th of the set matches the expected distribution.
+       checkSampleSliceDistributions(t, samples, 7, expected)
+}
+
+// Actual tests
+
+func TestStandardNormalValues(t *testing.T) {
+       for _, seed := range testSeeds {
+               testNormalDistribution(t, numTestSamples, 0, 1, seed)
+       }
+}
+
+func TestNonStandardNormalValues(t *testing.T) {
+       sdmax := 1000.0
+       mmax := 1000.0
+       if testing.Short() {
+               sdmax = 5
+               mmax = 5
+       }
+       for sd := 0.5; sd < sdmax; sd *= 2 {
+               for m := 0.5; m < mmax; m *= 2 {
+                       for _, seed := range testSeeds {
+                               testNormalDistribution(t, numTestSamples, m, sd, seed)
+                               if testing.Short() {
+                                       break
+                               }
+                       }
+               }
+       }
+}
+
+//
+// Exponential distribution tests
+//
+
+func generateExponentialSamples(nsamples int, rate float64, seed int64) []float64 {
+       r := New(NewSource(seed))
+       samples := make([]float64, nsamples)
+       for i := range samples {
+               samples[i] = r.ExpFloat64() / rate
+       }
+       return samples
+}
+
+func testExponentialDistribution(t *testing.T, nsamples int, rate float64, seed int64) {
+       //fmt.Printf("testing nsamples=%v rate=%v seed=%v\n", nsamples, rate, seed);
+
+       mean := 1 / rate
+       stddev := mean
+
+       samples := generateExponentialSamples(nsamples, rate, seed)
+       errorScale := max(1.0, 1/rate) // Error scales with the inverse of the rate
+       expected := &statsResults{mean, stddev, 0.10 * errorScale, 0.20 * errorScale}
+
+       // Make sure that the entire set matches the expected distribution.
+       checkSampleDistribution(t, samples, expected)
+
+       // Make sure that each half of the set matches the expected distribution.
+       checkSampleSliceDistributions(t, samples, 2, expected)
+
+       // Make sure that each 7th of the set matches the expected distribution.
+       checkSampleSliceDistributions(t, samples, 7, expected)
+}
+
+// Actual tests
+
+func TestStandardExponentialValues(t *testing.T) {
+       for _, seed := range testSeeds {
+               testExponentialDistribution(t, numTestSamples, 1, seed)
+       }
+}
+
+func TestNonStandardExponentialValues(t *testing.T) {
+       for rate := 0.05; rate < 10; rate *= 2 {
+               for _, seed := range testSeeds {
+                       testExponentialDistribution(t, numTestSamples, rate, seed)
+                       if testing.Short() {
+                               break
+                       }
+               }
+       }
+}
+
+//
+// Table generation tests
+//
+
+func initNorm() (testKn []uint32, testWn, testFn []float32) {
+       const m1 = 1 << 31
+       var (
+               dn float64 = rn
+               tn         = dn
+               vn float64 = 9.91256303526217e-3
+       )
+
+       testKn = make([]uint32, 128)
+       testWn = make([]float32, 128)
+       testFn = make([]float32, 128)
+
+       q := vn / math.Exp(-0.5*dn*dn)
+       testKn[0] = uint32((dn / q) * m1)
+       testKn[1] = 0
+       testWn[0] = float32(q / m1)
+       testWn[127] = float32(dn / m1)
+       testFn[0] = 1.0
+       testFn[127] = float32(math.Exp(-0.5 * dn * dn))
+       for i := 126; i >= 1; i-- {
+               dn = math.Sqrt(-2.0 * math.Log(vn/dn+math.Exp(-0.5*dn*dn)))
+               testKn[i+1] = uint32((dn / tn) * m1)
+               tn = dn
+               testFn[i] = float32(math.Exp(-0.5 * dn * dn))
+               testWn[i] = float32(dn / m1)
+       }
+       return
+}
+
+func initExp() (testKe []uint32, testWe, testFe []float32) {
+       const m2 = 1 << 32
+       var (
+               de float64 = re
+               te         = de
+               ve float64 = 3.9496598225815571993e-3
+       )
+
+       testKe = make([]uint32, 256)
+       testWe = make([]float32, 256)
+       testFe = make([]float32, 256)
+
+       q := ve / math.Exp(-de)
+       testKe[0] = uint32((de / q) * m2)
+       testKe[1] = 0
+       testWe[0] = float32(q / m2)
+       testWe[255] = float32(de / m2)
+       testFe[0] = 1.0
+       testFe[255] = float32(math.Exp(-de))
+       for i := 254; i >= 1; i-- {
+               de = -math.Log(ve/de + math.Exp(-de))
+               testKe[i+1] = uint32((de / te) * m2)
+               te = de
+               testFe[i] = float32(math.Exp(-de))
+               testWe[i] = float32(de / m2)
+       }
+       return
+}
+
+// compareUint32Slices returns the first index where the two slices
+// disagree, or <0 if the lengths are the same and all elements
+// are identical.
+func compareUint32Slices(s1, s2 []uint32) int {
+       if len(s1) != len(s2) {
+               if len(s1) > len(s2) {
+                       return len(s2) + 1
+               }
+               return len(s1) + 1
+       }
+       for i := range s1 {
+               if s1[i] != s2[i] {
+                       return i
+               }
+       }
+       return -1
+}
+
+// compareFloat32Slices returns the first index where the two slices
+// disagree, or <0 if the lengths are the same and all elements
+// are identical.
+func compareFloat32Slices(s1, s2 []float32) int {
+       if len(s1) != len(s2) {
+               if len(s1) > len(s2) {
+                       return len(s2) + 1
+               }
+               return len(s1) + 1
+       }
+       for i := range s1 {
+               if !nearEqual(float64(s1[i]), float64(s2[i]), 0, 1e-7) {
+                       return i
+               }
+       }
+       return -1
+}
+
+func TestNormTables(t *testing.T) {
+       testKn, testWn, testFn := initNorm()
+       if i := compareUint32Slices(kn[0:], testKn); i >= 0 {
+               t.Errorf("kn disagrees at index %v; %v != %v", i, kn[i], testKn[i])
+       }
+       if i := compareFloat32Slices(wn[0:], testWn); i >= 0 {
+               t.Errorf("wn disagrees at index %v; %v != %v", i, wn[i], testWn[i])
+       }
+       if i := compareFloat32Slices(fn[0:], testFn); i >= 0 {
+               t.Errorf("fn disagrees at index %v; %v != %v", i, fn[i], testFn[i])
+       }
+}
+
+func TestExpTables(t *testing.T) {
+       testKe, testWe, testFe := initExp()
+       if i := compareUint32Slices(ke[0:], testKe); i >= 0 {
+               t.Errorf("ke disagrees at index %v; %v != %v", i, ke[i], testKe[i])
+       }
+       if i := compareFloat32Slices(we[0:], testWe); i >= 0 {
+               t.Errorf("we disagrees at index %v; %v != %v", i, we[i], testWe[i])
+       }
+       if i := compareFloat32Slices(fe[0:], testFe); i >= 0 {
+               t.Errorf("fe disagrees at index %v; %v != %v", i, fe[i], testFe[i])
+       }
+}
+
+func hasSlowFloatingPoint() bool {
+       switch runtime.GOARCH {
+       case "arm":
+               return os.Getenv("GOARM") == "5"
+       case "mips", "mipsle", "mips64", "mips64le":
+               // Be conservative and assume that all mips boards
+               // have emulated floating point.
+               // TODO: detect what it actually has.
+               return true
+       }
+       return false
+}
+
+func TestFloat32(t *testing.T) {
+       // For issue 6721, the problem came after 7533753 calls, so check 10e6.
+       num := int(10e6)
+       // But do the full amount only on builders (not locally).
+       // But ARM5 floating point emulation is slow (Issue 10749), so
+       // do less for that builder:
+       if testing.Short() && (testenv.Builder() == "" || hasSlowFloatingPoint()) {
+               num /= 100 // 1.72 seconds instead of 172 seconds
+       }
+
+       r := New(NewSource(1))
+       for ct := 0; ct < num; ct++ {
+               f := r.Float32()
+               if f >= 1 {
+                       t.Fatal("Float32() should be in range [0,1). ct:", ct, "f:", f)
+               }
+       }
+}
+
+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))
+       for n := 0; n <= 1; n++ {
+               r.Shuffle(n, func(i, j int) { t.Fatalf("swap called, n=%d i=%d j=%d", n, i, j) })
+       }
+}
+
+// encodePerm converts from a permuted slice of length n, such as Perm generates, to an int in [0, n!).
+// See https://en.wikipedia.org/wiki/Lehmer_code.
+// encodePerm modifies the input slice.
+func encodePerm(s []int) int {
+       // Convert to Lehmer code.
+       for i, x := range s {
+               r := s[i+1:]
+               for j, y := range r {
+                       if y > x {
+                               r[j]--
+                       }
+               }
+       }
+       // Convert to int in [0, n!).
+       m := 0
+       fact := 1
+       for i := len(s) - 1; i >= 0; i-- {
+               m += s[i] * fact
+               fact *= len(s) - i
+       }
+       return m
+}
+
+// TestUniformFactorial tests several ways of generating a uniform value in [0, n!).
+func TestUniformFactorial(t *testing.T) {
+       r := New(NewSource(testSeeds[0]))
+       top := 6
+       if testing.Short() {
+               top = 3
+       }
+       for n := 3; n <= top; n++ {
+               t.Run(fmt.Sprintf("n=%d", n), func(t *testing.T) {
+                       // Calculate n!.
+                       nfact := 1
+                       for i := 2; i <= n; i++ {
+                               nfact *= i
+                       }
+
+                       // Test a few different ways to generate a uniform distribution.
+                       p := make([]int, n) // re-usable slice for Shuffle generator
+                       tests := [...]struct {
+                               name string
+                               fn   func() int
+                       }{
+                               {name: "Int31n", fn: func() int { return int(r.Int31n(int32(nfact))) }},
+                               {name: "int31n", fn: func() int { return int(Int31nForTest(r, int32(nfact))) }},
+                               {name: "Perm", fn: func() int { return encodePerm(r.Perm(n)) }},
+                               {name: "Shuffle", fn: func() int {
+                                       // Generate permutation using Shuffle.
+                                       for i := range p {
+                                               p[i] = i
+                                       }
+                                       r.Shuffle(n, func(i, j int) { p[i], p[j] = p[j], p[i] })
+                                       return encodePerm(p)
+                               }},
+                       }
+
+                       for _, test := range tests {
+                               t.Run(test.name, func(t *testing.T) {
+                                       // Gather chi-squared values and check that they follow
+                                       // the expected normal distribution given n!-1 degrees of freedom.
+                                       // See https://en.wikipedia.org/wiki/Pearson%27s_chi-squared_test and
+                                       // https://www.johndcook.com/Beautiful_Testing_ch10.pdf.
+                                       nsamples := 10 * nfact
+                                       if nsamples < 200 {
+                                               nsamples = 200
+                                       }
+                                       samples := make([]float64, nsamples)
+                                       for i := range samples {
+                                               // Generate some uniformly distributed values and count their occurrences.
+                                               const iters = 1000
+                                               counts := make([]int, nfact)
+                                               for i := 0; i < iters; i++ {
+                                                       counts[test.fn()]++
+                                               }
+                                               // Calculate chi-squared and add to samples.
+                                               want := iters / float64(nfact)
+                                               var χ2 float64
+                                               for _, have := range counts {
+                                                       err := float64(have) - want
+                                                       χ2 += err * err
+                                               }
+                                               χ2 /= want
+                                               samples[i] = χ2
+                                       }
+
+                                       // Check that our samples approximate the appropriate normal distribution.
+                                       dof := float64(nfact - 1)
+                                       expected := &statsResults{mean: dof, stddev: math.Sqrt(2 * dof)}
+                                       errorScale := max(1.0, expected.stddev)
+                                       expected.closeEnough = 0.10 * errorScale
+                                       expected.maxError = 0.08 // TODO: What is the right value here? See issue 21211.
+                                       checkSampleDistribution(t, samples, expected)
+                               })
+                       }
+               })
+       }
+}
+
+// Benchmarks
+
+func BenchmarkInt63Threadsafe(b *testing.B) {
+       for n := b.N; n > 0; n-- {
+               Int63()
+       }
+}
+
+func BenchmarkInt63ThreadsafeParallel(b *testing.B) {
+       b.RunParallel(func(pb *testing.PB) {
+               for pb.Next() {
+                       Int63()
+               }
+       })
+}
+
+func BenchmarkInt63Unthreadsafe(b *testing.B) {
+       r := New(NewSource(1))
+       for n := b.N; n > 0; n-- {
+               r.Int63()
+       }
+}
+
+func BenchmarkIntn1000(b *testing.B) {
+       r := New(NewSource(1))
+       for n := b.N; n > 0; n-- {
+               r.Intn(1000)
+       }
+}
+
+func BenchmarkInt63n1000(b *testing.B) {
+       r := New(NewSource(1))
+       for n := b.N; n > 0; n-- {
+               r.Int63n(1000)
+       }
+}
+
+func BenchmarkInt31n1000(b *testing.B) {
+       r := New(NewSource(1))
+       for n := b.N; n > 0; n-- {
+               r.Int31n(1000)
+       }
+}
+
+func BenchmarkFloat32(b *testing.B) {
+       r := New(NewSource(1))
+       for n := b.N; n > 0; n-- {
+               r.Float32()
+       }
+}
+
+func BenchmarkFloat64(b *testing.B) {
+       r := New(NewSource(1))
+       for n := b.N; n > 0; n-- {
+               r.Float64()
+       }
+}
+
+func BenchmarkPerm3(b *testing.B) {
+       r := New(NewSource(1))
+       for n := b.N; n > 0; n-- {
+               r.Perm(3)
+       }
+}
+
+func BenchmarkPerm30(b *testing.B) {
+       r := New(NewSource(1))
+       for n := b.N; n > 0; n-- {
+               r.Perm(30)
+       }
+}
+
+func BenchmarkPerm30ViaShuffle(b *testing.B) {
+       r := New(NewSource(1))
+       for n := b.N; n > 0; n-- {
+               p := make([]int, 30)
+               for i := range p {
+                       p[i] = i
+               }
+               r.Shuffle(30, func(i, j int) { p[i], p[j] = p[j], p[i] })
+       }
+}
+
+// BenchmarkShuffleOverhead uses a minimal swap function
+// to measure just the shuffling overhead.
+func BenchmarkShuffleOverhead(b *testing.B) {
+       r := New(NewSource(1))
+       for n := b.N; n > 0; n-- {
+               r.Shuffle(52, func(i, j int) {
+                       if i < 0 || i >= 52 || j < 0 || j >= 52 {
+                               b.Fatalf("bad swap(%d, %d)", i, j)
+                       }
+               })
+       }
+}
+
+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
+       wg.Add(goroutines)
+       for i := 0; i < goroutines; i++ {
+               go func() {
+                       defer wg.Done()
+                       for n := b.N; n > 0; n-- {
+                               Int63()
+                       }
+               }()
+       }
+       wg.Wait()
+}
diff --git a/src/math/rand/v2/regress_test.go b/src/math/rand/v2/regress_test.go
new file mode 100644 (file)
index 0000000..bfc9108
--- /dev/null
@@ -0,0 +1,404 @@
+// 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 (
+       "flag"
+       "fmt"
+       . "math/rand/v2"
+       "reflect"
+       "testing"
+)
+
+var printgolden = flag.Bool("printgolden", false, "print 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 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 permSizes = []int{0, 1, 5, 8, 9, 10, 16}
+       var readBufferSizes = []int{1, 7, 8, 9, 10}
+       r := New(NewSource(0))
+
+       rv := reflect.ValueOf(r)
+       n := rv.NumMethod()
+       p := 0
+       if *printgolden {
+               fmt.Printf("var regressGolden = []interface{}{\n")
+       }
+       for i := 0; i < n; i++ {
+               m := rv.Type().Method(i)
+               mv := rv.Method(i)
+               mt := mv.Type()
+               if mt.NumOut() == 0 {
+                       continue
+               }
+               r.Seed(0)
+               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 {
+                                               r.Int63n(big) // what would happen on 64-bit machine, to keep stream in sync
+                                               if *printgolden {
+                                                       fmt.Printf("\tskipped, // must run printgolden on 64-bit machine\n")
+                                               }
+                                               p++
+                                               continue
+                                       }
+                                       x = int(big)
+
+                               case reflect.Int32:
+                                       x = int32s[repeat%len(int32s)]
+
+                               case reflect.Int64:
+                                       x = int64s[repeat%len(int64s)]
+
+                               case reflect.Slice:
+                                       if m.Name == "Read" {
+                                               n := readBufferSizes[repeat%len(readBufferSizes)]
+                                               x = make([]byte, n)
+                                       }
+                               }
+                               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 == "Read" {
+                               out = args[0].Interface().([]byte)
+                       }
+                       if *printgolden {
+                               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.Printf("\t%s, // %s(%s)\n", val, m.Name, argstr)
+                       } 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 *printgolden {
+               fmt.Printf("}\n")
+       }
+}
+
+var regressGolden = []any{
+       float64(4.668112973579268),          // ExpFloat64()
+       float64(0.1601593871172866),         // ExpFloat64()
+       float64(3.0465834105636),            // ExpFloat64()
+       float64(0.06385839451671879),        // ExpFloat64()
+       float64(1.8578917487258961),         // ExpFloat64()
+       float64(0.784676123472182),          // ExpFloat64()
+       float64(0.11225477361256932),        // ExpFloat64()
+       float64(0.20173283329802255),        // ExpFloat64()
+       float64(0.3468619496201105),         // ExpFloat64()
+       float64(0.35601103454384536),        // ExpFloat64()
+       float64(0.888376329507869),          // ExpFloat64()
+       float64(1.4081362450365698),         // ExpFloat64()
+       float64(1.0077753823151994),         // ExpFloat64()
+       float64(0.23594100766227588),        // ExpFloat64()
+       float64(2.777245612300007),          // ExpFloat64()
+       float64(0.5202997830662377),         // ExpFloat64()
+       float64(1.2842705247770294),         // ExpFloat64()
+       float64(0.030307408362776206),       // ExpFloat64()
+       float64(2.204156824853721),          // ExpFloat64()
+       float64(2.09891923895058),           // ExpFloat64()
+       float32(0.94519615),                 // Float32()
+       float32(0.24496509),                 // Float32()
+       float32(0.65595627),                 // Float32()
+       float32(0.05434384),                 // Float32()
+       float32(0.3675872),                  // Float32()
+       float32(0.28948045),                 // Float32()
+       float32(0.1924386),                  // Float32()
+       float32(0.65533215),                 // Float32()
+       float32(0.8971697),                  // Float32()
+       float32(0.16735445),                 // Float32()
+       float32(0.28858566),                 // Float32()
+       float32(0.9026048),                  // Float32()
+       float32(0.84978026),                 // Float32()
+       float32(0.2730468),                  // Float32()
+       float32(0.6090802),                  // Float32()
+       float32(0.253656),                   // Float32()
+       float32(0.7746542),                  // Float32()
+       float32(0.017480763),                // Float32()
+       float32(0.78707397),                 // Float32()
+       float32(0.7993937),                  // Float32()
+       float64(0.9451961492941164),         // Float64()
+       float64(0.24496508529377975),        // Float64()
+       float64(0.6559562651954052),         // Float64()
+       float64(0.05434383959970039),        // Float64()
+       float64(0.36758720663245853),        // Float64()
+       float64(0.2894804331565928),         // Float64()
+       float64(0.19243860967493215),        // Float64()
+       float64(0.6553321508148324),         // Float64()
+       float64(0.897169713149801),          // Float64()
+       float64(0.16735444255905835),        // Float64()
+       float64(0.2885856518054551),         // Float64()
+       float64(0.9026048462705047),         // Float64()
+       float64(0.8497802817628735),         // Float64()
+       float64(0.2730468047134829),         // Float64()
+       float64(0.6090801919903561),         // Float64()
+       float64(0.25365600644283687),        // Float64()
+       float64(0.7746542391859803),         // Float64()
+       float64(0.017480762156647272),       // Float64()
+       float64(0.7870739563039942),         // Float64()
+       float64(0.7993936979594545),         // Float64()
+       int64(8717895732742165505),          // Int()
+       int64(2259404117704393152),          // Int()
+       int64(6050128673802995827),          // Int()
+       int64(501233450539197794),           // Int()
+       int64(3390393562759376202),          // Int()
+       int64(2669985732393126063),          // Int()
+       int64(1774932891286980153),          // Int()
+       int64(6044372234677422456),          // Int()
+       int64(8274930044578894929),          // Int()
+       int64(1543572285742637646),          // Int()
+       int64(2661732831099943416),          // Int()
+       int64(8325060299420976708),          // Int()
+       int64(7837839688282259259),          // Int()
+       int64(2518412263346885298),          // Int()
+       int64(5617773211005988520),          // Int()
+       int64(2339563716805116249),          // Int()
+       int64(7144924247938981575),          // Int()
+       int64(161231572858529631),           // Int()
+       int64(7259475919510918339),          // Int()
+       int64(7373105480197164748),          // Int()
+       int32(2029793274),                   // Int31()
+       int32(526058514),                    // Int31()
+       int32(1408655353),                   // Int31()
+       int32(116702506),                    // Int31()
+       int32(789387515),                    // Int31()
+       int32(621654496),                    // Int31()
+       int32(413258767),                    // Int31()
+       int32(1407315077),                   // Int31()
+       int32(1926657288),                   // Int31()
+       int32(359390928),                    // Int31()
+       int32(619732968),                    // Int31()
+       int32(1938329147),                   // Int31()
+       int32(1824889259),                   // Int31()
+       int32(586363548),                    // Int31()
+       int32(1307989752),                   // Int31()
+       int32(544722126),                    // Int31()
+       int32(1663557311),                   // Int31()
+       int32(37539650),                     // Int31()
+       int32(1690228450),                   // Int31()
+       int32(1716684894),                   // Int31()
+       int32(0),                            // Int31n(1)
+       int32(4),                            // Int31n(10)
+       int32(25),                           // Int31n(32)
+       int32(310570),                       // Int31n(1048576)
+       int32(857611),                       // Int31n(1048577)
+       int32(621654496),                    // Int31n(1000000000)
+       int32(413258767),                    // Int31n(1073741824)
+       int32(1407315077),                   // Int31n(2147483646)
+       int32(1926657288),                   // Int31n(2147483647)
+       int32(0),                            // Int31n(1)
+       int32(8),                            // Int31n(10)
+       int32(27),                           // Int31n(32)
+       int32(367019),                       // Int31n(1048576)
+       int32(209005),                       // Int31n(1048577)
+       int32(307989752),                    // Int31n(1000000000)
+       int32(544722126),                    // Int31n(1073741824)
+       int32(1663557311),                   // Int31n(2147483646)
+       int32(37539650),                     // Int31n(2147483647)
+       int32(0),                            // Int31n(1)
+       int32(4),                            // Int31n(10)
+       int64(8717895732742165505),          // Int63()
+       int64(2259404117704393152),          // Int63()
+       int64(6050128673802995827),          // Int63()
+       int64(501233450539197794),           // Int63()
+       int64(3390393562759376202),          // Int63()
+       int64(2669985732393126063),          // Int63()
+       int64(1774932891286980153),          // Int63()
+       int64(6044372234677422456),          // Int63()
+       int64(8274930044578894929),          // Int63()
+       int64(1543572285742637646),          // Int63()
+       int64(2661732831099943416),          // Int63()
+       int64(8325060299420976708),          // Int63()
+       int64(7837839688282259259),          // Int63()
+       int64(2518412263346885298),          // Int63()
+       int64(5617773211005988520),          // Int63()
+       int64(2339563716805116249),          // Int63()
+       int64(7144924247938981575),          // Int63()
+       int64(161231572858529631),           // Int63()
+       int64(7259475919510918339),          // Int63()
+       int64(7373105480197164748),          // Int63()
+       int64(0),                            // Int63n(1)
+       int64(2),                            // Int63n(10)
+       int64(19),                           // Int63n(32)
+       int64(959842),                       // Int63n(1048576)
+       int64(688912),                       // Int63n(1048577)
+       int64(393126063),                    // Int63n(1000000000)
+       int64(89212473),                     // Int63n(1073741824)
+       int64(834026388),                    // Int63n(2147483646)
+       int64(1577188963),                   // Int63n(2147483647)
+       int64(543572285742637646),           // Int63n(1000000000000000000)
+       int64(355889821886249464),           // Int63n(1152921504606846976)
+       int64(8325060299420976708),          // Int63n(9223372036854775806)
+       int64(7837839688282259259),          // Int63n(9223372036854775807)
+       int64(0),                            // Int63n(1)
+       int64(0),                            // Int63n(10)
+       int64(25),                           // Int63n(32)
+       int64(679623),                       // Int63n(1048576)
+       int64(882178),                       // Int63n(1048577)
+       int64(510918339),                    // Int63n(1000000000)
+       int64(782454476),                    // Int63n(1073741824)
+       int64(0),                            // Intn(1)
+       int64(4),                            // Intn(10)
+       int64(25),                           // Intn(32)
+       int64(310570),                       // Intn(1048576)
+       int64(857611),                       // Intn(1048577)
+       int64(621654496),                    // Intn(1000000000)
+       int64(413258767),                    // Intn(1073741824)
+       int64(1407315077),                   // Intn(2147483646)
+       int64(1926657288),                   // Intn(2147483647)
+       int64(543572285742637646),           // Intn(1000000000000000000)
+       int64(355889821886249464),           // Intn(1152921504606846976)
+       int64(8325060299420976708),          // Intn(9223372036854775806)
+       int64(7837839688282259259),          // Intn(9223372036854775807)
+       int64(0),                            // Intn(1)
+       int64(2),                            // Intn(10)
+       int64(14),                           // Intn(32)
+       int64(515775),                       // Intn(1048576)
+       int64(839455),                       // Intn(1048577)
+       int64(690228450),                    // Intn(1000000000)
+       int64(642943070),                    // Intn(1073741824)
+       float64(-0.28158587086436215),       // NormFloat64()
+       float64(0.570933095808067),          // NormFloat64()
+       float64(-1.6920196326157044),        // NormFloat64()
+       float64(0.1996229111693099),         // NormFloat64()
+       float64(1.9195199291234621),         // NormFloat64()
+       float64(0.8954838794918353),         // NormFloat64()
+       float64(0.41457072128813166),        // NormFloat64()
+       float64(-0.48700161491544713),       // NormFloat64()
+       float64(-0.1684059662402393),        // NormFloat64()
+       float64(0.37056410998929545),        // NormFloat64()
+       float64(1.0156889027029008),         // NormFloat64()
+       float64(-0.5174422210625114),        // NormFloat64()
+       float64(-0.5565834214413804),        // NormFloat64()
+       float64(0.778320596648391),          // NormFloat64()
+       float64(-1.8970718197702225),        // NormFloat64()
+       float64(0.5229525761688676),         // NormFloat64()
+       float64(-1.5515595563231523),        // NormFloat64()
+       float64(0.0182029289376123),         // NormFloat64()
+       float64(-0.6820951356608795),        // NormFloat64()
+       float64(-0.5987943422687668),        // NormFloat64()
+       []int{},                             // Perm(0)
+       []int{0},                            // Perm(1)
+       []int{0, 4, 1, 3, 2},                // Perm(5)
+       []int{3, 1, 0, 4, 7, 5, 2, 6},       // Perm(8)
+       []int{5, 0, 3, 6, 7, 4, 2, 1, 8},    // Perm(9)
+       []int{4, 5, 0, 2, 6, 9, 3, 1, 8, 7}, // Perm(10)
+       []int{14, 2, 0, 8, 3, 5, 13, 12, 1, 4, 6, 7, 11, 9, 15, 10}, // Perm(16)
+       []int{},                             // Perm(0)
+       []int{0},                            // Perm(1)
+       []int{3, 0, 1, 2, 4},                // Perm(5)
+       []int{5, 1, 2, 0, 4, 7, 3, 6},       // Perm(8)
+       []int{4, 0, 6, 8, 1, 5, 2, 7, 3},    // Perm(9)
+       []int{8, 6, 1, 7, 5, 4, 3, 2, 9, 0}, // Perm(10)
+       []int{0, 3, 13, 2, 15, 4, 10, 1, 8, 14, 7, 6, 12, 9, 5, 11}, // Perm(16)
+       []int{},                             // Perm(0)
+       []int{0},                            // Perm(1)
+       []int{0, 4, 2, 1, 3},                // Perm(5)
+       []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()
+}
diff --git a/src/math/rand/v2/rng.go b/src/math/rand/v2/rng.go
new file mode 100644 (file)
index 0000000..1e4a9e0
--- /dev/null
@@ -0,0 +1,252 @@
+// 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
+
+/*
+ * Uniform distribution
+ *
+ * algorithm by
+ * DP Mitchell and JA Reeds
+ */
+
+const (
+       rngLen   = 607
+       rngTap   = 273
+       rngMax   = 1 << 63
+       rngMask  = rngMax - 1
+       int32max = (1 << 31) - 1
+)
+
+var (
+       // rngCooked used for seeding. See gen_cooked.go for details.
+       rngCooked [rngLen]int64 = [...]int64{
+               -4181792142133755926, -4576982950128230565, 1395769623340756751, 5333664234075297259,
+               -6347679516498800754, 9033628115061424579, 7143218595135194537, 4812947590706362721,
+               7937252194349799378, 5307299880338848416, 8209348851763925077, -7107630437535961764,
+               4593015457530856296, 8140875735541888011, -5903942795589686782, -603556388664454774,
+               -7496297993371156308, 113108499721038619, 4569519971459345583, -4160538177779461077,
+               -6835753265595711384, -6507240692498089696, 6559392774825876886, 7650093201692370310,
+               7684323884043752161, -8965504200858744418, -2629915517445760644, 271327514973697897,
+               -6433985589514657524, 1065192797246149621, 3344507881999356393, -4763574095074709175,
+               7465081662728599889, 1014950805555097187, -4773931307508785033, -5742262670416273165,
+               2418672789110888383, 5796562887576294778, 4484266064449540171, 3738982361971787048,
+               -4699774852342421385, 10530508058128498, -589538253572429690, -6598062107225984180,
+               8660405965245884302, 10162832508971942, -2682657355892958417, 7031802312784620857,
+               6240911277345944669, 831864355460801054, -1218937899312622917, 2116287251661052151,
+               2202309800992166967, 9161020366945053561, 4069299552407763864, 4936383537992622449,
+               457351505131524928, -8881176990926596454, -6375600354038175299, -7155351920868399290,
+               4368649989588021065, 887231587095185257, -3659780529968199312, -2407146836602825512,
+               5616972787034086048, -751562733459939242, 1686575021641186857, -5177887698780513806,
+               -4979215821652996885, -1375154703071198421, 5632136521049761902, -8390088894796940536,
+               -193645528485698615, -5979788902190688516, -4907000935050298721, -285522056888777828,
+               -2776431630044341707, 1679342092332374735, 6050638460742422078, -2229851317345194226,
+               -1582494184340482199, 5881353426285907985, 812786550756860885, 4541845584483343330,
+               -6497901820577766722, 4980675660146853729, -4012602956251539747, -329088717864244987,
+               -2896929232104691526, 1495812843684243920, -2153620458055647789, 7370257291860230865,
+               -2466442761497833547, 4706794511633873654, -1398851569026877145, 8549875090542453214,
+               -9189721207376179652, -7894453601103453165, 7297902601803624459, 1011190183918857495,
+               -6985347000036920864, 5147159997473910359, -8326859945294252826, 2659470849286379941,
+               6097729358393448602, -7491646050550022124, -5117116194870963097, -896216826133240300,
+               -745860416168701406, 5803876044675762232, -787954255994554146, -3234519180203704564,
+               -4507534739750823898, -1657200065590290694, 505808562678895611, -4153273856159712438,
+               -8381261370078904295, 572156825025677802, 1791881013492340891, 3393267094866038768,
+               -5444650186382539299, 2352769483186201278, -7930912453007408350, -325464993179687389,
+               -3441562999710612272, -6489413242825283295, 5092019688680754699, -227247482082248967,
+               4234737173186232084, 5027558287275472836, 4635198586344772304, -536033143587636457,
+               5907508150730407386, -8438615781380831356, 972392927514829904, -3801314342046600696,
+               -4064951393885491917, -174840358296132583, 2407211146698877100, -1640089820333676239,
+               3940796514530962282, -5882197405809569433, 3095313889586102949, -1818050141166537098,
+               5832080132947175283, 7890064875145919662, 8184139210799583195, -8073512175445549678,
+               -7758774793014564506, -4581724029666783935, 3516491885471466898, -8267083515063118116,
+               6657089965014657519, 5220884358887979358, 1796677326474620641, 5340761970648932916,
+               1147977171614181568, 5066037465548252321, 2574765911837859848, 1085848279845204775,
+               -5873264506986385449, 6116438694366558490, 2107701075971293812, -7420077970933506541,
+               2469478054175558874, -1855128755834809824, -5431463669011098282, -9038325065738319171,
+               -6966276280341336160, 7217693971077460129, -8314322083775271549, 7196649268545224266,
+               -3585711691453906209, -5267827091426810625, 8057528650917418961, -5084103596553648165,
+               -2601445448341207749, -7850010900052094367, 6527366231383600011, 3507654575162700890,
+               9202058512774729859, 1954818376891585542, -2582991129724600103, 8299563319178235687,
+               -5321504681635821435, 7046310742295574065, -2376176645520785576, -7650733936335907755,
+               8850422670118399721, 3631909142291992901, 5158881091950831288, -6340413719511654215,
+               4763258931815816403, 6280052734341785344, -4979582628649810958, 2043464728020827976,
+               -2678071570832690343, 4562580375758598164, 5495451168795427352, -7485059175264624713,
+               553004618757816492, 6895160632757959823, -989748114590090637, 7139506338801360852,
+               -672480814466784139, 5535668688139305547, 2430933853350256242, -3821430778991574732,
+               -1063731997747047009, -3065878205254005442, 7632066283658143750, 6308328381617103346,
+               3681878764086140361, 3289686137190109749, 6587997200611086848, 244714774258135476,
+               -5143583659437639708, 8090302575944624335, 2945117363431356361, -8359047641006034763,
+               3009039260312620700, -793344576772241777, 401084700045993341, -1968749590416080887,
+               4707864159563588614, -3583123505891281857, -3240864324164777915, -5908273794572565703,
+               -3719524458082857382, -5281400669679581926, 8118566580304798074, 3839261274019871296,
+               7062410411742090847, -8481991033874568140, 6027994129690250817, -6725542042704711878,
+               -2971981702428546974, -7854441788951256975, 8809096399316380241, 6492004350391900708,
+               2462145737463489636, -8818543617934476634, -5070345602623085213, -8961586321599299868,
+               -3758656652254704451, -8630661632476012791, 6764129236657751224, -709716318315418359,
+               -3403028373052861600, -8838073512170985897, -3999237033416576341, -2920240395515973663,
+               -2073249475545404416, 368107899140673753, -6108185202296464250, -6307735683270494757,
+               4782583894627718279, 6718292300699989587, 8387085186914375220, 3387513132024756289,
+               4654329375432538231, -292704475491394206, -3848998599978456535, 7623042350483453954,
+               7725442901813263321, 9186225467561587250, -5132344747257272453, -6865740430362196008,
+               2530936820058611833, 1636551876240043639, -3658707362519810009, 1452244145334316253,
+               -7161729655835084979, -7943791770359481772, 9108481583171221009, -3200093350120725999,
+               5007630032676973346, 2153168792952589781, 6720334534964750538, -3181825545719981703,
+               3433922409283786309, 2285479922797300912, 3110614940896576130, -2856812446131932915,
+               -3804580617188639299, 7163298419643543757, 4891138053923696990, 580618510277907015,
+               1684034065251686769, 4429514767357295841, -8893025458299325803, -8103734041042601133,
+               7177515271653460134, 4589042248470800257, -1530083407795771245, 143607045258444228,
+               246994305896273627, -8356954712051676521, 6473547110565816071, 3092379936208876896,
+               2058427839513754051, -4089587328327907870, 8785882556301281247, -3074039370013608197,
+               -637529855400303673, 6137678347805511274, -7152924852417805802, 5708223427705576541,
+               -3223714144396531304, 4358391411789012426, 325123008708389849, 6837621693887290924,
+               4843721905315627004, -3212720814705499393, -3825019837890901156, 4602025990114250980,
+               1044646352569048800, 9106614159853161675, -8394115921626182539, -4304087667751778808,
+               2681532557646850893, 3681559472488511871, -3915372517896561773, -2889241648411946534,
+               -6564663803938238204, -8060058171802589521, 581945337509520675, 3648778920718647903,
+               -4799698790548231394, -7602572252857820065, 220828013409515943, -1072987336855386047,
+               4287360518296753003, -4633371852008891965, 5513660857261085186, -2258542936462001533,
+               -8744380348503999773, 8746140185685648781, 228500091334420247, 1356187007457302238,
+               3019253992034194581, 3152601605678500003, -8793219284148773595, 5559581553696971176,
+               4916432985369275664, -8559797105120221417, -5802598197927043732, 2868348622579915573,
+               -7224052902810357288, -5894682518218493085, 2587672709781371173, -7706116723325376475,
+               3092343956317362483, -5561119517847711700, 972445599196498113, -1558506600978816441,
+               1708913533482282562, -2305554874185907314, -6005743014309462908, -6653329009633068701,
+               -483583197311151195, 2488075924621352812, -4529369641467339140, -4663743555056261452,
+               2997203966153298104, 1282559373026354493, 240113143146674385, 8665713329246516443,
+               628141331766346752, -4651421219668005332, -7750560848702540400, 7596648026010355826,
+               -3132152619100351065, 7834161864828164065, 7103445518877254909, 4390861237357459201,
+               -4780718172614204074, -319889632007444440, 622261699494173647, -3186110786557562560,
+               -8718967088789066690, -1948156510637662747, -8212195255998774408, -7028621931231314745,
+               2623071828615234808, -4066058308780939700, -5484966924888173764, -6683604512778046238,
+               -6756087640505506466, 5256026990536851868, 7841086888628396109, 6640857538655893162,
+               -8021284697816458310, -7109857044414059830, -1689021141511844405, -4298087301956291063,
+               -4077748265377282003, -998231156719803476, 2719520354384050532, 9132346697815513771,
+               4332154495710163773, -2085582442760428892, 6994721091344268833, -2556143461985726874,
+               -8567931991128098309, 59934747298466858, -3098398008776739403, -265597256199410390,
+               2332206071942466437, -7522315324568406181, 3154897383618636503, -7585605855467168281,
+               -6762850759087199275, 197309393502684135, -8579694182469508493, 2543179307861934850,
+               4350769010207485119, -4468719947444108136, -7207776534213261296, -1224312577878317200,
+               4287946071480840813, 8362686366770308971, 6486469209321732151, -5605644191012979782,
+               -1669018511020473564, 4450022655153542367, -7618176296641240059, -3896357471549267421,
+               -4596796223304447488, -6531150016257070659, -8982326463137525940, -4125325062227681798,
+               -1306489741394045544, -8338554946557245229, 5329160409530630596, 7790979528857726136,
+               4955070238059373407, -4304834761432101506, -6215295852904371179, 3007769226071157901,
+               -6753025801236972788, 8928702772696731736, 7856187920214445904, -4748497451462800923,
+               7900176660600710914, -7082800908938549136, -6797926979589575837, -6737316883512927978,
+               4186670094382025798, 1883939007446035042, -414705992779907823, 3734134241178479257,
+               4065968871360089196, 6953124200385847784, -7917685222115876751, -7585632937840318161,
+               -5567246375906782599, -5256612402221608788, 3106378204088556331, -2894472214076325998,
+               4565385105440252958, 1979884289539493806, -6891578849933910383, 3783206694208922581,
+               8464961209802336085, 2843963751609577687, 3030678195484896323, -4429654462759003204,
+               4459239494808162889, 402587895800087237, 8057891408711167515, 4541888170938985079,
+               1042662272908816815, -3666068979732206850, 2647678726283249984, 2144477441549833761,
+               -3417019821499388721, -2105601033380872185, 5916597177708541638, -8760774321402454447,
+               8833658097025758785, 5970273481425315300, 563813119381731307, -6455022486202078793,
+               1598828206250873866, -4016978389451217698, -2988328551145513985, -6071154634840136312,
+               8469693267274066490, 125672920241807416, -3912292412830714870, -2559617104544284221,
+               -486523741806024092, -4735332261862713930, 5923302823487327109, -9082480245771672572,
+               -1808429243461201518, 7990420780896957397, 4317817392807076702, 3625184369705367340,
+               -6482649271566653105, -3480272027152017464, -3225473396345736649, -368878695502291645,
+               -3981164001421868007, -8522033136963788610, 7609280429197514109, 3020985755112334161,
+               -2572049329799262942, 2635195723621160615, 5144520864246028816, -8188285521126945980,
+               1567242097116389047, 8172389260191636581, -2885551685425483535, -7060359469858316883,
+               -6480181133964513127, -7317004403633452381, 6011544915663598137, 5932255307352610768,
+               2241128460406315459, -8327867140638080220, 3094483003111372717, 4583857460292963101,
+               9079887171656594975, -384082854924064405, -3460631649611717935, 4225072055348026230,
+               -7385151438465742745, 3801620336801580414, -399845416774701952, -7446754431269675473,
+               7899055018877642622, 5421679761463003041, 5521102963086275121, -4975092593295409910,
+               8735487530905098534, -7462844945281082830, -2080886987197029914, -1000715163927557685,
+               -4253840471931071485, -5828896094657903328, 6424174453260338141, 359248545074932887,
+               -5949720754023045210, -2426265837057637212, 3030918217665093212, -9077771202237461772,
+               -3186796180789149575, 740416251634527158, -2142944401404840226, 6951781370868335478,
+               399922722363687927, -8928469722407522623, -1378421100515597285, -8343051178220066766,
+               -3030716356046100229, -8811767350470065420, 9026808440365124461, 6440783557497587732,
+               4615674634722404292, 539897290441580544, 2096238225866883852, 8751955639408182687,
+               -7316147128802486205, 7381039757301768559, 6157238513393239656, -1473377804940618233,
+               8629571604380892756, 5280433031239081479, 7101611890139813254, 2479018537985767835,
+               7169176924412769570, -1281305539061572506, -7865612307799218120, 2278447439451174845,
+               3625338785743880657, 6477479539006708521, 8976185375579272206, -3712000482142939688,
+               1326024180520890843, 7537449876596048829, 5464680203499696154, 3189671183162196045,
+               6346751753565857109, -8982212049534145501, -6127578587196093755, -245039190118465649,
+               -6320577374581628592, 7208698530190629697, 7276901792339343736, -7490986807540332668,
+               4133292154170828382, 2918308698224194548, -7703910638917631350, -3929437324238184044,
+               -4300543082831323144, -6344160503358350167, 5896236396443472108, -758328221503023383,
+               -1894351639983151068, -307900319840287220, -6278469401177312761, -2171292963361310674,
+               8382142935188824023, 9103922860780351547, 4152330101494654406,
+       }
+)
+
+type rngSource struct {
+       tap  int           // index into vec
+       feed int           // index into vec
+       vec  [rngLen]int64 // current feedback register
+}
+
+// seed rng x[n+1] = 48271 * x[n] mod (2**31 - 1)
+func seedrand(x int32) int32 {
+       const (
+               A = 48271
+               Q = 44488
+               R = 3399
+       )
+
+       hi := x / Q
+       lo := x % Q
+       x = A*lo - R*hi
+       if x < 0 {
+               x += int32max
+       }
+       return x
+}
+
+// Seed uses the provided seed value to initialize the generator to a deterministic state.
+func (rng *rngSource) Seed(seed int64) {
+       rng.tap = 0
+       rng.feed = rngLen - rngTap
+
+       seed = seed % int32max
+       if seed < 0 {
+               seed += int32max
+       }
+       if seed == 0 {
+               seed = 89482311
+       }
+
+       x := int32(seed)
+       for i := -20; i < rngLen; i++ {
+               x = seedrand(x)
+               if i >= 0 {
+                       var u int64
+                       u = int64(x) << 40
+                       x = seedrand(x)
+                       u ^= int64(x) << 20
+                       x = seedrand(x)
+                       u ^= int64(x)
+                       u ^= rngCooked[i]
+                       rng.vec[i] = u
+               }
+       }
+}
+
+// Int63 returns a non-negative pseudo-random 63-bit integer as an int64.
+func (rng *rngSource) Int63() int64 {
+       return int64(rng.Uint64() & rngMask)
+}
+
+// Uint64 returns a non-negative pseudo-random 64-bit integer as a uint64.
+func (rng *rngSource) Uint64() uint64 {
+       rng.tap--
+       if rng.tap < 0 {
+               rng.tap += rngLen
+       }
+
+       rng.feed--
+       if rng.feed < 0 {
+               rng.feed += rngLen
+       }
+
+       x := rng.vec[rng.feed] + rng.vec[rng.tap]
+       rng.vec[rng.feed] = x
+       return uint64(x)
+}
diff --git a/src/math/rand/v2/zipf.go b/src/math/rand/v2/zipf.go
new file mode 100644 (file)
index 0000000..f04c814
--- /dev/null
@@ -0,0 +1,77 @@
+// 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.
+
+// W.Hormann, G.Derflinger:
+// "Rejection-Inversion to Generate Variates
+// from Monotone Discrete Distributions"
+// http://eeyore.wu-wien.ac.at/papers/96-04-04.wh-der.ps.gz
+
+package rand
+
+import "math"
+
+// A Zipf generates Zipf distributed variates.
+type Zipf struct {
+       r            *Rand
+       imax         float64
+       v            float64
+       q            float64
+       s            float64
+       oneminusQ    float64
+       oneminusQinv float64
+       hxm          float64
+       hx0minusHxm  float64
+}
+
+func (z *Zipf) h(x float64) float64 {
+       return math.Exp(z.oneminusQ*math.Log(z.v+x)) * z.oneminusQinv
+}
+
+func (z *Zipf) hinv(x float64) float64 {
+       return math.Exp(z.oneminusQinv*math.Log(z.oneminusQ*x)) - z.v
+}
+
+// NewZipf returns a Zipf variate generator.
+// The generator generates values k ∈ [0, imax]
+// such that P(k) is proportional to (v + k) ** (-s).
+// Requirements: s > 1 and v >= 1.
+func NewZipf(r *Rand, s float64, v float64, imax uint64) *Zipf {
+       z := new(Zipf)
+       if s <= 1.0 || v < 1 {
+               return nil
+       }
+       z.r = r
+       z.imax = float64(imax)
+       z.v = v
+       z.q = s
+       z.oneminusQ = 1.0 - z.q
+       z.oneminusQinv = 1.0 / z.oneminusQ
+       z.hxm = z.h(z.imax + 0.5)
+       z.hx0minusHxm = z.h(0.5) - math.Exp(math.Log(z.v)*(-z.q)) - z.hxm
+       z.s = 1 - z.hinv(z.h(1.5)-math.Exp(-z.q*math.Log(z.v+1.0)))
+       return z
+}
+
+// Uint64 returns a value drawn from the Zipf distribution described
+// by the Zipf object.
+func (z *Zipf) Uint64() uint64 {
+       if z == nil {
+               panic("rand: nil Zipf")
+       }
+       k := 0.0
+
+       for {
+               r := z.r.Float64() // r on [0,1]
+               ur := z.hxm + r*z.hx0minusHxm
+               x := z.hinv(ur)
+               k = math.Floor(x + 0.5)
+               if k-x <= z.s {
+                       break
+               }
+               if ur >= z.h(k+0.5)-math.Exp(-math.Log(k+z.v)*z.q) {
+                       break
+               }
+       }
+       return uint64(k)
+}
index 27dbfd21ed412cc0f095bab888f4c472ffe4be12..b70c9cc057a6676f8714cc187362e28b34b59470 100644 (file)
@@ -196,6 +196,9 @@ func fastrandu() uint {
 //go:linkname rand_fastrand64 math/rand.fastrand64
 func rand_fastrand64() uint64 { return fastrand64() }
 
+//go:linkname rand2_fastrand64 math/rand/v2.fastrand64
+func rand2_fastrand64() uint64 { return fastrand64() }
+
 //go:linkname sync_fastrandn sync.fastrandn
 func sync_fastrandn(n uint32) uint32 { return fastrandn(n) }