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 //===----------------------------------------------------------------------===//
8520c7fbbSLouis Dionne 
9eb1c5037SNikolas Klauser // REQUIRES: long_tests
10520c7fbbSLouis Dionne // UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME
11eb1c5037SNikolas Klauser 
12eb1c5037SNikolas Klauser // <random>
13eb1c5037SNikolas Klauser 
14eb1c5037SNikolas Klauser // template<class IntType = int>
15eb1c5037SNikolas Klauser // class discrete_distribution
16eb1c5037SNikolas Klauser 
17eb1c5037SNikolas Klauser // template<class _URNG> result_type operator()(_URNG& g);
18eb1c5037SNikolas Klauser 
190a4aa8a1SNikolas Klauser #include <cassert>
200a4aa8a1SNikolas Klauser #include <cstdint>
2175196f8eSNikolas Klauser #include <cstdlib>
22eb1c5037SNikolas Klauser #include <random>
23eb1c5037SNikolas Klauser #include <vector>
24eb1c5037SNikolas Klauser 
25eb1c5037SNikolas Klauser #include "test_macros.h"
26eb1c5037SNikolas Klauser 
2707e984bcSLouis Dionne template <class T>
tests()2807e984bcSLouis Dionne void tests() {
2907e984bcSLouis Dionne     typedef long long Frequency;
30eb1c5037SNikolas Klauser     {
3107e984bcSLouis Dionne         typedef std::discrete_distribution<T> D;
32eb1c5037SNikolas Klauser         typedef std::minstd_rand G;
33eb1c5037SNikolas Klauser         G g;
34eb1c5037SNikolas Klauser         D d;
35eb1c5037SNikolas Klauser         const int N = 100;
36db0ac307SIgor Zhukov         std::vector<Frequency> u(static_cast<std::size_t>(d.max()+1));
37db0ac307SIgor Zhukov         assert(u.max_size() > static_cast<unsigned long long>(d.max()));
38eb1c5037SNikolas Klauser         for (int i = 0; i < N; ++i)
39eb1c5037SNikolas Klauser         {
4007e984bcSLouis Dionne             typename D::result_type v = d(g);
41eb1c5037SNikolas Klauser             assert(d.min() <= v && v <= d.max());
42db0ac307SIgor Zhukov             u[static_cast<std::size_t>(v)]++;
43eb1c5037SNikolas Klauser         }
44eb1c5037SNikolas Klauser         std::vector<double> prob = d.probabilities();
4507e984bcSLouis Dionne         for (unsigned i = 0; i < u.size(); ++i)
46eb1c5037SNikolas Klauser             assert((double)u[i]/N == prob[i]);
47eb1c5037SNikolas Klauser     }
48eb1c5037SNikolas Klauser     {
4907e984bcSLouis Dionne         typedef std::discrete_distribution<T> D;
50eb1c5037SNikolas Klauser         typedef std::minstd_rand G;
51eb1c5037SNikolas Klauser         G g;
52eb1c5037SNikolas Klauser         double p0[] = {.3};
53eb1c5037SNikolas Klauser         D d(p0, p0+1);
54eb1c5037SNikolas Klauser         const int N = 100;
55db0ac307SIgor Zhukov         std::vector<Frequency> u(static_cast<std::size_t>(d.max()+1));
56db0ac307SIgor Zhukov         assert(u.max_size() > static_cast<unsigned long long>(d.max()));
57eb1c5037SNikolas Klauser         for (int i = 0; i < N; ++i)
58eb1c5037SNikolas Klauser         {
5907e984bcSLouis Dionne             typename D::result_type v = d(g);
60eb1c5037SNikolas Klauser             assert(d.min() <= v && v <= d.max());
61db0ac307SIgor Zhukov             u[static_cast<std::size_t>(v)]++;
62eb1c5037SNikolas Klauser         }
63eb1c5037SNikolas Klauser         std::vector<double> prob = d.probabilities();
6407e984bcSLouis Dionne         for (unsigned i = 0; i < u.size(); ++i)
65eb1c5037SNikolas Klauser             assert((double)u[i]/N == prob[i]);
66eb1c5037SNikolas Klauser     }
67eb1c5037SNikolas Klauser     {
6807e984bcSLouis Dionne         typedef std::discrete_distribution<T> D;
69eb1c5037SNikolas Klauser         typedef std::minstd_rand G;
70eb1c5037SNikolas Klauser         G g;
71eb1c5037SNikolas Klauser         double p0[] = {.75, .25};
72eb1c5037SNikolas Klauser         D d(p0, p0+2);
73eb1c5037SNikolas Klauser         const int N = 1000000;
74db0ac307SIgor Zhukov         std::vector<Frequency> u(static_cast<std::size_t>(d.max()+1));
75db0ac307SIgor Zhukov         assert(u.max_size() > static_cast<unsigned long long>(d.max()));
76eb1c5037SNikolas Klauser         for (int i = 0; i < N; ++i)
77eb1c5037SNikolas Klauser         {
7807e984bcSLouis Dionne             typename D::result_type v = d(g);
79eb1c5037SNikolas Klauser             assert(d.min() <= v && v <= d.max());
80db0ac307SIgor Zhukov             u[static_cast<std::size_t>(v)]++;
81eb1c5037SNikolas Klauser         }
82eb1c5037SNikolas Klauser         std::vector<double> prob = d.probabilities();
8307e984bcSLouis Dionne         for (unsigned i = 0; i < u.size(); ++i)
84*76aa042dSMatt Stephanson           assert(std::abs((double)u[i] / N - prob[i]) / prob[i] < 0.0013);
85eb1c5037SNikolas Klauser     }
86eb1c5037SNikolas Klauser     {
8707e984bcSLouis Dionne         typedef std::discrete_distribution<T> D;
88eb1c5037SNikolas Klauser         typedef std::minstd_rand G;
89eb1c5037SNikolas Klauser         G g;
90eb1c5037SNikolas Klauser         double p0[] = {0, 1};
91eb1c5037SNikolas Klauser         D d(p0, p0+2);
92eb1c5037SNikolas Klauser         const int N = 1000000;
93db0ac307SIgor Zhukov         std::vector<Frequency> u(static_cast<std::size_t>(d.max()+1));
94db0ac307SIgor Zhukov         assert(u.max_size() > static_cast<unsigned long long>(d.max()));
95eb1c5037SNikolas Klauser         for (int i = 0; i < N; ++i)
96eb1c5037SNikolas Klauser         {
9707e984bcSLouis Dionne             typename D::result_type v = d(g);
98eb1c5037SNikolas Klauser             assert(d.min() <= v && v <= d.max());
99db0ac307SIgor Zhukov             u[static_cast<std::size_t>(v)]++;
100eb1c5037SNikolas Klauser         }
101eb1c5037SNikolas Klauser         std::vector<double> prob = d.probabilities();
102eb1c5037SNikolas Klauser         assert((double)u[0]/N == prob[0]);
103eb1c5037SNikolas Klauser         assert((double)u[1]/N == prob[1]);
104eb1c5037SNikolas Klauser     }
105eb1c5037SNikolas Klauser     {
10607e984bcSLouis Dionne         typedef std::discrete_distribution<T> D;
107eb1c5037SNikolas Klauser         typedef std::minstd_rand G;
108eb1c5037SNikolas Klauser         G g;
109eb1c5037SNikolas Klauser         double p0[] = {1, 0};
110eb1c5037SNikolas Klauser         D d(p0, p0+2);
111eb1c5037SNikolas Klauser         const int N = 1000000;
112db0ac307SIgor Zhukov         std::vector<Frequency> u(static_cast<std::size_t>(d.max()+1));
113db0ac307SIgor Zhukov         assert(u.max_size() > static_cast<unsigned long long>(d.max()));
114eb1c5037SNikolas Klauser         for (int i = 0; i < N; ++i)
115eb1c5037SNikolas Klauser         {
11607e984bcSLouis Dionne             typename D::result_type v = d(g);
117eb1c5037SNikolas Klauser             assert(d.min() <= v && v <= d.max());
118db0ac307SIgor Zhukov             u[static_cast<std::size_t>(v)]++;
119eb1c5037SNikolas Klauser         }
120eb1c5037SNikolas Klauser         std::vector<double> prob = d.probabilities();
121eb1c5037SNikolas Klauser         assert((double)u[0]/N == prob[0]);
122eb1c5037SNikolas Klauser         assert((double)u[1]/N == prob[1]);
123eb1c5037SNikolas Klauser     }
124eb1c5037SNikolas Klauser     {
12507e984bcSLouis Dionne         typedef std::discrete_distribution<T> D;
126eb1c5037SNikolas Klauser         typedef std::minstd_rand G;
127eb1c5037SNikolas Klauser         G g;
128eb1c5037SNikolas Klauser         double p0[] = {.3, .1, .6};
129eb1c5037SNikolas Klauser         D d(p0, p0+3);
130eb1c5037SNikolas Klauser         const int N = 10000000;
131db0ac307SIgor Zhukov         std::vector<Frequency> u(static_cast<std::size_t>(d.max()+1));
132db0ac307SIgor Zhukov         assert(u.max_size() > static_cast<unsigned long long>(d.max()));
133eb1c5037SNikolas Klauser         for (int i = 0; i < N; ++i)
134eb1c5037SNikolas Klauser         {
13507e984bcSLouis Dionne             typename D::result_type v = d(g);
136eb1c5037SNikolas Klauser             assert(d.min() <= v && v <= d.max());
137db0ac307SIgor Zhukov             u[static_cast<std::size_t>(v)]++;
138eb1c5037SNikolas Klauser         }
139eb1c5037SNikolas Klauser         std::vector<double> prob = d.probabilities();
14007e984bcSLouis Dionne         for (unsigned i = 0; i < u.size(); ++i)
141eb1c5037SNikolas Klauser             assert(std::abs((double)u[i]/N - prob[i]) / prob[i] < 0.001);
142eb1c5037SNikolas Klauser     }
143eb1c5037SNikolas Klauser     {
14407e984bcSLouis Dionne         typedef std::discrete_distribution<T> D;
145eb1c5037SNikolas Klauser         typedef std::minstd_rand G;
146eb1c5037SNikolas Klauser         G g;
147eb1c5037SNikolas Klauser         double p0[] = {0, 25, 75};
148eb1c5037SNikolas Klauser         D d(p0, p0+3);
149eb1c5037SNikolas Klauser         const int N = 1000000;
150db0ac307SIgor Zhukov         std::vector<Frequency> u(static_cast<std::size_t>(d.max()+1));
151db0ac307SIgor Zhukov         assert(u.max_size() > static_cast<unsigned long long>(d.max()));
152eb1c5037SNikolas Klauser         for (int i = 0; i < N; ++i)
153eb1c5037SNikolas Klauser         {
15407e984bcSLouis Dionne             typename D::result_type v = d(g);
155eb1c5037SNikolas Klauser             assert(d.min() <= v && v <= d.max());
156db0ac307SIgor Zhukov             u[static_cast<std::size_t>(v)]++;
157eb1c5037SNikolas Klauser         }
158eb1c5037SNikolas Klauser         std::vector<double> prob = d.probabilities();
15907e984bcSLouis Dionne         for (unsigned i = 0; i < u.size(); ++i)
160eb1c5037SNikolas Klauser             if (prob[i] != 0)
161*76aa042dSMatt Stephanson               assert(std::abs((double)u[i] / N - prob[i]) / prob[i] < 0.0013);
162eb1c5037SNikolas Klauser             else
163eb1c5037SNikolas Klauser                 assert(u[i] == 0);
164eb1c5037SNikolas Klauser     }
165eb1c5037SNikolas Klauser     {
16607e984bcSLouis Dionne         typedef std::discrete_distribution<T> D;
167eb1c5037SNikolas Klauser         typedef std::minstd_rand G;
168eb1c5037SNikolas Klauser         G g;
169eb1c5037SNikolas Klauser         double p0[] = {25, 0, 75};
170eb1c5037SNikolas Klauser         D d(p0, p0+3);
171eb1c5037SNikolas Klauser         const int N = 1000000;
172db0ac307SIgor Zhukov         std::vector<Frequency> u(static_cast<std::size_t>(d.max()+1));
173db0ac307SIgor Zhukov         assert(u.max_size() > static_cast<unsigned long long>(d.max()));
174eb1c5037SNikolas Klauser         for (int i = 0; i < N; ++i)
175eb1c5037SNikolas Klauser         {
17607e984bcSLouis Dionne             typename D::result_type v = d(g);
177eb1c5037SNikolas Klauser             assert(d.min() <= v && v <= d.max());
178db0ac307SIgor Zhukov             u[static_cast<std::size_t>(v)]++;
179eb1c5037SNikolas Klauser         }
180eb1c5037SNikolas Klauser         std::vector<double> prob = d.probabilities();
18107e984bcSLouis Dionne         for (unsigned i = 0; i < u.size(); ++i)
182eb1c5037SNikolas Klauser             if (prob[i] != 0)
183eb1c5037SNikolas Klauser                 assert(std::abs((double)u[i]/N - prob[i]) / prob[i] < 0.001);
184eb1c5037SNikolas Klauser             else
185eb1c5037SNikolas Klauser                 assert(u[i] == 0);
186eb1c5037SNikolas Klauser     }
187eb1c5037SNikolas Klauser     {
18807e984bcSLouis Dionne         typedef std::discrete_distribution<T> D;
189eb1c5037SNikolas Klauser         typedef std::minstd_rand G;
190eb1c5037SNikolas Klauser         G g;
191eb1c5037SNikolas Klauser         double p0[] = {25, 75, 0};
192eb1c5037SNikolas Klauser         D d(p0, p0+3);
193eb1c5037SNikolas Klauser         const int N = 1000000;
194db0ac307SIgor Zhukov         std::vector<Frequency> u(static_cast<std::size_t>(d.max()+1));
195db0ac307SIgor Zhukov         assert(u.max_size() > static_cast<unsigned long long>(d.max()));
196eb1c5037SNikolas Klauser         for (int i = 0; i < N; ++i)
197eb1c5037SNikolas Klauser         {
19807e984bcSLouis Dionne             typename D::result_type v = d(g);
199eb1c5037SNikolas Klauser             assert(d.min() <= v && v <= d.max());
200db0ac307SIgor Zhukov             u[static_cast<std::size_t>(v)]++;
201eb1c5037SNikolas Klauser         }
202eb1c5037SNikolas Klauser         std::vector<double> prob = d.probabilities();
20307e984bcSLouis Dionne         for (unsigned i = 0; i < u.size(); ++i)
204eb1c5037SNikolas Klauser             if (prob[i] != 0)
205*76aa042dSMatt Stephanson               assert(std::abs((double)u[i] / N - prob[i]) / prob[i] < 0.0013);
206eb1c5037SNikolas Klauser             else
207eb1c5037SNikolas Klauser                 assert(u[i] == 0);
208eb1c5037SNikolas Klauser     }
209eb1c5037SNikolas Klauser     {
21007e984bcSLouis Dionne         typedef std::discrete_distribution<T> D;
211eb1c5037SNikolas Klauser         typedef std::minstd_rand G;
212eb1c5037SNikolas Klauser         G g;
213eb1c5037SNikolas Klauser         double p0[] = {0, 0, 1};
214eb1c5037SNikolas Klauser         D d(p0, p0+3);
215eb1c5037SNikolas Klauser         const int N = 100;
216db0ac307SIgor Zhukov         std::vector<Frequency> u(static_cast<std::size_t>(d.max()+1));
217db0ac307SIgor Zhukov         assert(u.max_size() > static_cast<unsigned long long>(d.max()));
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());
222db0ac307SIgor Zhukov             u[static_cast<std::size_t>(v)]++;
223eb1c5037SNikolas Klauser         }
224eb1c5037SNikolas Klauser         std::vector<double> prob = d.probabilities();
22507e984bcSLouis Dionne         for (unsigned i = 0; i < u.size(); ++i)
226eb1c5037SNikolas Klauser             if (prob[i] != 0)
227eb1c5037SNikolas Klauser                 assert(std::abs((double)u[i]/N - prob[i]) / prob[i] < 0.001);
228eb1c5037SNikolas Klauser             else
229eb1c5037SNikolas Klauser                 assert(u[i] == 0);
230eb1c5037SNikolas Klauser     }
231eb1c5037SNikolas Klauser     {
23207e984bcSLouis Dionne         typedef std::discrete_distribution<T> D;
233eb1c5037SNikolas Klauser         typedef std::minstd_rand G;
234eb1c5037SNikolas Klauser         G g;
235eb1c5037SNikolas Klauser         double p0[] = {0, 1, 0};
236eb1c5037SNikolas Klauser         D d(p0, p0+3);
237eb1c5037SNikolas Klauser         const int N = 100;
238db0ac307SIgor Zhukov         std::vector<Frequency> u(static_cast<std::size_t>(d.max()+1));
239db0ac307SIgor Zhukov         assert(u.max_size() > static_cast<unsigned long long>(d.max()));
240eb1c5037SNikolas Klauser         for (int i = 0; i < N; ++i)
241eb1c5037SNikolas Klauser         {
24207e984bcSLouis Dionne             typename D::result_type v = d(g);
243eb1c5037SNikolas Klauser             assert(d.min() <= v && v <= d.max());
244db0ac307SIgor Zhukov             u[static_cast<std::size_t>(v)]++;
245eb1c5037SNikolas Klauser         }
246eb1c5037SNikolas Klauser         std::vector<double> prob = d.probabilities();
24707e984bcSLouis Dionne         for (unsigned i = 0; i < u.size(); ++i)
248eb1c5037SNikolas Klauser             if (prob[i] != 0)
249eb1c5037SNikolas Klauser                 assert(std::abs((double)u[i]/N - prob[i]) / prob[i] < 0.001);
250eb1c5037SNikolas Klauser             else
251eb1c5037SNikolas Klauser                 assert(u[i] == 0);
252eb1c5037SNikolas Klauser     }
253eb1c5037SNikolas Klauser     {
25407e984bcSLouis Dionne         typedef std::discrete_distribution<T> D;
255eb1c5037SNikolas Klauser         typedef std::minstd_rand G;
256eb1c5037SNikolas Klauser         G g;
257eb1c5037SNikolas Klauser         double p0[] = {1, 0, 0};
258eb1c5037SNikolas Klauser         D d(p0, p0+3);
259eb1c5037SNikolas Klauser         const int N = 100;
260db0ac307SIgor Zhukov         std::vector<Frequency> u(static_cast<std::size_t>(d.max()+1));
261db0ac307SIgor Zhukov         assert(u.max_size() > static_cast<unsigned long long>(d.max()));
262eb1c5037SNikolas Klauser         for (int i = 0; i < N; ++i)
263eb1c5037SNikolas Klauser         {
26407e984bcSLouis Dionne             typename D::result_type v = d(g);
265eb1c5037SNikolas Klauser             assert(d.min() <= v && v <= d.max());
266db0ac307SIgor Zhukov             u[static_cast<std::size_t>(v)]++;
267eb1c5037SNikolas Klauser         }
268eb1c5037SNikolas Klauser         std::vector<double> prob = d.probabilities();
26907e984bcSLouis Dionne         for (unsigned i = 0; i < u.size(); ++i)
270eb1c5037SNikolas Klauser             if (prob[i] != 0)
271eb1c5037SNikolas Klauser                 assert(std::abs((double)u[i]/N - prob[i]) / prob[i] < 0.001);
272eb1c5037SNikolas Klauser             else
273eb1c5037SNikolas Klauser                 assert(u[i] == 0);
274eb1c5037SNikolas Klauser     }
275eb1c5037SNikolas Klauser     {
27607e984bcSLouis Dionne         typedef std::discrete_distribution<T> D;
277eb1c5037SNikolas Klauser         typedef std::minstd_rand G;
278eb1c5037SNikolas Klauser         G g;
279eb1c5037SNikolas Klauser         double p0[] = {33, 0, 0, 67};
280eb1c5037SNikolas Klauser         D d(p0, p0+3);
281eb1c5037SNikolas Klauser         const int N = 1000000;
282db0ac307SIgor Zhukov         std::vector<Frequency> u(static_cast<std::size_t>(d.max()+1));
283db0ac307SIgor Zhukov         assert(u.max_size() > static_cast<unsigned long long>(d.max()));
284eb1c5037SNikolas Klauser         for (int i = 0; i < N; ++i)
285eb1c5037SNikolas Klauser         {
28607e984bcSLouis Dionne             typename D::result_type v = d(g);
287eb1c5037SNikolas Klauser             assert(d.min() <= v && v <= d.max());
288db0ac307SIgor Zhukov             u[static_cast<std::size_t>(v)]++;
289eb1c5037SNikolas Klauser         }
290eb1c5037SNikolas Klauser         std::vector<double> prob = d.probabilities();
29107e984bcSLouis Dionne         for (unsigned i = 0; i < u.size(); ++i)
292eb1c5037SNikolas Klauser             if (prob[i] != 0)
293*76aa042dSMatt Stephanson               assert(std::abs((double)u[i] / N - prob[i]) / prob[i] < 0.0013);
294eb1c5037SNikolas Klauser             else
295eb1c5037SNikolas Klauser                 assert(u[i] == 0);
296eb1c5037SNikolas Klauser     }
29707e984bcSLouis Dionne }
29807e984bcSLouis Dionne 
main(int,char **)29907e984bcSLouis Dionne int main(int, char**) {
30007e984bcSLouis Dionne     tests<short>();
30107e984bcSLouis Dionne     tests<int>();
30207e984bcSLouis Dionne     tests<long>();
30307e984bcSLouis Dionne     tests<long long>();
30407e984bcSLouis Dionne 
30507e984bcSLouis Dionne     tests<unsigned short>();
30607e984bcSLouis Dionne     tests<unsigned int>();
30707e984bcSLouis Dionne     tests<unsigned long>();
30807e984bcSLouis Dionne     tests<unsigned long long>();
30907e984bcSLouis Dionne 
31007e984bcSLouis Dionne #if defined(_LIBCPP_VERSION) // extension
311bd5d0feeSMark de Wever     tests<std::int8_t>();
312bd5d0feeSMark de Wever     tests<std::uint8_t>();
31307e984bcSLouis Dionne #if !defined(TEST_HAS_NO_INT128)
31407e984bcSLouis Dionne     tests<__int128_t>();
31507e984bcSLouis Dionne     tests<__uint128_t>();
31607e984bcSLouis Dionne #endif
31707e984bcSLouis Dionne #endif
318eb1c5037SNikolas Klauser 
319eb1c5037SNikolas Klauser     return 0;
320eb1c5037SNikolas Klauser }
321