diff --git a/include/boost/math/distributions/cauchy.hpp b/include/boost/math/distributions/cauchy.hpp index 3a5af69e43..c0c76addf7 100644 --- a/include/boost/math/distributions/cauchy.hpp +++ b/include/boost/math/distributions/cauchy.hpp @@ -45,23 +45,11 @@ BOOST_MATH_GPU_ENABLED RealType cdf_imp(const cauchy_distribution -INF. - // - // Recall that for x < 0: - // - // atan(x) = -pi/2 - atan(1/x) - // - // Substituting into the above we get: - // - // CDF = -atan(1/x)/pi ; x < 0 - // - // So the procedure is to calculate the cdf for -fabs(x) - // using the above formula, and then subtract from 1 when required - // to get the result. + // where x is the standardized (i.e. shifted and scaled) domain variable. // BOOST_MATH_STD_USING // for ADL of std functions constexpr auto function = "boost::math::cdf(cauchy<%1%>&, %1%)"; @@ -99,13 +87,8 @@ BOOST_MATH_GPU_ENABLED RealType cdf_imp(const cauchy_distribution 0 - if(mx > -tools::epsilon() / 8) - { // special case first: x extremely close to location. - return static_cast(0.5f); - } - result = -atan(1 / mx) / constants::pi(); - return (((x > location) != complement) ? 1 - result : result); + RealType x_std = static_cast((complement) ? 1 : -1)*(x - location) / scale; + return atan2(static_cast(1), x_std) / constants::pi(); } // cdf template diff --git a/test/test_cauchy.cpp b/test/test_cauchy.cpp index f5893264a6..f2d3d6b250 100644 --- a/test/test_cauchy.cpp +++ b/test/test_cauchy.cpp @@ -124,6 +124,22 @@ void test_spots(RealType T) static_cast(-10.0)), // x static_cast(0.031725517430553569514977118601302L), // probability. tolerance); // % + BOOST_CHECK_CLOSE( + ::boost::math::cdf( + cauchy_distribution(), + static_cast(-15000000.0)), + static_cast(0.000000021220659078919346664504384865488560725L), + tolerance); // % + BOOST_CHECK_CLOSE( + // Test the CDF at -max_value()/4. + // For an input x of this magnitude, the reference value is 4/|x|/pi. + ::boost::math::cdf( + cauchy_distribution(), + -boost::math::tools::max_value()/4), + static_cast(4) + / boost::math::tools::max_value() + / boost::math::constants::pi(), + tolerance); // % // // Complements: @@ -188,6 +204,22 @@ void test_spots(RealType T) static_cast(-10.0))), // x static_cast(0.9682744825694464304850228813987L), // probability. tolerance); // % + BOOST_CHECK_CLOSE( + ::boost::math::cdf( + complement(cauchy_distribution(), + static_cast(15000000.0))), + static_cast(0.000000021220659078919346664504384865488560725L), + tolerance); // % + BOOST_CHECK_CLOSE( + // Test the complemented CDF at max_value()/4. + // For an input x of this magnitude, the reference value is 4/x/pi. + ::boost::math::cdf( + complement(cauchy_distribution(), + boost::math::tools::max_value()/4)), + static_cast(4) + / boost::math::tools::max_value() + / boost::math::constants::pi(), + tolerance); // % // // Quantiles: