]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Copyright John Maddock 2012. |
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 | #ifndef BOOST_MATH_TEST_OUT_OF_RANGE_HPP | |
9 | #define BOOST_MATH_TEST_OUT_OF_RANGE_HPP | |
10 | ||
11 | #include <boost/math/special_functions/next.hpp> | |
12 | #include <boost/test/test_tools.hpp> | |
13 | ||
14 | /*` check_out_of_range functions check that bad parameters | |
15 | passed to constructors and functions throw domain_error exceptions. | |
16 | ||
17 | Usage is `check_out_of_range<DistributionType >(list-of-params);` | |
18 | Where list-of-params is a list of *valid* parameters from which the distribution can be constructed | |
19 | - ie the same number of args are passed to the function, | |
20 | as are passed to the distribution constructor. | |
21 | ||
22 | Checks: | |
23 | ||
24 | * Infinity or NaN passed in place of each of the valid params. | |
25 | * Infinity or NaN as a random variable. | |
26 | * Out-of-range random variable passed to pdf and cdf (ie outside of "range(distro)"). | |
27 | * Out-of-range probability passed to quantile function and complement. | |
28 | ||
29 | but does *not* check finite but out-of-range parameters to the constructor | |
30 | because these are specific to each distribution. | |
31 | */ | |
32 | ||
33 | #ifdef BOOST_MSVC | |
34 | #pragma warning(push) | |
35 | #pragma warning(disable:4127) | |
36 | #endif | |
37 | ||
b32b8144 FG |
38 | //! \tparam Distro distribution class name, for example: @c students_t_distribution<RealType>. |
39 | //! \tparam Infinite only true if support includes infinity (default false means do not allow infinity). | |
7c673cae | 40 | template <class Distro> |
b32b8144 FG |
41 | void check_support(const Distro& d, bool Infinite = false) |
42 | { // Checks that support and function calls are within expected limits. | |
7c673cae | 43 | typedef typename Distro::value_type value_type; |
b32b8144 FG |
44 | if (Infinite == false) |
45 | { | |
46 | if ((boost::math::isfinite)(range(d).first) && (range(d).first != -boost::math::tools::max_value<value_type>())) | |
47 | { // If possible, check that a random variable value just less than the bottom of the supported range throws domain errors. | |
48 | value_type m = (range(d).first == 0) ? -boost::math::tools::min_value<value_type>() : boost::math::float_prior(range(d).first); | |
49 | BOOST_ASSERT(m != range(d).first); | |
50 | BOOST_ASSERT(m < range(d).first); | |
51 | BOOST_MATH_CHECK_THROW(pdf(d, m), std::domain_error); | |
52 | BOOST_MATH_CHECK_THROW(cdf(d, m), std::domain_error); | |
53 | BOOST_MATH_CHECK_THROW(cdf(complement(d, m)), std::domain_error); | |
54 | } | |
55 | if ((boost::math::isfinite)(range(d).second) && (range(d).second != boost::math::tools::max_value<value_type>())) | |
56 | { // If possible, check that a random variable value just more than the top of the supported range throws domain errors. | |
57 | value_type m = (range(d).second == 0) ? boost::math::tools::min_value<value_type>() : boost::math::float_next(range(d).second); | |
58 | BOOST_ASSERT(m != range(d).first); | |
59 | BOOST_ASSERT(m > range(d).first); | |
60 | BOOST_MATH_CHECK_THROW(pdf(d, m), std::domain_error); | |
61 | BOOST_MATH_CHECK_THROW(cdf(d, m), std::domain_error); | |
62 | BOOST_MATH_CHECK_THROW(cdf(complement(d, m)), std::domain_error); | |
63 | } | |
64 | if (std::numeric_limits<value_type>::has_infinity) | |
65 | { // Infinity is available, | |
66 | if ((boost::math::isfinite)(range(d).second)) | |
67 | { // and top of range doesn't include infinity, | |
68 | // check that using infinity throws domain errors. | |
7c673cae FG |
69 | BOOST_MATH_CHECK_THROW(pdf(d, std::numeric_limits<value_type>::infinity()), std::domain_error); |
70 | BOOST_MATH_CHECK_THROW(cdf(d, std::numeric_limits<value_type>::infinity()), std::domain_error); | |
71 | BOOST_MATH_CHECK_THROW(cdf(complement(d, std::numeric_limits<value_type>::infinity())), std::domain_error); | |
b32b8144 FG |
72 | } |
73 | if ((boost::math::isfinite)(range(d).first)) | |
74 | { // and bottom of range doesn't include infinity, | |
75 | // check that using infinity throws domain_error exception. | |
7c673cae FG |
76 | BOOST_MATH_CHECK_THROW(pdf(d, -std::numeric_limits<value_type>::infinity()), std::domain_error); |
77 | BOOST_MATH_CHECK_THROW(cdf(d, -std::numeric_limits<value_type>::infinity()), std::domain_error); | |
78 | BOOST_MATH_CHECK_THROW(cdf(complement(d, -std::numeric_limits<value_type>::infinity())), std::domain_error); | |
b32b8144 FG |
79 | } |
80 | // Check that using infinity with quantiles always throws domain_error exception. | |
81 | BOOST_MATH_CHECK_THROW(quantile(d, std::numeric_limits<value_type>::infinity()), std::domain_error); | |
82 | BOOST_MATH_CHECK_THROW(quantile(d, -std::numeric_limits<value_type>::infinity()), std::domain_error); | |
83 | BOOST_MATH_CHECK_THROW(quantile(complement(d, std::numeric_limits<value_type>::infinity())), std::domain_error); | |
84 | BOOST_MATH_CHECK_THROW(quantile(complement(d, -std::numeric_limits<value_type>::infinity())), std::domain_error); | |
85 | } | |
7c673cae FG |
86 | } |
87 | if(std::numeric_limits<value_type>::has_quiet_NaN) | |
88 | { // NaN is available. | |
89 | BOOST_MATH_CHECK_THROW(pdf(d, std::numeric_limits<value_type>::quiet_NaN()), std::domain_error); | |
90 | BOOST_MATH_CHECK_THROW(cdf(d, std::numeric_limits<value_type>::quiet_NaN()), std::domain_error); | |
91 | BOOST_MATH_CHECK_THROW(cdf(complement(d, std::numeric_limits<value_type>::quiet_NaN())), std::domain_error); | |
92 | BOOST_MATH_CHECK_THROW(pdf(d, -std::numeric_limits<value_type>::quiet_NaN()), std::domain_error); | |
93 | BOOST_MATH_CHECK_THROW(cdf(d, -std::numeric_limits<value_type>::quiet_NaN()), std::domain_error); | |
94 | BOOST_MATH_CHECK_THROW(cdf(complement(d, -std::numeric_limits<value_type>::quiet_NaN())), std::domain_error); | |
95 | BOOST_MATH_CHECK_THROW(quantile(d, std::numeric_limits<value_type>::quiet_NaN()), std::domain_error); | |
96 | BOOST_MATH_CHECK_THROW(quantile(d, -std::numeric_limits<value_type>::quiet_NaN()), std::domain_error); | |
97 | BOOST_MATH_CHECK_THROW(quantile(complement(d, std::numeric_limits<value_type>::quiet_NaN())), std::domain_error); | |
98 | BOOST_MATH_CHECK_THROW(quantile(complement(d, -std::numeric_limits<value_type>::quiet_NaN())), std::domain_error); | |
99 | } | |
100 | // Check that using probability outside [0,1] with quantiles always throws domain_error exception. | |
101 | BOOST_MATH_CHECK_THROW(quantile(d, -1), std::domain_error); | |
102 | BOOST_MATH_CHECK_THROW(quantile(d, 2), std::domain_error); | |
103 | BOOST_MATH_CHECK_THROW(quantile(complement(d, -1)), std::domain_error); | |
104 | BOOST_MATH_CHECK_THROW(quantile(complement(d, 2)), std::domain_error); | |
105 | } | |
106 | ||
107 | // Four check_out_of_range versions for distributions with zero to 3 constructor parameters. | |
108 | ||
109 | template <class Distro> | |
110 | void check_out_of_range() | |
111 | { | |
112 | Distro d; | |
113 | check_support(d); | |
114 | } | |
115 | ||
116 | template <class Distro> | |
117 | void check_out_of_range(typename Distro::value_type p1) | |
118 | { | |
119 | typedef typename Distro::value_type value_type; | |
120 | Distro d(p1); | |
121 | check_support(d); | |
122 | if(std::numeric_limits<value_type>::has_infinity) | |
123 | { | |
124 | BOOST_MATH_CHECK_THROW(pdf(Distro(std::numeric_limits<value_type>::infinity()), range(d).first), std::domain_error); | |
125 | // BOOST_MATH_CHECK_THROW(pdf(Distro(std::numeric_limits<value_type>::infinity()), range(d).second), std::domain_error); | |
126 | } | |
127 | if(std::numeric_limits<value_type>::has_quiet_NaN) | |
128 | { | |
129 | BOOST_MATH_CHECK_THROW(pdf(Distro(std::numeric_limits<value_type>::quiet_NaN()), range(d).first), std::domain_error); | |
130 | } | |
131 | } | |
132 | ||
133 | template <class Distro> | |
134 | void check_out_of_range(typename Distro::value_type p1, typename Distro::value_type p2) | |
135 | { | |
136 | typedef typename Distro::value_type value_type; | |
137 | Distro d(p1, p2); | |
138 | check_support(d); | |
139 | if(std::numeric_limits<value_type>::has_infinity) | |
140 | { | |
141 | BOOST_MATH_CHECK_THROW(pdf(Distro(std::numeric_limits<value_type>::infinity(), p2), range(d).first), std::domain_error); | |
142 | BOOST_MATH_CHECK_THROW(pdf(Distro(p1, std::numeric_limits<value_type>::infinity()), range(d).first), std::domain_error); | |
143 | } | |
144 | if(std::numeric_limits<value_type>::has_quiet_NaN) | |
145 | { | |
146 | BOOST_MATH_CHECK_THROW(pdf(Distro(std::numeric_limits<value_type>::quiet_NaN(), p2), range(d).first), std::domain_error); | |
147 | BOOST_MATH_CHECK_THROW(pdf(Distro(p1, std::numeric_limits<value_type>::quiet_NaN()), range(d).first), std::domain_error); | |
148 | } | |
149 | } | |
150 | ||
151 | template <class Distro> | |
152 | void check_out_of_range(typename Distro::value_type p1, typename Distro::value_type p2, typename Distro::value_type p3) | |
153 | { | |
154 | typedef typename Distro::value_type value_type; | |
155 | Distro d(p1, p2, p3); | |
156 | check_support(d); | |
157 | if(std::numeric_limits<value_type>::has_infinity) | |
158 | { | |
159 | BOOST_MATH_CHECK_THROW(pdf(Distro(std::numeric_limits<value_type>::infinity(), p2, p3), range(d).first), std::domain_error); | |
160 | BOOST_MATH_CHECK_THROW(pdf(Distro(p1, std::numeric_limits<value_type>::infinity(), p3), range(d).first), std::domain_error); | |
161 | BOOST_MATH_CHECK_THROW(pdf(Distro(p1, p2, std::numeric_limits<value_type>::infinity()), range(d).first), std::domain_error); | |
162 | } | |
163 | if(std::numeric_limits<value_type>::has_quiet_NaN) | |
164 | { | |
165 | BOOST_MATH_CHECK_THROW(pdf(Distro(std::numeric_limits<value_type>::quiet_NaN(), p2, p3), range(d).first), std::domain_error); | |
166 | BOOST_MATH_CHECK_THROW(pdf(Distro(p1, std::numeric_limits<value_type>::quiet_NaN(), p3), range(d).first), std::domain_error); | |
167 | BOOST_MATH_CHECK_THROW(pdf(Distro(p1, p2, std::numeric_limits<value_type>::quiet_NaN()), range(d).first), std::domain_error); | |
168 | } | |
169 | } | |
170 | ||
171 | #ifdef BOOST_MSVC | |
172 | #pragma warning(pop) | |
173 | #endif | |
174 | ||
175 | #endif // BOOST_MATH_TEST_OUT_OF_RANGE_HPP |