#9042 closed Bugs (fixed)
boost::math, cdf(complement(normal_distribution<>(...)) fails to catch invalid scale and location parameters
Reported by: | Owned by: | John Maddock | |
---|---|---|---|
Milestone: | To Be Determined | Component: | math |
Version: | Boost 1.54.0 | Severity: | Problem |
Keywords: | Cc: |
Description
In boost/math/distributions/normal.hpp:
template <class RealType, class Policy> inline RealType cdf(const complemented2_type<normal_distribution<RealType, Policy>, RealType>& c) { BOOST_MATH_STD_USING // for ADL of std functions RealType sd = c.dist.standard_deviation(); RealType mean = c.dist.mean(); RealType x = c.param; static const char* function = "boost::math::cdf(const complement(normal_distribution<%1%>&), %1%)"; if((boost::math::isinf)(x)) { if(x < 0) return 1; // cdf complement -infinity is unity. return 0; // cdf complement +infinity is zero } // These produce MSVC 4127 warnings, so the above used instead. //if(std::numeric_limits<RealType>::has_infinity && x == std::numeric_limits<RealType>::infinity()) //{ // cdf complement +infinity is zero. // return 0; //} //if(std::numeric_limits<RealType>::has_infinity && x == -std::numeric_limits<RealType>::infinity()) //{ // cdf complement -infinity is unity. // return 1; //} RealType result = 0; if(false == detail::check_scale(function, sd, &result, Policy())) return result; if(false == detail::check_location(function, mean, &result, Policy())) return result; if(false == detail::check_x(function, x, &result, Policy())) return result; RealType diff = (x - mean) / (sd * constants::root_two<RealType>()); result = boost::math::erfc(diff, Policy()) / 2; return result; } // cdf complement
The test if((boost::math::isinf)(x)) occurs before check_scale() or check_location() is called, returning 1 or 0 for infinite x, even if sd or mean are invalid.
The calls to check_scale() and check_location() should be moved up just before the test if((boost::math::isinf)(x)).
See, for example, how the tests are ordered here:
template <class RealType, class Policy> inline RealType cdf(const normal_distribution<RealType, Policy>& dist, const RealType& x) { BOOST_MATH_STD_USING // for ADL of std functions RealType sd = dist.standard_deviation(); RealType mean = dist.mean(); static const char* function = "boost::math::cdf(const normal_distribution<%1%>&, %1%)"; RealType result = 0; if(false == detail::check_scale(function, sd, &result, Policy())) { return result; } if(false == detail::check_location(function, mean, &result, Policy())) { return result; } if((boost::math::isinf)(x)) { if(x < 0) return 0; // -infinity return 1; // + infinity } // These produce MSVC 4127 warnings, so the above used instead. //if(std::numeric_limits<RealType>::has_infinity && x == std::numeric_limits<RealType>::infinity()) //{ // cdf +infinity is unity. // return 1; //} //if(std::numeric_limits<RealType>::has_infinity && x == -std::numeric_limits<RealType>::infinity()) //{ // cdf -infinity is zero. // return 0; //} if(false == detail::check_x(function, x, &result, Policy())) { return result; } RealType diff = (x - mean) / (sd * constants::root_two<RealType>()); result = boost::math::erfc(-diff, Policy()) / 2; return result; } // cdf
Note:
See TracTickets
for help on using tickets.
(In [85601]) Fix order of error checks. Fixes #9042.