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 151class partial_ordering; 152class weak_ordering; 153class strong_ordering; 154 155template<class _Tp, class... _Args> 156inline constexpr bool __one_of_v = (is_same_v<_Tp, _Args> || ...); 157 158struct _CmpUnspecifiedParam { 159 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEVAL 160 _CmpUnspecifiedParam(int _CmpUnspecifiedParam::*) noexcept {} 161 162 template<class _Tp, class = enable_if_t<!__one_of_v<_Tp, int, partial_ordering, weak_ordering, strong_ordering>>> 163 _CmpUnspecifiedParam(_Tp) = delete; 164}; 165 166class partial_ordering { 167 using _ValueT = signed char; 168 169 _LIBCPP_INLINE_VISIBILITY 170 explicit constexpr partial_ordering(_EqResult __v) noexcept 171 : __value_(_ValueT(__v)) {} 172 173 _LIBCPP_INLINE_VISIBILITY 174 explicit constexpr partial_ordering(_OrdResult __v) noexcept 175 : __value_(_ValueT(__v)) {} 176 177 _LIBCPP_INLINE_VISIBILITY 178 explicit constexpr partial_ordering(_NCmpResult __v) noexcept 179 : __value_(_ValueT(__v)) {} 180 181 constexpr bool __is_ordered() const noexcept { 182 return __value_ != _ValueT(_NCmpResult::__unordered); 183 } 184public: 185 // valid values 186 static const partial_ordering less; 187 static const partial_ordering equivalent; 188 static const partial_ordering greater; 189 static const partial_ordering unordered; 190 191 // comparisons 192 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(partial_ordering, partial_ordering) noexcept = default; 193 194 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept { 195 return __v.__is_ordered() && __v.__value_ == 0; 196 } 197 198 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (partial_ordering __v, _CmpUnspecifiedParam) noexcept { 199 return __v.__is_ordered() && __v.__value_ < 0; 200 } 201 202 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept { 203 return __v.__is_ordered() && __v.__value_ <= 0; 204 } 205 206 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (partial_ordering __v, _CmpUnspecifiedParam) noexcept { 207 return __v.__is_ordered() && __v.__value_ > 0; 208 } 209 210 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept { 211 return __v.__is_ordered() && __v.__value_ >= 0; 212 } 213 214 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (_CmpUnspecifiedParam, partial_ordering __v) noexcept { 215 return __v.__is_ordered() && 0 < __v.__value_; 216 } 217 218 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept { 219 return __v.__is_ordered() && 0 <= __v.__value_; 220 } 221 222 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, partial_ordering __v) noexcept { 223 return __v.__is_ordered() && 0 > __v.__value_; 224 } 225 226 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept { 227 return __v.__is_ordered() && 0 >= __v.__value_; 228 } 229 230 _LIBCPP_INLINE_VISIBILITY friend constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept { 231 return __v; 232 } 233 234 _LIBCPP_INLINE_VISIBILITY friend constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept { 235 return __v < 0 ? partial_ordering::greater : (__v > 0 ? partial_ordering::less : __v); 236 } 237private: 238 _ValueT __value_; 239}; 240 241_LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::less(_OrdResult::__less); 242_LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::equivalent(_EqResult::__equiv); 243_LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::greater(_OrdResult::__greater); 244_LIBCPP_INLINE_VAR constexpr partial_ordering partial_ordering::unordered(_NCmpResult ::__unordered); 245 246class weak_ordering { 247 using _ValueT = signed char; 248 249 _LIBCPP_INLINE_VISIBILITY 250 explicit constexpr weak_ordering(_EqResult __v) noexcept : __value_(_ValueT(__v)) {} 251 _LIBCPP_INLINE_VISIBILITY 252 explicit constexpr weak_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {} 253 254public: 255 static const weak_ordering less; 256 static const weak_ordering equivalent; 257 static const weak_ordering greater; 258 259 _LIBCPP_INLINE_VISIBILITY 260 constexpr operator partial_ordering() const noexcept { 261 return __value_ == 0 ? partial_ordering::equivalent 262 : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater); 263 } 264 265 // comparisons 266 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(weak_ordering, weak_ordering) noexcept = default; 267 268 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept { 269 return __v.__value_ == 0; 270 } 271 272 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (weak_ordering __v, _CmpUnspecifiedParam) noexcept { 273 return __v.__value_ < 0; 274 } 275 276 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept { 277 return __v.__value_ <= 0; 278 } 279 280 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (weak_ordering __v, _CmpUnspecifiedParam) noexcept { 281 return __v.__value_ > 0; 282 } 283 284 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept { 285 return __v.__value_ >= 0; 286 } 287 288 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (_CmpUnspecifiedParam, weak_ordering __v) noexcept { 289 return 0 < __v.__value_; 290 } 291 292 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept { 293 return 0 <= __v.__value_; 294 } 295 296 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, weak_ordering __v) noexcept { 297 return 0 > __v.__value_; 298 } 299 300 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept { 301 return 0 >= __v.__value_; 302 } 303 304 _LIBCPP_INLINE_VISIBILITY friend constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept { 305 return __v; 306 } 307 308 _LIBCPP_INLINE_VISIBILITY friend constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept { 309 return __v < 0 ? weak_ordering::greater : (__v > 0 ? weak_ordering::less : __v); 310 } 311 312private: 313 _ValueT __value_; 314}; 315 316_LIBCPP_INLINE_VAR constexpr weak_ordering weak_ordering::less(_OrdResult::__less); 317_LIBCPP_INLINE_VAR constexpr weak_ordering weak_ordering::equivalent(_EqResult::__equiv); 318_LIBCPP_INLINE_VAR constexpr weak_ordering weak_ordering::greater(_OrdResult::__greater); 319class strong_ordering { 320 using _ValueT = signed char; 321 322 _LIBCPP_INLINE_VISIBILITY 323 explicit constexpr strong_ordering(_EqResult __v) noexcept : __value_(_ValueT(__v)) {} 324 _LIBCPP_INLINE_VISIBILITY 325 explicit constexpr strong_ordering(_OrdResult __v) noexcept : __value_(_ValueT(__v)) {} 326 327public: 328 static const strong_ordering less; 329 static const strong_ordering equal; 330 static const strong_ordering equivalent; 331 static const strong_ordering greater; 332 333 // conversions 334 _LIBCPP_INLINE_VISIBILITY 335 constexpr operator partial_ordering() const noexcept { 336 return __value_ == 0 ? partial_ordering::equivalent 337 : (__value_ < 0 ? partial_ordering::less : partial_ordering::greater); 338 } 339 340 _LIBCPP_INLINE_VISIBILITY 341 constexpr operator weak_ordering() const noexcept { 342 return __value_ == 0 ? weak_ordering::equivalent 343 : (__value_ < 0 ? weak_ordering::less : weak_ordering::greater); 344 } 345 346 // comparisons 347 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(strong_ordering, strong_ordering) noexcept = default; 348 349 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept { 350 return __v.__value_ == 0; 351 } 352 353 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (strong_ordering __v, _CmpUnspecifiedParam) noexcept { 354 return __v.__value_ < 0; 355 } 356 357 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept { 358 return __v.__value_ <= 0; 359 } 360 361 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (strong_ordering __v, _CmpUnspecifiedParam) noexcept { 362 return __v.__value_ > 0; 363 } 364 365 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept { 366 return __v.__value_ >= 0; 367 } 368 369 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (_CmpUnspecifiedParam, strong_ordering __v) noexcept { 370 return 0 < __v.__value_; 371 } 372 373 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept { 374 return 0 <= __v.__value_; 375 } 376 377 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, strong_ordering __v) noexcept { 378 return 0 > __v.__value_; 379 } 380 381 _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept { 382 return 0 >= __v.__value_; 383 } 384 385 _LIBCPP_INLINE_VISIBILITY friend constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept { 386 return __v; 387 } 388 389 _LIBCPP_INLINE_VISIBILITY friend constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept { 390 return __v < 0 ? strong_ordering::greater : (__v > 0 ? strong_ordering::less : __v); 391 } 392 393private: 394 _ValueT __value_; 395}; 396 397_LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::less(_OrdResult::__less); 398_LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::equal(_EqResult::__equal); 399_LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::equivalent(_EqResult::__equiv); 400_LIBCPP_INLINE_VAR constexpr strong_ordering strong_ordering::greater(_OrdResult::__greater); 401 402// named comparison functions 403_LIBCPP_INLINE_VISIBILITY 404constexpr bool is_lt(partial_ordering __cmp) noexcept { return __cmp < 0; } 405 406_LIBCPP_INLINE_VISIBILITY 407constexpr bool is_lteq(partial_ordering __cmp) noexcept { return __cmp <= 0; } 408 409_LIBCPP_INLINE_VISIBILITY 410constexpr bool is_gt(partial_ordering __cmp) noexcept { return __cmp > 0; } 411 412_LIBCPP_INLINE_VISIBILITY 413constexpr bool is_gteq(partial_ordering __cmp) noexcept { return __cmp >= 0; } 414 415namespace __comp_detail { 416 417enum _ClassifyCompCategory : unsigned{ 418 _None, 419 _PartialOrd, 420 _WeakOrd, 421 _StrongOrd, 422 _CCC_Size 423}; 424 425template <class _Tp> 426_LIBCPP_INLINE_VISIBILITY 427constexpr _ClassifyCompCategory __type_to_enum() noexcept { 428 if (is_same_v<_Tp, partial_ordering>) 429 return _PartialOrd; 430 if (is_same_v<_Tp, weak_ordering>) 431 return _WeakOrd; 432 if (is_same_v<_Tp, strong_ordering>) 433 return _StrongOrd; 434 return _None; 435} 436 437template <size_t _Size> 438constexpr _ClassifyCompCategory 439__compute_comp_type(const _ClassifyCompCategory (&__types)[_Size]) { 440 int __seen[_CCC_Size] = {}; 441 for (auto __type : __types) 442 ++__seen[__type]; 443 if (__seen[_None]) 444 return _None; 445 if (__seen[_PartialOrd]) 446 return _PartialOrd; 447 if (__seen[_WeakOrd]) 448 return _WeakOrd; 449 return _StrongOrd; 450} 451 452template <class ..._Ts, bool _False = false> 453constexpr auto __get_comp_type() { 454 using _CCC = _ClassifyCompCategory; 455 constexpr _CCC __type_kinds[] = {_StrongOrd, __type_to_enum<_Ts>()...}; 456 constexpr _CCC _Cat = __compute_comp_type(__type_kinds); 457 if constexpr (_Cat == _None) 458 return void(); 459 else if constexpr (_Cat == _PartialOrd) 460 return partial_ordering::equivalent; 461 else if constexpr (_Cat == _WeakOrd) 462 return weak_ordering::equivalent; 463 else if constexpr (_Cat == _StrongOrd) 464 return strong_ordering::equivalent; 465 else 466 static_assert(_False, "unhandled case"); 467} 468} // namespace __comp_detail 469 470// [cmp.common], common comparison category type 471template<class... _Ts> 472struct _LIBCPP_TEMPLATE_VIS common_comparison_category { 473 using type = decltype(__comp_detail::__get_comp_type<_Ts...>()); 474}; 475 476template<class... _Ts> 477using common_comparison_category_t = typename common_comparison_category<_Ts...>::type; 478 479// [cmp.alg], comparison algorithms 480// TODO: unimplemented 481template<class _Tp> constexpr strong_ordering strong_order(const _Tp& __lhs, const _Tp& __rhs); 482template<class _Tp> constexpr weak_ordering weak_order(const _Tp& __lhs, const _Tp& __rhs); 483template<class _Tp> constexpr partial_ordering partial_order(const _Tp& __lhs, const _Tp& __rhs); 484 485#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) 486 487_LIBCPP_END_NAMESPACE_STD 488 489#endif // _LIBCPP_COMPARE 490