diff --git a/include/boost/decimal/decimal128.hpp b/include/boost/decimal/decimal128.hpp index 1da9b031b..9639eb409 100644 --- a/include/boost/decimal/decimal128.hpp +++ b/include/boost/decimal/decimal128.hpp @@ -1122,21 +1122,37 @@ constexpr auto signbit BOOST_DECIMAL_PREVENT_MACRO_SUBSTITUTION (decimal128 rhs) constexpr auto isnan BOOST_DECIMAL_PREVENT_MACRO_SUBSTITUTION (decimal128 rhs) noexcept -> bool { + #ifndef BOOST_DECIMAL_FAST_MATH return (rhs.bits_.high & detail::d128_nan_mask_high_bits) == detail::d128_nan_mask_high_bits; + #else + static_cast(rhs); + return false; + #endif } constexpr auto isinf BOOST_DECIMAL_PREVENT_MACRO_SUBSTITUTION (decimal128 rhs) noexcept -> bool { + #ifndef BOOST_DECIMAL_FAST_MATH return (rhs.bits_.high & detail::d128_nan_mask_high_bits) == detail::d128_inf_mask_high_bits; + #else + static_cast(rhs); + return false; + #endif } constexpr auto issignaling BOOST_DECIMAL_PREVENT_MACRO_SUBSTITUTION (decimal128 rhs) noexcept -> bool { + #ifndef BOOST_DECIMAL_FAST_MATH return (rhs.bits_.high & detail::d128_snan_mask_high_bits) == detail::d128_snan_mask_high_bits; + #else + static_cast(rhs); + return false; + #endif } constexpr auto isnormal BOOST_DECIMAL_PREVENT_MACRO_SUBSTITUTION (decimal128 rhs) noexcept -> bool { + #ifndef BOOST_DECIMAL_FAST_MATH // Check for de-normals const auto sig {rhs.full_significand()}; const auto exp {rhs.unbiased_exponent()}; @@ -1147,16 +1163,29 @@ constexpr auto isnormal BOOST_DECIMAL_PREVENT_MACRO_SUBSTITUTION (decimal128 rhs } return (sig != 0) && isfinite(rhs); + #else + return rhs.full_significand() != 0; + #endif } constexpr auto isfinite BOOST_DECIMAL_PREVENT_MACRO_SUBSTITUTION (decimal128 rhs) noexcept -> bool { + #ifndef BOOST_DECIMAL_FAST_MATH return (rhs.bits_.high & detail::d128_inf_mask_high_bits) != detail::d128_inf_mask_high_bits; + #else + static_cast(rhs); + return true; + #endif } constexpr auto not_finite(decimal128 rhs) noexcept -> bool { + #ifndef BOOST_DECIMAL_FAST_MATH return (rhs.bits_.high & detail::d128_inf_mask_high_bits) == detail::d128_inf_mask_high_bits; + #else + static_cast(rhs); + return false; + #endif } constexpr auto operator+(decimal128 rhs) noexcept -> decimal128 diff --git a/include/boost/decimal/decimal128_fast.hpp b/include/boost/decimal/decimal128_fast.hpp index 655669f95..f4bd65d52 100644 --- a/include/boost/decimal/decimal128_fast.hpp +++ b/include/boost/decimal/decimal128_fast.hpp @@ -468,37 +468,66 @@ constexpr auto signbit(decimal128_fast val) noexcept -> bool constexpr auto isinf(decimal128_fast val) noexcept -> bool { + #ifndef BOOST_DECIMAL_FAST_MATH return val.significand_.high == detail::d128_fast_inf_high_bits; + #else + static_cast(val); + return false; + #endif } constexpr auto isnan(decimal128_fast val) noexcept -> bool { + #ifndef BOOST_DECIMAL_FAST_MATH return val.significand_.high >= detail::d128_fast_qnan_high_bits; + #else + static_cast(val); + return false; + #endif } constexpr auto issignaling(decimal128_fast val) noexcept -> bool { + #ifndef BOOST_DECIMAL_FAST_MATH return val.significand_.high == detail::d128_fast_snan_high_bits; + #else + static_cast(val); + return false; + #endif } constexpr auto isnormal(decimal128_fast val) noexcept -> bool { + #ifndef BOOST_DECIMAL_FAST_MATH if (val.exponent_ <= static_cast(detail::precision_v - 1)) { return false; } return (val.significand_ != 0) && isfinite(val); + #else + return val.significand_ != 0; + #endif } constexpr auto isfinite(decimal128_fast val) noexcept -> bool { + #ifndef BOOST_DECIMAL_FAST_MATH return val.significand_.high < detail::d128_fast_inf_high_bits; + #else + static_cast(val); + return true; + #endif } constexpr auto not_finite(const decimal128_fast& val) noexcept -> bool { + #ifndef BOOST_DECIMAL_FAST_MATH return val.significand_.high >= detail::d128_fast_inf_high_bits; + #else + static_cast(val); + return false; + #endif } constexpr auto operator==(const decimal128_fast& lhs, const decimal128_fast& rhs) noexcept -> bool diff --git a/include/boost/decimal/decimal32.hpp b/include/boost/decimal/decimal32.hpp index 00accccdd..df4e36291 100644 --- a/include/boost/decimal/decimal32.hpp +++ b/include/boost/decimal/decimal32.hpp @@ -805,26 +805,47 @@ constexpr auto signbit BOOST_DECIMAL_PREVENT_MACRO_SUBSTITUTION (decimal32 rhs) constexpr auto isnan BOOST_DECIMAL_PREVENT_MACRO_SUBSTITUTION (decimal32 rhs) noexcept -> bool { + #ifndef BOOST_DECIMAL_FAST_MATH return (rhs.bits_ & detail::d32_nan_mask) == detail::d32_nan_mask; + #else + static_cast(rhs); + return false; + #endif } constexpr auto issignaling BOOST_DECIMAL_PREVENT_MACRO_SUBSTITUTION (decimal32 rhs) noexcept -> bool { + #ifndef BOOST_DECIMAL_FAST_MATH return (rhs.bits_ & detail::d32_snan_mask) == detail::d32_snan_mask; + #else + static_cast(rhs); + return false; + #endif } constexpr auto isinf BOOST_DECIMAL_PREVENT_MACRO_SUBSTITUTION (decimal32 rhs) noexcept -> bool { + #ifndef BOOST_DECIMAL_FAST_MATH return ((rhs.bits_ & detail::d32_nan_mask) == detail::d32_inf_mask); + #else + static_cast(rhs); + return false; + #endif } constexpr auto isfinite BOOST_DECIMAL_PREVENT_MACRO_SUBSTITUTION (decimal32 rhs) noexcept -> bool { + #ifndef BOOST_DECIMAL_FAST_MATH return ((rhs.bits_ & detail::d32_inf_mask) != detail::d32_inf_mask); + #else + static_cast(rhs); + return false; + #endif } constexpr auto isnormal BOOST_DECIMAL_PREVENT_MACRO_SUBSTITUTION (decimal32 rhs) noexcept -> bool { + #ifndef BOOST_DECIMAL_FAST_MATH // Check for de-normals const auto sig {rhs.full_significand()}; const auto exp {rhs.unbiased_exponent()}; @@ -835,6 +856,9 @@ constexpr auto isnormal BOOST_DECIMAL_PREVENT_MACRO_SUBSTITUTION (decimal32 rhs) } return (sig != 0) && isfinite(rhs); + #else + return rhs.full_significand() != 0; + #endif } constexpr auto operator+(decimal32 rhs) noexcept -> decimal32 diff --git a/include/boost/decimal/decimal32_fast.hpp b/include/boost/decimal/decimal32_fast.hpp index 348e84dcd..b650ff2d7 100644 --- a/include/boost/decimal/decimal32_fast.hpp +++ b/include/boost/decimal/decimal32_fast.hpp @@ -453,22 +453,41 @@ constexpr auto signbit(decimal32_fast val) noexcept -> bool constexpr auto isinf(decimal32_fast val) noexcept -> bool { + #ifndef BOOST_DECIMAL_FAST_MATH return val.significand_ == detail::d32_fast_inf; + #else + static_cast(val); + return false; + #endif } constexpr auto isnan(decimal32_fast val) noexcept -> bool { + #ifndef BOOST_DECIMAL_FAST_MATH return val.significand_ == detail::d32_fast_qnan || val.significand_ == detail::d32_fast_snan; + #else + static_cast(val); + return false; + #endif } constexpr auto issignaling(decimal32_fast val) noexcept -> bool { + #ifndef BOOST_DECIMAL_FAST_MATH return val.significand_ == detail::d32_fast_snan; + #else + static_cast(val); + return false; + #endif } constexpr auto isnormal(decimal32_fast val) noexcept -> bool { - return (val.significand_ != 0) && isfinite(val) && (val.exponent_ > static_cast(detail::precision_v - 1)); + return (val.significand_ != 0) + #ifndef BOOST_DECIMAL_FAST_MATH + && isfinite(val) && (val.exponent_ > static_cast(detail::precision_v - 1)) + #endif + ; } constexpr auto isfinite(decimal32_fast val) noexcept -> bool diff --git a/include/boost/decimal/decimal64.hpp b/include/boost/decimal/decimal64.hpp index 95df42edd..59e5e64df 100644 --- a/include/boost/decimal/decimal64.hpp +++ b/include/boost/decimal/decimal64.hpp @@ -1082,21 +1082,37 @@ constexpr auto signbit BOOST_DECIMAL_PREVENT_MACRO_SUBSTITUTION (decimal64 rhs) constexpr auto isnan BOOST_DECIMAL_PREVENT_MACRO_SUBSTITUTION (decimal64 rhs) noexcept -> bool { + #ifndef BOOST_DECIMAL_FAST_MATH return (rhs.bits_ & detail::d64_nan_mask) == detail::d64_nan_mask; + #else + static_cast(rhs); + return false; + #endif } constexpr auto isinf BOOST_DECIMAL_PREVENT_MACRO_SUBSTITUTION (decimal64 rhs) noexcept -> bool { + #ifndef BOOST_DECIMAL_FAST_MATH return ((rhs.bits_ & detail::d64_nan_mask) == detail::d64_inf_mask); + #else + static_cast(rhs); + return false; + #endif } constexpr auto issignaling BOOST_DECIMAL_PREVENT_MACRO_SUBSTITUTION (decimal64 rhs) noexcept -> bool { + #ifndef BOOST_DECIMAL_FAST_MATH return (rhs.bits_ & detail::d64_snan_mask) == detail::d64_snan_mask; + #else + static_cast(rhs); + return false; + #endif } constexpr auto isnormal BOOST_DECIMAL_PREVENT_MACRO_SUBSTITUTION (decimal64 rhs) noexcept -> bool { + #ifndef BOOST_DECIMAL_FAST_MATH // Check for de-normals const auto sig {rhs.full_significand()}; const auto exp {rhs.unbiased_exponent()}; @@ -1107,16 +1123,29 @@ constexpr auto isnormal BOOST_DECIMAL_PREVENT_MACRO_SUBSTITUTION (decimal64 rhs) } return (sig != 0) && isfinite(rhs); + #else + return rhs.full_significand() != 0; + #endif } constexpr auto isfinite BOOST_DECIMAL_PREVENT_MACRO_SUBSTITUTION (decimal64 rhs) noexcept -> bool { + #ifndef BOOST_DECIMAL_FAST_MATH return ((rhs.bits_ & detail::d64_inf_mask) != detail::d64_inf_mask); + #else + static_cast(rhs); + return true; + #endif } constexpr auto not_finite(decimal64 rhs) noexcept -> bool { + #ifndef BOOST_DECIMAL_FAST_MATH return ((rhs.bits_ & detail::d64_inf_mask) == detail::d64_inf_mask); + #else + static_cast(rhs); + return false; + #endif } constexpr auto operator+(decimal64 rhs) noexcept -> decimal64 diff --git a/include/boost/decimal/decimal64_fast.hpp b/include/boost/decimal/decimal64_fast.hpp index 1d3742dbb..5a30f1a65 100644 --- a/include/boost/decimal/decimal64_fast.hpp +++ b/include/boost/decimal/decimal64_fast.hpp @@ -458,28 +458,47 @@ constexpr auto signbit(decimal64_fast val) noexcept -> bool constexpr auto isinf(decimal64_fast val) noexcept -> bool { + #ifndef BOOST_DECIMAL_FAST_MATH return val.significand_ == detail::d64_fast_inf; + #else + static_cast(val); + return false; + #endif } constexpr auto isnan(decimal64_fast val) noexcept -> bool { + #ifndef BOOST_DECIMAL_FAST_MATH return val.significand_ == detail::d64_fast_qnan || val.significand_ == detail::d64_fast_snan; + #else + static_cast(val); + return false; + #endif } constexpr auto issignaling(decimal64_fast val) noexcept -> bool { + #ifndef BOOST_DECIMAL_FAST_MATH return val.significand_ == detail::d64_fast_snan; + #else + static_cast(val); + return false; + #endif } constexpr auto isnormal(decimal64_fast val) noexcept -> bool { + #ifndef BOOST_DECIMAL_FAST_MATH if (val.exponent_ <= static_cast(detail::precision_v - 1)) { return false; } return (val.significand_ != 0) && isfinite(val); + #else + return val.significand_ != 0; + #endif } constexpr auto isfinite(decimal64_fast val) noexcept -> bool diff --git a/include/boost/decimal/detail/cmath/acos.hpp b/include/boost/decimal/detail/cmath/acos.hpp index 72e2de3fe..2760d1c9e 100644 --- a/include/boost/decimal/detail/cmath/acos.hpp +++ b/include/boost/decimal/detail/cmath/acos.hpp @@ -30,10 +30,12 @@ template constexpr auto acos_impl(T x) noexcept BOOST_DECIMAL_REQUIRES(detail::is_decimal_floating_point_v, T) { + #ifndef BOOST_DECIMAL_FAST_MATH if (isnan(x)) { return x; } + #endif constexpr auto half_pi {numbers::pi_v / 2}; const auto absx {fabs(static_cast(x))}; diff --git a/include/boost/decimal/detail/cmath/acosh.hpp b/include/boost/decimal/detail/cmath/acosh.hpp index eebdb9ac1..1a1176a6a 100644 --- a/include/boost/decimal/detail/cmath/acosh.hpp +++ b/include/boost/decimal/detail/cmath/acosh.hpp @@ -30,6 +30,7 @@ constexpr auto acosh_impl(T x) noexcept T result { }; + #ifndef BOOST_DECIMAL_FAST_MATH if (fpc != FP_NORMAL) { if ((fpc == FP_INFINITE) && (!signbit(x))) @@ -45,6 +46,12 @@ constexpr auto acosh_impl(T x) noexcept result = x; } } + #else + if (fpc == FP_ZERO) + { + result = T{0, 0}; + } + #endif else { constexpr T one { 1, 0 }; diff --git a/include/boost/decimal/detail/cmath/asin.hpp b/include/boost/decimal/detail/cmath/asin.hpp index 7821f533e..256b3e17e 100644 --- a/include/boost/decimal/detail/cmath/asin.hpp +++ b/include/boost/decimal/detail/cmath/asin.hpp @@ -32,7 +32,11 @@ constexpr auto asin_impl(T x) noexcept const auto fpc {fpclassify(x)}; const auto isneg {signbit(x)}; - if (fpc == FP_ZERO || fpc == FP_NAN) + if (fpc == FP_ZERO + #ifndef BOOST_DECIMAL_FAST_MATH + || fpc == FP_NAN + #endif + ) { return x; } @@ -55,7 +59,11 @@ constexpr auto asin_impl(T x) noexcept } else { + #ifndef BOOST_DECIMAL_FAST_MATH result = std::numeric_limits::quiet_NaN(); + #else + result = T{0}; + #endif } // arcsin(-x) == -arcsin(x) diff --git a/include/boost/decimal/detail/cmath/atan.hpp b/include/boost/decimal/detail/cmath/atan.hpp index 1682d1bca..26fd3edd8 100644 --- a/include/boost/decimal/detail/cmath/atan.hpp +++ b/include/boost/decimal/detail/cmath/atan.hpp @@ -33,7 +33,11 @@ constexpr auto atan_impl(T x) noexcept constexpr T my_pi_half { numbers::pi_v / 2 }; - if (fpc == FP_ZERO || fpc == FP_NAN) + if (fpc == FP_ZERO + #ifndef BOOST_DECIMAL_FAST_MATH + || fpc == FP_NAN + #endif + ) { result = x; } @@ -41,10 +45,12 @@ constexpr auto atan_impl(T x) noexcept { result = -atan_impl(-x); } + #ifndef BOOST_DECIMAL_FAST_MATH else if (fpc == FP_INFINITE) { result = my_pi_half; } + #endif else { constexpr T one { 1 }; diff --git a/include/boost/decimal/detail/cmath/atan2.hpp b/include/boost/decimal/detail/cmath/atan2.hpp index a461970c5..144c3c9f9 100644 --- a/include/boost/decimal/detail/cmath/atan2.hpp +++ b/include/boost/decimal/detail/cmath/atan2.hpp @@ -51,6 +51,7 @@ constexpr auto atan2_impl(T y, T x) noexcept T result { }; + #ifndef BOOST_DECIMAL_FAST_MATH if (fpcx == FP_NAN) { result = x; @@ -59,7 +60,9 @@ constexpr auto atan2_impl(T y, T x) noexcept { result = y; } - else if (fpcy == FP_ZERO && signx) + else + #endif + if (fpcy == FP_ZERO && signx) { result = signy ? -numbers::pi_v : numbers::pi_v; } @@ -67,6 +70,7 @@ constexpr auto atan2_impl(T y, T x) noexcept { result = y; } + #ifndef BOOST_DECIMAL_FAST_MATH else if (fpcy == FP_INFINITE && isfinitex) { result = atan2_detail::pi_constants::pi_over_two; @@ -85,12 +89,14 @@ constexpr auto atan2_impl(T y, T x) noexcept if (signy) { result = -result; } } + #endif else if (fpcx == FP_ZERO) { result = atan2_detail::pi_constants::pi_over_two; if (signy) { result = -result; } } + #ifndef BOOST_DECIMAL_FAST_MATH else if (fpcx == FP_INFINITE && signx && isfinitey) { result = signy ? -numbers::pi_v : numbers::pi_v; @@ -101,6 +107,7 @@ constexpr auto atan2_impl(T y, T x) noexcept result = signy ? -zero : zero; } + #endif else { if (x == T{1, 0}) diff --git a/include/boost/decimal/detail/cmath/atanh.hpp b/include/boost/decimal/detail/cmath/atanh.hpp index edda078b8..7a97483b8 100644 --- a/include/boost/decimal/detail/cmath/atanh.hpp +++ b/include/boost/decimal/detail/cmath/atanh.hpp @@ -42,7 +42,11 @@ constexpr auto atanh_impl(T x) noexcept if (xx > one) { + #ifndef BOOST_DECIMAL_FAST_MATH result = std::numeric_limits::quiet_NaN(); + #else + result = zero; + #endif } else if (xx < one) { @@ -86,7 +90,11 @@ constexpr auto atanh_impl(T x) noexcept } else { + #ifndef BOOST_DECIMAL_FAST_MATH result = ((!b_neg) ? std::numeric_limits::infinity() : -std::numeric_limits::infinity()); + #else + result = zero; + #endif } } diff --git a/include/boost/decimal/detail/cmath/cbrt.hpp b/include/boost/decimal/detail/cmath/cbrt.hpp index e0df63682..06fd56b2f 100644 --- a/include/boost/decimal/detail/cmath/cbrt.hpp +++ b/include/boost/decimal/detail/cmath/cbrt.hpp @@ -31,7 +31,11 @@ constexpr auto cbrt_impl(T x) noexcept T result { }; - if ((fpc == FP_NAN) || (fpc == FP_ZERO)) + if ((fpc == FP_ZERO) + #ifndef BOOST_DECIMAL_FAST_MATH + || (fpc == FP_NAN) + #endif + ) { result = x; } @@ -39,10 +43,12 @@ constexpr auto cbrt_impl(T x) noexcept { result = -cbrt(-x); } + #ifndef BOOST_DECIMAL_FAST_MATH else if (fpc == FP_INFINITE) { result = std::numeric_limits::infinity(); } + #endif else { int exp10val { }; diff --git a/include/boost/decimal/detail/cmath/cos.hpp b/include/boost/decimal/detail/cmath/cos.hpp index 3b7e790dc..304e2fd44 100644 --- a/include/boost/decimal/detail/cmath/cos.hpp +++ b/include/boost/decimal/detail/cmath/cos.hpp @@ -32,14 +32,18 @@ constexpr auto cos_impl(T x) noexcept { T result { }; + #ifndef BOOST_DECIMAL_FAST_MATH const auto fpc = fpclassify(x); // First check non-finite values and small angles + if ((fpc == FP_INFINITE) || (fpc == FP_NAN)) { result = x; } - else if (signbit(x)) + else + #endif + if (signbit(x)) { result = cos(-x); } diff --git a/include/boost/decimal/detail/cmath/cosh.hpp b/include/boost/decimal/detail/cmath/cosh.hpp index 4c1ab2bf8..d2f067d1d 100644 --- a/include/boost/decimal/detail/cmath/cosh.hpp +++ b/include/boost/decimal/detail/cmath/cosh.hpp @@ -38,6 +38,7 @@ constexpr auto cosh_impl(T x) noexcept { result = one; } + #ifndef BOOST_DECIMAL_FAST_MATH else if (fpc != FP_NORMAL) { if (fpc == FP_INFINITE) @@ -49,6 +50,7 @@ constexpr auto cosh_impl(T x) noexcept result = abs(x); } } + #endif else { if (signbit(x)) diff --git a/include/boost/decimal/detail/cmath/ellint_1.hpp b/include/boost/decimal/detail/cmath/ellint_1.hpp index 76303d298..96033feae 100644 --- a/include/boost/decimal/detail/cmath/ellint_1.hpp +++ b/include/boost/decimal/detail/cmath/ellint_1.hpp @@ -53,7 +53,11 @@ constexpr auto ellint_1_impl(T m, T phi) noexcept } else if((fabs(m) > one) || (fpc_phi != FP_NORMAL) || (fpc_m != FP_NORMAL)) { + #ifndef BOOST_DECIMAL_FAST_MATH result = std::numeric_limits::quiet_NaN(); + #else + result = T{0}; + #endif } else if(signbit(phi)) { diff --git a/include/boost/decimal/detail/cmath/ellint_2.hpp b/include/boost/decimal/detail/cmath/ellint_2.hpp index 916a7e589..a84e3555a 100644 --- a/include/boost/decimal/detail/cmath/ellint_2.hpp +++ b/include/boost/decimal/detail/cmath/ellint_2.hpp @@ -53,7 +53,11 @@ constexpr auto ellint_2_impl(T m, T phi) noexcept } else if((fabs(m) > one) || (fpc_phi != FP_NORMAL) || (fpc_m != FP_NORMAL)) { + #ifndef BOOST_DECIMAL_FAST_MATH result = std::numeric_limits::quiet_NaN(); + #else + result = T{0}; + #endif } else if(signbit(phi)) { diff --git a/include/boost/decimal/detail/cmath/erf.hpp b/include/boost/decimal/detail/cmath/erf.hpp index 4c82596c9..417a05755 100644 --- a/include/boost/decimal/detail/cmath/erf.hpp +++ b/include/boost/decimal/detail/cmath/erf.hpp @@ -766,10 +766,12 @@ constexpr auto erf_impl(T z) noexcept { return z; } + #ifndef BOOST_DECIMAL_FAST_MATH else if (fp == FP_INFINITE) { return z < T{0} ? T{-1} : T{1}; } + #endif return detail::erf_calc_impl(z, false); } @@ -785,10 +787,12 @@ constexpr auto erfc_impl(T z) noexcept { return z; } + #ifndef BOOST_DECIMAL_FAST_MATH else if (fp == FP_INFINITE) { return z < T{0} ? T{2} : T{0}; } + #endif return detail::erf_calc_impl(z, true); } diff --git a/include/boost/decimal/detail/cmath/exp.hpp b/include/boost/decimal/detail/cmath/exp.hpp index e72b2c3af..f80eb1b82 100644 --- a/include/boost/decimal/detail/cmath/exp.hpp +++ b/include/boost/decimal/detail/cmath/exp.hpp @@ -39,6 +39,7 @@ constexpr auto exp_impl(T x) noexcept { result = one; } + #ifndef BOOST_DECIMAL_FAST_MATH else if (fpc != FP_NORMAL) { if (fpc == FP_INFINITE) @@ -50,6 +51,7 @@ constexpr auto exp_impl(T x) noexcept result = x; } } // LCOV_EXCL_LINE + #endif else { if (signbit(x)) diff --git a/include/boost/decimal/detail/cmath/expm1.hpp b/include/boost/decimal/detail/cmath/expm1.hpp index ae7796a28..4c9b0b452 100644 --- a/include/boost/decimal/detail/cmath/expm1.hpp +++ b/include/boost/decimal/detail/cmath/expm1.hpp @@ -38,6 +38,7 @@ constexpr auto expm1_impl(T x) noexcept { result = x; } + #ifndef BOOST_DECIMAL_FAST_MATH else if (fpc != FP_NORMAL) { if (fpc == FP_INFINITE) @@ -56,6 +57,7 @@ constexpr auto expm1_impl(T x) noexcept result = x; } } + #endif else { if (abs(x) > numbers::ln2_v) diff --git a/include/boost/decimal/detail/cmath/fdim.hpp b/include/boost/decimal/detail/cmath/fdim.hpp index b868b315e..b70abc9b4 100644 --- a/include/boost/decimal/detail/cmath/fdim.hpp +++ b/include/boost/decimal/detail/cmath/fdim.hpp @@ -25,6 +25,7 @@ constexpr auto fdim(T x, T y) noexcept { constexpr T zero {0, 0}; + #ifndef BOOST_DECIMAL_FAST_MATH if (isnan(x) || isinf(x)) { return x; @@ -33,6 +34,7 @@ constexpr auto fdim(T x, T y) noexcept { return y; } + #endif if (y >= x) { diff --git a/include/boost/decimal/detail/cmath/fmax.hpp b/include/boost/decimal/detail/cmath/fmax.hpp index ca9787919..1822bc7f7 100644 --- a/include/boost/decimal/detail/cmath/fmax.hpp +++ b/include/boost/decimal/detail/cmath/fmax.hpp @@ -25,6 +25,7 @@ constexpr auto fmax(T1 lhs, T2 rhs) noexcept { using promoted_type = detail::promote_args_t; + #ifndef BOOST_DECIMAL_FAST_MATH if (isnan(lhs) && !isnan(rhs)) { return static_cast(rhs); @@ -34,6 +35,7 @@ constexpr auto fmax(T1 lhs, T2 rhs) noexcept { return static_cast(lhs); } + #endif return lhs > rhs ? static_cast(lhs) : static_cast(rhs); } diff --git a/include/boost/decimal/detail/cmath/fmin.hpp b/include/boost/decimal/detail/cmath/fmin.hpp index d4e13cfab..4021020b5 100644 --- a/include/boost/decimal/detail/cmath/fmin.hpp +++ b/include/boost/decimal/detail/cmath/fmin.hpp @@ -24,6 +24,7 @@ constexpr auto fmin(T1 lhs, T2 rhs) noexcept { using promoted_type = detail::promote_args_t; + #ifndef BOOST_DECIMAL_FAST_MATH if (isnan(lhs) && !isnan(rhs)) { return static_cast(rhs); @@ -33,6 +34,7 @@ constexpr auto fmin(T1 lhs, T2 rhs) noexcept { return static_cast(lhs); } + #endif return lhs < rhs ? static_cast(lhs) : static_cast(rhs); } diff --git a/include/boost/decimal/detail/cmath/frexp.hpp b/include/boost/decimal/detail/cmath/frexp.hpp index 8b2edbefe..ae454ec24 100644 --- a/include/boost/decimal/detail/cmath/frexp.hpp +++ b/include/boost/decimal/detail/cmath/frexp.hpp @@ -38,6 +38,7 @@ constexpr auto frexp_impl(T v, int* expon) noexcept { if (expon != nullptr) { *expon = 0; } + #ifndef BOOST_DECIMAL_FAST_MATH if (v_fp == FP_NAN) { result_frexp = std::numeric_limits::quiet_NaN(); @@ -46,6 +47,7 @@ constexpr auto frexp_impl(T v, int* expon) noexcept { result_frexp = std::numeric_limits::infinity(); } + #endif } else { diff --git a/include/boost/decimal/detail/cmath/frexp10.hpp b/include/boost/decimal/detail/cmath/frexp10.hpp index 5bc5e9fa3..76339baea 100644 --- a/include/boost/decimal/detail/cmath/frexp10.hpp +++ b/include/boost/decimal/detail/cmath/frexp10.hpp @@ -28,8 +28,6 @@ namespace decimal { BOOST_DECIMAL_EXPORT template constexpr auto frexp10(T num, int* expptr) noexcept -> typename T::significand_type { - using ReturnType = typename T::significand_type; - constexpr T zero {0, 0}; if (num == zero) @@ -37,11 +35,13 @@ constexpr auto frexp10(T num, int* expptr) noexcept -> typename T::significand_t *expptr = 0; return 0; } + #ifndef BOOST_DECIMAL_FAST_MATH else if (isinf(num) || isnan(num)) { *expptr = 0; - return (std::numeric_limits::max)(); + return (std::numeric_limits::max)(); } + #endif auto num_exp {num.biased_exponent()}; auto num_sig {num.full_significand()}; diff --git a/include/boost/decimal/detail/cmath/hypot.hpp b/include/boost/decimal/detail/cmath/hypot.hpp index 898b7be7c..cb354a372 100644 --- a/include/boost/decimal/detail/cmath/hypot.hpp +++ b/include/boost/decimal/detail/cmath/hypot.hpp @@ -30,19 +30,29 @@ constexpr auto hypot_impl(T x, T y) noexcept { constexpr T zero {0, 0}; - if (abs(x) == zero || isnan(y)) + if (abs(x) == zero + #ifndef BOOST_DECIMAL_FAST_MATH + || isnan(y) + #endif + ) { return y; } - else if (abs(y) == zero || isnan(x)) + else if (abs(y) == zero + #ifndef BOOST_DECIMAL_FAST_MATH + || isnan(x) + #endif + ) { return x; } + #ifndef BOOST_DECIMAL_FAST_MATH else if (isinf(x) || isinf(y)) { // Return +inf even if the other value is nan return std::numeric_limits::infinity(); } + #endif auto new_x {abs(x)}; auto new_y {abs(y)}; @@ -64,6 +74,7 @@ constexpr auto hypot_impl(T x, T y) noexcept template constexpr auto hypot_impl(T x, T y, T z) noexcept { + #ifndef BOOST_DECIMAL_FAST_MATH if (isinf(x) || isinf(y) || isinf(z)) { return std::numeric_limits::infinity(); @@ -80,6 +91,7 @@ constexpr auto hypot_impl(T x, T y, T z) noexcept { return z; } + #endif const auto a {fmax(fmax(x, y), z)}; const auto x_over_a {x / a}; diff --git a/include/boost/decimal/detail/cmath/ilogb.hpp b/include/boost/decimal/detail/cmath/ilogb.hpp index 5e1755456..3f032dbaf 100644 --- a/include/boost/decimal/detail/cmath/ilogb.hpp +++ b/include/boost/decimal/detail/cmath/ilogb.hpp @@ -30,6 +30,7 @@ constexpr auto ilogb(T d) noexcept { result = static_cast(FP_ILOGB0); } + #ifndef BOOST_DECIMAL_FAST_MATH else if (fpc == FP_INFINITE) { result = static_cast(INT_MAX); @@ -38,6 +39,7 @@ constexpr auto ilogb(T d) noexcept { result = static_cast(FP_ILOGBNAN); } + #endif else { const auto offset = detail::num_digits(d.full_significand()) - 1; diff --git a/include/boost/decimal/detail/cmath/isfinite.hpp b/include/boost/decimal/detail/cmath/isfinite.hpp index d1306656e..c9a9fa1dd 100644 --- a/include/boost/decimal/detail/cmath/isfinite.hpp +++ b/include/boost/decimal/detail/cmath/isfinite.hpp @@ -22,7 +22,12 @@ BOOST_DECIMAL_EXPORT template constexpr auto isfinite BOOST_DECIMAL_PREVENT_MACRO_SUBSTITUTION (T rhs) noexcept BOOST_DECIMAL_REQUIRES_RETURN(detail::is_decimal_floating_point_v, T, bool) { + #ifndef BOOST_DECIMAL_FAST_MATH return !isinf(rhs) && !isnan(rhs); + #else + static_cast(rhs); + return true; + #endif } } // namespace decimal diff --git a/include/boost/decimal/detail/cmath/isgreater.hpp b/include/boost/decimal/detail/cmath/isgreater.hpp index 3538d82e3..95db13cb5 100644 --- a/include/boost/decimal/detail/cmath/isgreater.hpp +++ b/include/boost/decimal/detail/cmath/isgreater.hpp @@ -22,10 +22,12 @@ BOOST_DECIMAL_EXPORT template constexpr auto isgreater(T lhs, T rhs) noexcept BOOST_DECIMAL_REQUIRES_RETURN(detail::is_decimal_floating_point_v, T, bool) { + #ifndef BOOST_DECIMAL_FAST_MATH if (isnan(lhs) || isnan(rhs)) { return false; } + #endif return lhs > rhs; } @@ -34,10 +36,12 @@ BOOST_DECIMAL_EXPORT template constexpr auto isgreaterequal(T lhs, T rhs) noexcept BOOST_DECIMAL_REQUIRES_RETURN(detail::is_decimal_floating_point_v, T, bool) { + #ifndef BOOST_DECIMAL_FAST_MATH if (isnan(lhs) || isnan(rhs)) { return false; } + #endif return lhs >= rhs; } diff --git a/include/boost/decimal/detail/cmath/isless.hpp b/include/boost/decimal/detail/cmath/isless.hpp index 9ad61fdc4..7efd02087 100644 --- a/include/boost/decimal/detail/cmath/isless.hpp +++ b/include/boost/decimal/detail/cmath/isless.hpp @@ -22,10 +22,12 @@ BOOST_DECIMAL_EXPORT template constexpr auto isless(T lhs, T rhs) noexcept BOOST_DECIMAL_REQUIRES_RETURN(detail::is_decimal_floating_point_v, T, bool) { + #ifndef BOOST_DECIMAL_FAST_MATH if (isnan(lhs) || isnan(rhs)) { return false; } + #endif return lhs < rhs; } @@ -34,10 +36,12 @@ BOOST_DECIMAL_EXPORT template constexpr auto islessequal(T lhs, T rhs) noexcept BOOST_DECIMAL_REQUIRES_RETURN(detail::is_decimal_floating_point_v, T, bool) { + #ifndef BOOST_DECIMAL_FAST_MATH if (isnan(lhs) || isnan(rhs)) { return false; } + #endif return lhs <= rhs; } @@ -46,10 +50,12 @@ BOOST_DECIMAL_EXPORT template constexpr auto islessgreater(T lhs, T rhs) noexcept BOOST_DECIMAL_REQUIRES_RETURN(detail::is_decimal_floating_point_v, T, bool) { + #ifndef BOOST_DECIMAL_FAST_MATH if (isnan(lhs) || isnan(rhs)) { return false; } + #endif return lhs < rhs || lhs > rhs; } diff --git a/include/boost/decimal/detail/cmath/isunordered.hpp b/include/boost/decimal/detail/cmath/isunordered.hpp index 43ddb332e..8d687291e 100644 --- a/include/boost/decimal/detail/cmath/isunordered.hpp +++ b/include/boost/decimal/detail/cmath/isunordered.hpp @@ -22,7 +22,13 @@ BOOST_DECIMAL_EXPORT template constexpr auto isunordered(T lhs, T rhs) noexcept BOOST_DECIMAL_REQUIRES_RETURN(detail::is_decimal_floating_point_v, T, bool) { + #ifndef BOOST_DECIMAL_FAST_MATH return isnan(lhs) || isnan(rhs); + #else + static_cast(lhs); + static_cast(rhs); + return false; + #endif } } // namespace decimal diff --git a/include/boost/decimal/detail/cmath/ldexp.hpp b/include/boost/decimal/detail/cmath/ldexp.hpp index 47e5cf61d..ebdefd998 100644 --- a/include/boost/decimal/detail/cmath/ldexp.hpp +++ b/include/boost/decimal/detail/cmath/ldexp.hpp @@ -30,6 +30,7 @@ constexpr auto ldexp_impl(T v, int e2) noexcept if (v_fp != FP_NORMAL) { + #ifndef BOOST_DECIMAL_FAST_MATH if (v_fp == FP_NAN) { result = std::numeric_limits::quiet_NaN(); @@ -39,6 +40,7 @@ constexpr auto ldexp_impl(T v, int e2) noexcept result = std::numeric_limits::infinity(); } else + #endif { result = T { 0, 0 }; } diff --git a/include/boost/decimal/detail/cmath/legendre.hpp b/include/boost/decimal/detail/cmath/legendre.hpp index 273f81c01..9752087a6 100644 --- a/include/boost/decimal/detail/cmath/legendre.hpp +++ b/include/boost/decimal/detail/cmath/legendre.hpp @@ -39,12 +39,18 @@ constexpr auto legendre_impl(unsigned l, T x) noexcept { if (x < -1 || x > 1 || l > 128) { + #ifndef BOOST_DECIMAL_FAST_MATH return std::numeric_limits::quiet_NaN(); + #else + return T{0}; + #endif } + #ifndef BOOST_DECIMAL_FAST_MATH else if (isnan(x)) { return x; } + #endif T p0 {1}; T p1 {x}; diff --git a/include/boost/decimal/detail/cmath/lgamma.hpp b/include/boost/decimal/detail/cmath/lgamma.hpp index 51348aef9..af53ed2ad 100644 --- a/include/boost/decimal/detail/cmath/lgamma.hpp +++ b/include/boost/decimal/detail/cmath/lgamma.hpp @@ -37,6 +37,7 @@ constexpr auto lgamma_impl(T x) noexcept const auto fpc = fpclassify(x); + #ifndef BOOST_DECIMAL_FAST_MATH if (fpc != FP_NORMAL) { if ((fpc == FP_ZERO) || (fpc == FP_INFINITE)) @@ -48,10 +49,20 @@ constexpr auto lgamma_impl(T x) noexcept result = x; } } + #else + if (fpc == FP_ZERO) + { + result = std::numeric_limits::max(); + } + #endif else if ((is_pure_int) && (nx < 0)) { // Pure negative integer argument. + #ifndef BOOST_DECIMAL_FAST_MATH result = std::numeric_limits::infinity(); + #else + result = T{0}; + #endif } else if ((is_pure_int) && ((nx == 1) || (nx == 2))) { diff --git a/include/boost/decimal/detail/cmath/log.hpp b/include/boost/decimal/detail/cmath/log.hpp index bf2350b27..87d25d413 100644 --- a/include/boost/decimal/detail/cmath/log.hpp +++ b/include/boost/decimal/detail/cmath/log.hpp @@ -38,12 +38,18 @@ constexpr auto log_impl(T x) noexcept } else if (signbit(x) || (fpc == FP_NAN)) { + #ifndef BOOST_DECIMAL_FAST_MATH result = std::numeric_limits::quiet_NaN(); + #else + result = T{0}; + #endif } + #ifndef BOOST_DECIMAL_FAST_MATH else if (fpc == FP_INFINITE) { result = std::numeric_limits::infinity(); } + #endif else if (x < one) { // Handle reflection. diff --git a/include/boost/decimal/detail/cmath/log10.hpp b/include/boost/decimal/detail/cmath/log10.hpp index 6e8842592..97100d6dc 100644 --- a/include/boost/decimal/detail/cmath/log10.hpp +++ b/include/boost/decimal/detail/cmath/log10.hpp @@ -33,11 +33,19 @@ constexpr auto log10_impl(T x) noexcept if (fpc == FP_ZERO) { + #ifndef BOOST_DECIMAL_FAST_MATH result = -std::numeric_limits::infinity(); + #else + result = T{0}; + #endif } else if (signbit(x)) { + #ifndef BOOST_DECIMAL_FAST_MATH result = std::numeric_limits::quiet_NaN(); + #else + result = T{0}; + #endif } else if (fpc != FP_NORMAL) { diff --git a/include/boost/decimal/detail/cmath/log1p.hpp b/include/boost/decimal/detail/cmath/log1p.hpp index 810293ffd..58de22162 100644 --- a/include/boost/decimal/detail/cmath/log1p.hpp +++ b/include/boost/decimal/detail/cmath/log1p.hpp @@ -37,6 +37,7 @@ constexpr auto log1p_impl(T x) noexcept { result = x; } + #ifndef BOOST_DECIMAL_FAST_MATH else if (fpc != FP_NORMAL) { result = @@ -44,12 +45,17 @@ constexpr auto log1p_impl(T x) noexcept ((fpc == FP_INFINITE) && signbit(x)) ? std::numeric_limits::quiet_NaN() : x ); } + #endif else if (-x >= one) { + #ifndef BOOST_DECIMAL_FAST_MATH result = ( (-x == one) ? -std::numeric_limits::infinity() : std::numeric_limits::quiet_NaN() ); + #else + result = T{0}; + #endif } else { diff --git a/include/boost/decimal/detail/cmath/logb.hpp b/include/boost/decimal/detail/cmath/logb.hpp index 91aede876..00be8063c 100644 --- a/include/boost/decimal/detail/cmath/logb.hpp +++ b/include/boost/decimal/detail/cmath/logb.hpp @@ -24,6 +24,7 @@ constexpr auto logb(T num) noexcept { const auto fpc {fpclassify(num)}; + #ifndef BOOST_DECIMAL_FAST_MATH if (fpc == FP_ZERO) { return -std::numeric_limits::infinity(); @@ -36,6 +37,12 @@ constexpr auto logb(T num) noexcept { return num; } + #else + if (fpc == FP_ZERO) + { + return T{0}; + } + #endif const auto offset = detail::num_digits(num.full_significand()) - 1; const auto expval = static_cast(static_cast(num.unbiased_exponent()) + offset); diff --git a/include/boost/decimal/detail/cmath/modf.hpp b/include/boost/decimal/detail/cmath/modf.hpp index e133ee4d8..a799e5d90 100644 --- a/include/boost/decimal/detail/cmath/modf.hpp +++ b/include/boost/decimal/detail/cmath/modf.hpp @@ -33,11 +33,13 @@ constexpr auto modf(T x, T* iptr) noexcept *iptr = x; return is_neg ? -zero : zero; } + #ifndef BOOST_DECIMAL_FAST_MATH else if (isnan(x)) { *iptr = x; return x; } + #endif *iptr = (x > zero) ? floor(x) : ceil(x); return (x - *iptr); diff --git a/include/boost/decimal/detail/cmath/next.hpp b/include/boost/decimal/detail/cmath/next.hpp index 4ad4acac6..f0febcaf0 100644 --- a/include/boost/decimal/detail/cmath/next.hpp +++ b/include/boost/decimal/detail/cmath/next.hpp @@ -33,6 +33,7 @@ template ::epsilon(); diff --git a/include/boost/decimal/detail/cmath/pow.hpp b/include/boost/decimal/detail/cmath/pow.hpp index 0b615b7fb..e9dd2ba4c 100644 --- a/include/boost/decimal/detail/cmath/pow.hpp +++ b/include/boost/decimal/detail/cmath/pow.hpp @@ -57,6 +57,7 @@ constexpr auto pow(T b, IntegralType p) noexcept result = ((p < static_cast(0)) ? std::numeric_limits::infinity() : ((p_is_odd && signbit(b)) ? -zero : zero)); } + #ifndef BOOST_DECIMAL_FAST_MATH else if (fpc_x == FP_INFINITE) { if (signbit(b)) @@ -91,6 +92,7 @@ constexpr auto pow(T b, IntegralType p) noexcept result = std::numeric_limits::quiet_NaN(); // LCOV_EXCL_LINE } + #endif else { using local_unsigned_integral_type = std::make_unsigned_t; @@ -173,6 +175,7 @@ constexpr auto pow(T x, T a) noexcept } else if (fpc_x == FP_ZERO) { + #ifndef BOOST_DECIMAL_FAST_MATH if ((fpc_a == FP_NORMAL) || (fpc_a == FP_INFINITE)) { // pow(+/-0, exp), where exp is negative and finite, returns +infinity. @@ -187,7 +190,14 @@ constexpr auto pow(T x, T a) noexcept { result = std::numeric_limits::quiet_NaN(); } + #else + if (fpc_a == FP_NORMAL) + { + result = T{0}; + } + #endif } + #ifndef BOOST_DECIMAL_FAST_MATH else if (fpc_x == FP_INFINITE) { if ((fpc_a == FP_NORMAL) || (fpc_a == FP_INFINITE)) @@ -206,12 +216,14 @@ constexpr auto pow(T x, T a) noexcept { result = x; } + #endif else { if (fpc_a == FP_ZERO) { result = one; } + #ifndef BOOST_DECIMAL_FAST_MATH else if (fpc_a == FP_INFINITE) { result = @@ -221,6 +233,7 @@ constexpr auto pow(T x, T a) noexcept : one ); } + #endif else { const T a_log_x { a * log(x) }; diff --git a/include/boost/decimal/detail/cmath/remainder.hpp b/include/boost/decimal/detail/cmath/remainder.hpp index 1a151602b..8ed8a4d62 100644 --- a/include/boost/decimal/detail/cmath/remainder.hpp +++ b/include/boost/decimal/detail/cmath/remainder.hpp @@ -26,6 +26,7 @@ constexpr auto remainder(T x, T y) noexcept constexpr T zero {0, 0}; constexpr T half {5, -1}; + #ifndef BOOST_DECIMAL_FAST_MATH if ((isinf(x) && !isinf(y)) || (abs(y) == zero && !isnan(x))) { @@ -39,6 +40,12 @@ constexpr auto remainder(T x, T y) noexcept { return y; } + #else + if (abs(y) == zero) + { + return zero; + } + #endif T n {}; const T frac {modf(x / y, &n)}; diff --git a/include/boost/decimal/detail/cmath/remquo.hpp b/include/boost/decimal/detail/cmath/remquo.hpp index 13fed3da8..783aec922 100644 --- a/include/boost/decimal/detail/cmath/remquo.hpp +++ b/include/boost/decimal/detail/cmath/remquo.hpp @@ -30,6 +30,7 @@ constexpr auto remquo(T x, T y, int* quo) noexcept constexpr T zero {0, 0}; constexpr T half {5, -1}; + #ifndef BOOST_DECIMAL_FAST_MATH if ((isinf(x) && !isinf(y)) || (abs(y) == zero && !isnan(x))) { @@ -43,6 +44,12 @@ constexpr auto remquo(T x, T y, int* quo) noexcept { return y; } + #else + if (abs(y) == zero) + { + return zero; + } + #endif // Compute quo auto div {x / y}; diff --git a/include/boost/decimal/detail/cmath/riemann_zeta.hpp b/include/boost/decimal/detail/cmath/riemann_zeta.hpp index 8ad26d5ce..21915d65e 100644 --- a/include/boost/decimal/detail/cmath/riemann_zeta.hpp +++ b/include/boost/decimal/detail/cmath/riemann_zeta.hpp @@ -44,10 +44,12 @@ constexpr auto riemann_zeta_impl(T x) noexcept result = T { 5, -1, true }; } + #ifndef BOOST_DECIMAL_FAST_MATH else if (fpc != FP_NORMAL) { result = ((fpc == FP_INFINITE) ? (is_neg ? -std::numeric_limits::infinity() : one) : x); } + #endif else { if (is_neg) @@ -89,8 +91,11 @@ constexpr auto riemann_zeta_impl(T x) noexcept else { // The argument is exaclty one. The result is complex-infinity. - + #ifndef BOOST_DECIMAL_FAST_MATH result = std::numeric_limits::quiet_NaN(); + #else + result = T{0}; + #endif } } else diff --git a/include/boost/decimal/detail/cmath/rint.hpp b/include/boost/decimal/detail/cmath/rint.hpp index 940c57ce4..831f61046 100644 --- a/include/boost/decimal/detail/cmath/rint.hpp +++ b/include/boost/decimal/detail/cmath/rint.hpp @@ -55,6 +55,7 @@ constexpr auto lrint_impl(T num) noexcept -> Int constexpr T lmax {(std::numeric_limits::max)()}; constexpr T lmin {(std::numeric_limits::min)()}; + #ifndef BOOST_DECIMAL_FAST_MATH if (isinf(num) || isnan(num)) { // Implementation defined what to return here @@ -64,6 +65,12 @@ constexpr auto lrint_impl(T num) noexcept -> Int { return 0; } + #else + if (abs(num) == zero) + { + return zero; + } + #endif int expptr {}; auto sig {frexp10(num, &expptr)}; // Always returns detail::precision digits @@ -112,10 +119,17 @@ constexpr auto rint(T num) noexcept constexpr T zero {0, 0}; constexpr T max_round_value {1 / std::numeric_limits::epsilon()}; + #ifndef BOOST_DECIMAL_FAST_MATH if (isinf(num) || isnan(num) || abs(num) == zero || abs(num) > max_round_value) { return num; } + #else + if (abs(num) == zero || abs(num) > max_round_value) + { + return num; + } + #endif int expptr {}; auto sig {frexp10(num, &expptr)}; // Always returns detail::precision digits diff --git a/include/boost/decimal/detail/cmath/round.hpp b/include/boost/decimal/detail/cmath/round.hpp index 3d9e85826..4d78a0b30 100644 --- a/include/boost/decimal/detail/cmath/round.hpp +++ b/include/boost/decimal/detail/cmath/round.hpp @@ -28,10 +28,17 @@ constexpr auto round(T num) noexcept constexpr T zero {0, 0}; constexpr T half {5, -1}; + #ifndef BOOST_DECIMAL_FAST_MATH if (isnan(num) || isinf(num) || abs(num) == zero) { return num; } + #else + if (abs(num) == zero) + { + return num; + } + #endif T iptr {}; const auto x {modf(num, &iptr)}; @@ -66,6 +73,7 @@ constexpr auto int_round_impl(T num) noexcept -> Int const auto rounded_val {round(num)}; + #ifndef BOOST_DECIMAL_FAST_MATH if (isinf(num) || isnan(num)) { return std::numeric_limits::min(); @@ -74,6 +82,12 @@ constexpr auto int_round_impl(T num) noexcept -> Int { return 0; } + #else + if (abs(num) == zero) + { + return 0; + } + #endif if (rounded_val > lmax) { diff --git a/include/boost/decimal/detail/cmath/sin.hpp b/include/boost/decimal/detail/cmath/sin.hpp index 03f5dc030..d3aea1069 100644 --- a/include/boost/decimal/detail/cmath/sin.hpp +++ b/include/boost/decimal/detail/cmath/sin.hpp @@ -35,7 +35,11 @@ constexpr auto sin_impl(T x) noexcept const auto fpc = fpclassify(x); // First check non-finite values and small angles. - if (fabs(x) < std::numeric_limits::epsilon() || (fpc == FP_INFINITE) || (fpc == FP_NAN)) + if (fabs(x) < std::numeric_limits::epsilon() + #ifndef BOOST_DECIMAL_FAST_MATH + || (fpc == FP_INFINITE) || (fpc == FP_NAN) + #endif + ) { result = x; } diff --git a/include/boost/decimal/detail/cmath/sinh.hpp b/include/boost/decimal/detail/cmath/sinh.hpp index 123b37c30..98b165a90 100644 --- a/include/boost/decimal/detail/cmath/sinh.hpp +++ b/include/boost/decimal/detail/cmath/sinh.hpp @@ -37,6 +37,7 @@ constexpr auto sinh_impl(T x) noexcept { result = x; } + #ifndef BOOST_DECIMAL_FAST_MATH else if (fpc != FP_NORMAL) { if (fpc == FP_INFINITE) @@ -48,6 +49,7 @@ constexpr auto sinh_impl(T x) noexcept result = x; } } + #endif else { if (signbit(x)) diff --git a/include/boost/decimal/detail/cmath/sqrt.hpp b/include/boost/decimal/detail/cmath/sqrt.hpp index 15711df96..ac17096f3 100644 --- a/include/boost/decimal/detail/cmath/sqrt.hpp +++ b/include/boost/decimal/detail/cmath/sqrt.hpp @@ -30,6 +30,7 @@ constexpr auto sqrt_impl(T x) noexcept T result { }; + #ifndef BOOST_DECIMAL_FAST_MATH if ((fpc == FP_NAN) || (fpc == FP_ZERO)) { result = x; @@ -42,6 +43,12 @@ constexpr auto sqrt_impl(T x) noexcept { result = std::numeric_limits::infinity(); } + #else + if (signbit(x)) + { + result = T{0}; + } + #endif else { int exp10val { }; diff --git a/include/boost/decimal/detail/cmath/tan.hpp b/include/boost/decimal/detail/cmath/tan.hpp index 511fd3691..5ec3e2d3b 100644 --- a/include/boost/decimal/detail/cmath/tan.hpp +++ b/include/boost/decimal/detail/cmath/tan.hpp @@ -33,6 +33,7 @@ constexpr auto tan(T x) noexcept const auto fpc = fpclassify(x); // First check non-finite values and small angles. + #ifndef BOOST_DECIMAL_FAST_MATH if (fabs(x) < std::numeric_limits::epsilon() || (fpc == FP_NAN)) { result = x; @@ -45,6 +46,12 @@ constexpr auto tan(T x) noexcept { result = -tan(-x); } + #else + if (fabs(x) < std::numeric_limits::epsilon()) + { + result = x; + } + #endif else { // Perform argument reduction. diff --git a/include/boost/decimal/detail/cmath/tanh.hpp b/include/boost/decimal/detail/cmath/tanh.hpp index 819b16d27..940d7a3aa 100644 --- a/include/boost/decimal/detail/cmath/tanh.hpp +++ b/include/boost/decimal/detail/cmath/tanh.hpp @@ -38,6 +38,7 @@ constexpr auto tanh_impl(T x) noexcept { result = x; } + #ifndef BOOST_DECIMAL_FAST_MATH else if (fpc != FP_NORMAL) { if (fpc == FP_INFINITE) @@ -56,6 +57,7 @@ constexpr auto tanh_impl(T x) noexcept result = x; } } + #endif else { if (signbit(x)) diff --git a/include/boost/decimal/detail/cmath/tgamma.hpp b/include/boost/decimal/detail/cmath/tgamma.hpp index cac238ac7..35a5c1402 100644 --- a/include/boost/decimal/detail/cmath/tgamma.hpp +++ b/include/boost/decimal/detail/cmath/tgamma.hpp @@ -43,6 +43,7 @@ constexpr auto tgamma_impl(T x) noexcept { result = (is_neg ? -std::numeric_limits::infinity() : std::numeric_limits::infinity()); } + #ifndef BOOST_DECIMAL_FAST_MATH else if(fpc == FP_INFINITE) { result = (is_neg ? std::numeric_limits::quiet_NaN() : std::numeric_limits::infinity()); @@ -51,11 +52,16 @@ constexpr auto tgamma_impl(T x) noexcept { result = x; } + #endif } else if (is_pure_int && is_neg) { // Pure negative integer argument. + #ifndef BOOST_DECIMAL_FAST_MATH result = std::numeric_limits::quiet_NaN(); + #else + result = T{0}; + #endif } else {