id summary reporter owner description type status milestone component version severity resolution keywords cc 9042 boost::math, cdf(complement(normal_distribution<>(...)) fails to catch invalid scale and location parameters Paul McClellan John Maddock "In boost/math/distributions/normal.hpp: {{{ template inline RealType cdf(const complemented2_type, 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::has_infinity && x == std::numeric_limits::infinity()) //{ // cdf complement +infinity is zero. // return 0; //} //if(std::numeric_limits::has_infinity && x == -std::numeric_limits::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()); 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 inline RealType cdf(const normal_distribution& 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::has_infinity && x == std::numeric_limits::infinity()) //{ // cdf +infinity is unity. // return 1; //} //if(std::numeric_limits::has_infinity && x == -std::numeric_limits::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()); result = boost::math::erfc(-diff, Policy()) / 2; return result; } // cdf }}} " Bugs closed To Be Determined math Boost 1.54.0 Problem fixed