forked from leesper/go_rng
-
Notifications
You must be signed in to change notification settings - Fork 0
/
uniform.go
138 lines (121 loc) · 3.57 KB
/
uniform.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
package rng
import (
"fmt"
"math"
"math/rand"
"sync"
)
// UniformGenerator is a random number generator for uniform distribution.
// The zero value is invalid, use NewUniformGenerator to create a generator
type UniformGenerator struct {
mu *sync.Mutex
rd *rand.Rand
}
// NewUniformGenerator returns a uniform-distribution generator
// it is recommended using time.Now().UnixNano() as the seed, for example:
// urng := rng.NewUniformGenerator(time.Now().UnixNano())
func NewUniformGenerator(seed int64) *UniformGenerator {
return &UniformGenerator{mu: new(sync.Mutex), rd: rand.New(rand.NewSource(seed))}
}
// Int32 returns a random uint32
func (ung UniformGenerator) Int32() int32 {
ung.mu.Lock()
defer ung.mu.Unlock()
return ung.rd.Int31()
}
// Int64 returns a random uint64
func (ung UniformGenerator) Int64() int64 {
ung.mu.Lock()
defer ung.mu.Unlock()
return ung.rd.Int63()
}
// Int32n returns a random uint32 in [0, n)
func (ung UniformGenerator) Int32n(n int32) int32 {
if n <= 0 {
panic(fmt.Sprintf("Illegal parameter n: %d", n))
}
ung.mu.Lock()
defer ung.mu.Unlock()
return ung.rd.Int31n(n)
}
// Int64n returns a random uint64 in [0, n)
func (ung UniformGenerator) Int64n(n int64) int64 {
if n <= 0 {
panic(fmt.Sprintf("Illegal parameter n: %d", n))
}
ung.mu.Lock()
defer ung.mu.Unlock()
return ung.rd.Int63n(n)
}
// Int32Range returns a random uint32 in [a, b)
func (ung UniformGenerator) Int32Range(a, b int32) int32 {
if b <= a {
panic(fmt.Sprintf("Illegal parameter a, b: %d, %d", a, b))
}
if b-a > math.MaxInt32 {
panic(fmt.Sprintf("Illegal parameter a, b: %d, %d", a, b))
}
return a + ung.Int32n(b-a)
}
// Int64Range returns a random uint64 in [a, b)
func (ung UniformGenerator) Int64Range(a, b int64) int64 {
if b <= a {
panic(fmt.Sprintf("Illegal parameter a, b: %d, %d", a, b))
}
if b-a > math.MaxInt32 {
panic(fmt.Sprintf("Illegal parameter a, b: %d, %d", a, b))
}
return a + ung.Int64n(b-a)
}
// Float32 returns a random float32 in [0.0, 1.0)
func (ung UniformGenerator) Float32() float32 {
ung.mu.Lock()
defer ung.mu.Unlock()
return ung.rd.Float32()
}
// Float64 returns a random float64 in [0.0, 1.0)
func (ung UniformGenerator) Float64() float64 {
ung.mu.Lock()
defer ung.mu.Unlock()
return ung.rd.Float64()
}
// Float32Range returns a random float32 in [a, b)
func (ung UniformGenerator) Float32Range(a, b float32) float32 {
if !(a < b) {
panic(fmt.Sprintf("Invalid range: %.2f ~ %.2f", a, b))
}
return a + ung.Float32()*(b-a)
}
// Float32Range returns a random float32 in [a, b)
func (ung UniformGenerator) Float64Range(a, b float64) float64 {
if !(a < b) {
panic(fmt.Sprintf("Invalid range: %.2f ~ %.2f", a, b))
}
return a + ung.Float64()*(b-a)
}
// Float32n returns a random float32 in [0.0, n)
func (ung UniformGenerator) Float32n(n float32) float32 {
return ung.Float32Range(0.0, n)
}
// Float64n returns a random float64 in [0.0, n)
func (ung UniformGenerator) Float64n(n float64) float64 {
return ung.Float64Range(0.0, n)
}
// Shuffle rearrange the elements of an array in random order
func (ung UniformGenerator) Shuffle(arr []interface{}) {
N := len(arr)
for i := range arr {
r := int32(i) + ung.Int32n(int32(N-i))
arr[i], arr[r] = arr[r], arr[i]
}
}
// Shuffle rearrange the elements of the subarray[low..high] in random order
func (ung UniformGenerator) ShuffleRange(arr []interface{}, low, high int) {
if low < 0 || low > high || high >= len(arr) {
panic(fmt.Sprintf("Illegal subarray range %d ~ %d", low, high))
}
for i := low; i <= high; i++ {
r := int32(i) + ung.Int32n(int32(high-i+1))
arr[i], arr[r] = arr[r], arr[i]
}
}