v / vlib / rand / dist_test.v
130 lines · 114 sloc · 2.62 KB · a302236be40c366eeffb694e673cce83fd4b6e4a
Raw
1import math
2import rand
3
4// The sample size to be used
5const count = 2000
6// Accepted error is within 5% of the actual values.
7const error = 0.05
8// The seeds used (for reproducible testing)
9const seeds = [[u32(0x24ffff), 0xabcd], [u32(0x141024), 0x42851],
10 [u32(0x1452), 0x90cd]]
11
12fn 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
29fn 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
56fn 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
84fn 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
109fn 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