| |
| |
| |
|
|
| package fuzz |
|
|
| import ( |
| "math/bits" |
| "os" |
| "strconv" |
| "strings" |
| "sync/atomic" |
| "time" |
| ) |
|
|
| type mutatorRand interface { |
| uint32() uint32 |
| intn(int) int |
| uint32n(uint32) uint32 |
| bool() bool |
|
|
| save(randState, randInc *uint64) |
| restore(randState, randInc uint64) |
| } |
|
|
| |
| |
| |
| |
| |
|
|
| var globalInc atomic.Uint64 |
|
|
| const multiplier uint64 = 6364136223846793005 |
|
|
| |
| |
| type pcgRand struct { |
| noCopy noCopy |
| state uint64 |
| inc uint64 |
| } |
|
|
| func godebugSeed() *int { |
| debug := strings.Split(os.Getenv("GODEBUG"), ",") |
| for _, f := range debug { |
| if strings.HasPrefix(f, "fuzzseed=") { |
| seed, err := strconv.Atoi(strings.TrimPrefix(f, "fuzzseed=")) |
| if err != nil { |
| panic("malformed fuzzseed") |
| } |
| return &seed |
| } |
| } |
| return nil |
| } |
|
|
| |
| func newPcgRand() *pcgRand { |
| r := new(pcgRand) |
| now := uint64(time.Now().UnixNano()) |
| if seed := godebugSeed(); seed != nil { |
| now = uint64(*seed) |
| } |
| inc := globalInc.Add(1) |
| r.state = now |
| r.inc = (inc << 1) | 1 |
| r.step() |
| r.state += now |
| r.step() |
| return r |
| } |
|
|
| func (r *pcgRand) step() { |
| r.state *= multiplier |
| r.state += r.inc |
| } |
|
|
| func (r *pcgRand) save(randState, randInc *uint64) { |
| *randState = r.state |
| *randInc = r.inc |
| } |
|
|
| func (r *pcgRand) restore(randState, randInc uint64) { |
| r.state = randState |
| r.inc = randInc |
| } |
|
|
| |
| func (r *pcgRand) uint32() uint32 { |
| x := r.state |
| r.step() |
| return bits.RotateLeft32(uint32(((x>>18)^x)>>27), -int(x>>59)) |
| } |
|
|
| |
| |
| func (r *pcgRand) intn(n int) int { |
| if int(uint32(n)) != n { |
| panic("large Intn") |
| } |
| return int(r.uint32n(uint32(n))) |
| } |
|
|
| |
| |
| |
| |
| |
| func (r *pcgRand) uint32n(n uint32) uint32 { |
| v := r.uint32() |
| prod := uint64(v) * uint64(n) |
| low := uint32(prod) |
| if low < n { |
| thresh := uint32(-int32(n)) % n |
| for low < thresh { |
| v = r.uint32() |
| prod = uint64(v) * uint64(n) |
| low = uint32(prod) |
| } |
| } |
| return uint32(prod >> 32) |
| } |
|
|
| |
| func (r *pcgRand) bool() bool { |
| return r.uint32()&1 == 0 |
| } |
|
|
| |
| |
| |
| |
| |
| type noCopy struct{} |
|
|
| |
| func (*noCopy) Lock() {} |
| func (*noCopy) Unlock() {} |
|
|