Re: [PATCH] libsupc++: Implement comparison algorithms for C++20

2019-11-13 Thread Jonathan Wakely

On 13/11/19 18:52 +0100, Daniel Krügler wrote:

Am Mi., 13. Nov. 2019 um 17:26 Uhr schrieb Jonathan Wakely :


This is incomplete because std::strong_order doesn't support
floating-point types.


I'm wondering whether the local __cat lambda expression at the
beginning of __fp_weak_ordering is part of the incomplete code or just
spurious?


Oops, it's spurious. That was part of a previous implementation, but
is no longer used. I'll remove that.

__fp_weak_order is complete, it's the strong_order implementation for
floating-point types that's missing. I'll be posting that in reply to
https://gcc.gnu.org/ml/libstdc++/2019-11/msg00011.html in a few
minutes.

However, I think __fp_weak_order will fail for __float128 because
comparisons involving 128-bit NaNs are not valid in constant
expressions. I'll add some tests with __float128 and investigate that.



Re: [PATCH] libsupc++: Implement comparison algorithms for C++20

2019-11-13 Thread Daniel Krügler
Am Mi., 13. Nov. 2019 um 17:26 Uhr schrieb Jonathan Wakely :
>
> This is incomplete because std::strong_order doesn't support
> floating-point types.

I'm wondering whether the local __cat lambda expression at the
beginning of __fp_weak_ordering is part of the incomplete code or just
spurious?

- Daniel


[PATCH] libsupc++: Implement comparison algorithms for C++20

2019-11-13 Thread Jonathan Wakely

This is incomplete because std::strong_order doesn't support
floating-point types.

The partial_order and weak_order tests use VERIFY instead of
static_assert because of PR 92431.

* libsupc++/compare (strong_order, weak_order, partial_order)
(compare_strong_order_fallback, compare_weak_order_fallback)
(compare_partial_order_fallback): Define customization point objects
for C++20.
* testsuite/18_support/comparisons/algorithms/partial_order.cc: New
test.
* testsuite/18_support/comparisons/algorithms/strong_order.cc: New
test.
* testsuite/18_support/comparisons/algorithms/weak_order.cc: New test.

Tested powerpc64le-linux, committed to trunk.

commit e4dc0c07ed229d6efca300b42753fcd365db0085
Author: Jonathan Wakely 
Date:   Thu Nov 7 21:58:46 2019 +

libsupc++: Implement comparison algorithms for C++20

This is incomplete because std::strong_order doesn't support
floating-point types.

The partial_order and weak_order tests use VERIFY instead of
static_assert because of PR 92431.

* libsupc++/compare (strong_order, weak_order, partial_order)
(compare_strong_order_fallback, compare_weak_order_fallback)
(compare_partial_order_fallback): Define customization point objects
for C++20.
* testsuite/18_support/comparisons/algorithms/partial_order.cc: New
test.
* testsuite/18_support/comparisons/algorithms/strong_order.cc: New
test.
* testsuite/18_support/comparisons/algorithms/weak_order.cc: New 
test.

diff --git a/libstdc++-v3/libsupc++/compare b/libstdc++-v3/libsupc++/compare
index 94728e29de8..289145dea56 100644
--- a/libstdc++-v3/libsupc++/compare
+++ b/libstdc++-v3/libsupc++/compare
@@ -576,20 +576,346 @@ namespace std
 using is_transparent = void;
   };
 
+  namespace __cmp_cust
+  {
+template
+  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;
+   else  // unordered, at least one argument is NaN
+ {
+   // return -1 for negative nan, +1 for positive nan, 0 otherwise.
+   auto __isnan_sign = [](_Tp __fp) -> int {
+ return __builtin_isnan(__fp)
+   ? __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;
+ }
+  }
+
+template
+  concept __adl_strong = requires(_Tp&& __t, _Up&& __u)
+   {
+ strong_ordering(strong_order(static_cast<_Tp&&>(__t),
+  static_cast<_Up&&>(__u)));
+   };
+
+template
+  concept __adl_weak = requires(_Tp&& __t, _Up&& __u)
+   {
+ weak_ordering(weak_order(static_cast<_Tp&&>(__t),
+  static_cast<_Up&&>(__u)));
+   };
+
+template
+  concept __adl_partial = requires(_Tp&& __t, _Up&& __u)
+   {
+ partial_ordering(partial_order(static_cast<_Tp&&>(__t),
+static_cast<_Up&&>(__u)));
+   };
+
+template
+  concept __op_cmp = requires(_Tp&& __t, _Up&& __u)
+   {
+ _Ord(static_cast<_Tp&&>(__t) <=> static_cast<_Up&&>(__u));
+   };
+
+template
+  concept __strongly_ordered
+   = __adl_strong<_Tp, _Up>
+ // FIXME: || floating_point>
+ || __op_cmp;
+
+class _Strong_order
+{
+  template
+   static constexpr bool
+   _S_noexcept()
+   {
+ if constexpr (floating_point>)
+   return true;
+ else if constexpr (__adl_strong<_Tp, _Up>)
+   return noexcept(strong_ordering(strong_order(std::declval<_Tp>(),
+std::declval<_Up>(;
+ else if constexpr (__op_cmp)
+   return noexcept(std::declval<_Tp>() <=> std::declval<_Up>());
+   }
+
+  friend class _W