xref: /llvm-project/libcxx/test/std/numerics/rand/rand.dist/rand.dist.bern/rand.dist.bern.bin/eval.pass.cpp (revision 09e3a360581dc36d0820d3fb6da9bd7cfed87b5d)
1eb1c5037SNikolas Klauser //===----------------------------------------------------------------------===//
2eb1c5037SNikolas Klauser //
3eb1c5037SNikolas Klauser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4eb1c5037SNikolas Klauser // See https://llvm.org/LICENSE.txt for license information.
5eb1c5037SNikolas Klauser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6eb1c5037SNikolas Klauser //
7eb1c5037SNikolas Klauser //===----------------------------------------------------------------------===//
8eb1c5037SNikolas Klauser //
9eb1c5037SNikolas Klauser // REQUIRES: long_tests
10eb1c5037SNikolas Klauser 
11eb1c5037SNikolas Klauser // <random>
12eb1c5037SNikolas Klauser 
13eb1c5037SNikolas Klauser // template<class IntType = int>
14eb1c5037SNikolas Klauser // class binomial_distribution
15eb1c5037SNikolas Klauser 
16eb1c5037SNikolas Klauser // template<class _URNG> result_type operator()(_URNG& g);
17eb1c5037SNikolas Klauser 
18eb1c5037SNikolas Klauser #include <cassert>
19*09e3a360SLouis Dionne #include <cmath>
200a4aa8a1SNikolas Klauser #include <cstdint>
210a4aa8a1SNikolas Klauser #include <numeric>
220a4aa8a1SNikolas Klauser #include <random>
230a4aa8a1SNikolas Klauser #include <type_traits>
240a4aa8a1SNikolas Klauser #include <vector>
25eb1c5037SNikolas Klauser 
2607e984bcSLouis Dionne #include "test_macros.h"
2707e984bcSLouis Dionne 
28eb1c5037SNikolas Klauser template <class T>
2907e984bcSLouis Dionne T sqr(T x) {
30eb1c5037SNikolas Klauser     return x * x;
31eb1c5037SNikolas Klauser }
32eb1c5037SNikolas Klauser 
3307e984bcSLouis Dionne template <class T>
3407e984bcSLouis Dionne void test1() {
3507e984bcSLouis Dionne     typedef std::binomial_distribution<T> D;
36eb1c5037SNikolas Klauser     typedef std::mt19937_64 G;
37eb1c5037SNikolas Klauser     G g;
38eb1c5037SNikolas Klauser     D d(5, .75);
39eb1c5037SNikolas Klauser     const int N = 1000000;
4007e984bcSLouis Dionne     std::vector<typename D::result_type> u;
41eb1c5037SNikolas Klauser     for (int i = 0; i < N; ++i)
42eb1c5037SNikolas Klauser     {
4307e984bcSLouis Dionne         typename D::result_type v = d(g);
44eb1c5037SNikolas Klauser         assert(d.min() <= v && v <= d.max());
45eb1c5037SNikolas Klauser         u.push_back(v);
46eb1c5037SNikolas Klauser     }
47eb1c5037SNikolas Klauser     double mean = std::accumulate(u.begin(), u.end(),
48eb1c5037SNikolas Klauser                                           double(0)) / u.size();
49eb1c5037SNikolas Klauser     double var = 0;
50eb1c5037SNikolas Klauser     double skew = 0;
51eb1c5037SNikolas Klauser     double kurtosis = 0;
52eb1c5037SNikolas Klauser     for (unsigned i = 0; i < u.size(); ++i)
53eb1c5037SNikolas Klauser     {
54eb1c5037SNikolas Klauser         double dbl = (u[i] - mean);
55eb1c5037SNikolas Klauser         double d2 = sqr(dbl);
56eb1c5037SNikolas Klauser         var += d2;
57eb1c5037SNikolas Klauser         skew += dbl * d2;
58eb1c5037SNikolas Klauser         kurtosis += d2 * d2;
59eb1c5037SNikolas Klauser     }
60eb1c5037SNikolas Klauser     var /= u.size();
61eb1c5037SNikolas Klauser     double dev = std::sqrt(var);
62eb1c5037SNikolas Klauser     skew /= u.size() * dev * var;
63eb1c5037SNikolas Klauser     kurtosis /= u.size() * var * var;
64eb1c5037SNikolas Klauser     kurtosis -= 3;
65eb1c5037SNikolas Klauser     double x_mean = d.t() * d.p();
66eb1c5037SNikolas Klauser     double x_var = x_mean*(1-d.p());
67eb1c5037SNikolas Klauser     double x_skew = (1-2*d.p()) / std::sqrt(x_var);
68eb1c5037SNikolas Klauser     double x_kurtosis = (1-6*d.p()*(1-d.p())) / x_var;
69eb1c5037SNikolas Klauser     assert(std::abs((mean - x_mean) / x_mean) < 0.01);
70eb1c5037SNikolas Klauser     assert(std::abs((var - x_var) / x_var) < 0.01);
71eb1c5037SNikolas Klauser     assert(std::abs((skew - x_skew) / x_skew) < 0.01);
7276aa042dSMatt Stephanson     assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.08);
73eb1c5037SNikolas Klauser }
74eb1c5037SNikolas Klauser 
7507e984bcSLouis Dionne template <class T>
7607e984bcSLouis Dionne void test2() {
7707e984bcSLouis Dionne     typedef std::binomial_distribution<T> D;
78eb1c5037SNikolas Klauser     typedef std::mt19937 G;
79eb1c5037SNikolas Klauser     G g;
80eb1c5037SNikolas Klauser     D d(30, .03125);
81eb1c5037SNikolas Klauser     const int N = 100000;
8207e984bcSLouis Dionne     std::vector<typename D::result_type> u;
83eb1c5037SNikolas Klauser     for (int i = 0; i < N; ++i)
84eb1c5037SNikolas Klauser     {
8507e984bcSLouis Dionne         typename D::result_type v = d(g);
86eb1c5037SNikolas Klauser         assert(d.min() <= v && v <= d.max());
87eb1c5037SNikolas Klauser         u.push_back(v);
88eb1c5037SNikolas Klauser     }
89eb1c5037SNikolas Klauser     double mean = std::accumulate(u.begin(), u.end(),
90eb1c5037SNikolas Klauser                                           double(0)) / u.size();
91eb1c5037SNikolas Klauser     double var = 0;
92eb1c5037SNikolas Klauser     double skew = 0;
93eb1c5037SNikolas Klauser     double kurtosis = 0;
94eb1c5037SNikolas Klauser     for (unsigned i = 0; i < u.size(); ++i)
95eb1c5037SNikolas Klauser     {
96eb1c5037SNikolas Klauser         double dbl = (u[i] - mean);
97eb1c5037SNikolas Klauser         double d2 = sqr(dbl);
98eb1c5037SNikolas Klauser         var += d2;
99eb1c5037SNikolas Klauser         skew += dbl * d2;
100eb1c5037SNikolas Klauser         kurtosis += d2 * d2;
101eb1c5037SNikolas Klauser     }
102eb1c5037SNikolas Klauser     var /= u.size();
103eb1c5037SNikolas Klauser     double dev = std::sqrt(var);
104eb1c5037SNikolas Klauser     skew /= u.size() * dev * var;
105eb1c5037SNikolas Klauser     kurtosis /= u.size() * var * var;
106eb1c5037SNikolas Klauser     kurtosis -= 3;
107eb1c5037SNikolas Klauser     double x_mean = d.t() * d.p();
108eb1c5037SNikolas Klauser     double x_var = x_mean*(1-d.p());
109eb1c5037SNikolas Klauser     double x_skew = (1-2*d.p()) / std::sqrt(x_var);
110eb1c5037SNikolas Klauser     double x_kurtosis = (1-6*d.p()*(1-d.p())) / x_var;
111eb1c5037SNikolas Klauser     assert(std::abs((mean - x_mean) / x_mean) < 0.01);
112eb1c5037SNikolas Klauser     assert(std::abs((var - x_var) / x_var) < 0.01);
11376aa042dSMatt Stephanson     assert(std::abs((skew - x_skew) / x_skew) < 0.02);
11476aa042dSMatt Stephanson     assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.08);
115eb1c5037SNikolas Klauser }
116eb1c5037SNikolas Klauser 
11707e984bcSLouis Dionne template <class T>
11807e984bcSLouis Dionne void test3() {
11907e984bcSLouis Dionne     typedef std::binomial_distribution<T> D;
120eb1c5037SNikolas Klauser     typedef std::mt19937 G;
121eb1c5037SNikolas Klauser     G g;
122eb1c5037SNikolas Klauser     D d(40, .25);
123eb1c5037SNikolas Klauser     const int N = 100000;
12407e984bcSLouis Dionne     std::vector<typename D::result_type> u;
125eb1c5037SNikolas Klauser     for (int i = 0; i < N; ++i)
126eb1c5037SNikolas Klauser     {
12707e984bcSLouis Dionne         typename D::result_type v = d(g);
128eb1c5037SNikolas Klauser         assert(d.min() <= v && v <= d.max());
129eb1c5037SNikolas Klauser         u.push_back(v);
130eb1c5037SNikolas Klauser     }
131eb1c5037SNikolas Klauser     double mean = std::accumulate(u.begin(), u.end(),
132eb1c5037SNikolas Klauser                                           double(0)) / u.size();
133eb1c5037SNikolas Klauser     double var = 0;
134eb1c5037SNikolas Klauser     double skew = 0;
135eb1c5037SNikolas Klauser     double kurtosis = 0;
136eb1c5037SNikolas Klauser     for (unsigned i = 0; i < u.size(); ++i)
137eb1c5037SNikolas Klauser     {
138eb1c5037SNikolas Klauser         double dbl = (u[i] - mean);
139eb1c5037SNikolas Klauser         double d2 = sqr(dbl);
140eb1c5037SNikolas Klauser         var += d2;
141eb1c5037SNikolas Klauser         skew += dbl * d2;
142eb1c5037SNikolas Klauser         kurtosis += d2 * d2;
143eb1c5037SNikolas Klauser     }
144eb1c5037SNikolas Klauser     var /= u.size();
145eb1c5037SNikolas Klauser     double dev = std::sqrt(var);
146eb1c5037SNikolas Klauser     skew /= u.size() * dev * var;
147eb1c5037SNikolas Klauser     kurtosis /= u.size() * var * var;
148eb1c5037SNikolas Klauser     kurtosis -= 3;
149eb1c5037SNikolas Klauser     double x_mean = d.t() * d.p();
150eb1c5037SNikolas Klauser     double x_var = x_mean*(1-d.p());
151eb1c5037SNikolas Klauser     double x_skew = (1-2*d.p()) / std::sqrt(x_var);
152eb1c5037SNikolas Klauser     double x_kurtosis = (1-6*d.p()*(1-d.p())) / x_var;
153eb1c5037SNikolas Klauser     assert(std::abs((mean - x_mean) / x_mean) < 0.01);
154eb1c5037SNikolas Klauser     assert(std::abs((var - x_var) / x_var) < 0.01);
15576aa042dSMatt Stephanson     assert(std::abs((skew - x_skew) / x_skew) < 0.07);
15676aa042dSMatt Stephanson     assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 2.0);
157eb1c5037SNikolas Klauser }
158eb1c5037SNikolas Klauser 
15907e984bcSLouis Dionne template <class T>
16007e984bcSLouis Dionne void test4() {
16107e984bcSLouis Dionne     typedef std::binomial_distribution<T> D;
162eb1c5037SNikolas Klauser     typedef std::mt19937 G;
163eb1c5037SNikolas Klauser     G g;
164eb1c5037SNikolas Klauser     D d(40, 0);
165eb1c5037SNikolas Klauser     const int N = 100000;
16607e984bcSLouis Dionne     std::vector<typename D::result_type> u;
167eb1c5037SNikolas Klauser     for (int i = 0; i < N; ++i)
168eb1c5037SNikolas Klauser     {
16907e984bcSLouis Dionne         typename D::result_type v = d(g);
170eb1c5037SNikolas Klauser         assert(d.min() <= v && v <= d.max());
171eb1c5037SNikolas Klauser         u.push_back(v);
172eb1c5037SNikolas Klauser     }
173eb1c5037SNikolas Klauser     double mean = std::accumulate(u.begin(), u.end(),
174eb1c5037SNikolas Klauser                                           double(0)) / u.size();
175eb1c5037SNikolas Klauser     double var = 0;
176eb1c5037SNikolas Klauser     double skew = 0;
177eb1c5037SNikolas Klauser     double kurtosis = 0;
178eb1c5037SNikolas Klauser     for (unsigned i = 0; i < u.size(); ++i)
179eb1c5037SNikolas Klauser     {
180eb1c5037SNikolas Klauser         double dbl = (u[i] - mean);
181eb1c5037SNikolas Klauser         double d2 = sqr(dbl);
182eb1c5037SNikolas Klauser         var += d2;
183eb1c5037SNikolas Klauser         skew += dbl * d2;
184eb1c5037SNikolas Klauser         kurtosis += d2 * d2;
185eb1c5037SNikolas Klauser     }
186eb1c5037SNikolas Klauser     var /= u.size();
187eb1c5037SNikolas Klauser     double dev = std::sqrt(var);
188eb1c5037SNikolas Klauser     // In this case:
189eb1c5037SNikolas Klauser     //   skew     computes to 0./0. == nan
190eb1c5037SNikolas Klauser     //   kurtosis computes to 0./0. == nan
191eb1c5037SNikolas Klauser     //   x_skew     == inf
192eb1c5037SNikolas Klauser     //   x_kurtosis == inf
193eb1c5037SNikolas Klauser     skew /= u.size() * dev * var;
194eb1c5037SNikolas Klauser     kurtosis /= u.size() * var * var;
195eb1c5037SNikolas Klauser     kurtosis -= 3;
196eb1c5037SNikolas Klauser     double x_mean = d.t() * d.p();
197eb1c5037SNikolas Klauser     double x_var = x_mean*(1-d.p());
198eb1c5037SNikolas Klauser     double x_skew = (1-2*d.p()) / std::sqrt(x_var);
199eb1c5037SNikolas Klauser     double x_kurtosis = (1-6*d.p()*(1-d.p())) / x_var;
200eb1c5037SNikolas Klauser     assert(mean == x_mean);
201eb1c5037SNikolas Klauser     assert(var == x_var);
202eb1c5037SNikolas Klauser     // assert(skew == x_skew);
203eb1c5037SNikolas Klauser     (void)skew; (void)x_skew;
204eb1c5037SNikolas Klauser     // assert(kurtosis == x_kurtosis);
205eb1c5037SNikolas Klauser     (void)kurtosis; (void)x_kurtosis;
206eb1c5037SNikolas Klauser }
207eb1c5037SNikolas Klauser 
20807e984bcSLouis Dionne template <class T>
20907e984bcSLouis Dionne void test5() {
21007e984bcSLouis Dionne     typedef std::binomial_distribution<T> D;
211eb1c5037SNikolas Klauser     typedef std::mt19937 G;
212eb1c5037SNikolas Klauser     G g;
213eb1c5037SNikolas Klauser     D d(40, 1);
214eb1c5037SNikolas Klauser     const int N = 100000;
21507e984bcSLouis Dionne     std::vector<typename D::result_type> u;
216eb1c5037SNikolas Klauser     for (int i = 0; i < N; ++i)
217eb1c5037SNikolas Klauser     {
21807e984bcSLouis Dionne         typename D::result_type v = d(g);
219eb1c5037SNikolas Klauser         assert(d.min() <= v && v <= d.max());
220eb1c5037SNikolas Klauser         u.push_back(v);
221eb1c5037SNikolas Klauser     }
222eb1c5037SNikolas Klauser     double mean = std::accumulate(u.begin(), u.end(),
223eb1c5037SNikolas Klauser                                           double(0)) / u.size();
224eb1c5037SNikolas Klauser     double var = 0;
225eb1c5037SNikolas Klauser     double skew = 0;
226eb1c5037SNikolas Klauser     double kurtosis = 0;
227eb1c5037SNikolas Klauser     for (unsigned i = 0; i < u.size(); ++i)
228eb1c5037SNikolas Klauser     {
229eb1c5037SNikolas Klauser         double dbl = (u[i] - mean);
230eb1c5037SNikolas Klauser         double d2 = sqr(dbl);
231eb1c5037SNikolas Klauser         var += d2;
232eb1c5037SNikolas Klauser         skew += dbl * d2;
233eb1c5037SNikolas Klauser         kurtosis += d2 * d2;
234eb1c5037SNikolas Klauser     }
235eb1c5037SNikolas Klauser     var /= u.size();
236eb1c5037SNikolas Klauser     double dev = std::sqrt(var);
237eb1c5037SNikolas Klauser     // In this case:
238eb1c5037SNikolas Klauser     //   skew     computes to 0./0. == nan
239eb1c5037SNikolas Klauser     //   kurtosis computes to 0./0. == nan
240eb1c5037SNikolas Klauser     //   x_skew     == -inf
241eb1c5037SNikolas Klauser     //   x_kurtosis == inf
242eb1c5037SNikolas Klauser     skew /= u.size() * dev * var;
243eb1c5037SNikolas Klauser     kurtosis /= u.size() * var * var;
244eb1c5037SNikolas Klauser     kurtosis -= 3;
245eb1c5037SNikolas Klauser     double x_mean = d.t() * d.p();
246eb1c5037SNikolas Klauser     double x_var = x_mean*(1-d.p());
247eb1c5037SNikolas Klauser     double x_skew = (1-2*d.p()) / std::sqrt(x_var);
248eb1c5037SNikolas Klauser     double x_kurtosis = (1-6*d.p()*(1-d.p())) / x_var;
249eb1c5037SNikolas Klauser     assert(mean == x_mean);
250eb1c5037SNikolas Klauser     assert(var == x_var);
251eb1c5037SNikolas Klauser     // assert(skew == x_skew);
252eb1c5037SNikolas Klauser     (void)skew; (void)x_skew;
253eb1c5037SNikolas Klauser     // assert(kurtosis == x_kurtosis);
254eb1c5037SNikolas Klauser     (void)kurtosis; (void)x_kurtosis;
255eb1c5037SNikolas Klauser }
256eb1c5037SNikolas Klauser 
25707e984bcSLouis Dionne template <class T>
25807e984bcSLouis Dionne void test6() {
25907e984bcSLouis Dionne     typedef std::binomial_distribution<T> D;
260eb1c5037SNikolas Klauser     typedef std::mt19937 G;
261eb1c5037SNikolas Klauser     G g;
26207e984bcSLouis Dionne     D d(127, 0.5);
263eb1c5037SNikolas Klauser     const int N = 100000;
26407e984bcSLouis Dionne     std::vector<typename D::result_type> u;
265eb1c5037SNikolas Klauser     for (int i = 0; i < N; ++i)
266eb1c5037SNikolas Klauser     {
26707e984bcSLouis Dionne         typename D::result_type v = d(g);
268eb1c5037SNikolas Klauser         assert(d.min() <= v && v <= d.max());
269eb1c5037SNikolas Klauser         u.push_back(v);
270eb1c5037SNikolas Klauser     }
271eb1c5037SNikolas Klauser     double mean = std::accumulate(u.begin(), u.end(),
272eb1c5037SNikolas Klauser                                           double(0)) / u.size();
273eb1c5037SNikolas Klauser     double var = 0;
274eb1c5037SNikolas Klauser     double skew = 0;
275eb1c5037SNikolas Klauser     double kurtosis = 0;
276eb1c5037SNikolas Klauser     for (unsigned i = 0; i < u.size(); ++i)
277eb1c5037SNikolas Klauser     {
278eb1c5037SNikolas Klauser         double dbl = (u[i] - mean);
279eb1c5037SNikolas Klauser         double d2 = sqr(dbl);
280eb1c5037SNikolas Klauser         var += d2;
281eb1c5037SNikolas Klauser         skew += dbl * d2;
282eb1c5037SNikolas Klauser         kurtosis += d2 * d2;
283eb1c5037SNikolas Klauser     }
284eb1c5037SNikolas Klauser     var /= u.size();
285eb1c5037SNikolas Klauser     double dev = std::sqrt(var);
286eb1c5037SNikolas Klauser     skew /= u.size() * dev * var;
287eb1c5037SNikolas Klauser     kurtosis /= u.size() * var * var;
288eb1c5037SNikolas Klauser     kurtosis -= 3;
289eb1c5037SNikolas Klauser     double x_mean = d.t() * d.p();
290eb1c5037SNikolas Klauser     double x_var = x_mean*(1-d.p());
291eb1c5037SNikolas Klauser     double x_skew = (1-2*d.p()) / std::sqrt(x_var);
292eb1c5037SNikolas Klauser     double x_kurtosis = (1-6*d.p()*(1-d.p())) / x_var;
293eb1c5037SNikolas Klauser     assert(std::abs((mean - x_mean) / x_mean) < 0.01);
294eb1c5037SNikolas Klauser     assert(std::abs((var - x_var) / x_var) < 0.01);
29507e984bcSLouis Dionne     assert(std::abs(skew - x_skew) < 0.02);
29676aa042dSMatt Stephanson     assert(std::abs(kurtosis - x_kurtosis) < 0.03);
297eb1c5037SNikolas Klauser }
298eb1c5037SNikolas Klauser 
29907e984bcSLouis Dionne template <class T>
30007e984bcSLouis Dionne void test7() {
30107e984bcSLouis Dionne     typedef std::binomial_distribution<T> D;
302eb1c5037SNikolas Klauser     typedef std::mt19937 G;
303eb1c5037SNikolas Klauser     G g;
304eb1c5037SNikolas Klauser     D d(1, 0.5);
305eb1c5037SNikolas Klauser     const int N = 100000;
30607e984bcSLouis Dionne     std::vector<typename D::result_type> u;
307eb1c5037SNikolas Klauser     for (int i = 0; i < N; ++i)
308eb1c5037SNikolas Klauser     {
30907e984bcSLouis Dionne         typename D::result_type v = d(g);
310eb1c5037SNikolas Klauser         assert(d.min() <= v && v <= d.max());
311eb1c5037SNikolas Klauser         u.push_back(v);
312eb1c5037SNikolas Klauser     }
313eb1c5037SNikolas Klauser     double mean = std::accumulate(u.begin(), u.end(),
314eb1c5037SNikolas Klauser                                           double(0)) / u.size();
315eb1c5037SNikolas Klauser     double var = 0;
316eb1c5037SNikolas Klauser     double skew = 0;
317eb1c5037SNikolas Klauser     double kurtosis = 0;
318eb1c5037SNikolas Klauser     for (unsigned i = 0; i < u.size(); ++i)
319eb1c5037SNikolas Klauser     {
320eb1c5037SNikolas Klauser         double dbl = (u[i] - mean);
321eb1c5037SNikolas Klauser         double d2 = sqr(dbl);
322eb1c5037SNikolas Klauser         var += d2;
323eb1c5037SNikolas Klauser         skew += dbl * d2;
324eb1c5037SNikolas Klauser         kurtosis += d2 * d2;
325eb1c5037SNikolas Klauser     }
326eb1c5037SNikolas Klauser     var /= u.size();
327eb1c5037SNikolas Klauser     double dev = std::sqrt(var);
328eb1c5037SNikolas Klauser     skew /= u.size() * dev * var;
329eb1c5037SNikolas Klauser     kurtosis /= u.size() * var * var;
330eb1c5037SNikolas Klauser     kurtosis -= 3;
331eb1c5037SNikolas Klauser     double x_mean = d.t() * d.p();
332eb1c5037SNikolas Klauser     double x_var = x_mean*(1-d.p());
333eb1c5037SNikolas Klauser     double x_skew = (1-2*d.p()) / std::sqrt(x_var);
334eb1c5037SNikolas Klauser     double x_kurtosis = (1-6*d.p()*(1-d.p())) / x_var;
335eb1c5037SNikolas Klauser     assert(std::abs((mean - x_mean) / x_mean) < 0.01);
336eb1c5037SNikolas Klauser     assert(std::abs((var - x_var) / x_var) < 0.01);
337eb1c5037SNikolas Klauser     assert(std::abs(skew - x_skew) < 0.01);
338eb1c5037SNikolas Klauser     assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
339eb1c5037SNikolas Klauser }
340eb1c5037SNikolas Klauser 
34107e984bcSLouis Dionne template <class T>
34207e984bcSLouis Dionne void test8() {
343eb1c5037SNikolas Klauser     const int N = 100000;
344eb1c5037SNikolas Klauser     std::mt19937 gen1;
345eb1c5037SNikolas Klauser     std::mt19937 gen2;
346eb1c5037SNikolas Klauser 
34707e984bcSLouis Dionne     using UnsignedT = typename std::make_unsigned<T>::type;
34807e984bcSLouis Dionne     std::binomial_distribution<T>         dist1(5, 0.1);
34907e984bcSLouis Dionne     std::binomial_distribution<UnsignedT> dist2(5, 0.1);
350eb1c5037SNikolas Klauser 
351eb1c5037SNikolas Klauser     for (int i = 0; i < N; ++i) {
35207e984bcSLouis Dionne         T r1 = dist1(gen1);
35307e984bcSLouis Dionne         UnsignedT r2 = dist2(gen2);
354eb1c5037SNikolas Klauser         assert(r1 >= 0);
35507e984bcSLouis Dionne         assert(static_cast<UnsignedT>(r1) == r2);
356eb1c5037SNikolas Klauser     }
357eb1c5037SNikolas Klauser }
358eb1c5037SNikolas Klauser 
35907e984bcSLouis Dionne template <class T>
36007e984bcSLouis Dionne void test9() {
36107e984bcSLouis Dionne     typedef std::binomial_distribution<T> D;
362eb1c5037SNikolas Klauser     typedef std::mt19937 G;
363eb1c5037SNikolas Klauser     G g;
364eb1c5037SNikolas Klauser     D d(0, 0.005);
365eb1c5037SNikolas Klauser     const int N = 100000;
36607e984bcSLouis Dionne     std::vector<typename D::result_type> u;
367eb1c5037SNikolas Klauser     for (int i = 0; i < N; ++i)
368eb1c5037SNikolas Klauser     {
36907e984bcSLouis Dionne         typename D::result_type v = d(g);
370eb1c5037SNikolas Klauser         assert(d.min() <= v && v <= d.max());
371eb1c5037SNikolas Klauser         u.push_back(v);
372eb1c5037SNikolas Klauser     }
373eb1c5037SNikolas Klauser     double mean = std::accumulate(u.begin(), u.end(),
374eb1c5037SNikolas Klauser                                           double(0)) / u.size();
375eb1c5037SNikolas Klauser     double var = 0;
376eb1c5037SNikolas Klauser     double skew = 0;
377eb1c5037SNikolas Klauser     double kurtosis = 0;
378eb1c5037SNikolas Klauser     for (unsigned i = 0; i < u.size(); ++i)
379eb1c5037SNikolas Klauser     {
380eb1c5037SNikolas Klauser         double dbl = (u[i] - mean);
381eb1c5037SNikolas Klauser         double d2 = sqr(dbl);
382eb1c5037SNikolas Klauser         var += d2;
383eb1c5037SNikolas Klauser         skew += dbl * d2;
384eb1c5037SNikolas Klauser         kurtosis += d2 * d2;
385eb1c5037SNikolas Klauser     }
386eb1c5037SNikolas Klauser     var /= u.size();
387eb1c5037SNikolas Klauser     double dev = std::sqrt(var);
388eb1c5037SNikolas Klauser     // In this case:
389eb1c5037SNikolas Klauser     //   skew     computes to 0./0. == nan
390eb1c5037SNikolas Klauser     //   kurtosis computes to 0./0. == nan
391eb1c5037SNikolas Klauser     //   x_skew     == inf
392eb1c5037SNikolas Klauser     //   x_kurtosis == inf
393eb1c5037SNikolas Klauser     skew /= u.size() * dev * var;
394eb1c5037SNikolas Klauser     kurtosis /= u.size() * var * var;
395eb1c5037SNikolas Klauser     kurtosis -= 3;
396eb1c5037SNikolas Klauser     double x_mean = d.t() * d.p();
397eb1c5037SNikolas Klauser     double x_var = x_mean*(1-d.p());
398eb1c5037SNikolas Klauser     double x_skew = (1-2*d.p()) / std::sqrt(x_var);
399eb1c5037SNikolas Klauser     double x_kurtosis = (1-6*d.p()*(1-d.p())) / x_var;
400eb1c5037SNikolas Klauser     assert(mean == x_mean);
401eb1c5037SNikolas Klauser     assert(var == x_var);
402eb1c5037SNikolas Klauser     // assert(skew == x_skew);
403eb1c5037SNikolas Klauser     (void)skew; (void)x_skew;
404eb1c5037SNikolas Klauser     // assert(kurtosis == x_kurtosis);
405eb1c5037SNikolas Klauser     (void)kurtosis; (void)x_kurtosis;
406eb1c5037SNikolas Klauser }
407eb1c5037SNikolas Klauser 
40807e984bcSLouis Dionne template <class T>
40907e984bcSLouis Dionne void test10() {
41007e984bcSLouis Dionne     typedef std::binomial_distribution<T> D;
411eb1c5037SNikolas Klauser     typedef std::mt19937 G;
412eb1c5037SNikolas Klauser     G g;
413eb1c5037SNikolas Klauser     D d(0, 0);
414eb1c5037SNikolas Klauser     const int N = 100000;
41507e984bcSLouis Dionne     std::vector<typename D::result_type> u;
416eb1c5037SNikolas Klauser     for (int i = 0; i < N; ++i)
417eb1c5037SNikolas Klauser     {
41807e984bcSLouis Dionne         typename D::result_type v = d(g);
419eb1c5037SNikolas Klauser         assert(d.min() <= v && v <= d.max());
420eb1c5037SNikolas Klauser         u.push_back(v);
421eb1c5037SNikolas Klauser     }
422eb1c5037SNikolas Klauser     double mean = std::accumulate(u.begin(), u.end(),
423eb1c5037SNikolas Klauser                                           double(0)) / u.size();
424eb1c5037SNikolas Klauser     double var = 0;
425eb1c5037SNikolas Klauser     double skew = 0;
426eb1c5037SNikolas Klauser     double kurtosis = 0;
427eb1c5037SNikolas Klauser     for (unsigned i = 0; i < u.size(); ++i)
428eb1c5037SNikolas Klauser     {
429eb1c5037SNikolas Klauser         double dbl = (u[i] - mean);
430eb1c5037SNikolas Klauser         double d2 = sqr(dbl);
431eb1c5037SNikolas Klauser         var += d2;
432eb1c5037SNikolas Klauser         skew += dbl * d2;
433eb1c5037SNikolas Klauser         kurtosis += d2 * d2;
434eb1c5037SNikolas Klauser     }
435eb1c5037SNikolas Klauser     var /= u.size();
436eb1c5037SNikolas Klauser     double dev = std::sqrt(var);
437eb1c5037SNikolas Klauser     // In this case:
438eb1c5037SNikolas Klauser     //   skew     computes to 0./0. == nan
439eb1c5037SNikolas Klauser     //   kurtosis computes to 0./0. == nan
440eb1c5037SNikolas Klauser     //   x_skew     == inf
441eb1c5037SNikolas Klauser     //   x_kurtosis == inf
442eb1c5037SNikolas Klauser     skew /= u.size() * dev * var;
443eb1c5037SNikolas Klauser     kurtosis /= u.size() * var * var;
444eb1c5037SNikolas Klauser     kurtosis -= 3;
445eb1c5037SNikolas Klauser     double x_mean = d.t() * d.p();
446eb1c5037SNikolas Klauser     double x_var = x_mean*(1-d.p());
447eb1c5037SNikolas Klauser     double x_skew = (1-2*d.p()) / std::sqrt(x_var);
448eb1c5037SNikolas Klauser     double x_kurtosis = (1-6*d.p()*(1-d.p())) / x_var;
449eb1c5037SNikolas Klauser     assert(mean == x_mean);
450eb1c5037SNikolas Klauser     assert(var == x_var);
451eb1c5037SNikolas Klauser     // assert(skew == x_skew);
452eb1c5037SNikolas Klauser     (void)skew; (void)x_skew;
453eb1c5037SNikolas Klauser     // assert(kurtosis == x_kurtosis);
454eb1c5037SNikolas Klauser     (void)kurtosis; (void)x_kurtosis;
455eb1c5037SNikolas Klauser }
456eb1c5037SNikolas Klauser 
45707e984bcSLouis Dionne template <class T>
45807e984bcSLouis Dionne void test11() {
45907e984bcSLouis Dionne     typedef std::binomial_distribution<T> D;
460eb1c5037SNikolas Klauser     typedef std::mt19937 G;
461eb1c5037SNikolas Klauser     G g;
462eb1c5037SNikolas Klauser     D d(0, 1);
463eb1c5037SNikolas Klauser     const int N = 100000;
46407e984bcSLouis Dionne     std::vector<typename D::result_type> u;
465eb1c5037SNikolas Klauser     for (int i = 0; i < N; ++i)
466eb1c5037SNikolas Klauser     {
46707e984bcSLouis Dionne         typename D::result_type v = d(g);
468eb1c5037SNikolas Klauser         assert(d.min() <= v && v <= d.max());
469eb1c5037SNikolas Klauser         u.push_back(v);
470eb1c5037SNikolas Klauser     }
471eb1c5037SNikolas Klauser     double mean = std::accumulate(u.begin(), u.end(),
472eb1c5037SNikolas Klauser                                           double(0)) / u.size();
473eb1c5037SNikolas Klauser     double var = 0;
474eb1c5037SNikolas Klauser     double skew = 0;
475eb1c5037SNikolas Klauser     double kurtosis = 0;
476eb1c5037SNikolas Klauser     for (unsigned i = 0; i < u.size(); ++i)
477eb1c5037SNikolas Klauser     {
478eb1c5037SNikolas Klauser         double dbl = (u[i] - mean);
479eb1c5037SNikolas Klauser         double d2 = sqr(dbl);
480eb1c5037SNikolas Klauser         var += d2;
481eb1c5037SNikolas Klauser         skew += dbl * d2;
482eb1c5037SNikolas Klauser         kurtosis += d2 * d2;
483eb1c5037SNikolas Klauser     }
484eb1c5037SNikolas Klauser     var /= u.size();
485eb1c5037SNikolas Klauser     double dev = std::sqrt(var);
486eb1c5037SNikolas Klauser     // In this case:
487eb1c5037SNikolas Klauser     //   skew     computes to 0./0. == nan
488eb1c5037SNikolas Klauser     //   kurtosis computes to 0./0. == nan
489eb1c5037SNikolas Klauser     //   x_skew     == -inf
490eb1c5037SNikolas Klauser     //   x_kurtosis == inf
491eb1c5037SNikolas Klauser     skew /= u.size() * dev * var;
492eb1c5037SNikolas Klauser     kurtosis /= u.size() * var * var;
493eb1c5037SNikolas Klauser     kurtosis -= 3;
494eb1c5037SNikolas Klauser     double x_mean = d.t() * d.p();
495eb1c5037SNikolas Klauser     double x_var = x_mean*(1-d.p());
496eb1c5037SNikolas Klauser     double x_skew = (1-2*d.p()) / std::sqrt(x_var);
497eb1c5037SNikolas Klauser     double x_kurtosis = (1-6*d.p()*(1-d.p())) / x_var;
498eb1c5037SNikolas Klauser     assert(mean == x_mean);
499eb1c5037SNikolas Klauser     assert(var == x_var);
500eb1c5037SNikolas Klauser     // assert(skew == x_skew);
501eb1c5037SNikolas Klauser     (void)skew; (void)x_skew;
502eb1c5037SNikolas Klauser     // assert(kurtosis == x_kurtosis);
503eb1c5037SNikolas Klauser     (void)kurtosis; (void)x_kurtosis;
504eb1c5037SNikolas Klauser }
505eb1c5037SNikolas Klauser 
50607e984bcSLouis Dionne template <class T>
50707e984bcSLouis Dionne void tests() {
50807e984bcSLouis Dionne     test1<T>();
50907e984bcSLouis Dionne     test2<T>();
51007e984bcSLouis Dionne     test3<T>();
51107e984bcSLouis Dionne     test4<T>();
51207e984bcSLouis Dionne     test5<T>();
51307e984bcSLouis Dionne     test6<T>();
51407e984bcSLouis Dionne     test7<T>();
51507e984bcSLouis Dionne     test8<T>();
51607e984bcSLouis Dionne     test9<T>();
51707e984bcSLouis Dionne     test10<T>();
51807e984bcSLouis Dionne     test11<T>();
51907e984bcSLouis Dionne }
52007e984bcSLouis Dionne 
52107e984bcSLouis Dionne int main(int, char**) {
52207e984bcSLouis Dionne     tests<short>();
52307e984bcSLouis Dionne     tests<int>();
52407e984bcSLouis Dionne     tests<long>();
52507e984bcSLouis Dionne     tests<long long>();
52607e984bcSLouis Dionne 
52707e984bcSLouis Dionne     tests<unsigned short>();
52807e984bcSLouis Dionne     tests<unsigned int>();
52907e984bcSLouis Dionne     tests<unsigned long>();
53007e984bcSLouis Dionne     tests<unsigned long long>();
53107e984bcSLouis Dionne 
53207e984bcSLouis Dionne #if defined(_LIBCPP_VERSION) // extension
533bd5d0feeSMark de Wever     tests<std::int8_t>();
534bd5d0feeSMark de Wever     tests<std::uint8_t>();
53507e984bcSLouis Dionne #if !defined(TEST_HAS_NO_INT128)
53607e984bcSLouis Dionne     tests<__int128_t>();
53707e984bcSLouis Dionne     tests<__uint128_t>();
53807e984bcSLouis Dionne #endif
53907e984bcSLouis Dionne #endif
540eb1c5037SNikolas Klauser 
541eb1c5037SNikolas Klauser     return 0;
542eb1c5037SNikolas Klauser }
543