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