1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
|
// Copied from https://cs.opensource.google/go/x/exp/+/24438e51023af3bfc1db8aed43c1342817e8cfcd:rand/modulo_test.go
// Copyright 2017 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.
// This file validates that the calculation in Uint64n corrects for
// possible bias.
package rand
import (
"testing"
)
// modSource is used to probe the upper region of uint64 space. It
// generates values sequentially in [maxUint64-15,maxUint64]. With
// modEdge == 15 and maxUint64 == 1<<64-1 == 18446744073709551615,
// this means that Uint64n(10) will repeatedly probe the top range.
// We thus expect a bias to result unless the calculation in Uint64n
// gets the edge condition right. We test this by calling Uint64n 100
// times; the results should be perfectly evenly distributed across
// [0,10).
type modSource uint64
const modEdge = 15
func (m *modSource) Seed(uint64) {}
// Uint64 returns a non-pseudo-random 64-bit unsigned integer as a uint64.
func (m *modSource) Uint64() uint64 {
if *m > modEdge {
*m = 0
}
r := maxUint64 - *m
*m++
return uint64(r)
}
func TestUint64Modulo(t *testing.T) {
var src modSource
rng := New(&src)
var result [10]uint64
for i := 0; i < 100; i++ {
result[rng.Uint64n(10)]++
}
for _, r := range result {
if r != 10 {
t.Fatal(result)
}
}
}
|