OpenKalman
is_square_shaped.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) 2022-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_IS_SQUARE_SHAPED_HPP
17 #define OPENKALMAN_IS_SQUARE_SHAPED_HPP
18 
19 #include <optional>
20 #include "coordinates/coordinates.hpp"
24 
25 namespace OpenKalman
26 {
27 
28  namespace detail
29  {
30  template<typename T, std::size_t i>
31  constexpr std::size_t
32  get_best_square_index()
33  {
34  if constexpr (i == 0) return i;
35  else if constexpr (coordinates::fixed_pattern<decltype(get_index_pattern<i - 1>(std::declval<T>()))>) return i - 1;
36  else return get_best_square_index<T, i - 1>();
37  }
38 
39 
40  template<typename T, std::size_t...is>
41  constexpr auto
42  is_square_shaped_impl(const T& t, std::index_sequence<is...>)
43  {
44  constexpr std::size_t best = get_best_square_index<T, sizeof...(is)>();
45  auto best_patt = get_index_pattern<best>(t);
46  using opt = std::optional<std::decay_t<decltype(best_patt)>>;
47  if ((... and (is == best or coordinates::compare(get_index_pattern<is>(t), best_patt)))) return opt {best_patt};
48  else return opt {};
49  }
50  }
51 
52 
63 #ifdef __cpp_concepts
64  template<indexible T>
65 #else
66  template<typename T, std::enable_if_t<indexible<T>, int> = 0>
67 #endif
68  constexpr auto
69  is_square_shaped(const T& t)
70  {
71  if constexpr (index_count_v<T> == stdex::dynamic_extent)
72  {
73  auto d0 = get_index_pattern<0>(t);
74  for (std::size_t i = 1; i < count_indices(t); ++i)
75  {
76  if (coordinates::compare<&stdex::is_neq>(d0, get_index_pattern(t, i)))
77  return std::optional<decltype((d0))> {};
78  }
79  return std::optional {d0};
80  }
81  else
82  {
83  constexpr std::size_t c = index_count_v<T>;
84  if constexpr (c == 1)
85  {
86  using opt = std::optional<coordinates::Dimensions<1>>;
87  if (get_index_extent<0>(t) == 1) return opt {coordinates::Dimensions<1>{}};
88  else return opt {};
89  }
90  else
91  {
92  return detail::is_square_shaped_impl(t, std::make_index_sequence<c>{});
93  }
94  }
95  }
96 
97 
98 }
99 
100 #endif
constexpr auto compare(const A &a, const B &b)
Compare two coordinates::pattern objects lexicographically.
Definition: compare.hpp:40
constexpr auto count_indices(const T &)
Get the number of indices necessary to address all the components of an indexible object...
Definition: count_indices.hpp:51
constexpr auto is_square_shaped(const T &t)
Determine whether an object is square_shaped.
Definition: is_square_shaped.hpp:69
Definition of count_indices.
The root namespace for OpenKalman.
Definition: basics.hpp:34
constexpr bool fixed_pattern
A coordinates::pattern for which the dimension is fixed at compile time.
Definition: fixed_pattern.hpp:46
Definition for index_count.
Definition of get_index_pattern function.
A structure representing the dimensions associated with of a particular index.
Definition: Dimensions.hpp:42
decltype(auto) constexpr get_index_pattern(T &&t, I i={})
Get the coordinates::pattern associated with indexible object T at a given index. ...
Definition: get_index_pattern.hpp:41