diff options
author | Tomasz Kamiński <tkaminsk@redhat.com> | 2025-08-28 11:10:05 +0200 |
---|---|---|
committer | Tomasz Kamiński <tkaminsk@redhat.com> | 2025-08-28 14:40:48 +0200 |
commit | fcb5cd8e9483daafd6f786f3b607028cb1293ce7 (patch) | |
tree | f23827a47d8a5e8dfb427cdceba190730b78ac33 | |
parent | 10418a6cbd34e0a4081f6dcdf8c36a9592aaf318 (diff) | |
download | gcc-fcb5cd8e9483daafd6f786f3b607028cb1293ce7.zip gcc-fcb5cd8e9483daafd6f786f3b607028cb1293ce7.tar.gz gcc-fcb5cd8e9483daafd6f786f3b607028cb1293ce7.tar.bz2 |
libstdc++: Provide helpers to interoperate between __cmp_cat::_Ord and ordering types.
This patch adds two new internal helpers for ordering types:
* __cmp_cat::__ord to retrieve an internal _Ord value,
* __cmp_cat::__make<Ordering> to create an ordering from an _Ord value.
Conversions between ordering types are now handled by __cmp_cat::__make. As a
result, ordering types no longer need to befriend each other, only the new
helpers.
The __fp_weak_ordering implementation has also been simplified by:
* using the new helpers to convert partial_ordering to weak_ordering,
* using strong_ordering to weak_ordering conversion operator,
for the __isnan_sign comparison,
* removing the unused __cat local variable.
Finally, the _Ncmp enum is removed, and the unordered enumerator is added
to the existing _Ord enum.
libstdc++-v3/ChangeLog:
* libsupc++/compare (__cmp_cat::_Ord): Add unordered enumerator.
(__cmp_cat::_Ncmp): Remove.
(__cmp_cat::__ord, __cmp_cat::__make): Define.
(partial_ordering::partial_ordering(__cmp_cat::_Ncmp)): Remove.
(operator<=>(__cmp_cat::__unspec, partial_ordering))
(partial_ordering::unordered): Replace _Ncmp with _Ord.
(std::partial_ordering, std::weak_ordering, std::strong_ordering):
Befriend __ord and __make helpers, remove friend declartions for
other orderings.
(__compare::__fp_weak_ordering): Remove unused __cat variable.
Simplify ordering conversions.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
-rw-r--r-- | libstdc++-v3/libsupc++/compare | 85 |
1 files changed, 41 insertions, 44 deletions
diff --git a/libstdc++-v3/libsupc++/compare b/libstdc++-v3/libsupc++/compare index ef0f037..ca7c909 100644 --- a/libstdc++-v3/libsupc++/compare +++ b/libstdc++-v3/libsupc++/compare @@ -54,9 +54,24 @@ namespace std _GLIBCXX_VISIBILITY(default) { using type = signed char; - enum class _Ord : type { equivalent = 0, less = -1, greater = 1 }; + enum class _Ord : type + { + equivalent = 0, less = -1, greater = 1, + // value remains unchanged when negated + unordered = -__SCHAR_MAX__ - 1 + }; - enum class _Ncmp : type { unordered = -__SCHAR_MAX__ - 1 }; + template<typename _Ordering> + [[__gnu__::__always_inline__]] + constexpr _Ord + __ord(_Ordering __o) noexcept + { return _Ord(__o._M_value); } + + template<typename _Ordering> + [[__gnu__::__always_inline__]] + constexpr _Ordering + __make(_Ord __o) noexcept + { return _Ordering(__o); } struct __unspec { @@ -74,22 +89,19 @@ namespace std _GLIBCXX_VISIBILITY(default) : _M_value(__cmp_cat::type(__v)) { } - constexpr explicit - partial_ordering(__cmp_cat::_Ncmp __v) noexcept - : _M_value(__cmp_cat::type(__v)) - { } - - friend class weak_ordering; - friend class strong_ordering; - [[__gnu__::__always_inline__]] constexpr __cmp_cat::type _M_reverse() const { - // leaves _Ncmp::unordered unchanged + // leaves _Ord::unordered unchanged return static_cast<__cmp_cat::type>(-_M_value); } + friend constexpr __cmp_cat::_Ord + __cmp_cat::__ord<partial_ordering>(partial_ordering) noexcept; + friend constexpr partial_ordering + __cmp_cat::__make<partial_ordering>(__cmp_cat::_Ord) noexcept; + public: // valid values static const partial_ordering less; @@ -155,7 +167,7 @@ namespace std _GLIBCXX_VISIBILITY(default) [[nodiscard]] friend constexpr partial_ordering operator<=>(__cmp_cat::__unspec, partial_ordering __v) noexcept - { return partial_ordering(__cmp_cat::_Ncmp(__v._M_reverse())); } + { return partial_ordering(__cmp_cat::_Ord(__v._M_reverse())); } }; // valid values' definitions @@ -169,7 +181,7 @@ namespace std _GLIBCXX_VISIBILITY(default) partial_ordering::greater(__cmp_cat::_Ord::greater); inline constexpr partial_ordering - partial_ordering::unordered(__cmp_cat::_Ncmp::unordered); + partial_ordering::unordered(__cmp_cat::_Ord::unordered); class weak_ordering { @@ -179,7 +191,10 @@ namespace std _GLIBCXX_VISIBILITY(default) weak_ordering(__cmp_cat::_Ord __v) noexcept : _M_value(__cmp_cat::type(__v)) { } - friend class strong_ordering; + friend constexpr __cmp_cat::_Ord + __cmp_cat::__ord<weak_ordering>(weak_ordering) noexcept; + friend constexpr weak_ordering + __cmp_cat::__make<weak_ordering>(__cmp_cat::_Ord) noexcept; public: // valid values @@ -189,7 +204,7 @@ namespace std _GLIBCXX_VISIBILITY(default) [[nodiscard]] constexpr operator partial_ordering() const noexcept - { return partial_ordering(__cmp_cat::_Ord(_M_value)); } + { return __cmp_cat::__make<partial_ordering>(__cmp_cat::_Ord(_M_value)); } // comparisons [[nodiscard]] @@ -271,6 +286,11 @@ namespace std _GLIBCXX_VISIBILITY(default) : _M_value(__cmp_cat::type(__v)) { } + friend constexpr __cmp_cat::_Ord + __cmp_cat::__ord<strong_ordering>(strong_ordering) noexcept; + friend constexpr strong_ordering + __cmp_cat::__make<strong_ordering>(__cmp_cat::_Ord) noexcept; + public: // valid values static const strong_ordering less; @@ -280,11 +300,11 @@ namespace std _GLIBCXX_VISIBILITY(default) [[nodiscard]] constexpr operator partial_ordering() const noexcept - { return partial_ordering(__cmp_cat::_Ord(_M_value)); } + { return __cmp_cat::__make<partial_ordering>(__cmp_cat::_Ord(_M_value)); } [[nodiscard]] constexpr operator weak_ordering() const noexcept - { return weak_ordering(__cmp_cat::_Ord(_M_value)); } + { return __cmp_cat::__make<weak_ordering>(__cmp_cat::_Ord(_M_value)); } // comparisons [[nodiscard]] @@ -584,26 +604,9 @@ namespace std _GLIBCXX_VISIBILITY(default) constexpr weak_ordering __fp_weak_ordering(_Tp __e, _Tp __f) { - // Returns an integer with the same sign as the argument, and magnitude - // indicating the classification: zero=1 subnorm=2 norm=3 inf=4 nan=5 - auto __cat = [](_Tp __fp) -> int { - const int __sign = __builtin_signbit(__fp) ? -1 : 1; - if (__builtin_isnormal(__fp)) - return (__fp == 0 ? 1 : 3) * __sign; - if (__builtin_isnan(__fp)) - return 5 * __sign; - if (int __inf = __builtin_isinf_sign(__fp)) - return 4 * __inf; - return 2 * __sign; - }; - - auto __po = __e <=> __f; - if (is_lt(__po)) - return weak_ordering::less; - else if (is_gt(__po)) - return weak_ordering::greater; - else if (__po == partial_ordering::equivalent) - return weak_ordering::equivalent; + auto __po = __cmp_cat::__ord(__e <=> __f); + if (__po != __cmp_cat::_Ord::unordered) + return __cmp_cat::__make<weak_ordering>(__po); else // unordered, at least one argument is NaN { // return -1 for negative nan, +1 for positive nan, 0 otherwise. @@ -612,13 +615,7 @@ namespace std _GLIBCXX_VISIBILITY(default) ? __builtin_signbit(__fp) ? -1 : 1 : 0; }; - auto __ord = __isnan_sign(__e) <=> __isnan_sign(__f); - if (is_eq(__ord)) - return weak_ordering::equivalent; - else if (is_lt(__ord)) - return weak_ordering::less; - else - return weak_ordering::greater; + return __isnan_sign(__e) <=> __isnan_sign(__f); } } |