]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/math/test/test_hyperexponential_dist.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / math / test / test_hyperexponential_dist.cpp
CommitLineData
7c673cae
FG
1// Copyright 2014 Marco Guazzone (marco.guazzone@gmail.com).
2//
3// Use, modification and distribution are subject to the
4// Boost Software License, Version 1.0.
5// (See accompanying file LICENSE_1_0.txt
6// or copy at http://www.boost.org/LICENSE_1_0.txt)
7//
8
9#include <algorithm>
10#include <boost/math/tools/test.hpp>
11#include <boost/math/concepts/real_concept.hpp>
12#include <boost/math/distributions/complement.hpp>
13#include <boost/math/distributions/hyperexponential.hpp>
14#include <boost/math/tools/precision.hpp>
15
16#define BOOST_TEST_MAIN
17#include <boost/test/unit_test.hpp>
92f5a8d4 18#include <boost/test/tools/floating_point_comparison.hpp>
7c673cae
FG
19
20#include <cstddef>
21#include <iostream>
22#include <vector>
1e59de90 23#include <tuple>
7c673cae
FG
24
25#define BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(T, actual, expected, tol) \
26 do { \
27 std::vector<T> x = (actual); \
28 std::vector<T> y = (expected); \
29 BOOST_CHECK_EQUAL( x.size(), y.size() ); \
30 const std::size_t n = x.size(); \
31 for (std::size_t i = 0; i < n; ++i) \
32 { \
33 BOOST_CHECK_CLOSE( x[i], y[i], tol ); \
34 } \
35 } while(false)
36
1e59de90
TL
37#if !defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS) && !defined(BOOST_MATH_NO_REAL_CONCEPT_TESTS)
38using test_types = std::tuple<float, double, long double, boost::math::concepts::real_concept>;
39#elif !defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS)
40using test_types = std::tuple<float, double, long double>;
7c673cae 41#else
1e59de90 42using test_types = std::tuple<float, double>;
7c673cae
FG
43#endif
44
45template <typename RealT>
46RealT make_tolerance()
47{
f67539c2 48 // Tolerance is 100eps expressed as a percentage (as required by Boost.Build):
7c673cae
FG
49 return boost::math::tools::epsilon<RealT>() * 100 * 100;
50}
51
52BOOST_AUTO_TEST_CASE_TEMPLATE(klass, RealT, test_types)
53{
54 const RealT tol = make_tolerance<RealT>();
55
56 boost::math::hyperexponential_distribution<RealT> dist;
57 BOOST_CHECK_EQUAL(dist.num_phases(), 1);
58 BOOST_CHECK_CLOSE(dist.probabilities()[0], static_cast<RealT>(1L), tol);
59 BOOST_CHECK_CLOSE(dist.rates()[0], static_cast<RealT>(1L), tol);
60
61 const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
62 const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
63 const std::size_t n = sizeof(probs) / sizeof(RealT);
64
65 boost::math::hyperexponential_distribution<RealT> dist_it(probs, probs+n, rates, rates+n);
66 BOOST_CHECK_EQUAL(dist_it.num_phases(), n);
67 BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_it.probabilities(), std::vector<RealT>(probs, probs+n), tol);
68 BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_it.rates(), std::vector<RealT>(rates, rates+n), tol);
69
70 boost::math::hyperexponential_distribution<RealT> dist_r(probs, rates);
71 BOOST_CHECK_EQUAL(dist_r.num_phases(), n);
72 BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_r.probabilities(), std::vector<RealT>(probs, probs+n), tol);
73 BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_r.rates(), std::vector<RealT>(rates, rates+n), tol);
74
75#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) && !(defined(BOOST_GCC_VERSION) && (BOOST_GCC_VERSION < 40500))
76 boost::math::hyperexponential_distribution<RealT> dist_il = {{static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L)}, {static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L)}};
77 BOOST_CHECK_EQUAL(dist_il.num_phases(), n);
78 BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_il.probabilities(), std::vector<RealT>(probs, probs+n), tol);
79 BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_il.rates(), std::vector<RealT>(rates, rates+n), tol);
80
81 boost::math::hyperexponential_distribution<RealT> dist_n_r = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
82 BOOST_CHECK_EQUAL(dist_n_r.num_phases(), n);
83 BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_n_r.probabilities(), std::vector<RealT>(n, static_cast<RealT>(1.0L / 3.0L)), tol);
84 BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_n_r.rates(), std::vector<RealT>(rates, rates + n), tol);
85#endif // BOOST_NO_CXX11_HDR_INITIALIZER_LIST
86
87 boost::math::hyperexponential_distribution<RealT> dist_n_it(rates, rates+n);
88 BOOST_CHECK_EQUAL(dist_n_it.num_phases(), n);
89 BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_n_it.probabilities(), std::vector<RealT>(n, static_cast<RealT>(1.0L/3.0L)), tol);
90 BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_n_it.rates(), std::vector<RealT>(rates, rates+n), tol);
91
92 boost::math::hyperexponential_distribution<RealT> dist_n_r2(rates);
93 BOOST_CHECK_EQUAL(dist_n_r2.num_phases(), n);
94 BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_n_r2.probabilities(), std::vector<RealT>(n, static_cast<RealT>(1.0L/3.0L)), tol);
95 BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_n_r2.rates(), std::vector<RealT>(rates, rates+n), tol);
96}
97
98BOOST_AUTO_TEST_CASE_TEMPLATE(range, RealT, test_types)
99{
100 const RealT tol = make_tolerance<RealT>();
101
102 const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
103 const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
104 const std::size_t n = sizeof(probs) / sizeof(RealT);
105
106 boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
107
108 std::pair<RealT,RealT> res;
109 res = boost::math::range(dist);
110
111 BOOST_CHECK_CLOSE( res.first, static_cast<RealT>(0), tol );
112 if(std::numeric_limits<RealT>::has_infinity)
113 {
114 BOOST_CHECK_EQUAL(res.second, std::numeric_limits<RealT>::infinity());
115 }
116 else
117 {
118 BOOST_CHECK_EQUAL(res.second, boost::math::tools::max_value<RealT>());
119 }
120}
121
122BOOST_AUTO_TEST_CASE_TEMPLATE(support, RealT, test_types)
123{
124 const RealT tol = make_tolerance<RealT>();
125
126 const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
127 const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1), static_cast<RealT>(1.5L) };
128 const std::size_t n = sizeof(probs)/sizeof(RealT);
129
130 boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
131
132 std::pair<RealT,RealT> res;
133 res = boost::math::support(dist);
134
135 BOOST_CHECK_CLOSE( res.first, boost::math::tools::min_value<RealT>(), tol );
136 BOOST_CHECK_CLOSE( res.second, boost::math::tools::max_value<RealT>(), tol );
137}
138
139BOOST_AUTO_TEST_CASE_TEMPLATE(pdf, RealT, test_types)
140{
141 const RealT tol = make_tolerance<RealT>();
142
143 const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
144 const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1), static_cast<RealT>(1.5) };
145 const std::size_t n = sizeof(probs)/sizeof(RealT);
146
147 boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
148
149 // Mathematica: Table[N[PDF[HyperexponentialDistribution[{1/5, 3/10, 1/2}, {1/2, 1, 3/2}], x], 35], {x, 0, 4}]
150 BOOST_CHECK_CLOSE( boost::math::pdf(dist, static_cast<RealT>(0)), static_cast<RealT>(1.15L), tol );
151 BOOST_CHECK_CLOSE( boost::math::pdf(dist, static_cast<RealT>(1)), static_cast<RealT>(0.33836451843401841053899743762056570L), tol );
152 BOOST_CHECK_CLOSE( boost::math::pdf(dist, static_cast<RealT>(2)), static_cast<RealT>(0.11472883036402599696225903724543774L), tol );
153 BOOST_CHECK_CLOSE( boost::math::pdf(dist, static_cast<RealT>(3)), static_cast<RealT>(0.045580883928883895659238122486617681L), tol );
154 BOOST_CHECK_CLOSE( boost::math::pdf(dist, static_cast<RealT>(4)), static_cast<RealT>(0.020887284122781292094799231452333314L), tol );
155}
156
157BOOST_AUTO_TEST_CASE_TEMPLATE(cdf, RealT, test_types)
158{
159 const RealT tol = make_tolerance<RealT>();
160
161 const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
162 const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
163 const std::size_t n = sizeof(probs)/sizeof(RealT);
164
165 boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
166
167 // Mathematica: Table[N[CDF[HyperexponentialDistribution[{1/5, 3/10, 1/2}, {1/2, 1, 3/2}], x], 35], {x, 0, 4}]
168 BOOST_CHECK_CLOSE( boost::math::cdf(dist, static_cast<RealT>(0)), static_cast<RealT>(0), tol );
169 BOOST_CHECK_CLOSE( boost::math::cdf(dist, static_cast<RealT>(1)), static_cast<RealT>(0.65676495563182570433394272657131939L), tol );
170 BOOST_CHECK_CLOSE( boost::math::cdf(dist, static_cast<RealT>(2)), static_cast<RealT>(0.86092999261079575662302418965093162L), tol );
171 BOOST_CHECK_CLOSE( boost::math::cdf(dist, static_cast<RealT>(3)), static_cast<RealT>(0.93488334919083369807146961400871370L), tol );
172 BOOST_CHECK_CLOSE( boost::math::cdf(dist, static_cast<RealT>(4)), static_cast<RealT>(0.96619887559772402832156211090812241L), tol );
173}
174
175
176BOOST_AUTO_TEST_CASE_TEMPLATE(quantile, RealT, test_types)
177{
178 const RealT tol = make_tolerance<RealT>();
179
180 const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
181 const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
182 const std::size_t n = sizeof(probs)/sizeof(RealT);
183
184 boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
185
186 // Mathematica: Table[N[Quantile[HyperexponentialDistribution[{1/5, 3/10, 1/2}, {1/2, 1, 3/2}], p], 35], {p, {0.`35, 0.6567649556318257043339427265713193884067872189124925936717`35, 0.8609299926107957566230241896509316171726985139265620607067`35, 0.9348833491908336980714696140087136988562861627183715044229`35, 0.9661988755977240283215621109081224127091468307592751727719`35}}]
187 BOOST_CHECK_CLOSE( boost::math::quantile(dist, static_cast<RealT>(0)), static_cast<RealT>(0), tol );
188 BOOST_CHECK_CLOSE( boost::math::quantile(dist, static_cast<RealT>(0.65676495563182570433394272657131939L)), static_cast<RealT>(1), tol );
189 BOOST_CHECK_CLOSE( boost::math::quantile(dist, static_cast<RealT>(0.86092999261079575662302418965093162L)), static_cast<RealT>(2), tol );
190 BOOST_CHECK_CLOSE( boost::math::quantile(dist, static_cast<RealT>(0.93488334919083369807146961400871370L)), static_cast<RealT>(3), tol );
191 BOOST_CHECK_CLOSE( boost::math::quantile(dist, static_cast<RealT>(0.96619887559772402832156211090812241L)), static_cast<RealT>(4), tol );
192}
193
194BOOST_AUTO_TEST_CASE_TEMPLATE(ccdf, RealT, test_types)
195{
196 const RealT tol = make_tolerance<RealT>();
197
198 const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
199 const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
200 const std::size_t n = sizeof(probs)/sizeof(RealT);
201
202 boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
203
204 // Mathematica: Table[N[SurvivalFunction[HyperexponentialDistribution[{1/5, 3/10, 1/2}, {1/2, 1, 3/2}], x], 35], {x, 0, 4}]
205 BOOST_CHECK_CLOSE( boost::math::cdf(boost::math::complement(dist, static_cast<RealT>(0))), static_cast<RealT>(1), tol );
206 BOOST_CHECK_CLOSE( boost::math::cdf(boost::math::complement(dist, static_cast<RealT>(1))), static_cast<RealT>(0.34323504436817429566605727342868061L), tol );
207 BOOST_CHECK_CLOSE( boost::math::cdf(boost::math::complement(dist, static_cast<RealT>(2))), static_cast<RealT>(0.13907000738920424337697581034906838L), tol );
208 BOOST_CHECK_CLOSE( boost::math::cdf(boost::math::complement(dist, static_cast<RealT>(3))), static_cast<RealT>(0.065116650809166301928530385991286301L), tol );
209 BOOST_CHECK_CLOSE( boost::math::cdf(boost::math::complement(dist, static_cast<RealT>(4))), static_cast<RealT>(0.033801124402275971678437889091877587L), tol );
210}
211
212
213BOOST_AUTO_TEST_CASE_TEMPLATE(cquantile, RealT, test_types)
214{
215 const RealT tol = make_tolerance<RealT>();
216
217 const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
218 const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
219 const std::size_t n = sizeof(probs) / sizeof(RealT);
220
221 boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
222
223 // Mathematica: Table[N[InverseSurvivalFunction[HyperexponentialDistribution[{1/5, 3/10, 1/2}, {1/2, 1, 3/2}], p], 35], {p, {1.`35, 0.3432350443681742956660572734286806115932127810875074063283`35, 0.1390700073892042433769758103490683828273014860734379392933`35, 0.0651166508091663019285303859912863011437138372816284955771`35, 0.0338011244022759716784378890918775872908531692407248272281`35}}]
224 BOOST_CHECK_CLOSE( boost::math::quantile(boost::math::complement(dist, static_cast<RealT>(1))), static_cast<RealT>(0), tol );
225 BOOST_CHECK_CLOSE( boost::math::quantile(boost::math::complement(dist, static_cast<RealT>(0.34323504436817429566605727342868061L))), static_cast<RealT>(1), tol );
226 BOOST_CHECK_CLOSE( boost::math::quantile(boost::math::complement(dist, static_cast<RealT>(0.13907000738920424337697581034906838L))), static_cast<RealT>(2), tol );
227 BOOST_CHECK_CLOSE( boost::math::quantile(boost::math::complement(dist, static_cast<RealT>(0.065116650809166301928530385991286301L))), static_cast<RealT>(3), tol );
228 BOOST_CHECK_CLOSE( boost::math::quantile(boost::math::complement(dist, static_cast<RealT>(0.033801124402275971678437889091877587L))), static_cast<RealT>(4), tol );
229}
230
231BOOST_AUTO_TEST_CASE_TEMPLATE(mean, RealT, test_types)
232{
233 const RealT tol = make_tolerance<RealT>();
234
235 const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
236 const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
237 const std::size_t n = sizeof(probs) / sizeof(RealT);
238
239 boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
240
241 // Mathematica: N[Mean[HyperexponentialDistribution[{1/5, 3/10, 1/2}, {1/2, 1, 3/2}]], 35]
242 BOOST_CHECK_CLOSE( boost::math::mean(dist), static_cast<RealT>(1.0333333333333333333333333333333333L), tol );
243}
244
245BOOST_AUTO_TEST_CASE_TEMPLATE(variance, RealT, test_types)
246{
247 const RealT tol = make_tolerance<RealT>();
248
249 const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
250 const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
251 const std::size_t n = sizeof(probs) / sizeof(RealT);
252
253 boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
254
255 // Mathematica: N[Variance[HyperexponentialDistribution[{1/5, 3/10, 1/2}, {1/2, 1, 3/2}]], 35]
256 BOOST_CHECK_CLOSE( boost::math::variance(dist), static_cast<RealT>(1.5766666666666666666666666666666667L), tol );
257}
258
259BOOST_AUTO_TEST_CASE_TEMPLATE(kurtosis, RealT, test_types)
260{
261 const RealT tol = make_tolerance<RealT>();
262
263 const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
264 const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
265 const std::size_t n = sizeof(probs) / sizeof(RealT);
266
267 boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
268
269 // Mathematica: N[Kurtosis[HyperexponentialDistribution[{1/5, 3/10, 1/2}, {1/2, 1, 3/2}]], 35]
270 BOOST_CHECK_CLOSE( boost::math::kurtosis(dist), static_cast<RealT>(19.750738616808728416968743435138046L), tol );
271 // Mathematica: N[Kurtosis[HyperexponentialDistribution[{1/5, 3/10, 1/2}, {1/2, 1, 3/2}] - 3.`35], 35]
272 BOOST_CHECK_CLOSE( boost::math::kurtosis_excess(dist), static_cast<RealT>(16.750738616808728416968743435138046L), tol );
273}
274
275BOOST_AUTO_TEST_CASE_TEMPLATE(skewness, RealT, test_types)
276{
277 const RealT tol = make_tolerance<RealT>();
278
279 const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
280 const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
281 const std::size_t n = sizeof(probs) / sizeof(RealT);
282
283 boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
284
285 // Mathematica: N[Skewness[HyperexponentialDistribution[{1/5, 3/10, 1/2}, {1/2, 1, 3/2}]], 35]
286 BOOST_CHECK_CLOSE( boost::math::skewness(dist), static_cast<RealT>(3.1811387449963809211146099116375685L), tol );
287}
288
289BOOST_AUTO_TEST_CASE_TEMPLATE(mode, RealT, test_types)
290{
291 const RealT tol = make_tolerance<RealT>();
292
293 const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
294 const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
295 const std::size_t n = sizeof(probs) / sizeof(RealT);
296
297 boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
298
299 BOOST_CHECK_CLOSE( boost::math::mode(dist), static_cast<RealT>(0), tol );
300}
301
302template <class T>
303void f(T t)
304{
305 std::cout << typeid(t).name() << std::endl;
306}
307
308BOOST_AUTO_TEST_CASE(construct)
309{
1e59de90
TL
310 std::array<double, 3> da1 = { { 0.5, 1, 1.5 } };
311 std::array<double, 3> da2 = { { 0.25, 0.5, 0.25 } };
7c673cae
FG
312 std::vector<double> v1(da1.begin(), da1.end());
313 std::vector<double> v2(da2.begin(), da2.end());
314
315 std::vector<double> result_v;
316 boost::math::hyperexponential he1(v2, v1);
317 result_v = he1.rates();
318 BOOST_CHECK_EQUAL_COLLECTIONS(v1.begin(), v1.end(), result_v.begin(), result_v.end());
319 result_v = he1.probabilities();
320 BOOST_CHECK_EQUAL_COLLECTIONS(v2.begin(), v2.end(), result_v.begin(), result_v.end());
321
322 boost::math::hyperexponential he2(da2, da1);
323 result_v = he2.rates();
324 BOOST_CHECK_EQUAL_COLLECTIONS(v1.begin(), v1.end(), result_v.begin(), result_v.end());
325 result_v = he2.probabilities();
326 BOOST_CHECK_EQUAL_COLLECTIONS(v2.begin(), v2.end(), result_v.begin(), result_v.end());
327
328#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) && !(defined(BOOST_GCC_VERSION) && (BOOST_GCC_VERSION < 40500))
329 std::initializer_list<double> il = { 0.25, 0.5, 0.25 };
330 std::initializer_list<double> il2 = { 0.5, 1, 1.5 };
331 boost::math::hyperexponential he3(il, il2);
332 result_v = he3.rates();
333 BOOST_CHECK_EQUAL_COLLECTIONS(v1.begin(), v1.end(), result_v.begin(), result_v.end());
334 result_v = he3.probabilities();
335 BOOST_CHECK_EQUAL_COLLECTIONS(v2.begin(), v2.end(), result_v.begin(), result_v.end());
336
337 boost::math::hyperexponential he4({ 0.25, 0.5, 0.25 }, { 0.5, 1.0, 1.5 });
338 result_v = he4.rates();
339 BOOST_CHECK_EQUAL_COLLECTIONS(v1.begin(), v1.end(), result_v.begin(), result_v.end());
340 result_v = he4.probabilities();
341 BOOST_CHECK_EQUAL_COLLECTIONS(v2.begin(), v2.end(), result_v.begin(), result_v.end());
342#endif
343}
344
345BOOST_AUTO_TEST_CASE_TEMPLATE(special_cases, RealT, test_types)
346{
347 const RealT tol = make_tolerance<RealT>();
348
349 // When the number of phases is 1, the hyperexponential distribution is an exponential distribution
350 const RealT rates1[] = { static_cast<RealT>(0.5L) };
351 boost::math::hyperexponential_distribution<RealT> hexp1(rates1);
352 boost::math::exponential_distribution<RealT> exp1(rates1[0]);
353 BOOST_CHECK_CLOSE(boost::math::pdf(hexp1, static_cast<RealT>(1L)), boost::math::pdf(exp1, static_cast<RealT>(1L)), tol);
354 BOOST_CHECK_CLOSE(boost::math::cdf(hexp1, static_cast<RealT>(1L)), boost::math::cdf(exp1, static_cast<RealT>(1L)), tol);
355 BOOST_CHECK_CLOSE(boost::math::mean(hexp1), boost::math::mean(exp1), tol);
356 BOOST_CHECK_CLOSE(boost::math::variance(hexp1), boost::math::variance(exp1), tol);
357 BOOST_CHECK_CLOSE(boost::math::quantile(hexp1, static_cast<RealT>(0.25L)), boost::math::quantile(exp1, static_cast<RealT>(0.25L)), tol);
358 BOOST_CHECK_CLOSE(boost::math::median(hexp1), boost::math::median(exp1), tol);
359 BOOST_CHECK_CLOSE(boost::math::quantile(hexp1, static_cast<RealT>(0.75L)), boost::math::quantile(exp1, static_cast<RealT>(0.75L)), tol);
360 BOOST_CHECK_CLOSE(boost::math::mode(hexp1), boost::math::mode(exp1), tol);
361
362 // When a k-phase hyperexponential distribution has all rates equal to r, the distribution is an exponential distribution with rate r
363 const RealT rate2 = static_cast<RealT>(0.5L);
364 const RealT rates2[] = { rate2, rate2, rate2 };
365 boost::math::hyperexponential_distribution<RealT> hexp2(rates2);
366 boost::math::exponential_distribution<RealT> exp2(rate2);
367 BOOST_CHECK_CLOSE(boost::math::pdf(hexp2, static_cast<RealT>(1L)), boost::math::pdf(exp2, static_cast<RealT>(1L)), tol);
368 BOOST_CHECK_CLOSE(boost::math::cdf(hexp2, static_cast<RealT>(1L)), boost::math::cdf(exp2, static_cast<RealT>(1L)), tol);
369 BOOST_CHECK_CLOSE(boost::math::mean(hexp2), boost::math::mean(exp2), tol);
370 BOOST_CHECK_CLOSE(boost::math::variance(hexp2), boost::math::variance(exp2), tol);
371 BOOST_CHECK_CLOSE(boost::math::quantile(hexp2, static_cast<RealT>(0.25L)), boost::math::quantile(exp2, static_cast<RealT>(0.25L)), tol);
372 BOOST_CHECK_CLOSE(boost::math::median(hexp2), boost::math::median(exp2), tol);
373 BOOST_CHECK_CLOSE(boost::math::quantile(hexp2, static_cast<RealT>(0.75L)), boost::math::quantile(exp2, static_cast<RealT>(0.75L)), tol);
374 BOOST_CHECK_CLOSE(boost::math::mode(hexp2), boost::math::mode(exp2), tol);
375}
376
377BOOST_AUTO_TEST_CASE_TEMPLATE(error_cases, RealT, test_types)
378{
379 typedef boost::math::hyperexponential_distribution<RealT> dist_t;
1e59de90
TL
380 std::array<RealT, 2> probs = { { 1, 2 } };
381 std::array<RealT, 3> probs2 = { { 1, 2, 3 } };
382 std::array<RealT, 3> rates = { { 1, 2, 3 } };
7c673cae
FG
383 BOOST_MATH_CHECK_THROW(dist_t(probs.begin(), probs.end(), rates.begin(), rates.end()), std::domain_error);
384 BOOST_MATH_CHECK_THROW(dist_t(probs, rates), std::domain_error);
385 rates[1] = 0;
386 BOOST_MATH_CHECK_THROW(dist_t(probs2, rates), std::domain_error);
387 rates[1] = -1;
388 BOOST_MATH_CHECK_THROW(dist_t(probs2, rates), std::domain_error);
389 BOOST_MATH_CHECK_THROW(dist_t(probs.begin(), probs.begin(), rates.begin(), rates.begin()), std::domain_error);
390 BOOST_MATH_CHECK_THROW(dist_t(rates.begin(), rates.begin()), std::domain_error);
1e59de90
TL
391
392 // Test C++20 ranges (Currently only GCC10 has full support to P0896R4)
393 #if (__cplusplus > 202000L || _MSVC_LANG > 202000L) && __has_include(<ranges>) && __GNUC__ >= 10
394 // Support for ranges is broken using gcc 11.1
395 #if __GNUC__ != 11
396 #include <ranges>
397 #include <array>
398
399 std::array<RealT, 2> probs_array {1,2};
400 std::array<RealT, 3> rates_array {1,2,3};
401 BOOST_MATH_CHECK_THROW(dist_t(std::ranges::begin(probs_array), std::ranges::end(probs_array), std::ranges::begin(rates_array), std::ranges::end(rates_array)), std::domain_error);
402
403 const auto probs_range = probs_array | std::ranges::views::all;
404 const auto rates_range = rates_array | std::ranges::views::all;
405
406 BOOST_MATH_CHECK_THROW(dist_t(probs_range, rates_range), std::domain_error);
407 #endif
408 #endif
7c673cae 409}