Skip to content

Commit 9e61fca

Browse files
authored
Merge pull request #730 from cppalliance/64_bit_comps
Improved comparisons for `decimal64`
2 parents cb7f7b0 + 13726f3 commit 9e61fca

File tree

2 files changed

+25
-18
lines changed

2 files changed

+25
-18
lines changed

include/boost/decimal/decimal64.hpp

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,9 @@ BOOST_DECIMAL_EXPORT class decimal64 final
222222
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE DecimalType>
223223
friend constexpr auto equality_impl(DecimalType lhs, DecimalType rhs) noexcept -> bool;
224224

225+
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE DecimalType>
226+
friend constexpr auto sequential_less_impl(DecimalType lhs, DecimalType rhs) noexcept -> bool;
227+
225228
public:
226229
// 3.2.3.1 construct/copy/destroy
227230
constexpr decimal64() noexcept = default;
@@ -1625,16 +1628,7 @@ constexpr auto decimal64::operator%=(decimal64 rhs) noexcept -> decimal64&
16251628

16261629
constexpr auto operator==(decimal64 lhs, decimal64 rhs) noexcept -> bool
16271630
{
1628-
#ifndef BOOST_DECIMAL_FAST_MATH
1629-
// Check for IEEE requirement that nan != nan
1630-
if (isnan(lhs) || isnan(rhs))
1631-
{
1632-
return false;
1633-
}
1634-
#endif
1635-
1636-
return equal_parts_impl<decimal64>(lhs.full_significand(), lhs.biased_exponent(), lhs.isneg(),
1637-
rhs.full_significand(), rhs.biased_exponent(), rhs.isneg());
1631+
return equality_impl(lhs, rhs);
16381632
}
16391633

16401634
template <typename Integer>
@@ -1691,8 +1685,7 @@ constexpr auto operator<(decimal64 lhs, decimal64 rhs) noexcept -> bool
16911685
}
16921686
#endif
16931687

1694-
return less_parts_impl<decimal64>(lhs.full_significand(), lhs.biased_exponent(), lhs.isneg(),
1695-
rhs.full_significand(), rhs.biased_exponent(), rhs.isneg());
1688+
return sequential_less_impl(lhs, rhs);
16961689
}
16971690

16981691
template <typename Integer>

include/boost/decimal/detail/comparison.hpp

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <boost/decimal/detail/cmath/isfinite.hpp>
1616
#include <boost/decimal/detail/concepts.hpp>
1717
#include <boost/decimal/detail/power_tables.hpp>
18+
#include <boost/decimal/detail/emulated128.hpp>
1819

1920
#ifndef BOOST_DECIMAL_BUILD_MODULE
2021
#include <limits>
@@ -51,17 +52,18 @@ BOOST_DECIMAL_FORCE_INLINE constexpr auto equality_impl(DecimalType lhs, Decimal
5152
const auto lhs_exp {lhs.biased_exponent()};
5253
const auto rhs_exp {rhs.biased_exponent()};
5354

55+
auto lhs_sig {lhs.full_significand()};
56+
auto rhs_sig {rhs.full_significand()};
57+
5458
const auto delta_exp {lhs_exp - rhs_exp};
5559

56-
if (delta_exp > detail::precision_v<DecimalType> || delta_exp < -detail::precision_v<DecimalType>)
60+
if (delta_exp > detail::precision_v<DecimalType> || delta_exp < -detail::precision_v<DecimalType> ||
61+
((lhs_sig == static_cast<comp_type>(0)) ^ (rhs_sig == static_cast<comp_type>(0))))
5762
{
5863
return false;
5964
}
6065

6166
// Step 5: Normalize the significand and compare
62-
auto lhs_sig {lhs.full_significand()};
63-
auto rhs_sig {rhs.full_significand()};
64-
6567
delta_exp >= 0 ? lhs_sig *= detail::pow10(static_cast<comp_type>(delta_exp)) :
6668
rhs_sig *= detail::pow10(static_cast<comp_type>(-delta_exp));
6769

@@ -244,7 +246,19 @@ BOOST_DECIMAL_FORCE_INLINE constexpr auto fast_type_less_parts_impl(T lhs_sig, U
244246
template <BOOST_DECIMAL_DECIMAL_FLOATING_TYPE DecimalType>
245247
constexpr auto sequential_less_impl(DecimalType lhs, DecimalType rhs) noexcept -> bool
246248
{
247-
using comp_type = std::uint_fast64_t;
249+
using comp_type = std::conditional_t<std::is_same<DecimalType, decimal32>::value, std::uint_fast64_t,
250+
// GCC less than 10 in non-GNU mode, Clang < 10 and MinGW all have issues with the built-in u128,
251+
// so use the emulated one
252+
#if defined(BOOST_DECIMAL_HAS_INT128)
253+
#if ( (defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 10) || (defined(__clang__) && __clang_major__ < 13) )
254+
detail::uint128
255+
# else
256+
detail::uint128_t
257+
# endif
258+
#else
259+
detail::uint128
260+
#endif
261+
>;
248262

249263
// Step 1: Handle our non-finite values in their own calling functions
250264

@@ -278,7 +292,7 @@ constexpr auto sequential_less_impl(DecimalType lhs, DecimalType rhs) noexcept -
278292
auto rhs_exp {rhs.biased_exponent()};
279293

280294
const auto delta_exp {lhs_exp - rhs_exp};
281-
constexpr auto max_delta_diff {std::numeric_limits<std::uint_fast64_t>::digits10 - detail::precision_v<DecimalType>};
295+
constexpr auto max_delta_diff {std::numeric_limits<comp_type>::digits10 - detail::precision_v<DecimalType>};
282296

283297
if (delta_exp > max_delta_diff || delta_exp < -max_delta_diff)
284298
{

0 commit comments

Comments
 (0)