From bfbffe9546f1925b897cc0e1ec865d692940783e Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 10 Jul 2024 14:26:28 -0400 Subject: [PATCH 01/13] Fix comparison of signed zeros --- include/boost/decimal/decimal32_fast.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/boost/decimal/decimal32_fast.hpp b/include/boost/decimal/decimal32_fast.hpp index 884f13c20..faab19884 100644 --- a/include/boost/decimal/decimal32_fast.hpp +++ b/include/boost/decimal/decimal32_fast.hpp @@ -534,7 +534,11 @@ constexpr auto operator<(decimal32_fast lhs, decimal32_fast rhs) noexcept -> boo { if (lhs.significand_ == 0 && rhs.significand_ == 0) { + #ifndef BOOST_DECIMAL_FAST_MATH + return lhs.sign_ && !rhs.sign_; + #else return false; + #endif } return lhs.significand_ == 0 ? !rhs.sign_ : lhs.sign_; } From 00604fbb52329c52d0eb06d36a49a3f74470e468 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 10 Jul 2024 14:50:41 -0400 Subject: [PATCH 02/13] Add missing BOOST_DECIMAL_FAST_MATH --- include/boost/decimal/decimal32.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/boost/decimal/decimal32.hpp b/include/boost/decimal/decimal32.hpp index b2002934a..4f642281c 100644 --- a/include/boost/decimal/decimal32.hpp +++ b/include/boost/decimal/decimal32.hpp @@ -1056,10 +1056,12 @@ constexpr auto decimal32::operator-=(Integer rhs) noexcept constexpr auto operator==(decimal32 lhs, decimal32 rhs) noexcept -> bool { + #ifndef BOOST_DECIMAL_FAST_MATH if (isnan(lhs) || isnan(rhs)) { return false; } + #endif return equal_parts_impl(lhs.full_significand(), lhs.biased_exponent(), lhs.isneg(), rhs.full_significand(), rhs.biased_exponent(), rhs.isneg()); From 85aa7a96ab3206a87e19ad0d33aa87ab9616bae7 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 10 Jul 2024 14:52:38 -0400 Subject: [PATCH 03/13] Enable fast math in implementations --- include/boost/decimal/detail/comparison.hpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/include/boost/decimal/detail/comparison.hpp b/include/boost/decimal/detail/comparison.hpp index f35aae61c..b05d78fd1 100644 --- a/include/boost/decimal/detail/comparison.hpp +++ b/include/boost/decimal/detail/comparison.hpp @@ -106,10 +106,12 @@ constexpr auto mixed_equality_impl(Decimal lhs, Integer rhs) noexcept { using exp_type = typename Decimal::biased_exponent_type; + #ifndef BOOST_DECIMAL_FAST_MATH if (isnan(lhs) || isinf(lhs)) { return false; } + #endif bool rhs_isneg {false}; BOOST_DECIMAL_IF_CONSTEXPR (detail::is_signed_v) @@ -134,10 +136,12 @@ constexpr auto mixed_decimal_equality_impl(Decimal1 lhs, Decimal2 rhs) noexcept static_assert(!std::is_same::value, "Equality of same type exists in simpler form"); using Bigger_Decimal_Type = std::conditional_t<(sizeof(lhs) > sizeof(rhs)), Decimal1, Decimal2>; + #ifndef BOOST_DECIMAL_FAST_MATH if (isnan(lhs) || isnan(rhs)) { return false; } + #endif const auto new_lhs = to_decimal(lhs); const auto new_rhs = to_decimal(rhs); @@ -239,6 +243,7 @@ constexpr auto less_impl(Decimal lhs, Integer rhs) noexcept { using exp_type = typename Decimal::biased_exponent_type; + #ifndef BOOST_DECIMAL_FAST_MATH if (isnan(lhs)) { return false; @@ -247,6 +252,7 @@ constexpr auto less_impl(Decimal lhs, Integer rhs) noexcept { return lhs.isneg(); } + #endif bool lhs_sign {lhs.isneg()}; bool rhs_sign {false}; @@ -288,7 +294,13 @@ constexpr auto mixed_decimal_less_impl(Decimal1 lhs, Decimal2 rhs) noexcept { using Bigger_Decimal_Type = std::conditional_t<(sizeof(lhs) > sizeof(rhs)), Decimal1, Decimal2>; - if (isnan(lhs) || isnan(rhs) || (!lhs.isneg() && rhs.isneg())) + + if ( + #ifndef BOOST_DECIMAL_FAST_MATH + isnan(lhs) || isnan(rhs) || + #endif + (!lhs.isneg() && rhs.isneg()) + ) { return false; } @@ -296,6 +308,7 @@ constexpr auto mixed_decimal_less_impl(Decimal1 lhs, Decimal2 rhs) noexcept { return true; } + #ifndef BOOST_DECIMAL_FAST_MATH else if (boost::decimal::isfinite(lhs) && isinf(rhs)) { if (!signbit(rhs)) @@ -307,6 +320,7 @@ constexpr auto mixed_decimal_less_impl(Decimal1 lhs, Decimal2 rhs) noexcept return false; } } + #endif return less_parts_impl(lhs.full_significand(), lhs.biased_exponent(), lhs.isneg(), rhs.full_significand(), rhs.biased_exponent(), rhs.isneg()); @@ -325,10 +339,12 @@ constexpr auto operator<=(Decimal1 lhs, Decimal2 rhs) noexcept -> std::enable_if_t<(detail::is_decimal_floating_point_v && detail::is_decimal_floating_point_v), bool> { + #ifndef BOOST_DECIMAL_FAST_MATH if (isnan(lhs) || isnan(rhs)) { return false; } + #endif return !(rhs < lhs); } @@ -346,10 +362,12 @@ constexpr auto operator>=(Decimal1 lhs, Decimal2 rhs) noexcept -> std::enable_if_t<(detail::is_decimal_floating_point_v && detail::is_decimal_floating_point_v), bool> { + #ifndef BOOST_DECIMAL_FAST_MATH if (isnan(lhs) || isnan(rhs)) { return false; } + #endif return !(lhs < rhs); } From 0893270e5cc58208ac3eeb3845fe7303816d89b2 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 10 Jul 2024 15:44:36 -0400 Subject: [PATCH 04/13] Enable 64 bit support to new equality impl --- include/boost/decimal/detail/comparison.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/decimal/detail/comparison.hpp b/include/boost/decimal/detail/comparison.hpp index b05d78fd1..e3f6783bb 100644 --- a/include/boost/decimal/detail/comparison.hpp +++ b/include/boost/decimal/detail/comparison.hpp @@ -27,9 +27,9 @@ namespace decimal { template constexpr auto equal_parts_impl(T1 lhs_sig, U1 lhs_exp, bool lhs_sign, - T2 rhs_sig, U2 rhs_exp, bool rhs_sign) noexcept -> std::enable_if_t::value, bool> + T2 rhs_sig, U2 rhs_exp, bool rhs_sign) noexcept -> std::enable_if_t::value || std::is_same::value, bool> { - using comp_type = std::uint_fast64_t; + using comp_type = std::conditional_t::value, std::uint_fast32_t, std::uint_fast64_t>; BOOST_DECIMAL_ASSERT(lhs_sig >= 0); BOOST_DECIMAL_ASSERT(rhs_sig >= 0); @@ -74,7 +74,7 @@ constexpr auto equal_parts_impl(T1 lhs_sig, U1 lhs_exp, bool lhs_sign, template constexpr auto equal_parts_impl(T1 lhs_sig, U1 lhs_exp, bool lhs_sign, - T2 rhs_sig, U2 rhs_exp, bool rhs_sign) noexcept -> std::enable_if_t::value, bool> + T2 rhs_sig, U2 rhs_exp, bool rhs_sign) noexcept -> std::enable_if_t::value || std::is_same::value), bool> { using comp_type = std::conditional_t<(std::numeric_limits::digits10 > std::numeric_limits::digits10), T1, T2>; From 6a83fa843a9522aeb72e18ff867ac5acf17e1d5b Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 10 Jul 2024 15:59:03 -0400 Subject: [PATCH 05/13] Use new operator less impl for decimal64 --- include/boost/decimal/decimal64.hpp | 34 +++++++++------------ include/boost/decimal/detail/comparison.hpp | 4 +-- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/include/boost/decimal/decimal64.hpp b/include/boost/decimal/decimal64.hpp index 588ef5ad0..ac44a243a 100644 --- a/include/boost/decimal/decimal64.hpp +++ b/include/boost/decimal/decimal64.hpp @@ -1670,27 +1670,21 @@ constexpr auto operator!=(Integer lhs, decimal64 rhs) noexcept constexpr auto operator<(decimal64 lhs, decimal64 rhs) noexcept -> bool { #ifndef BOOST_DECIMAL_FAST_MATH - if (isnan(lhs) || isnan(rhs) || - (!lhs.isneg() && rhs.isneg())) - { - return false; - } - else if (lhs.isneg() && !rhs.isneg()) - { - return true; - } - else if (isfinite(lhs) && isinf(rhs)) - { - return !rhs.isneg(); - } - #else - if (!lhs.isneg() && rhs.isneg()) - { - return false; - } - else if (lhs.isneg() && !rhs.isneg()) + if (not_finite(lhs) || not_finite(rhs)) { - return true; + if (isnan(lhs) || isnan(rhs) || + (!lhs.isneg() && rhs.isneg())) + { + return false; + } + else if (lhs.isneg() && !rhs.isneg()) + { + return true; + } + else if (isfinite(lhs) && isinf(rhs)) + { + return !rhs.isneg(); + } } #endif diff --git a/include/boost/decimal/detail/comparison.hpp b/include/boost/decimal/detail/comparison.hpp index e3f6783bb..c8030c1a1 100644 --- a/include/boost/decimal/detail/comparison.hpp +++ b/include/boost/decimal/detail/comparison.hpp @@ -168,7 +168,7 @@ constexpr auto operator!=(Decimal1 lhs, Decimal2 rhs) noexcept template constexpr auto less_parts_impl(T1 lhs_sig, U1 lhs_exp, bool lhs_sign, - T2 rhs_sig, U2 rhs_exp, bool rhs_sign) noexcept -> std::enable_if_t::value, bool> + T2 rhs_sig, U2 rhs_exp, bool rhs_sign) noexcept -> std::enable_if_t::value || std::is_same::value, bool> { using comp_type = std::uint_fast64_t; @@ -202,7 +202,7 @@ constexpr auto less_parts_impl(T1 lhs_sig, U1 lhs_exp, bool lhs_sign, template constexpr auto less_parts_impl(T1 lhs_sig, U1 lhs_exp, bool lhs_sign, - T2 rhs_sig, U2 rhs_exp, bool rhs_sign) noexcept -> std::enable_if_t::value, bool> + T2 rhs_sig, U2 rhs_exp, bool rhs_sign) noexcept -> std::enable_if_t::value || std::is_same::value), bool> { using comp_type = std::conditional_t<(std::numeric_limits::digits10 > std::numeric_limits::digits10), T1, T2>; From a5a0a6ca9f71557515e4ee2ca447c953cdd7082a Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 10 Jul 2024 16:16:11 -0400 Subject: [PATCH 06/13] Remove unneeded fast path --- include/boost/decimal/decimal32_fast.hpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/include/boost/decimal/decimal32_fast.hpp b/include/boost/decimal/decimal32_fast.hpp index faab19884..c1c4e9ccb 100644 --- a/include/boost/decimal/decimal32_fast.hpp +++ b/include/boost/decimal/decimal32_fast.hpp @@ -519,15 +519,6 @@ constexpr auto operator<(decimal32_fast lhs, decimal32_fast rhs) noexcept -> boo return signbit(rhs); } } - #else - if (!lhs.isneg() && rhs.isneg()) - { - return false; - } - else if (lhs.isneg() && !rhs.isneg()) - { - return true; - } #endif if (lhs.significand_ == 0 || rhs.significand_ == 0) From 6fab198eadabefbadad2041b37ea09fd65f4a88f Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 10 Jul 2024 16:16:24 -0400 Subject: [PATCH 07/13] Improve operator< for decimal64_fast --- include/boost/decimal/decimal64_fast.hpp | 54 ++++++++++++++---------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/include/boost/decimal/decimal64_fast.hpp b/include/boost/decimal/decimal64_fast.hpp index 47d04bba3..37e4712c8 100644 --- a/include/boost/decimal/decimal64_fast.hpp +++ b/include/boost/decimal/decimal64_fast.hpp @@ -538,37 +538,45 @@ constexpr auto operator!=(Integer lhs, decimal64_fast rhs) noexcept constexpr auto operator<(decimal64_fast lhs, decimal64_fast rhs) noexcept -> bool { #ifndef BOOST_DECIMAL_FAST_MATH - if (isnan(lhs) || isnan(rhs)) + if (not_finite(lhs) || not_finite(rhs)) { - return false; + if (isnan(lhs) || isnan(rhs) || + (!lhs.isneg() && rhs.isneg())) + { + return false; + } + else if (lhs.isneg() && !rhs.isneg()) + { + return true; + } + else if (isfinite(lhs) && isinf(rhs)) + { + return !signbit(rhs); + } + else if (isinf(lhs) && isfinite(rhs)) + { + return signbit(rhs); + } } #endif - if (!lhs.isneg() && rhs.isneg()) - { - return false; - } - - if (lhs.isneg() && !rhs.isneg()) - { - return true; - } - - #ifndef BOOST_DECIMAL_FAST_MATH - if (isfinite(lhs) && isinf(rhs)) - { - return !signbit(rhs); - } - - if (isinf(lhs) && isfinite(rhs)) + // Needed to correctly compare signed and unsigned zeros + if (lhs.significand_ == 0 || rhs.significand_ == 0) { - return signbit(rhs); + if (lhs.significand_ == 0 && rhs.significand_ == 0) + { + #ifndef BOOST_DECIMAL_FAST_MATH + return lhs.sign_ && !rhs.sign_; + #else + return false; + #endif + } + return lhs.significand_ == 0 ? !rhs.sign_ : lhs.sign_; } - #endif - if (lhs.significand_ == 0 || rhs.significand_ == 0) + if (lhs.sign_ != rhs.sign_) { - return lhs.significand_ == 0 ? !rhs.sign_ : lhs.sign_; + return lhs.sign_; } if (lhs.exponent_ != rhs.exponent_) From 73510aca4616329b8f5f52d674634ef794c1f09b Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Thu, 11 Jul 2024 08:06:40 -0400 Subject: [PATCH 08/13] Add assertion at point of fuzzing crash --- include/boost/decimal/charconv.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/decimal/charconv.hpp b/include/boost/decimal/charconv.hpp index fa6d1abcc..001c76d28 100644 --- a/include/boost/decimal/charconv.hpp +++ b/include/boost/decimal/charconv.hpp @@ -615,7 +615,7 @@ BOOST_DECIMAL_CONSTEXPR auto to_chars_hex_impl(char* first, char* last, const Ta int exp {}; Unsigned_Integer significand = frexp10(value, &exp); - + BOOST_DECIMAL_ASSERT(significand != 0); // Strip zeros of the significand since frexp10 normalizes it while (significand % 10U == 0) { From b9a6cc8adf5dfd84fc27d00cab521069b194f19d Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Thu, 11 Jul 2024 08:07:12 -0400 Subject: [PATCH 09/13] Add local fuzzing crash files --- .../crash-b064ecb574301d4db076a40a163c97e7b3493730 | Bin 0 -> 37 bytes .../crash-cabfe2d6422408ec1acebc5b61bb755b140c2d7a | Bin 0 -> 37 bytes .../crash-e89fafed26debffb24aaa20cfcc7a08ad61ac5ff | 1 + .../crash-fb2d3435b218b7000ccf2e76b3d2e820800f51aa | 1 + 4 files changed, 2 insertions(+) create mode 100644 fuzzing/old_crashes/fuzz_snprintf/crash-b064ecb574301d4db076a40a163c97e7b3493730 create mode 100644 fuzzing/old_crashes/fuzz_snprintf/crash-cabfe2d6422408ec1acebc5b61bb755b140c2d7a create mode 100644 fuzzing/old_crashes/fuzz_snprintf/crash-e89fafed26debffb24aaa20cfcc7a08ad61ac5ff create mode 100644 fuzzing/old_crashes/fuzz_snprintf/crash-fb2d3435b218b7000ccf2e76b3d2e820800f51aa diff --git a/fuzzing/old_crashes/fuzz_snprintf/crash-b064ecb574301d4db076a40a163c97e7b3493730 b/fuzzing/old_crashes/fuzz_snprintf/crash-b064ecb574301d4db076a40a163c97e7b3493730 new file mode 100644 index 0000000000000000000000000000000000000000..d87389b818f0f1a127357f76a05825e68156cea6 GIT binary patch literal 37 WcmYc_G%zqQ0%BBPir_LbqyhkokOu?+ literal 0 HcmV?d00001 diff --git a/fuzzing/old_crashes/fuzz_snprintf/crash-cabfe2d6422408ec1acebc5b61bb755b140c2d7a b/fuzzing/old_crashes/fuzz_snprintf/crash-cabfe2d6422408ec1acebc5b61bb755b140c2d7a new file mode 100644 index 0000000000000000000000000000000000000000..4e713208261890f83704019e7ab99faea62fabdd GIT binary patch literal 37 VcmYc_Gyno45P=L#5gbN_Q~-;P2Lu2B literal 0 HcmV?d00001 diff --git a/fuzzing/old_crashes/fuzz_snprintf/crash-e89fafed26debffb24aaa20cfcc7a08ad61ac5ff b/fuzzing/old_crashes/fuzz_snprintf/crash-e89fafed26debffb24aaa20cfcc7a08ad61ac5ff new file mode 100644 index 000000000..5bb8fa2b7 --- /dev/null +++ b/fuzzing/old_crashes/fuzz_snprintf/crash-e89fafed26debffb24aaa20cfcc7a08ad61ac5ff @@ -0,0 +1 @@ +e1000a00000000000000000000p06 \ No newline at end of file diff --git a/fuzzing/old_crashes/fuzz_snprintf/crash-fb2d3435b218b7000ccf2e76b3d2e820800f51aa b/fuzzing/old_crashes/fuzz_snprintf/crash-fb2d3435b218b7000ccf2e76b3d2e820800f51aa new file mode 100644 index 000000000..9eceaa5f9 --- /dev/null +++ b/fuzzing/old_crashes/fuzz_snprintf/crash-fb2d3435b218b7000ccf2e76b3d2e820800f51aa @@ -0,0 +1 @@ +50000100000000000000078591790822 \ No newline at end of file From 9526ef4a1cbec67d8b24ec9588248211dd02c7b2 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Thu, 11 Jul 2024 09:33:34 -0400 Subject: [PATCH 10/13] Add fpclassify testing --- test/test_cmath.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/test_cmath.cpp b/test/test_cmath.cpp index 8e69adc24..a6046508a 100644 --- a/test/test_cmath.cpp +++ b/test/test_cmath.cpp @@ -1286,6 +1286,17 @@ void test_log10() } } +template +void test_fpclassify() +{ + std::uniform_int_distribution dist(1, 2); + BOOST_TEST_EQ(fpclassify(T(1) * dist(rng)), FP_NORMAL); + BOOST_TEST_EQ(fpclassify(std::numeric_limits::infinity() * dist(rng)), FP_INFINITE); + BOOST_TEST_EQ(fpclassify(std::numeric_limits::quiet_NaN() * dist(rng)), FP_NAN); + BOOST_TEST_EQ(fpclassify(T{0} * dist(rng)), FP_ZERO); + BOOST_TEST_EQ(fpclassify(-T{0} * dist(rng)), FP_ZERO); +} + int main() { test_fmax(); @@ -1529,5 +1540,13 @@ int main() test_log10(); #endif + test_fpclassify(); + test_fpclassify(); + test_fpclassify(); + + test_fpclassify(); + test_fpclassify(); + test_fpclassify(); + return boost::report_errors(); } From 3d64278e873f9b2390681c433aced2ca45c36e9f Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Thu, 11 Jul 2024 09:34:43 -0400 Subject: [PATCH 11/13] Add additional test for debugging --- test/test_to_chars.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/test_to_chars.cpp b/test/test_to_chars.cpp index 37fcc0060..a6b7479cb 100644 --- a/test/test_to_chars.cpp +++ b/test/test_to_chars.cpp @@ -42,6 +42,19 @@ void test_value(T val, const char* result) BOOST_TEST_CSTR_EQ(result, buffer); } +template +void test_error_value(const char* input, chars_format format, int precision = -1) +{ + T val; + const auto r_from = from_chars(input, input + std::strlen(input), val, format); + BOOST_TEST(r_from); + std::cerr << "Val: " << val + << "\nIsneg: " << signbit(val) << std::endl; + char buffer[boost::decimal::limits::max_chars] {}; + const auto r_to = to_chars(buffer, buffer + sizeof(buffer), val, format, precision); + BOOST_TEST(r_to); +} + template void test_non_finite_values() { @@ -648,6 +661,12 @@ int main() // See: https://github.com/cppalliance/decimal/issues/478 test_value(std::numeric_limits::epsilon(), "1e-07"); + // Value found from fuzzing + for (int precision = -1; precision < 10; ++precision) + { + test_error_value("e1000a00000000000000000000p06", chars_format::hex, precision); + } + return boost::report_errors(); } From 7278a7dd7172d669e270d29db87a8f48032044fd Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Thu, 11 Jul 2024 09:35:00 -0400 Subject: [PATCH 12/13] Check sigs for 0 before proceeding --- include/boost/decimal/detail/comparison.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/boost/decimal/detail/comparison.hpp b/include/boost/decimal/detail/comparison.hpp index c8030c1a1..3be37e63b 100644 --- a/include/boost/decimal/detail/comparison.hpp +++ b/include/boost/decimal/detail/comparison.hpp @@ -46,7 +46,9 @@ constexpr auto equal_parts_impl(T1 lhs_sig, U1 lhs_exp, bool lhs_sign, const auto delta_exp {lhs_exp - rhs_exp}; // Check the value of delta exp to avoid to large a value for pow10 - if (delta_exp > detail::precision_v || delta_exp < -detail::precision_v) + // Also if only one of the significands is 0 then we know the values have to be mismatched + if (delta_exp > detail::precision_v || delta_exp < -detail::precision_v || + (new_lhs_sig == static_cast(0) ^ new_rhs_sig == static_cast(0))) { return false; } From 0d04df29668ded15d35c7ecc7652557a170b927d Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Thu, 11 Jul 2024 09:49:22 -0400 Subject: [PATCH 13/13] Fix operator precedence warning --- include/boost/decimal/detail/comparison.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/decimal/detail/comparison.hpp b/include/boost/decimal/detail/comparison.hpp index 3be37e63b..9fa0cdfee 100644 --- a/include/boost/decimal/detail/comparison.hpp +++ b/include/boost/decimal/detail/comparison.hpp @@ -48,7 +48,7 @@ constexpr auto equal_parts_impl(T1 lhs_sig, U1 lhs_exp, bool lhs_sign, // Check the value of delta exp to avoid to large a value for pow10 // Also if only one of the significands is 0 then we know the values have to be mismatched if (delta_exp > detail::precision_v || delta_exp < -detail::precision_v || - (new_lhs_sig == static_cast(0) ^ new_rhs_sig == static_cast(0))) + ((new_lhs_sig == static_cast(0)) ^ (new_rhs_sig == static_cast(0)))) { return false; }