• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 poisson_distribution
16 
17 // template<class _URNG> result_type operator()(_URNG& g);
18 
19 #include <random>
20 #include <cassert>
21 #include <vector>
22 #include <numeric>
23 
24 template <class T>
25 inline
26 T
sqr(T x)27 sqr(T x)
28 {
29     return x * x;
30 }
31 
test_bad_ranges()32 void test_bad_ranges() {
33   // Test cases where the mean is around the largest representable integer for
34   // `result_type`. These cases don't generate valid poisson distributions, but
35   // at least they don't blow up.
36   std::mt19937 eng;
37 
38   {
39     std::poisson_distribution<std::int16_t> distribution(32710.9);
40     for (int i=0; i < 1000; ++i) {
41       volatile std::int16_t res = distribution(eng);
42       ((void)res);
43     }
44   }
45   {
46     std::poisson_distribution<std::int16_t> distribution(std::numeric_limits<std::int16_t>::max());
47     for (int i=0; i < 1000; ++i) {
48       volatile std::int16_t res = distribution(eng);
49       ((void)res);
50     }
51   }
52   {
53     std::poisson_distribution<std::int16_t> distribution(
54     static_cast<double>(std::numeric_limits<std::int16_t>::max()) + 10);
55     for (int i=0; i < 1000; ++i) {
56       volatile std::int16_t res = distribution(eng);
57       ((void)res);
58     }
59   }
60   {
61     std::poisson_distribution<std::int16_t> distribution(
62       static_cast<double>(std::numeric_limits<std::int16_t>::max()) * 2);
63       for (int i=0; i < 1000; ++i) {
64         volatile std::int16_t res = distribution(eng);
65         ((void)res);
66       }
67   }
68   {
69     // We convert `INF` to `DBL_MAX` otherwise the distribution will hang.
70     std::poisson_distribution<std::int16_t> distribution(std::numeric_limits<double>::infinity());
71     for (int i=0; i < 1000; ++i) {
72       volatile std::int16_t res = distribution(eng);
73       ((void)res);
74     }
75   }
76   {
77     std::poisson_distribution<std::int16_t> distribution(0);
78     for (int i=0; i < 1000; ++i) {
79       volatile std::int16_t res = distribution(eng);
80       ((void)res);
81     }
82   }
83   {
84     // We convert `INF` to `DBL_MAX` otherwise the distribution will hang.
85     std::poisson_distribution<std::int16_t> distribution(-100);
86     for (int i=0; i < 1000; ++i) {
87       volatile std::int16_t res = distribution(eng);
88       ((void)res);
89     }
90   }
91 }
92 
93 
main()94 int main()
95 {
96     {
97         typedef std::poisson_distribution<> D;
98         typedef std::minstd_rand G;
99         G g;
100         D d(2);
101         const int N = 100000;
102         std::vector<double> u;
103         for (int i = 0; i < N; ++i)
104         {
105             D::result_type v = d(g);
106             assert(d.min() <= v && v <= d.max());
107             u.push_back(v);
108         }
109         double mean = std::accumulate(u.begin(), u.end(), 0.0) / u.size();
110         double var = 0;
111         double skew = 0;
112         double kurtosis = 0;
113         for (unsigned i = 0; i < u.size(); ++i)
114         {
115             double dbl = (u[i] - mean);
116             double d2 = sqr(dbl);
117             var += d2;
118             skew += dbl * d2;
119             kurtosis += d2 * d2;
120         }
121         var /= u.size();
122         double dev = std::sqrt(var);
123         skew /= u.size() * dev * var;
124         kurtosis /= u.size() * var * var;
125         kurtosis -= 3;
126         double x_mean = d.mean();
127         double x_var = d.mean();
128         double x_skew = 1 / std::sqrt(x_var);
129         double x_kurtosis = 1 / x_var;
130         assert(std::abs((mean - x_mean) / x_mean) < 0.01);
131         assert(std::abs((var - x_var) / x_var) < 0.01);
132         assert(std::abs((skew - x_skew) / x_skew) < 0.01);
133         assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.03);
134     }
135     {
136         typedef std::poisson_distribution<> D;
137         typedef std::minstd_rand G;
138         G g;
139         D d(0.75);
140         const int N = 100000;
141         std::vector<double> u;
142         for (int i = 0; i < N; ++i)
143         {
144             D::result_type v = d(g);
145             assert(d.min() <= v && v <= d.max());
146             u.push_back(v);
147         }
148         double mean = std::accumulate(u.begin(), u.end(), 0.0) / u.size();
149         double var = 0;
150         double skew = 0;
151         double kurtosis = 0;
152         for (unsigned i = 0; i < u.size(); ++i)
153         {
154             double dbl = (u[i] - mean);
155             double d2 = sqr(dbl);
156             var += d2;
157             skew += dbl * d2;
158             kurtosis += d2 * d2;
159         }
160         var /= u.size();
161         double dev = std::sqrt(var);
162         skew /= u.size() * dev * var;
163         kurtosis /= u.size() * var * var;
164         kurtosis -= 3;
165         double x_mean = d.mean();
166         double x_var = d.mean();
167         double x_skew = 1 / std::sqrt(x_var);
168         double x_kurtosis = 1 / x_var;
169         assert(std::abs((mean - x_mean) / x_mean) < 0.01);
170         assert(std::abs((var - x_var) / x_var) < 0.01);
171         assert(std::abs((skew - x_skew) / x_skew) < 0.01);
172         assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.04);
173     }
174     {
175         typedef std::poisson_distribution<> D;
176         typedef std::mt19937 G;
177         G g;
178         D d(20);
179         const int N = 1000000;
180         std::vector<double> u;
181         for (int i = 0; i < N; ++i)
182         {
183             D::result_type v = d(g);
184             assert(d.min() <= v && v <= d.max());
185             u.push_back(v);
186         }
187         double mean = std::accumulate(u.begin(), u.end(), 0.0) / u.size();
188         double var = 0;
189         double skew = 0;
190         double kurtosis = 0;
191         for (unsigned i = 0; i < u.size(); ++i)
192         {
193             double dbl = (u[i] - mean);
194             double d2 = sqr(dbl);
195             var += d2;
196             skew += dbl * d2;
197             kurtosis += d2 * d2;
198         }
199         var /= u.size();
200         double dev = std::sqrt(var);
201         skew /= u.size() * dev * var;
202         kurtosis /= u.size() * var * var;
203         kurtosis -= 3;
204         double x_mean = d.mean();
205         double x_var = d.mean();
206         double x_skew = 1 / std::sqrt(x_var);
207         double x_kurtosis = 1 / x_var;
208         assert(std::abs((mean - x_mean) / x_mean) < 0.01);
209         assert(std::abs((var - x_var) / x_var) < 0.01);
210         assert(std::abs((skew - x_skew) / x_skew) < 0.01);
211         assert(std::abs((kurtosis - x_kurtosis) / x_kurtosis) < 0.01);
212     }
213 
214   test_bad_ranges();
215 }
216