OpenKalman
constant_adapter.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) 2019-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_CONSTANT_ADAPTER_HPP
17 #define OPENKALMAN_CONSTANT_ADAPTER_HPP
18 
19 #include "coordinates/coordinates.hpp"
23 #include "linear-algebra/traits/internal/library_base.hpp"
27 
28 namespace OpenKalman
29 {
47 #ifdef __cpp_concepts
48  template<values::value Value, indexible Shape> requires std::is_object_v<Value>
49 #else
50  template<typename Value, typename Shape>
51 #endif
52  struct constant_adapter : internal::library_base_t<constant_adapter<Value, Shape>, Shape>
53  {
54  private:
55 
56  using Pattern = decltype(get_pattern_collection(std::declval<const Shape&>()));
57 
58  public:
59 
63 #ifdef __cpp_lib_ranges
64  template<values::value V, coordinates::pattern_collection P> requires
65  std::constructible_from<Value, V&&> and
66  std::constructible_from<Pattern, P&&>
67 #else
68  template<typename V, typename P, std::enable_if_t<
69  values::value<V> and pattern_collection<P> and
70  stdex::constructible_from<Value, V&&> and stdex::constructible_from<Pattern, P&&>, int> = 0>
71 #endif
72  explicit constexpr constant_adapter(V&& v, P&& p)
73  : value_ {std::forward<V>(v)}, pattern_ {std::forward<P>(p)} {}
74 
75 
79 #ifdef __cpp_lib_ranges
80  template<values::value V, indexible S> requires
81  std::constructible_from<Value, V&&> and
82  std::constructible_from<Pattern, decltype(get_pattern_collection(std::declval<S&&>()))>
83 #else
84  template<typename V, typename S, std::enable_if_t<values::value<V> and
85  stdex::constructible_from<Value, V&&> and
86  stdex::constructible_from<Pattern, decltype(get_pattern_collection(std::declval<S&&>()))>, int> = 0>
87 #endif
88  explicit constexpr constant_adapter(V&& v, S&& s)
89  : value_ {std::forward<V>(v)}, pattern_ {get_pattern_collection(std::forward<S>(s))} {}
90 
91 
96 #ifdef __cpp_lib_ranges
97  template<values::value V> requires
98  std::constructible_from<Value, V&&> and
99  coordinates::fixed_pattern_collection<Pattern>
100 #else
101  template<typename V, typename S, std::enable_if_t<values::value<V> and
102  stdex::constructible_from<Value, V&&> and coordinates::fixed_pattern_collection<Pattern>, int> = 0>
103 #endif
104  explicit constexpr constant_adapter(V&& v)
105  : value_ {std::forward<V>(v)}, pattern_ {} {}
106 
107 
112 #ifdef __cpp_lib_ranges
113  explicit constexpr constant_adapter()
114  requires values::fixed<Value> and coordinates::fixed_pattern_collection<Pattern>
115 #else
116  template<bool Enable, std::enable_if_t<Enable and values::fixed<Value> and coordinates::fixed_pattern_collection<Pattern>, int> = 0>
117  explicit constexpr constant_adapter()
118 #endif
119  : value_ {}, pattern_ {} {}
120 
121 
125 #ifdef __cpp_concepts
126  template<constant_object Arg> requires
127  (not std::same_as<std::decay_t<Arg>, constant_adapter>) and
128  std::constructible_from<Value, constant_value<Arg>> and
129  std::constructible_from<Pattern, decltype(get_pattern_collection(std::declval<Arg&&>()))>
130 #else
131  template<typename Arg, std::enable_if_t<constant_object<Arg> and
132  (not stdex::same_as<std::decay_t<Arg>, constant_adapter>) and
133  stdex::constructible_from<Value, constant_value<Arg>> and
134  stdex::constructible_from<Pattern, decltype(get_pattern_collection(std::declval<Arg&&>()))>, int> = 0>
135 #endif
136  constexpr constant_adapter(Arg&& arg) :
137  value_ {constant_value {arg}},
138  pattern_ {get_pattern_collection(std::forward<Arg>(arg))} {}
139 
140 
144 #ifdef __cpp_concepts
145  template<constant_object Arg> requires
146  (not std::same_as<std::decay_t<Arg>, constant_adapter>) and
147  std::assignable_from<Value&, constant_value<Arg>> and
148  std::assignable_from<Pattern&, decltype(get_pattern_collection(std::declval<Arg&&>()))>
149 #else
150  template<typename Arg, std::enable_if_t<constant_object<Arg> and
151  (not stdex::same_as<std::decay_t<Arg>, constant_adapter>) and
152  stdex::assignable_from<Value&, constant_value<Arg>> and
153  stdex::assignable_from<Pattern&, decltype(get_pattern_collection(std::declval<Arg&&>()))>, int> = 0>
154 #endif
155  constexpr auto& operator=(const Arg& arg)
156  {
157  value_ = constant_value {arg};
158  pattern_ = get_pattern_collection(std::forward<Arg>(arg));
159  return *this;
160  }
161 
162 
167 #ifdef __cpp_lib_ranges
168  template<index_collection_for<Shape> Indices> requires (not empty_object<PatternMatrix>)
169  constexpr values::scalar auto
170 #else
171  template<typename Indices, std::enable_if_t<
172  index_collection_for<Indices, Shape> and (not empty_object<PatternMatrix>), int> = 0>
173  constexpr auto
174 #endif
175  operator[](const Indices& indices) const
176  {
177  return values::to_value_type(value_);
178  }
179 
180 
184 #ifdef __cpp_concepts
185  constexpr values::value auto
186 #else
187  constexpr auto
188 #endif
189  value() const
190  {
191  return value_;
192  }
193 
194  protected:
195 
196  Value value_;
197 
198  Pattern pattern_;
199 
200  friend struct interface::object_traits<constant_adapter>;
201  friend struct interface::library_interface<constant_adapter>;
202 
203  };
204 
205 
206  // ------------------ //
207  // Deduction guides //
208  // ------------------ //
209 
210 #ifdef __cpp_concepts
211  template<values::value C, indexible Arg>
212 #else
213  template<typename C, typename Arg, std::enable_if_t<values::scalar<C> and indexible<Arg>, int> = 0>
214 #endif
215  constant_adapter(const C&, const Arg&) -> constant_adapter<C, Arg>;
216 
217 
218 #ifdef __cpp_concepts
219  template<constant_object Arg> requires (not is_constant_adapter<Arg>::value)
220 #else
221  template<typename Arg, std::enable_if_t<constant_object<Arg> and (not is_constant_adapter<Arg>), int> = 0>
222 #endif
224 
225 
226  // -------------- //
227  // zero_adapter //
228  // -------------- //
229 
235 #ifdef __cpp_concepts
236  template<indexible Shape, values::number N = element_type_of_t<Shape>>
237 #else
238  template<typename Shape, typename N = element_type_of_t<Shape>>
239 #endif
241 
242 
243  // ------------ //
244  // Interfaces //
245  // ------------ //
246 
247  namespace interface
248  {
249  template<typename PatternMatrix, typename Scalar, auto...constant>
250  struct object_traits<constant_adapter<PatternMatrix, Scalar, constant...>>
251  {
252  private:
253 
254  using XprType = constant_adapter<PatternMatrix, Scalar, constant...>;
255 
256  public:
257 
258  using scalar_type = typename XprType::MyScalarType;
259  using MyDims = typename XprType::MyDimensions_t;
260 
261 
262  template<typename Arg>
263  static constexpr auto count_indices(const Arg& arg)
264  {
265  if constexpr (index_count_v<PatternMatrix> == stdex::dynamic_extent)
266  return std::forward<Arg>(arg).pattern_.size();
267  else
269  }
270 
271 
272  template<typename Arg, typename N>
273  static constexpr auto get_pattern_collection(Arg&& arg, const N& n)
274  {
275  if constexpr (index_count_v<PatternMatrix> == stdex::dynamic_extent)
276  {
277  return std::forward<Arg>(arg).pattern_[static_cast<typename MyDims::size_type>(n)];
278  }
279  else if constexpr (values::fixed<N>)
280  {
281  if constexpr (N::value >= index_count_v<PatternMatrix>) return Dimensions<1>{};
282  else return std::get<N::value>(std::forward<Arg>(arg).pattern_);
283  }
284  else if (n >= collections::size_of_v<MyDims>)
285  {
286  return 1_uz;
287  }
288  else
289  {
290  return std::apply(
291  [](auto&&...ds){ return std::array<std::size_t, collections::size_of_v<MyDims>> {std::forward<decltype(ds)>(ds)...}; },
292  std::forward<Arg>(arg).pattern_)[n];
293  }
294  }
295 
296 
297  // No nested_object defined
298 
299 
300  template<typename Arg>
301  static constexpr auto get_constant(const Arg& arg) { return arg.value(); }
302 
303 
304  // No get_constant_diagonal defined
305 
306 
307  template<applicability b>
308  static constexpr bool one_dimensional = OpenKalman::one_dimensional<PatternMatrix, b>;
309 
310 
311  template<applicability b>
312  static constexpr bool is_square = OpenKalman::square_shaped<PatternMatrix, b>;
313 
314 
315  // No triangle_type_value, is_triangular_adapter, is_hermitian, or hermitian_adapter_type defined
316 
317 
318  static constexpr bool is_writable = false;
319 
320 
321  // No raw_data, layout, or strides defined.
322 
323  };
324 
325 
326  template<typename PatternMatrix, typename Scalar, auto...constant>
327  struct library_interface<constant_adapter<PatternMatrix, Scalar, constant...>>
328  {
329  template<typename Derived>
330  using library_base = internal::library_base_t<Derived, PatternMatrix>;
331 
332 
333  template<typename Arg, typename Indices>
334  static constexpr auto
335  access(Arg&& arg, const Indices&) { return std::forward<Arg>(arg).value(); }
336 
337 
338  // No set_component defined because constant_adapter is not writable.
339 
340 
341  template<typename Arg>
342  static decltype(auto)
343  to_native_matrix(Arg&& arg)
344  {
345  return OpenKalman::to_native_matrix<PatternMatrix>(std::forward<Arg>(arg));
346  }
347 
348 
349  template<data_layout layout, typename S, typename D>
350  static auto
351  make_default(D&& d)
352  {
353  return make_dense_object<PatternMatrix, layout, S>(std::forward<D>(d));
354  }
355 
356 
357  // fill_components not necessary because T is not a dense writable matrix.
358 
359 
360  template<typename C, typename D>
361  static constexpr auto
362  make_constant(C&& c, D&& d)
363  {
364  return OpenKalman::make_constant<PatternMatrix>(std::forward<C>(c), std::forward<D>(d));
365  }
366 
367 
368  template<typename S, typename D>
369  static constexpr auto
370  make_identity_matrix(D&& d)
371  {
372  return make_identity_matrix_like<PatternMatrix, S>(std::forward<D>(d));
373  }
374 
375 
376  // no get_slice
377  // no set_slice
378  // no set_triangle
379  // no to_diagonal
380  // no diagonal_of
381 
382 
383  template<typename...Ds, typename Arg>
384  static decltype(auto)
385  replicate(const std::tuple<Ds...>& tup, Arg&& arg)
386  {
387  return library_interface<PatternMatrix>::replicate(tup, std::forward<Arg>(arg));
388  }
389 
390 
391  template<typename...Ds, typename Op, typename...Args>
392  static constexpr decltype(auto)
393  n_ary_operation(const std::tuple<Ds...>& d_tup, Op&& op, Args&&...args)
394  {
395  return library_interface<PatternMatrix>::n_ary_operation(d_tup, std::forward<Op>(op), std::forward<Args>(args)...);
396  }
397 
398 
399  template<std::size_t...indices, typename BinaryFunction, typename Arg>
400  static constexpr decltype(auto)
401  reduce(BinaryFunction&& b, Arg&& arg)
402  {
403  return library_interface<PatternMatrix>::template reduce<indices...>(std::forward<BinaryFunction>(b), std::forward<Arg>(arg));
404  }
405 
406 
407  // no to_euclidean
408  // no from_euclidean
409  // no wrap_angles
410 
411  // conjugate is not necessary because it is handled by the general conjugate function.
412  // transpose is not necessary because it is handled by the general transpose function.
413  // adjoint is not necessary because it is handled by the general adjoint function.
414  // determinant is not necessary because it is handled by the general determinant function.
415 
416 
417  template<typename A, typename B>
418  static constexpr auto sum(A&& a, B&& b)
419  {
420  return library_interface<PatternMatrix>::sum(std::forward<A>(a), std::forward<B>(b));
421  }
422 
423 
424  template<typename A, typename B>
425  static constexpr auto contract(A&& a, B&& b)
426  {
427  return library_interface<PatternMatrix>::contract(std::forward<A>(a), std::forward<B>(b));
428  }
429 
430 
431  // contract_in_place is not necessary because the argument will not be writable.
432 
433  // cholesky_factor is not necessary because it is handled by the general cholesky_factor function.
434 
435 
436  template<HermitianAdapterType significant_triangle, typename A, typename U, typename Alpha>
437  static decltype(auto) rank_update_hermitian(A&& a, U&& u, const Alpha alpha)
438  {
440  return Trait::template rank_update_hermitian<significant_triangle>(std::forward<A>(a), std::forward<U>(u), alpha);
441  }
442 
443 
444  // rank_update_triangular is not necessary because it is handled by the general rank_update_triangular function.
445 
446  // solve is not necessary because it is handled by the general solve function.
447 
448  // LQ_decomposition is not necessary because it is handled by the general LQ_decomposition function.
449 
450  // QR_decomposition is not necessary because it is handled by the general QR_decomposition function.
451 
452  };
453 
454  }
455 
456 
457 }
458 
459 
460 #endif
constexpr auto n_ary_operation(const std::tuple< Ds... > &d_tup, Operation &&operation, Args &&...args)
Perform a component-wise n-ary operation, using broadcasting to match the size of a pattern matrix...
Definition: n_ary_operation.hpp:325
Definition for constant_value.
constexpr bool one_dimensional
Specifies that a type is one-dimensional in every index.
Definition: one_dimensional.hpp:56
decltype(auto) constexpr contract(A &&a, B &&b)
Matrix multiplication of A * B.
Definition: contract.hpp:54
Definition for constant_object.
decltype(auto) rank_update_hermitian(A &&a, U &&u, scalar_type_of_t< A > alpha=1)
Do a rank update on a hermitian matrix.
Definition: rank_update_hermitian.hpp:45
constexpr constant_adapter(V &&v)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: constant_adapter.hpp:104
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
Definition for index_collection_for.
constexpr constant_adapter(V &&v, P &&p)
Construct from value and a pattern_collection.
Definition: constant_adapter.hpp:72
decltype(auto) constexpr get_pattern_collection(T &&t)
Get the coordinates::pattern_collection associated with indexible object T.
Definition: get_pattern_collection.hpp:59
decltype(auto) constexpr to_value_type(Arg &&arg)
Convert, if necessary, a fixed or dynamic value to its underlying base type.
Definition: to_value_type.hpp:28
The size of a sized object (including a collection).
Definition: size_of.hpp:33
constexpr bool value
T is a fixed or dynamic value that is reducible to a number.
Definition: value.hpp:45
decltype(auto) constexpr reduce(BinaryFunction &&b, Arg &&arg)
Perform a partial reduction based on an associative binary function, across one or more indices...
Definition: reduce.hpp:143
decltype(auto) constexpr apply(F &&f, T &&t)
A generalization of std::apply.
Definition: apply.hpp:49
constexpr detail::replicate_adaptor replicate
a std::ranges::range_adaptor_closure associated with replicate_view.
Definition: replicate.hpp:440
Definition for element_type_of.
constexpr constant_adapter()
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: constant_adapter.hpp:117
The root namespace for OpenKalman.
Definition: basics.hpp:34
An interface to various routines from the linear algebra library associated with indexible object T...
Definition: library_interface.hpp:42
decltype(auto) constexpr access(Arg &&arg, const Indices &indices)
Access a component of an indexible object at a given set of indices.
Definition: access.hpp:74
Definition: object_traits.hpp:38
constexpr auto operator[](const Indices &indices) const
Access a component at a set of indices.
Definition: constant_adapter.hpp:175
constexpr auto value() const
Get the values::scalar associated with this object.
Definition: constant_adapter.hpp:189
decltype(auto) constexpr sum(Ts &&...ts)
Element-by-element sum of one or more objects.
Definition: sum.hpp:112
constexpr constant_adapter(V &&v, S &&s)
Construct from value and a reference to an indexible object.
Definition: constant_adapter.hpp:88
constexpr auto constant_value(T &&t)
The constant value associated with a constant_object or constant_diagonal_object. ...
Definition: constant_value.hpp:37
Definition of get_pattern_collection function.
Definition for indexible.
constexpr auto make_constant(C c, stdex::extents< IndexType, Extents... > extents)
Make an indexible object in which every element is a constant value.
Definition: make_constant.hpp:39
A matrix with typed rows and columns.
Definition: forward-class-declarations.hpp:292
constexpr constant_adapter(Arg &&arg)
Construct from another constant_object.
Definition: constant_adapter.hpp:136
A tensor or other matrix in which all elements are a constant value.
Definition: constant_adapter.hpp:52