xref: /llvm-project/libcxx/test/std/numerics/rand/rand.dist/rand.dist.bern/rand.dist.bern.geo/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 geometric_distribution
15eb1c5037SNikolas Klauser 
16eb1c5037SNikolas Klauser // template<class _URNG> result_type operator()(_URNG& g);
17eb1c5037SNikolas Klauser 
18*09e3a360SLouis Dionne #include <random>
19eb1c5037SNikolas Klauser #include <cassert>
20*09e3a360SLouis Dionne #include <cmath>
210a4aa8a1SNikolas Klauser #include <cstdint>
220a4aa8a1SNikolas Klauser #include <numeric>
230a4aa8a1SNikolas Klauser #include <vector>
24eb1c5037SNikolas Klauser 
25eb1c5037SNikolas Klauser #include "test_macros.h"
26eb1c5037SNikolas Klauser 
27eb1c5037SNikolas Klauser template <class T>
2807e984bcSLouis Dionne T sqr(T x) {
29eb1c5037SNikolas Klauser     return x * x;
30eb1c5037SNikolas Klauser }
31eb1c5037SNikolas Klauser 
32eb1c5037SNikolas Klauser void test_small_inputs() {
33eb1c5037SNikolas Klauser   std::mt19937 engine;
34eb1c5037SNikolas Klauser   std::geometric_distribution<std::int16_t> distribution(5.45361e-311);
35eb1c5037SNikolas Klauser   typedef std::geometric_distribution<std::int16_t>::result_type result_type;
36eb1c5037SNikolas Klauser   for (int i = 0; i < 1000; ++i) {
37eb1c5037SNikolas Klauser     volatile result_type res = distribution(engine);
38eb1c5037SNikolas Klauser     ((void)res);
39eb1c5037SNikolas Klauser   }
40eb1c5037SNikolas Klauser }
41eb1c5037SNikolas Klauser 
4207e984bcSLouis Dionne template <class T>
4307e984bcSLouis Dionne void test1() {
4407e984bcSLouis Dionne     typedef std::geometric_distribution<T> D;
45eb1c5037SNikolas Klauser     typedef std::mt19937 G;
46eb1c5037SNikolas Klauser     G g;
47eb1c5037SNikolas Klauser     D d(.03125);
48eb1c5037SNikolas Klauser     const int N = 1000000;
4907e984bcSLouis Dionne     std::vector<typename D::result_type> u;
50eb1c5037SNikolas Klauser     for (int i = 0; i < N; ++i)
51eb1c5037SNikolas Klauser     {
5207e984bcSLouis Dionne         typename D::result_type v = d(g);
53eb1c5037SNikolas Klauser         assert(d.min() <= v && v <= d.max());
54eb1c5037SNikolas Klauser         u.push_back(v);
55eb1c5037SNikolas Klauser     }
56eb1c5037SNikolas Klauser     double mean = std::accumulate(u.begin(), u.end(),
57eb1c5037SNikolas Klauser                                           double(0)) / u.size();
58eb1c5037SNikolas Klauser     double var = 0;
59eb1c5037SNikolas Klauser     double skew = 0;
60eb1c5037SNikolas Klauser     double kurtosis = 0;
61eb1c5037SNikolas Klauser     for (unsigned i = 0; i < u.size(); ++i)
62eb1c5037SNikolas Klauser     {
63eb1c5037SNikolas Klauser         double dbl = (u[i] - mean);
64eb1c5037SNikolas Klauser         double d2 = sqr(dbl);
65eb1c5037SNikolas Klauser         var += d2;
66eb1c5037SNikolas Klauser         skew += dbl * d2;
67eb1c5037SNikolas Klauser         kurtosis += d2 * d2;
68eb1c5037SNikolas Klauser     }
69eb1c5037SNikolas Klauser     var /= u.size();
70eb1c5037SNikolas Klauser     double dev = std::sqrt(var);
71eb1c5037SNikolas Klauser     skew /= u.size() * dev * var;
72eb1c5037SNikolas Klauser     kurtosis /= u.size() * var * var;
73eb1c5037SNikolas Klauser     kurtosis -= 3;
74eb1c5037SNikolas Klauser     double x_mean = (1 - d.p()) / d.p();
75eb1c5037SNikolas Klauser     double x_var = x_mean / d.p();
76eb1c5037SNikolas Klauser     double x_skew = (2 - d.p()) / std::sqrt((1 - d.p()));
77eb1c5037SNikolas Klauser     double x_kurtosis = 6 + sqr(d.p()) / (1 - d.p());
78eb1c5037SNikolas Klauser     assert(std::abs((mean - x_mean) / x_mean) < 0.01);
79eb1c5037SNikolas Klauser     assert(std::abs((var - x_var) / x_var) < 0.01);
80eb1c5037SNikolas Klauser     assert(std::abs((skew - x_skew) / x_skew) < 0.01);
8176aa042dSMatt Stephanson     assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.03);
82eb1c5037SNikolas Klauser }
83eb1c5037SNikolas Klauser 
8407e984bcSLouis Dionne template <class T>
8507e984bcSLouis Dionne void test2() {
8607e984bcSLouis Dionne     typedef std::geometric_distribution<T> D;
87eb1c5037SNikolas Klauser     typedef std::mt19937 G;
88eb1c5037SNikolas Klauser     G g;
89eb1c5037SNikolas Klauser     D d(0.05);
90eb1c5037SNikolas Klauser     const int N = 1000000;
9107e984bcSLouis Dionne     std::vector<typename D::result_type> u;
92eb1c5037SNikolas Klauser     for (int i = 0; i < N; ++i)
93eb1c5037SNikolas Klauser     {
9407e984bcSLouis Dionne         typename D::result_type v = d(g);
95eb1c5037SNikolas Klauser         assert(d.min() <= v && v <= d.max());
96eb1c5037SNikolas Klauser         u.push_back(v);
97eb1c5037SNikolas Klauser     }
98eb1c5037SNikolas Klauser     double mean = std::accumulate(u.begin(), u.end(),
99eb1c5037SNikolas Klauser                                           double(0)) / u.size();
100eb1c5037SNikolas Klauser     double var = 0;
101eb1c5037SNikolas Klauser     double skew = 0;
102eb1c5037SNikolas Klauser     double kurtosis = 0;
103eb1c5037SNikolas Klauser     for (unsigned i = 0; i < u.size(); ++i)
104eb1c5037SNikolas Klauser     {
105eb1c5037SNikolas Klauser         double dbl = (u[i] - mean);
106eb1c5037SNikolas Klauser         double d2 = sqr(dbl);
107eb1c5037SNikolas Klauser         var += d2;
108eb1c5037SNikolas Klauser         skew += dbl * d2;
109eb1c5037SNikolas Klauser         kurtosis += d2 * d2;
110eb1c5037SNikolas Klauser     }
111eb1c5037SNikolas Klauser     var /= u.size();
112eb1c5037SNikolas Klauser     double dev = std::sqrt(var);
113eb1c5037SNikolas Klauser     skew /= u.size() * dev * var;
114eb1c5037SNikolas Klauser     kurtosis /= u.size() * var * var;
115eb1c5037SNikolas Klauser     kurtosis -= 3;
116eb1c5037SNikolas Klauser     double x_mean = (1 - d.p()) / d.p();
117eb1c5037SNikolas Klauser     double x_var = x_mean / d.p();
118eb1c5037SNikolas Klauser     double x_skew = (2 - d.p()) / std::sqrt((1 - d.p()));
119eb1c5037SNikolas Klauser     double x_kurtosis = 6 + sqr(d.p()) / (1 - d.p());
120eb1c5037SNikolas Klauser     assert(std::abs((mean - x_mean) / x_mean) < 0.01);
121eb1c5037SNikolas Klauser     assert(std::abs((var - x_var) / x_var) < 0.01);
122eb1c5037SNikolas Klauser     assert(std::abs((skew - x_skew) / x_skew) < 0.01);
123eb1c5037SNikolas Klauser     assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.03);
124eb1c5037SNikolas Klauser }
125eb1c5037SNikolas Klauser 
12607e984bcSLouis Dionne template <class T>
12707e984bcSLouis Dionne void test3() {
12807e984bcSLouis Dionne     typedef std::geometric_distribution<T> D;
129eb1c5037SNikolas Klauser     typedef std::minstd_rand G;
130eb1c5037SNikolas Klauser     G g;
131eb1c5037SNikolas Klauser     D d(.25);
132eb1c5037SNikolas Klauser     const int N = 1000000;
13307e984bcSLouis Dionne     std::vector<typename D::result_type> u;
134eb1c5037SNikolas Klauser     for (int i = 0; i < N; ++i)
135eb1c5037SNikolas Klauser     {
13607e984bcSLouis Dionne         typename D::result_type v = d(g);
137eb1c5037SNikolas Klauser         assert(d.min() <= v && v <= d.max());
138eb1c5037SNikolas Klauser         u.push_back(v);
139eb1c5037SNikolas Klauser     }
140eb1c5037SNikolas Klauser     double mean = std::accumulate(u.begin(), u.end(),
141eb1c5037SNikolas Klauser                                           double(0)) / u.size();
142eb1c5037SNikolas Klauser     double var = 0;
143eb1c5037SNikolas Klauser     double skew = 0;
144eb1c5037SNikolas Klauser     double kurtosis = 0;
145eb1c5037SNikolas Klauser     for (unsigned i = 0; i < u.size(); ++i)
146eb1c5037SNikolas Klauser     {
147eb1c5037SNikolas Klauser         double dbl = (u[i] - mean);
148eb1c5037SNikolas Klauser         double d2 = sqr(dbl);
149eb1c5037SNikolas Klauser         var += d2;
150eb1c5037SNikolas Klauser         skew += dbl * d2;
151eb1c5037SNikolas Klauser         kurtosis += d2 * d2;
152eb1c5037SNikolas Klauser     }
153eb1c5037SNikolas Klauser     var /= u.size();
154eb1c5037SNikolas Klauser     double dev = std::sqrt(var);
155eb1c5037SNikolas Klauser     skew /= u.size() * dev * var;
156eb1c5037SNikolas Klauser     kurtosis /= u.size() * var * var;
157eb1c5037SNikolas Klauser     kurtosis -= 3;
158eb1c5037SNikolas Klauser     double x_mean = (1 - d.p()) / d.p();
159eb1c5037SNikolas Klauser     double x_var = x_mean / d.p();
160eb1c5037SNikolas Klauser     double x_skew = (2 - d.p()) / std::sqrt((1 - d.p()));
161eb1c5037SNikolas Klauser     double x_kurtosis = 6 + sqr(d.p()) / (1 - d.p());
162eb1c5037SNikolas Klauser     assert(std::abs((mean - x_mean) / x_mean) < 0.01);
163eb1c5037SNikolas Klauser     assert(std::abs((var - x_var) / x_var) < 0.01);
164eb1c5037SNikolas Klauser     assert(std::abs((skew - x_skew) / x_skew) < 0.01);
16576aa042dSMatt Stephanson     assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.03);
166eb1c5037SNikolas Klauser }
167eb1c5037SNikolas Klauser 
16807e984bcSLouis Dionne template <class T>
16907e984bcSLouis Dionne void test4() {
17007e984bcSLouis Dionne     typedef std::geometric_distribution<T> D;
171eb1c5037SNikolas Klauser     typedef std::mt19937 G;
172eb1c5037SNikolas Klauser     G g;
173eb1c5037SNikolas Klauser     D d(0.5);
174eb1c5037SNikolas Klauser     const int N = 1000000;
17507e984bcSLouis Dionne     std::vector<typename D::result_type> u;
176eb1c5037SNikolas Klauser     for (int i = 0; i < N; ++i)
177eb1c5037SNikolas Klauser     {
17807e984bcSLouis Dionne         typename D::result_type v = d(g);
179eb1c5037SNikolas Klauser         assert(d.min() <= v && v <= d.max());
180eb1c5037SNikolas Klauser         u.push_back(v);
181eb1c5037SNikolas Klauser     }
182eb1c5037SNikolas Klauser     double mean = std::accumulate(u.begin(), u.end(),
183eb1c5037SNikolas Klauser                                           double(0)) / u.size();
184eb1c5037SNikolas Klauser     double var = 0;
185eb1c5037SNikolas Klauser     double skew = 0;
186eb1c5037SNikolas Klauser     double kurtosis = 0;
187eb1c5037SNikolas Klauser     for (unsigned i = 0; i < u.size(); ++i)
188eb1c5037SNikolas Klauser     {
189eb1c5037SNikolas Klauser         double dbl = (u[i] - mean);
190eb1c5037SNikolas Klauser         double d2 = sqr(dbl);
191eb1c5037SNikolas Klauser         var += d2;
192eb1c5037SNikolas Klauser         skew += dbl * d2;
193eb1c5037SNikolas Klauser         kurtosis += d2 * d2;
194eb1c5037SNikolas Klauser     }
195eb1c5037SNikolas Klauser     var /= u.size();
196eb1c5037SNikolas Klauser     double dev = std::sqrt(var);
197eb1c5037SNikolas Klauser     skew /= u.size() * dev * var;
198eb1c5037SNikolas Klauser     kurtosis /= u.size() * var * var;
199eb1c5037SNikolas Klauser     kurtosis -= 3;
200eb1c5037SNikolas Klauser     double x_mean = (1 - d.p()) / d.p();
201eb1c5037SNikolas Klauser     double x_var = x_mean / d.p();
202eb1c5037SNikolas Klauser     double x_skew = (2 - d.p()) / std::sqrt((1 - d.p()));
203eb1c5037SNikolas Klauser     double x_kurtosis = 6 + sqr(d.p()) / (1 - d.p());
204eb1c5037SNikolas Klauser     assert(std::abs((mean - x_mean) / x_mean) < 0.01);
205eb1c5037SNikolas Klauser     assert(std::abs((var - x_var) / x_var) < 0.01);
206eb1c5037SNikolas Klauser     assert(std::abs((skew - x_skew) / x_skew) < 0.01);
20776aa042dSMatt Stephanson     assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.03);
208eb1c5037SNikolas Klauser }
209eb1c5037SNikolas Klauser 
21007e984bcSLouis Dionne template <class T>
21107e984bcSLouis Dionne void test5() {
21207e984bcSLouis Dionne     typedef std::geometric_distribution<T> D;
213eb1c5037SNikolas Klauser     typedef std::mt19937 G;
214eb1c5037SNikolas Klauser     G g;
215eb1c5037SNikolas Klauser     D d(0.75);
216eb1c5037SNikolas Klauser     const int N = 1000000;
21707e984bcSLouis Dionne     std::vector<typename D::result_type> u;
218eb1c5037SNikolas Klauser     for (int i = 0; i < N; ++i)
219eb1c5037SNikolas Klauser     {
22007e984bcSLouis Dionne         typename D::result_type v = d(g);
221eb1c5037SNikolas Klauser         assert(d.min() <= v && v <= d.max());
222eb1c5037SNikolas Klauser         u.push_back(v);
223eb1c5037SNikolas Klauser     }
224eb1c5037SNikolas Klauser     double mean = std::accumulate(u.begin(), u.end(),
225eb1c5037SNikolas Klauser                                           double(0)) / u.size();
226eb1c5037SNikolas Klauser     double var = 0;
227eb1c5037SNikolas Klauser     double skew = 0;
228eb1c5037SNikolas Klauser     double kurtosis = 0;
229eb1c5037SNikolas Klauser     for (unsigned i = 0; i < u.size(); ++i)
230eb1c5037SNikolas Klauser     {
231eb1c5037SNikolas Klauser         double dbl = (u[i] - mean);
232eb1c5037SNikolas Klauser         double d2 = sqr(dbl);
233eb1c5037SNikolas Klauser         var += d2;
234eb1c5037SNikolas Klauser         skew += dbl * d2;
235eb1c5037SNikolas Klauser         kurtosis += d2 * d2;
236eb1c5037SNikolas Klauser     }
237eb1c5037SNikolas Klauser     var /= u.size();
238eb1c5037SNikolas Klauser     double dev = std::sqrt(var);
239eb1c5037SNikolas Klauser     skew /= u.size() * dev * var;
240eb1c5037SNikolas Klauser     kurtosis /= u.size() * var * var;
241eb1c5037SNikolas Klauser     kurtosis -= 3;
242eb1c5037SNikolas Klauser     double x_mean = (1 - d.p()) / d.p();
243eb1c5037SNikolas Klauser     double x_var = x_mean / d.p();
244eb1c5037SNikolas Klauser     double x_skew = (2 - d.p()) / std::sqrt((1 - d.p()));
245eb1c5037SNikolas Klauser     double x_kurtosis = 6 + sqr(d.p()) / (1 - d.p());
246eb1c5037SNikolas Klauser     assert(std::abs((mean - x_mean) / x_mean) < 0.01);
247eb1c5037SNikolas Klauser     assert(std::abs((var - x_var) / x_var) < 0.01);
248eb1c5037SNikolas Klauser     assert(std::abs((skew - x_skew) / x_skew) < 0.01);
24976aa042dSMatt Stephanson     assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.03);
250eb1c5037SNikolas Klauser }
251eb1c5037SNikolas Klauser 
25207e984bcSLouis Dionne template <class T>
25307e984bcSLouis Dionne void test6() {
25407e984bcSLouis Dionne     typedef std::geometric_distribution<T> D;
255eb1c5037SNikolas Klauser     typedef std::mt19937 G;
256eb1c5037SNikolas Klauser     G g;
257eb1c5037SNikolas Klauser     D d(0.96875);
258eb1c5037SNikolas Klauser     const int N = 1000000;
25907e984bcSLouis Dionne     std::vector<typename D::result_type> u;
260eb1c5037SNikolas Klauser     for (int i = 0; i < N; ++i)
261eb1c5037SNikolas Klauser     {
26207e984bcSLouis Dionne         typename D::result_type v = d(g);
263eb1c5037SNikolas Klauser         assert(d.min() <= v && v <= d.max());
264eb1c5037SNikolas Klauser         u.push_back(v);
265eb1c5037SNikolas Klauser     }
266eb1c5037SNikolas Klauser     double mean = std::accumulate(u.begin(), u.end(),
267eb1c5037SNikolas Klauser                                           double(0)) / u.size();
268eb1c5037SNikolas Klauser     double var = 0;
269eb1c5037SNikolas Klauser     double skew = 0;
270eb1c5037SNikolas Klauser     double kurtosis = 0;
271eb1c5037SNikolas Klauser     for (unsigned i = 0; i < u.size(); ++i)
272eb1c5037SNikolas Klauser     {
273eb1c5037SNikolas Klauser         double dbl = (u[i] - mean);
274eb1c5037SNikolas Klauser         double d2 = sqr(dbl);
275eb1c5037SNikolas Klauser         var += d2;
276eb1c5037SNikolas Klauser         skew += dbl * d2;
277eb1c5037SNikolas Klauser         kurtosis += d2 * d2;
278eb1c5037SNikolas Klauser     }
279eb1c5037SNikolas Klauser     var /= u.size();
280eb1c5037SNikolas Klauser     double dev = std::sqrt(var);
281eb1c5037SNikolas Klauser     skew /= u.size() * dev * var;
282eb1c5037SNikolas Klauser     kurtosis /= u.size() * var * var;
283eb1c5037SNikolas Klauser     kurtosis -= 3;
284eb1c5037SNikolas Klauser     double x_mean = (1 - d.p()) / d.p();
285eb1c5037SNikolas Klauser     double x_var = x_mean / d.p();
286eb1c5037SNikolas Klauser     double x_skew = (2 - d.p()) / std::sqrt((1 - d.p()));
287eb1c5037SNikolas Klauser     double x_kurtosis = 6 + sqr(d.p()) / (1 - d.p());
28876aa042dSMatt Stephanson     assert(std::abs((mean - x_mean) / x_mean) < 0.02);
28976aa042dSMatt Stephanson     assert(std::abs((var - x_var) / x_var) < 0.02);
290eb1c5037SNikolas Klauser     assert(std::abs((skew - x_skew) / x_skew) < 0.01);
291eb1c5037SNikolas Klauser     assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.02);
292eb1c5037SNikolas Klauser }
293eb1c5037SNikolas Klauser 
29407e984bcSLouis Dionne template <class T>
29507e984bcSLouis Dionne void tests() {
29607e984bcSLouis Dionne     test1<T>();
29707e984bcSLouis Dionne     test2<T>();
29807e984bcSLouis Dionne     test3<T>();
29907e984bcSLouis Dionne     test4<T>();
30007e984bcSLouis Dionne     test5<T>();
30107e984bcSLouis Dionne     test6<T>();
30207e984bcSLouis Dionne }
30307e984bcSLouis Dionne 
30407e984bcSLouis Dionne int main(int, char**) {
305eb1c5037SNikolas Klauser     test_small_inputs();
306eb1c5037SNikolas Klauser 
30707e984bcSLouis Dionne     tests<short>();
30807e984bcSLouis Dionne     tests<int>();
30907e984bcSLouis Dionne     tests<long>();
31007e984bcSLouis Dionne     tests<long long>();
31107e984bcSLouis Dionne 
31207e984bcSLouis Dionne     tests<unsigned short>();
31307e984bcSLouis Dionne     tests<unsigned int>();
31407e984bcSLouis Dionne     tests<unsigned long>();
31507e984bcSLouis Dionne     tests<unsigned long long>();
31607e984bcSLouis Dionne 
31707e984bcSLouis Dionne #if defined(_LIBCPP_VERSION) // extension
31807e984bcSLouis Dionne     // TODO: std::geometric_distribution currently doesn't work reliably with small types.
31907e984bcSLouis Dionne     // tests<int8_t>();
32007e984bcSLouis Dionne     // tests<uint8_t>();
32107e984bcSLouis Dionne #if !defined(TEST_HAS_NO_INT128)
32207e984bcSLouis Dionne     tests<__int128_t>();
32307e984bcSLouis Dionne     tests<__uint128_t>();
32407e984bcSLouis Dionne #endif
32507e984bcSLouis Dionne #endif
32607e984bcSLouis Dionne 
327eb1c5037SNikolas Klauser     return 0;
328eb1c5037SNikolas Klauser }
329