OpenKalman
Dimensions.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_DIMENSIONS_HPP
17 #define OPENKALMAN_DIMENSIONS_HPP
18 
19 #include <cstddef>
20 #include <type_traits>
21 #include "linear-algebra/coordinates/interfaces/coordinate_descriptor_traits.hpp"
28 
30 {
31  // ------------ //
32  // fixed case //
33  // ------------ //
34 
41  template<std::size_t N = dynamic_size>
42  struct Dimensions
43  {
45  constexpr Dimensions() = default;
46 
47 
49 #ifdef __cpp_concepts
50  template<typename D> requires (not std::same_as<std::decay_t<D>, Dimensions>) and
51  ((euclidean_pattern<D> and fixed_pattern<D> and dimension_of_v<D> == N) or
52  dynamic_pattern<D>)
53 #else
54  template<typename D, std::enable_if_t<
55  (not std::is_same_v<std::decay_t<D>, Dimensions>) and
56  ((euclidean_pattern<D> and fixed_pattern<D> and dimension_of<D>::value == N) or
57  dynamic_pattern<D>), int> = 0>
58 #endif
59  explicit constexpr Dimensions(D&& d)
60  {
61  if constexpr (dynamic_pattern<D>)
62  {
63  if constexpr (not euclidean_pattern<D>)
64  {
65  if (not get_is_euclidean(d))
66  throw std::invalid_argument{"Argument of dynamic 'Dimensions' constructor must be a euclidean_coordinate_list."};
67  }
68  if (get_dimension(d) != N)
69  throw std::invalid_argument{"Dynamic argument to static 'Dimensions' constructor has the wrong size."};
70  }
71  }
72 
73 
74  template<typename Int>
75  explicit constexpr operator std::integral_constant<Int, N>()
76  {
77  return std::integral_constant<Int, N>{};
78  }
79 
80 
81 #ifdef __cpp_concepts
82  template<std::integral Int>
83 #else
84  template<typename Int, std::enable_if_t<std::is_integral_v<Int>, int> = 0>
85 #endif
86  explicit constexpr operator Int()
87  {
88  return N;
89  }
90 
91  }; // struct Dimensions, static case
92 
93 
94  // -------------- //
95  // dynamic case //
96  // -------------- //
97 
102  template<>
104  {
106 #ifdef __cpp_concepts
107  template<typename D> requires (euclidean_pattern<D> or dynamic_pattern<D>) and
108  (not std::is_base_of_v<Dimensions, D>)
109 #else
110  template<typename D, std::enable_if_t<(euclidean_pattern<D> or dynamic_pattern<D>) and
111  (not std::is_base_of_v<Dimensions, D>), int> = 0>
112 #endif
113  explicit constexpr Dimensions(const D& d) : runtime_size {get_dimension(d)}
114  {
115  if constexpr (not euclidean_pattern<D>)
116  if (not get_is_euclidean(d))
117  throw std::invalid_argument{"Argument of dynamic 'Dimensions' constructor must be a euclidean_coordinate_list."};
118  }
119 
120 
122  explicit constexpr Dimensions(const std::size_t& d = 0) : runtime_size {static_cast<std::size_t>(d)}
123  {}
124 
125 
129 #ifdef __cpp_concepts
130  template<typename D> requires (euclidean_pattern<D> or dynamic_pattern<D>) and
131  (not std::is_base_of_v<Dimensions, D>)
132 #else
133  template<typename D, std::enable_if_t<(euclidean_pattern<D> or dynamic_pattern<D>) and
134  (not std::is_base_of_v<Dimensions, D>), int> = 0>
135 #endif
136  constexpr Dimensions& operator=(const D& d)
137  {
138  if constexpr (not euclidean_pattern<D>)
139  if (not get_is_euclidean(d))
140  throw std::invalid_argument{"Argument of dynamic 'Dimensions' assignment operator must be a euclidean_coordinate_list."};
141  runtime_size = get_dimension(d);
142  return *this;
143  }
144 
145 
146 #ifdef __cpp_concepts
147  template<std::integral Int>
148 #else
149  template<typename Int, std::enable_if_t<std::is_integral_v<Int>, int> = 0>
150 #endif
151  explicit constexpr operator Int()
152  {
153  return runtime_size;
154  }
155 
156  protected:
157 
158  std::size_t runtime_size;
159 
161  };
162 
163 
164  // ------------------ //
165  // deduction guides //
166  // ------------------ //
167 
168 #ifdef __cpp_concepts
169  template<fixed_pattern D> requires euclidean_pattern<D>
170 #else
171  template<typename D, std::enable_if_t<fixed_pattern<D> and euclidean_pattern<D>, int> = 0>
172 #endif
174 
175 
176 #ifdef __cpp_concepts
177  template<dynamic_pattern D> requires euclidean_pattern<D>
178 #else
179  template<typename D, std::enable_if_t<dynamic_pattern<D> and euclidean_pattern<D>, int> = 0>
180 #endif
181  explicit Dimensions(D&&) -> Dimensions<dynamic_size>;
182 
183 
184  explicit Dimensions(const std::size_t&) -> Dimensions<dynamic_size>;
185 
186 
187  // ------ //
188  // Axis //
189  // ------ //
190 
195 
196 
197 } // OpenKalman::coordinates
198 
199 
200 namespace OpenKalman::interface
201 {
206  template<std::size_t N>
207  struct coordinate_descriptor_traits<coordinates::Dimensions<N>>
208  {
209  private:
210 
212 
213  public:
214 
215  static constexpr bool is_specialized = true;
216 
217 
218  static constexpr auto
219  dimension = [](const T& t)
220  {
221  if constexpr (N == dynamic_size) return t.runtime_size;
222  else return std::integral_constant<std::size_t, N>{};
223  };
224 
225 
226  static constexpr auto
227  stat_dimension = [](const T& t) { return dimension(t); };
228 
229 
230  static constexpr auto
231  is_euclidean = [](const T&) { return std::true_type{}; };
232 
233 
234  static constexpr std::size_t
235  hash_code = [](const T& t)
236  {
237  if constexpr (N == dynamic_size) return static_cast<std::size_t>(t.runtime_size);
238  else return N;
239  };
240 
241  };
242 
243 
244 } // namespace OpenKalman::interface
245 
246 
247 #endif //OPENKALMAN_DIMENSIONS_HPP
Definition for coordinates::euclidean_pattern.
Definition: basics.hpp:41
Definition for coordinates::dynamic_pattern.
Definition for coordinates::fixed_pattern.
constexpr Dimensions(const std::size_t &d=0)
Construct from an integral value.
Definition: Dimensions.hpp:122
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: Dimensions.hpp:103
The size of a coordinates::pattern.
Definition: dimension_of.hpp:37
constexpr Dimensions & operator=(const D &d)
Assign from another coordinates::euclidean_pattern or dynamic_pattern.
Definition: Dimensions.hpp:136
constexpr auto get_dimension(const Arg &arg)
Get the vector dimension of coordinates::pattern Arg.
Definition: get_dimension.hpp:55
Definition: compares_with.hpp:28
constexpr Dimensions(const D &d)
Construct from a coordinates::euclidean_pattern or dynamic_pattern.
Definition: Dimensions.hpp:113
constexpr auto get_is_euclidean(const Arg &arg)
Determine, whether coordinates::pattern Arg is euclidean.
Definition: get_is_euclidean.hpp:70
constexpr Dimensions(D &&d)
Constructor, taking a static coordinates::euclidean_pattern.
Definition: Dimensions.hpp:59
Traits for coordinates::pattern objects.
Definition: coordinate_descriptor_traits.hpp:41
Definition for get_is_euclidean.
Definition for coordinates::get_dimension.
A structure representing the dimensions associated with of a particular index.
Definition: Dimensions.hpp:42
constexpr Dimensions()=default
Default constructor.
constexpr std::size_t dynamic_size
A constant indicating that a size or index is dynamic.
Definition: global-definitions.hpp:33
Definition for coordinates::dimension_of.