| 1 | import math |
| 2 | import rand |
| 3 | |
| 4 | // The sample size to be used |
| 5 | const count = 2000 |
| 6 | // Accepted error is within 5% of the actual values. |
| 7 | const error = 0.05 |
| 8 | // The seeds used (for reproducible testing) |
| 9 | const seeds = [[u32(0x24ffff), 0xabcd], [u32(0x141024), 0x42851], |
| 10 | [u32(0x1452), 0x90cd]] |
| 11 | |
| 12 | fn test_bernoulli() { |
| 13 | ps := [0.0, 0.1, 1.0 / 3.0, 0.5, 0.8, 17.0 / 18.0, 1.0] |
| 14 | |
| 15 | for seed in seeds { |
| 16 | rand.seed(seed) |
| 17 | for p in ps { |
| 18 | mut successes := 0 |
| 19 | for _ in 0 .. count { |
| 20 | if rand.bernoulli(p) or { false } { |
| 21 | successes++ |
| 22 | } |
| 23 | } |
| 24 | assert math.abs(f64(successes) / count - p) < error |
| 25 | } |
| 26 | } |
| 27 | } |
| 28 | |
| 29 | fn test_binomial() { |
| 30 | ns := [100, 200, 1000] |
| 31 | ps := [0.0, 0.5, 0.95, 1.0] |
| 32 | |
| 33 | for seed in seeds { |
| 34 | rand.seed(seed) |
| 35 | for n in ns { |
| 36 | for p in ps { |
| 37 | np := n * p |
| 38 | npq := np * (1 - p) |
| 39 | |
| 40 | mut sum := 0 |
| 41 | mut var := 0.0 |
| 42 | for _ in 0 .. count { |
| 43 | x := rand.binomial(n, p) or { 0 } |
| 44 | sum += x |
| 45 | dist := (x - np) |
| 46 | var += dist * dist |
| 47 | } |
| 48 | |
| 49 | assert math.abs(f64(sum / count) - np) / n < error |
| 50 | assert math.abs(f64(var / count) - npq) / n < error |
| 51 | } |
| 52 | } |
| 53 | } |
| 54 | } |
| 55 | |
| 56 | fn test_normal_pair() { |
| 57 | mus := [0, 10, 100, -40] |
| 58 | sigmas := [1, 2, 40, 5] |
| 59 | total := 2 * count |
| 60 | |
| 61 | for seed in seeds { |
| 62 | rand.seed(seed) |
| 63 | for mu in mus { |
| 64 | for sigma in sigmas { |
| 65 | mut sum := 0.0 |
| 66 | mut var := 0.0 |
| 67 | for _ in 0 .. count { |
| 68 | x, y := rand.normal_pair(mu: mu, sigma: sigma) or { 0.0, 0.0 } |
| 69 | sum += x + y |
| 70 | dist_x := x - mu |
| 71 | dist_y := y - mu |
| 72 | var += dist_x * dist_x |
| 73 | var += dist_y * dist_y |
| 74 | } |
| 75 | |
| 76 | variance := sigma * sigma |
| 77 | assert math.abs(f64(sum / total) - mu) / sigma < 1 |
| 78 | assert math.abs(f64(var / total) - variance) / variance < 2 * error |
| 79 | } |
| 80 | } |
| 81 | } |
| 82 | } |
| 83 | |
| 84 | fn test_normal() { |
| 85 | mus := [0, 10, 100, -40, 20] |
| 86 | sigmas := [1, 2, 5] |
| 87 | |
| 88 | for seed in seeds { |
| 89 | rand.seed(seed) |
| 90 | for mu in mus { |
| 91 | for sigma in sigmas { |
| 92 | mut sum := 0.0 |
| 93 | mut var := 0.0 |
| 94 | for _ in 0 .. count { |
| 95 | x := rand.normal(mu: mu, sigma: sigma) or { 0.0 } |
| 96 | sum += x |
| 97 | dist := x - mu |
| 98 | var += dist * dist |
| 99 | } |
| 100 | |
| 101 | variance := sigma * sigma |
| 102 | assert math.abs(f64(sum / count) - mu) / sigma < 1 |
| 103 | assert math.abs(f64(var / count) - variance) / variance < 2 * error |
| 104 | } |
| 105 | } |
| 106 | } |
| 107 | } |
| 108 | |
| 109 | fn test_exponential() { |
| 110 | lambdas := [1.0, 10, 1 / 20.0, 1 / 10000.0, 1 / 524.0, 200] |
| 111 | |
| 112 | for seed in seeds { |
| 113 | rand.seed(seed) |
| 114 | for lambda in lambdas { |
| 115 | mu := 1 / lambda |
| 116 | variance := mu * mu |
| 117 | mut sum := 0.0 |
| 118 | mut var := 0.0 |
| 119 | for _ in 0 .. count { |
| 120 | x := rand.exponential(lambda) |
| 121 | sum += x |
| 122 | dist := x - mu |
| 123 | var += dist * dist |
| 124 | } |
| 125 | |
| 126 | assert math.abs((f64(sum / count) - mu) / mu) < error |
| 127 | assert math.abs((f64(var / count) - variance) / variance) < 2 * error |
| 128 | } |
| 129 | } |
| 130 | } |
| 131 | |