| // 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) |
| } |
| } |
| } |