16 #ifndef OPENKALMAN_COMPATIBILILTY_COMPARISON_HPP 17 #define OPENKALMAN_COMPATIBILILTY_COMPARISON_HPP 20 #ifdef __cpp_impl_three_way_comparison 28 #ifdef __cpp_lib_integer_comparison_functions 30 using std::cmp_not_equal;
32 using std::cmp_greater;
33 using std::cmp_less_equal;
34 using std::cmp_greater_equal;
36 template<
typename T,
typename U>
37 constexpr
bool cmp_equal(T t, U u) noexcept
39 if constexpr (std::is_signed_v<T> == std::is_signed_v<U>)
43 else if constexpr (std::is_signed_v<T>)
45 return t >= 0 && std::make_unsigned_t<T>(t) == u;
49 return u >= 0 && std::make_unsigned_t<U>(u) == t;
53 template<
typename T,
typename U>
54 constexpr
bool cmp_not_equal(T t, U u) noexcept
56 return not cmp_equal(t, u);
59 template<
typename T,
typename U>
60 constexpr
bool cmp_less(T t, U u) noexcept
62 if constexpr (std::is_signed_v<T> == std::is_signed_v<U>)
return t < u;
63 else if constexpr (std::is_signed_v<T>)
return t < 0 or std::make_unsigned_t<T>(t) < u;
64 else return u >= 0 and t < std::make_unsigned_t<U>(u);
67 template<
typename T,
typename U>
68 constexpr
bool cmp_greater(T t, U u) noexcept
70 return cmp_less(u, t);
73 template<
typename T,
typename U>
74 constexpr
bool cmp_less_equal(T t, U u) noexcept
76 return not cmp_less(u, t);
79 template<
typename T,
typename U>
80 constexpr
bool cmp_greater_equal(T t, U u) noexcept
82 return not cmp_less(t, u);
87 #ifdef __cpp_impl_three_way_comparison 88 using std::partial_ordering;
90 using std::lexicographical_compare_three_way;
100 enum struct Ord : signed char { equivalent = 0, less = -1, greater = 1, unordered = 2 };
106 struct unspecified { constexpr unspecified(unspecified*) noexcept {} };
108 detail::Ord my_value;
119 template<
typename I, std::enable_if_t<stdex::constructible_from<std::ptrdiff_t, I>,
int> = 0>
120 explicit constexpr
partial_ordering(I i) : my_value(static_cast<detail::Ord>(i)) {}
122 [[nodiscard]]
friend constexpr
bool 123 operator==(partial_ordering v, unspecified) noexcept {
return v.my_value == detail::Ord::equivalent; }
125 [[nodiscard]]
friend constexpr
bool 126 operator==(unspecified, partial_ordering v) noexcept {
return v.my_value == detail::Ord::equivalent; }
128 [[nodiscard]]
friend constexpr
bool 129 operator==(partial_ordering v, partial_ordering w) noexcept {
return v.my_value == w.my_value; };
131 [[nodiscard]]
friend constexpr
bool 132 operator!=(partial_ordering v, unspecified) noexcept {
return v.my_value != detail::Ord::equivalent; }
134 [[nodiscard]]
friend constexpr
bool 135 operator!=(unspecified, partial_ordering v) noexcept {
return v.my_value != detail::Ord::equivalent; }
137 [[nodiscard]]
friend constexpr
bool 138 operator!=(partial_ordering v, partial_ordering w) noexcept {
return v.my_value != w.my_value; };
140 [[nodiscard]]
friend constexpr
bool 141 operator<(partial_ordering v, unspecified) noexcept {
return v.my_value == detail::Ord::less; }
143 [[nodiscard]]
friend constexpr
bool 144 operator<(unspecified, partial_ordering v) noexcept {
return v.my_value == detail::Ord::greater; }
146 [[nodiscard]]
friend constexpr
bool 147 operator>(partial_ordering v, unspecified) noexcept {
return v.my_value == detail::Ord::greater; }
149 [[nodiscard]]
friend constexpr
bool 150 operator>(unspecified, partial_ordering v) noexcept {
return v.my_value == detail::Ord::less; }
152 [[nodiscard]]
friend constexpr
bool 153 operator<=(partial_ordering v, unspecified) noexcept {
return v.my_value <= detail::Ord::equivalent; }
155 [[nodiscard]]
friend constexpr
bool 156 operator<=(unspecified, partial_ordering v) noexcept {
return v.my_value == detail::Ord::greater or v.my_value == detail::Ord::equivalent; }
158 [[nodiscard]]
friend constexpr
bool 159 operator>=(partial_ordering v, unspecified) noexcept {
return v.my_value == detail::Ord::greater or v.my_value == detail::Ord::equivalent; }
161 [[nodiscard]]
friend constexpr
bool 162 operator>=(unspecified, partial_ordering v) noexcept {
return v.my_value <= detail::Ord::equivalent; }
167 inline constexpr
partial_ordering partial_ordering::less(detail::Ord::less);
169 inline constexpr
partial_ordering partial_ordering::equivalent(detail::Ord::equivalent);
171 inline constexpr
partial_ordering partial_ordering::greater(detail::Ord::greater);
173 inline constexpr
partial_ordering partial_ordering::unordered(detail::Ord::unordered);
178 template<
typename T,
typename U>
180 operator() [[nodiscard]] (T&& t, U&& u)
const 182 if (stdex::cmp_equal(t, u))
return partial_ordering::equivalent;
183 if (stdex::cmp_less(t, u))
return partial_ordering::less;
184 if (stdex::cmp_greater(t, u))
return partial_ordering::greater;
185 return partial_ordering::unordered;
188 using is_transparent = void;
192 template<
typename InputIt1,
typename InputIt2,
typename Cmp>
194 lexicographical_compare_three_way(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, Cmp comp)
195 -> decltype(comp(*first1, *first2))
197 using ret_t = decltype(comp(*first1, *first2));
198 static_assert(std::disjunction_v<
201 std::is_same<ret_t, partial_ordering>>,
202 "The return type must be a comparison category type.");
204 bool exhaust1 = (first1 == last1);
205 bool exhaust2 = (first2 == last2);
206 for (; not exhaust1 and not exhaust2; exhaust1 = (++first1 == last1), exhaust2 = (++first2 == last2))
209 return not exhaust1 ? partial_ordering::greater:
210 not exhaust2 ? partial_ordering::less:
211 partial_ordering::equivalent;
215 template<
typename InputIt1,
typename InputIt2>
217 lexicographical_compare_three_way(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2 )
219 return lexicographical_compare_three_way(first1, last1, first2, last2,
compare_three_way());
224 constexpr
bool is_neq(
partial_ordering cmp ) noexcept {
return cmp != 0; };
226 constexpr
bool is_lteq(
partial_ordering cmp ) noexcept {
return cmp <= 0; };
228 constexpr
bool is_gteq(
partial_ordering cmp ) noexcept {
return cmp >= 0; };
232 #ifdef __cpp_lib_concepts 233 using std::equality_comparable;
234 using std::equality_comparable_with;
235 using std::totally_ordered;
236 using std::totally_ordered_with;
240 template<typename T, typename U, typename C = typename stdex::common_reference<const T&, const U&>::type,
typename =
void>
243 template<
typename T,
typename U,
typename C>
245 stdex::same_as<common_reference_t<const T&, const U&>, common_reference_t<const U&, const T&>> and
246 (stdex::convertible_to<const T&, const C&> or stdex::convertible_to<T&, const C&>) and
247 (stdex::convertible_to<const U&, const C&> or stdex::convertible_to<U&, const C&>)
248 >> : std::true_type {};
251 template<
typename T,
typename U>
252 inline constexpr
bool 258 inline constexpr
bool 259 equality_comparable = OpenKalman::internal::WeaklyEqualityComparableWith<T, T>;
262 template<
typename T,
typename U>
263 inline constexpr
bool 264 equality_comparable_with =
265 equality_comparable<T> and
266 equality_comparable<U> and
267 detail::ComparisonCommonTypeWith<T, U> and
268 equality_comparable<common_reference_t<const std::remove_reference_t<T>&,
const std::remove_reference_t<U>&>> and
269 OpenKalman::internal::WeaklyEqualityComparableWith<T, U>;
280 inline constexpr
bool 281 totally_ordered = equality_comparable<T> and OpenKalman::internal::PartiallyOrderedWith<T, T>;
286 template<
typename T,
typename U,
typename =
void>
289 template<
typename T,
typename U>
291 totally_ordered<typename stdex::common_reference<const std::remove_reference_t<T>&, const std::remove_reference_t<U>&>::type>>> : std::true_type {};
295 template<
typename T,
typename U>
296 inline constexpr
bool 297 totally_ordered_with =
298 totally_ordered<T> and
299 totally_ordered<U> and
300 equality_comparable_with<T, U> and
302 OpenKalman::internal::PartiallyOrderedWith<T, U>;
Definition: comparison.hpp:104
Definition: comparison.hpp:176
constexpr bool value
T is a fixed or dynamic value that is reducible to a number.
Definition: value.hpp:45
Exposition-only definitions from teh c++ language standard.
Definition: comparison.hpp:287
Definition: comparison.hpp:241
constexpr auto compare_three_way(A &&a, B &&b, const Comparison &c={})
Compare two coordinates::pattern objects lexicographically.
Definition: compare_three_way.hpp:142
Definition: basics.hpp:55