From 57fe87b751fe866f9b5b05d8cb8a2fefb4288b40 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 19 Feb 2025 09:19:15 -0500 Subject: [PATCH 1/9] Replace separate equality implementations with unified friend function --- include/boost/decimal/decimal128_fast.hpp | 27 ++++---------------- include/boost/decimal/decimal32_fast.hpp | 26 +++---------------- include/boost/decimal/decimal64_fast.hpp | 28 ++++----------------- include/boost/decimal/detail/comparison.hpp | 27 ++++++++++++++++++++ 4 files changed, 41 insertions(+), 67 deletions(-) diff --git a/include/boost/decimal/decimal128_fast.hpp b/include/boost/decimal/decimal128_fast.hpp index 520c53ac..41241cd3 100644 --- a/include/boost/decimal/decimal128_fast.hpp +++ b/include/boost/decimal/decimal128_fast.hpp @@ -14,6 +14,7 @@ #include #include #include +#include #ifndef BOOST_DECIMAL_BUILD_MODULE @@ -132,6 +133,9 @@ BOOST_DECIMAL_EXPORT class decimal128_fast final friend constexpr auto to_dpd_d128(DecimalType val) noexcept BOOST_DECIMAL_REQUIRES_RETURN(detail::is_decimal_floating_point_v, DecimalType, detail::uint128); + template + BOOST_DECIMAL_FORCE_INLINE friend constexpr auto fast_equality_impl(const DecimalType& lhs, const DecimalType& rhs) noexcept -> bool; + public: constexpr decimal128_fast() noexcept = default; @@ -535,28 +539,7 @@ constexpr auto not_finite(const decimal128_fast& val) noexcept -> bool constexpr auto operator==(const decimal128_fast& lhs, const decimal128_fast& rhs) noexcept -> bool { - if (lhs.exponent_ != rhs.exponent_) - { - return false; - } - if (lhs.significand_ != rhs.significand_) - { - return false; - } - - #ifndef BOOST_DECIMAL_FAST_MATH - if (isnan(lhs)) - { - return false; - } - #endif - - if (lhs.significand_ == 0) - { - return true; // -0 == +0 - } - - return lhs.sign_ == rhs.sign_; + return fast_equality_impl(lhs, rhs); } template diff --git a/include/boost/decimal/decimal32_fast.hpp b/include/boost/decimal/decimal32_fast.hpp index ed99ff3c..efd87084 100644 --- a/include/boost/decimal/decimal32_fast.hpp +++ b/include/boost/decimal/decimal32_fast.hpp @@ -114,6 +114,9 @@ BOOST_DECIMAL_EXPORT class decimal32_fast final template friend constexpr auto detail::d32_add_impl(const T& lhs, const T& rhs) noexcept -> ReturnType; + template + BOOST_DECIMAL_FORCE_INLINE friend constexpr auto fast_equality_impl(const DecimalType& lhs, const DecimalType& rhs) noexcept -> bool; + public: constexpr decimal32_fast() noexcept = default; @@ -494,28 +497,7 @@ constexpr auto isfinite(decimal32_fast val) noexcept -> bool constexpr auto operator==(decimal32_fast lhs, decimal32_fast rhs) noexcept -> bool { - if (lhs.exponent_ != rhs.exponent_) - { - return false; - } - if (lhs.significand_ != rhs.significand_) - { - return false; - } - - #ifndef BOOST_DECIMAL_FAST_MATH - if (isnan(lhs)) - { - return false; - } - #endif - - if (lhs.significand_ == 0) - { - return true; // -0 == +0 - } - - return lhs.sign_ == rhs.sign_; + return fast_equality_impl(lhs, rhs); } constexpr auto operator!=(decimal32_fast lhs, decimal32_fast rhs) noexcept -> bool diff --git a/include/boost/decimal/decimal64_fast.hpp b/include/boost/decimal/decimal64_fast.hpp index 5f01a608..bd7ce689 100644 --- a/include/boost/decimal/decimal64_fast.hpp +++ b/include/boost/decimal/decimal64_fast.hpp @@ -132,6 +132,9 @@ BOOST_DECIMAL_EXPORT class decimal64_fast final template BOOST_DECIMAL_FORCE_INLINE friend constexpr auto detail::d64_mul_impl(const T& lhs, const T& rhs) noexcept -> std::enable_if_t, ReturnType>; + template + BOOST_DECIMAL_FORCE_INLINE friend constexpr auto fast_equality_impl(const DecimalType& lhs, const DecimalType& rhs) noexcept -> bool; + public: constexpr decimal64_fast() noexcept = default; @@ -350,7 +353,7 @@ BOOST_DECIMAL_EXPORT class decimal64_fast final constexpr auto operator++(int) noexcept -> decimal64_fast&; constexpr auto operator--() noexcept -> decimal64_fast&; constexpr auto operator--(int) noexcept -> decimal64_fast&; - + // Cmath friend functions template friend constexpr auto frexp10(T num, int* expptr) noexcept -> typename T::significand_type; @@ -523,28 +526,7 @@ constexpr auto not_finite(decimal64_fast val) noexcept -> bool constexpr auto operator==(decimal64_fast lhs, decimal64_fast rhs) noexcept -> bool { - if (lhs.exponent_ != rhs.exponent_) - { - return false; - } - if (lhs.significand_ != rhs.significand_) - { - return false; - } - - #ifndef BOOST_DECIMAL_FAST_MATH - if (isnan(lhs)) - { - return false; - } - #endif - - if (lhs.significand_ == 0) - { - return true; // -0 == +0 - } - - return lhs.sign_ == rhs.sign_; + return fast_equality_impl(lhs, rhs); } template diff --git a/include/boost/decimal/detail/comparison.hpp b/include/boost/decimal/detail/comparison.hpp index 17f3e102..eb198d41 100644 --- a/include/boost/decimal/detail/comparison.hpp +++ b/include/boost/decimal/detail/comparison.hpp @@ -98,6 +98,33 @@ BOOST_DECIMAL_FORCE_INLINE constexpr auto equality_impl(DecimalType lhs, Decimal return lhs_sig == rhs_sig; } +template +BOOST_DECIMAL_FORCE_INLINE constexpr auto fast_equality_impl(const DecimalType& lhs, const DecimalType& rhs) noexcept -> bool +{ + if (lhs.exponent_ != rhs.exponent_) + { + return false; + } + if (lhs.significand_ != rhs.significand_) + { + return false; + } + + #ifndef BOOST_DECIMAL_FAST_MATH + if (isnan(lhs)) + { + return false; + } + #endif + + if (lhs.significand_ == 0) + { + return true; // -0 == +0 + } + + return lhs.sign_ == rhs.sign_; +} + template constexpr auto equal_parts_impl(T1 lhs_sig, U1 lhs_exp, bool lhs_sign, From 741df441b3338fbb941415448140592bed6557e7 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 19 Feb 2025 09:47:03 -0500 Subject: [PATCH 2/9] Consolidate inequality impls --- include/boost/decimal/decimal128_fast.hpp | 5 ++++- include/boost/decimal/decimal32_fast.hpp | 12 +++++------- include/boost/decimal/decimal64_fast.hpp | 5 ++++- include/boost/decimal/detail/comparison.hpp | 12 ++++++++++++ 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/include/boost/decimal/decimal128_fast.hpp b/include/boost/decimal/decimal128_fast.hpp index 41241cd3..17b0c8cf 100644 --- a/include/boost/decimal/decimal128_fast.hpp +++ b/include/boost/decimal/decimal128_fast.hpp @@ -136,6 +136,9 @@ BOOST_DECIMAL_EXPORT class decimal128_fast final template BOOST_DECIMAL_FORCE_INLINE friend constexpr auto fast_equality_impl(const DecimalType& lhs, const DecimalType& rhs) noexcept -> bool; + template + BOOST_DECIMAL_FORCE_INLINE friend constexpr auto fast_inequality_impl(const DecimalType& lhs, const DecimalType& rhs) noexcept -> bool; + public: constexpr decimal128_fast() noexcept = default; @@ -558,7 +561,7 @@ constexpr auto operator==(Integer lhs, decimal128_fast rhs) noexcept constexpr auto operator!=(const decimal128_fast& lhs, const decimal128_fast& rhs) noexcept -> bool { - return !(lhs == rhs); + return fast_inequality_impl(lhs, rhs); } template diff --git a/include/boost/decimal/decimal32_fast.hpp b/include/boost/decimal/decimal32_fast.hpp index efd87084..078bf19e 100644 --- a/include/boost/decimal/decimal32_fast.hpp +++ b/include/boost/decimal/decimal32_fast.hpp @@ -16,6 +16,7 @@ #include #include #include +#include #ifndef BOOST_DECIMAL_BUILD_MODULE #include @@ -117,6 +118,9 @@ BOOST_DECIMAL_EXPORT class decimal32_fast final template BOOST_DECIMAL_FORCE_INLINE friend constexpr auto fast_equality_impl(const DecimalType& lhs, const DecimalType& rhs) noexcept -> bool; + template + BOOST_DECIMAL_FORCE_INLINE friend constexpr auto fast_inequality_impl(const DecimalType& lhs, const DecimalType& rhs) noexcept -> bool; + public: constexpr decimal32_fast() noexcept = default; @@ -502,13 +506,7 @@ constexpr auto operator==(decimal32_fast lhs, decimal32_fast rhs) noexcept -> bo constexpr auto operator!=(decimal32_fast lhs, decimal32_fast rhs) noexcept -> bool { - return - #ifndef BOOST_DECIMAL_FAST_MATH - isnan(lhs) || isnan(rhs) || - #endif - (lhs.sign_ != rhs.sign_) || - (lhs.exponent_ != rhs.exponent_) || - (lhs.significand_ != rhs.significand_); + return fast_inequality_impl(lhs, rhs); } constexpr auto operator<(decimal32_fast lhs, decimal32_fast rhs) noexcept -> bool diff --git a/include/boost/decimal/decimal64_fast.hpp b/include/boost/decimal/decimal64_fast.hpp index bd7ce689..54e30fa1 100644 --- a/include/boost/decimal/decimal64_fast.hpp +++ b/include/boost/decimal/decimal64_fast.hpp @@ -135,6 +135,9 @@ BOOST_DECIMAL_EXPORT class decimal64_fast final template BOOST_DECIMAL_FORCE_INLINE friend constexpr auto fast_equality_impl(const DecimalType& lhs, const DecimalType& rhs) noexcept -> bool; + template + BOOST_DECIMAL_FORCE_INLINE friend constexpr auto fast_inequality_impl(const DecimalType& lhs, const DecimalType& rhs) noexcept -> bool; + public: constexpr decimal64_fast() noexcept = default; @@ -545,7 +548,7 @@ constexpr auto operator==(Integer lhs, decimal64_fast rhs) noexcept constexpr auto operator!=(decimal64_fast lhs, decimal64_fast rhs) noexcept -> bool { - return !(lhs == rhs); + return fast_inequality_impl(lhs, rhs); } template diff --git a/include/boost/decimal/detail/comparison.hpp b/include/boost/decimal/detail/comparison.hpp index eb198d41..83a5dabf 100644 --- a/include/boost/decimal/detail/comparison.hpp +++ b/include/boost/decimal/detail/comparison.hpp @@ -125,6 +125,18 @@ BOOST_DECIMAL_FORCE_INLINE constexpr auto fast_equality_impl(const DecimalType& return lhs.sign_ == rhs.sign_; } +template +BOOST_DECIMAL_FORCE_INLINE constexpr auto fast_inequality_impl(const DecimalType& lhs, const DecimalType& rhs) noexcept -> bool +{ + return + #ifndef BOOST_DECIMAL_FAST_MATH + isnan(lhs) || isnan(rhs) || + #endif + (lhs.sign_ != rhs.sign_) || + (lhs.exponent_ != rhs.exponent_) || + (lhs.significand_ != rhs.significand_); +} + template constexpr auto equal_parts_impl(T1 lhs_sig, U1 lhs_exp, bool lhs_sign, From d0f777e8312c4665e2f716638dfab8d1a77670fd Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 19 Feb 2025 12:16:09 -0500 Subject: [PATCH 3/9] Add fast decimal type concept --- include/boost/decimal/detail/concepts.hpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/boost/decimal/detail/concepts.hpp b/include/boost/decimal/detail/concepts.hpp index 16634156..371825e0 100644 --- a/include/boost/decimal/detail/concepts.hpp +++ b/include/boost/decimal/detail/concepts.hpp @@ -228,6 +228,9 @@ concept random_access_container = is_container && template concept decimal_floating_point_type = boost::decimal::detail::is_decimal_floating_point_v; +template +concept fast_decimal_floating_point_type = boost::decimal::detail::is_fast_type_v; + } // boost::decimal::detail::concepts #define BOOST_DECIMAL_HAS_CONCEPTS 1 @@ -253,6 +256,7 @@ concept decimal_floating_point_type = boost::decimal::detail::is_decimal_floatin #define BOOST_DECIMAL_ARBITRARY_REAL_OR_COMPLEX boost::decimal::detail::concepts::arbitrary_real_or_complex_type #define BOOST_DECIMAL_ARBITRARY_NUMERICAL boost::decimal::detail::concepts::arbitrary_numerical_type #define BOOST_DECIMAL_DECIMAL_FLOATING_TYPE boost::decimal::detail::concepts::decimal_floating_point_type +#define BOOST_DECIMAL_FAST_DECIMAL_FLOATING_TYPE boost::decimal::detail::concepts::fast_decimal_floating_point_type #define BOOST_DECIMAL_CONTAINER boost::decimal::detail::concepts::is_container #define BOOST_DECIMAL_RANDOM_ACCESS_CONTAINER boost::decimal::detail::concepts::random_access_container @@ -388,6 +392,10 @@ concept execution_policy = std::is_execution_policy_v>; # define BOOST_DECIMAL_DECIMAL_FLOATING_TYPE typename #endif +#ifndef BOOST_DECIMAL_FAST_DECIMAL_FLOATING_TYPE +# define BOOST_DECIMAL_FAST_DECIMAL_FLOATING_TYPE typename +#endif + #ifndef BOOST_DECIMAL_OUTPUT_ITER # define BOOST_DECIMAL_OUTPUT_ITER(I, T) #endif From 203b3e5cae7fedd3a64ce0ca5e218c2e5c72df3a Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 19 Feb 2025 12:16:21 -0500 Subject: [PATCH 4/9] Add missing header --- include/boost/decimal/detail/add_impl.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/decimal/detail/add_impl.hpp b/include/boost/decimal/detail/add_impl.hpp index 43fafad7..a861de77 100644 --- a/include/boost/decimal/detail/add_impl.hpp +++ b/include/boost/decimal/detail/add_impl.hpp @@ -9,6 +9,7 @@ #include #include #include +#include #ifndef BOOST_DECIMAL_BUILD_MODULE #include From ad40dc14f3760a02675b08571802d4a9d4099bb1 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 19 Feb 2025 12:19:02 -0500 Subject: [PATCH 5/9] Update signatures with new concept --- include/boost/decimal/decimal128_fast.hpp | 4 ++-- include/boost/decimal/decimal32_fast.hpp | 4 ++-- include/boost/decimal/decimal64_fast.hpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/boost/decimal/decimal128_fast.hpp b/include/boost/decimal/decimal128_fast.hpp index 17b0c8cf..297d1090 100644 --- a/include/boost/decimal/decimal128_fast.hpp +++ b/include/boost/decimal/decimal128_fast.hpp @@ -133,10 +133,10 @@ BOOST_DECIMAL_EXPORT class decimal128_fast final friend constexpr auto to_dpd_d128(DecimalType val) noexcept BOOST_DECIMAL_REQUIRES_RETURN(detail::is_decimal_floating_point_v, DecimalType, detail::uint128); - template + template BOOST_DECIMAL_FORCE_INLINE friend constexpr auto fast_equality_impl(const DecimalType& lhs, const DecimalType& rhs) noexcept -> bool; - template + template BOOST_DECIMAL_FORCE_INLINE friend constexpr auto fast_inequality_impl(const DecimalType& lhs, const DecimalType& rhs) noexcept -> bool; public: diff --git a/include/boost/decimal/decimal32_fast.hpp b/include/boost/decimal/decimal32_fast.hpp index 078bf19e..ab0af279 100644 --- a/include/boost/decimal/decimal32_fast.hpp +++ b/include/boost/decimal/decimal32_fast.hpp @@ -115,10 +115,10 @@ BOOST_DECIMAL_EXPORT class decimal32_fast final template friend constexpr auto detail::d32_add_impl(const T& lhs, const T& rhs) noexcept -> ReturnType; - template + template BOOST_DECIMAL_FORCE_INLINE friend constexpr auto fast_equality_impl(const DecimalType& lhs, const DecimalType& rhs) noexcept -> bool; - template + template BOOST_DECIMAL_FORCE_INLINE friend constexpr auto fast_inequality_impl(const DecimalType& lhs, const DecimalType& rhs) noexcept -> bool; public: diff --git a/include/boost/decimal/decimal64_fast.hpp b/include/boost/decimal/decimal64_fast.hpp index 54e30fa1..d1b8aafa 100644 --- a/include/boost/decimal/decimal64_fast.hpp +++ b/include/boost/decimal/decimal64_fast.hpp @@ -132,10 +132,10 @@ BOOST_DECIMAL_EXPORT class decimal64_fast final template BOOST_DECIMAL_FORCE_INLINE friend constexpr auto detail::d64_mul_impl(const T& lhs, const T& rhs) noexcept -> std::enable_if_t, ReturnType>; - template + template BOOST_DECIMAL_FORCE_INLINE friend constexpr auto fast_equality_impl(const DecimalType& lhs, const DecimalType& rhs) noexcept -> bool; - template + template BOOST_DECIMAL_FORCE_INLINE friend constexpr auto fast_inequality_impl(const DecimalType& lhs, const DecimalType& rhs) noexcept -> bool; public: From 13094f8a53dd51dec3f62f6d31f60e7f9b7a030b Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 19 Feb 2025 12:27:22 -0500 Subject: [PATCH 6/9] Consolidate operator< implementations for fast types --- include/boost/decimal/decimal128_fast.hpp | 52 ++----------------- include/boost/decimal/decimal32_fast.hpp | 36 ++++--------- include/boost/decimal/decimal64_fast.hpp | 52 ++----------------- include/boost/decimal/detail/comparison.hpp | 57 ++++++++++++++++++++- 4 files changed, 74 insertions(+), 123 deletions(-) diff --git a/include/boost/decimal/decimal128_fast.hpp b/include/boost/decimal/decimal128_fast.hpp index 297d1090..6d4a2618 100644 --- a/include/boost/decimal/decimal128_fast.hpp +++ b/include/boost/decimal/decimal128_fast.hpp @@ -139,6 +139,9 @@ BOOST_DECIMAL_EXPORT class decimal128_fast final template BOOST_DECIMAL_FORCE_INLINE friend constexpr auto fast_inequality_impl(const DecimalType& lhs, const DecimalType& rhs) noexcept -> bool; + template + BOOST_DECIMAL_FORCE_INLINE friend constexpr auto fast_less_impl(const DecimalType& lhs, const DecimalType& rhs) noexcept -> bool; + public: constexpr decimal128_fast() noexcept = default; @@ -580,54 +583,7 @@ constexpr auto operator!=(Integer lhs, decimal128_fast rhs) noexcept constexpr auto operator<(const decimal128_fast& lhs, const decimal128_fast& rhs) noexcept -> bool { - #ifndef BOOST_DECIMAL_FAST_MATH - if (not_finite(lhs) || not_finite(rhs)) - { - 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 - - // Needed to correctly compare signed and unsigned zeros - if (lhs.significand_ == 0 || rhs.significand_ == 0) - { - 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_; - } - - if (lhs.sign_ != rhs.sign_) - { - return lhs.sign_; - } - - if (lhs.exponent_ != rhs.exponent_) - { - return lhs.sign_ ? lhs.exponent_ > rhs.exponent_ : lhs.exponent_ < rhs.exponent_; - } - - return lhs.sign_ ? lhs.significand_ > rhs.significand_ : lhs.significand_ < rhs.significand_; + return fast_less_impl(lhs, rhs); } template diff --git a/include/boost/decimal/decimal32_fast.hpp b/include/boost/decimal/decimal32_fast.hpp index ab0af279..c1546556 100644 --- a/include/boost/decimal/decimal32_fast.hpp +++ b/include/boost/decimal/decimal32_fast.hpp @@ -121,6 +121,11 @@ BOOST_DECIMAL_EXPORT class decimal32_fast final template BOOST_DECIMAL_FORCE_INLINE friend constexpr auto fast_inequality_impl(const DecimalType& lhs, const DecimalType& rhs) noexcept -> bool; + template + BOOST_DECIMAL_FORCE_INLINE friend constexpr auto fast_less_impl(const DecimalType& lhs, const DecimalType& rhs) noexcept -> bool; + + friend constexpr auto not_finite(const decimal32_fast& val) noexcept -> bool; + public: constexpr decimal32_fast() noexcept = default; @@ -499,6 +504,11 @@ constexpr auto isfinite(decimal32_fast val) noexcept -> bool return val.significand_ < detail::d32_fast_inf; } +constexpr auto not_finite(const decimal32_fast& val) noexcept -> bool +{ + return val.significand_ >= detail::d32_fast_inf; +} + constexpr auto operator==(decimal32_fast lhs, decimal32_fast rhs) noexcept -> bool { return fast_equality_impl(lhs, rhs); @@ -511,31 +521,7 @@ constexpr auto operator!=(decimal32_fast lhs, decimal32_fast rhs) noexcept -> bo constexpr auto operator<(decimal32_fast lhs, decimal32_fast rhs) noexcept -> bool { - #ifndef BOOST_DECIMAL_FAST_MATH - if (!isfinite(lhs) || !isfinite(rhs)) - { - 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 - - return fast_type_less_parts_impl(lhs.significand_, lhs.biased_exponent(), lhs.sign_, - rhs.significand_, rhs.biased_exponent(), rhs.sign_); + return fast_less_impl(lhs, rhs); } constexpr auto operator<=(decimal32_fast lhs, decimal32_fast rhs) noexcept -> bool diff --git a/include/boost/decimal/decimal64_fast.hpp b/include/boost/decimal/decimal64_fast.hpp index d1b8aafa..231633ab 100644 --- a/include/boost/decimal/decimal64_fast.hpp +++ b/include/boost/decimal/decimal64_fast.hpp @@ -138,6 +138,9 @@ BOOST_DECIMAL_EXPORT class decimal64_fast final template BOOST_DECIMAL_FORCE_INLINE friend constexpr auto fast_inequality_impl(const DecimalType& lhs, const DecimalType& rhs) noexcept -> bool; + template + BOOST_DECIMAL_FORCE_INLINE friend constexpr auto fast_less_impl(const DecimalType& lhs, const DecimalType& rhs) noexcept -> bool; + public: constexpr decimal64_fast() noexcept = default; @@ -567,54 +570,7 @@ 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 (not_finite(lhs) || not_finite(rhs)) - { - 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 - - // Needed to correctly compare signed and unsigned zeros - if (lhs.significand_ == 0 || rhs.significand_ == 0) - { - 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_; - } - - if (lhs.sign_ != rhs.sign_) - { - return lhs.sign_; - } - - if (lhs.exponent_ != rhs.exponent_) - { - return lhs.sign_ ? lhs.exponent_ > rhs.exponent_ : lhs.exponent_ < rhs.exponent_; - } - - return lhs.sign_ ? lhs.significand_ > rhs.significand_ : lhs.significand_ < rhs.significand_; + return fast_less_impl(lhs, rhs); } template diff --git a/include/boost/decimal/detail/comparison.hpp b/include/boost/decimal/detail/comparison.hpp index 83a5dabf..6c3fdec2 100644 --- a/include/boost/decimal/detail/comparison.hpp +++ b/include/boost/decimal/detail/comparison.hpp @@ -98,7 +98,7 @@ BOOST_DECIMAL_FORCE_INLINE constexpr auto equality_impl(DecimalType lhs, Decimal return lhs_sig == rhs_sig; } -template +template BOOST_DECIMAL_FORCE_INLINE constexpr auto fast_equality_impl(const DecimalType& lhs, const DecimalType& rhs) noexcept -> bool { if (lhs.exponent_ != rhs.exponent_) @@ -125,7 +125,7 @@ BOOST_DECIMAL_FORCE_INLINE constexpr auto fast_equality_impl(const DecimalType& return lhs.sign_ == rhs.sign_; } -template +template BOOST_DECIMAL_FORCE_INLINE constexpr auto fast_inequality_impl(const DecimalType& lhs, const DecimalType& rhs) noexcept -> bool { return @@ -295,6 +295,59 @@ constexpr auto operator!=(Decimal1 lhs, Decimal2 rhs) noexcept return !(mixed_decimal_equality_impl(lhs, rhs)); } +template +BOOST_DECIMAL_FORCE_INLINE constexpr auto fast_less_impl(const T& lhs, const T& rhs) noexcept -> bool +{ + #ifndef BOOST_DECIMAL_FAST_MATH + if (not_finite(lhs) || not_finite(rhs)) + { + 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 + + // Needed to correctly compare signed and unsigned zeros + if (lhs.significand_ == 0 || rhs.significand_ == 0) + { + 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_; + } + + if (lhs.sign_ != rhs.sign_) + { + return lhs.sign_; + } + + if (lhs.exponent_ != rhs.exponent_) + { + return lhs.sign_ ? lhs.exponent_ > rhs.exponent_ : lhs.exponent_ < rhs.exponent_; + } + + return lhs.sign_ ? lhs.significand_ > rhs.significand_ : lhs.significand_ < rhs.significand_; +} + template BOOST_DECIMAL_FORCE_INLINE constexpr auto fast_type_less_parts_impl(T lhs_sig, U lhs_exp, bool lhs_sign, T rhs_sig, U rhs_exp, bool rhs_sign) noexcept -> bool From 811c71592f0f2ae381022eecf4cf7fb5d2681793 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 19 Feb 2025 12:42:53 -0500 Subject: [PATCH 7/9] Consolidate operator <= implementations --- include/boost/decimal/decimal32_fast.hpp | 23 +++------------------ include/boost/decimal/decimal64_fast.hpp | 3 +++ include/boost/decimal/detail/comparison.hpp | 4 ++-- 3 files changed, 8 insertions(+), 22 deletions(-) diff --git a/include/boost/decimal/decimal32_fast.hpp b/include/boost/decimal/decimal32_fast.hpp index c1546556..57b75731 100644 --- a/include/boost/decimal/decimal32_fast.hpp +++ b/include/boost/decimal/decimal32_fast.hpp @@ -527,30 +527,13 @@ constexpr auto operator<(decimal32_fast lhs, decimal32_fast rhs) noexcept -> boo constexpr auto operator<=(decimal32_fast lhs, decimal32_fast rhs) noexcept -> bool { #ifndef BOOST_DECIMAL_FAST_MATH - if (!isfinite(lhs) || !isfinite(rhs)) + if (isnan(lhs) || isnan(rhs)) { - 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); - } + return false; } #endif - return !fast_type_less_parts_impl(rhs.significand_, rhs.biased_exponent(), rhs.sign_, - lhs.significand_, lhs.biased_exponent(), lhs.sign_); + return !(rhs < lhs); } constexpr auto operator>(decimal32_fast lhs, decimal32_fast rhs) noexcept -> bool diff --git a/include/boost/decimal/decimal64_fast.hpp b/include/boost/decimal/decimal64_fast.hpp index 231633ab..81833fe9 100644 --- a/include/boost/decimal/decimal64_fast.hpp +++ b/include/boost/decimal/decimal64_fast.hpp @@ -141,6 +141,9 @@ BOOST_DECIMAL_EXPORT class decimal64_fast final template BOOST_DECIMAL_FORCE_INLINE friend constexpr auto fast_less_impl(const DecimalType& lhs, const DecimalType& rhs) noexcept -> bool; + template + BOOST_DECIMAL_FORCE_INLINE friend constexpr auto fast_less_equal_impl(const DecimalType& lhs, const DecimalType& rhs) noexcept -> bool; + public: constexpr decimal64_fast() noexcept = default; diff --git a/include/boost/decimal/detail/comparison.hpp b/include/boost/decimal/detail/comparison.hpp index 6c3fdec2..48746f7d 100644 --- a/include/boost/decimal/detail/comparison.hpp +++ b/include/boost/decimal/detail/comparison.hpp @@ -295,8 +295,8 @@ constexpr auto operator!=(Decimal1 lhs, Decimal2 rhs) noexcept return !(mixed_decimal_equality_impl(lhs, rhs)); } -template -BOOST_DECIMAL_FORCE_INLINE constexpr auto fast_less_impl(const T& lhs, const T& rhs) noexcept -> bool +template +BOOST_DECIMAL_FORCE_INLINE constexpr auto fast_less_impl(const DecimalType& lhs, const DecimalType& rhs) noexcept -> bool { #ifndef BOOST_DECIMAL_FAST_MATH if (not_finite(lhs) || not_finite(rhs)) From fab3bb64161e1bd4bb7456929d9dce2a281e82f7 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 19 Feb 2025 12:44:59 -0500 Subject: [PATCH 8/9] Consolidate operator >= impl --- include/boost/decimal/decimal32_fast.hpp | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/include/boost/decimal/decimal32_fast.hpp b/include/boost/decimal/decimal32_fast.hpp index 57b75731..a391f52b 100644 --- a/include/boost/decimal/decimal32_fast.hpp +++ b/include/boost/decimal/decimal32_fast.hpp @@ -544,29 +544,13 @@ constexpr auto operator>(decimal32_fast lhs, decimal32_fast rhs) noexcept -> boo constexpr auto operator>=(decimal32_fast lhs, decimal32_fast rhs) noexcept -> bool { #ifndef BOOST_DECIMAL_FAST_MATH - if (!isfinite(lhs) || !isfinite(rhs)) + if (isnan(lhs) || isnan(rhs)) { - if (isnan(lhs) || isnan(rhs)) - { - return false; - } - else if (lhs.isneg() && !rhs.isneg()) - { - return false; - } - else if (isfinite(lhs) && isinf(rhs)) - { - return signbit(rhs); - } - else if (isinf(lhs) && isfinite(rhs)) - { - return !signbit(lhs); - } + return false; } #endif - return !fast_type_less_parts_impl(lhs.significand_, lhs.biased_exponent(), lhs.sign_, - rhs.significand_, rhs.biased_exponent(), rhs.sign_); + return !(lhs < rhs); } template From 35c3ce6cb8eb2673c53a91e0ba419c83caf1b806 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 19 Feb 2025 13:04:16 -0500 Subject: [PATCH 9/9] Remove IDE added header --- include/boost/decimal/decimal128_fast.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/include/boost/decimal/decimal128_fast.hpp b/include/boost/decimal/decimal128_fast.hpp index 6d4a2618..277065a6 100644 --- a/include/boost/decimal/decimal128_fast.hpp +++ b/include/boost/decimal/decimal128_fast.hpp @@ -14,7 +14,6 @@ #include #include #include -#include #ifndef BOOST_DECIMAL_BUILD_MODULE