OpenKalman
lexicographical_compare_three_way.hpp
Go to the documentation of this file.
1 /* This file is part of OpenKalman, a header-only C++ library for
2  * Kalman filters and other recursive filters.
3  *
4  * Copyright (c) 2025 Christopher Lee Ogden <ogden@gatech.edu>
5  *
6  * This Source Code Form is subject to the terms of the Mozilla Public
7  * License, v. 2.0. If a copy of the MPL was not distributed with this
8  * file, You can obtain one at https://mozilla.org/MPL/2.0/.
9  */
10 
16 #ifndef OPENKALMAN_COLLECTION_LEXICOGRAPHICAL_COMPARE_THREE_WAY_HPP
17 #define OPENKALMAN_COLLECTION_LEXICOGRAPHICAL_COMPARE_THREE_WAY_HPP
18 
19 #include <type_traits>
20 #include "basics/basics.hpp"
25 
27 {
28  namespace detail
29  {
30  template<std::size_t i = 0, typename Lhs, typename Rhs>
31  constexpr stdex::partial_ordering
32  fixed_lexicographical_compare(const Lhs& lhs, const Rhs& rhs)
33  {
34  using ix = std::integral_constant<std::size_t, i>;
35  constexpr bool exhaust_lhs = values::size_compares_with<size_of<Lhs>, ix>;
36  constexpr bool exhaust_rhs = values::size_compares_with<size_of<Rhs>, ix>;
37  constexpr bool dyn_lhs = values::fixed_value_compares_with<size_of<Lhs>, stdex::dynamic_extent>;
38  constexpr bool dyn_rhs = values::fixed_value_compares_with<size_of<Rhs>, stdex::dynamic_extent>;
39 
40  if constexpr (exhaust_lhs and exhaust_rhs)
41  {
42  return stdex::partial_ordering::equivalent;
43  }
44  else if constexpr (exhaust_lhs)
45  {
46  if constexpr (dyn_rhs) if (i == get_size(rhs)) return stdex::partial_ordering::equivalent;
47  return stdex::partial_ordering::less;
48  }
49  else if constexpr (exhaust_rhs)
50  {
51  if constexpr (dyn_lhs) if (i == get_size(lhs)) return stdex::partial_ordering::equivalent;
52  return stdex::partial_ordering::greater;
53  }
54  else // if constexpr (not exhaust_lhs and not exhaust_rhs)
55  {
56  if constexpr (dyn_lhs) if (i == get_size(lhs)) return stdex::partial_ordering::less;
57  if constexpr (dyn_rhs) if (i == get_size(rhs)) return stdex::partial_ordering::greater;
58  if (auto cmp = stdex::compare_three_way{}(collections::get<i>(lhs), collections::get<i>(rhs));
59  stdex::is_eq(cmp))
60  return fixed_lexicographical_compare<i + 1>(lhs, rhs);
61  else return cmp;
62  }
63  }
64  }
65 
66 
71 #ifdef __cpp_concepts
72  template<collection Lhs, collection Rhs> requires
73  (collection_view<Lhs> or collection_view<Rhs>) and
74  (sized<Lhs> or sized<Rhs>)
75 #else
76  template<typename Lhs, typename Rhs, std::enable_if_t<
77  collection<Lhs> and collection<Rhs> and
78  (collection_view<Lhs> or collection_view<Rhs>) and
79  (sized<Lhs> or sized<Rhs>), int> = 0>
80 #endif
81  constexpr stdex::partial_ordering
82  lexicographical_compare_three_way(const Lhs& lhs, const Rhs& rhs)
83  {
84  if constexpr (values::fixed_value_compares_with<size_of<Lhs>, stdex::dynamic_extent, &stdex::is_neq> or
85  values::fixed_value_compares_with<size_of<Rhs>, stdex::dynamic_extent, &stdex::is_neq>)
86  {
87  return detail::fixed_lexicographical_compare(lhs, rhs);
88  }
89  else if constexpr (stdex::ranges::common_range<Lhs> and stdex::ranges::common_range<Rhs>)
90  {
92  stdex::ranges::begin(lhs),
93  stdex::ranges::end(lhs),
94  stdex::ranges::begin(rhs),
95  stdex::ranges::end(rhs));
96  }
97  else
98  {
99  auto f1 = stdex::ranges::begin(lhs);
100  const auto l1 = stdex::ranges::end(lhs);
101  auto f2 = stdex::ranges::begin(rhs);
102  const auto l2 = stdex::ranges::end(rhs);
103  bool exhaust1 = (f1 == l1);
104  bool exhaust2 = (f2 == l2);
105  for (; not exhaust1 and not exhaust2; exhaust1 = (++f1 == l1), exhaust2 = (++f2 == l2))
106  if (auto c = stdex::compare_three_way{}(*f1, *f2); stdex::is_neq(c)) return c;
107  return !exhaust1 ? stdex::partial_ordering::greater:
108  !exhaust2 ? stdex::partial_ordering::less:
109  stdex::partial_ordering::equivalent;
110  }
111  }
112 
113 
114 }
115 
116 #endif
Namespace for collections.
Definition: collections.hpp:27
Definition for collections::get.
Definition for collections::collection.
Definition: comparison.hpp:176
Definition for collections::size_of.
The size of a sized object (including a collection).
Definition: size_of.hpp:33
constexpr stdex::partial_ordering lexicographical_compare_three_way(const Lhs &lhs, const Rhs &rhs)
Compares two collections.
Definition: lexicographical_compare_three_way.hpp:82
Definition for collections::collection_view.
constexpr bool fixed_value_compares_with
T has a fixed value that compares with N in a particular way based on parameter comp.
Definition: fixed_value_compares_with.hpp:74
constexpr auto compare_three_way(A &&a, B &&b, const Comparison &c={})
Compare two coordinates::pattern objects lexicographically.
Definition: compare_three_way.hpp:142
Basic definitions for OpenKalman as a whole.
constexpr auto get_size(Arg &&arg)
Get the size of a sized object (e.g, a collection)
Definition: get_size.hpp:188