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. 4 5 package rand 6 7 import ( 8 "errors" 9 "fmt" 10 "math" 11 "os" 12 "runtime" 13 "testing" 14 ) 15 16 const ( 17 numTestSamples = 10000 18 ) 19 20 type statsResults struct { 21 mean float64 22 stddev float64 23 closeEnough float64 24 maxError float64 25 } 26 27 func max(a, b float64) float64 { 28 if a > b { 29 return a 30 } 31 return b 32 } 33 34 func nearEqual(a, b, closeEnough, maxError float64) bool { 35 absDiff := math.Abs(a - b) 36 if absDiff < closeEnough { // Necessary when one value is zero and one value is close to zero. 37 return true 38 } 39 return absDiff/max(math.Abs(a), math.Abs(b)) < maxError 40 } 41 42 var testSeeds = []int64{1, 1754801282, 1698661970, 1550503961} 43 44 // checkSimilarDistribution returns success if the mean and stddev of the 45 // two statsResults are similar. 46 func (this *statsResults) checkSimilarDistribution(expected *statsResults) error { 47 if !nearEqual(this.mean, expected.mean, expected.closeEnough, expected.maxError) { 48 s := fmt.Sprintf("mean %v != %v (allowed error %v, %v)", this.mean, expected.mean, expected.closeEnough, expected.maxError) 49 fmt.Println(s) 50 return errors.New(s) 51 } 52 if !nearEqual(this.stddev, expected.stddev, 0, expected.maxError) { 53 s := fmt.Sprintf("stddev %v != %v (allowed error %v, %v)", this.stddev, expected.stddev, expected.closeEnough, expected.maxError) 54 fmt.Println(s) 55 return errors.New(s) 56 } 57 return nil 58 } 59 60 func getStatsResults(samples []float64) *statsResults { 61 res := new(statsResults) 62 var sum, squaresum float64 63 for _, s := range samples { 64 sum += s 65 squaresum += s * s 66 } 67 res.mean = sum / float64(len(samples)) 68 res.stddev = math.Sqrt(squaresum/float64(len(samples)) - res.mean*res.mean) 69 return res 70 } 71 72 func checkSampleDistribution(t *testing.T, samples []float64, expected *statsResults) { 73 actual := getStatsResults(samples) 74 err := actual.checkSimilarDistribution(expected) 75 if err != nil { 76 t.Errorf(err.Error()) 77 } 78 } 79 80 func checkSampleSliceDistributions(t *testing.T, samples []float64, nslices int, expected *statsResults) { 81 chunk := len(samples) / nslices 82 for i := 0; i < nslices; i++ { 83 low := i * chunk 84 var high int 85 if i == nslices-1 { 86 high = len(samples) - 1 87 } else { 88 high = (i + 1) * chunk 89 } 90 checkSampleDistribution(t, samples[low:high], expected) 91 } 92 } 93 94 // 95 // Normal distribution tests 96 // 97 98 func generateNormalSamples(nsamples int, mean, stddev float64, seed int64) []float64 { 99 r := New(NewSource(seed)) 100 samples := make([]float64, nsamples) 101 for i := range samples { 102 samples[i] = r.NormFloat64()*stddev + mean 103 } 104 return samples 105 } 106 107 func testNormalDistribution(t *testing.T, nsamples int, mean, stddev float64, seed int64) { 108 //fmt.Printf("testing nsamples=%v mean=%v stddev=%v seed=%v\n", nsamples, mean, stddev, seed); 109 110 samples := generateNormalSamples(nsamples, mean, stddev, seed) 111 errorScale := max(1.0, stddev) // Error scales with stddev 112 expected := &statsResults{mean, stddev, 0.10 * errorScale, 0.08 * errorScale} 113 114 // Make sure that the entire set matches the expected distribution. 115 checkSampleDistribution(t, samples, expected) 116 117 // Make sure that each half of the set matches the expected distribution. 118 checkSampleSliceDistributions(t, samples, 2, expected) 119 120 // Make sure that each 7th of the set matches the expected distribution. 121 checkSampleSliceDistributions(t, samples, 7, expected) 122 } 123 124 // Actual tests 125 126 func TestStandardNormalValues(t *testing.T) { 127 for _, seed := range testSeeds { 128 testNormalDistribution(t, numTestSamples, 0, 1, seed) 129 } 130 } 131 132 func TestNonStandardNormalValues(t *testing.T) { 133 sdmax := 1000.0 134 mmax := 1000.0 135 if testing.Short() { 136 sdmax = 5 137 mmax = 5 138 } 139 for sd := 0.5; sd < sdmax; sd *= 2 { 140 for m := 0.5; m < mmax; m *= 2 { 141 for _, seed := range testSeeds { 142 testNormalDistribution(t, numTestSamples, m, sd, seed) 143 if testing.Short() { 144 break 145 } 146 } 147 } 148 } 149 } 150 151 // 152 // Exponential distribution tests 153 // 154 155 func generateExponentialSamples(nsamples int, rate float64, seed int64) []float64 { 156 r := New(NewSource(seed)) 157 samples := make([]float64, nsamples) 158 for i := range samples { 159 samples[i] = r.ExpFloat64() / rate 160 } 161 return samples 162 } 163 164 func testExponentialDistribution(t *testing.T, nsamples int, rate float64, seed int64) { 165 //fmt.Printf("testing nsamples=%v rate=%v seed=%v\n", nsamples, rate, seed); 166 167 mean := 1 / rate 168 stddev := mean 169 170 samples := generateExponentialSamples(nsamples, rate, seed) 171 errorScale := max(1.0, 1/rate) // Error scales with the inverse of the rate 172 expected := &statsResults{mean, stddev, 0.10 * errorScale, 0.20 * errorScale} 173 174 // Make sure that the entire set matches the expected distribution. 175 checkSampleDistribution(t, samples, expected) 176 177 // Make sure that each half of the set matches the expected distribution. 178 checkSampleSliceDistributions(t, samples, 2, expected) 179 180 // Make sure that each 7th of the set matches the expected distribution. 181 checkSampleSliceDistributions(t, samples, 7, expected) 182 } 183 184 // Actual tests 185 186 func TestStandardExponentialValues(t *testing.T) { 187 for _, seed := range testSeeds { 188 testExponentialDistribution(t, numTestSamples, 1, seed) 189 } 190 } 191 192 func TestNonStandardExponentialValues(t *testing.T) { 193 for rate := 0.05; rate < 10; rate *= 2 { 194 for _, seed := range testSeeds { 195 testExponentialDistribution(t, numTestSamples, rate, seed) 196 if testing.Short() { 197 break 198 } 199 } 200 } 201 } 202 203 // 204 // Table generation tests 205 // 206 207 func initNorm() (testKn []uint32, testWn, testFn []float32) { 208 const m1 = 1 << 31 209 var ( 210 dn float64 = rn 211 tn = dn 212 vn float64 = 9.91256303526217e-3 213 ) 214 215 testKn = make([]uint32, 128) 216 testWn = make([]float32, 128) 217 testFn = make([]float32, 128) 218 219 q := vn / math.Exp(-0.5*dn*dn) 220 testKn[0] = uint32((dn / q) * m1) 221 testKn[1] = 0 222 testWn[0] = float32(q / m1) 223 testWn[127] = float32(dn / m1) 224 testFn[0] = 1.0 225 testFn[127] = float32(math.Exp(-0.5 * dn * dn)) 226 for i := 126; i >= 1; i-- { 227 dn = math.Sqrt(-2.0 * math.Log(vn/dn+math.Exp(-0.5*dn*dn))) 228 testKn[i+1] = uint32((dn / tn) * m1) 229 tn = dn 230 testFn[i] = float32(math.Exp(-0.5 * dn * dn)) 231 testWn[i] = float32(dn / m1) 232 } 233 return 234 } 235 236 func initExp() (testKe []uint32, testWe, testFe []float32) { 237 const m2 = 1 << 32 238 var ( 239 de float64 = re 240 te = de 241 ve float64 = 3.9496598225815571993e-3 242 ) 243 244 testKe = make([]uint32, 256) 245 testWe = make([]float32, 256) 246 testFe = make([]float32, 256) 247 248 q := ve / math.Exp(-de) 249 testKe[0] = uint32((de / q) * m2) 250 testKe[1] = 0 251 testWe[0] = float32(q / m2) 252 testWe[255] = float32(de / m2) 253 testFe[0] = 1.0 254 testFe[255] = float32(math.Exp(-de)) 255 for i := 254; i >= 1; i-- { 256 de = -math.Log(ve/de + math.Exp(-de)) 257 testKe[i+1] = uint32((de / te) * m2) 258 te = de 259 testFe[i] = float32(math.Exp(-de)) 260 testWe[i] = float32(de / m2) 261 } 262 return 263 } 264 265 // compareUint32Slices returns the first index where the two slices 266 // disagree, or <0 if the lengths are the same and all elements 267 // are identical. 268 func compareUint32Slices(s1, s2 []uint32) int { 269 if len(s1) != len(s2) { 270 if len(s1) > len(s2) { 271 return len(s2) + 1 272 } 273 return len(s1) + 1 274 } 275 for i := range s1 { 276 if s1[i] != s2[i] { 277 return i 278 } 279 } 280 return -1 281 } 282 283 // compareFloat32Slices returns the first index where the two slices 284 // disagree, or <0 if the lengths are the same and all elements 285 // are identical. 286 func compareFloat32Slices(s1, s2 []float32) int { 287 if len(s1) != len(s2) { 288 if len(s1) > len(s2) { 289 return len(s2) + 1 290 } 291 return len(s1) + 1 292 } 293 for i := range s1 { 294 if !nearEqual(float64(s1[i]), float64(s2[i]), 0, 1e-7) { 295 return i 296 } 297 } 298 return -1 299 } 300 301 func TestNormTables(t *testing.T) { 302 testKn, testWn, testFn := initNorm() 303 if i := compareUint32Slices(kn[0:], testKn); i >= 0 { 304 t.Errorf("kn disagrees at index %v; %v != %v", i, kn[i], testKn[i]) 305 } 306 if i := compareFloat32Slices(wn[0:], testWn); i >= 0 { 307 t.Errorf("wn disagrees at index %v; %v != %v", i, wn[i], testWn[i]) 308 } 309 if i := compareFloat32Slices(fn[0:], testFn); i >= 0 { 310 t.Errorf("fn disagrees at index %v; %v != %v", i, fn[i], testFn[i]) 311 } 312 } 313 314 func TestExpTables(t *testing.T) { 315 testKe, testWe, testFe := initExp() 316 if i := compareUint32Slices(ke[0:], testKe); i >= 0 { 317 t.Errorf("ke disagrees at index %v; %v != %v", i, ke[i], testKe[i]) 318 } 319 if i := compareFloat32Slices(we[0:], testWe); i >= 0 { 320 t.Errorf("we disagrees at index %v; %v != %v", i, we[i], testWe[i]) 321 } 322 if i := compareFloat32Slices(fe[0:], testFe); i >= 0 { 323 t.Errorf("fe disagrees at index %v; %v != %v", i, fe[i], testFe[i]) 324 } 325 } 326 327 func TestFloat32(t *testing.T) { 328 // For issue 6721, the problem came after 7533753 calls, so check 10e6. 329 num := int(10e6) 330 // But ARM5 floating point emulation is slow (Issue 10749), so 331 // do less for that builder: 332 if testing.Short() && runtime.GOARCH == "arm" && os.Getenv("GOARM") == "5" { 333 num /= 100 // 1.72 seconds instead of 172 seconds 334 } 335 336 r := New(NewSource(1)) 337 for ct := 0; ct < num; ct++ { 338 f := r.Float32() 339 if f >= 1 { 340 t.Fatal("Float32() should be in range [0,1). ct:", ct, "f:", f) 341 } 342 } 343 } 344 345 // Benchmarks 346 347 func BenchmarkInt63Threadsafe(b *testing.B) { 348 for n := b.N; n > 0; n-- { 349 Int63() 350 } 351 } 352 353 func BenchmarkInt63Unthreadsafe(b *testing.B) { 354 r := New(NewSource(1)) 355 for n := b.N; n > 0; n-- { 356 r.Int63() 357 } 358 } 359 360 func BenchmarkIntn1000(b *testing.B) { 361 r := New(NewSource(1)) 362 for n := b.N; n > 0; n-- { 363 r.Intn(1000) 364 } 365 } 366 367 func BenchmarkInt63n1000(b *testing.B) { 368 r := New(NewSource(1)) 369 for n := b.N; n > 0; n-- { 370 r.Int63n(1000) 371 } 372 } 373 374 func BenchmarkInt31n1000(b *testing.B) { 375 r := New(NewSource(1)) 376 for n := b.N; n > 0; n-- { 377 r.Int31n(1000) 378 } 379 } 380 381 func BenchmarkFloat32(b *testing.B) { 382 r := New(NewSource(1)) 383 for n := b.N; n > 0; n-- { 384 r.Float32() 385 } 386 } 387 388 func BenchmarkFloat64(b *testing.B) { 389 r := New(NewSource(1)) 390 for n := b.N; n > 0; n-- { 391 r.Float64() 392 } 393 } 394 395 func BenchmarkPerm3(b *testing.B) { 396 r := New(NewSource(1)) 397 for n := b.N; n > 0; n-- { 398 r.Perm(3) 399 } 400 } 401 402 func BenchmarkPerm30(b *testing.B) { 403 r := New(NewSource(1)) 404 for n := b.N; n > 0; n-- { 405 r.Perm(30) 406 } 407 } 408