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