Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions include/boost/math/distributions/binomial.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ namespace boost
template <class RealType, class Policy>
BOOST_MATH_CUDA_ENABLED inline bool check_dist_and_prob(const char* function, const RealType& N, RealType p, RealType prob, RealType* result, const Policy& pol)
{
if((check_dist(function, N, p, result, pol) && detail::check_probability(function, prob, result, pol)) == false)
if(!(check_dist(function, N, p, result, pol) && detail::check_probability(function, prob, result, pol)))
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't mind this change, but the two lines are equivalent I think, so if we end up with too many of these it gets harder to review the PR.

That said, I wonder if we should just simplify the whole thing down to:

return check_dist(function, N, p, result, pol) && detail::check_probability(function, prob, result, pol);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW I get the point that the others have a missing set of ()'s. I wonder if those would simplify down to one liners too and be easier to read as a result?

return false;
return true;
}
Expand Down Expand Up @@ -321,11 +321,11 @@ namespace boost
BOOST_MATH_STATIC const char* function = "boost::math::binomial_distribution<%1%>::find_lower_bound_on_p";
// Error checks:
RealType result = 0;
if(false == binomial_detail::check_dist_and_k(
if(!(binomial_detail::check_dist_and_k(
function, trials, RealType(0), successes, &result, Policy())
&&
binomial_detail::check_dist_and_prob(
function, trials, RealType(0), probability, &result, Policy()))
function, trials, RealType(0), probability, &result, Policy())))
{ return result; }

if(successes == 0)
Expand All @@ -346,11 +346,11 @@ namespace boost
BOOST_MATH_STATIC const char* function = "boost::math::binomial_distribution<%1%>::find_upper_bound_on_p";
// Error checks:
RealType result = 0;
if(false == binomial_detail::check_dist_and_k(
if(!(binomial_detail::check_dist_and_k(
function, trials, RealType(0), successes, &result, Policy())
&&
binomial_detail::check_dist_and_prob(
function, trials, RealType(0), probability, &result, Policy()))
function, trials, RealType(0), probability, &result, Policy())))
{ return result; }

if(trials == successes)
Expand All @@ -373,11 +373,11 @@ namespace boost
BOOST_MATH_STATIC const char* function = "boost::math::binomial_distribution<%1%>::find_minimum_number_of_trials";
// Error checks:
RealType result = 0;
if(false == binomial_detail::check_dist_and_k(
if(!(binomial_detail::check_dist_and_k(
function, k, p, k, &result, Policy())
&&
binomial_detail::check_dist_and_prob(
function, k, p, alpha, &result, Policy()))
function, k, p, alpha, &result, Policy())))
{ return result; }

result = ibetac_invb(k + 1, p, alpha, Policy()); // returns n - k
Expand All @@ -392,11 +392,11 @@ namespace boost
BOOST_MATH_STATIC const char* function = "boost::math::binomial_distribution<%1%>::find_maximum_number_of_trials";
// Error checks:
RealType result = 0;
if(false == binomial_detail::check_dist_and_k(
if(!(binomial_detail::check_dist_and_k(
function, k, p, k, &result, Policy())
&&
binomial_detail::check_dist_and_prob(
function, k, p, alpha, &result, Policy()))
function, k, p, alpha, &result, Policy())))
{ return result; }

result = ibeta_invb(k + 1, p, alpha, Policy()); // returns n - k
Expand Down
18 changes: 9 additions & 9 deletions include/boost/math/distributions/cauchy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@ BOOST_MATH_GPU_ENABLED RealType cdf_imp(const cauchy_distribution<RealType, Poli
RealType result = 0;
RealType location = dist.location();
RealType scale = dist.scale();
if(false == detail::check_location(function, location, &result, Policy()))
if(!detail::check_location(function, location, &result, Policy()))
{
return result;
}
if(false == detail::check_scale(function, scale, &result, Policy()))
if(!detail::check_scale(function, scale, &result, Policy()))
{
return result;
}
Expand All @@ -84,7 +84,7 @@ BOOST_MATH_GPU_ENABLED RealType cdf_imp(const cauchy_distribution<RealType, Poli
return static_cast<RealType>((complement) ? 1 : 0);
}
#endif
if(false == detail::check_x(function, x, &result, Policy()))
if(!detail::check_x(function, x, &result, Policy()))
{ // Catches x == NaN
return result;
}
Expand All @@ -111,15 +111,15 @@ BOOST_MATH_GPU_ENABLED RealType quantile_imp(
RealType result = 0;
RealType location = dist.location();
RealType scale = dist.scale();
if(false == detail::check_location(function, location, &result, Policy()))
if(!detail::check_location(function, location, &result, Policy()))
{
return result;
}
if(false == detail::check_scale(function, scale, &result, Policy()))
if(!detail::check_scale(function, scale, &result, Policy()))
{
return result;
}
if(false == detail::check_probability(function, p, &result, Policy()))
if(!detail::check_probability(function, p, &result, Policy()))
{
return result;
}
Expand Down Expand Up @@ -224,11 +224,11 @@ BOOST_MATH_GPU_ENABLED inline RealType pdf(const cauchy_distribution<RealType, P
RealType result = 0;
RealType location = dist.location();
RealType scale = dist.scale();
if(false == detail::check_scale(function, scale, &result, Policy()))
if(!detail::check_scale(function, scale, &result, Policy()))
{
return result;
}
if(false == detail::check_location(function, location, &result, Policy()))
if(!detail::check_location(function, location, &result, Policy()))
{
return result;
}
Expand All @@ -242,7 +242,7 @@ BOOST_MATH_GPU_ENABLED inline RealType pdf(const cauchy_distribution<RealType, P
// return 0;
//}

if(false == detail::check_x(function, x, &result, Policy()))
if(!detail::check_x(function, x, &result, Policy()))
{ // Catches x = NaN
return result;
}
Expand Down
14 changes: 6 additions & 8 deletions include/boost/math/distributions/chi_squared.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ BOOST_MATH_GPU_ENABLED RealType pdf(const chi_squared_distribution<RealType, Pol

constexpr auto function = "boost::math::pdf(const chi_squared_distribution<%1%>&, %1%)";

if(false == detail::check_df(
if(!detail::check_df(
function, degrees_of_freedom, &error_result, Policy()))
return error_result;

Expand Down Expand Up @@ -142,7 +142,7 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const chi_squared_distribution<RealTy
RealType error_result;
constexpr auto function = "boost::math::cdf(const chi_squared_distribution<%1%>&, %1%)";

if(false == detail::check_df(
if(!detail::check_df(
function, degrees_of_freedom, &error_result, Policy()))
return error_result;

Expand Down Expand Up @@ -180,7 +180,7 @@ BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type<chi_squared_
constexpr auto function = "boost::math::cdf(const chi_squared_distribution<%1%>&, %1%)";
// Error check:
RealType error_result;
if(false == detail::check_df(
if(!detail::check_df(
function, degrees_of_freedom, &error_result, Policy()))
return error_result;

Expand All @@ -201,8 +201,7 @@ BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type<chi_squ
constexpr auto function = "boost::math::quantile(const chi_squared_distribution<%1%>&, %1%)";
// Error check:
RealType error_result;
if(false == (
detail::check_df(function, degrees_of_freedom, &error_result, Policy())
if (!(detail::check_df(function, degrees_of_freedom, &error_result, Policy())
&& detail::check_probability(function, q, &error_result, Policy()))
)
return error_result;
Expand Down Expand Up @@ -310,9 +309,8 @@ BOOST_MATH_GPU_ENABLED RealType chi_squared_distribution<RealType, Policy>::find
constexpr auto function = "boost::math::chi_squared_distribution<%1%>::find_degrees_of_freedom(%1%,%1%,%1%,%1%,%1%)";
// Check for domain errors:
RealType error_result;
if(false ==
detail::check_probability(function, alpha, &error_result, Policy())
&& detail::check_probability(function, beta, &error_result, Policy()))
if(!(detail::check_probability(function, alpha, &error_result, Policy())
&& detail::check_probability(function, beta, &error_result, Policy())))
{ // Either probability is outside 0 to 1.
return error_result;
}
Expand Down
36 changes: 31 additions & 5 deletions test/test_arcsine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ void test_ignore_policy(RealType)
//std::cout << "pdf(ignore_error_arcsine(-1, +1), std::numeric_limits<RealType>::infinity()) = " << pdf(ignore_error_arcsine(-1, +1), std::numeric_limits<RealType>::infinity()) << std::endl;
// Outputs: pdf(ignore_error_arcsine(-1, +1), std::numeric_limits<RealType>::infinity()) = 1.#QNAN
}
// PDF
BOOST_CHECK((boost::math::isnan)(pdf(ignore_error_arcsine(0, 1), std::numeric_limits<RealType>::infinity()))); // x == infinity
BOOST_CHECK((boost::math::isnan)(pdf(ignore_error_arcsine(-1, 1), std::numeric_limits<RealType>::infinity()))); // x == infinity
BOOST_CHECK((boost::math::isnan)(pdf(ignore_error_arcsine(0, 1), static_cast <RealType>(-2)))); // x < xmin
Expand All @@ -120,9 +121,31 @@ void test_ignore_policy(RealType)
BOOST_CHECK((boost::math::isnan)(logpdf(ignore_error_arcsine(0, 1), static_cast <RealType>(+2)))); // x > x_max
BOOST_CHECK((boost::math::isnan)(logpdf(ignore_error_arcsine(-1, 1), static_cast <RealType>(+2)))); // x > x_max

// CDF
BOOST_CHECK((boost::math::isnan)(cdf(ignore_error_arcsine(0, 1), std::numeric_limits<RealType>::infinity()))); // x == infinity
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My only comment here, is that generally I would prefer to see a BOOST_CHECK_THROW and verify that the correct exception is thrown: as long as we're getting the right error handler called (and hence correct exception thrown) then we know it's guaranteed we'll get a NaN when exceptions are off, where as a NaN when exceptions are off does not guarantee the correct exception type when they're on. Hope that makes sense!

It wouldn't hurt to do both of course, but probably the only time we actually NEED both is to check for the correct sign on infinities when an overflow_error is raised.

One final really picky point: we should really hide use of std::numeric_limits<RealType>::infinity() behind a BOOST_MATH_IF_CONSTEXPR(std::numeric_limits<RealType>::has_infinity), likewise for NaN's.

BOOST_CHECK((boost::math::isnan)(cdf(ignore_error_arcsine(-1, 1), std::numeric_limits<RealType>::infinity()))); // x == infinity
BOOST_CHECK((boost::math::isnan)(cdf(ignore_error_arcsine(0, 1), static_cast <RealType>(-2)))); // x < xmin
BOOST_CHECK((boost::math::isnan)(cdf(ignore_error_arcsine(-1, 1), static_cast <RealType>(-2)))); // x < xmin
BOOST_CHECK((boost::math::isnan)(cdf(ignore_error_arcsine(0, 1), static_cast <RealType>(+2)))); // x > x_max
BOOST_CHECK((boost::math::isnan)(cdf(ignore_error_arcsine(-1, 1), static_cast <RealType>(+2)))); // x > x_max
BOOST_CHECK((boost::math::isnan)(cdf(complement(ignore_error_arcsine(0, 1), std::numeric_limits<RealType>::infinity())))); // x == infinity
BOOST_CHECK((boost::math::isnan)(cdf(complement(ignore_error_arcsine(0, 1), static_cast <RealType>(-2))))); // x < xmin

// Quantile
BOOST_CHECK((boost::math::isnan)(quantile(ignore_error_arcsine(0, 1), std::numeric_limits<RealType>::infinity()))); // p == infinity
BOOST_CHECK((boost::math::isnan)(quantile(ignore_error_arcsine(0, 1), static_cast<RealType>(-1)))); // p < 0
BOOST_CHECK((boost::math::isnan)(quantile(ignore_error_arcsine(0, 1), static_cast<RealType>(2)))); // p > 1
BOOST_CHECK((boost::math::isnan)(quantile(complement(ignore_error_arcsine(0, 1), std::numeric_limits<RealType>::infinity())))); // q == infinity
BOOST_CHECK((boost::math::isnan)(quantile(complement(ignore_error_arcsine(0, 1), static_cast<RealType>(-1))))); // q < 0
BOOST_CHECK((boost::math::isnan)(quantile(complement(ignore_error_arcsine(0, 1), static_cast<RealType>(2))))); // q > 1

// Mean
BOOST_CHECK((boost::math::isnan)(mean(ignore_error_arcsine(-nan, 0))));
BOOST_CHECK((boost::math::isnan)(mean(ignore_error_arcsine(+nan, 0))));

// Median
BOOST_CHECK((boost::math::isnan)(median(ignore_error_arcsine(-nan, 0))));
BOOST_CHECK((boost::math::isnan)(median(ignore_error_arcsine(+nan, 0))));

if (std::numeric_limits<RealType>::has_infinity)
{
Expand Down Expand Up @@ -276,7 +299,8 @@ void test_spots(RealType)
BOOST_CHECK_EQUAL(variance(arcsine_01), 0.125); // 1/8 = 0.125
BOOST_CHECK_CLOSE_FRACTION(standard_deviation(arcsine_01), one_div_root_two<double>() / 2, tolerance); // 1/ sqrt(s) = 0.35355339059327379
BOOST_CHECK_EQUAL(skewness(arcsine_01), 0); //
BOOST_CHECK_EQUAL(kurtosis_excess(arcsine_01), -1.5); // 3/2
BOOST_CHECK_EQUAL(kurtosis_excess(arcsine_01), -1.5); // -3/2
BOOST_CHECK_EQUAL(kurtosis(arcsine_01), 1.5); // 3/2
BOOST_CHECK_EQUAL(support(arcsine_01).first, 0); //
BOOST_CHECK_EQUAL(range(arcsine_01).first, 0); //
BOOST_CHECK_THROW(mode(arcsine_01), std::domain_error); // Two modes at x_min and x_max, so throw instead.
Expand Down Expand Up @@ -374,8 +398,8 @@ void test_spots(RealType)

BOOST_CHECK_EQUAL(variance(as_m11), 0.5); // 1 - (-1) = 2 ^ 2 = 4 /8 = 0.5
BOOST_CHECK_EQUAL(skewness(as_m11), 0); //
BOOST_CHECK_EQUAL(kurtosis_excess(as_m11), -1.5); // 3/2

BOOST_CHECK_EQUAL(kurtosis_excess(as_m11), -1.5); // -3/2
BOOST_CHECK_EQUAL(kurtosis(as_m11), 1.5); // 3/2

BOOST_CHECK_CLOSE_FRACTION(pdf(as_m11, 0.05), static_cast<RealType>(0.31870852113797122803869876869296281629727218095644L), tolerance);
BOOST_CHECK_CLOSE_FRACTION(pdf(as_m11, 0.5), static_cast<RealType>(0.36755259694786136634088433220864629426492432024443L), tolerance);
Expand Down Expand Up @@ -428,7 +452,8 @@ void test_spots(RealType)
BOOST_CHECK_EQUAL(median(as_m2m1), -1.5); // 1 / (1 + 1) = 1/2 exactly.
BOOST_CHECK_EQUAL(variance(as_m2m1), 0.125);
BOOST_CHECK_EQUAL(skewness(as_m2m1), 0); //
BOOST_CHECK_EQUAL(kurtosis_excess(as_m2m1), -1.5); // 3/2
BOOST_CHECK_EQUAL(kurtosis(as_m2m1), 1.5); // 3/2
BOOST_CHECK_EQUAL(kurtosis_excess(as_m2m1), -1.5); // -3/2

BOOST_CHECK_CLOSE_FRACTION(pdf(as_m2m1, -1.95), static_cast<RealType>(1.4605059227421865250256574657088244053723856445614L), 4 * tolerance);
BOOST_CHECK_CLOSE_FRACTION(pdf(as_m2m1, -1.5), static_cast<RealType>(0.63661977236758134307553505349005744813783858296183L), tolerance);
Expand Down Expand Up @@ -615,7 +640,8 @@ void test_spots(RealType)
BOOST_CHECK_EQUAL(variance(as), 0.125); //0.125
BOOST_CHECK_CLOSE_FRACTION(standard_deviation(as), one_div_root_two<double>() / 2, std::numeric_limits<double>::epsilon()); // 0.353553
BOOST_CHECK_EQUAL(skewness(as), 0); //
BOOST_CHECK_EQUAL(kurtosis_excess(as), -1.5); // 3/2
BOOST_CHECK_EQUAL(kurtosis(as), 1.5); // 3/2
BOOST_CHECK_EQUAL(kurtosis_excess(as), -1.5); // -3/2
BOOST_CHECK_EQUAL(support(as).first, 0); //
BOOST_CHECK_EQUAL(range(as).first, 0); //
BOOST_CHECK_THROW(mode(as), std::domain_error); // Two modes at x_min and x_max, so throw instead.
Expand Down
45 changes: 45 additions & 0 deletions test/test_bernoulli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,11 @@ void test_spots(RealType)
bernoulli_distribution<RealType>(static_cast<RealType>(0.4L)), static_cast<RealType>(0)),
static_cast<RealType>(0.6L), tolerance); // Expect 1- p.

BOOST_CHECK_CLOSE_FRACTION(
pdf( // OK k (or n)
bernoulli_distribution<RealType>(static_cast<RealType>(0.4L)), static_cast<RealType>(1)),
static_cast<RealType>(0.4L), tolerance); // Expect p.

BOOST_CHECK_EQUAL(
mean(bernoulli_distribution<RealType>(static_cast<RealType>(0.5L))), static_cast<RealType>(0.5L));

Expand Down Expand Up @@ -280,6 +285,46 @@ void test_spots(RealType)
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::ignore_error>,
boost::math::policies::overflow_error<boost::math::policies::ignore_error>,
boost::math::policies::underflow_error<boost::math::policies::ignore_error>,
boost::math::policies::denorm_error<boost::math::policies::ignore_error>,
boost::math::policies::pole_error<boost::math::policies::ignore_error>,
boost::math::policies::evaluation_error<boost::math::policies::ignore_error>
> ignore_all_policy;

typedef bernoulli_distribution<RealType, ignore_all_policy> ignore_error_bernoulli;

if (std::numeric_limits<RealType>::has_quiet_NaN)
{
// PDF
BOOST_CHECK((boost::math::isnan)(pdf(ignore_error_bernoulli(0.5), std::numeric_limits<RealType>::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<RealType>(0.5)))); // k != 0, 1
BOOST_CHECK((boost::math::isnan)(pdf(ignore_error_bernoulli(0.5), static_cast<RealType>(-0.5)))); // k != 0, 1

// CDF
BOOST_CHECK((boost::math::isnan)(cdf(ignore_error_bernoulli(0.5), std::numeric_limits<RealType>::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<RealType>(0.5)))); // k != 0, 1
BOOST_CHECK((boost::math::isnan)(cdf(ignore_error_bernoulli(0.5), static_cast<RealType>(-0.5)))); // k != 0, 1
BOOST_CHECK((boost::math::isnan)(cdf(complement(ignore_error_bernoulli(0.5), std::numeric_limits<RealType>::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<RealType>(0.5))))); // k != 0, 1
BOOST_CHECK((boost::math::isnan)(cdf(complement(ignore_error_bernoulli(0.5), static_cast<RealType>(-0.5))))); // k != 0, 1

// // Quantile
BOOST_CHECK((boost::math::isnan)(quantile(ignore_error_bernoulli(0.5), std::numeric_limits<RealType>::infinity()))); // p == infinity
BOOST_CHECK((boost::math::isnan)(quantile(ignore_error_bernoulli(0.5), static_cast<RealType>(-1)))); // p < 0
BOOST_CHECK((boost::math::isnan)(quantile(ignore_error_bernoulli(0.5), static_cast<RealType>(2)))); // p > 1
BOOST_CHECK((boost::math::isnan)(quantile(complement(ignore_error_bernoulli(0.5), std::numeric_limits<RealType>::infinity())))); // q == infinity
BOOST_CHECK((boost::math::isnan)(quantile(complement(ignore_error_bernoulli(0.5), static_cast<RealType>(-1))))); // q < 0
BOOST_CHECK((boost::math::isnan)(quantile(complement(ignore_error_bernoulli(0.5), static_cast<RealType>(2))))); // q > 1

} // has_quiet_NaN
} // template <class RealType>void test_spots(RealType)

BOOST_AUTO_TEST_CASE( test_main )
Expand Down
Loading
Loading