bursavich.dev/fastrand@v0.2.1/fastrand.go (about) 1 // SPDX-License-Identifier: MIT 2 // 3 // Copyright 2023 Andrew Bursavich. All rights reserved. 4 // Use of this source code is governed by The MIT License 5 // which can be found in the LICENSE file. 6 7 // Package fastrand provides quickly generated pseudo-random numbers 8 // with no repeatability guarantees on the stream of values. 9 package fastrand 10 11 import ( 12 "io" 13 14 "golang.org/x/exp/constraints" 15 ) 16 17 const ( 18 maxUint32 = (1 << 32) - 1 19 maxUint64 = (1 << 64) - 1 20 maxInt32 = maxUint32 >> 1 21 maxInt64 = maxUint64 >> 1 22 ) 23 24 // Float32 returns a pseudo-random float32 in the half-open interval [0,n). 25 func Float32() float32 { 26 const ( 27 mask = 1<<24 - 1 28 mult = 0x1.0p-24 29 ) 30 return float32(u32()&mask) * mult 31 } 32 33 // Float64 returns a pseudo-random float64 in the half-open interval [0,n). 34 func Float64() float64 { 35 const ( 36 mask = 1<<53 - 1 37 mult = 0x1.0p-53 38 ) 39 return float64(u64()&mask) * mult 40 } 41 42 // Int31 returns a non-negative pseudo-random int32. 43 func Int31() int32 { 44 return int32(u32() >> 1) 45 } 46 47 // Int31n returns a non-negative pseudo-random int32 in the half-open interval [0,n). 48 // It panics if n <= 0. 49 func Int31n(n int32) int32 { 50 if n <= 0 { 51 panic("fastrand.Int31n: invalid argument") 52 } 53 if n&(n-1) == 0 { // n is power of two, can mask 54 return Int31() & (n - 1) 55 } 56 max := maxInt32 - maxInt32%n 57 v := Int31() 58 for v >= max { 59 v = Int31() 60 } 61 return v % n 62 } 63 64 // Int63 returns a non-negative pseudo-random int64. 65 func Int63() int64 { 66 return int64(u64() >> 1) 67 } 68 69 // Int63n returns a non-negative pseudo-random int64 in the half-open interval [0,n). 70 // It panics if n <= 0. 71 func Int63n(n int64) int64 { 72 if n <= 0 { 73 panic("fastrand.Int63n: invalid argument") 74 } 75 if n&(n-1) == 0 { // n is power of two, can mask 76 return Int63() & (n - 1) 77 } 78 max := maxInt64 - maxInt64%n 79 v := Int63() 80 for v >= max { 81 v = Int63() 82 } 83 return v % n 84 } 85 86 // Uint32 returns a pseudo-random uint32. 87 func Uint32() uint32 { 88 return u32() 89 } 90 91 // Uint32n returns a pseudo-random uint32 in the half-open interval [0,n). 92 func Uint64nUint32n(n uint32) uint32 { 93 if n&(n-1) == 0 { // n is power of two, can mask 94 return u32() & (n - 1) 95 } 96 max := maxUint32 - maxUint32%uint32(n) 97 v := u32() 98 for v >= max { 99 v = u32() 100 } 101 return v % n 102 } 103 104 // Uint64 returns a pseudo-random uint64. 105 func Uint64() uint64 { 106 return u64() 107 } 108 109 // Uint64n returns a pseudo-random uint64 in the half-open interval [0,n). 110 func Uint64n(n uint64) uint64 { 111 if n&(n-1) == 0 { // n is power of two, can mask 112 return u64() & (n - 1) 113 } 114 max := maxUint64 - maxUint64%uint64(n) 115 v := u64() 116 for v >= max { 117 v = u64() 118 } 119 return v % n 120 } 121 122 // A Real is a real number. 123 type Real interface { 124 constraints.Signed | constraints.Unsigned 125 } 126 127 // Jitter returns a pseudo-random value in the interval [v - factor*v, v + factor*v]. 128 func Jitter[T Real](v T, factor float64) T { 129 r := Float64() 130 // r = [0, 1) 131 // 2*r = [0, 2) 132 // 2*r - 1 = [-1, 1) 133 // j*(2*r - 1) = [-j, j) 134 // 1 + j*(2*r - 1) = [1 - j, 1 + j) 135 // b*(1 + j*(2*r - 1)) = [b - j*b, b + j*b) 136 return T(float64(v) * (1 + (factor * (2*r - 1)))) 137 } 138 139 // Shuffle pseudo-randomizes the order of elements in s. 140 func Shuffle[E any](s []E) { 141 // Fisher-Yates shuffle: https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle 142 i := len(s) - 1 143 // Shuffle really ought not be called with slice indices that requires more than 31 bits. 144 // Nevertheless, handle it as best we can. 145 for ; i >= maxInt32-1; i-- { 146 j := Int63n(int64(i + 1)) 147 s[i], s[j] = s[j], s[i] 148 } 149 // Switch to 31-bit indices. 150 for ; i > 0; i-- { 151 j := Int31n(int32(i + 1)) 152 s[i], s[j] = s[j], s[i] 153 } 154 } 155 156 var ioReader io.Reader = &reader{} 157 158 // Reader returns an io.Reader that fills the read buffer with 159 // pseudo-random bytes and never returns an error. 160 func Reader() io.Reader { 161 return ioReader 162 } 163 164 type reader struct{} 165 166 func (*reader) Read(p []byte) (int, error) { 167 Fill(p) 168 return len(p), nil 169 } 170 171 // Fill fills b with pseudo-random bytes. 172 func Fill(p []byte) { 173 for len(p) >= 8 { 174 putU64(p, u64()) 175 p = p[8:] 176 } 177 switch { 178 case len(p) > 4: 179 fill(p, u64()) 180 case len(p) > 0: 181 fill(p, u32()) 182 } 183 } 184 185 func fill[T interface{ uint32 | uint64 }](p []byte, v T) { 186 for i := range p { 187 p[i] = byte(v >> (i * 8)) 188 } 189 }