1 // Copyright Paul Bristow 2007.
2 // Copyright John Maddock 2006.
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)
14 # pragma warning(disable: 4127) // conditional expression is constant.
15 # pragma warning(disable: 4100) // unreferenced formal parameter.
18 #include <boost/math/concepts/real_concept.hpp> // for real_concept
19 #define BOOST_TEST_MAIN
20 #include <boost/test/unit_test.hpp> // Boost.Test
21 #include <boost/test/floating_point_comparison.hpp>
23 #include <boost/math/distributions/uniform.hpp>
24 using boost::math::uniform_distribution;
25 #include <boost/math/tools/test.hpp>
26 #include "test_out_of_range.hpp"
32 using std::setprecision;
34 using std::numeric_limits;
36 template <class RealType>
37 void check_uniform(RealType lower, RealType upper, RealType x, RealType p, RealType q, RealType tol)
39 BOOST_CHECK_CLOSE_FRACTION(
41 uniform_distribution<RealType>(lower, upper), // distribution.
42 x), // random variable.
45 BOOST_CHECK_CLOSE_FRACTION(
48 uniform_distribution<RealType>(lower, upper), // distribution.
49 x)), // random variable.
50 q, // probability complement.
52 BOOST_CHECK_CLOSE_FRACTION(
53 ::boost::math::quantile(
54 uniform_distribution<RealType>(lower, upper), // distribution.
56 x, // random variable.
58 BOOST_CHECK_CLOSE_FRACTION(
59 ::boost::math::quantile(
61 uniform_distribution<RealType>(lower, upper), // distribution.
62 q)), // probability complement.
63 x, // random variable.
65 } // void check_uniform
67 template <class RealType>
68 void test_spots(RealType)
70 // Basic sanity checks
72 // These test values were generated for the normal distribution
73 // using the online calculator at
74 // http://espse.ed.psu.edu/edpsych/faculty/rhale/hale/507Mat/statlets/free/pdist.htm
76 // Tolerance is just over 5 decimal digits expressed as a fraction:
77 // that's the limit of the test data.
78 RealType tolerance = 2e-5f;
79 cout << "Tolerance for type " << typeid(RealType).name() << " is " << tolerance << "." << endl;
85 BOOST_CHECK_CLOSE_FRACTION( // x == upper
86 pdf(uniform_distribution<RealType>(0, 1), static_cast<RealType>(0)),
87 static_cast<RealType>(1),
89 BOOST_CHECK_CLOSE_FRACTION( // x == lower
90 pdf(uniform_distribution<RealType>(0, 1), static_cast<RealType>(1)),
91 static_cast<RealType>(1),
93 BOOST_CHECK_CLOSE_FRACTION( // x > upper
94 pdf(uniform_distribution<RealType>(0, 1), static_cast<RealType>(-1)),
95 static_cast<RealType>(0),
97 BOOST_CHECK_CLOSE_FRACTION( // x < lower
98 pdf(uniform_distribution<RealType>(0, 1), static_cast<RealType>(2)),
99 static_cast<RealType>(0),
102 if(std::numeric_limits<RealType>::has_infinity)
103 { // BOOST_CHECK tests for infinity using std::numeric_limits<>::infinity()
104 // Note that infinity is not implemented for real_concept, so these tests
105 // are only done for types, like built-in float, double.. that have infinity.
106 // Note that these assume that BOOST_MATH_OVERFLOW_ERROR_POLICY is NOT throw_on_error.
107 // #define BOOST_MATH_OVERFLOW_ERROR_POLICY == throw_on_error would give a throw here.
108 // #define BOOST_MATH_DOMAIN_ERROR_POLICY == throw_on_error IS defined, so the throw path
109 // of error handling is tested below with BOOST_CHECK_THROW tests.
111 BOOST_CHECK_THROW( // x == infinity should NOT be OK.
112 pdf(uniform_distribution<RealType>(0, 1), static_cast<RealType>(std::numeric_limits<RealType>::infinity())),
115 BOOST_CHECK_THROW( // x == minus infinity should be OK too.
116 pdf(uniform_distribution<RealType>(0, 1), static_cast<RealType>(-std::numeric_limits<RealType>::infinity())),
119 if(std::numeric_limits<RealType>::has_quiet_NaN)
120 { // BOOST_CHECK tests for NaN using std::numeric_limits<>::has_quiet_NaN() - should throw.
122 pdf(uniform_distribution<RealType>(0, 1), static_cast<RealType>(std::numeric_limits<RealType>::quiet_NaN())),
125 pdf(uniform_distribution<RealType>(0, 1), static_cast<RealType>(-std::numeric_limits<RealType>::quiet_NaN())),
127 } // test for x = NaN using std::numeric_limits<>::quiet_NaN()
130 BOOST_CHECK_EQUAL( // x < lower
131 cdf(uniform_distribution<RealType>(0, 1), static_cast<RealType>(-1)),
132 static_cast<RealType>(0) );
133 BOOST_CHECK_CLOSE_FRACTION(
134 cdf(uniform_distribution<RealType>(0, 1), static_cast<RealType>(0)),
135 static_cast<RealType>(0),
137 BOOST_CHECK_CLOSE_FRACTION(
138 cdf(uniform_distribution<RealType>(0, 1), static_cast<RealType>(0.5)),
139 static_cast<RealType>(0.5),
141 BOOST_CHECK_CLOSE_FRACTION(
142 cdf(uniform_distribution<RealType>(0, 1), static_cast<RealType>(0.1)),
143 static_cast<RealType>(0.1),
145 BOOST_CHECK_CLOSE_FRACTION(
146 cdf(uniform_distribution<RealType>(0, 1), static_cast<RealType>(0.9)),
147 static_cast<RealType>(0.9),
149 BOOST_CHECK_EQUAL( // x > upper
150 cdf(uniform_distribution<RealType>(0, 1), static_cast<RealType>(2)),
151 static_cast<RealType>(1));
154 BOOST_CHECK_EQUAL( // x < lower
155 cdf(complement(uniform_distribution<RealType>(0, 1), static_cast<RealType>(0))),
156 static_cast<RealType>(1));
157 BOOST_CHECK_EQUAL( // x == 0
158 cdf(complement(uniform_distribution<RealType>(0, 1), static_cast<RealType>(0))),
159 static_cast<RealType>(1));
160 BOOST_CHECK_CLOSE_FRACTION( // x = 0.1
161 cdf(complement(uniform_distribution<RealType>(0, 1), static_cast<RealType>(0.1))),
162 static_cast<RealType>(0.9),
164 BOOST_CHECK_CLOSE_FRACTION( // x = 0.5
165 cdf(complement(uniform_distribution<RealType>(0, 1), static_cast<RealType>(0.5))),
166 static_cast<RealType>(0.5),
168 BOOST_CHECK_EQUAL( // x == 1
169 cdf(complement(uniform_distribution<RealType>(0, 1), static_cast<RealType>(1))),
170 static_cast<RealType>(0));
171 BOOST_CHECK_EQUAL( // x > upper
172 cdf(complement(uniform_distribution<RealType>(0, 1), static_cast<RealType>(2))),
173 static_cast<RealType>(0));
177 BOOST_CHECK_CLOSE_FRACTION(
178 quantile(uniform_distribution<RealType>(0, 1), static_cast<RealType>(0.9)),
179 static_cast<RealType>(0.9),
181 BOOST_CHECK_CLOSE_FRACTION(
182 quantile(uniform_distribution<RealType>(0, 1), static_cast<RealType>(0.1)),
183 static_cast<RealType>(0.1),
185 BOOST_CHECK_CLOSE_FRACTION(
186 quantile(uniform_distribution<RealType>(0, 1), static_cast<RealType>(0.5)),
187 static_cast<RealType>(0.5),
189 BOOST_CHECK_CLOSE_FRACTION(
190 quantile(uniform_distribution<RealType>(0, 1), static_cast<RealType>(0)),
191 static_cast<RealType>(0),
193 BOOST_CHECK_CLOSE_FRACTION(
194 quantile(uniform_distribution<RealType>(0, 1), static_cast<RealType>(1)),
195 static_cast<RealType>(1),
198 // quantile complement
200 BOOST_CHECK_CLOSE_FRACTION(
201 quantile(complement(uniform_distribution<RealType>(0, 1), static_cast<RealType>(0.1))),
202 static_cast<RealType>(0.9),
204 BOOST_CHECK_CLOSE_FRACTION(
205 quantile(complement(uniform_distribution<RealType>(0, 1), static_cast<RealType>(0.9))),
206 static_cast<RealType>(0.1),
208 BOOST_CHECK_CLOSE_FRACTION(
209 quantile(complement(uniform_distribution<RealType>(0, 1), static_cast<RealType>(0.5))),
210 static_cast<RealType>(0.5),
212 BOOST_CHECK_CLOSE_FRACTION(
213 quantile(complement(uniform_distribution<RealType>(0, 1), static_cast<RealType>(0))),
214 static_cast<RealType>(1),
216 BOOST_CHECK_CLOSE_FRACTION(
217 quantile(complement(uniform_distribution<RealType>(0, 1), static_cast<RealType>(1))),
218 static_cast<RealType>(1),
221 // Some tests using a different location & scale, neight zero or unity.
222 BOOST_CHECK_CLOSE_FRACTION( // x == mid
223 pdf(uniform_distribution<RealType>(-1, 2), static_cast<RealType>(1)),
224 static_cast<RealType>(0.3333333333333333333333333333333333333333333333333333),
227 BOOST_CHECK_CLOSE_FRACTION( // x == upper
228 pdf(uniform_distribution<RealType>(-1, 2), static_cast<RealType>(+2)),
229 static_cast<RealType>(0.3333333333333333333333333333333333333333333333333333), // 1 / (2 - -1) = 1/3
232 BOOST_CHECK_CLOSE_FRACTION( // x == lower
233 cdf(uniform_distribution<RealType>(-1, 2), static_cast<RealType>(-1)),
234 static_cast<RealType>(0),
236 BOOST_CHECK_CLOSE_FRACTION( // x == upper
237 cdf(uniform_distribution<RealType>(-1, 2), static_cast<RealType>(0)),
238 static_cast<RealType>(0.3333333333333333333333333333333333333333333333333333),
241 BOOST_CHECK_CLOSE_FRACTION( // x == upper
242 cdf(uniform_distribution<RealType>(-1, 2), static_cast<RealType>(1)),
243 static_cast<RealType>(0.6666666666666666666666666666666666666666666666666667),
246 BOOST_CHECK_CLOSE_FRACTION( // x == lower
247 cdf(uniform_distribution<RealType>(-1, 2), static_cast<RealType>(2)),
248 static_cast<RealType>(1),
251 BOOST_CHECK_CLOSE_FRACTION( // x == upper
252 quantile(uniform_distribution<RealType>(-1, 2), static_cast<RealType>(0.6666666666666666666666666666666666666666666666666667)),
253 static_cast<RealType>(1),
257 static_cast<RealType>(0), // lower
258 static_cast<RealType>(1), // upper
259 static_cast<RealType>(0.5), // x
260 static_cast<RealType>(0.5), // p
261 static_cast<RealType>(1 - 0.5), // q
264 // Some Not-standard uniform tests.
266 static_cast<RealType>(-1), // lower
267 static_cast<RealType>(1), // upper
268 static_cast<RealType>(0), // x
269 static_cast<RealType>(0.5), // p
270 static_cast<RealType>(1 - 0.5), // q = 1 - p
274 static_cast<RealType>(1), // lower
275 static_cast<RealType>(3), // upper
276 static_cast<RealType>(2), // x
277 static_cast<RealType>(0.5), // p
278 static_cast<RealType>(1 - 0.5), // q = 1 - p
282 static_cast<RealType>(-1), // lower
283 static_cast<RealType>(2), // upper
284 static_cast<RealType>(1), // x
285 static_cast<RealType>(0.66666666666666666666666666666666666666666667), // p
286 static_cast<RealType>(0.33333333333333333333333333333333333333333333), // q = 1 - p
288 tolerance = (std::max)(
289 boost::math::tools::epsilon<RealType>(),
290 static_cast<RealType>(boost::math::tools::epsilon<double>())) * 5; // 5 eps as a fraction.
291 cout << "Tolerance (as fraction) for type " << typeid(RealType).name() << " is " << tolerance << "." << endl;
292 uniform_distribution<RealType> distu01(0, 1);
293 RealType x = static_cast<RealType>(0.5);
294 using namespace std; // ADL of std names.
296 BOOST_CHECK_CLOSE_FRACTION(
297 mean(distu01), static_cast<RealType>(0.5), tolerance);
299 BOOST_CHECK_CLOSE_FRACTION(
300 variance(distu01), static_cast<RealType>(0.0833333333333333333333333333333333333333333), tolerance);
302 BOOST_CHECK_CLOSE_FRACTION(
303 standard_deviation(distu01), sqrt(variance(distu01)), tolerance);
305 BOOST_CHECK_CLOSE_FRACTION(
306 hazard(distu01, x), pdf(distu01, x) / cdf(complement(distu01, x)), tolerance);
307 // cumulative hazard:
308 BOOST_CHECK_CLOSE_FRACTION(
309 chf(distu01, x), -log(cdf(complement(distu01, x))), tolerance);
310 // coefficient_of_variation:
311 BOOST_CHECK_CLOSE_FRACTION(
312 coefficient_of_variation(distu01), standard_deviation(distu01) / mean(distu01), tolerance);
314 BOOST_CHECK_CLOSE_FRACTION(
315 mode(distu01), static_cast<RealType>(0), tolerance);
316 BOOST_CHECK_CLOSE_FRACTION(
317 median(distu01), static_cast<RealType>(0.5), tolerance);
320 skewness(distu01), static_cast<RealType>(0));
322 BOOST_CHECK_CLOSE_FRACTION(
323 kurtosis(distu01), kurtosis_excess(distu01) + static_cast<RealType>(3), tolerance);
325 BOOST_CHECK_CLOSE_FRACTION(
326 kurtosis_excess(distu01), static_cast<RealType>(-1.2), tolerance);
328 if(std::numeric_limits<RealType>::has_infinity)
329 { // BOOST_CHECK tests for infinity using std::numeric_limits<>::infinity()
330 // Note that infinity is not implemented for real_concept, so these tests
331 // are only done for types, like built-in float, double, long double, that have infinity.
332 // Note that these assume that BOOST_MATH_OVERFLOW_ERROR_POLICY is NOT throw_on_error.
333 // #define BOOST_MATH_OVERFLOW_ERROR_POLICY == throw_on_error would give a throw here.
334 // #define BOOST_MATH_DOMAIN_ERROR_POLICY == throw_on_error IS defined, so the throw path
335 // of error handling is tested below with BOOST_CHECK_THROW tests.
337 BOOST_CHECK_THROW(pdf(distu01, std::numeric_limits<RealType>::infinity()), std::domain_error);
338 BOOST_CHECK_THROW(pdf(distu01, -std::numeric_limits<RealType>::infinity()), std::domain_error);
339 } // test for infinity using std::numeric_limits<>::infinity()
341 { // real_concept case, does has_infinfity == false, so can't check it throws.
342 // cout << std::numeric_limits<RealType>::infinity() << ' '
343 // << (boost::math::fpclassify)(std::numeric_limits<RealType>::infinity()) << endl;
344 // value of std::numeric_limits<RealType>::infinity() is zero, so FPclassify is zero,
345 // so (boost::math::isfinite)(std::numeric_limits<RealType>::infinity()) does not detect infinity.
346 // so these tests would never throw.
347 //BOOST_CHECK_THROW(pdf(distu01, std::numeric_limits<RealType>::infinity()), std::domain_error);
348 //BOOST_CHECK_THROW(pdf(distu01, std::numeric_limits<RealType>::quiet_NaN()), std::domain_error);
349 // BOOST_CHECK_THROW(pdf(distu01, boost::math::tools::max_value<RealType>() * 2), std::domain_error); // Doesn't throw.
350 BOOST_CHECK_EQUAL(pdf(distu01, boost::math::tools::max_value<RealType>()), 0);
353 BOOST_CHECK(pdf(distu01, 0) == 1);
354 BOOST_CHECK(cdf(distu01, 0) == 0);
355 BOOST_CHECK(pdf(distu01, 1) == 1);
356 BOOST_CHECK(cdf(distu01, 1) == 1);
357 BOOST_CHECK(cdf(complement(distu01, 0)) == 1);
358 BOOST_CHECK(cdf(complement(distu01, 1)) == 0);
359 BOOST_CHECK(quantile(distu01, 0) == 0);
360 BOOST_CHECK(quantile(complement(distu01, 0)) == 1);
361 BOOST_CHECK(quantile(distu01, 1) == 1);
362 BOOST_CHECK(quantile(complement(distu01, 1)) == 1);
365 if(std::numeric_limits<RealType>::has_quiet_NaN)
366 { // BOOST_CHECK tests for constructing with quiet_NaN (not for real_concept, for example - see notes above).
367 BOOST_CHECK_THROW(uniform_distribution<RealType>(0, std::numeric_limits<RealType>::quiet_NaN()), std::domain_error);
368 BOOST_CHECK_THROW(uniform_distribution<RealType>(0, -std::numeric_limits<RealType>::quiet_NaN()), std::domain_error);
370 BOOST_CHECK_THROW(uniform_distribution<RealType>(1, 0), std::domain_error); // lower > upper!
371 BOOST_CHECK_THROW(uniform_distribution<RealType>(1, 1), std::domain_error); // lower == upper!
373 check_out_of_range<uniform_distribution<RealType> >(1, 5);
374 } // template <class RealType>void test_spots(RealType)
376 BOOST_AUTO_TEST_CASE( test_main )
378 // Check that can construct uniform distribution using the two convenience methods:
379 using namespace boost::math;
380 uniform unistd; // Using typedef
381 // == uniform_distribution<double> unistd;
382 BOOST_CHECK_EQUAL(unistd.lower(), 0); // Check defaults.
383 BOOST_CHECK_EQUAL(unistd.upper(), 1);
384 uniform_distribution<> myu01(0, 1); // Using default RealType double.
385 BOOST_CHECK_EQUAL(myu01.lower(), 0); // Check defaults again.
386 BOOST_CHECK_EQUAL(myu01.upper(), 1);
388 // Test on extreme values of random variate x, using just double because it has numeric_limit infinity etc..
389 // No longer allow x to be + or - infinity, then these tests should throw.
390 BOOST_CHECK_THROW(pdf(unistd, +std::numeric_limits<double>::infinity()), std::domain_error); // x = + infinity
391 BOOST_CHECK_THROW(pdf(unistd, -std::numeric_limits<double>::infinity()), std::domain_error); // x = - infinity
392 BOOST_CHECK_THROW(cdf(unistd, +std::numeric_limits<double>::infinity()), std::domain_error); // x = + infinity
393 BOOST_CHECK_THROW(cdf(unistd, -std::numeric_limits<double>::infinity()), std::domain_error); // x = - infinity
395 BOOST_CHECK_EQUAL(pdf(unistd, +(std::numeric_limits<double>::max)()), 0); // x = + max
396 BOOST_CHECK_EQUAL(pdf(unistd, -(std::numeric_limits<double>::min)()), 0); // x = - min
397 BOOST_CHECK_EQUAL(cdf(unistd, +(std::numeric_limits<double>::max)()), 1); // x = + max
398 BOOST_CHECK_EQUAL(cdf(unistd, -(std::numeric_limits<double>::min)()), 0); // x = - min
400 BOOST_CHECK_THROW(uniform_distribution<> zinf(0, +std::numeric_limits<double>::infinity()), std::domain_error); // zero to infinity using default RealType double.
402 uniform_distribution<> zmax(0, +(std::numeric_limits<double>::max)()); // zero to max using default RealType double.
403 BOOST_CHECK_EQUAL(zmax.lower(), 0); // Check defaults again.
404 BOOST_CHECK_EQUAL(zmax.upper(), +(std::numeric_limits<double>::max)());
406 BOOST_CHECK_EQUAL(pdf(zmax, -1), 0); // pdf is 1/(0 - max) = almost zero for all x
407 BOOST_CHECK_EQUAL(pdf(zmax, 0), (std::numeric_limits<double>::min)()/4); // x =
408 BOOST_CHECK_EQUAL(pdf(zmax, 1), (std::numeric_limits<double>::min)()/4); // x =
409 BOOST_CHECK_THROW(pdf(zmax, +std::numeric_limits<double>::infinity()), std::domain_error); // pdf is 1/(0 - infinity) = zero for all x
410 BOOST_CHECK_THROW(pdf(zmax, -std::numeric_limits<double>::infinity()), std::domain_error);
411 BOOST_CHECK_EQUAL(pdf(zmax, +(std::numeric_limits<double>::max)()), (std::numeric_limits<double>::min)()/4); // x =
412 BOOST_CHECK_EQUAL(pdf(zmax, -(std::numeric_limits<double>::max)()), 0); // x =
414 // Ensure NaN throws an exception.
415 BOOST_CHECK_THROW(uniform_distribution<> zNaN(0, std::numeric_limits<double>::quiet_NaN()), std::domain_error);
416 BOOST_CHECK_THROW(pdf(unistd, std::numeric_limits<double>::quiet_NaN()), std::domain_error);
418 // Basic sanity-check spot values.
419 // (Parameter value, arbitrarily zero, only communicates the floating point type).
420 test_spots(0.0F); // Test float. OK at decdigits = 0 tolerance = 0.0001 %
421 test_spots(0.0); // Test double. OK at decdigits 7, tolerance = 1e07 %
422 #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
423 test_spots(0.0L); // Test long double.
424 #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0582))
425 test_spots(boost::math::concepts::real_concept(0.)); // Test real concept.
428 std::cout << "<note>The long double tests have been disabled on this platform "
429 "either because the long double overloads of the usual math functions are "
430 "not available at all, or because they are too inaccurate for these tests "
431 "to pass.</note>" << std::cout;
435 } // BOOST_AUTO_TEST_CASE( test_main )
441 Autorun "i:\boost-06-05-03-1300\libs\math\test\Math_test\debug\test_uniform.exe"
442 Running 1 test case...
443 Tolerance for type float is 2e-005.
444 Tolerance (as fraction) for type float is 5.96046e-007.
445 Tolerance for type double is 2e-005.
446 Tolerance (as fraction) for type double is 1.11022e-015.
447 Tolerance for type long double is 2e-005.
448 Tolerance (as fraction) for type long double is 1.11022e-015.
449 Tolerance for type class boost::math::concepts::real_concept is 2e-005.
450 Tolerance (as fraction) for type class boost::math::concepts::real_concept is 1.11022e-015.
451 *** No errors detected