1 //===----------------------------------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // REQUIRES: long_tests
11 
12 // <random>
13 
14 // template<class IntType = int>
15 // class binomial_distribution
16 
17 // template<class _URNG> result_type operator()(_URNG& g);
18 
19 #include <random>
20 #include <numeric>
21 #include <vector>
22 #include <cassert>
23 
24 template <class T>
25 inline
26 T
sqr(T x)27 sqr(T x)
28 {
29     return x * x;
30 }
31 
main()32 int main()
33 {
34     {
35         typedef std::binomial_distribution<> D;
36         typedef std::mt19937_64 G;
37         G g;
38         D d(5, .75);
39         const int N = 1000000;
40         std::vector<D::result_type> u;
41         for (int i = 0; i < N; ++i)
42         {
43             D::result_type v = d(g);
44             assert(d.min() <= v && v <= d.max());
45             u.push_back(v);
46         }
47         double mean = std::accumulate(u.begin(), u.end(),
48                                               double(0)) / u.size();
49         double var = 0;
50         double skew = 0;
51         double kurtosis = 0;
52         for (int i = 0; i < u.size(); ++i)
53         {
54             double d = (u[i] - mean);
55             double d2 = sqr(d);
56             var += d2;
57             skew += d * d2;
58             kurtosis += d2 * d2;
59         }
60         var /= u.size();
61         double dev = std::sqrt(var);
62         skew /= u.size() * dev * var;
63         kurtosis /= u.size() * var * var;
64         kurtosis -= 3;
65         double x_mean = d.t() * d.p();
66         double x_var = x_mean*(1-d.p());
67         double x_skew = (1-2*d.p()) / std::sqrt(x_var);
68         double x_kurtosis = (1-6*d.p()*(1-d.p())) / x_var;
69         assert(std::abs((mean - x_mean) / x_mean) < 0.01);
70         assert(std::abs((var - x_var) / x_var) < 0.01);
71         assert(std::abs((skew - x_skew) / x_skew) < 0.01);
72         assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.04);
73     }
74     {
75         typedef std::binomial_distribution<> D;
76         typedef std::mt19937 G;
77         G g;
78         D d(30, .03125);
79         const int N = 100000;
80         std::vector<D::result_type> u;
81         for (int i = 0; i < N; ++i)
82         {
83             D::result_type v = d(g);
84             assert(d.min() <= v && v <= d.max());
85             u.push_back(v);
86         }
87         double mean = std::accumulate(u.begin(), u.end(),
88                                               double(0)) / u.size();
89         double var = 0;
90         double skew = 0;
91         double kurtosis = 0;
92         for (int i = 0; i < u.size(); ++i)
93         {
94             double d = (u[i] - mean);
95             double d2 = sqr(d);
96             var += d2;
97             skew += d * d2;
98             kurtosis += d2 * d2;
99         }
100         var /= u.size();
101         double dev = std::sqrt(var);
102         skew /= u.size() * dev * var;
103         kurtosis /= u.size() * var * var;
104         kurtosis -= 3;
105         double x_mean = d.t() * d.p();
106         double x_var = x_mean*(1-d.p());
107         double x_skew = (1-2*d.p()) / std::sqrt(x_var);
108         double x_kurtosis = (1-6*d.p()*(1-d.p())) / x_var;
109         assert(std::abs((mean - x_mean) / x_mean) < 0.01);
110         assert(std::abs((var - x_var) / x_var) < 0.01);
111         assert(std::abs((skew - x_skew) / x_skew) < 0.01);
112         assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
113     }
114     {
115         typedef std::binomial_distribution<> D;
116         typedef std::mt19937 G;
117         G g;
118         D d(40, .25);
119         const int N = 100000;
120         std::vector<D::result_type> u;
121         for (int i = 0; i < N; ++i)
122         {
123             D::result_type v = d(g);
124             assert(d.min() <= v && v <= d.max());
125             u.push_back(v);
126         }
127         double mean = std::accumulate(u.begin(), u.end(),
128                                               double(0)) / u.size();
129         double var = 0;
130         double skew = 0;
131         double kurtosis = 0;
132         for (int i = 0; i < u.size(); ++i)
133         {
134             double d = (u[i] - mean);
135             double d2 = sqr(d);
136             var += d2;
137             skew += d * d2;
138             kurtosis += d2 * d2;
139         }
140         var /= u.size();
141         double dev = std::sqrt(var);
142         skew /= u.size() * dev * var;
143         kurtosis /= u.size() * var * var;
144         kurtosis -= 3;
145         double x_mean = d.t() * d.p();
146         double x_var = x_mean*(1-d.p());
147         double x_skew = (1-2*d.p()) / std::sqrt(x_var);
148         double x_kurtosis = (1-6*d.p()*(1-d.p())) / x_var;
149         assert(std::abs((mean - x_mean) / x_mean) < 0.01);
150         assert(std::abs((var - x_var) / x_var) < 0.01);
151         assert(std::abs((skew - x_skew) / x_skew) < 0.03);
152         assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.3);
153     }
154     {
155         typedef std::binomial_distribution<> D;
156         typedef std::mt19937 G;
157         G g;
158         D d(40, 0);
159         const int N = 100000;
160         std::vector<D::result_type> u;
161         for (int i = 0; i < N; ++i)
162         {
163             D::result_type v = d(g);
164             assert(d.min() <= v && v <= d.max());
165             u.push_back(v);
166         }
167         double mean = std::accumulate(u.begin(), u.end(),
168                                               double(0)) / u.size();
169         double var = 0;
170         double skew = 0;
171         double kurtosis = 0;
172         for (int i = 0; i < u.size(); ++i)
173         {
174             double d = (u[i] - mean);
175             double d2 = sqr(d);
176             var += d2;
177             skew += d * d2;
178             kurtosis += d2 * d2;
179         }
180         var /= u.size();
181         double dev = std::sqrt(var);
182         // In this case:
183         //   skew     computes to 0./0. == nan
184         //   kurtosis computes to 0./0. == nan
185         //   x_skew     == inf
186         //   x_kurtosis == inf
187         //   These tests are commented out because UBSan warns about division by 0
188 //        skew /= u.size() * dev * var;
189 //        kurtosis /= u.size() * var * var;
190 //        kurtosis -= 3;
191         double x_mean = d.t() * d.p();
192         double x_var = x_mean*(1-d.p());
193 //        double x_skew = (1-2*d.p()) / std::sqrt(x_var);
194 //        double x_kurtosis = (1-6*d.p()*(1-d.p())) / x_var;
195         assert(mean == x_mean);
196         assert(var == x_var);
197 //        assert(skew == x_skew);
198 //        assert(kurtosis == x_kurtosis);
199     }
200     {
201         typedef std::binomial_distribution<> D;
202         typedef std::mt19937 G;
203         G g;
204         D d(40, 1);
205         const int N = 100000;
206         std::vector<D::result_type> u;
207         for (int i = 0; i < N; ++i)
208         {
209             D::result_type v = d(g);
210             assert(d.min() <= v && v <= d.max());
211             u.push_back(v);
212         }
213         double mean = std::accumulate(u.begin(), u.end(),
214                                               double(0)) / u.size();
215         double var = 0;
216         double skew = 0;
217         double kurtosis = 0;
218         for (int i = 0; i < u.size(); ++i)
219         {
220             double d = (u[i] - mean);
221             double d2 = sqr(d);
222             var += d2;
223             skew += d * d2;
224             kurtosis += d2 * d2;
225         }
226         var /= u.size();
227         double dev = std::sqrt(var);
228         // In this case:
229         //   skew     computes to 0./0. == nan
230         //   kurtosis computes to 0./0. == nan
231         //   x_skew     == -inf
232         //   x_kurtosis == inf
233         //   These tests are commented out because UBSan warns about division by 0
234 //        skew /= u.size() * dev * var;
235 //        kurtosis /= u.size() * var * var;
236 //        kurtosis -= 3;
237         double x_mean = d.t() * d.p();
238         double x_var = x_mean*(1-d.p());
239 //        double x_skew = (1-2*d.p()) / std::sqrt(x_var);
240 //        double x_kurtosis = (1-6*d.p()*(1-d.p())) / x_var;
241         assert(mean == x_mean);
242         assert(var == x_var);
243 //        assert(skew == x_skew);
244 //        assert(kurtosis == x_kurtosis);
245     }
246     {
247         typedef std::binomial_distribution<> D;
248         typedef std::mt19937 G;
249         G g;
250         D d(400, 0.5);
251         const int N = 100000;
252         std::vector<D::result_type> u;
253         for (int i = 0; i < N; ++i)
254         {
255             D::result_type v = d(g);
256             assert(d.min() <= v && v <= d.max());
257             u.push_back(v);
258         }
259         double mean = std::accumulate(u.begin(), u.end(),
260                                               double(0)) / u.size();
261         double var = 0;
262         double skew = 0;
263         double kurtosis = 0;
264         for (int i = 0; i < u.size(); ++i)
265         {
266             double d = (u[i] - mean);
267             double d2 = sqr(d);
268             var += d2;
269             skew += d * d2;
270             kurtosis += d2 * d2;
271         }
272         var /= u.size();
273         double dev = std::sqrt(var);
274         skew /= u.size() * dev * var;
275         kurtosis /= u.size() * var * var;
276         kurtosis -= 3;
277         double x_mean = d.t() * d.p();
278         double x_var = x_mean*(1-d.p());
279         double x_skew = (1-2*d.p()) / std::sqrt(x_var);
280         double x_kurtosis = (1-6*d.p()*(1-d.p())) / x_var;
281         assert(std::abs((mean - x_mean) / x_mean) < 0.01);
282         assert(std::abs((var - x_var) / x_var) < 0.01);
283         assert(std::abs(skew - x_skew) < 0.01);
284         assert(std::abs(kurtosis - x_kurtosis) < 0.01);
285     }
286     {
287         typedef std::binomial_distribution<> D;
288         typedef std::mt19937 G;
289         G g;
290         D d(1, 0.5);
291         const int N = 100000;
292         std::vector<D::result_type> u;
293         for (int i = 0; i < N; ++i)
294         {
295             D::result_type v = d(g);
296             assert(d.min() <= v && v <= d.max());
297             u.push_back(v);
298         }
299         double mean = std::accumulate(u.begin(), u.end(),
300                                               double(0)) / u.size();
301         double var = 0;
302         double skew = 0;
303         double kurtosis = 0;
304         for (int i = 0; i < u.size(); ++i)
305         {
306             double d = (u[i] - mean);
307             double d2 = sqr(d);
308             var += d2;
309             skew += d * d2;
310             kurtosis += d2 * d2;
311         }
312         var /= u.size();
313         double dev = std::sqrt(var);
314         skew /= u.size() * dev * var;
315         kurtosis /= u.size() * var * var;
316         kurtosis -= 3;
317         double x_mean = d.t() * d.p();
318         double x_var = x_mean*(1-d.p());
319         double x_skew = (1-2*d.p()) / std::sqrt(x_var);
320         double x_kurtosis = (1-6*d.p()*(1-d.p())) / x_var;
321         assert(std::abs((mean - x_mean) / x_mean) < 0.01);
322         assert(std::abs((var - x_var) / x_var) < 0.01);
323         assert(std::abs(skew - x_skew) < 0.01);
324         assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
325     }
326     {
327         const int N = 100000;
328         std::mt19937 gen1;
329         std::mt19937 gen2;
330 
331         std::binomial_distribution<>         dist1(5, 0.1);
332         std::binomial_distribution<unsigned> dist2(5, 0.1);
333 
334         for(int i = 0; i < N; ++i)
335             assert(dist1(gen1) == dist2(gen2));
336     }
337     {
338         typedef std::binomial_distribution<> D;
339         typedef std::mt19937 G;
340         G g;
341         D d(0, 0.005);
342         const int N = 100000;
343         std::vector<D::result_type> u;
344         for (int i = 0; i < N; ++i)
345         {
346             D::result_type v = d(g);
347             assert(d.min() <= v && v <= d.max());
348             u.push_back(v);
349         }
350         double mean = std::accumulate(u.begin(), u.end(),
351                                               double(0)) / u.size();
352         double var = 0;
353         double skew = 0;
354         double kurtosis = 0;
355         for (int i = 0; i < u.size(); ++i)
356         {
357             double d = (u[i] - mean);
358             double d2 = sqr(d);
359             var += d2;
360             skew += d * d2;
361             kurtosis += d2 * d2;
362         }
363         var /= u.size();
364         double dev = std::sqrt(var);
365         // In this case:
366         //   skew     computes to 0./0. == nan
367         //   kurtosis computes to 0./0. == nan
368         //   x_skew     == inf
369         //   x_kurtosis == inf
370         //   These tests are commented out because UBSan warns about division by 0
371 //        skew /= u.size() * dev * var;
372 //        kurtosis /= u.size() * var * var;
373 //        kurtosis -= 3;
374         double x_mean = d.t() * d.p();
375         double x_var = x_mean*(1-d.p());
376 //        double x_skew = (1-2*d.p()) / std::sqrt(x_var);
377 //        double x_kurtosis = (1-6*d.p()*(1-d.p())) / x_var;
378         assert(mean == x_mean);
379         assert(var == x_var);
380 //        assert(skew == x_skew);
381 //        assert(kurtosis == x_kurtosis);
382     }
383     {
384         typedef std::binomial_distribution<> D;
385         typedef std::mt19937 G;
386         G g;
387         D d(0, 0);
388         const int N = 100000;
389         std::vector<D::result_type> u;
390         for (int i = 0; i < N; ++i)
391         {
392             D::result_type v = d(g);
393             assert(d.min() <= v && v <= d.max());
394             u.push_back(v);
395         }
396         double mean = std::accumulate(u.begin(), u.end(),
397                                               double(0)) / u.size();
398         double var = 0;
399         double skew = 0;
400         double kurtosis = 0;
401         for (int i = 0; i < u.size(); ++i)
402         {
403             double d = (u[i] - mean);
404             double d2 = sqr(d);
405             var += d2;
406             skew += d * d2;
407             kurtosis += d2 * d2;
408         }
409         var /= u.size();
410         double dev = std::sqrt(var);
411         // In this case:
412         //   skew     computes to 0./0. == nan
413         //   kurtosis computes to 0./0. == nan
414         //   x_skew     == inf
415         //   x_kurtosis == inf
416         //   These tests are commented out because UBSan warns about division by 0
417 //        skew /= u.size() * dev * var;
418 //        kurtosis /= u.size() * var * var;
419 //        kurtosis -= 3;
420         double x_mean = d.t() * d.p();
421         double x_var = x_mean*(1-d.p());
422 //        double x_skew = (1-2*d.p()) / std::sqrt(x_var);
423 //        double x_kurtosis = (1-6*d.p()*(1-d.p())) / x_var;
424         assert(mean == x_mean);
425         assert(var == x_var);
426 //        assert(skew == x_skew);
427 //        assert(kurtosis == x_kurtosis);
428     }
429     {
430         typedef std::binomial_distribution<> D;
431         typedef std::mt19937 G;
432         G g;
433         D d(0, 1);
434         const int N = 100000;
435         std::vector<D::result_type> u;
436         for (int i = 0; i < N; ++i)
437         {
438             D::result_type v = d(g);
439             assert(d.min() <= v && v <= d.max());
440             u.push_back(v);
441         }
442         double mean = std::accumulate(u.begin(), u.end(),
443                                               double(0)) / u.size();
444         double var = 0;
445         double skew = 0;
446         double kurtosis = 0;
447         for (int i = 0; i < u.size(); ++i)
448         {
449             double d = (u[i] - mean);
450             double d2 = sqr(d);
451             var += d2;
452             skew += d * d2;
453             kurtosis += d2 * d2;
454         }
455         var /= u.size();
456         double dev = std::sqrt(var);
457         // In this case:
458         //   skew     computes to 0./0. == nan
459         //   kurtosis computes to 0./0. == nan
460         //   x_skew     == -inf
461         //   x_kurtosis == inf
462         //   These tests are commented out because UBSan warns about division by 0
463 //        skew /= u.size() * dev * var;
464 //        kurtosis /= u.size() * var * var;
465 //        kurtosis -= 3;
466         double x_mean = d.t() * d.p();
467         double x_var = x_mean*(1-d.p());
468 //        double x_skew = (1-2*d.p()) / std::sqrt(x_var);
469 //        double x_kurtosis = (1-6*d.p()*(1-d.p())) / x_var;
470         assert(mean == x_mean);
471         assert(var == x_var);
472 //        assert(skew == x_skew);
473 //        assert(kurtosis == x_kurtosis);
474     }
475 }
476