3 ms·
Use PCG: https://www.pcg-random.org/ https://www.pcg-random.org/ Here is a stand-alone implementation of PCG32 in Go: package pcg32 type Src [2]uint64
by 37ef_ced3 5y ago
Use PCG: https://www.pcg-random.org/ https://www.pcg-random.org/
Here is a stand-alone implementation of PCG32 in Go:
package pcg32
type Src [2]uint64
func New(bits1, bits2 uint64) *Src {
return &Src{bits1, bits2 | 1}
}
func (s *Src) Uint32() uint32 {
var (
x = s[0]
y = uint32(x >> 59)
z = uint32((x>>18 ^ x) >> 27)
)
s[0] = s[1] + x*6364136223846793005
return z>>y | z<<(-y&31)
}
func (s *Src) LessThan(n uint32) uint32 {
for min := -n % n; ; {
r := s.Uint32()
if r >= min {
return r % n
}
}
}
- kloch 5y agoMultipliers for other widths: https://www.pcg-random.org/posts/does-it-beat-the-minimal-standard.html https://www.pcg-random.org/posts/does-it-beat-the-minimal-st...
- SamiPerttu 5y agoUnfortunately, any PCG code is not complete without a seeding procedure. That is, if you enter non-random seeds, you can get correlated streams, which is very bad for randomness.
- 37ef_ced3 5y agoYou need 128 random bits to seed the generator (i.e., two uint64 variables). The bits1 and bits2 arguments to pcg32.New() should each be 64 bits of "noise". They may be drawn from /dev/urandom or whatever. You can use crypto/rand.Read() from Go's standard library, for example. Just read 16 bytes using crypto/rand.Read() and use encoding/binary.LittleEndian.Uint64() to produce bits1 and bits2. Or you can use a hash to produce bits1 and bits2. If you want to use a constant seed, take 32 hex digits from an arbitrary git commit id. Like this: bits1=0xd240853866f20fc3 bits2=0xe536cb3bca86c86c It's an orthogonal issue.