github.com/zhangyunhao116/fastrand@v0.4.0/fastrand.go (about) 1 // Package fastrand is the fastest pseudorandom number generator in Go(multiple-cores). 2 package fastrand 3 4 import ( 5 "math/bits" 6 "unsafe" 7 ) 8 9 // Uint32 returns a pseudo-random 32-bit value as a uint32. 10 var Uint32 = runtimefastrand 11 12 // Uint64 returns a pseudo-random 64-bit value as a uint64. 13 var Uint64 = runtimefastrand64 14 15 // Int returns a non-negative pseudo-random int. 16 func Int() int { 17 // EQ 18 u := uint(Int63()) 19 return int(u << 1 >> 1) // clear sign bit if int == int32 20 } 21 22 // Int31 returns a non-negative pseudo-random 31-bit integer as an int32. 23 func Int31() int32 { return int32(Uint32() & (1<<31 - 1)) } 24 25 // Int63 returns a non-negative pseudo-random 63-bit integer as an int64. 26 func Int63() int64 { 27 // EQ 28 return int64(Uint64() & (1<<63 - 1)) 29 } 30 31 // Int63n returns, as an int64, a non-negative pseudo-random number in [0,n). 32 // It panics if n <= 0. 33 func Int63n(n int64) int64 { 34 // EQ 35 if n <= 0 { 36 panic("invalid argument to Int63n") 37 } 38 if n&(n-1) == 0 { // n is power of two, can mask 39 return Int63() & (n - 1) 40 } 41 max := int64((1 << 63) - 1 - (1<<63)%uint64(n)) 42 v := Int63() 43 for v > max { 44 v = Int63() 45 } 46 return v % n 47 } 48 49 // Int31n returns, as an int32, a non-negative pseudo-random number in [0,n). 50 // It panics if n <= 0. 51 // For implementation details, see: 52 // https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction 53 func Int31n(n int32) int32 { 54 // EQ 55 if n <= 0 { 56 panic("invalid argument to Int31n") 57 } 58 v := Uint32() 59 prod := uint64(v) * uint64(n) 60 low := uint32(prod) 61 if low < uint32(n) { 62 thresh := uint32(-n) % uint32(n) 63 for low < thresh { 64 v = Uint32() 65 prod = uint64(v) * uint64(n) 66 low = uint32(prod) 67 } 68 } 69 return int32(prod >> 32) 70 } 71 72 // Intn returns, as an int, a non-negative pseudo-random number in [0,n). 73 // It panics if n <= 0. 74 func Intn(n int) int { 75 // EQ 76 if n <= 0 { 77 panic("invalid argument to Intn") 78 } 79 if n <= 1<<31-1 { 80 return int(Int31n(int32(n))) 81 } 82 return int(Int63n(int64(n))) 83 } 84 85 func Float64() float64 { 86 // EQ 87 return float64(Int63n(1<<53)) / (1 << 53) 88 } 89 90 func Float32() float32 { 91 // EQ 92 return float32(Int31n(1<<24)) / (1 << 24) 93 } 94 95 // Uint returns a pseudo-random 32-bit or 64-bit value. 96 var Uint = runtimefastrandu 97 98 // Uintn returns a pseudo-random number in [0,n). 99 func Uintn(n uint) uint { 100 return Uint() % n 101 } 102 103 // Uint32n returns a pseudo-random number in [0,n). 104 // 105 //go:nosplit 106 func Uint32n(n uint32) uint32 { 107 // This is similar to Uint32() % n, but faster. 108 // See https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/ 109 return uint32(uint64(Uint32()) * uint64(n) >> 32) 110 } 111 112 // Uint64n returns a pseudo-random number in [0,n). 113 func Uint64n(n uint64) uint64 { 114 return Uint64() % n 115 } 116 117 // wyrand: https://github.com/wangyi-fudan/wyhash 118 type wyrand uint64 119 120 func _wymix(a, b uint64) uint64 { 121 hi, lo := bits.Mul64(a, b) 122 return hi ^ lo 123 } 124 125 func (r *wyrand) Uint64() uint64 { 126 *r += wyrand(0xa0761d6478bd642f) 127 return _wymix(uint64(*r), uint64(*r^wyrand(0xe7037ed1a0b428db))) 128 } 129 130 func (r *wyrand) Uint64n(n uint64) uint64 { 131 return r.Uint64() % n 132 } 133 134 func (r *wyrand) Uint32() uint32 { 135 return uint32(Uint64()) 136 } 137 138 func (r *wyrand) Uint32n(n int) uint32 { 139 // This is similar to Uint32() % n, but faster. 140 // See https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/ 141 return uint32(uint64(r.Uint32()) * uint64(n) >> 32) 142 } 143 144 // Read generates len(p) random bytes and writes them into p. 145 // It always returns len(p) and a nil error. 146 // It is safe for concurrent use. 147 func Read(p []byte) (int, error) { 148 l := len(p) 149 if l == 0 { 150 return 0, nil 151 } 152 153 r := wyrand(Uint32()) 154 155 if l >= 8 { 156 var i int 157 uint64p := *(*[]uint64)(unsafe.Pointer(&p)) 158 for l >= 8 { 159 uint64p[i] = r.Uint64() 160 i++ 161 l -= 8 162 } 163 } 164 165 if l > 0 { 166 for l > 0 { 167 p[len(p)-l] = byte(r.Uint64() >> (l * 8)) 168 l-- 169 } 170 } 171 172 return len(p), nil 173 } 174 175 // Shuffle pseudo-randomizes the order of elements. 176 // n is the number of elements. Shuffle panics if n < 0. 177 // swap swaps the elements with indexes i and j. 178 func Shuffle(n int, swap func(i, j int)) { 179 if n < 0 { 180 panic("invalid argument to Shuffle") 181 } 182 // Fisher-Yates shuffle: https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle 183 // Shuffle really ought not be called with n that doesn't fit in 32 bits. 184 // Not only will it take a very long time, but with 2³¹! possible permutations, 185 // there's no way that any PRNG can have a big enough internal state to 186 // generate even a minuscule percentage of the possible permutations. 187 // Nevertheless, the right API signature accepts an int n, so handle it as best we can. 188 i := n - 1 189 for ; i > 1<<31-1-1; i-- { 190 j := int(Int63n(int64(i + 1))) 191 swap(i, j) 192 } 193 for ; i > 0; i-- { 194 j := int(Int31n(int32(i + 1))) 195 swap(i, j) 196 } 197 } 198 199 // Perm returns, as a slice of n ints, a pseudo-random permutation of the integers 200 // in the half-open interval [0,n). 201 func Perm(n int) []int { 202 m := make([]int, n) 203 for i := 1; i < n; i++ { 204 j := Intn(i + 1) 205 m[i] = m[j] 206 m[j] = i 207 } 208 return m 209 }