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. --- I bundled the removal of _N_cmp and putting unordered in _Ord here, it is related, as new helpers now cleary can operate with one enumerator. Tested on x86_64-linux locally. Testing on powerpc64le. OK for trunk? libstdc++-v3/libsupc++/compare | 79 +++++++++++++++------------------- 1 file changed, 35 insertions(+), 44 deletions(-) diff --git a/libstdc++-v3/libsupc++/compare b/libstdc++-v3/libsupc++/compare index ef0f0376964..7722e205190 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) + { return _Ord(__o._M_value); } + + template<typename _Ordering> + [[__gnu__::__always_inline__]] + constexpr _Ordering + __make(_Ord __o) + { return _Ordering(__o); } struct __unspec { @@ -74,22 +89,17 @@ 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); + friend constexpr partial_ordering __cmp_cat::__make<>(__cmp_cat::_Ord); + public: // valid values static const partial_ordering less; @@ -155,7 +165,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 +179,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 +189,8 @@ 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); + friend constexpr weak_ordering __cmp_cat::__make<>(__cmp_cat::_Ord); public: // valid values @@ -189,7 +200,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 +282,9 @@ namespace std _GLIBCXX_VISIBILITY(default) : _M_value(__cmp_cat::type(__v)) { } + friend constexpr __cmp_cat::_Ord __cmp_cat::__ord<>(strong_ordering); + friend constexpr strong_ordering __cmp_cat::__make<>(__cmp_cat::_Ord); + public: // valid values static const strong_ordering less; @@ -280,11 +294,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 +598,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 +609,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); } } -- 2.50.1