1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
15 numTestSamples
= 10000
18 type statsResults
struct {
25 func max(a
, b
float64) float64 {
32 func nearEqual(a
, b
, closeEnough
, maxError
float64) bool {
33 absDiff
:= math
.Abs(a
- b
)
34 if absDiff
< closeEnough
{ // Necessary when one value is zero and one value is close to zero.
37 return absDiff
/max(math
.Abs(a
), math
.Abs(b
)) < maxError
40 var testSeeds
= []int64{1, 1754801282, 1698661970, 1550503961}
42 // checkSimilarDistribution returns success if the mean and stddev of the
43 // two statsResults are similar.
44 func (this
*statsResults
) checkSimilarDistribution(expected
*statsResults
) error
{
45 if !nearEqual(this
.mean
, expected
.mean
, expected
.closeEnough
, expected
.maxError
) {
46 s
:= fmt
.Sprintf("mean %v != %v (allowed error %v, %v)", this
.mean
, expected
.mean
, expected
.closeEnough
, expected
.maxError
)
50 if !nearEqual(this
.stddev
, expected
.stddev
, 0, expected
.maxError
) {
51 s
:= fmt
.Sprintf("stddev %v != %v (allowed error %v, %v)", this
.stddev
, expected
.stddev
, expected
.closeEnough
, expected
.maxError
)
58 func getStatsResults(samples
[]float64) *statsResults
{
59 res
:= new(statsResults
)
60 var sum
, squaresum
float64
61 for _
, s
:= range samples
{
65 res
.mean
= sum
/ float64(len(samples
))
66 res
.stddev
= math
.Sqrt(squaresum
/float64(len(samples
)) - res
.mean
*res
.mean
)
70 func checkSampleDistribution(t
*testing
.T
, samples
[]float64, expected
*statsResults
) {
71 actual
:= getStatsResults(samples
)
72 err
:= actual
.checkSimilarDistribution(expected
)
78 func checkSampleSliceDistributions(t
*testing
.T
, samples
[]float64, nslices
int, expected
*statsResults
) {
79 chunk
:= len(samples
) / nslices
80 for i
:= 0; i
< nslices
; i
++ {
84 high
= len(samples
) - 1
86 high
= (i
+ 1) * chunk
88 checkSampleDistribution(t
, samples
[low
:high
], expected
)
93 // Normal distribution tests
96 func generateNormalSamples(nsamples
int, mean
, stddev
float64, seed
int64) []float64 {
97 r
:= New(NewSource(seed
))
98 samples
:= make([]float64, nsamples
)
99 for i
:= range samples
{
100 samples
[i
] = r
.NormFloat64()*stddev
+ mean
105 func testNormalDistribution(t
*testing
.T
, nsamples
int, mean
, stddev
float64, seed
int64) {
106 //fmt.Printf("testing nsamples=%v mean=%v stddev=%v seed=%v\n", nsamples, mean, stddev, seed);
108 samples
:= generateNormalSamples(nsamples
, mean
, stddev
, seed
)
109 errorScale
:= max(1.0, stddev
) // Error scales with stddev
110 expected
:= &statsResults
{mean
, stddev
, 0.10 * errorScale
, 0.08 * errorScale
}
112 // Make sure that the entire set matches the expected distribution.
113 checkSampleDistribution(t
, samples
, expected
)
115 // Make sure that each half of the set matches the expected distribution.
116 checkSampleSliceDistributions(t
, samples
, 2, expected
)
118 // Make sure that each 7th of the set matches the expected distribution.
119 checkSampleSliceDistributions(t
, samples
, 7, expected
)
124 func TestStandardNormalValues(t
*testing
.T
) {
125 for _
, seed
:= range testSeeds
{
126 testNormalDistribution(t
, numTestSamples
, 0, 1, seed
)
130 func TestNonStandardNormalValues(t
*testing
.T
) {
137 for sd
:= 0.5; sd
< sdmax
; sd
*= 2 {
138 for m
:= 0.5; m
< mmax
; m
*= 2 {
139 for _
, seed
:= range testSeeds
{
140 testNormalDistribution(t
, numTestSamples
, m
, sd
, seed
)
150 // Exponential distribution tests
153 func generateExponentialSamples(nsamples
int, rate
float64, seed
int64) []float64 {
154 r
:= New(NewSource(seed
))
155 samples
:= make([]float64, nsamples
)
156 for i
:= range samples
{
157 samples
[i
] = r
.ExpFloat64() / rate
162 func testExponentialDistribution(t
*testing
.T
, nsamples
int, rate
float64, seed
int64) {
163 //fmt.Printf("testing nsamples=%v rate=%v seed=%v\n", nsamples, rate, seed);
168 samples
:= generateExponentialSamples(nsamples
, rate
, seed
)
169 errorScale
:= max(1.0, 1/rate
) // Error scales with the inverse of the rate
170 expected
:= &statsResults
{mean
, stddev
, 0.10 * errorScale
, 0.20 * errorScale
}
172 // Make sure that the entire set matches the expected distribution.
173 checkSampleDistribution(t
, samples
, expected
)
175 // Make sure that each half of the set matches the expected distribution.
176 checkSampleSliceDistributions(t
, samples
, 2, expected
)
178 // Make sure that each 7th of the set matches the expected distribution.
179 checkSampleSliceDistributions(t
, samples
, 7, expected
)
184 func TestStandardExponentialValues(t
*testing
.T
) {
185 for _
, seed
:= range testSeeds
{
186 testExponentialDistribution(t
, numTestSamples
, 1, seed
)
190 func TestNonStandardExponentialValues(t
*testing
.T
) {
191 for rate
:= 0.05; rate
< 10; rate
*= 2 {
192 for _
, seed
:= range testSeeds
{
193 testExponentialDistribution(t
, numTestSamples
, rate
, seed
)
202 // Table generation tests
205 func initNorm() (testKn
[]uint32, testWn
, testFn
[]float32) {
210 vn
float64 = 9.91256303526217e-3
213 testKn
= make([]uint32, 128)
214 testWn
= make([]float32, 128)
215 testFn
= make([]float32, 128)
217 q
:= vn
/ math
.Exp(-0.5*dn
*dn
)
218 testKn
[0] = uint32((dn
/ q
) * m1
)
220 testWn
[0] = float32(q
/ m1
)
221 testWn
[127] = float32(dn
/ m1
)
223 testFn
[127] = float32(math
.Exp(-0.5 * dn
* dn
))
224 for i
:= 126; i
>= 1; i
-- {
225 dn
= math
.Sqrt(-2.0 * math
.Log(vn
/dn
+math
.Exp(-0.5*dn
*dn
)))
226 testKn
[i
+1] = uint32((dn
/ tn
) * m1
)
228 testFn
[i
] = float32(math
.Exp(-0.5 * dn
* dn
))
229 testWn
[i
] = float32(dn
/ m1
)
234 func initExp() (testKe
[]uint32, testWe
, testFe
[]float32) {
239 ve
float64 = 3.9496598225815571993e-3
242 testKe
= make([]uint32, 256)
243 testWe
= make([]float32, 256)
244 testFe
= make([]float32, 256)
246 q
:= ve
/ math
.Exp(-de
)
247 testKe
[0] = uint32((de
/ q
) * m2
)
249 testWe
[0] = float32(q
/ m2
)
250 testWe
[255] = float32(de
/ m2
)
252 testFe
[255] = float32(math
.Exp(-de
))
253 for i
:= 254; i
>= 1; i
-- {
254 de
= -math
.Log(ve
/de
+ math
.Exp(-de
))
255 testKe
[i
+1] = uint32((de
/ te
) * m2
)
257 testFe
[i
] = float32(math
.Exp(-de
))
258 testWe
[i
] = float32(de
/ m2
)
263 // compareUint32Slices returns the first index where the two slices
264 // disagree, or <0 if the lengths are the same and all elements
266 func compareUint32Slices(s1
, s2
[]uint32) int {
267 if len(s1
) != len(s2
) {
268 if len(s1
) > len(s2
) {
281 // compareFloat32Slices returns the first index where the two slices
282 // disagree, or <0 if the lengths are the same and all elements
284 func compareFloat32Slices(s1
, s2
[]float32) int {
285 if len(s1
) != len(s2
) {
286 if len(s1
) > len(s2
) {
292 if !nearEqual(float64(s1
[i
]), float64(s2
[i
]), 0, 1e-7) {
299 func TestNormTables(t
*testing
.T
) {
300 testKn
, testWn
, testFn
:= initNorm()
301 if i
:= compareUint32Slices(kn
[0:], testKn
); i
>= 0 {
302 t
.Errorf("kn disagrees at index %v; %v != %v", i
, kn
[i
], testKn
[i
])
304 if i
:= compareFloat32Slices(wn
[0:], testWn
); i
>= 0 {
305 t
.Errorf("wn disagrees at index %v; %v != %v", i
, wn
[i
], testWn
[i
])
307 if i
:= compareFloat32Slices(fn
[0:], testFn
); i
>= 0 {
308 t
.Errorf("fn disagrees at index %v; %v != %v", i
, fn
[i
], testFn
[i
])
312 func TestExpTables(t
*testing
.T
) {
313 testKe
, testWe
, testFe
:= initExp()
314 if i
:= compareUint32Slices(ke
[0:], testKe
); i
>= 0 {
315 t
.Errorf("ke disagrees at index %v; %v != %v", i
, ke
[i
], testKe
[i
])
317 if i
:= compareFloat32Slices(we
[0:], testWe
); i
>= 0 {
318 t
.Errorf("we disagrees at index %v; %v != %v", i
, we
[i
], testWe
[i
])
320 if i
:= compareFloat32Slices(fe
[0:], testFe
); i
>= 0 {
321 t
.Errorf("fe disagrees at index %v; %v != %v", i
, fe
[i
], testFe
[i
])
325 // For issue 6721, the problem came after 7533753 calls, so check 10e6.
326 func TestFloat32(t
*testing
.T
) {
327 r
:= New(NewSource(1))
328 for ct
:= 0; ct
< 10e6
; ct
++ {
331 t
.Fatal("Float32() should be in range [0,1). ct:", ct
, "f:", f
)
338 func BenchmarkInt63Threadsafe(b
*testing
.B
) {
339 for n
:= b
.N
; n
> 0; n
-- {
344 func BenchmarkInt63Unthreadsafe(b
*testing
.B
) {
345 r
:= New(NewSource(1))
346 for n
:= b
.N
; n
> 0; n
-- {
351 func BenchmarkIntn1000(b
*testing
.B
) {
352 r
:= New(NewSource(1))
353 for n
:= b
.N
; n
> 0; n
-- {
358 func BenchmarkInt63n1000(b
*testing
.B
) {
359 r
:= New(NewSource(1))
360 for n
:= b
.N
; n
> 0; n
-- {
365 func BenchmarkInt31n1000(b
*testing
.B
) {
366 r
:= New(NewSource(1))
367 for n
:= b
.N
; n
> 0; n
-- {
372 func BenchmarkFloat32(b
*testing
.B
) {
373 r
:= New(NewSource(1))
374 for n
:= b
.N
; n
> 0; n
-- {
379 func BenchmarkPerm3(b
*testing
.B
) {
380 r
:= New(NewSource(1))
381 for n
:= b
.N
; n
> 0; n
-- {
386 func BenchmarkPerm30(b
*testing
.B
) {
387 r
:= New(NewSource(1))
388 for n
:= b
.N
; n
> 0; n
-- {