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

Reply via email to