From 73a01fcfe995e3f3ff1a851be99b0764b5005b85 Mon Sep 17 00:00:00 2001 From: Nicholas McKibben Date: Sat, 4 Feb 2023 22:14:37 -0700 Subject: [PATCH 1/4] FIX: avoid overflow on overflow check in halley_step on Apple M1 --- include/boost/math/tools/roots.hpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/boost/math/tools/roots.hpp b/include/boost/math/tools/roots.hpp index 6493e81228..5e4290703f 100644 --- a/include/boost/math/tools/roots.hpp +++ b/include/boost/math/tools/roots.hpp @@ -354,7 +354,12 @@ namespace detail { BOOST_MATH_INSTRUMENT_VARIABLE(denom); BOOST_MATH_INSTRUMENT_VARIABLE(num); - if ((fabs(num) < 1) && (fabs(denom) >= fabs(num) * tools::max_value())) + // denom/num overflows if: + // |denom| >= |num| * max_value + // RHS may overflow on Apple M1, so rearrange: + // |denom| * 1/max_value >= |num| + static const T inv_max_value = 1.0 / tools::max_value(); + if ((fabs(num) < 1) && (inv_max_value * fabs(denom) >= fabs(num))) { // possible overflow, use Newton step: delta = f0 / f1; From 9fc329a3d220c40f2123c60edc3f50a0faff33d4 Mon Sep 17 00:00:00 2001 From: Nicholas McKibben Date: Sat, 4 Feb 2023 22:16:41 -0700 Subject: [PATCH 2/4] FIX: avoid overflow on overflow check in toms748_solve safe_div --- include/boost/math/tools/toms748_solve.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/boost/math/tools/toms748_solve.hpp b/include/boost/math/tools/toms748_solve.hpp index 2de491a951..15599e8297 100644 --- a/include/boost/math/tools/toms748_solve.hpp +++ b/include/boost/math/tools/toms748_solve.hpp @@ -160,7 +160,8 @@ inline T safe_div(T num, T denom, T r) if(fabs(denom) < 1) { - if(fabs(denom * tools::max_value()) <= fabs(num)) + static const T inv_max_value = 1.0 / tools::max_value(); + if(fabs(denom) <= inv_max_value * fabs(num)) return r; } return num / denom; From c80af8e8997f4d83677e67cc3d4d5daa01a733f3 Mon Sep 17 00:00:00 2001 From: Nicholas McKibben Date: Sat, 4 Feb 2023 22:43:51 -0700 Subject: [PATCH 3/4] FIX: avoid overflow on overflow check in gamma_p_derivative_imp --- include/boost/math/special_functions/gamma.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/boost/math/special_functions/gamma.hpp b/include/boost/math/special_functions/gamma.hpp index 68afe66e30..efd9eef713 100644 --- a/include/boost/math/special_functions/gamma.hpp +++ b/include/boost/math/special_functions/gamma.hpp @@ -1795,7 +1795,8 @@ T gamma_p_derivative_imp(T a, T x, const Policy& pol) // typedef typename lanczos::lanczos::type lanczos_type; T f1 = detail::regularised_gamma_prefix(a, x, pol, lanczos_type()); - if((x < 1) && (tools::max_value() * x < f1)) + static const T inv_max_value = 1.0 / tools::max_value(); + if((x < 1) && (x < inv_max_value * f1)) { // overflow: return policies::raise_overflow_error("boost::math::gamma_p_derivative<%1%>(%1%, %1%)", nullptr, pol); From 3f76cce432012422df18e5693c9539853e37d4c0 Mon Sep 17 00:00:00 2001 From: Nicholas McKibben Date: Sat, 4 Feb 2023 23:40:45 -0700 Subject: [PATCH 4/4] FIX: avoid data-dependent overflow in halley_step --- include/boost/math/tools/roots.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/boost/math/tools/roots.hpp b/include/boost/math/tools/roots.hpp index 5e4290703f..d62ee8dbf9 100644 --- a/include/boost/math/tools/roots.hpp +++ b/include/boost/math/tools/roots.hpp @@ -652,7 +652,9 @@ namespace detail { } else if (result > max) { - T diff = ((fabs(max) < 1) && (fabs(result) > 1) && (tools::max_value() / fabs(result) < fabs(max))) ? T(1000) : T(result / max); + const T amax = fabs(max); + volatile const T aresult = fabs(result); // volatile: force compiler to honor data-dependency in chained bool exprs below + T diff = ((amax < 1) && (aresult > 1) && (tools::max_value() / aresult < amax)) ? T(1000) : T(result / max); if (fabs(diff) < 1) diff = 1 / diff; if (!out_of_bounds_sentry && (diff > 0) && (diff < 3))