1
2
3
4
5 package fuzz
6
7 import (
8 "math/bits"
9 "os"
10 "strconv"
11 "strings"
12 "sync/atomic"
13 "time"
14 )
15
16 type mutatorRand interface {
17 uint32() uint32
18 intn(int) int
19 uint32n(uint32) uint32
20 exp2() int
21 bool() bool
22
23 save(randState, randInc *uint64)
24 restore(randState, randInc uint64)
25 }
26
27
28
29
30
31
32
33 var globalInc atomic.Uint64
34
35 const multiplier uint64 = 6364136223846793005
36
37
38
39 type pcgRand struct {
40 noCopy noCopy
41 state uint64
42 inc uint64
43 }
44
45 func godebugSeed() *int {
46 debug := strings.Split(os.Getenv("GODEBUG"), ",")
47 for _, f := range debug {
48 if strings.HasPrefix(f, "fuzzseed=") {
49 seed, err := strconv.Atoi(strings.TrimPrefix(f, "fuzzseed="))
50 if err != nil {
51 panic("malformed fuzzseed")
52 }
53 return &seed
54 }
55 }
56 return nil
57 }
58
59
60 func newPcgRand() *pcgRand {
61 r := new(pcgRand)
62 now := uint64(time.Now().UnixNano())
63 if seed := godebugSeed(); seed != nil {
64 now = uint64(*seed)
65 }
66 inc := globalInc.Add(1)
67 r.state = now
68 r.inc = (inc << 1) | 1
69 r.step()
70 r.state += now
71 r.step()
72 return r
73 }
74
75 func (r *pcgRand) step() {
76 r.state *= multiplier
77 r.state += r.inc
78 }
79
80 func (r *pcgRand) save(randState, randInc *uint64) {
81 *randState = r.state
82 *randInc = r.inc
83 }
84
85 func (r *pcgRand) restore(randState, randInc uint64) {
86 r.state = randState
87 r.inc = randInc
88 }
89
90
91 func (r *pcgRand) uint32() uint32 {
92 x := r.state
93 r.step()
94 return bits.RotateLeft32(uint32(((x>>18)^x)>>27), -int(x>>59))
95 }
96
97
98
99 func (r *pcgRand) intn(n int) int {
100 if int(uint32(n)) != n {
101 panic("large Intn")
102 }
103 return int(r.uint32n(uint32(n)))
104 }
105
106
107
108
109
110
111 func (r *pcgRand) uint32n(n uint32) uint32 {
112 v := r.uint32()
113 prod := uint64(v) * uint64(n)
114 low := uint32(prod)
115 if low < n {
116 thresh := uint32(-int32(n)) % n
117 for low < thresh {
118 v = r.uint32()
119 prod = uint64(v) * uint64(n)
120 low = uint32(prod)
121 }
122 }
123 return uint32(prod >> 32)
124 }
125
126
127 func (r *pcgRand) exp2() int {
128 return bits.TrailingZeros32(r.uint32())
129 }
130
131
132 func (r *pcgRand) bool() bool {
133 return r.uint32()&1 == 0
134 }
135
136
137
138
139
140
141 type noCopy struct{}
142
143
144 func (*noCopy) Lock() {}
145 func (*noCopy) Unlock() {}
146
View as plain text