/
randwrapper.go
211 lines (177 loc) · 5.06 KB
/
randwrapper.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
package randomizer
import (
"math"
"math/rand"
"sync"
"time"
)
// RandWrapper encapsulates a rand.Rand and adds more features. Implements Randomizer.
// The only way to make it concurrent safe is to use NewRandWrapper(true, ...)
// Do not use this struct directly to avoid braking changes, use the Randomizer interface!
type RandWrapper struct {
//each faker has its own entropy source
src *rand.Rand
//use the mutex only if this is true
safe bool
//the mutex has to protect all calls to the src
mutex sync.Mutex
}
// NewRandWrapper returns a wrapper of a rand.Rand with extra features.
//All functions are concurrent safe only if the param concurrentSafe==true
//If source is nil a new source will be generated with a random seed.
func NewRandWrapper(concurrentSafe bool, source rand.Source) Randomizer {
result := &RandWrapper{}
result.safe = concurrentSafe
if source == nil {
result.src = rand.New(rand.NewSource(time.Now().UTC().UnixNano()))
} else {
result.src = rand.New(source)
}
return result
}
// Seed uses the provided seed value to initialize the generator to a deterministic state.
func (f *RandWrapper) Seed(seed int64) {
if f.safe {
f.mutex.Lock()
defer f.mutex.Unlock()
}
f.src.Seed(seed)
}
// Number will generate a random number between given min And max
func (f *RandWrapper) Number(min int, max int) int {
if min == max {
return min
}
return f.Intn((max+1)-min) + min
}
// Uint8 will generate a random uint8 value
func (f *RandWrapper) Uint8() uint8 {
return uint8(f.Number(0, math.MaxUint8))
}
// Uint16 will generate a random uint16 value
func (f *RandWrapper) Uint16() uint16 {
return uint16(f.Number(0, math.MaxUint16))
}
// Uint32 will generate a random uint32 value
func (f *RandWrapper) Uint32() uint32 {
return uint32(f.Number(0, math.MaxInt32))
}
// Uint64 will generate a random uint64 value
func (f *RandWrapper) Uint64() uint64 {
if f.safe {
f.mutex.Lock()
defer f.mutex.Unlock()
}
return uint64(f.src.Int63n(math.MaxInt64))
}
// Int8 will generate a random Int8 value
func (f *RandWrapper) Int8() int8 {
return int8(f.Number(math.MinInt8, math.MaxInt8))
}
// Int16 will generate a random int16 value
func (f *RandWrapper) Int16() int16 {
return int16(f.Number(math.MinInt16, math.MaxInt16))
}
// Int32 will generate a random int32 value [math.MinInt32, math.MaxInt32)
func (f *RandWrapper) Int32() int32 {
return int32(f.Number(math.MinInt32, math.MaxInt32))
}
// Int64 will generate a random int64 value [math.MinInt64, math.MaxInt64)
func (f *RandWrapper) Int64() int64 {
if f.safe {
f.mutex.Lock()
defer f.mutex.Unlock()
}
return f.src.Int63n(math.MaxInt64) + math.MinInt64
}
// Int64Positive returns a non-negative pseudo-random 63-bit integer as an int64 [0, math.Maxint64)
func (f *RandWrapper) Int64Positive() int64 {
if f.safe {
f.mutex.Lock()
defer f.mutex.Unlock()
}
return f.src.Int63()
}
// Int32Range generates a random int32 between [min, max)
func (f *RandWrapper) Int32Range(min, max int32) int32 {
if min >= max {
return min
}
if f.safe {
f.mutex.Lock()
defer f.mutex.Unlock()
}
return f.src.Int31()%(max-min) + min
}
// Int64Range generates a random int64 between [min, max)
func (f *RandWrapper) Int64Range(min, max int64) int64 {
if min >= max {
return min
}
if f.safe {
f.mutex.Lock()
defer f.mutex.Unlock()
}
return f.src.Int63()%(max-min) + min
}
// Float32Range will generate a random float32 value between min and max
func (f *RandWrapper) Float32Range(min, max float32) float32 {
if min >= max {
return min
}
if f.safe {
f.mutex.Lock()
defer f.mutex.Unlock()
}
return f.src.Float32()*(max-min) + min
}
// Float64Range will generate a random float64 value between min and max
func (f *RandWrapper) Float64Range(min, max float64) float64 {
if min >= max {
return min
}
if f.safe {
f.mutex.Lock()
defer f.mutex.Unlock()
}
return f.src.Float64()*(max-min) + min
}
// ShuffleInts will randomize a slice of ints
func (f *RandWrapper) ShuffleInts(a []int) {
for i := range a {
j := f.Intn(i + 1)
a[i], a[j] = a[j], a[i]
}
}
// Intn returns a random number between [0, n)
func (f *RandWrapper) Intn(n int) int {
if f.safe {
f.mutex.Lock()
defer f.mutex.Unlock()
}
return f.src.Intn(n)
}
// Float32 returns a random positive float number [0.000000000001, math.MaxFloat32)
func (f *RandWrapper) Float32() float32 {
return f.Float32Range(math.SmallestNonzeroFloat32, math.MaxFloat32)
}
// Float64 returns a random positive float number [0.000000000001, math.MaxFloat64)
func (f *RandWrapper) Float64() float64 {
return f.Float64Range(math.SmallestNonzeroFloat64, math.MaxFloat64)
}
// Float64Unary returns, as a float64, a pseudo-random number in [0.0,1.0) from the default Source.
func (f *RandWrapper) Float64Unary() float64 {
if f.safe {
f.mutex.Lock()
defer f.mutex.Unlock()
}
return f.src.Float64()
}
// Read generates len(p) random bytes from the default Source and writes them into p. It always returns len(p) and a nil error.
func (f *RandWrapper) Read(p []byte) (n int, err error) {
if f.safe {
f.mutex.Lock()
defer f.mutex.Unlock()
}
return f.src.Read(p)
}