github.com/flyinox/gosm@v0.0.0-20171117061539-16768cb62077/src/math/rand/rand_test.go (about) 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 "bytes" 9 "errors" 10 "fmt" 11 "internal/testenv" 12 "io" 13 "math" 14 "os" 15 "runtime" 16 "testing" 17 "testing/iotest" 18 ) 19 20 const ( 21 numTestSamples = 10000 22 ) 23 24 type statsResults struct { 25 mean float64 26 stddev float64 27 closeEnough float64 28 maxError float64 29 } 30 31 func max(a, b float64) float64 { 32 if a > b { 33 return a 34 } 35 return b 36 } 37 38 func nearEqual(a, b, closeEnough, maxError float64) bool { 39 absDiff := math.Abs(a - b) 40 if absDiff < closeEnough { // Necessary when one value is zero and one value is close to zero. 41 return true 42 } 43 return absDiff/max(math.Abs(a), math.Abs(b)) < maxError 44 } 45 46 var testSeeds = []int64{1, 1754801282, 1698661970, 1550503961} 47 48 // checkSimilarDistribution returns success if the mean and stddev of the 49 // two statsResults are similar. 50 func (this *statsResults) checkSimilarDistribution(expected *statsResults) error { 51 if !nearEqual(this.mean, expected.mean, expected.closeEnough, expected.maxError) { 52 s := fmt.Sprintf("mean %v != %v (allowed error %v, %v)", this.mean, expected.mean, expected.closeEnough, expected.maxError) 53 fmt.Println(s) 54 return errors.New(s) 55 } 56 if !nearEqual(this.stddev, expected.stddev, 0, expected.maxError) { 57 s := fmt.Sprintf("stddev %v != %v (allowed error %v, %v)", this.stddev, expected.stddev, expected.closeEnough, expected.maxError) 58 fmt.Println(s) 59 return errors.New(s) 60 } 61 return nil 62 } 63 64 func getStatsResults(samples []float64) *statsResults { 65 res := new(statsResults) 66 var sum, squaresum float64 67 for _, s := range samples { 68 sum += s 69 squaresum += s * s 70 } 71 res.mean = sum / float64(len(samples)) 72 res.stddev = math.Sqrt(squaresum/float64(len(samples)) - res.mean*res.mean) 73 return res 74 } 75 76 func checkSampleDistribution(t *testing.T, samples []float64, expected *statsResults) { 77 actual := getStatsResults(samples) 78 err := actual.checkSimilarDistribution(expected) 79 if err != nil { 80 t.Errorf(err.Error()) 81 } 82 } 83 84 func checkSampleSliceDistributions(t *testing.T, samples []float64, nslices int, expected *statsResults) { 85 chunk := len(samples) / nslices 86 for i := 0; i < nslices; i++ { 87 low := i * chunk 88 var high int 89 if i == nslices-1 { 90 high = len(samples) - 1 91 } else { 92 high = (i + 1) * chunk 93 } 94 checkSampleDistribution(t, samples[low:high], expected) 95 } 96 } 97 98 // 99 // Normal distribution tests 100 // 101 102 func generateNormalSamples(nsamples int, mean, stddev float64, seed int64) []float64 { 103 r := New(NewSource(seed)) 104 samples := make([]float64, nsamples) 105 for i := range samples { 106 samples[i] = r.NormFloat64()*stddev + mean 107 } 108 return samples 109 } 110 111 func testNormalDistribution(t *testing.T, nsamples int, mean, stddev float64, seed int64) { 112 //fmt.Printf("testing nsamples=%v mean=%v stddev=%v seed=%v\n", nsamples, mean, stddev, seed); 113 114 samples := generateNormalSamples(nsamples, mean, stddev, seed) 115 errorScale := max(1.0, stddev) // Error scales with stddev 116 expected := &statsResults{mean, stddev, 0.10 * errorScale, 0.08 * errorScale} 117 118 // Make sure that the entire set matches the expected distribution. 119 checkSampleDistribution(t, samples, expected) 120 121 // Make sure that each half of the set matches the expected distribution. 122 checkSampleSliceDistributions(t, samples, 2, expected) 123 124 // Make sure that each 7th of the set matches the expected distribution. 125 checkSampleSliceDistributions(t, samples, 7, expected) 126 } 127 128 // Actual tests 129 130 func TestStandardNormalValues(t *testing.T) { 131 for _, seed := range testSeeds { 132 testNormalDistribution(t, numTestSamples, 0, 1, seed) 133 } 134 } 135 136 func TestNonStandardNormalValues(t *testing.T) { 137 sdmax := 1000.0 138 mmax := 1000.0 139 if testing.Short() { 140 sdmax = 5 141 mmax = 5 142 } 143 for sd := 0.5; sd < sdmax; sd *= 2 { 144 for m := 0.5; m < mmax; m *= 2 { 145 for _, seed := range testSeeds { 146 testNormalDistribution(t, numTestSamples, m, sd, seed) 147 if testing.Short() { 148 break 149 } 150 } 151 } 152 } 153 } 154 155 // 156 // Exponential distribution tests 157 // 158 159 func generateExponentialSamples(nsamples int, rate float64, seed int64) []float64 { 160 r := New(NewSource(seed)) 161 samples := make([]float64, nsamples) 162 for i := range samples { 163 samples[i] = r.ExpFloat64() / rate 164 } 165 return samples 166 } 167 168 func testExponentialDistribution(t *testing.T, nsamples int, rate float64, seed int64) { 169 //fmt.Printf("testing nsamples=%v rate=%v seed=%v\n", nsamples, rate, seed); 170 171 mean := 1 / rate 172 stddev := mean 173 174 samples := generateExponentialSamples(nsamples, rate, seed) 175 errorScale := max(1.0, 1/rate) // Error scales with the inverse of the rate 176 expected := &statsResults{mean, stddev, 0.10 * errorScale, 0.20 * errorScale} 177 178 // Make sure that the entire set matches the expected distribution. 179 checkSampleDistribution(t, samples, expected) 180 181 // Make sure that each half of the set matches the expected distribution. 182 checkSampleSliceDistributions(t, samples, 2, expected) 183 184 // Make sure that each 7th of the set matches the expected distribution. 185 checkSampleSliceDistributions(t, samples, 7, expected) 186 } 187 188 // Actual tests 189 190 func TestStandardExponentialValues(t *testing.T) { 191 for _, seed := range testSeeds { 192 testExponentialDistribution(t, numTestSamples, 1, seed) 193 } 194 } 195 196 func TestNonStandardExponentialValues(t *testing.T) { 197 for rate := 0.05; rate < 10; rate *= 2 { 198 for _, seed := range testSeeds { 199 testExponentialDistribution(t, numTestSamples, rate, seed) 200 if testing.Short() { 201 break 202 } 203 } 204 } 205 } 206 207 // 208 // Table generation tests 209 // 210 211 func initNorm() (testKn []uint32, testWn, testFn []float32) { 212 const m1 = 1 << 31 213 var ( 214 dn float64 = rn 215 tn = dn 216 vn float64 = 9.91256303526217e-3 217 ) 218 219 testKn = make([]uint32, 128) 220 testWn = make([]float32, 128) 221 testFn = make([]float32, 128) 222 223 q := vn / math.Exp(-0.5*dn*dn) 224 testKn[0] = uint32((dn / q) * m1) 225 testKn[1] = 0 226 testWn[0] = float32(q / m1) 227 testWn[127] = float32(dn / m1) 228 testFn[0] = 1.0 229 testFn[127] = float32(math.Exp(-0.5 * dn * dn)) 230 for i := 126; i >= 1; i-- { 231 dn = math.Sqrt(-2.0 * math.Log(vn/dn+math.Exp(-0.5*dn*dn))) 232 testKn[i+1] = uint32((dn / tn) * m1) 233 tn = dn 234 testFn[i] = float32(math.Exp(-0.5 * dn * dn)) 235 testWn[i] = float32(dn / m1) 236 } 237 return 238 } 239 240 func initExp() (testKe []uint32, testWe, testFe []float32) { 241 const m2 = 1 << 32 242 var ( 243 de float64 = re 244 te = de 245 ve float64 = 3.9496598225815571993e-3 246 ) 247 248 testKe = make([]uint32, 256) 249 testWe = make([]float32, 256) 250 testFe = make([]float32, 256) 251 252 q := ve / math.Exp(-de) 253 testKe[0] = uint32((de / q) * m2) 254 testKe[1] = 0 255 testWe[0] = float32(q / m2) 256 testWe[255] = float32(de / m2) 257 testFe[0] = 1.0 258 testFe[255] = float32(math.Exp(-de)) 259 for i := 254; i >= 1; i-- { 260 de = -math.Log(ve/de + math.Exp(-de)) 261 testKe[i+1] = uint32((de / te) * m2) 262 te = de 263 testFe[i] = float32(math.Exp(-de)) 264 testWe[i] = float32(de / m2) 265 } 266 return 267 } 268 269 // compareUint32Slices returns the first index where the two slices 270 // disagree, or <0 if the lengths are the same and all elements 271 // are identical. 272 func compareUint32Slices(s1, s2 []uint32) int { 273 if len(s1) != len(s2) { 274 if len(s1) > len(s2) { 275 return len(s2) + 1 276 } 277 return len(s1) + 1 278 } 279 for i := range s1 { 280 if s1[i] != s2[i] { 281 return i 282 } 283 } 284 return -1 285 } 286 287 // compareFloat32Slices returns the first index where the two slices 288 // disagree, or <0 if the lengths are the same and all elements 289 // are identical. 290 func compareFloat32Slices(s1, s2 []float32) int { 291 if len(s1) != len(s2) { 292 if len(s1) > len(s2) { 293 return len(s2) + 1 294 } 295 return len(s1) + 1 296 } 297 for i := range s1 { 298 if !nearEqual(float64(s1[i]), float64(s2[i]), 0, 1e-7) { 299 return i 300 } 301 } 302 return -1 303 } 304 305 func TestNormTables(t *testing.T) { 306 testKn, testWn, testFn := initNorm() 307 if i := compareUint32Slices(kn[0:], testKn); i >= 0 { 308 t.Errorf("kn disagrees at index %v; %v != %v", i, kn[i], testKn[i]) 309 } 310 if i := compareFloat32Slices(wn[0:], testWn); i >= 0 { 311 t.Errorf("wn disagrees at index %v; %v != %v", i, wn[i], testWn[i]) 312 } 313 if i := compareFloat32Slices(fn[0:], testFn); i >= 0 { 314 t.Errorf("fn disagrees at index %v; %v != %v", i, fn[i], testFn[i]) 315 } 316 } 317 318 func TestExpTables(t *testing.T) { 319 testKe, testWe, testFe := initExp() 320 if i := compareUint32Slices(ke[0:], testKe); i >= 0 { 321 t.Errorf("ke disagrees at index %v; %v != %v", i, ke[i], testKe[i]) 322 } 323 if i := compareFloat32Slices(we[0:], testWe); i >= 0 { 324 t.Errorf("we disagrees at index %v; %v != %v", i, we[i], testWe[i]) 325 } 326 if i := compareFloat32Slices(fe[0:], testFe); i >= 0 { 327 t.Errorf("fe disagrees at index %v; %v != %v", i, fe[i], testFe[i]) 328 } 329 } 330 331 func hasSlowFloatingPoint() bool { 332 switch runtime.GOARCH { 333 case "arm": 334 return os.Getenv("GOARM") == "5" 335 case "mips", "mipsle", "mips64", "mips64le": 336 // Be conservative and assume that all mips boards 337 // have emulated floating point. 338 // TODO: detect what it actually has. 339 return true 340 } 341 return false 342 } 343 344 func TestFloat32(t *testing.T) { 345 // For issue 6721, the problem came after 7533753 calls, so check 10e6. 346 num := int(10e6) 347 // But do the full amount only on builders (not locally). 348 // But ARM5 floating point emulation is slow (Issue 10749), so 349 // do less for that builder: 350 if testing.Short() && (testenv.Builder() == "" || hasSlowFloatingPoint()) { 351 num /= 100 // 1.72 seconds instead of 172 seconds 352 } 353 354 r := New(NewSource(1)) 355 for ct := 0; ct < num; ct++ { 356 f := r.Float32() 357 if f >= 1 { 358 t.Fatal("Float32() should be in range [0,1). ct:", ct, "f:", f) 359 } 360 } 361 } 362 363 func testReadUniformity(t *testing.T, n int, seed int64) { 364 r := New(NewSource(seed)) 365 buf := make([]byte, n) 366 nRead, err := r.Read(buf) 367 if err != nil { 368 t.Errorf("Read err %v", err) 369 } 370 if nRead != n { 371 t.Errorf("Read returned unexpected n; %d != %d", nRead, n) 372 } 373 374 // Expect a uniform distribution of byte values, which lie in [0, 255]. 375 var ( 376 mean = 255.0 / 2 377 stddev = math.Sqrt(255.0 * 255.0 / 12.0) 378 errorScale = stddev / math.Sqrt(float64(n)) 379 ) 380 381 expected := &statsResults{mean, stddev, 0.10 * errorScale, 0.08 * errorScale} 382 383 // Cast bytes as floats to use the common distribution-validity checks. 384 samples := make([]float64, n) 385 for i, val := range buf { 386 samples[i] = float64(val) 387 } 388 // Make sure that the entire set matches the expected distribution. 389 checkSampleDistribution(t, samples, expected) 390 } 391 392 func TestReadUniformity(t *testing.T) { 393 testBufferSizes := []int{ 394 2, 4, 7, 64, 1024, 1 << 16, 1 << 20, 395 } 396 for _, seed := range testSeeds { 397 for _, n := range testBufferSizes { 398 testReadUniformity(t, n, seed) 399 } 400 } 401 } 402 403 func TestReadEmpty(t *testing.T) { 404 r := New(NewSource(1)) 405 buf := make([]byte, 0) 406 n, err := r.Read(buf) 407 if err != nil { 408 t.Errorf("Read err into empty buffer; %v", err) 409 } 410 if n != 0 { 411 t.Errorf("Read into empty buffer returned unexpected n of %d", n) 412 } 413 } 414 415 func TestReadByOneByte(t *testing.T) { 416 r := New(NewSource(1)) 417 b1 := make([]byte, 100) 418 _, err := io.ReadFull(iotest.OneByteReader(r), b1) 419 if err != nil { 420 t.Errorf("read by one byte: %v", err) 421 } 422 r = New(NewSource(1)) 423 b2 := make([]byte, 100) 424 _, err = r.Read(b2) 425 if err != nil { 426 t.Errorf("read: %v", err) 427 } 428 if !bytes.Equal(b1, b2) { 429 t.Errorf("read by one byte vs single read:\n%x\n%x", b1, b2) 430 } 431 } 432 433 func TestReadSeedReset(t *testing.T) { 434 r := New(NewSource(42)) 435 b1 := make([]byte, 128) 436 _, err := r.Read(b1) 437 if err != nil { 438 t.Errorf("read: %v", err) 439 } 440 r.Seed(42) 441 b2 := make([]byte, 128) 442 _, err = r.Read(b2) 443 if err != nil { 444 t.Errorf("read: %v", err) 445 } 446 if !bytes.Equal(b1, b2) { 447 t.Errorf("mismatch after re-seed:\n%x\n%x", b1, b2) 448 } 449 } 450 451 // Benchmarks 452 453 func BenchmarkInt63Threadsafe(b *testing.B) { 454 for n := b.N; n > 0; n-- { 455 Int63() 456 } 457 } 458 459 func BenchmarkInt63Unthreadsafe(b *testing.B) { 460 r := New(NewSource(1)) 461 for n := b.N; n > 0; n-- { 462 r.Int63() 463 } 464 } 465 466 func BenchmarkIntn1000(b *testing.B) { 467 r := New(NewSource(1)) 468 for n := b.N; n > 0; n-- { 469 r.Intn(1000) 470 } 471 } 472 473 func BenchmarkInt63n1000(b *testing.B) { 474 r := New(NewSource(1)) 475 for n := b.N; n > 0; n-- { 476 r.Int63n(1000) 477 } 478 } 479 480 func BenchmarkInt31n1000(b *testing.B) { 481 r := New(NewSource(1)) 482 for n := b.N; n > 0; n-- { 483 r.Int31n(1000) 484 } 485 } 486 487 func BenchmarkFloat32(b *testing.B) { 488 r := New(NewSource(1)) 489 for n := b.N; n > 0; n-- { 490 r.Float32() 491 } 492 } 493 494 func BenchmarkFloat64(b *testing.B) { 495 r := New(NewSource(1)) 496 for n := b.N; n > 0; n-- { 497 r.Float64() 498 } 499 } 500 501 func BenchmarkPerm3(b *testing.B) { 502 r := New(NewSource(1)) 503 for n := b.N; n > 0; n-- { 504 r.Perm(3) 505 } 506 } 507 508 func BenchmarkPerm30(b *testing.B) { 509 r := New(NewSource(1)) 510 for n := b.N; n > 0; n-- { 511 r.Perm(30) 512 } 513 } 514 515 func BenchmarkRead3(b *testing.B) { 516 r := New(NewSource(1)) 517 buf := make([]byte, 3) 518 b.ResetTimer() 519 for n := b.N; n > 0; n-- { 520 r.Read(buf) 521 } 522 } 523 524 func BenchmarkRead64(b *testing.B) { 525 r := New(NewSource(1)) 526 buf := make([]byte, 64) 527 b.ResetTimer() 528 for n := b.N; n > 0; n-- { 529 r.Read(buf) 530 } 531 } 532 533 func BenchmarkRead1000(b *testing.B) { 534 r := New(NewSource(1)) 535 buf := make([]byte, 1000) 536 b.ResetTimer() 537 for n := b.N; n > 0; n-- { 538 r.Read(buf) 539 } 540 }