pgregory.net/rand@v1.0.3-0.20230808192358-a0b8ce02f4da/global_test.go (about) 1 // Copyright 2022 Gregory Petrosyan <gregory.petrosyan@gmail.com> 2 // 3 // This Source Code Form is subject to the terms of the Mozilla Public 4 // License, v. 2.0. If a copy of the MPL was not distributed with this 5 // file, You can obtain one at https://mozilla.org/MPL/2.0/. 6 7 package rand_test 8 9 import ( 10 "math" 11 "math/bits" 12 "pgregory.net/rand" 13 "pgregory.net/rapid" 14 "sync/atomic" 15 "testing" 16 ) 17 18 const ( 19 wyrandAdd = 0xa0761d6478bd642f 20 wyrandXor = 0xe7037ed1a0b428db 21 ) 22 23 func wyrand64(state *uint64) uint64 { 24 s := *state + wyrandAdd 25 *state = s 26 hi, lo := bits.Mul64(s, s^wyrandXor) 27 return hi ^ lo 28 } 29 30 func wyrand64Atomic(state *uint64) uint64 { 31 s := atomic.AddUint64(state, wyrandAdd) 32 hi, lo := bits.Mul64(s, s^wyrandXor) 33 return hi ^ lo 34 } 35 36 func BenchmarkRand64(b *testing.B) { 37 var s uint64 38 for i := 0; i < b.N; i++ { 39 s = rand.Uint64() 40 } 41 sinkUint64 = s 42 } 43 44 func BenchmarkWyRand64(b *testing.B) { 45 var s uint64 46 var state uint64 47 for i := 0; i < b.N; i++ { 48 s = wyrand64(&state) 49 } 50 sinkUint64 = s 51 } 52 53 func BenchmarkWyRand64Atomic(b *testing.B) { 54 var s uint64 55 var state uint64 56 for i := 0; i < b.N; i++ { 57 s = wyrand64Atomic(&state) 58 } 59 sinkUint64 = s 60 } 61 62 func TestFloat32(t *testing.T) { 63 rapid.Check(t, func(t *rapid.T) { 64 f := rand.Float32() 65 if f < 0 || f >= 1 { 66 t.Fatalf("got %v outside of [0, 1)", f) 67 } 68 }) 69 } 70 71 func TestFloat64(t *testing.T) { 72 rapid.Check(t, func(t *rapid.T) { 73 f := rand.Float64() 74 if f < 0 || f >= 1 { 75 t.Fatalf("got %v outside of [0, 1)", f) 76 } 77 }) 78 } 79 80 func TestInt31n(t *testing.T) { 81 rapid.Check(t, func(t *rapid.T) { 82 n := rapid.Int32Range(1, math.MaxInt32).Draw(t, "n").(int32) 83 v := rand.Int31n(n) 84 if v < 0 || v >= n { 85 t.Fatalf("got %v outside of [0, %v)", v, n) 86 } 87 }) 88 } 89 90 func TestInt63n(t *testing.T) { 91 rapid.Check(t, func(t *rapid.T) { 92 n := rapid.Int64Range(1, math.MaxInt64).Draw(t, "n").(int64) 93 v := rand.Int63n(n) 94 if v < 0 || v >= n { 95 t.Fatalf("got %v outside of [0, %v)", v, n) 96 } 97 }) 98 } 99 100 func TestIntn(t *testing.T) { 101 rapid.Check(t, func(t *rapid.T) { 102 n := rapid.IntRange(1, math.MaxInt).Draw(t, "n").(int) 103 v := rand.Intn(n) 104 if v < 0 || v >= n { 105 t.Fatalf("got %v outside of [0, %v)", v, n) 106 } 107 }) 108 } 109 110 func TestUint32n(t *testing.T) { 111 rapid.Check(t, func(t *rapid.T) { 112 n := rapid.Uint32Range(1, math.MaxUint32).Draw(t, "n").(uint32) 113 v := rand.Uint32n(n) 114 if v >= n { 115 t.Fatalf("got %v outside of [0, %v)", v, n) 116 } 117 }) 118 } 119 120 func TestUint64n(t *testing.T) { 121 rapid.Check(t, func(t *rapid.T) { 122 n := rapid.Uint64Range(1, math.MaxUint64).Draw(t, "n").(uint64) 123 v := rand.Uint64n(n) 124 if v >= n { 125 t.Fatalf("got %v outside of [0, %v)", v, n) 126 } 127 }) 128 }