1 //===----------------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // REQUIRES: long_tests
13 // template<class IntType = int>
14 // class poisson_distribution
16 // template<class _URNG> result_type operator()(_URNG& g);
26 #include "test_macros.h"
33 void test_bad_ranges() {
34 // Test cases where the mean is around the largest representable integer for
35 // `result_type`. These cases don't generate valid poisson distributions, but
36 // at least they don't blow up.
40 std::poisson_distribution
<std::int16_t> distribution(32710.9);
41 for (int i
=0; i
< 1000; ++i
) {
42 volatile std::int16_t res
= distribution(eng
);
47 std::poisson_distribution
<std::int16_t> distribution(std::numeric_limits
<std::int16_t>::max());
48 for (int i
=0; i
< 1000; ++i
) {
49 volatile std::int16_t res
= distribution(eng
);
54 std::poisson_distribution
<std::int16_t> distribution(
55 static_cast<double>(std::numeric_limits
<std::int16_t>::max()) + 10);
56 for (int i
=0; i
< 1000; ++i
) {
57 volatile std::int16_t res
= distribution(eng
);
62 std::poisson_distribution
<std::int16_t> distribution(
63 static_cast<double>(std::numeric_limits
<std::int16_t>::max()) * 2);
64 for (int i
=0; i
< 1000; ++i
) {
65 volatile std::int16_t res
= distribution(eng
);
70 // We convert `INF` to `DBL_MAX` otherwise the distribution will hang.
71 std::poisson_distribution
<std::int16_t> distribution(std::numeric_limits
<double>::infinity());
72 for (int i
=0; i
< 1000; ++i
) {
73 volatile std::int16_t res
= distribution(eng
);
78 std::poisson_distribution
<std::int16_t> distribution(0);
79 for (int i
=0; i
< 1000; ++i
) {
80 volatile std::int16_t res
= distribution(eng
);
85 // We convert `INF` to `DBL_MAX` otherwise the distribution will hang.
86 std::poisson_distribution
<std::int16_t> distribution(-100);
87 for (int i
=0; i
< 1000; ++i
) {
88 volatile std::int16_t res
= distribution(eng
);
97 typedef std::poisson_distribution
<T
> D
;
98 typedef std::minstd_rand G
;
101 const int N
= 100000;
102 std::vector
<double> u
;
103 for (int i
= 0; i
< N
; ++i
)
105 typename
D::result_type v
= d(g
);
106 assert(d
.min() <= v
&& v
<= d
.max());
109 double mean
= std::accumulate(u
.begin(), u
.end(), 0.0) / u
.size();
113 for (unsigned i
= 0; i
< u
.size(); ++i
)
115 double dbl
= (u
[i
] - mean
);
116 double d2
= sqr(dbl
);
122 double dev
= std::sqrt(var
);
123 skew
/= u
.size() * dev
* var
;
124 kurtosis
/= u
.size() * var
* var
;
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);
136 typedef std::poisson_distribution
<T
> D
;
137 typedef std::minstd_rand G
;
140 const int N
= 100000;
141 std::vector
<double> u
;
142 for (int i
= 0; i
< N
; ++i
)
144 typename
D::result_type v
= d(g
);
145 assert(d
.min() <= v
&& v
<= d
.max());
148 double mean
= std::accumulate(u
.begin(), u
.end(), 0.0) / u
.size();
152 for (unsigned i
= 0; i
< u
.size(); ++i
)
154 double dbl
= (u
[i
] - mean
);
155 double d2
= sqr(dbl
);
161 double dev
= std::sqrt(var
);
162 skew
/= u
.size() * dev
* var
;
163 kurtosis
/= u
.size() * var
* var
;
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);
175 typedef std::poisson_distribution
<T
> D
;
176 typedef std::mt19937 G
;
179 const int N
= 1000000;
180 std::vector
<double> u
;
181 for (int i
= 0; i
< N
; ++i
)
183 typename
D::result_type v
= d(g
);
184 assert(d
.min() <= v
&& v
<= d
.max());
187 double mean
= std::accumulate(u
.begin(), u
.end(), 0.0) / u
.size();
191 for (unsigned i
= 0; i
< u
.size(); ++i
)
193 double dbl
= (u
[i
] - mean
);
194 double d2
= sqr(dbl
);
200 double dev
= std::sqrt(var
);
201 skew
/= u
.size() * dev
* var
;
202 kurtosis
/= u
.size() * var
* var
;
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);
215 int main(int, char**) {
223 tests
<unsigned short>();
224 tests
<unsigned int>();
225 tests
<unsigned long>();
226 tests
<unsigned long long>();
228 #if defined(_LIBCPP_VERSION) // extension
229 // TODO: std::poisson_distribution currently doesn't work reliably with small types.
232 #if !defined(TEST_HAS_NO_INT128)
234 tests
<__uint128_t
>();