]>
Commit | Line | Data |
---|---|---|
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) |
38 | using test_types = std::tuple<float, double, long double, boost::math::concepts::real_concept>; | |
39 | #elif !defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS) | |
40 | using test_types = std::tuple<float, double, long double>; | |
7c673cae | 41 | #else |
1e59de90 | 42 | using test_types = std::tuple<float, double>; |
7c673cae FG |
43 | #endif |
44 | ||
45 | template <typename RealT> | |
46 | RealT 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 | ||
52 | BOOST_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 | ||
98 | BOOST_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 | ||
122 | BOOST_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 | ||
139 | BOOST_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 | ||
157 | BOOST_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 | ||
176 | BOOST_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 | ||
194 | BOOST_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 | ||
213 | BOOST_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 | ||
231 | BOOST_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 | ||
245 | BOOST_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 | ||
259 | BOOST_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 | ||
275 | BOOST_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 | ||
289 | BOOST_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 | ||
302 | template <class T> | |
303 | void f(T t) | |
304 | { | |
305 | std::cout << typeid(t).name() << std::endl; | |
306 | } | |
307 | ||
308 | BOOST_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 | ||
345 | BOOST_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 | ||
377 | BOOST_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 | } |