17 #ifndef OPENKALMAN_COLLECTION_COMPARE_HPP 18 #define OPENKALMAN_COLLECTION_COMPARE_HPP 20 #include <type_traits> 23 #ifdef __cpp_lib_ranges 36 #ifdef __cpp_lib_ranges 38 concept comparable = collection_view<T> and (size_of_v<T> !=
dynamic_size) or std::ranges::input_range<T>;
41 inline constexpr
bool comparable = collection_view<T> and (size_of_v<T> !=
dynamic_size) or ranges::input_range<T>;
45 template<std::
size_t i = 0,
typename T1,
typename T2>
47 fixed_compare(
const T1& lhs,
const T2& rhs)
50 constexpr
auto ix = std::integral_constant<std::size_t, i>{};
51 if constexpr (i == size_of_v<T1> and i == size_of_v<T2>) {
return partial_ordering::equivalent; }
52 else if constexpr (i == size_of_v<T1>) {
return partial_ordering::less; }
53 else if constexpr (i == size_of_v<T2>) {
return partial_ordering::greater; }
54 else if (
get(lhs, ix) ==
get(rhs, ix)) {
return fixed_compare<i + 1>(lhs, rhs); }
57 auto cmp = compare_three_way{}(
get(lhs, ix),
get(rhs, ix));
58 if (cmp == 0)
return partial_ordering::equivalent;
59 if (cmp < 0)
return partial_ordering::less;
60 if (cmp > 0)
return partial_ordering::greater;
61 return partial_ordering::unordered;
70 #ifdef __cpp_impl_three_way_comparison 71 template<detail::comparable Lhs, detail::comparable Rhs>
72 constexpr std::partial_ordering
73 compare(
const Lhs& lhs,
const Rhs& rhs)
75 #ifdef __cpp_lib_ranges 76 namespace ranges = std::ranges;
78 if constexpr (size_of_v<Lhs> !=
dynamic_size and size_of_v<Rhs> !=
dynamic_size) {
return detail::fixed_compare(lhs, rhs); }
79 else {
return std::lexicographical_compare_three_way(ranges::begin(lhs), ranges::end(lhs), ranges::begin(rhs), ranges::end(rhs)); }
86 template<detail::comparable Lhs, detail::comparable Rhs>
87 constexpr std::partial_ordering
88 operator<=>(
const Lhs& lhs,
const Rhs& rhs) noexcept
97 template<detail::comparable Lhs, detail::comparable Rhs>
99 operator==(
const Lhs& lhs,
const Rhs& rhs) noexcept
101 return std::is_eq(operator<=>(lhs, rhs));
104 template<
typename Lhs,
typename Rhs, std::enable_if_t<detail::comparable<Lhs> and detail::comparable<Rhs>,
int> = 0>
105 constexpr partial_ordering
108 if constexpr (size_of_v<Lhs> !=
dynamic_size and size_of_v<Rhs> !=
dynamic_size)
return detail::fixed_compare(lhs, rhs);
111 #ifdef __cpp_lib_ranges 112 namespace ranges = std::ranges;
114 auto l = ranges::begin(lhs);
115 auto r = ranges::begin(rhs);
116 auto le = ranges::end(lhs);
117 auto re = ranges::end(rhs);
118 for (; l != le and r != re; ++l, ++r)
120 if (*l == *r) {
continue; }
121 if (*l < *r) {
return partial_ordering::less; }
122 if (*l > *r) {
return partial_ordering::greater; }
123 return partial_ordering::unordered;
125 if (l == le and r == re) {
return partial_ordering::equivalent; }
126 if (l == le) {
return partial_ordering::less; }
127 if (r == re) {
return partial_ordering::greater; }
128 return partial_ordering::unordered;
133 template<
typename Lhs,
typename Rhs, std::enable_if_t<detail::comparable<Lhs> and detail::comparable<Rhs>,
int> = 0>
134 constexpr
bool operator==(
const Lhs& lhs,
const Rhs& rhs) {
return compare(lhs, rhs) == 0; }
136 template<
typename Lhs,
typename Rhs, std::enable_if_t<detail::comparable<Lhs> and detail::comparable<Rhs>,
int> = 0>
137 constexpr
bool operator!=(
const Lhs& lhs,
const Rhs& rhs) {
return not (
compare(lhs, rhs) == 0); }
139 template<
typename Lhs,
typename Rhs, std::enable_if_t<detail::comparable<Lhs> and detail::comparable<Rhs>,
int> = 0>
140 constexpr
bool operator<(
const Lhs& lhs,
const Rhs& rhs) {
return compare(lhs, rhs) < 0; }
142 template<
typename Lhs,
typename Rhs, std::enable_if_t<detail::comparable<Lhs> and detail::comparable<Rhs>,
int> = 0>
143 constexpr
bool operator>(
const Lhs& lhs,
const Rhs& rhs) {
return compare(lhs, rhs) > 0; }
145 template<
typename Lhs,
typename Rhs, std::enable_if_t<detail::comparable<Lhs> and detail::comparable<Rhs>,
int> = 0>
146 constexpr
bool operator<=(
const Lhs& lhs,
const Rhs& rhs) {
return compare(lhs, rhs) <= 0; }
148 template<
typename Lhs,
typename Rhs, std::enable_if_t<detail::comparable<Lhs> and detail::comparable<Rhs>,
int> = 0>
149 constexpr
bool operator>=(
const Lhs& lhs,
const Rhs& rhs) {
return compare(lhs, rhs) >= 0; }
154 #endif //OPENKALMAN_COLLECTION_COMPARE_HPP Namespace for collections.
Definition: collections.hpp:27
Definition for collections::get.
constexpr partial_ordering compare(const Lhs &lhs, const Rhs &rhs)
Compare two collections.
Definition: compare.hpp:106
Definition: tuple_reverse.hpp:103
Definition for collections::size_of.
Definition for collections::collection_view.
Definitions relating to the availability of c++ language features.
Definitions implementing features of the c++ ranges library for compatibility.
constexpr std::size_t dynamic_size
A constant indicating that a size or index is dynamic.
Definition: global-definitions.hpp:33