14824e7fdSDimitry Andric //===----------------------------------------------------------------------===// 24824e7fdSDimitry Andric // 34824e7fdSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 44824e7fdSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 54824e7fdSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 64824e7fdSDimitry Andric // 74824e7fdSDimitry Andric //===----------------------------------------------------------------------===// 84824e7fdSDimitry Andric 94824e7fdSDimitry Andric #ifndef _LIBCPP___COMPARE_WEAK_ORDER 104824e7fdSDimitry Andric #define _LIBCPP___COMPARE_WEAK_ORDER 114824e7fdSDimitry Andric 124824e7fdSDimitry Andric #include <__compare/compare_three_way.h> 134824e7fdSDimitry Andric #include <__compare/ordering.h> 144824e7fdSDimitry Andric #include <__compare/strong_order.h> 154824e7fdSDimitry Andric #include <__config> 16*0fca6ea1SDimitry Andric #include <__math/traits.h> 17bdd1243dSDimitry Andric #include <__type_traits/decay.h> 18*0fca6ea1SDimitry Andric #include <__type_traits/is_floating_point.h> 19*0fca6ea1SDimitry Andric #include <__type_traits/is_same.h> 204824e7fdSDimitry Andric #include <__utility/forward.h> 214824e7fdSDimitry Andric #include <__utility/priority_tag.h> 224824e7fdSDimitry Andric 234824e7fdSDimitry Andric #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER 244824e7fdSDimitry Andric # pragma GCC system_header 254824e7fdSDimitry Andric #endif 264824e7fdSDimitry Andric 274824e7fdSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 284824e7fdSDimitry Andric 2906c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20 304824e7fdSDimitry Andric 314824e7fdSDimitry Andric // [cmp.alg] 324824e7fdSDimitry Andric namespace __weak_order { 33*0fca6ea1SDimitry Andric void weak_order() = delete; 34*0fca6ea1SDimitry Andric 354824e7fdSDimitry Andric struct __fn { 36bdd1243dSDimitry Andric // NOLINTBEGIN(libcpp-robust-against-adl) weak_order should use ADL, but only here 374824e7fdSDimitry Andric template <class _Tp, class _Up> 384824e7fdSDimitry Andric requires is_same_v<decay_t<_Tp>, decay_t<_Up>> 39cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI static constexpr auto __go(_Tp&& __t, _Up&& __u, __priority_tag<3>) noexcept( 40cb14a3feSDimitry Andric noexcept(weak_ordering(weak_order(std::forward<_Tp>(__t), std::forward<_Up>(__u))))) 41cb14a3feSDimitry Andric -> decltype(weak_ordering(weak_order(std::forward<_Tp>(__t), std::forward<_Up>(__u)))) { 42cb14a3feSDimitry Andric return weak_ordering(weak_order(std::forward<_Tp>(__t), std::forward<_Up>(__u))); 43cb14a3feSDimitry Andric } 44bdd1243dSDimitry Andric // NOLINTEND(libcpp-robust-against-adl) 454824e7fdSDimitry Andric 464824e7fdSDimitry Andric template <class _Tp, class _Up, class _Dp = decay_t<_Tp>> 474824e7fdSDimitry Andric requires is_same_v<_Dp, decay_t<_Up>> && is_floating_point_v<_Dp> 48cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI static constexpr weak_ordering __go(_Tp&& __t, _Up&& __u, __priority_tag<2>) noexcept { 490eae32dcSDimitry Andric partial_ordering __po = (__t <=> __u); 500eae32dcSDimitry Andric if (__po == partial_ordering::less) { 510eae32dcSDimitry Andric return weak_ordering::less; 520eae32dcSDimitry Andric } else if (__po == partial_ordering::equivalent) { 530eae32dcSDimitry Andric return weak_ordering::equivalent; 540eae32dcSDimitry Andric } else if (__po == partial_ordering::greater) { 550eae32dcSDimitry Andric return weak_ordering::greater; 564824e7fdSDimitry Andric } else { 574824e7fdSDimitry Andric // Otherwise, at least one of them is a NaN. 58*0fca6ea1SDimitry Andric bool __t_is_nan = __math::isnan(__t); 59*0fca6ea1SDimitry Andric bool __u_is_nan = __math::isnan(__u); 60*0fca6ea1SDimitry Andric bool __t_is_negative = __math::signbit(__t); 61*0fca6ea1SDimitry Andric bool __u_is_negative = __math::signbit(__u); 624824e7fdSDimitry Andric if (__t_is_nan && __u_is_nan) { 634824e7fdSDimitry Andric return (__u_is_negative <=> __t_is_negative); 644824e7fdSDimitry Andric } else if (__t_is_nan) { 654824e7fdSDimitry Andric return __t_is_negative ? weak_ordering::less : weak_ordering::greater; 664824e7fdSDimitry Andric } else { 674824e7fdSDimitry Andric return __u_is_negative ? weak_ordering::greater : weak_ordering::less; 684824e7fdSDimitry Andric } 694824e7fdSDimitry Andric } 704824e7fdSDimitry Andric } 714824e7fdSDimitry Andric 724824e7fdSDimitry Andric template <class _Tp, class _Up> 734824e7fdSDimitry Andric requires is_same_v<decay_t<_Tp>, decay_t<_Up>> 74cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI static constexpr auto __go(_Tp&& __t, _Up&& __u, __priority_tag<1>) noexcept( 75cb14a3feSDimitry Andric noexcept(weak_ordering(compare_three_way()(std::forward<_Tp>(__t), std::forward<_Up>(__u))))) 76cb14a3feSDimitry Andric -> decltype(weak_ordering(compare_three_way()(std::forward<_Tp>(__t), std::forward<_Up>(__u)))) { 77cb14a3feSDimitry Andric return weak_ordering(compare_three_way()(std::forward<_Tp>(__t), std::forward<_Up>(__u))); 78cb14a3feSDimitry Andric } 794824e7fdSDimitry Andric 804824e7fdSDimitry Andric template <class _Tp, class _Up> 814824e7fdSDimitry Andric requires is_same_v<decay_t<_Tp>, decay_t<_Up>> 82cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI static constexpr auto __go(_Tp&& __t, _Up&& __u, __priority_tag<0>) noexcept( 83cb14a3feSDimitry Andric noexcept(weak_ordering(std::strong_order(std::forward<_Tp>(__t), std::forward<_Up>(__u))))) 84cb14a3feSDimitry Andric -> decltype(weak_ordering(std::strong_order(std::forward<_Tp>(__t), std::forward<_Up>(__u)))) { 85cb14a3feSDimitry Andric return weak_ordering(std::strong_order(std::forward<_Tp>(__t), std::forward<_Up>(__u))); 86cb14a3feSDimitry Andric } 874824e7fdSDimitry Andric 884824e7fdSDimitry Andric template <class _Tp, class _Up> 894824e7fdSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t, _Up&& __u) const 905f757f3fSDimitry Andric noexcept(noexcept(__go(std::forward<_Tp>(__t), std::forward<_Up>(__u), __priority_tag<3>()))) 91cb14a3feSDimitry Andric -> decltype(__go(std::forward<_Tp>(__t), std::forward<_Up>(__u), __priority_tag<3>())) { 92cb14a3feSDimitry Andric return __go(std::forward<_Tp>(__t), std::forward<_Up>(__u), __priority_tag<3>()); 93cb14a3feSDimitry Andric } 944824e7fdSDimitry Andric }; 954824e7fdSDimitry Andric } // namespace __weak_order 964824e7fdSDimitry Andric 974824e7fdSDimitry Andric inline namespace __cpo { 984824e7fdSDimitry Andric inline constexpr auto weak_order = __weak_order::__fn{}; 994824e7fdSDimitry Andric } // namespace __cpo 1004824e7fdSDimitry Andric 10106c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 20 1024824e7fdSDimitry Andric 1034824e7fdSDimitry Andric _LIBCPP_END_NAMESPACE_STD 1044824e7fdSDimitry Andric 1054824e7fdSDimitry Andric #endif // _LIBCPP___COMPARE_WEAK_ORDER 106