]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Copyright 2008 Gautam Sewani |
2 | // Copyright 2013 Paul A. Bristow | |
3 | ||
4 | // Use, modification and distribution are subject to the | |
5 | // Boost Software License, Version 1.0. | |
6 | // (See accompanying file LICENSE_1_0.txt | |
7 | // or copy at http://www.boost.org/LICENSE_1_0.txt) | |
8 | ||
9 | #ifdef _MSC_VER | |
10 | # pragma warning (disable : 4127) // conditional expression is constant. | |
11 | # pragma warning (disable : 4512) // assignment operator could not be generated. | |
12 | #endif | |
13 | ||
14 | #include <boost/config.hpp> | |
15 | #ifndef BOOST_NO_EXCEPTIONS | |
16 | #define BOOST_MATH_UNDERFLOW_ERROR_POLICY throw_on_error | |
17 | #define BOOST_MATH_OVERFLOW_ERROR_POLICY throw_on_error | |
18 | #endif | |
19 | #include <boost/math/tools/test.hpp> | |
20 | #include <boost/math/concepts/real_concept.hpp> // for real_concept | |
21 | #include <boost/math/distributions/logistic.hpp> | |
22 | using boost::math::logistic_distribution; | |
23 | ||
24 | #define BOOST_TEST_MAIN | |
25 | #include <boost/test/unit_test.hpp> // Boost.Test | |
92f5a8d4 | 26 | #include <boost/test/tools/floating_point_comparison.hpp> |
7c673cae FG |
27 | #include "test_out_of_range.hpp" |
28 | ||
29 | #include <iostream> | |
30 | using std::cout; | |
31 | using std::endl; | |
32 | using std::setprecision; | |
33 | ||
34 | template <class RealType> | |
35 | void test_spot(RealType location, RealType scale, RealType x, RealType p, RealType q, RealType tolerance) | |
36 | { | |
37 | BOOST_CHECK_CLOSE( | |
38 | ::boost::math::cdf( | |
39 | logistic_distribution<RealType>(location,scale), | |
40 | x), | |
41 | p, | |
42 | tolerance); // % | |
43 | BOOST_CHECK_CLOSE( | |
44 | ::boost::math::cdf( | |
45 | complement(logistic_distribution<RealType>(location,scale), | |
46 | x)), | |
47 | q, | |
48 | tolerance); // % | |
49 | if(p < 0.999) | |
50 | { | |
51 | BOOST_CHECK_CLOSE( | |
52 | ::boost::math::quantile( | |
53 | logistic_distribution<RealType>(location,scale), | |
54 | p), | |
55 | x, | |
56 | tolerance); // % | |
57 | } | |
58 | if(q < 0.999) | |
59 | { | |
60 | BOOST_CHECK_CLOSE( | |
61 | ::boost::math::quantile( | |
62 | complement(logistic_distribution<RealType>(location,scale), | |
63 | q)), | |
64 | x, | |
65 | 2 * tolerance); // % | |
66 | } | |
67 | } | |
68 | ||
69 | ||
70 | template <class RealType> | |
71 | void test_spots(RealType T) | |
72 | { | |
73 | // Basic sanity checks. | |
74 | // 50 eps as a percentage, up to a maximum of double precision | |
75 | // Test data taken from Mathematica 6 | |
76 | RealType tolerance = (std::max)( | |
77 | static_cast<RealType>(1e-33L), | |
78 | boost::math::tools::epsilon<RealType>()); | |
79 | cout<<"Absolute tolerance:"<<tolerance<<endl; | |
80 | ||
81 | tolerance *= 50 * 100; | |
82 | // # pragma warning(disable: 4100) // unreferenced formal parameter. | |
83 | // prevent his spurious warning. | |
84 | if (T != 0) | |
85 | { | |
86 | cout << "Expect parameter T == 0!" << endl; | |
87 | } | |
88 | cout << "Tolerance for type " << typeid(T).name() << " is " << tolerance << " %" << endl; | |
89 | ||
90 | test_spot( | |
91 | static_cast<RealType>(1), // location | |
92 | static_cast<RealType>(0.5L), // scale | |
93 | static_cast<RealType>(0.1L), // x | |
94 | static_cast<RealType>(0.141851064900487789594278108470953L), // p | |
95 | static_cast<RealType>(0.858148935099512210405721891529047L), //q | |
96 | tolerance); | |
97 | ||
98 | test_spot( | |
99 | static_cast<RealType>(5), // location | |
100 | static_cast<RealType>(2), // scale | |
101 | static_cast<RealType>(3.123123123L),//x | |
102 | static_cast<RealType>(0.281215878622547904873088053477813L), // p | |
103 | static_cast<RealType>(0.718784121377452095126911946522187L), //q | |
104 | tolerance); | |
105 | ||
106 | test_spot( | |
107 | static_cast<RealType>(1.2345L), // location | |
108 | static_cast<RealType>(0.12345L), // scale | |
109 | static_cast<RealType>(3.123123123L),//x | |
110 | static_cast<RealType>(0.999999773084685079723328282229357L), // p | |
111 | static_cast<RealType>(2.26915314920276671717770643005212e-7L), //q | |
112 | tolerance); | |
113 | ||
114 | ||
115 | //High probability | |
116 | test_spot( | |
117 | static_cast<RealType>(1), // location | |
118 | static_cast<RealType>(0.5L), // scale | |
119 | static_cast<RealType>(10), // x | |
120 | static_cast<RealType>(0.99999998477002048723965105559179L), // p | |
121 | static_cast<RealType>(1.5229979512760348944408208801237e-8L), //q | |
122 | tolerance); | |
123 | ||
124 | //negative x | |
125 | test_spot( | |
126 | static_cast<RealType>(5), // location | |
127 | static_cast<RealType>(2), // scale | |
128 | static_cast<RealType>(-0.1L), // scale | |
129 | static_cast<RealType>(0.0724264853615177178439235061476928L), // p | |
130 | static_cast<RealType>(0.927573514638482282156076493852307L), //q | |
131 | tolerance); | |
132 | ||
133 | ||
134 | test_spot( | |
135 | static_cast<RealType>(5), // location | |
136 | static_cast<RealType>(2), // scale | |
137 | static_cast<RealType>(-20), // x | |
138 | static_cast<RealType>(3.72663928418656138608800947863869e-6L), // p | |
139 | static_cast<RealType>(0.999996273360715813438613911990521L), //q | |
140 | tolerance); | |
141 | ||
142 | ||
143 | // Test value to check cancellation error in straight/complemented quantile. | |
144 | // The subtraction in the formula location-scale*log term introduces catastrophic | |
145 | // cancellation error if location and scale*log term are close. | |
146 | // For these values, the tests fail at tolerance, but work at 100*tolerance. | |
147 | test_spot( | |
148 | static_cast<RealType>(-1.2345L), // location | |
149 | static_cast<RealType>(1.4555L), // scale | |
150 | static_cast<RealType>(-0.00125796420642514024493852425918807L),// x | |
151 | static_cast<RealType>(0.7L), // p | |
152 | static_cast<RealType>(0.3L), //q | |
153 | 80*tolerance); | |
154 | ||
155 | test_spot( | |
156 | static_cast<RealType>(1.2345L), // location | |
157 | static_cast<RealType>(0.12345L), // scale | |
158 | static_cast<RealType>(0.0012345L), // x | |
159 | static_cast<RealType>(0.0000458541039469413343331170952855318L), // p | |
160 | static_cast<RealType>(0.999954145896053058665666882904714L), //q | |
161 | 80*tolerance); | |
162 | ||
163 | ||
164 | ||
165 | test_spot( | |
166 | static_cast<RealType>(5L), // location | |
167 | static_cast<RealType>(2L), // scale | |
168 | static_cast<RealType>(0.0012345L), // x | |
169 | static_cast<RealType>(0.0759014628704232983512906076564256L), // p | |
170 | static_cast<RealType>(0.924098537129576701648709392343574L), //q | |
171 | 80*tolerance); | |
172 | ||
173 | //negative location | |
174 | test_spot( | |
175 | static_cast<RealType>(-123.123123L), // location | |
176 | static_cast<RealType>(2.123L), // scale | |
177 | static_cast<RealType>(3), // x | |
178 | static_cast<RealType>(0.999999999999999999999999984171276L), // p | |
179 | static_cast<RealType>(1.58287236765203121622150720373972e-26L), //q | |
180 | tolerance); | |
181 | //PDF Testing | |
182 | BOOST_CHECK_CLOSE( | |
183 | ::boost::math::pdf( | |
184 | logistic_distribution<RealType>(5,2), | |
185 | static_cast<RealType>(0.125L) ),//x | |
186 | static_cast<RealType>(0.0369500730133475464584898192104821L), // probability | |
187 | tolerance); // % | |
188 | ||
189 | BOOST_CHECK_CLOSE( | |
190 | ::boost::math::pdf( | |
191 | logistic_distribution<RealType>(static_cast<RealType>(1.2345L), static_cast<RealType>(0.12345L)), | |
192 | static_cast<RealType>(0.0012345L) ),//x | |
193 | static_cast<RealType>(0.000371421639109700748742498671686243L), // probability | |
194 | tolerance); // % | |
195 | BOOST_CHECK_CLOSE( | |
196 | ::boost::math::pdf( | |
197 | logistic_distribution<RealType>(2,1), | |
198 | static_cast<RealType>(2L) ),//x | |
199 | static_cast<RealType>(0.25L), // probability | |
200 | tolerance); // % | |
201 | ||
202 | //Extreme value testing | |
203 | ||
204 | if(std::numeric_limits<RealType>::has_infinity) | |
205 | { | |
206 | BOOST_CHECK_EQUAL(pdf(logistic_distribution<RealType>(), +std::numeric_limits<RealType>::infinity()), 0); // x = + infinity, pdf = 0 | |
207 | BOOST_CHECK_EQUAL(pdf(logistic_distribution<RealType>(), -std::numeric_limits<RealType>::infinity()), 0); // x = - infinity, pdf = 0 | |
208 | BOOST_CHECK_EQUAL(cdf(logistic_distribution<RealType>(), +std::numeric_limits<RealType>::infinity()), 1); // x = + infinity, cdf = 1 | |
209 | BOOST_CHECK_EQUAL(cdf(logistic_distribution<RealType>(), -std::numeric_limits<RealType>::infinity()), 0); // x = - infinity, cdf = 0 | |
210 | BOOST_CHECK_EQUAL(cdf(complement(logistic_distribution<RealType>(), +std::numeric_limits<RealType>::infinity())), 0); // x = + infinity, c cdf = 0 | |
211 | BOOST_CHECK_EQUAL(cdf(complement(logistic_distribution<RealType>(), -std::numeric_limits<RealType>::infinity())), 1); // x = - infinity, c cdf = 1 | |
212 | } | |
213 | BOOST_MATH_CHECK_THROW(quantile(logistic_distribution<RealType>(), static_cast<RealType>(1)), std::overflow_error); // x = + infinity, cdf = 1 | |
214 | BOOST_MATH_CHECK_THROW(quantile(logistic_distribution<RealType>(), static_cast<RealType>(0)), std::overflow_error); // x = - infinity, cdf = 0 | |
215 | BOOST_MATH_CHECK_THROW(quantile(complement(logistic_distribution<RealType>(), static_cast<RealType>(1))), std::overflow_error); // x = - infinity, cdf = 0 | |
216 | BOOST_MATH_CHECK_THROW(quantile(complement(logistic_distribution<RealType>(), static_cast<RealType>(0))), std::overflow_error); // x = + infinity, cdf = 1 | |
217 | BOOST_CHECK_EQUAL(cdf(logistic_distribution<RealType>(), +boost::math::tools::max_value<RealType>()), 1); // x = + infinity, cdf = 1 | |
218 | BOOST_CHECK_EQUAL(cdf(logistic_distribution<RealType>(), -boost::math::tools::max_value<RealType>()), 0); // x = - infinity, cdf = 0 | |
219 | BOOST_CHECK_EQUAL(cdf(complement(logistic_distribution<RealType>(), +boost::math::tools::max_value<RealType>())), 0); // x = + infinity, c cdf = 0 | |
220 | BOOST_CHECK_EQUAL(cdf(complement(logistic_distribution<RealType>(), -boost::math::tools::max_value<RealType>())), 1); // x = - infinity, c cdf = 1 | |
221 | BOOST_CHECK_EQUAL(pdf(logistic_distribution<RealType>(), +boost::math::tools::max_value<RealType>()), 0); // x = + infinity, pdf = 0 | |
222 | BOOST_CHECK_EQUAL(pdf(logistic_distribution<RealType>(), -boost::math::tools::max_value<RealType>()), 0); // x = - infinity, pdf = 0 | |
223 | ||
224 | // | |
225 | // Things that are errors: | |
226 | // 1. Domain errors for scale and location. | |
227 | // 2. x being NAN. | |
228 | // 3. Probabilies being outside (0,1). | |
229 | check_out_of_range<logistic_distribution<RealType> >(0, 1); | |
230 | if(std::numeric_limits<RealType>::has_infinity) | |
231 | { | |
232 | RealType inf = std::numeric_limits<RealType>::infinity(); | |
233 | BOOST_CHECK_EQUAL(pdf(logistic_distribution<RealType>(0, 1), inf), 0); | |
234 | BOOST_CHECK_EQUAL(pdf(logistic_distribution<RealType>(0, 1), -inf), 0); | |
235 | BOOST_CHECK_EQUAL(cdf(logistic_distribution<RealType>(0, 1), inf), 1); | |
236 | BOOST_CHECK_EQUAL(cdf(logistic_distribution<RealType>(0, 1), -inf), 0); | |
237 | BOOST_CHECK_EQUAL(cdf(complement(logistic_distribution<RealType>(0, 1), inf)), 0); | |
238 | BOOST_CHECK_EQUAL(cdf(complement(logistic_distribution<RealType>(0, 1), -inf)), 1); | |
239 | } | |
240 | ||
241 | // location/scale can't be infinity. | |
242 | if(std::numeric_limits<RealType>::has_infinity) | |
243 | { | |
244 | #ifndef BOOST_NO_EXCEPTIONS | |
245 | BOOST_MATH_CHECK_THROW( | |
246 | logistic_distribution<RealType> dist(std::numeric_limits<RealType>::infinity(), 0.5), | |
247 | std::domain_error); | |
248 | BOOST_MATH_CHECK_THROW( | |
249 | logistic_distribution<RealType> dist(0.5, std::numeric_limits<RealType>::infinity()), | |
250 | std::domain_error); | |
251 | #else | |
252 | BOOST_MATH_CHECK_THROW( | |
253 | logistic_distribution<RealType>(std::numeric_limits<RealType>::infinity(), 0.5), | |
254 | std::domain_error); | |
255 | BOOST_MATH_CHECK_THROW( | |
256 | logistic_distribution<RealType>(0.5, std::numeric_limits<RealType>::infinity()), | |
257 | std::domain_error); | |
258 | #endif | |
259 | } | |
260 | // scale can't be negative or 0. | |
261 | #ifndef BOOST_NO_EXCEPTIONS | |
262 | BOOST_MATH_CHECK_THROW( | |
263 | logistic_distribution<RealType> dist(0.5, -0.5), | |
264 | std::domain_error); | |
265 | BOOST_MATH_CHECK_THROW( | |
266 | logistic_distribution<RealType> dist(0.5, 0), | |
267 | std::domain_error); | |
268 | #else | |
269 | BOOST_MATH_CHECK_THROW( | |
270 | logistic_distribution<RealType>(0.5, -0.5), | |
271 | std::domain_error); | |
272 | BOOST_MATH_CHECK_THROW( | |
273 | logistic_distribution<RealType>(0.5, 0), | |
274 | std::domain_error); | |
275 | #endif | |
276 | ||
277 | logistic_distribution<RealType> dist(0.5, 0.5); | |
278 | // x can't be NaN, p can't be NaN. | |
279 | ||
280 | if (std::numeric_limits<RealType>::has_quiet_NaN) | |
281 | { | |
282 | // No longer allow x to be NaN, then these tests should throw. | |
283 | BOOST_MATH_CHECK_THROW(pdf(dist, +std::numeric_limits<RealType>::quiet_NaN()), std::domain_error); // x = NaN | |
284 | BOOST_MATH_CHECK_THROW(cdf(dist, +std::numeric_limits<RealType>::quiet_NaN()), std::domain_error); // x = NaN | |
285 | BOOST_MATH_CHECK_THROW(cdf(complement(dist, +std::numeric_limits<RealType>::quiet_NaN())), std::domain_error); // x = + infinity | |
286 | BOOST_MATH_CHECK_THROW(quantile(dist, +std::numeric_limits<RealType>::quiet_NaN()), std::domain_error); // p = + infinity | |
287 | BOOST_MATH_CHECK_THROW(quantile(complement(dist, +std::numeric_limits<RealType>::quiet_NaN())), std::domain_error); // p = + infinity | |
288 | } | |
289 | if (std::numeric_limits<RealType>::has_infinity) | |
290 | { | |
291 | // Added test for Trac https://svn.boost.org/trac/boost/ticket/9126#comment:1 | |
292 | logistic_distribution<RealType> dist(0., 0.5); | |
293 | BOOST_CHECK_EQUAL(pdf(dist, +std::numeric_limits<RealType>::infinity()), static_cast<RealType>(0) ); // x = infinity | |
294 | ||
295 | } | |
296 | ||
297 | ||
298 | // p can't be outside (0,1). | |
299 | BOOST_MATH_CHECK_THROW(quantile(dist, static_cast<RealType>(1.1)), std::domain_error); | |
300 | BOOST_MATH_CHECK_THROW(quantile(dist, static_cast<RealType>(-0.1)), std::domain_error); | |
301 | BOOST_MATH_CHECK_THROW(quantile(dist, static_cast<RealType>(1)), std::overflow_error); | |
302 | BOOST_MATH_CHECK_THROW(quantile(dist, static_cast<RealType>(0)), std::overflow_error); | |
303 | ||
304 | BOOST_MATH_CHECK_THROW(quantile(complement(dist, static_cast<RealType>(1.1))), std::domain_error); | |
305 | BOOST_MATH_CHECK_THROW(quantile(complement(dist, static_cast<RealType>(-0.1))), std::domain_error); | |
306 | BOOST_MATH_CHECK_THROW(quantile(complement(dist, static_cast<RealType>(1))), std::overflow_error); | |
307 | BOOST_MATH_CHECK_THROW(quantile(complement(dist, static_cast<RealType>(0))), std::overflow_error); | |
308 | ||
309 | // Tests for mean,mode,median,variance,skewness,kurtosis. | |
310 | //mean | |
311 | BOOST_CHECK_CLOSE( | |
312 | ::boost::math::mean( | |
313 | logistic_distribution<RealType>(2,1) | |
314 | ),//x | |
315 | static_cast<RealType>(2), // probability | |
316 | tolerance); // % | |
317 | //median | |
318 | BOOST_CHECK_CLOSE( | |
319 | ::boost::math::median( | |
320 | logistic_distribution<RealType>(2,1) | |
321 | ),//x | |
322 | static_cast<RealType>(2), // probability | |
323 | tolerance); | |
324 | //mode | |
325 | BOOST_CHECK_CLOSE( | |
326 | ::boost::math::mode( | |
327 | logistic_distribution<RealType>(2,1) | |
328 | ),//x | |
329 | static_cast<RealType>(2), // probability | |
330 | tolerance); | |
331 | //variance | |
332 | BOOST_CHECK_CLOSE( | |
333 | ::boost::math::variance( | |
334 | logistic_distribution<RealType>(2,1) | |
335 | ),//x | |
336 | static_cast<RealType>(3.28986813369645287294483033329205L), // probability | |
337 | tolerance); | |
338 | //skewness | |
339 | BOOST_CHECK_CLOSE( | |
340 | ::boost::math::skewness( | |
341 | logistic_distribution<RealType>(2,1) | |
342 | ),//x | |
343 | static_cast<RealType>(0), // probability | |
344 | tolerance); | |
345 | BOOST_CHECK_CLOSE( | |
346 | ::boost::math::kurtosis_excess( | |
347 | logistic_distribution<RealType>(2,1) | |
348 | ),//x | |
349 | static_cast<RealType>(1.2L), // probability | |
350 | tolerance); | |
351 | ||
352 | } // template <class RealType>void test_spots(RealType) | |
353 | ||
354 | ||
355 | BOOST_AUTO_TEST_CASE( test_main ) | |
356 | { | |
357 | // Check that can generate logistic distribution using the two convenience methods: | |
358 | boost::math::logistic mycexp1(1.); // Using typedef | |
359 | logistic_distribution<> myexp2(1.); // Using default RealType double. | |
360 | ||
361 | // Basic sanity-check spot values. | |
362 | // (Parameter value, arbitrarily zero, only communicates the floating point type). | |
363 | test_spots(0.0F); // Test float. OK at decdigits = 0 tolerance = 0.0001 % | |
364 | test_spots(0.0); // Test double. OK at decdigits 7, tolerance = 1e07 % | |
365 | #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS | |
366 | test_spots(0.0L); // Test long double. | |
367 | #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) | |
368 | test_spots(boost::math::concepts::real_concept(0.)); // Test real concept. | |
369 | #endif | |
370 | #else | |
371 | std::cout << "<note>The long double tests have been disabled on this platform " | |
372 | "either because the long double overloads of the usual math functions are " | |
373 | "not available at all, or because they are too inaccurate for these tests " | |
374 | "to pass.</note>" << std::endl; | |
375 | #endif | |
376 | ||
377 | } // BOOST_AUTO_TEST_CASE( test_main ) | |
378 |