1// -*- C++ -*- 2//===-------------------------- compare -----------------------------------===// 3// 4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5// See https://llvm.org/LICENSE.txt for license information. 6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7// 8//===----------------------------------------------------------------------===// 9 10#ifndef _LIBCPP_COMPARE 11#define _LIBCPP_COMPARE 12 13/* 14 compare synopsis 15 16namespace std { 17 // [cmp.categories], comparison category types 18 class partial_ordering; 19 class weak_ordering; 20 class strong_ordering; 21 22 // named comparison functions 23 constexpr bool is_eq (partial_ordering cmp) noexcept { return cmp == 0; } 24 constexpr bool is_neq (partial_ordering cmp) noexcept { return cmp != 0; } 25 constexpr bool is_lt (partial_ordering cmp) noexcept { return cmp < 0; } 26 constexpr bool is_lteq(partial_ordering cmp) noexcept { return cmp <= 0; } 27 constexpr bool is_gt (partial_ordering cmp) noexcept { return cmp > 0; } 28 constexpr bool is_gteq(partial_ordering cmp) noexcept { return cmp >= 0; } 29 30 // [cmp.common], common comparison category type 31 template<class... Ts> 32 struct common_comparison_category { 33 using type = see below; 34 }; 35 template<class... Ts> 36 using common_comparison_category_t = typename common_comparison_category<Ts...>::type; 37 38 // [cmp.alg], comparison algorithms 39 template<class T> constexpr strong_ordering strong_order(const T& a, const T& b); 40 template<class T> constexpr weak_ordering weak_order(const T& a, const T& b); 41 template<class T> constexpr partial_ordering partial_order(const T& a, const T& b); 42 43 // [cmp.partialord], Class partial_ordering 44 class partial_ordering { 45 public: 46 // valid values 47 static const partial_ordering less; 48 static const partial_ordering equivalent; 49 static const partial_ordering greater; 50 static const partial_ordering unordered; 51 52 // comparisons 53 friend constexpr bool operator==(partial_ordering v, unspecified) noexcept; 54 friend constexpr bool operator==(partial_ordering v, partial_ordering w) noexcept = default; 55 friend constexpr bool operator< (partial_ordering v, unspecified) noexcept; 56 friend constexpr bool operator> (partial_ordering v, unspecified) noexcept; 57 friend constexpr bool operator<=(partial_ordering v, unspecified) noexcept; 58 friend constexpr bool operator>=(partial_ordering v, unspecified) noexcept; 59 friend constexpr bool operator< (unspecified, partial_ordering v) noexcept; 60 friend constexpr bool operator> (unspecified, partial_ordering v) noexcept; 61 friend constexpr bool operator<=(unspecified, partial_ordering v) noexcept; 62 friend constexpr bool operator>=(unspecified, partial_ordering v) noexcept; 63 friend constexpr partial_ordering operator<=>(partial_ordering v, unspecified) noexcept; 64 friend constexpr partial_ordering operator<=>(unspecified, partial_ordering v) noexcept; 65 }; 66 67 // [cmp.weakord], Class weak_ordering 68 class weak_ordering { 69 public: 70 // valid values 71 static const weak_ordering less; 72 static const weak_ordering equivalent; 73 static const weak_ordering greater; 74 75 // conversions 76 constexpr operator partial_ordering() const noexcept; 77 78 // comparisons 79 friend constexpr bool operator==(weak_ordering v, unspecified) noexcept; 80 friend constexpr bool operator==(weak_ordering v, weak_ordering w) noexcept = default; 81 friend constexpr bool operator< (weak_ordering v, unspecified) noexcept; 82 friend constexpr bool operator> (weak_ordering v, unspecified) noexcept; 83 friend constexpr bool operator<=(weak_ordering v, unspecified) noexcept; 84 friend constexpr bool operator>=(weak_ordering v, unspecified) noexcept; 85 friend constexpr bool operator< (unspecified, weak_ordering v) noexcept; 86 friend constexpr bool operator> (unspecified, weak_ordering v) noexcept; 87 friend constexpr bool operator<=(unspecified, weak_ordering v) noexcept; 88 friend constexpr bool operator>=(unspecified, weak_ordering v) noexcept; 89 friend constexpr weak_ordering operator<=>(weak_ordering v, unspecified) noexcept; 90 friend constexpr weak_ordering operator<=>(unspecified, weak_ordering v) noexcept; 91 }; 92 93 // [cmp.strongord], Class strong_ordering 94 class strong_ordering { 95 public: 96 // valid values 97 static const strong_ordering less; 98 static const strong_ordering equal; 99 static const strong_ordering equivalent; 100 static const strong_ordering greater; 101 102 // conversions 103 constexpr operator partial_ordering() const noexcept; 104 constexpr operator weak_ordering() const noexcept; 105 106 // comparisons 107 friend constexpr bool operator==(strong_ordering v, unspecified) noexcept; 108 friend constexpr bool operator==(strong_ordering v, strong_ordering w) noexcept = default; 109 friend constexpr bool operator< (strong_ordering v, unspecified) noexcept; 110 friend constexpr bool operator> (strong_ordering v, unspecified) noexcept; 111 friend constexpr bool operator<=(strong_ordering v, unspecified) noexcept; 112 friend constexpr bool operator>=(strong_ordering v, unspecified) noexcept; 113 friend constexpr bool operator< (unspecified, strong_ordering v) noexcept; 114 friend constexpr bool operator> (unspecified, strong_ordering v) noexcept; 115 friend constexpr bool operator<=(unspecified, strong_ordering v) noexcept; 116 friend constexpr bool operator>=(unspecified, strong_ordering v) noexcept; 117 friend constexpr strong_ordering operator<=>(strong_ordering v, unspecified) noexcept; 118 friend constexpr strong_ordering operator<=>(unspecified, strong_ordering v) noexcept; 119 }; 120} 121*/ 122 123#include <__config> 124#include <type_traits> 125 126#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER 127#pragma GCC system_header 128#endif 129 130_LIBCPP_BEGIN_NAMESPACE_STD 131 132#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) 133// exposition only 134enum class _LIBCPP_ENUM_VIS _EqResult : unsigned char { 135 __zero = 0, 136 __equal = __zero, 137 __equiv = __equal, 138 __nonequal = 1, 139 __nonequiv = __nonequal 140}; 141 142enum class _LIBCPP_ENUM_VIS _OrdResult : signed char { 143 __less = -1, 144 __greater = 1 145}; 146 147enum class _LIBCPP_ENUM_VIS _NCmpResult : signed char { 148 __unordered = -127 149}; 150 151struct _CmpUnspecifiedParam { 152 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEVAL 153 _CmpUnspecifiedParam(int _CmpUnspecifiedParam::*) noexcept {} 154 155 template<typename _Tp, typename = enable_if_t<!is_same_v<_Tp, int>>> 156 _CmpUnspecifiedParam(_Tp) = delete; 157}; 158 159class partial_ordering { 160 using _ValueT = signed char; 161 162 _LIBCPP_INLINE_VISIBILITY 163 explicit constexpr partial_ordering(_EqResult __v) noexcept 164 : __value_(_ValueT(__v)) {} 165 166 _LIBCPP_INLINE_VISIBILITY 167 explicit constexpr partial_ordering(_OrdResult __v) noexcept 168 : __value_(_ValueT(__v)) {} 169 170 _LIBCPP_INLINE_VISIBILITY 171 explicit constexpr partial_ordering(_NCmpResult __v) noexcept 172 : __value_(_ValueT(__v)) {} 173 174 constexpr bool __is_ordered() const noexcept { 175 return __value_ != _ValueT(_NCmpResult::__unordered); 176 } 177public: 178 // valid values 179 static const partial_ordering less; 180 static const partial_ordering equivalent; 181 static const partial_ordering greater; 182 static const partial_ordering unordered; 183 184 // comparisons 185 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(partial_ordering, partial_ordering) noexcept = default; 186 187 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept { 188 return __v.__is_ordered() && __v.__value_ == 0; 189 } 190 191 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (partial_ordering __v, _CmpUnspecifiedParam) noexcept { 192 return __v.__is_ordered() && __v.__value_ < 0; 193 } 194 195 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept { 196 return __v.__is_ordered() && __v.__value_ <= 0; 197 } 198 199 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (partial_ordering __v, _CmpUnspecifiedParam) noexcept { 200 return __v.__is_ordered() && __v.__value_ > 0; 201 } 202 203 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept { 204 return __v.__is_ordered() && __v.__value_ >= 0; 205 } 206 207 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (_CmpUnspecifiedParam, partial_ordering __v) noexcept { 208 return __v.__is_ordered() && 0 < __v.__value_; 209 } 210 211 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept { 212 return __v.__is_ordered() && 0 <= __v.__value_; 213 } 214 215 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, partial_ordering __v) noexcept { 216 return __v.__is_ordered() && 0 > __v.__value_; 217 } 218 219 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept { 220 return __v.__is_ordered() && 0 >= __v.__value_; 221 } 222 223 _LIBCPP_INLINE_VISIBILITY friend constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept { 224 return __v; 225 } 226 227 _LIBCPP_INLINE_VISIBILITY friend constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept { 228 return __v < 0 ? partial_ordering::greater : (__v > 0 ? partial_ordering::less : __v); 229 } 230private: 231 _ValueT __value_; 232}; 233 234_LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::less(_OrdResult::__less); 235_LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::equivalent(_EqResult::__equiv); 236_LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::greater(_OrdResult::__greater); 237_LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::unordered(_NCmpResult ::__unordered); 238 239class weak_ordering { 240 using _ValueT = signed char; 241 242 _LIBCPP_INLINE_VISIBILITY 243 explicit constexpr weak_ordering(_EqResult __v) noexcept : __value_(_ValueT(__v)) {} 244 _LIBCPP_INLINE_VISIBILITY 245 explicit constexpr weak_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {} 246 247public: 248 static const weak_ordering less; 249 static const weak_ordering equivalent; 250 static const weak_ordering greater; 251 252 _LIBCPP_INLINE_VISIBILITY 253 constexpr operator partial_ordering() const noexcept { 254 return __value_ == 0 ? partial_ordering::equivalent 255 : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater); 256 } 257 258 // comparisons 259 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(weak_ordering, weak_ordering) noexcept = default; 260 261 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept { 262 return __v.__value_ == 0; 263 } 264 265 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (weak_ordering __v, _CmpUnspecifiedParam) noexcept { 266 return __v.__value_ < 0; 267 } 268 269 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept { 270 return __v.__value_ <= 0; 271 } 272 273 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (weak_ordering __v, _CmpUnspecifiedParam) noexcept { 274 return __v.__value_ > 0; 275 } 276 277 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept { 278 return __v.__value_ >= 0; 279 } 280 281 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (_CmpUnspecifiedParam, weak_ordering __v) noexcept { 282 return 0 < __v.__value_; 283 } 284 285 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept { 286 return 0 <= __v.__value_; 287 } 288 289 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, weak_ordering __v) noexcept { 290 return 0 > __v.__value_; 291 } 292 293 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept { 294 return 0 >= __v.__value_; 295 } 296 297 _LIBCPP_INLINE_VISIBILITY friend constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept { 298 return __v; 299 } 300 301 _LIBCPP_INLINE_VISIBILITY friend constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept { 302 return __v < 0 ? weak_ordering::greater : (__v > 0 ? weak_ordering::less : __v); 303 } 304 305private: 306 _ValueT __value_; 307}; 308 309_LIBCPP_INLINE_VAR constexpr weak_ordering weak_ordering::less(_OrdResult::__less); 310_LIBCPP_INLINE_VAR constexpr weak_ordering weak_ordering::equivalent(_EqResult::__equiv); 311_LIBCPP_INLINE_VAR constexpr weak_ordering weak_ordering::greater(_OrdResult::__greater); 312class strong_ordering { 313 using _ValueT = signed char; 314 315 _LIBCPP_INLINE_VISIBILITY 316 explicit constexpr strong_ordering(_EqResult __v) noexcept : __value_(_ValueT(__v)) {} 317 _LIBCPP_INLINE_VISIBILITY 318 explicit constexpr strong_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {} 319 320public: 321 static const strong_ordering less; 322 static const strong_ordering equal; 323 static const strong_ordering equivalent; 324 static const strong_ordering greater; 325 326 // conversions 327 _LIBCPP_INLINE_VISIBILITY 328 constexpr operator partial_ordering() const noexcept { 329 return __value_ == 0 ? partial_ordering::equivalent 330 : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater); 331 } 332 333 _LIBCPP_INLINE_VISIBILITY 334 constexpr operator weak_ordering() const noexcept { 335 return __value_ == 0 ? weak_ordering::equivalent 336 : (__value_ < 0 ? weak_ordering::less : weak_ordering::greater); 337 } 338 339 // comparisons 340 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(strong_ordering, strong_ordering) noexcept = default; 341 342 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept { 343 return __v.__value_ == 0; 344 } 345 346 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (strong_ordering __v, _CmpUnspecifiedParam) noexcept { 347 return __v.__value_ < 0; 348 } 349 350 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept { 351 return __v.__value_ <= 0; 352 } 353 354 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (strong_ordering __v, _CmpUnspecifiedParam) noexcept { 355 return __v.__value_ > 0; 356 } 357 358 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept { 359 return __v.__value_ >= 0; 360 } 361 362 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (_CmpUnspecifiedParam, strong_ordering __v) noexcept { 363 return 0 < __v.__value_; 364 } 365 366 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept { 367 return 0 <= __v.__value_; 368 } 369 370 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, strong_ordering __v) noexcept { 371 return 0 > __v.__value_; 372 } 373 374 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept { 375 return 0 >= __v.__value_; 376 } 377 378 _LIBCPP_INLINE_VISIBILITY friend constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept { 379 return __v; 380 } 381 382 _LIBCPP_INLINE_VISIBILITY friend constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept { 383 return __v < 0 ? strong_ordering::greater : (__v > 0 ? strong_ordering::less : __v); 384 } 385 386private: 387 _ValueT __value_; 388}; 389 390_LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::less(_OrdResult::__less); 391_LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::equal(_EqResult::__equal); 392_LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::equivalent(_EqResult::__equiv); 393_LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::greater(_OrdResult::__greater); 394 395// named comparison functions 396_LIBCPP_INLINE_VISIBILITY 397constexpr bool is_lt(partial_ordering __cmp) noexcept { return __cmp < 0; } 398 399_LIBCPP_INLINE_VISIBILITY 400constexpr bool is_lteq(partial_ordering __cmp) noexcept { return __cmp <= 0; } 401 402_LIBCPP_INLINE_VISIBILITY 403constexpr bool is_gt(partial_ordering __cmp) noexcept { return __cmp > 0; } 404 405_LIBCPP_INLINE_VISIBILITY 406constexpr bool is_gteq(partial_ordering __cmp) noexcept { return __cmp >= 0; } 407 408namespace __comp_detail { 409 410enum _ClassifyCompCategory : unsigned{ 411 _None, 412 _PartialOrd, 413 _WeakOrd, 414 _StrongOrd, 415 _CCC_Size 416}; 417 418template <class _Tp> 419_LIBCPP_INLINE_VISIBILITY 420constexpr _ClassifyCompCategory __type_to_enum() noexcept { 421 if (is_same_v<_Tp, partial_ordering>) 422 return _PartialOrd; 423 if (is_same_v<_Tp, weak_ordering>) 424 return _WeakOrd; 425 if (is_same_v<_Tp, strong_ordering>) 426 return _StrongOrd; 427 return _None; 428} 429 430template <size_t _Size> 431constexpr _ClassifyCompCategory 432__compute_comp_type(const _ClassifyCompCategory (&__types)[_Size]) { 433 int __seen[_CCC_Size] = {}; 434 for (auto __type : __types) 435 ++__seen[__type]; 436 if (__seen[_None]) 437 return _None; 438 if (__seen[_PartialOrd]) 439 return _PartialOrd; 440 if (__seen[_WeakOrd]) 441 return _WeakOrd; 442 return _StrongOrd; 443} 444 445template <class ..._Ts> 446constexpr auto __get_comp_type() { 447 using _CCC = _ClassifyCompCategory; 448 constexpr _CCC __type_kinds[] = {_StrongOrd, __type_to_enum<_Ts>()...}; 449 constexpr _CCC _Cat = __compute_comp_type(__type_kinds); 450 if constexpr (_Cat == _None) 451 return void(); 452 else if constexpr (_Cat == _PartialOrd) 453 return partial_ordering::equivalent; 454 else if constexpr (_Cat == _WeakOrd) 455 return weak_ordering::equivalent; 456 else if constexpr (_Cat == _StrongOrd) 457 return strong_ordering::equivalent; 458 else 459 static_assert(_Cat != _Cat, "unhandled case"); 460} 461} // namespace __comp_detail 462 463// [cmp.common], common comparison category type 464template<class... _Ts> 465struct _LIBCPP_TEMPLATE_VIS common_comparison_category { 466 using type = decltype(__comp_detail::__get_comp_type<_Ts...>()); 467}; 468 469template<class... _Ts> 470using common_comparison_category_t = typename common_comparison_category<_Ts...>::type; 471 472// [cmp.alg], comparison algorithms 473// TODO: unimplemented 474template<class _Tp> constexpr strong_ordering strong_order(const _Tp& __lhs, const _Tp& __rhs); 475template<class _Tp> constexpr weak_ordering weak_order(const _Tp& __lhs, const _Tp& __rhs); 476template<class _Tp> constexpr partial_ordering partial_order(const _Tp& __lhs, const _Tp& __rhs); 477 478#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) 479 480_LIBCPP_END_NAMESPACE_STD 481 482#endif // _LIBCPP_COMPARE 483