-
Notifications
You must be signed in to change notification settings - Fork 0
/
rand.go
127 lines (114 loc) · 2.35 KB
/
rand.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
package random
import (
"math"
"math/rand"
)
const (
halfPi = 0.5 * math.Pi
)
// Dist is a distribution function
type Dist func() float64
// DiscrDist is a discrete distribution function
type DiscrDist func() int64
// Gauss returns a normally distributed float64 in the range
// [-math.MaxFloat64, +math.MaxFloat64] with standard normal distribution of
// mean=mean and stddev=stddev.
func Gauss(mean, stddev float64, src *rand.Source) Dist {
fct := func() float64 {
return rand.NormFloat64()*stddev + mean
}
if src != nil {
r := rand.New(*src)
fct = func() float64 {
return r.NormFloat64()*stddev + mean
}
}
return Dist(fct)
}
// Exp returns an exponentially distributed float64
func Exp(mean float64, src *rand.Source) Dist {
fct := func() float64 {
return rand.ExpFloat64() / mean
}
if src != nil {
r := rand.New(*src)
fct = func() float64 {
return r.ExpFloat64() / mean
}
}
return Dist(fct)
}
// Chi2 returns a Chi2 distributed random number generation function
func Chi2(ndf int64, src *rand.Source) Dist {
norm := Gauss(0, 1, src)
fct := func() float64 {
x := 0.
for i := int64(0); i < ndf; i++ {
n := norm()
x += n * n
}
return x
}
return Dist(fct)
}
// Poisson
func Poisson(mean float64, src *rand.Source) DiscrDist {
flat := Flat(0, 1, src)
fct := func() int64 {
i := int64(0)
t := math.Exp(-mean)
p := 1.0
for ; p > t; p *= flat() {
i += 1
}
return i
}
return DiscrDist(fct)
}
// Flat
func Flat(min, max float64, src *rand.Source) Dist {
delta := max - min
fct := func() float64 {
return rand.Float64()*delta + min
}
if src != nil {
r := rand.New(*src)
fct = func() float64 {
return r.Float64()*delta + min
}
}
return Dist(fct)
}
// Bernoulli
func Bernoulli(p float64, src *rand.Source) DiscrDist {
uniform := Flat(0., 1., src)
fct := func() int64 {
if uniform() < p {
return 1
}
return 0
}
return DiscrDist(fct)
}
// Binomial
func Binomial(n int64, p float64, src *rand.Source) DiscrDist {
b := Bernoulli(p, src)
fct := func() int64 {
x := int64(0)
for i := int64(0); i <= n; i++ {
x += b()
}
return x
}
return DiscrDist(fct)
}
// Breit-Wigner
func BreitWigner(flat Dist, mean, gamma float64, src *rand.Source) Dist {
fct := func() float64 {
rval := 2*flat() - 1
displ := 0.5 * gamma * math.Tan(rval*halfPi)
return mean + displ
}
return Dist(fct)
}
// EOF