From 6f59f3852acd161d56eaa04540bcc0b59b5bdd4f Mon Sep 17 00:00:00 2001 From: jzmaddock Date: Wed, 11 Mar 2026 16:39:39 +0000 Subject: [PATCH 1/2] Correct ellint_2 for N * PI / 2 phi argument. Fixes https://github.com/boostorg/math/issues/1377. --- include/boost/math/special_functions/ellint_2.hpp | 12 +++++++++--- test/test_ellint_2.hpp | 6 +++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/include/boost/math/special_functions/ellint_2.hpp b/include/boost/math/special_functions/ellint_2.hpp index 0cc1fa0944..76aff168de 100644 --- a/include/boost/math/special_functions/ellint_2.hpp +++ b/include/boost/math/special_functions/ellint_2.hpp @@ -136,9 +136,15 @@ BOOST_MATH_GPU_ENABLED T ellint_e_imp(T phi, T k, const Policy& pol) return policies::raise_domain_error("boost::math::ellint_2<%1%>(%1%, %1%)", "The parameter k is out of range, got k = %1%", k, pol); } T cosp = cos(rphi); - T c = 1 / (sinp * sinp); - T cm1 = cosp * cosp / (sinp * sinp); // c - 1 - result = s * ((1 - k2) * ellint_rf_imp(cm1, T(c - k2), c, pol) + k2 * (1 - k2) * ellint_rd(cm1, c, T(c - k2), pol) / 3 + k2 * sqrt(cm1 / (c * (c - k2)))); + T c = sinp * sinp; + if (c > tools::min_value()) + { + c = 1 / c; + T cm1 = cosp * cosp / (sinp * sinp); // c - 1 + result = s * ((1 - k2) * ellint_rf_imp(cm1, T(c - k2), c, pol) + k2 * (1 - k2) * ellint_rd(cm1, c, T(c - k2), pol) / 3 + k2 * sqrt(cm1 / (c * (c - k2)))); + } + else + result = 0; } if (m != 0) { diff --git a/test/test_ellint_2.hpp b/test/test_ellint_2.hpp index 29a73c9961..3b565a493d 100644 --- a/test/test_ellint_2.hpp +++ b/test/test_ellint_2.hpp @@ -97,7 +97,7 @@ void test_spots(T, const char* type_name) // called a second time. // #ifndef TEST_UDT - static const std::array, 28> data1 = {{ + static const std::array, 31> data1 = {{ {{ SC_(0.0), SC_(0.0), SC_(0.0) }}, {{ SC_(-10.0), SC_(0.0), SC_(-10.0) }}, {{ SC_(-1.0), SC_(-1.0), SC_(-0.84147098480789650665250232163029899962256306079837) }}, @@ -127,6 +127,10 @@ void test_spots(T, const char* type_name) {{ -2 * boost::math::constants::pi(), SC_(1.0), SC_(-4.0) }}, {{ -(20 * boost::math::constants::pi()) / 21, SC_(1.0), SC_(-1.85095773382382555307064528472278244309033056100177750424044959888147151556780639619867349409562910808166870200808) }}, {{ -(20 * boost::math::constants::pi()) / 19, SC_(1.0), SC_(-2.16459459028073389414365205908793841951217248335965412335147127404907690285247170629778731438009399303864259295133) }}, + // Test at n * pi / 2, see https://github.com/boostorg/math/issues/1377 + {{ boost::math::constants::half_pi(), SC_(0.25), boost::math::ellint_2(static_cast(0.25)) }}, + {{ 3 * boost::math::constants::half_pi(), SC_(0.25), 3 * boost::math::ellint_2(static_cast(0.25)) }}, + {{ 6 * boost::math::constants::half_pi(), SC_(0.25), 6 * boost::math::ellint_2(static_cast(0.25)) }}, }}; do_test_ellint_e2(data1, type_name, "Elliptic Integral E: Mathworld Data"); From c793e1cd1b4ad84dfdb5bcd551857a951ca4556d Mon Sep 17 00:00:00 2001 From: jzmaddock Date: Thu, 12 Mar 2026 10:22:45 +0000 Subject: [PATCH 2/2] Ellint2: Simplify fix. --- include/boost/math/special_functions/ellint_2.hpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/include/boost/math/special_functions/ellint_2.hpp b/include/boost/math/special_functions/ellint_2.hpp index 76aff168de..501d36b66b 100644 --- a/include/boost/math/special_functions/ellint_2.hpp +++ b/include/boost/math/special_functions/ellint_2.hpp @@ -122,7 +122,7 @@ BOOST_MATH_GPU_ENABLED T ellint_e_imp(T phi, T k, const Policy& pol) rphi = constants::half_pi() - rphi; } T k2 = k * k; - if(boost::math::pow<3>(rphi) * k2 / 6 < tools::epsilon() * fabs(rphi)) + if(boost::math::pow<3>(rphi) * k2 / 6 <= tools::epsilon() * fabs(rphi)) { // See http://functions.wolfram.com/EllipticIntegrals/EllipticE2/06/01/03/0001/ result = s * rphi; @@ -136,15 +136,9 @@ BOOST_MATH_GPU_ENABLED T ellint_e_imp(T phi, T k, const Policy& pol) return policies::raise_domain_error("boost::math::ellint_2<%1%>(%1%, %1%)", "The parameter k is out of range, got k = %1%", k, pol); } T cosp = cos(rphi); - T c = sinp * sinp; - if (c > tools::min_value()) - { - c = 1 / c; - T cm1 = cosp * cosp / (sinp * sinp); // c - 1 - result = s * ((1 - k2) * ellint_rf_imp(cm1, T(c - k2), c, pol) + k2 * (1 - k2) * ellint_rd(cm1, c, T(c - k2), pol) / 3 + k2 * sqrt(cm1 / (c * (c - k2)))); - } - else - result = 0; + T c = 1 / (sinp * sinp); + T cm1 = cosp * cosp / (sinp * sinp); // c - 1 + result = s * ((1 - k2) * ellint_rf_imp(cm1, T(c - k2), c, pol) + k2 * (1 - k2) * ellint_rd(cm1, c, T(c - k2), pol) / 3 + k2 * sqrt(cm1 / (c * (c - k2)))); } if (m != 0) {