diff --git a/include/boost/math/distributions/arcsine.hpp b/include/boost/math/distributions/arcsine.hpp index 4fe3c7d751..cd3bbaaa9d 100644 --- a/include/boost/math/distributions/arcsine.hpp +++ b/include/boost/math/distributions/arcsine.hpp @@ -229,11 +229,11 @@ namespace boost // Special cases: if (p == 0) { - return 0; + return x_min; } if (p == 1) { - return 1; + return x_max; } using boost::math::constants::half_pi; RealType sin2hpip = sin(half_pi() * p); @@ -247,11 +247,11 @@ namespace boost // Special cases: if (q == 1) { - return 0; + return x_min; } if (q == 0) { - return 1; + return x_max; } // Naive RealType p = 1 - q; result = sin(half_pi() * p); loses accuracy, so use a cos alternative instead. //result = cos(half_pi() * q); // for arcsine(0,1) diff --git a/include/boost/math/distributions/exponential.hpp b/include/boost/math/distributions/exponential.hpp index 9d45ac4933..1022e5a8a8 100644 --- a/include/boost/math/distributions/exponential.hpp +++ b/include/boost/math/distributions/exponential.hpp @@ -109,10 +109,15 @@ template BOOST_MATH_GPU_ENABLED inline boost::math::pair support(const exponential_distribution& /*dist*/) { // Range of supported values for random variable x. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - using boost::math::tools::max_value; - using boost::math::tools::min_value; - return boost::math::pair(min_value(), max_value()); - // min_value() to avoid a discontinuity at x = 0. + BOOST_MATH_IF_CONSTEXPR (boost::math::numeric_limits::has_infinity) + { + return boost::math::pair(static_cast(0), boost::math::numeric_limits::infinity()); // - to + infinity. + } + else + { // Can only use max_value. + using boost::math::tools::max_value; + return boost::math::pair(static_cast(0), max_value()); // - to + max. + } } template @@ -128,9 +133,6 @@ BOOST_MATH_GPU_ENABLED inline RealType pdf(const exponential_distribution= tools::max_value()) - return 0; result = exp(-c.param * lambda); return result; @@ -246,9 +245,6 @@ BOOST_MATH_GPU_ENABLED inline RealType logcdf(const complemented2_type= tools::max_value()) - return 0; result = -c.param * lambda; return result; diff --git a/include/boost/math/distributions/fisher_f.hpp b/include/boost/math/distributions/fisher_f.hpp index 56b288d88e..09d89a24aa 100644 --- a/include/boost/math/distributions/fisher_f.hpp +++ b/include/boost/math/distributions/fisher_f.hpp @@ -140,10 +140,10 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const fisher_f_distribution +BOOST_MATH_GPU_ENABLED inline bool check_gamma_x_positive( + const char* function, + RealType const& x, + RealType* result, const Policy& pol) +{ + if((x < 0) || (boost::math::isnan)(x)) + { + *result = policies::raise_domain_error( + function, + "Random variate is %1% but must be >= 0 !", x, pol); + return false; + } + return true; +} + template BOOST_MATH_GPU_ENABLED inline bool check_gamma( const char* function, @@ -112,17 +128,30 @@ gamma_distribution(RealType,RealType)->gamma_distribution BOOST_MATH_GPU_ENABLED inline boost::math::pair range(const gamma_distribution& /* dist */) { // Range of permissible values for random variable x. - using boost::math::tools::max_value; - return boost::math::pair(static_cast(0), max_value()); + BOOST_MATH_IF_CONSTEXPR (boost::math::numeric_limits::has_infinity) + { + return boost::math::pair(static_cast(0), boost::math::numeric_limits::infinity()); // 0 to + infinity. + } + else + { + using boost::math::tools::max_value; + return boost::math::pair(static_cast(0), max_value()); // 0 to + max + } } template BOOST_MATH_GPU_ENABLED inline boost::math::pair support(const gamma_distribution& /* dist */) { // Range of supported values for random variable x. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. - using boost::math::tools::max_value; - using boost::math::tools::min_value; - return boost::math::pair(min_value(), max_value()); + BOOST_MATH_IF_CONSTEXPR (boost::math::numeric_limits::has_infinity) + { + return boost::math::pair(static_cast(0), boost::math::numeric_limits::infinity()); // 0 to + infinity. + } + else + { + using boost::math::tools::max_value; + return boost::math::pair(static_cast(0), max_value()); // 0 to + max + } } template @@ -138,13 +167,18 @@ BOOST_MATH_GPU_ENABLED inline RealType pdf(const gamma_distribution::quiet_NaN(); + return policies::raise_domain_error(function, "Random variate is %1% but must be > 0 !", x, Policy());; } - result = -k*log(theta) + (k-1)*log(x) - lgamma(k) - (x/theta); return result; @@ -189,8 +222,17 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const gamma_distribution::infinity(); + return result; } if(k == 0) { @@ -452,7 +452,7 @@ namespace boost k, &result, Policy())) { - return -boost::math::numeric_limits::infinity(); + return result; } return boost::math::log1p(-p, Policy()) * (k+1); @@ -497,10 +497,6 @@ namespace boost { // p <= pdf(dist, 0) == cdf(dist, 0) return 0; } - if (x == 1) - { - return 0; - } // log(1-x) /log(1-success_fraction) -1; but use log1p in case success_fraction is small result = boost::math::log1p(-x, Policy()) / boost::math::log1p(-success_fraction, Policy()) - 1; diff --git a/test/test_arcsine.cpp b/test/test_arcsine.cpp index dc2fba919e..070a94c6a9 100644 --- a/test/test_arcsine.cpp +++ b/test/test_arcsine.cpp @@ -38,6 +38,7 @@ using boost::math::constants::one_div_root_two; #include #include "test_out_of_range.hpp" +#include "test_dist_helpers.hpp" #include using std::cout; @@ -65,21 +66,6 @@ void test_ignore_policy(RealType) RealType nan = std::numeric_limits::quiet_NaN(); using boost::math::policies::policy; - // Types of error whose action can be altered by policies:. - //using boost::math::policies::evaluation_error; - //using boost::math::policies::domain_error; - //using boost::math::policies::overflow_error; - //using boost::math::policies::underflow_error; - //using boost::math::policies::domain_error; - //using boost::math::policies::pole_error; - - //// Actions on error (in enum error_policy_type): - //using boost::math::policies::errno_on_error; - //using boost::math::policies::ignore_error; - //using boost::math::policies::throw_on_error; - //using boost::math::policies::denorm_error; - //using boost::math::policies::pole_error; - //using boost::math::policies::user_error; typedef policy< boost::math::policies::domain_error, @@ -105,39 +91,6 @@ void test_ignore_policy(RealType) //std::cout << "pdf(ignore_error_arcsine(-1, +1), std::numeric_limits::infinity()) = " << pdf(ignore_error_arcsine(-1, +1), std::numeric_limits::infinity()) << std::endl; // Outputs: pdf(ignore_error_arcsine(-1, +1), std::numeric_limits::infinity()) = 1.#QNAN } - // PDF - BOOST_CHECK((boost::math::isnan)(pdf(ignore_error_arcsine(0, 1), std::numeric_limits::infinity()))); // x == infinity - BOOST_CHECK((boost::math::isnan)(pdf(ignore_error_arcsine(-1, 1), std::numeric_limits::infinity()))); // x == infinity - BOOST_CHECK((boost::math::isnan)(pdf(ignore_error_arcsine(0, 1), static_cast (-2)))); // x < xmin - BOOST_CHECK((boost::math::isnan)(pdf(ignore_error_arcsine(-1, 1), static_cast (-2)))); // x < xmin - BOOST_CHECK((boost::math::isnan)(pdf(ignore_error_arcsine(0, 1), static_cast (+2)))); // x > x_max - BOOST_CHECK((boost::math::isnan)(pdf(ignore_error_arcsine(-1, 1), static_cast (+2)))); // x > x_max - - // Logpdf - BOOST_CHECK((boost::math::isnan)(logpdf(ignore_error_arcsine(0, 1), std::numeric_limits::infinity()))); // x == infinity - BOOST_CHECK((boost::math::isnan)(logpdf(ignore_error_arcsine(-1, 1), std::numeric_limits::infinity()))); // x == infinity - BOOST_CHECK((boost::math::isnan)(logpdf(ignore_error_arcsine(0, 1), static_cast (-2)))); // x < xmin - BOOST_CHECK((boost::math::isnan)(logpdf(ignore_error_arcsine(-1, 1), static_cast (-2)))); // x < xmin - BOOST_CHECK((boost::math::isnan)(logpdf(ignore_error_arcsine(0, 1), static_cast (+2)))); // x > x_max - BOOST_CHECK((boost::math::isnan)(logpdf(ignore_error_arcsine(-1, 1), static_cast (+2)))); // x > x_max - - // CDF - BOOST_CHECK((boost::math::isnan)(cdf(ignore_error_arcsine(0, 1), std::numeric_limits::infinity()))); // x == infinity - BOOST_CHECK((boost::math::isnan)(cdf(ignore_error_arcsine(-1, 1), std::numeric_limits::infinity()))); // x == infinity - BOOST_CHECK((boost::math::isnan)(cdf(ignore_error_arcsine(0, 1), static_cast (-2)))); // x < xmin - BOOST_CHECK((boost::math::isnan)(cdf(ignore_error_arcsine(-1, 1), static_cast (-2)))); // x < xmin - BOOST_CHECK((boost::math::isnan)(cdf(ignore_error_arcsine(0, 1), static_cast (+2)))); // x > x_max - BOOST_CHECK((boost::math::isnan)(cdf(ignore_error_arcsine(-1, 1), static_cast (+2)))); // x > x_max - BOOST_CHECK((boost::math::isnan)(cdf(complement(ignore_error_arcsine(0, 1), std::numeric_limits::infinity())))); // x == infinity - BOOST_CHECK((boost::math::isnan)(cdf(complement(ignore_error_arcsine(0, 1), static_cast (-2))))); // x < xmin - - // Quantile - BOOST_CHECK((boost::math::isnan)(quantile(ignore_error_arcsine(0, 1), std::numeric_limits::infinity()))); // p == infinity - BOOST_CHECK((boost::math::isnan)(quantile(ignore_error_arcsine(0, 1), static_cast(-1)))); // p < 0 - BOOST_CHECK((boost::math::isnan)(quantile(ignore_error_arcsine(0, 1), static_cast(2)))); // p > 1 - BOOST_CHECK((boost::math::isnan)(quantile(complement(ignore_error_arcsine(0, 1), std::numeric_limits::infinity())))); // q == infinity - BOOST_CHECK((boost::math::isnan)(quantile(complement(ignore_error_arcsine(0, 1), static_cast(-1))))); // q < 0 - BOOST_CHECK((boost::math::isnan)(quantile(complement(ignore_error_arcsine(0, 1), static_cast(2))))); // q > 1 // Mean BOOST_CHECK((boost::math::isnan)(mean(ignore_error_arcsine(-nan, 0)))); @@ -201,6 +154,9 @@ void test_ignore_policy(RealType) BOOST_CHECK(boost::math::isfinite(mean(ignore_error_arcsine(0, std::numeric_limits::epsilon())))); check_support >(arcsine_distribution(0, 1)); + test_invalid_support >, + arcsine_distribution, + RealType>({0, 1}); } // ordinary floats. } // template void test_ignore_policy(RealType) @@ -363,7 +319,6 @@ void test_spots(RealType) BOOST_CHECK_CLOSE_FRACTION(cdf(complement(arcsine_01, 0.95)), static_cast(0.14356629312870627075094188477505571882161519989741L), 8 * tolerance); // 2 for asin BOOST_CHECK_CLOSE_FRACTION(cdf(complement(arcsine_01, 0.999999)), static_cast(1 - 0.99936338012152907551581622632042615133907872213939L), 1000000 * tolerance); // 10000 for asin, 1000000 for acos. - // Quantile. // Check 1st, 2nd and 3rd quartiles. BOOST_CHECK_CLOSE_FRACTION(quantile(arcsine_01, static_cast(0.25L)), static_cast(0.14644660940672624L), tolerance); @@ -471,10 +426,6 @@ void test_spots(RealType) BOOST_CHECK_CLOSE_FRACTION(quantile(as_m2m1, static_cast(0.85643370687129372924905811522494428117838480010259L)), -static_cast(1.05L), 2 * tolerance); // BOOST_CHECK_CLOSE_FRACTION(quantile(as_m2m1, static_cast(0.5L)), -static_cast(1.5L), 2 * tolerance); // BOOST_CHECK_CLOSE_FRACTION(quantile(as_m2m1, static_cast(0.14356629312870627075094188477505571882161519989741L)), -static_cast(1.95L), 4 * tolerance); // - BOOST_CHECK_EQUAL(quantile(as_m2m1, 1), 1); - BOOST_CHECK_EQUAL(quantile(as_m2m1, 0), 0); - BOOST_CHECK_EQUAL(quantile(complement(as_m2m1, 1)), 0); - BOOST_CHECK_EQUAL(quantile(complement(as_m2m1, 0)), 1); BOOST_CHECK_CLOSE_FRACTION(quantile(complement(as_m2m1, static_cast(0.14356629312870627075094188477505571882161519989741L))), -static_cast(1.05L), 2 * tolerance); // BOOST_CHECK_CLOSE_FRACTION(quantile(as_m2m1, static_cast(0.5L)), -static_cast(1.5L), 2 * tolerance); // @@ -484,134 +435,56 @@ void test_spots(RealType) BOOST_CHECK_THROW(mode(arcsine_distribution(static_cast(0), static_cast(1))), std::domain_error); // mode is undefined, and must throw domain_error! + using boost::math::policies::policy; - BOOST_CHECK_THROW( // For various bad arguments. - pdf( - arcsine_distribution(static_cast(+1), static_cast(-1)), // min_x > max_x - static_cast(1)), std::domain_error); - - BOOST_CHECK_THROW( - pdf( - arcsine_distribution(static_cast(1), static_cast(0)), // bad constructor parameters. - static_cast(1)), std::domain_error); - - BOOST_CHECK_THROW( - pdf( - arcsine_distribution(static_cast(1), static_cast(-1)), // bad constructor parameters. - static_cast(1)), std::domain_error); - - BOOST_CHECK_THROW( - pdf( - arcsine_distribution(static_cast(1), static_cast(1)), // equal constructor parameters. - static_cast(-1)), std::domain_error); - - BOOST_CHECK_THROW( - pdf( - arcsine_distribution(static_cast(0), static_cast(1)), // bad x > 1. - static_cast(999)), std::domain_error); - - BOOST_CHECK_THROW( // For various bad arguments. - logpdf( - arcsine_distribution(static_cast(+1), static_cast(-1)), // min_x > max_x - static_cast(1)), std::domain_error); - - BOOST_CHECK_THROW( - logpdf( - arcsine_distribution(static_cast(1), static_cast(0)), // bad constructor parameters. - static_cast(1)), std::domain_error); - - BOOST_CHECK_THROW( - logpdf( - arcsine_distribution(static_cast(1), static_cast(-1)), // bad constructor parameters. - static_cast(1)), std::domain_error); - - BOOST_CHECK_THROW( - logpdf( - arcsine_distribution(static_cast(1), static_cast(1)), // equal constructor parameters. - static_cast(-1)), std::domain_error); - - BOOST_CHECK_THROW( - logpdf( - arcsine_distribution(static_cast(0), static_cast(1)), // bad x > 1. - static_cast(999)), std::domain_error); - - // Checks on things that are errors. - - // Construction with 'bad' parameters. - BOOST_CHECK_THROW(arcsine_distribution(+1, -1), std::domain_error); // max < min. - BOOST_CHECK_THROW(arcsine_distribution(+1, 0), std::domain_error); // max < min. - - arcsine_distribution<> dist; - BOOST_CHECK_THROW(pdf(dist, -1), std::domain_error); - BOOST_CHECK_THROW(logpdf(dist, -1), std::domain_error); - BOOST_CHECK_THROW(cdf(dist, -1), std::domain_error); - BOOST_CHECK_THROW(cdf(complement(dist, -1)), std::domain_error); - BOOST_CHECK_THROW(quantile(dist, -1), std::domain_error); - BOOST_CHECK_THROW(quantile(complement(dist, -1)), std::domain_error); - BOOST_CHECK_THROW(quantile(dist, -1), std::domain_error); - BOOST_CHECK_THROW(quantile(complement(dist, -1)), std::domain_error); - - // Various combinations of bad constructor and member function parameters. - BOOST_CHECK_THROW(pdf(boost::math::arcsine_distribution(0, 1), -1), std::domain_error); - BOOST_CHECK_THROW(pdf(boost::math::arcsine_distribution(-1, 1), +2), std::domain_error); - BOOST_CHECK_THROW(logpdf(boost::math::arcsine_distribution(0, 1), -1), std::domain_error); - BOOST_CHECK_THROW(logpdf(boost::math::arcsine_distribution(-1, 1), +2), std::domain_error); - BOOST_CHECK_THROW(quantile(boost::math::arcsine_distribution(1, 1), -1), std::domain_error); - BOOST_CHECK_THROW(quantile(boost::math::arcsine_distribution(1, 1), 2), std::domain_error); - - // No longer allow any parameter to be NaN or inf, so all these tests should throw. - if (std::numeric_limits::has_quiet_NaN) - { + typedef policy< + boost::math::policies::domain_error, + boost::math::policies::overflow_error, + boost::math::policies::underflow_error, + boost::math::policies::denorm_error, + boost::math::policies::pole_error, + boost::math::policies::evaluation_error + > ignore_all_policy; + + std::vector > invalid_params = {{1, 0}, // x_min > x_max + {1, -1}, + {1, 1}}; + test_invalid_parameters >, + arcsine_distribution, + RealType>(invalid_params); + + // Check constructing with NaNs + if (std::numeric_limits::has_quiet_NaN){ // Attempt to construct from non-finite parameters should throw. RealType nan = std::numeric_limits::quiet_NaN(); -#ifndef BOOST_NO_EXCEPTIONS - BOOST_CHECK_THROW(arcsine_distribution w(nan), std::domain_error); - BOOST_CHECK_THROW(arcsine_distribution w(1, nan), std::domain_error); - BOOST_CHECK_THROW(arcsine_distribution w(nan, 1), std::domain_error); -#else - BOOST_CHECK_THROW(arcsine_distribution(nan), std::domain_error); - BOOST_CHECK_THROW(arcsine_distribution(1, nan), std::domain_error); - BOOST_CHECK_THROW(arcsine_distribution(nan, 1), std::domain_error); -#endif - - arcsine_distribution w(RealType(-1), RealType(+1)); - // NaN parameters to member functions should throw. - BOOST_CHECK_THROW(pdf(w, +nan), std::domain_error); // x = NaN - BOOST_CHECK_THROW(logpdf(w, +nan), std::domain_error); // x = NaN - BOOST_CHECK_THROW(cdf(w, +nan), std::domain_error); // x = NaN - BOOST_CHECK_THROW(cdf(complement(w, +nan)), std::domain_error); // x = + nan - BOOST_CHECK_THROW(quantile(w, +nan), std::domain_error); // p = + nan - BOOST_CHECK_THROW(quantile(complement(w, +nan)), std::domain_error); // p = + nan - } // has_quiet_NaN + invalid_params = {{nan}, + {1, nan}, // x_min > x_max + {nan, 1}}; + test_invalid_parameters >, + arcsine_distribution, + RealType>(invalid_params); + } + // Check construcing with Infinity if (std::numeric_limits::has_infinity) { // Attempt to construct from non-finite should throw. RealType inf = std::numeric_limits::infinity(); -#ifndef BOOST_NO_EXCEPTIONS - BOOST_CHECK_THROW(arcsine_distribution w(inf), std::domain_error); - BOOST_CHECK_THROW(arcsine_distribution w(1, inf), std::domain_error); -#else - BOOST_CHECK_THROW(arcsine_distribution(inf), std::domain_error); - BOOST_CHECK_THROW(arcsine_distribution(1, inf), std::domain_error); -#endif - // Infinite parameters to member functions should throw. - arcsine_distribution w(RealType(0), RealType(1)); -#ifndef BOOST_NO_EXCEPTIONS - BOOST_CHECK_THROW(arcsine_distribution w(inf), std::domain_error); - BOOST_CHECK_THROW(arcsine_distribution w(1, inf), std::domain_error); -#else - BOOST_CHECK_THROW(arcsine_distribution(inf), std::domain_error); - BOOST_CHECK_THROW(arcsine_distribution(1, inf), std::domain_error); -#endif - BOOST_CHECK_THROW(pdf(w, +inf), std::domain_error); // x = inf - BOOST_CHECK_THROW(logpdf(w, +inf), std::domain_error); // x = inf - BOOST_CHECK_THROW(cdf(w, +inf), std::domain_error); // x = inf - BOOST_CHECK_THROW(cdf(complement(w, +inf)), std::domain_error); // x = + inf - BOOST_CHECK_THROW(quantile(w, +inf), std::domain_error); // p = + inf - BOOST_CHECK_THROW(quantile(complement(w, +inf)), std::domain_error); // p = + inf + invalid_params = {{inf}, + {1, inf}, // x_min > x_max + {inf, 1}}; + test_invalid_parameters >, + arcsine_distribution, + RealType>(invalid_params); } // has_infinity + // Quantile should return x_min and x_max + arcsine_distribution dist(0, 1); + BOOST_CHECK_EQUAL(quantile(dist, static_cast(1)), static_cast(1)); // p = 1 + BOOST_CHECK_EQUAL(quantile(dist, static_cast(0)), static_cast(0)); // p = 0 + BOOST_CHECK_EQUAL(quantile(complement(dist, static_cast(1))), static_cast(0)); // q = 1 + BOOST_CHECK_EQUAL(quantile(complement(dist, static_cast(0))), static_cast(1)); // q = 0 + // Error handling checks: check_out_of_range >(-1, +1); // (All) valid constructor parameter values. // and range and non-finite. diff --git a/test/test_bernoulli.cpp b/test/test_bernoulli.cpp index 256a897783..5257fa0ee5 100644 --- a/test/test_bernoulli.cpp +++ b/test/test_bernoulli.cpp @@ -35,6 +35,7 @@ using boost::math::bernoulli_distribution; #define BOOST_TEST_MAIN #include // for test_main #include // for BOOST_CHECK_CLOSE_FRACTION, BOOST_CHECK_EQUAL... +#include "test_dist_helpers.hpp" #include using std::cout; @@ -50,6 +51,8 @@ using std::setprecision; #include using std::numeric_limits; +#include + template // Any floating-point type RealType. void test_spots(RealType) { // Parameter only provides the type, float, double... value ignored. @@ -230,63 +233,8 @@ void test_spots(RealType) ); // Checks for 'bad' parameters. - // Construction. - #ifndef BOOST_MATH_NO_EXCEPTIONS - BOOST_MATH_CHECK_THROW(bernoulli_distribution(-1), std::domain_error); // p outside 0 to 1. - BOOST_MATH_CHECK_THROW(bernoulli_distribution(+2), std::domain_error); // p outside 0 to 1. - - // Parameters. - bernoulli_distribution dist(RealType(1)); - BOOST_MATH_CHECK_THROW(pdf(dist, -1), std::domain_error); - BOOST_MATH_CHECK_THROW(cdf(dist, -1), std::domain_error); - BOOST_MATH_CHECK_THROW(cdf(complement(dist, -1)), std::domain_error); - BOOST_MATH_CHECK_THROW(quantile(dist, 2), std::domain_error); - BOOST_MATH_CHECK_THROW(quantile(complement(dist, -1)), std::domain_error); - BOOST_MATH_CHECK_THROW(quantile(dist, -1), std::domain_error); - BOOST_MATH_CHECK_THROW(quantile(complement(dist, -1)), std::domain_error); - - // No longer allow any parameter to be NaN or inf, so all these tests should throw. - if (std::numeric_limits::has_quiet_NaN) - { - // Attempt to construct from non-finite should throw. - RealType nan = std::numeric_limits::quiet_NaN(); -#ifndef BOOST_NO_EXCEPTIONS - BOOST_MATH_CHECK_THROW(bernoulli_distribution b(nan), std::domain_error); -#else - BOOST_MATH_CHECK_THROW(bernoulli_distribution(nan), std::domain_error); -#endif - // Non-finite parameters should throw. - bernoulli_distribution b(RealType(1)); - BOOST_MATH_CHECK_THROW(pdf(b, +nan), std::domain_error); // x = NaN - BOOST_MATH_CHECK_THROW(cdf(b, +nan), std::domain_error); // x = NaN - BOOST_MATH_CHECK_THROW(cdf(complement(b, +nan)), std::domain_error); // x = + nan - BOOST_MATH_CHECK_THROW(quantile(b, +nan), std::domain_error); // p = + nan - BOOST_MATH_CHECK_THROW(quantile(complement(b, +nan)), std::domain_error); // p = + nan - } // has_quiet_NaN - - if (std::numeric_limits::has_infinity) - { - RealType inf = std::numeric_limits::infinity(); -#ifndef BOOST_NO_EXCEPTIONS - BOOST_MATH_CHECK_THROW(bernoulli_distribution w(inf), std::domain_error); -#else - BOOST_MATH_CHECK_THROW(bernoulli_distribution(inf), std::domain_error); -#endif - bernoulli_distribution w(RealType(1)); -#ifndef BOOST_NO_EXCEPTIONS - BOOST_MATH_CHECK_THROW(bernoulli_distribution w(inf), std::domain_error); -#else - BOOST_MATH_CHECK_THROW(bernoulli_distribution(inf), std::domain_error); -#endif - BOOST_MATH_CHECK_THROW(pdf(w, +inf), std::domain_error); // x = inf - BOOST_MATH_CHECK_THROW(cdf(w, +inf), std::domain_error); // x = inf - BOOST_MATH_CHECK_THROW(cdf(complement(w, +inf)), std::domain_error); // x = + inf - BOOST_MATH_CHECK_THROW(quantile(w, +inf), std::domain_error); // p = + inf - BOOST_MATH_CHECK_THROW(quantile(complement(w, +inf)), std::domain_error); // p = + inf - } // has_infinity - #endif - using boost::math::policies::policy; + typedef policy< boost::math::policies::domain_error, boost::math::policies::overflow_error, @@ -294,37 +242,47 @@ void test_spots(RealType) boost::math::policies::denorm_error, boost::math::policies::pole_error, boost::math::policies::evaluation_error - > ignore_all_policy; - - typedef bernoulli_distribution ignore_error_bernoulli; - + > ignore_all_policy; + + std::vector > invalid_params = {{-1}, // x_min > x_max + {2}}; + test_invalid_parameters >, + bernoulli_distribution, + RealType>(invalid_params); + + // Check constructing with NaNs + if (std::numeric_limits::has_quiet_NaN){ + // Attempt to construct from non-finite parameters should throw. + RealType nan = std::numeric_limits::quiet_NaN(); + invalid_params = {{nan}}; + test_invalid_parameters >, + bernoulli_distribution, + RealType>(invalid_params); + } + + // Check construcing with Infinity + if (std::numeric_limits::has_infinity) + { + // Attempt to construct from non-finite should throw. + RealType inf = std::numeric_limits::infinity(); + invalid_params = {{inf}}; + test_invalid_parameters >, + bernoulli_distribution, + RealType>(invalid_params); + } // has_infinity + + bernoulli_distribution fair_dist(0.5); + BOOST_CHECK_EQUAL(quantile(fair_dist, static_cast(1)), static_cast(1)); // p = 1 + BOOST_CHECK_EQUAL(quantile(fair_dist, static_cast(0)), static_cast(0)); // p = 0 + BOOST_CHECK_EQUAL(quantile(complement(fair_dist, static_cast(1))), static_cast(0)); // q = 1 + BOOST_CHECK_EQUAL(quantile(complement(fair_dist, static_cast(0))), static_cast(1)); // q = 0 + if (std::numeric_limits::has_quiet_NaN) - { - // PDF - BOOST_CHECK((boost::math::isnan)(pdf(ignore_error_bernoulli(0.5), std::numeric_limits::infinity()))); // k == infinity - BOOST_CHECK((boost::math::isnan)(pdf(ignore_error_bernoulli(0.5), 2))); // k > 1 - BOOST_CHECK((boost::math::isnan)(pdf(ignore_error_bernoulli(0.5), static_cast(0.5)))); // k != 0, 1 - BOOST_CHECK((boost::math::isnan)(pdf(ignore_error_bernoulli(0.5), static_cast(-0.5)))); // k != 0, 1 - - // CDF - BOOST_CHECK((boost::math::isnan)(cdf(ignore_error_bernoulli(0.5), std::numeric_limits::infinity()))); // k == infinity - BOOST_CHECK((boost::math::isnan)(cdf(ignore_error_bernoulli(0.5), 2))); // k > 1 - BOOST_CHECK((boost::math::isnan)(cdf(ignore_error_bernoulli(0.5), static_cast(0.5)))); // k != 0, 1 - BOOST_CHECK((boost::math::isnan)(cdf(ignore_error_bernoulli(0.5), static_cast(-0.5)))); // k != 0, 1 - BOOST_CHECK((boost::math::isnan)(cdf(complement(ignore_error_bernoulli(0.5), std::numeric_limits::infinity())))); // k == infinity - BOOST_CHECK((boost::math::isnan)(cdf(complement(ignore_error_bernoulli(0.5), 2)))); // k > 1 - BOOST_CHECK((boost::math::isnan)(cdf(complement(ignore_error_bernoulli(0.5), static_cast(0.5))))); // k != 0, 1 - BOOST_CHECK((boost::math::isnan)(cdf(complement(ignore_error_bernoulli(0.5), static_cast(-0.5))))); // k != 0, 1 - - // // Quantile - BOOST_CHECK((boost::math::isnan)(quantile(ignore_error_bernoulli(0.5), std::numeric_limits::infinity()))); // p == infinity - BOOST_CHECK((boost::math::isnan)(quantile(ignore_error_bernoulli(0.5), static_cast(-1)))); // p < 0 - BOOST_CHECK((boost::math::isnan)(quantile(ignore_error_bernoulli(0.5), static_cast(2)))); // p > 1 - BOOST_CHECK((boost::math::isnan)(quantile(complement(ignore_error_bernoulli(0.5), std::numeric_limits::infinity())))); // q == infinity - BOOST_CHECK((boost::math::isnan)(quantile(complement(ignore_error_bernoulli(0.5), static_cast(-1))))); // q < 0 - BOOST_CHECK((boost::math::isnan)(quantile(complement(ignore_error_bernoulli(0.5), static_cast(2))))); // q > 1 - - } // has_quiet_NaN + { + test_invalid_support >, + bernoulli_distribution, + RealType>({0.5}); + } // has_quiet_NaN } // template void test_spots(RealType) BOOST_AUTO_TEST_CASE( test_main ) diff --git a/test/test_beta_dist.cpp b/test/test_beta_dist.cpp index 3983f526ff..8764038a89 100644 --- a/test/test_beta_dist.cpp +++ b/test/test_beta_dist.cpp @@ -54,12 +54,14 @@ using boost::math::beta; #include // for BOOST_CHECK_CLOSE_FRACTION #include "test_out_of_range.hpp" +#include "test_dist_helpers.hpp" #include using std::cout; using std::endl; #include using std::numeric_limits; +#include #if __has_include() # include @@ -494,23 +496,59 @@ void test_spots(RealType) static_cast(1-0.5545844446520295253493059553548880128511L), // Complement of CDF Q = 1 - P tolerance); // Test tolerance. - // + // // Error checks: // Construction with 'bad' parameters. - BOOST_MATH_CHECK_THROW(beta_distribution(1, -1), std::domain_error); - BOOST_MATH_CHECK_THROW(beta_distribution(-1, 1), std::domain_error); - BOOST_MATH_CHECK_THROW(beta_distribution(1, 0), std::domain_error); - BOOST_MATH_CHECK_THROW(beta_distribution(0, 1), std::domain_error); - - beta_distribution<> dist; - BOOST_MATH_CHECK_THROW(pdf(dist, -1), std::domain_error); - BOOST_MATH_CHECK_THROW(cdf(dist, -1), std::domain_error); - BOOST_MATH_CHECK_THROW(cdf(complement(dist, -1)), std::domain_error); - BOOST_MATH_CHECK_THROW(quantile(dist, -1), std::domain_error); - BOOST_MATH_CHECK_THROW(quantile(complement(dist, -1)), std::domain_error); - BOOST_MATH_CHECK_THROW(quantile(dist, -1), std::domain_error); - BOOST_MATH_CHECK_THROW(quantile(complement(dist, -1)), std::domain_error); + using boost::math::policies::policy; + typedef policy< + boost::math::policies::domain_error, + boost::math::policies::overflow_error, + boost::math::policies::underflow_error, + boost::math::policies::denorm_error, + boost::math::policies::pole_error, + boost::math::policies::evaluation_error + > ignore_all_policy; + + std::vector > invalid_params = {{1, -1}, + {-1, 1}, + {1, 0}, + {0, 1}}; + test_invalid_parameters >, + beta_distribution, + RealType>(invalid_params); + + // Check constructing with NaNs + if (std::numeric_limits::has_quiet_NaN){ + // Attempt to construct from non-finite parameters should throw. + RealType nan = std::numeric_limits::quiet_NaN(); + invalid_params = {{nan}, + {1, nan}}; + test_invalid_parameters >, + beta_distribution, + RealType>(invalid_params); + } + + // Check construcing with Infinity + if (std::numeric_limits::has_infinity) + { + // Attempt to construct from non-finite should throw. + RealType inf = std::numeric_limits::infinity(); + invalid_params = {{inf}, + {1, inf}}; + test_invalid_parameters >, + beta_distribution, + RealType>(invalid_params); + } // has_infinity + + if (std::numeric_limits::has_quiet_NaN) + { + test_invalid_support >, + beta_distribution, + RealType>({1, 1}); + } // has_quiet_NaN + + // PDF not defind for alpha < 1, x = 0 and beta < 1, x = 1 BOOST_MATH_CHECK_THROW(pdf(beta_distribution(static_cast(0.5), static_cast(1.5)), static_cast(0)), std::overflow_error); // alpha < 1, x = 0 BOOST_MATH_CHECK_THROW(pdf(beta_distribution(static_cast(1.5), static_cast(0.5)), static_cast(1)), std::overflow_error); // beta < 1, x = 1 @@ -523,85 +561,26 @@ void test_spots(RealType) test_find_alpha_beta(static_cast(1), static_cast(1.5), static_cast(0.5)); // x > 0 test_find_alpha_beta(static_cast(1), static_cast(-0.5), static_cast(0.5)); // x < 0 - // No longer allow any parameter to be NaN or inf, so all these tests should throw. - if (std::numeric_limits::has_quiet_NaN) - { - // Attempt to construct from non-finite should throw. - RealType nan = std::numeric_limits::quiet_NaN(); -#ifndef BOOST_NO_EXCEPTIONS - BOOST_MATH_CHECK_THROW(beta_distribution w(nan), std::domain_error); - BOOST_MATH_CHECK_THROW(beta_distribution w(1, nan), std::domain_error); -#else - BOOST_MATH_CHECK_THROW(beta_distribution(nan), std::domain_error); - BOOST_MATH_CHECK_THROW(beta_distribution(1, nan), std::domain_error); -#endif - - // Non-finite parameters should throw. - beta_distribution w(RealType(1)); - BOOST_MATH_CHECK_THROW(pdf(w, +nan), std::domain_error); // x = NaN - BOOST_MATH_CHECK_THROW(cdf(w, +nan), std::domain_error); // x = NaN - BOOST_MATH_CHECK_THROW(cdf(complement(w, +nan)), std::domain_error); // x = + nan - BOOST_MATH_CHECK_THROW(quantile(w, +nan), std::domain_error); // p = + nan - BOOST_MATH_CHECK_THROW(quantile(complement(w, +nan)), std::domain_error); // p = + nan - } // has_quiet_NaN - if (std::numeric_limits::has_infinity) { // Attempt to construct from non-finite should throw. RealType inf = std::numeric_limits::infinity(); -#ifndef BOOST_NO_EXCEPTIONS - BOOST_MATH_CHECK_THROW(beta_distribution w(inf), std::domain_error); - BOOST_MATH_CHECK_THROW(beta_distribution w(1, inf), std::domain_error); -#else - BOOST_MATH_CHECK_THROW(beta_distribution(inf), std::domain_error); - BOOST_MATH_CHECK_THROW(beta_distribution(1, inf), std::domain_error); -#endif - - // Non-finite parameters should throw. - beta_distribution w(RealType(1)); -#ifndef BOOST_NO_EXCEPTIONS - BOOST_MATH_CHECK_THROW(beta_distribution w(inf), std::domain_error); - BOOST_MATH_CHECK_THROW(beta_distribution w(1, inf), std::domain_error); -#else - BOOST_MATH_CHECK_THROW(beta_distribution(inf), std::domain_error); - BOOST_MATH_CHECK_THROW(beta_distribution(1, inf), std::domain_error); -#endif - BOOST_MATH_CHECK_THROW(pdf(w, +inf), std::domain_error); // x = inf - BOOST_MATH_CHECK_THROW(cdf(w, +inf), std::domain_error); // x = inf - BOOST_MATH_CHECK_THROW(cdf(complement(w, +inf)), std::domain_error); // x = + inf - BOOST_MATH_CHECK_THROW(quantile(w, +inf), std::domain_error); // p = + inf - BOOST_MATH_CHECK_THROW(quantile(complement(w, +inf)), std::domain_error); // p = + inf test_find_alpha_beta(static_cast(1), static_cast(0.5), inf); // p = inf test_find_alpha_beta(inf, static_cast(0.5)); // mean = inf test_find_alpha_beta(static_cast(0.5), inf); // var = inf test_find_alpha_beta(static_cast(1), inf, static_cast(0.5)); // x = inf - // Check isnan policies - using boost::math::policies::policy; - - typedef policy< - boost::math::policies::domain_error, - boost::math::policies::overflow_error, - boost::math::policies::underflow_error, - boost::math::policies::denorm_error, - boost::math::policies::pole_error, - boost::math::policies::evaluation_error - > ignore_all_policy; - typedef beta_distribution ignore_error_beta; BOOST_CHECK((boost::math::isnan)(ignore_error_beta::find_alpha(inf, static_cast(0.5)))); // mean = inf BOOST_CHECK((boost::math::isnan)(ignore_error_beta::find_beta(inf, static_cast(0.5)))); // mean = inf + BOOST_CHECK((boost::math::isnan)(ignore_error_beta::find_alpha(static_cast(0.5), inf))); // var = inf + BOOST_CHECK((boost::math::isnan)(ignore_error_beta::find_beta(static_cast(0.5), inf))); // var = inf BOOST_CHECK((boost::math::isnan)(ignore_error_beta::find_alpha(inf, static_cast(0.5), static_cast(0.5)))); // beta = inf BOOST_CHECK((boost::math::isnan)(ignore_error_beta::find_beta(inf, static_cast(0.5), static_cast(0.5)))); // alpha = inf BOOST_CHECK((boost::math::isnan)(mode(ignore_error_beta(static_cast(2), static_cast(1))))); // beta = 1 BOOST_CHECK((boost::math::isnan)(mode(ignore_error_beta(static_cast(1), static_cast(2))))); // alpha = 1 - BOOST_CHECK((boost::math::isnan)(pdf(ignore_error_beta(static_cast(1), static_cast(1)), 2))); // x > 1 - BOOST_CHECK((boost::math::isnan)(cdf(ignore_error_beta(static_cast(1), static_cast(1)), 2))); // x > 1 - BOOST_CHECK((boost::math::isnan)(cdf(complement(ignore_error_beta(static_cast(1), static_cast(1)), 2)))); // x > 1 - BOOST_CHECK((boost::math::isnan)(quantile(ignore_error_beta(static_cast(1), static_cast(1)), 2))); // p > 1 - BOOST_CHECK((boost::math::isnan)(quantile(complement(ignore_error_beta(static_cast(1), static_cast(1)), 2)))); // p > 1 } // has_infinity // Error handling checks: @@ -614,14 +593,6 @@ void test_spots(RealType) check_out_of_range >(1, 1); // (All) valid constructor parameter values. #endif // and range and non-finite. - - // Not needed?????? - BOOST_MATH_CHECK_THROW(pdf(boost::math::beta_distribution(0, 1), 0), std::domain_error); - BOOST_MATH_CHECK_THROW(pdf(boost::math::beta_distribution(-1, 1), 0), std::domain_error); - BOOST_MATH_CHECK_THROW(quantile(boost::math::beta_distribution(1, 1), -1), std::domain_error); - BOOST_MATH_CHECK_THROW(quantile(boost::math::beta_distribution(1, 1), 2), std::domain_error); - - } // template void test_spots(RealType) BOOST_AUTO_TEST_CASE( test_main ) diff --git a/test/test_binomial.cpp b/test/test_binomial.cpp index b76c8e03e4..9ec3934f76 100644 --- a/test/test_binomial.cpp +++ b/test/test_binomial.cpp @@ -39,12 +39,14 @@ using boost::math::binomial_distribution; #include "table_type.hpp" #include "test_out_of_range.hpp" +#include "test_dist_helpers.hpp" #include using std::cout; using std::endl; #include using std::numeric_limits; +#include template void test_spot( @@ -521,69 +523,12 @@ void test_spots(RealType T) binomial_distribution(static_cast(0), static_cast(0.25)), static_cast(0)), static_cast(1) ); - BOOST_CHECK_THROW( - pdf( - binomial_distribution(static_cast(-1), static_cast(0.25)), - static_cast(0)), std::domain_error - ); - BOOST_CHECK_THROW( - pdf( - binomial_distribution(static_cast(8), static_cast(-0.25)), - static_cast(0)), std::domain_error - ); - BOOST_CHECK_THROW( - pdf( - binomial_distribution(static_cast(8), static_cast(1.25)), - static_cast(0)), std::domain_error - ); - BOOST_CHECK_THROW( - pdf( - binomial_distribution(static_cast(8), static_cast(0.25)), - static_cast(-1)), std::domain_error - ); - BOOST_CHECK_THROW( - pdf( - binomial_distribution(static_cast(8), static_cast(0.25)), - static_cast(9)), std::domain_error - ); - BOOST_CHECK_THROW( - cdf( - binomial_distribution(static_cast(8), static_cast(0.25)), - static_cast(-1)), std::domain_error - ); - BOOST_CHECK_THROW( - cdf( - binomial_distribution(static_cast(8), static_cast(0.25)), - static_cast(9)), std::domain_error - ); - BOOST_CHECK_THROW( - cdf( - binomial_distribution(static_cast(8), static_cast(-0.25)), - static_cast(0)), std::domain_error - ); - BOOST_CHECK_THROW( - cdf( - binomial_distribution(static_cast(8), static_cast(1.25)), - static_cast(0)), std::domain_error - ); - BOOST_CHECK_THROW( - quantile( - binomial_distribution(static_cast(8), static_cast(-0.25)), - static_cast(0)), std::domain_error - ); - BOOST_CHECK_THROW( - quantile( - binomial_distribution(static_cast(8), static_cast(1.25)), - static_cast(0)), std::domain_error - ); - BOOST_CHECK_EQUAL( quantile( binomial_distribution(static_cast(16), static_cast(0.25)), static_cast(0.01)), // Less than cdf == pdf(binomial_distribution(16, 0.25), 0) static_cast(0) // so expect zero as best approximation. ); - BOOST_CHECK_EQUAL( cdf( binomial_distribution(static_cast(8), static_cast(0.25)), @@ -610,6 +555,56 @@ void test_spots(RealType T) static_cast(7))), static_cast(1) ); + using boost::math::policies::policy; + + typedef policy< + boost::math::policies::domain_error, + boost::math::policies::overflow_error, + boost::math::policies::underflow_error, + boost::math::policies::denorm_error, + boost::math::policies::pole_error, + boost::math::policies::evaluation_error + > ignore_all_policy; + + std::vector > invalid_params = {{-1, 0.25}, + {8, -0.25}, + {8, 1.25}}; + test_invalid_parameters >, + binomial_distribution, + RealType>(invalid_params); + + // Check constructing with NaNs + if (std::numeric_limits::has_quiet_NaN){ + // Attempt to construct from non-finite parameters should throw. + RealType nan = std::numeric_limits::quiet_NaN(); + invalid_params = {{nan}, + {8, nan}, + {nan, 8}}; + test_invalid_parameters >, + binomial_distribution, + RealType>(invalid_params); + } + + // Check construcing with Infinity + if (std::numeric_limits::has_infinity) + { + // Attempt to construct from non-finite should throw. + RealType inf = std::numeric_limits::infinity(); + invalid_params = {{inf}, + {1, inf}, + {inf, 1}}; + test_invalid_parameters >, + binomial_distribution, + RealType>(invalid_params); + } // has_infinity + + if (std::numeric_limits::has_quiet_NaN) + { + test_invalid_support >, + binomial_distribution, + RealType>({10, 0.5}); + } // has_quiet_NaN + // Check Error handling and edge cases BOOST_CHECK_EQUAL(binomial_distribution::find_lower_bound_on_p(static_cast(5), static_cast(0), @@ -670,39 +665,21 @@ void test_spots(RealType T) if (std::numeric_limits::has_infinity) { - // Check isnan policies - using boost::math::policies::policy; - - typedef policy< - boost::math::policies::domain_error, - boost::math::policies::overflow_error, - boost::math::policies::underflow_error, - boost::math::policies::denorm_error, - boost::math::policies::pole_error, - boost::math::policies::evaluation_error - > ignore_all_policy; - - typedef binomial_distribution ignore_error_binomial; - - BOOST_CHECK((boost::math::isnan)(ignore_error_binomial::find_lower_bound_on_p(static_cast(5), - static_cast(2), - static_cast(-0.5)))); // probability < 0 - BOOST_CHECK((boost::math::isnan)(ignore_error_binomial::find_upper_bound_on_p(static_cast(5), - static_cast(2), - static_cast(-0.5)))); // probability < 0 - BOOST_CHECK((boost::math::isnan)(ignore_error_binomial::find_minimum_number_of_trials(static_cast(10), - static_cast(-1), - static_cast(0.05)))); // probability < 0 - BOOST_CHECK((boost::math::isnan)(ignore_error_binomial::find_maximum_number_of_trials(static_cast(10), - static_cast(-1), - static_cast(0.05)))); // probability < 0 - - BOOST_CHECK((boost::math::isnan)(pdf(ignore_error_binomial(static_cast(-8), static_cast(0.25)), static_cast(8)))); - BOOST_CHECK((boost::math::isnan)(pdf(ignore_error_binomial(static_cast(8), static_cast(-0.25)), static_cast(8)))); - BOOST_CHECK((boost::math::isnan)(pdf(ignore_error_binomial(static_cast(8), static_cast(0.25)), static_cast(9)))); - BOOST_CHECK((boost::math::isnan)(cdf(ignore_error_binomial(static_cast(8), static_cast(0.25)), static_cast(9)))); - BOOST_CHECK((boost::math::isnan)(cdf(complement(ignore_error_binomial(static_cast(8), static_cast(0.25)), static_cast(9))))); - BOOST_CHECK((boost::math::isnan)(quantile(ignore_error_binomial(static_cast(8), static_cast(0.25)), static_cast(-1)))); + // Check isnan policies + typedef binomial_distribution ignore_error_binomial; + + BOOST_CHECK((boost::math::isnan)(ignore_error_binomial::find_lower_bound_on_p(static_cast(5), + static_cast(2), + static_cast(-0.5)))); // probability < 0 + BOOST_CHECK((boost::math::isnan)(ignore_error_binomial::find_upper_bound_on_p(static_cast(5), + static_cast(2), + static_cast(-0.5)))); // probability < 0 + BOOST_CHECK((boost::math::isnan)(ignore_error_binomial::find_minimum_number_of_trials(static_cast(10), + static_cast(-1), + static_cast(0.05)))); // probability < 0 + BOOST_CHECK((boost::math::isnan)(ignore_error_binomial::find_maximum_number_of_trials(static_cast(10), + static_cast(-1), + static_cast(0.05)))); // probability < 0 } #endif diff --git a/test/test_cauchy.cpp b/test/test_cauchy.cpp index 4e8286c60e..cb1ed131c1 100644 --- a/test/test_cauchy.cpp +++ b/test/test_cauchy.cpp @@ -33,10 +33,18 @@ #include #include "test_out_of_range.hpp" +#include "test_dist_helpers.hpp" + +#if defined(BOOST_CHECK_THROW) && defined(BOOST_MATH_NO_EXCEPTIONS) +# undef BOOST_CHECK_THROW +# define BOOST_CHECK_THROW(x, y) +#endif #include using std::cout; using std::endl; +#include +using std::numeric_limits; template void test_spots(RealType T) @@ -671,6 +679,12 @@ void test_spots(RealType T) static_cast(1-0.039583424160566))), // x static_cast(3), // probability. tolerance); // % + BOOST_CHECK_EQUAL( + ::boost::math::quantile( + cauchy_distribution(-2, 0.25), + static_cast(0.5)), // p + static_cast(-2) // location + ); /* BOOST_CHECK_CLOSE( ::boost::math::quantile( @@ -744,62 +758,52 @@ void test_spots(RealType T) check_out_of_range >(0, 1); // (All) valid constructor parameter values. + using boost::math::policies::policy; + + typedef policy< + boost::math::policies::domain_error, + boost::math::policies::overflow_error, + boost::math::policies::underflow_error, + boost::math::policies::denorm_error, + boost::math::policies::pole_error, + boost::math::policies::evaluation_error + > ignore_all_policy; + + std::vector > invalid_params = {{0, -1}}; + test_invalid_parameters >, + cauchy_distribution, + RealType>(invalid_params); + + // Check constructing with NaNs + if (std::numeric_limits::has_quiet_NaN){ + // Attempt to construct from non-finite parameters should throw. + RealType nan = std::numeric_limits::quiet_NaN(); + invalid_params = {{nan}, + {0, nan}, + {nan, 1}}; + test_invalid_parameters >, + cauchy_distribution, + RealType>(invalid_params); + } + + // Check construcing with Infinity if (std::numeric_limits::has_infinity) { - BOOST_CHECK_EQUAL( - boost::math::pdf( - cauchy_distribution(-2, 0.25), - std::numeric_limits::infinity()), // x - static_cast(0) // probability - ); - BOOST_CHECK_EQUAL( - boost::math::cdf( - cauchy_distribution(-2, 0.25), - std::numeric_limits::infinity()), // x - static_cast(1) // probability - ); - BOOST_CHECK_EQUAL( - boost::math::cdf( - cauchy_distribution(-2, 0.25), - -std::numeric_limits::infinity()), // x - static_cast(0) // probability - ); - BOOST_CHECK_EQUAL( - boost::math::quantile( - cauchy_distribution(-2, 0.25), - static_cast(0.5)), // p - static_cast(-2) // location - ); - - using boost::math::policies::policy; - - typedef policy< - boost::math::policies::domain_error, - boost::math::policies::overflow_error, - boost::math::policies::underflow_error, - boost::math::policies::denorm_error, - boost::math::policies::pole_error, - boost::math::policies::evaluation_error - > ignore_all_policy; - - typedef boost::math::cauchy_distribution ignore_error_cauchy; - - // PDF - BOOST_CHECK((boost::math::isnan)(boost::math::pdf(ignore_error_cauchy(static_cast(0), static_cast(-1)), static_cast(0)))); - BOOST_CHECK((boost::math::isnan)(boost::math::pdf(ignore_error_cauchy(std::numeric_limits::infinity(), static_cast(1)), static_cast(0)))); - BOOST_CHECK((boost::math::isnan)(boost::math::pdf(ignore_error_cauchy(static_cast(0), static_cast(1)), std::numeric_limits::quiet_NaN()))); - - // CDF - BOOST_CHECK((boost::math::isnan)(boost::math::cdf(ignore_error_cauchy(static_cast(0), static_cast(-1)), static_cast(0)))); - BOOST_CHECK((boost::math::isnan)(boost::math::cdf(ignore_error_cauchy(std::numeric_limits::infinity(), static_cast(1)), static_cast(0)))); - BOOST_CHECK((boost::math::isnan)(boost::math::cdf(ignore_error_cauchy(static_cast(0), static_cast(1)), std::numeric_limits::quiet_NaN()))); - - // Quantile - BOOST_CHECK((boost::math::isnan)(boost::math::quantile(ignore_error_cauchy(static_cast(0), static_cast(-1)), static_cast(0.25)))); - BOOST_CHECK((boost::math::isnan)(boost::math::quantile(ignore_error_cauchy(std::numeric_limits::infinity(), static_cast(1)), static_cast(0.25)))); - BOOST_CHECK((boost::math::isnan)(boost::math::quantile(ignore_error_cauchy(static_cast(0), static_cast(1)), static_cast(-0.25)))); + // Attempt to construct from non-finite should throw. + RealType inf = std::numeric_limits::infinity(); + invalid_params = {{inf}, + {0, inf}, + {inf, 1}}; + test_invalid_parameters >, + cauchy_distribution, + RealType>(invalid_params); + } // has_infinity + if (std::numeric_limits::has_quiet_NaN) + { + test_invalid_support >, + cauchy_distribution, + RealType>({0, 1}); } - } // template void test_spots(RealType) BOOST_AUTO_TEST_CASE(test_main) diff --git a/test/test_dist_helpers.hpp b/test/test_dist_helpers.hpp new file mode 100644 index 0000000000..44cb2b14f2 --- /dev/null +++ b/test/test_dist_helpers.hpp @@ -0,0 +1,191 @@ +#ifndef BOOST_MATH_TEST_DIST_HELPERS_HPP +#define BOOST_MATH_TEST_DIST_HELPERS_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +template +Dist make_distribution(const Container& c) +{ + using value_type = typename Dist::value_type; + if constexpr (std::is_constructible::value) + { + if (c.size() >= 3) + return Dist(c.data()[0], c.data()[1], c.data()[2]); + } + if constexpr (std::is_constructible::value) + { + if (c.size() >= 2) + return Dist(c.data()[0], c.data()[1]); + } + if constexpr (std::is_constructible::value) + { + if (c.size() >= 1) + return Dist(c.data()[0]); + } + throw std::domain_error("Object not initialized!"); +} + +template +Dist make_distribution(const std::initializer_list& c) +{ + return make_distribution>(c); +} + +template +void test_invalid_support(std::vector params) +{ + using namespace boost::math; + + Dist dist = make_distribution(params); + Ignore_Error_Dist ignore_error_dist = make_distribution(params); + + /* We will assume that std::numeric_limits::has_infinity */ + std::pair sup = support(dist); + + // Test outside lower bound: + Real invalid = sup.first; + if (boost::math::isfinite(invalid)) + { + if (invalid == -boost::math::tools::max_value()) + invalid = -std::numeric_limits::infinity(); + else if (invalid == boost::math::tools::min_value()) + { + invalid = -boost::math::tools::min_value(); + } + else + invalid = boost::math::float_prior(invalid); + + // Test PDF/CDF + BOOST_CHECK_THROW(pdf(dist, invalid), std::domain_error); + BOOST_CHECK_THROW(cdf(dist, invalid), std::domain_error); + BOOST_CHECK_THROW(cdf(complement(dist, invalid)), std::domain_error); + BOOST_CHECK((boost::math::isnan)(pdf(ignore_error_dist, invalid))); + BOOST_CHECK((boost::math::isnan)(cdf(ignore_error_dist, invalid))); + BOOST_CHECK((boost::math::isnan)(cdf(complement(ignore_error_dist, invalid)))); + + // Test log PDF/CDF + BOOST_CHECK_THROW(logpdf(dist, invalid), std::domain_error); + BOOST_CHECK_THROW(logcdf(dist, invalid), std::domain_error); + BOOST_CHECK_THROW(logcdf(complement(dist, invalid)), std::domain_error); + BOOST_CHECK((boost::math::isnan)(logpdf(ignore_error_dist, invalid))); + BOOST_CHECK((boost::math::isnan)(logcdf(ignore_error_dist, invalid))); + BOOST_CHECK((boost::math::isnan)(logcdf(complement(ignore_error_dist, invalid)))); + } + else // lower bound is -infinity + { + BOOST_CHECK_THROW(quantile(dist, static_cast(0.0)), std::overflow_error); + BOOST_CHECK_THROW(quantile(complement(dist, static_cast(1.0))), std::overflow_error); + BOOST_CHECK_EQUAL(pdf(dist, invalid), static_cast(0)); + BOOST_CHECK_EQUAL(cdf(dist, invalid), static_cast(0)); + BOOST_CHECK_EQUAL(cdf(complement(dist, invalid)), static_cast(1)); + } + // Test outside upper bound: + invalid = sup.second; + if (boost::math::isfinite(invalid)) + { + if (invalid == boost::math::tools::max_value()) + invalid = std::numeric_limits::infinity(); + else + invalid = boost::math::float_next(invalid); + // Test PDF/CDF + BOOST_CHECK_THROW(pdf(dist, invalid), std::domain_error); + BOOST_CHECK_THROW(cdf(dist, invalid), std::domain_error); + BOOST_CHECK_THROW(cdf(complement(dist, invalid)), std::domain_error); + // Test NaN handling + BOOST_CHECK((boost::math::isnan)(pdf(ignore_error_dist, invalid))); + BOOST_CHECK((boost::math::isnan)(cdf(ignore_error_dist, invalid))); + BOOST_CHECK((boost::math::isnan)(cdf(complement(ignore_error_dist, invalid)))); + + // Test log PDF/CDF + BOOST_CHECK_THROW(logpdf(dist, invalid), std::domain_error); + BOOST_CHECK_THROW(logcdf(dist, invalid), std::domain_error); + BOOST_CHECK_THROW(logcdf(complement(dist, invalid)), std::domain_error); + BOOST_CHECK((boost::math::isnan)(logpdf(ignore_error_dist, invalid))); + BOOST_CHECK((boost::math::isnan)(logcdf(ignore_error_dist, invalid))); + BOOST_CHECK((boost::math::isnan)(logcdf(complement(ignore_error_dist, invalid)))); + } + else // upper bound is +infinity + { + BOOST_CHECK_EQUAL(pdf(dist, invalid), static_cast(0)); + BOOST_CHECK_EQUAL(cdf(dist, invalid), static_cast(1)); + BOOST_CHECK_EQUAL(cdf(complement(dist, invalid)), static_cast(0)); + + // If support is infinite quantile will throw overflow error + BOOST_CHECK_THROW(quantile(dist, static_cast(1.0)), std::overflow_error); + BOOST_CHECK_THROW(quantile(complement(dist, static_cast(0.0))), std::overflow_error); + } + + // NaN checks for PDF/CDF + invalid = std::numeric_limits::quiet_NaN(); + BOOST_CHECK_THROW(pdf(dist, invalid), std::domain_error); + BOOST_CHECK_THROW(cdf(dist, invalid), std::domain_error); + BOOST_CHECK_THROW(cdf(complement(dist, invalid)), std::domain_error); + BOOST_CHECK((boost::math::isnan)(pdf(ignore_error_dist, invalid))); + BOOST_CHECK((boost::math::isnan)(cdf(ignore_error_dist, invalid))); + BOOST_CHECK((boost::math::isnan)(cdf(complement(ignore_error_dist, invalid)))); + + // NaN checks for log PDF/CDF + BOOST_CHECK_THROW(logpdf(dist, invalid), std::domain_error); + BOOST_CHECK_THROW(logcdf(dist, invalid), std::domain_error); + BOOST_CHECK_THROW(logcdf(complement(dist, invalid)), std::domain_error); + BOOST_CHECK((boost::math::isnan)(logpdf(ignore_error_dist, invalid))); + BOOST_CHECK((boost::math::isnan)(logcdf(ignore_error_dist, invalid))); + BOOST_CHECK((boost::math::isnan)(logcdf(complement(ignore_error_dist, invalid)))); + + // Quantile Checks + BOOST_CHECK_THROW(quantile(dist, std::numeric_limits::infinity()), std::domain_error); // p == infinity + BOOST_CHECK_THROW(quantile(dist, static_cast(-1)), std::domain_error); // p < 0 + BOOST_CHECK_THROW(quantile(dist, static_cast(2)), std::domain_error); // p > 1 + BOOST_CHECK_THROW(quantile(complement(dist, std::numeric_limits::infinity())), std::domain_error); // q == infinity + BOOST_CHECK_THROW(quantile(complement(dist, static_cast(-1))), std::domain_error); // q < 0 + BOOST_CHECK_THROW(quantile(complement(dist, static_cast(2))), std::domain_error); // q > 1 + + BOOST_CHECK((boost::math::isnan)(quantile(ignore_error_dist, std::numeric_limits::infinity()))); // p == infinity + BOOST_CHECK((boost::math::isnan)(quantile(ignore_error_dist, static_cast(-1)))); // p < 0 + BOOST_CHECK((boost::math::isnan)(quantile(ignore_error_dist, static_cast(2)))); // p > 1 + BOOST_CHECK((boost::math::isnan)(quantile(complement(ignore_error_dist, std::numeric_limits::infinity())))); // q == infinity + BOOST_CHECK((boost::math::isnan)(quantile(complement(ignore_error_dist, static_cast(-1))))); // q < 0 + BOOST_CHECK((boost::math::isnan)(quantile(complement(ignore_error_dist, static_cast(2))))); // q > 1 +} + +template +void test_invalid_parameters(std::vector > invalid_parameters) +{ + std::vector params; + for (unsigned i=0; i(params), std::domain_error); + BOOST_CHECK_THROW(pdf(make_distribution(params), static_cast(0)), std::domain_error); + BOOST_CHECK_THROW(logpdf(make_distribution(params), static_cast(0)), std::domain_error); + BOOST_CHECK_THROW(cdf(make_distribution(params), static_cast(0)), std::domain_error); + BOOST_CHECK_THROW(cdf(complement(make_distribution(params), static_cast(0))), std::domain_error); + BOOST_CHECK_THROW(logcdf(make_distribution(params), static_cast(0)), std::domain_error); + BOOST_CHECK_THROW(logcdf(complement(make_distribution(params), static_cast(0))), std::domain_error); + BOOST_CHECK_THROW(quantile(make_distribution(params), static_cast(0.5)), std::domain_error); + BOOST_CHECK_THROW(quantile(complement(make_distribution(params), static_cast(0.5))), std::domain_error); + + // Check return NaN + if (std::numeric_limits::has_quiet_NaN) + { + BOOST_CHECK((boost::math::isnan)(pdf(make_distribution(params), static_cast(0)))); + BOOST_CHECK((boost::math::isnan)(logpdf(make_distribution(params), static_cast(0)))); + BOOST_CHECK((boost::math::isnan)(cdf(make_distribution(params), static_cast(0)))); + BOOST_CHECK((boost::math::isnan)(cdf(complement(make_distribution(params), static_cast(0))))); + BOOST_CHECK((boost::math::isnan)(logcdf(make_distribution(params), static_cast(0)))); + BOOST_CHECK((boost::math::isnan)(logcdf(complement(make_distribution(params), static_cast(0))))); + BOOST_CHECK((boost::math::isnan)(quantile(make_distribution(params), static_cast(0.5)))); + BOOST_CHECK((boost::math::isnan)(quantile(complement(make_distribution(params), static_cast(0.5))))); + } + } +} + +#endif // BOOST_MATH_TEST_DIST_HELPERS_HPP \ No newline at end of file diff --git a/test/test_exponential_dist.cpp b/test/test_exponential_dist.cpp index ecf5106d01..3c1a034202 100644 --- a/test/test_exponential_dist.cpp +++ b/test/test_exponential_dist.cpp @@ -21,6 +21,7 @@ #include // Boost.Test #include #include "test_out_of_range.hpp" +#include "test_dist_helpers.hpp" #include #include @@ -29,7 +30,7 @@ using std::endl; using std::setprecision; using std::log; - +#include #if __has_include() # include #endif @@ -330,80 +331,54 @@ void test_spots(RealType T) // // Things that are errors: // - exponential_distribution dist(0.5); - BOOST_MATH_CHECK_THROW( - quantile(dist, RealType(1.0)), - std::overflow_error); - BOOST_MATH_CHECK_THROW( - quantile(complement(dist, RealType(0.0))), - std::overflow_error); - BOOST_MATH_CHECK_THROW( - pdf(dist, RealType(-1)), - std::domain_error); - BOOST_MATH_CHECK_THROW( - cdf(dist, RealType(-1)), - std::domain_error); - BOOST_MATH_CHECK_THROW( - cdf(exponential_distribution(-1), RealType(1)), - std::domain_error); - BOOST_MATH_CHECK_THROW( - quantile(dist, RealType(-1)), - std::domain_error); - BOOST_MATH_CHECK_THROW( - quantile(dist, RealType(2)), - std::domain_error); - check_out_of_range >(2); - BOOST_MATH_CHECK_THROW(exponential_distribution(0), std::domain_error); - BOOST_MATH_CHECK_THROW(exponential_distribution(-1), std::domain_error); - if(std::numeric_limits::has_infinity) + + using boost::math::policies::policy; + + typedef policy< + boost::math::policies::domain_error, + boost::math::policies::overflow_error, + boost::math::policies::underflow_error, + boost::math::policies::denorm_error, + boost::math::policies::pole_error, + boost::math::policies::evaluation_error + > ignore_all_policy; + + std::vector > invalid_params = {{-1}, + {0}}; + test_invalid_parameters >, + exponential_distribution, + RealType>(invalid_params); + + // Check constructing with NaNs + if (std::numeric_limits::has_quiet_NaN){ + // Attempt to construct from non-finite parameters should throw. + RealType nan = std::numeric_limits::quiet_NaN(); + invalid_params = {{nan}}; + test_invalid_parameters >, + exponential_distribution, + RealType>(invalid_params); + + BOOST_CHECK((boost::math::isnan)(mean(exponential_distribution(static_cast(-1))))); + BOOST_CHECK((boost::math::isnan)(standard_deviation(exponential_distribution(static_cast(-1))))); + } + + // Check construcing with Infinity + if (std::numeric_limits::has_infinity) { + // Attempt to construct from non-finite should throw. RealType inf = std::numeric_limits::infinity(); - BOOST_CHECK_EQUAL(pdf(exponential_distribution(2), inf), 0); - BOOST_CHECK_EQUAL(cdf(exponential_distribution(2), inf), 1); - BOOST_CHECK_EQUAL(cdf(complement(exponential_distribution(2), inf)), 0); - - // Test NaN policies - using boost::math::policies::policy; + invalid_params = {{inf}}; + test_invalid_parameters >, + exponential_distribution, + RealType>(invalid_params); - typedef policy< - boost::math::policies::domain_error, - boost::math::policies::overflow_error, - boost::math::policies::underflow_error, - boost::math::policies::denorm_error, - boost::math::policies::pole_error, - boost::math::policies::evaluation_error - > ignore_all_policy; - - typedef boost::math::exponential_distribution ignore_error_exponential; - - // PDF - BOOST_CHECK((boost::math::isnan)(pdf(ignore_error_exponential(static_cast(-1)), static_cast(1)))); - BOOST_CHECK((boost::math::isnan)(pdf(ignore_error_exponential(static_cast(1)), static_cast(-1)))); - BOOST_CHECK((boost::math::isnan)(logpdf(ignore_error_exponential(static_cast(-1)), static_cast(1)))); - BOOST_CHECK((boost::math::isnan)(logpdf(ignore_error_exponential(static_cast(1)), static_cast(-1)))); - - // CDF - BOOST_CHECK((boost::math::isnan)(cdf(ignore_error_exponential(static_cast(-1)), static_cast(1)))); - BOOST_CHECK((boost::math::isnan)(cdf(ignore_error_exponential(static_cast(1)), static_cast(-1)))); - BOOST_CHECK((boost::math::isnan)(logcdf(ignore_error_exponential(static_cast(-1)), static_cast(1)))); - BOOST_CHECK((boost::math::isnan)(logcdf(ignore_error_exponential(static_cast(1)), static_cast(-1)))); - - // Complement CDF - BOOST_CHECK((boost::math::isnan)(cdf(complement(ignore_error_exponential(static_cast(-1)), static_cast(1))))); - BOOST_CHECK((boost::math::isnan)(cdf(complement(ignore_error_exponential(static_cast(1)), static_cast(-1))))); - BOOST_CHECK((boost::math::isnan)(logcdf(complement(ignore_error_exponential(static_cast(-1)), static_cast(1))))); - BOOST_CHECK((boost::math::isnan)(logcdf(complement(ignore_error_exponential(static_cast(1)), static_cast(-1))))); - - // Quantile - BOOST_CHECK((boost::math::isnan)(quantile(ignore_error_exponential(static_cast(-1)), static_cast(0.5)))); - BOOST_CHECK((boost::math::isnan)(quantile(ignore_error_exponential(static_cast(1)), static_cast(-0.5)))); - BOOST_CHECK((boost::math::isnan)(quantile(complement(ignore_error_exponential(static_cast(-1)), static_cast(0.5))))); - BOOST_CHECK((boost::math::isnan)(quantile(complement(ignore_error_exponential(static_cast(1)), static_cast(-0.5))))); - - // Mean and Standard Deviation - BOOST_CHECK((boost::math::isnan)(mean(ignore_error_exponential(static_cast(-1))))); - BOOST_CHECK((boost::math::isnan)(standard_deviation(ignore_error_exponential(static_cast(-1))))); + } // has_infinity + if (std::numeric_limits::has_quiet_NaN) + { + test_invalid_support >, + exponential_distribution, + RealType>({1}); } } // template void test_spots(RealType) diff --git a/test/test_fisher_f.cpp b/test/test_fisher_f.cpp index 0739dfbda2..f71a1c6cfb 100644 --- a/test/test_fisher_f.cpp +++ b/test/test_fisher_f.cpp @@ -27,12 +27,14 @@ using boost::math::fisher_f_distribution; #include // for test_main #include // for BOOST_CHECK_CLOSE #include "test_out_of_range.hpp" +#include "test_dist_helpers.hpp" #include using std::cout; using std::endl; #include using std::numeric_limits; +#include template RealType naive_pdf(RealType df1, RealType df2, RealType x) @@ -444,72 +446,86 @@ void test_spots(RealType) cdf(complement(fisher_f_distribution(3, 3), static_cast(0))) , static_cast(1)); - BOOST_MATH_CHECK_THROW( - pdf( - fisher_f_distribution(-1, 2), - static_cast(1)), std::domain_error - ); - BOOST_MATH_CHECK_THROW( - pdf( - fisher_f_distribution(1, -1), - static_cast(1)), std::domain_error - ); - BOOST_MATH_CHECK_THROW( - pdf( - fisher_f_distribution(8, 2), - static_cast(-1)), std::domain_error - ); - BOOST_MATH_CHECK_THROW( - cdf( - fisher_f_distribution(-1, 1), - static_cast(1)), std::domain_error - ); - BOOST_MATH_CHECK_THROW( - cdf( - fisher_f_distribution(8, 4), - static_cast(-1)), std::domain_error - ); - BOOST_MATH_CHECK_THROW( - cdf(complement( - fisher_f_distribution(-1, 2), - static_cast(1))), std::domain_error - ); - BOOST_MATH_CHECK_THROW( - cdf(complement( - fisher_f_distribution(8, 4), - static_cast(-1))), std::domain_error - ); - BOOST_MATH_CHECK_THROW( - quantile( - fisher_f_distribution(-1, 2), - static_cast(0.5)), std::domain_error - ); - BOOST_MATH_CHECK_THROW( - quantile( - fisher_f_distribution(8, 8), - static_cast(-1)), std::domain_error - ); - BOOST_MATH_CHECK_THROW( - quantile( - fisher_f_distribution(8, 8), - static_cast(1.1)), std::domain_error - ); - BOOST_MATH_CHECK_THROW( - quantile(complement( - fisher_f_distribution(2, -1), - static_cast(0.5))), std::domain_error - ); - BOOST_MATH_CHECK_THROW( - quantile(complement( - fisher_f_distribution(8, 8), - static_cast(-1))), std::domain_error - ); - BOOST_MATH_CHECK_THROW( - quantile(complement( - fisher_f_distribution(8, 8), - static_cast(1.1))), std::domain_error - ); check_out_of_range >(2, 3); + + using boost::math::policies::policy; + + typedef policy< + boost::math::policies::domain_error, + boost::math::policies::overflow_error, + boost::math::policies::underflow_error, + boost::math::policies::denorm_error, + boost::math::policies::pole_error, + boost::math::policies::evaluation_error + > ignore_all_policy; + + std::vector > invalid_params = {{-1, 1}, + {0, 1}, + {1, -1}, + {1, 0}}; + test_invalid_parameters >, + fisher_f_distribution, + RealType>(invalid_params); + + // Check constructing with NaNs + if (std::numeric_limits::has_quiet_NaN){ + // Attempt to construct from non-finite parameters should throw. + RealType nan = std::numeric_limits::quiet_NaN(); + invalid_params = {{nan, 1}, + {1, nan}}; + test_invalid_parameters >, + fisher_f_distribution, + RealType>(invalid_params); + + // Check moment function for bad constructors + BOOST_CHECK_THROW(mean(fisher_f_distribution >(-1, 1)), std::domain_error); + BOOST_CHECK_THROW(mean(fisher_f_distribution >(1, -1)), std::domain_error); + BOOST_CHECK_THROW(variance(fisher_f_distribution >(-1, 1)), std::domain_error); + BOOST_CHECK_THROW(variance(fisher_f_distribution >(1, -1)), std::domain_error); + BOOST_CHECK_THROW(mode(fisher_f_distribution >(-1, 1)), std::domain_error); + BOOST_CHECK_THROW(mode(fisher_f_distribution >(1, -1)), std::domain_error); + BOOST_CHECK_THROW(skewness(fisher_f_distribution >(-1, 1)), std::domain_error); + BOOST_CHECK_THROW(skewness(fisher_f_distribution >(1, -1)), std::domain_error); + BOOST_CHECK_THROW(kurtosis_excess(fisher_f_distribution >(-1, 1)), std::domain_error); + BOOST_CHECK_THROW(kurtosis_excess(fisher_f_distribution >(1, -1)), std::domain_error); + + BOOST_CHECK((boost::math::isnan)(mean(fisher_f_distribution(-1, 1)))); + BOOST_CHECK((boost::math::isnan)(mean(fisher_f_distribution(1, -1)))); + BOOST_CHECK((boost::math::isnan)(variance(fisher_f_distribution(-1, 1)))); + BOOST_CHECK((boost::math::isnan)(variance(fisher_f_distribution(1, -1)))); + BOOST_CHECK((boost::math::isnan)(mode(fisher_f_distribution(-1, 1)))); + BOOST_CHECK((boost::math::isnan)(mode(fisher_f_distribution(1, -1)))); + BOOST_CHECK((boost::math::isnan)(skewness(fisher_f_distribution(-1, 1)))); + BOOST_CHECK((boost::math::isnan)(skewness(fisher_f_distribution(1, -1)))); + BOOST_CHECK((boost::math::isnan)(kurtosis_excess(fisher_f_distribution(-1, 1)))); + BOOST_CHECK((boost::math::isnan)(kurtosis_excess(fisher_f_distribution(1, -1)))); + + // Check undefined moments + BOOST_CHECK_THROW(mean(fisher_f_distribution >(1, 2)), std::domain_error); + BOOST_CHECK_THROW(variance(fisher_f_distribution >(1, 4)), std::domain_error); + BOOST_CHECK_THROW(mode(fisher_f_distribution >(1, 2)), std::domain_error); + BOOST_CHECK_THROW(skewness(fisher_f_distribution >(1, 6)), std::domain_error); + BOOST_CHECK_THROW(kurtosis_excess(fisher_f_distribution >(1, 8)), std::domain_error); + } + + // Check construcing with Infinity + if (std::numeric_limits::has_infinity) + { + // Attempt to construct from non-finite should throw. + RealType inf = std::numeric_limits::infinity(); + invalid_params = {{inf, 1}, + {1, inf}}; + test_invalid_parameters >, + fisher_f_distribution, + RealType>(invalid_params); + + } // has_infinity + if (std::numeric_limits::has_quiet_NaN) + { + test_invalid_support >, + fisher_f_distribution, + RealType>({1, 1}); + } } // template void test_spots(RealType) BOOST_AUTO_TEST_CASE( test_main ) diff --git a/test/test_gamma_dist.cpp b/test/test_gamma_dist.cpp index f1abbfd995..83f78cbc15 100644 --- a/test/test_gamma_dist.cpp +++ b/test/test_gamma_dist.cpp @@ -35,6 +35,7 @@ using boost::math::gamma_distribution; #include "../include_private/boost/math/tools/test.hpp" #include "test_out_of_range.hpp" +#include "test_dist_helpers.hpp" #include #include @@ -237,14 +238,78 @@ void test_spots(RealType) BOOST_CHECK_CLOSE( entropy(dist), expected_entropy, tol2); - // Rely on default definition in derived accessors. - - // error tests + // Error tests check_out_of_range >(1, 1); - BOOST_MATH_CHECK_THROW(boost::math::gamma_distribution(0, 1), std::domain_error); - BOOST_MATH_CHECK_THROW(boost::math::gamma_distribution(-1, 1), std::domain_error); - BOOST_MATH_CHECK_THROW(boost::math::gamma_distribution(1, 0), std::domain_error); - BOOST_MATH_CHECK_THROW(boost::math::gamma_distribution(1, -1), std::domain_error); + using boost::math::policies::policy; + + typedef policy< + boost::math::policies::domain_error, + boost::math::policies::overflow_error, + boost::math::policies::underflow_error, + boost::math::policies::denorm_error, + boost::math::policies::pole_error, + boost::math::policies::evaluation_error + > ignore_all_policy; + + std::vector > invalid_params = {{-1, 1}, + {0, 1}, + {1, -1}, + {1, 0}}; + test_invalid_parameters >, + gamma_distribution, + RealType>(invalid_params); + + // Check constructing with NaNs + if (std::numeric_limits::has_quiet_NaN){ + // Attempt to construct from non-finite parameters should throw. + RealType nan = std::numeric_limits::quiet_NaN(); + invalid_params = {{nan, 1}, + {1, nan}}; + test_invalid_parameters >, + gamma_distribution, + RealType>(invalid_params); + } + + // Check construcing with Infinity + if (std::numeric_limits::has_infinity) + { + // Attempt to construct from non-finite should throw. + RealType inf = std::numeric_limits::infinity(); + invalid_params = {{inf, 1}, + {1, inf}}; + test_invalid_parameters >, + gamma_distribution, + RealType>(invalid_params); + + } // has_infinity + if (std::numeric_limits::has_quiet_NaN) + { + test_invalid_support > >, + gamma_distribution, + RealType>({1, 1}); + } + + // Test Special Values + if (std::numeric_limits::has_quiet_NaN){ + BOOST_CHECK((boost::math::isnan)(logpdf(gamma_distribution(0.5,1), static_cast(0)))); + BOOST_CHECK((boost::math::isnan)(mean(gamma_distribution(-1, 1)))); + BOOST_CHECK((boost::math::isnan)(mean(gamma_distribution(1, -1)))); + BOOST_CHECK((boost::math::isnan)(variance(gamma_distribution(-1, 1)))); + BOOST_CHECK((boost::math::isnan)(variance(gamma_distribution(1, -1)))); + BOOST_CHECK((boost::math::isnan)(skewness(gamma_distribution(-1, 1)))); + BOOST_CHECK((boost::math::isnan)(skewness(gamma_distribution(1, -1)))); + BOOST_CHECK((boost::math::isnan)(kurtosis_excess(gamma_distribution(-1, 1)))); + BOOST_CHECK((boost::math::isnan)(kurtosis_excess(gamma_distribution(1, -1)))); + BOOST_CHECK((boost::math::isnan)(mode(gamma_distribution(-1, 1)))); + BOOST_CHECK((boost::math::isnan)(mode(gamma_distribution(1, -1)))); + BOOST_CHECK((boost::math::isnan)(mode(gamma_distribution(0.5, 1)))); + } + BOOST_CHECK_EQUAL(pdf(gamma_distribution(2, 1), 0), 0); + BOOST_CHECK_THROW(logpdf(gamma_distribution(2, 1), static_cast(0)), std::domain_error); + BOOST_CHECK_EQUAL(cdf(gamma_distribution(2, 1), 0), 0); + BOOST_CHECK_EQUAL(cdf(complement(gamma_distribution(2, 1), 0)), 1); + + // More errors in moments } // template void test_spots(RealType) diff --git a/test/test_geometric.cpp b/test/test_geometric.cpp index 7e1a00f574..b48d171c18 100644 --- a/test/test_geometric.cpp +++ b/test/test_geometric.cpp @@ -49,6 +49,7 @@ using boost::math::geometric; // using typedef for geometric_distribution // for test_main #include // for BOOST_CHECK_CLOSE_FRACTION #include "test_out_of_range.hpp" +#include "test_dist_helpers.hpp" #include using std::cout; @@ -798,8 +799,75 @@ if(std::numeric_limits::is_specialized) negative_binomial_distribution::find_maximum_number_of_trials(k, p, alpha), tolerance); } - //geometric::find_upper_bound_on_p(k, alpha); - return; + + using boost::math::policies::policy; + + typedef policy< + boost::math::policies::domain_error, + boost::math::policies::overflow_error, + boost::math::policies::underflow_error, + boost::math::policies::denorm_error, + boost::math::policies::pole_error, + boost::math::policies::evaluation_error + > ignore_all_policy; + + std::vector > invalid_params = {{-1}, + {2}}; + test_invalid_parameters >, + geometric_distribution, + RealType>(invalid_params); + + // Check constructing with NaNs + if (std::numeric_limits::has_quiet_NaN){ + // Attempt to construct from non-finite parameters should throw. + RealType nan = std::numeric_limits::quiet_NaN(); + invalid_params = {{nan}}; + test_invalid_parameters >, + geometric_distribution, + RealType>(invalid_params); + } + + // Check construcing with Infinity + if (std::numeric_limits::has_infinity) + { + // Attempt to construct from non-finite should throw. + RealType inf = std::numeric_limits::infinity(); + invalid_params = {{inf}}; + test_invalid_parameters >, + geometric_distribution, + RealType>(invalid_params); + + } // has_infinity + if (std::numeric_limits::has_quiet_NaN) + { + test_invalid_support >, + geometric_distribution, + RealType>({0.5}); + // Check incorrect constructors for find_lower_bound_on_p + BOOST_CHECK((boost::math::isnan)(geometric_distribution::find_lower_bound_on_p(8, -0.25))); + BOOST_CHECK((boost::math::isnan)(geometric_distribution::find_lower_bound_on_p(8, 1.25))); + BOOST_CHECK((boost::math::isnan)(geometric_distribution::find_lower_bound_on_p(0, 0.25))); + BOOST_CHECK((boost::math::isnan)(geometric_distribution::find_lower_bound_on_p(-1, 0.25))); + BOOST_CHECK((boost::math::isnan)(geometric_distribution::find_upper_bound_on_p(8, -0.25))); + BOOST_CHECK((boost::math::isnan)(geometric_distribution::find_upper_bound_on_p(8, 1.25))); + BOOST_CHECK((boost::math::isnan)(geometric_distribution::find_upper_bound_on_p(0, 0.25))); + BOOST_CHECK((boost::math::isnan)(geometric_distribution::find_upper_bound_on_p(-1, 0.25))); + + // Incorrect constructors for find_minimum_number_of_trials + BOOST_CHECK((boost::math::isnan)(geometric_distribution::find_minimum_number_of_trials(1, 0.25, -0.25))); + BOOST_CHECK((boost::math::isnan)(geometric_distribution::find_minimum_number_of_trials(1, 0.25, 1.25))); + BOOST_CHECK((boost::math::isnan)(geometric_distribution::find_minimum_number_of_trials(1, -0.25, 0.25))); + BOOST_CHECK((boost::math::isnan)(geometric_distribution::find_minimum_number_of_trials(1, 1.25, 0.25))); + BOOST_CHECK((boost::math::isnan)(geometric_distribution::find_minimum_number_of_trials(-1, 0.25, 0.25))); + BOOST_CHECK((boost::math::isnan)(geometric_distribution::find_maximum_number_of_trials(1, 0.25, -0.25))); + BOOST_CHECK((boost::math::isnan)(geometric_distribution::find_maximum_number_of_trials(1, 0.25, 1.25))); + BOOST_CHECK((boost::math::isnan)(geometric_distribution::find_maximum_number_of_trials(1, -0.25, 0.25))); + BOOST_CHECK((boost::math::isnan)(geometric_distribution::find_maximum_number_of_trials(1, 1.25, 0.25))); + BOOST_CHECK((boost::math::isnan)(geometric_distribution::find_maximum_number_of_trials(-1, 0.25, 0.25))); + } + + //geometric::find_upper_bound_on_p(k, alpha); + return; } // template void test_spots(RealType) // Any floating-point type RealType. BOOST_AUTO_TEST_CASE( test_main ) diff --git a/test/test_hyperexponential_dist.cpp b/test/test_hyperexponential_dist.cpp index c7d3c9843b..a4fc5509ed 100644 --- a/test/test_hyperexponential_dist.cpp +++ b/test/test_hyperexponential_dist.cpp @@ -398,6 +398,26 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(error_cases, RealT, test_types) BOOST_MATH_CHECK_THROW(dist_t(probs.begin(), probs.begin(), rates.begin(), rates.begin()), std::domain_error); BOOST_MATH_CHECK_THROW(dist_t(rates.begin(), rates.begin()), std::domain_error); + typedef boost::math::policies::policy< + boost::math::policies::domain_error, + boost::math::policies::overflow_error, + boost::math::policies::underflow_error, + boost::math::policies::denorm_error, + boost::math::policies::pole_error, + boost::math::policies::evaluation_error + > ignore_all_policy; + + if (std::numeric_limits::has_quiet_NaN) + { + typedef boost::math::hyperexponential_distribution ignore_all_hyperexp; + BOOST_CHECK((boost::math::isnan)(boost::math::pdf(ignore_all_hyperexp({ 0.25, 0.5, 0.25 }, { -0.5, 1.0, 1.5 }), 1))); + BOOST_CHECK((boost::math::isnan)(boost::math::pdf(ignore_all_hyperexp({ 0.25, 0.5, 0.25 }, { 0.5, 1.0, 1.5 }), -1))); + BOOST_CHECK((boost::math::isnan)(boost::math::cdf(ignore_all_hyperexp({ 0.25, 0.5, 0.25 }, { 0.5, 1.0, 1.5 }), -1))); + BOOST_CHECK((boost::math::isnan)(boost::math::cdf(complement(ignore_all_hyperexp({ 0.25, 0.5, 0.25 }, { 0.5, 1.0, 1.5 }), -1)))); + BOOST_CHECK((boost::math::isnan)(boost::math::quantile(ignore_all_hyperexp({ 0.25, 0.5, 0.25 }, { 1.0, 1.5 }), -0.25))); + BOOST_CHECK((boost::math::isnan)(boost::math::quantile(ignore_all_hyperexp({ 0.25, 0.5, 0.25 }, { 1.0, 1.5 }), 1.25))); + } + // Test C++20 ranges (Currently only GCC10 has full support to P0896R4) #if (__cplusplus > 202000L || _MSVC_LANG > 202000L) && __has_include() && __GNUC__ >= 10 // Support for ranges is broken using gcc 11.1 diff --git a/test/test_hypergeometric_dist.cpp b/test/test_hypergeometric_dist.cpp index 961e5394a6..30339e24fe 100644 --- a/test/test_hypergeometric_dist.cpp +++ b/test/test_hypergeometric_dist.cpp @@ -16,6 +16,7 @@ #include #include #include +#include "test_dist_helpers.hpp" #include using std::cout; @@ -491,6 +492,40 @@ void test_spots(RealType /*T*/, const char* type_name) BOOST_MATH_CHECK_THROW(d = boost::math::hypergeometric_distribution(501, 40, 500), std::domain_error); BOOST_MATH_CHECK_THROW(d = boost::math::hypergeometric_distribution(40, 501, 500), std::domain_error); + + using boost::math::policies::policy; + using boost::math::hypergeometric_distribution; + + typedef policy< + boost::math::policies::domain_error, + boost::math::policies::overflow_error, + boost::math::policies::underflow_error, + boost::math::policies::denorm_error, + boost::math::policies::pole_error, + boost::math::policies::evaluation_error + > ignore_all_policy; + + typedef policy< + boost::math::policies::domain_error, + boost::math::policies::overflow_error, + boost::math::policies::underflow_error, + boost::math::policies::denorm_error, + boost::math::policies::pole_error, + boost::math::policies::evaluation_error + > throw_all_policy; + + std::vector > invalid_params = {{51., 40., 50.}, + {40., 51., 50.}}; + if (std::numeric_limits::has_quiet_NaN) + { + test_invalid_parameters, + hypergeometric_distribution, + RealType>(invalid_params); + + test_invalid_support, + hypergeometric_distribution, + RealType>({4, 13, 26}); + } } diff --git a/test/test_inverse_gamma_distribution.cpp b/test/test_inverse_gamma_distribution.cpp index 4115e1e0c1..2cfc62284f 100644 --- a/test/test_inverse_gamma_distribution.cpp +++ b/test/test_inverse_gamma_distribution.cpp @@ -30,6 +30,7 @@ using ::boost::math::concepts::real_concept; #include // for test_main #include // for BOOST_CHECK_CLOSE_FRACTION #include "test_out_of_range.hpp" +#include "test_dist_helpers.hpp" #include // for inverse_gamma_distribution using boost::math::inverse_gamma_distribution; @@ -287,7 +288,6 @@ void test_spots(RealType) BOOST_CHECK_EQUAL( cdf(complement(inverse_gamma_distribution(3), static_cast(0))) , static_cast(1)); - BOOST_MATH_CHECK_THROW( pdf( inverse_gamma_distribution(static_cast(-1)), // shape negative. @@ -347,8 +347,58 @@ void test_spots(RealType) quantile(complement( inverse_gamma_distribution(static_cast(8)), static_cast(1.1))), std::domain_error - ); + ); check_out_of_range >(1, 1); + + using boost::math::policies::policy; + + typedef policy< + boost::math::policies::domain_error, + boost::math::policies::overflow_error, + boost::math::policies::underflow_error, + boost::math::policies::denorm_error, + boost::math::policies::pole_error, + boost::math::policies::evaluation_error + > ignore_all_policy; + + std::vector > invalid_params = {{-1, 1}, + {1, -1}, + {-1, -1}}; + test_invalid_parameters >, + inverse_gamma_distribution, + RealType>(invalid_params); + + // Check constructing with NaNs + if (std::numeric_limits::has_quiet_NaN){ + // Attempt to construct from non-finite parameters should throw. + RealType nan = std::numeric_limits::quiet_NaN(); + invalid_params = {{nan, 1}, + {1, nan}, + {nan, nan}}; + test_invalid_parameters >, + inverse_gamma_distribution, + RealType>(invalid_params); + } + + // Check construcing with Infinity + if (std::numeric_limits::has_infinity) + { + // Attempt to construct from non-finite should throw. + RealType inf = std::numeric_limits::infinity(); + invalid_params = {{inf, 1}, + {1, inf}, + {inf, inf}}; + test_invalid_parameters >, + inverse_gamma_distribution, + RealType>(invalid_params); + + } // has_infinity + if (std::numeric_limits::has_quiet_NaN) + { + test_invalid_support >, + inverse_gamma_distribution, + RealType>({1, 1}); + } } // template void test_spots(RealType) BOOST_AUTO_TEST_CASE( test_main ) diff --git a/test/test_inverse_gaussian.cpp b/test/test_inverse_gaussian.cpp index 0fe64223dc..0fc125154d 100644 --- a/test/test_inverse_gaussian.cpp +++ b/test/test_inverse_gaussian.cpp @@ -32,6 +32,7 @@ using boost::math::inverse_gaussian_distribution; using boost::math::inverse_gaussian; #include "test_out_of_range.hpp" +#include "test_dist_helpers.hpp" #include #include @@ -173,6 +174,56 @@ void test_spots(RealType) static_cast(10-3), tolerance); BOOST_CHECK_CLOSE_FRACTION(kurtosis_excess(dist), static_cast(10), tolerance); + + // Check errors + using boost::math::policies::policy; + + typedef policy< + boost::math::policies::domain_error, + boost::math::policies::overflow_error, + boost::math::policies::underflow_error, + boost::math::policies::denorm_error, + boost::math::policies::pole_error, + boost::math::policies::evaluation_error + > ignore_all_policy; + + std::vector > invalid_params = {{0, -1}}; + test_invalid_parameters >, + inverse_gaussian_distribution, + RealType>(invalid_params); + + // Check constructing with NaNs + if (std::numeric_limits::has_quiet_NaN){ + // Attempt to construct from non-finite parameters should throw. + RealType nan = std::numeric_limits::quiet_NaN(); + invalid_params = {{nan, 1}, + {1, nan}, + {nan, nan}}; + test_invalid_parameters >, + inverse_gaussian_distribution, + RealType>(invalid_params); + } + + // Check construcing with Infinity + if (std::numeric_limits::has_infinity) + { + // Attempt to construct from non-finite should throw. + RealType inf = std::numeric_limits::infinity(); + invalid_params = {{inf, 1}, + {1, inf}, + {1, -inf}, + {inf, inf}}; + test_invalid_parameters >, + inverse_gaussian_distribution, + RealType>(invalid_params); + + } // has_infinity + if (std::numeric_limits::has_quiet_NaN) + { + test_invalid_support >, + inverse_gaussian_distribution, + RealType>({1, 1}); + } } // template void test_spots(RealType) BOOST_AUTO_TEST_CASE( test_main )