16 #ifndef OPENKALMAN_COORDINATES_COMPARISON_OPERATORS_HPP 17 #define OPENKALMAN_COORDINATES_COMPARISON_OPERATORS_HPP 19 #ifdef __cpp_impl_three_way_comparison 23 #include <type_traits> 26 #include "collections/views/single.hpp" 37 #ifdef __cpp_impl_three_way_comparison 38 using ordering = std::partial_ordering;
40 template<
typename A,
typename B>
41 static constexpr std::partial_ordering
42 ordering_compare(
const A& a,
const B& b)
49 using type =
signed char;
50 enum struct Ord : type { equivalent = 0, less = -1, greater = 1 };
51 enum struct Ncmp : type { unordered = 2 };
56 cmp_cat::type m_value;
59 ordering(cmp_cat::Ord v) noexcept : m_value(cmp_cat::type(v)) {}
62 ordering(cmp_cat::Ncmp v) noexcept : m_value(cmp_cat::type(v)) {}
71 [[nodiscard]]
friend constexpr
bool 72 operator==(
ordering v,
ordering w) noexcept {
return v.m_value == w.m_value; }
75 constexpr
ordering ordering::less(cmp_cat::Ord::less);
76 constexpr
ordering ordering::equivalent(cmp_cat::Ord::equivalent);
77 constexpr
ordering ordering::greater(cmp_cat::Ord::greater);
78 constexpr
ordering ordering::unordered(cmp_cat::Ncmp::unordered);
81 template<
typename A,
typename B>
83 ordering_compare(
const A& a,
const B& b)
86 a < b ? ordering::less :
87 a > b ? ordering::greater :
88 a == b ? ordering::equivalent :
94 template<std::
size_t ai = 0, std::
size_t bi = 0, std::
size_t abank = 0, std::
size_t bbank = 0,
typename A,
typename B>
96 compare_fixed(
const A& a,
const B& b)
98 if constexpr (ai < collections::size_of_v<A> and bi < collections::size_of_v<B>)
100 using Ai = std::tuple_element_t<ai, A>;
101 using Bi = std::tuple_element_t<bi, B>;
102 constexpr
bool ae = euclidean_pattern<Ai>, be = euclidean_pattern<Bi>;
103 if constexpr (ae and be)
return compare_fixed<ai + 1, bi + 1, abank + dimension_of_v<Ai>, bbank + dimension_of_v<Bi>>(a, b);
104 else if constexpr (ae)
return compare_fixed<ai + 1, bi, abank + dimension_of_v<Ai>, bbank>(a, b);
105 else if constexpr (be)
return compare_fixed<ai, bi + 1, abank, bbank + dimension_of_v<Bi>>(a, b);
108 if constexpr (abank == bbank)
if (internal::get_hash_code(collections::get<ai>(a)) == internal::get_hash_code(collections::get<bi>(b)))
109 return compare_fixed<ai + 1, bi + 1>(a, b);
110 return ordering::unordered;
113 else if constexpr (ai < collections::size_of_v<A>)
115 using Ai = std::tuple_element_t<ai, A>;
116 if (euclidean_pattern<Ai>)
return compare_fixed<ai + 1, bi, abank + dimension_of_v<Ai>, bbank>(a, b);
118 return ordering::unordered;
120 else if constexpr (bi < collections::size_of_v<B>)
122 using Bi = std::tuple_element_t<bi, B>;
123 if (euclidean_pattern<Bi>)
return compare_fixed<ai, bi + 1, abank, bbank + dimension_of_v<Bi>>(a, b);
125 return ordering::unordered;
135 template<
typename A,
typename B>
137 compare_impl(
const A& a,
const B& b, std::size_t ai = 0, std::size_t bi = 0, std::size_t abank = 0, std::size_t bbank = 0)
142 if (ai_in_range and bi_in_range)
144 auto a_i = internal::get_descriptor_collection_element(a, ai);
145 auto b_i = internal::get_descriptor_collection_element(b, bi);
147 if (ae or be)
return compare_impl(a, b, (ae ? ai + 1 : ai), (be ? bi + 1 : bi),
149 if (internal::get_hash_code(a_i) == internal::get_hash_code(b_i) and abank == bbank)
return compare_impl(a, b, ai + 1, bi + 1);
150 return ordering::unordered;
154 auto a_i = internal::get_descriptor_collection_element(a, ai);
156 if (abank >= bbank)
return ordering::greater;
157 return ordering::unordered;
161 auto b_i = internal::get_descriptor_collection_element(b, bi);
163 if (abank <= bbank)
return ordering::less;
164 return ordering::unordered;
167 return ordering_compare(abank, bbank);
177 #if defined(__cpp_concepts) and defined(__cpp_impl_three_way_comparison) 178 template<pattern A, pattern B>
179 constexpr std::partial_ordering
180 operator<=>(
const A& a,
const B& b)
183 if (
get_dimension(a) == 0)
return std::partial_ordering::less;
184 if (
get_dimension(b) == 0)
return std::partial_ordering::greater;
186 if constexpr (descriptor<A> and descriptor<B>)
188 if (internal::get_hash_code(a) == internal::get_hash_code(b))
return std::partial_ordering::equivalent;
189 return std::partial_ordering::unordered;
191 else if constexpr (fixed_pattern<A> and fixed_pattern<B>)
193 if constexpr (descriptor<A>)
194 return detail::compare_fixed(OpenKalman::views::single(a), b);
195 else if constexpr (descriptor<B>)
196 return detail::compare_fixed(a, OpenKalman::views::single(b));
198 return detail::compare_fixed(a, b);
202 if constexpr (descriptor<A>)
203 return detail::compare_impl(OpenKalman::views::single(a), b);
204 else if constexpr (descriptor<B>)
205 return detail::compare_impl(a, OpenKalman::views::single(b));
207 return detail::compare_impl(a, b);
215 template<pattern A, pattern B>
217 operator==(
const A& a,
const B& b)
219 return std::is_eq(a <=> b);
224 template<
typename A,
typename B, std::enable_if_t<pattern<A> and pattern<B>,
int> = 0>
225 constexpr
bool operator==(
const A& a,
const B& b)
229 if constexpr (descriptor<A> and descriptor<B>)
return internal::get_hash_code(a) == internal::get_hash_code(b);
230 else if constexpr (descriptor<A>)
return std::array {a} == b;
231 else if constexpr (descriptor<B>)
return a == std::array {b};
232 else if constexpr (fixed_pattern<A> and fixed_pattern<B>)
return detail::compare_fixed(a, b) == detail::ordering::equivalent;
233 else return detail::compare_impl(a, b) == detail::ordering::equivalent;
237 template<
typename A,
typename B, std::enable_if_t<pattern<A> and pattern<B>,
int> = 0>
238 constexpr
bool operator<(
const A& a,
const B& b)
243 if constexpr ((descriptor<A> and descriptor<B>) or descriptor<B>)
return false;
244 else if constexpr (descriptor<A>)
return std::array {a} < b;
245 else if constexpr (fixed_pattern<A> and fixed_pattern<B>)
return detail::compare_fixed(a, b) == detail::ordering::less;
246 else return detail::compare_impl(a, b) == detail::ordering::less;
250 template<
typename A,
typename B, std::enable_if_t<pattern<A> and pattern<B>,
int> = 0>
251 constexpr
bool operator>(
const A& a,
const B& b)
256 if constexpr ((descriptor<A> and descriptor<B>) or descriptor<A>)
return false;
257 else if constexpr (descriptor<B>)
return a > std::array {b};
258 else if constexpr (fixed_pattern<A> and fixed_pattern<B>)
return detail::compare_fixed(a, b) == detail::ordering::greater;
259 else return detail::compare_impl(a, b) == detail::ordering::greater;
263 template<
typename A,
typename B, std::enable_if_t<pattern<A> and pattern<B>,
int> = 0>
264 constexpr
bool operator<=(
const A& a,
const B& b)
269 if constexpr (descriptor<A> and descriptor<B>)
return internal::get_hash_code(a) == internal::get_hash_code(b);
270 else if constexpr (descriptor<A>)
return std::array {a} <= b;
271 else if constexpr (descriptor<B>)
return a == std::array {b};
272 else if constexpr (fixed_pattern<A> and fixed_pattern<B>)
273 {
auto comp = detail::compare_fixed(a, b);
return comp == detail::ordering::less or comp == detail::ordering::equivalent; }
275 {
auto comp = detail::compare_impl(a, b);
return comp == detail::ordering::less or comp == detail::ordering::equivalent; }
279 template<
typename A,
typename B, std::enable_if_t<pattern<A> and pattern<B>,
int> = 0>
280 constexpr
bool operator>=(
const A& a,
const B& b)
285 if constexpr (descriptor<A> and descriptor<B>)
return internal::get_hash_code(a) == internal::get_hash_code(b);
286 else if constexpr (descriptor<B>)
return a >= std::array {b};
287 else if constexpr (descriptor<A>)
return std::array {a} == b;
288 else if constexpr (fixed_pattern<A> and fixed_pattern<B>)
289 {
auto comp = detail::compare_fixed(a, b);
return comp == detail::ordering::greater or comp == detail::ordering::equivalent; }
291 {
auto comp = detail::compare_impl(a, b);
return comp == detail::ordering::greater or comp == detail::ordering::equivalent; }
295 template<
typename A,
typename B, std::enable_if_t<pattern<A> and pattern<B>,
int> = 0>
296 constexpr
bool operator!=(
const A& a,
const B& b)
298 return not operator==(a, b);
306 #endif //OPENKALMAN_COORDINATES_COMPARISON_OPERATORS_HPP Definition for coordinates::euclidean_pattern.
Definition for get_hash_code.
A generalization of std::greater in which the arguments may be of different types.
Definition: greater.hpp:29
Definition for values::to_number.
A generalization of std::less in which the arguments may be of different types.
Definition: less.hpp:29
Definition: comparison-operators.hpp:54
constexpr auto to_number(Arg arg)
Convert any values::value to a values::number.
Definition: to_number.hpp:34
constexpr auto get_dimension(const Arg &arg)
Get the vector dimension of coordinates::pattern Arg.
Definition: get_dimension.hpp:55
Definition for coordinates::descriptor.
Definition: compares_with.hpp:28
constexpr auto get_is_euclidean(const Arg &arg)
Determine, whether coordinates::pattern Arg is euclidean.
Definition: get_is_euclidean.hpp:70
Definition for coordinates::get_dimension.
Global definitions for OpenKalman.
constexpr auto get_size(Arg &&arg)
Get the size of a sized object (e.g, a collection)
Definition: get_size.hpp:191
A matrix with typed rows and columns.
Definition: forward-class-declarations.hpp:448