OpenKalman
ConstantAdapter.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-2024 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_CONSTANTADAPTER_HPP
17 #define OPENKALMAN_CONSTANTADAPTER_HPP
18 
19 #include <type_traits>
20 #include <algorithm>
21 
22 namespace OpenKalman
23 {
24  // ----------------- //
25  // ConstantAdapter //
26  // ----------------- //
27 
28 #ifdef __cpp_concepts
29  template<indexible PatternMatrix, values::scalar Scalar, auto...constant>
30  requires (sizeof...(constant) == 0) or requires { Scalar {constant...}; }
31 #else
32  template<typename PatternMatrix, typename Scalar, auto...constant>
33 #endif
34  struct ConstantAdapter : internal::library_base_t<ConstantAdapter<PatternMatrix, Scalar, constant...>, PatternMatrix>
35  {
36 
37  private:
38 
39 #ifndef __cpp_concepts
40  static_assert(indexible<PatternMatrix>);
41  static_assert(values::scalar<Scalar>);
42  static_assert(sizeof...(constant) == 0 or std::is_constructible_v<Scalar, decltype(constant)...>);
43 #endif
44 
45  using MyConstant = std::conditional_t<sizeof...(constant) == 0, Scalar, values::Fixed<Scalar, constant...>>;
46  using MyScalarType = values::number_type_of_t<MyConstant>;
47 
48  using AllDescriptorsType = decltype(all_vector_space_descriptors(std::declval<PatternMatrix>()));
49  using DescriptorCollection = std::conditional_t<
50  pattern_tuple<AllDescriptorsType>,
51  AllDescriptorsType,
52  std::vector<DynamicDescriptor<MyScalarType>>>;
53 
54 
55  template<typename D, std::size_t...Ix, std::size_t...IxExtra>
56  static constexpr auto make_descriptors_tuple(D&& d, std::index_sequence<Ix...>, std::index_sequence<IxExtra...>)
57  {
58  if constexpr ((... or dynamic_pattern<std::tuple_element_t<IxExtra, D>>))
59  if ((... or (std::get<IxExtra>(d) != Axis{})));
60  throw std::invalid_argument {"Too many elements in vector space descriptors_collection_tuple argument of a constant adapter"};
61 
62  return std::tuple {[](D&& d){
63  using E = std::tuple_element_t<Ix, DescriptorCollection>;
64 
65  if constexpr (Ix < std::tuple_size_v<D>)
66  {
67  if constexpr (fixed_pattern<E>)
68  {
69  if constexpr (dynamic_pattern<std::tuple_element_t<Ix, D>>)
70  if (std::get<Ix>(d) != E{}) throw std::invalid_argument {
71  "Invalid dynamic element in pattern_tuple argument of a constant adapter"};
72  return E{};
73  }
74  else // if constexpr (dynamic_pattern<E>)
75  {
76  return std::forward<D>(d);
77  }
78  }
79  else
80  {
81  return E{};
82  }
83  }(std::forward<D>(d))...};
84  }
85 
86 
87  template<std::size_t N = 0, typename Iterator, typename Sentinel>
88  static constexpr auto make_descriptors_tuple_from_range(Iterator it, const Sentinel& end)
89  {
90  if constexpr (N >= std::tuple_size_v<DescriptorCollection>)
91  {
92  for (; it != end; ++it) if (*it != Axis{}) throw std::invalid_argument {
93  "Too many elements in vector space descriptors_collection range argument of a constant adapter"};
94  return std::tuple {};
95  }
96  else if constexpr (fixed_pattern<std::tuple_element_t<N, DescriptorCollection>>)
97  {
98  using E = std::tuple_element_t<N, DescriptorCollection>;
99  if (it == end)
100  {
101  if (not compares_with<E, Axis>) throw std::invalid_argument {
102  "Too few elements in vector space descriptors_collection range argument of a constant adapter"};
103  return std::tuple_cat(std::forward_as_tuple(E{}),
104  make_descriptors_tuple_from_range<N + 1>(std::move(it), end));
105  }
106  else
107  {
108  if constexpr (dynamic_pattern<decltype(*it)>)
109  if (*it != E{}) throw std::invalid_argument {
110  "Invalid dynamic element in pattern_collection range argument of a constant adapter"};
111  return std::tuple_cat(std::forward_as_tuple(E{}),
112  make_descriptors_tuple_from_range<N + 1>(++it, end));
113  }
114  }
115  else // if constexpr (dynamic_pattern<std::tuple_element_t<N, DescriptorCollection>>)
116  {
117  using E = std::tuple_element_t<N, DescriptorCollection>;
118  if (it == end) throw std::invalid_argument {
119  "Too few elements in vector space descriptors_collection range argument of a constant adapter"};
120  std::tuple_element_t<N, DescriptorCollection> e {*it};
121  return std::tuple_cat(std::forward_as_tuple(std::move(e)),
122  make_descriptors_tuple_from_range<N + 1>(++it, end));
123  }
124  }
125 
126 
127  template<typename D, std::size_t...Ix>
128  static constexpr auto make_descriptors_range_from_tuple(D&& d, std::index_sequence<Ix...>)
129  {
130  return DescriptorCollection {{DynamicDescriptor<MyScalarType> {std::get<Ix>(std::forward<D>(d))}...}};
131  }
132 
133 
134  template<typename Descriptors>
135  static constexpr auto make_descriptors_collection(Descriptors&& descriptors)
136  {
137 #ifdef __cpp_lib_ranges
138  namespace ranges = std::ranges;
139 #endif
140  if constexpr (pattern_tuple<DescriptorCollection>)
141  {
142  if constexpr (pattern_tuple<Descriptors>)
143  {
144  constexpr auto N = std::tuple_size_v<DescriptorCollection>;
145  constexpr auto M = std::tuple_size_v<Descriptors>;
146  return make_descriptors_tuple(std::forward<Descriptors>(descriptors),
147  std::make_index_sequence<N> {},
148  std::make_index_sequence<(M > N) ? M - N : 0> {});
149  }
150  else
151  {
152  return make_descriptors_tuple_from_range(ranges::begin(descriptors), ranges::end(descriptors));
153  }
154  }
155  else if constexpr (pattern_tuple<Descriptors>)
156  {
157  return make_descriptors_range_from_tuple(std::forward<Descriptors>(descriptors),
158  std::make_index_sequence<std::tuple_size_v<Descriptors>> {});
159  }
160  else
161  {
162  DescriptorCollection ret;
163  std::copy(ranges::begin(descriptors), ranges::end(descriptors), ranges::begin(ret));
164  return ret;
165  }
166  }
167 
168  public:
169 
173 #ifdef __cpp_lib_ranges
174  template<values::scalar C, pattern_collection Descriptors> requires
175  std::constructible_from<MyConstant, C&&> and
176  compatible_with_vector_space_descriptor_collection<PatternMatrix, Descriptors>
177 #else
178  template<typename C, typename Descriptors, std::enable_if_t<
179  values::scalar<C> and pattern_collection<Descriptors> and
180  std::is_constructible_v<MyConstant, C&&> and
181  compatible_with_vector_space_descriptor_collection<PatternMatrix, Descriptors>, int> = 0>
182 #endif
183  explicit constexpr ConstantAdapter(C&& c, Descriptors&& descriptors)
184  : my_constant {std::forward<C>(c)},
185  descriptor_collection {make_descriptors_collection(std::forward<Descriptors>(descriptors))} {}
186 
187 
192 #ifdef __cpp_lib_ranges
193  template<pattern_collection Descriptors> requires
194  values::fixed<MyConstant> and
195  compatible_with_vector_space_descriptor_collection<PatternMatrix, Descriptors>
196 #else
197  template<typename Descriptors, std::enable_if_t<
198  pattern_collection<Descriptors> and
199  values::fixed<MyConstant> and
200  compatible_with_vector_space_descriptor_collection<PatternMatrix, Descriptors>, int> = 0>
201 #endif
202  explicit constexpr ConstantAdapter(Descriptors&& descriptors)
203  : descriptor_collection {make_descriptors_collection(std::forward<Descriptors>(descriptors))} {}
204 
205 
217 #ifdef __cpp_concepts
218  template<values::scalar C, vector_space_descriptors_may_match_with<PatternMatrix> Arg> requires
219  std::constructible_from<MyConstant, C&&>
220 #else
221  template<typename C, typename Arg, std::enable_if_t<
222  values::scalar<C> and vector_space_descriptors_may_match_with<Arg, PatternMatrix> and
223  std::is_constructible_v<MyConstant, C&&>, int> = 0>
224 #endif
225  constexpr ConstantAdapter(C&& c, const Arg& arg) :
226  my_constant {std::forward<C>(c)},
227  descriptor_collection {make_descriptors_collection(all_vector_space_descriptors(arg))} {}
228 
229 
234 #ifdef __cpp_concepts
235  template<vector_space_descriptors_may_match_with<PatternMatrix> Arg> requires
236  (not std::is_base_of_v<ConstantAdapter, Arg>) and
237  values::fixed<MyConstant>
238 #else
239  template<typename Arg, std::enable_if_t<
240  vector_space_descriptors_may_match_with<Arg, PatternMatrix> and
241  (not std::is_base_of_v<ConstantAdapter, Arg>) and
242  values::fixed<MyConstant>, int> = 0>
243 #endif
244  constexpr ConstantAdapter(const Arg& arg) :
245  descriptor_collection {make_descriptors_collection(all_vector_space_descriptors(arg))} {}
246 
247 
251 #ifdef __cpp_concepts
252  template<constant_matrix Arg> requires
253  (not std::is_base_of_v<ConstantAdapter, Arg>) and
254  vector_space_descriptors_may_match_with<Arg, PatternMatrix> and
255  std::constructible_from<MyConstant, constant_coefficient<Arg>>
256 #else
257  template<typename Arg, std::enable_if_t<constant_matrix<Arg> and
258  (not std::is_base_of_v<ConstantAdapter, Arg>) and
259  vector_space_descriptors_may_match_with<Arg, PatternMatrix> and
260  std::is_constructible_v<MyConstant, constant_coefficient<Arg>>, int> = 0>
261 #endif
262  constexpr ConstantAdapter(const Arg& arg) :
263  my_constant {constant_coefficient {arg}},
264  descriptor_collection {make_descriptors_collection(all_vector_space_descriptors(arg))} {}
265 
266 
276 #ifdef __cpp_concepts
277  template<values::scalar C, coordinates::pattern...Ds> requires
278  std::constructible_from<MyConstant, C&&> and
279  compatible_with_vector_space_descriptor_collection<PatternMatrix, std::tuple<Ds...>>
280 #else
281  template<typename C, typename...Ds, std::enable_if_t<
282  values::scalar<C> and (coordinates::pattern<Ds> and ...) and
283  std::is_constructible_v<MyConstant, C&&> and
284  compatible_with_vector_space_descriptor_collection<PatternMatrix, std::tuple<Ds...>>, int> = 0>
285 #endif
286  explicit constexpr ConstantAdapter(C&& c, Ds&&...ds)
287  : ConstantAdapter(std::forward<C>(c), std::tuple {std::forward<Ds>(ds)...}) {}
288 
289 
303 #ifdef __cpp_concepts
304  template<coordinates::pattern...Ds> requires
305  values::fixed<MyConstant> and
306  compatible_with_vector_space_descriptor_collection<PatternMatrix, std::tuple<Ds...>>
307 #else
308  template<typename...Ds, std::enable_if_t<
309  (coordinates::pattern<Ds> and ...) and
310  values::fixed<MyConstant> and
311  compatible_with_vector_space_descriptor_collection<PatternMatrix, std::tuple<Ds...>>, int> = 0>
312 #endif
313  explicit constexpr ConstantAdapter(Ds&&...ds)
314  : ConstantAdapter(std::tuple {std::forward<Ds>(ds)...}) {}
315 
316  private:
317 
318  template<std::size_t N = 0>
319  constexpr auto make_dynamic_dimensions_tuple()
320  {
321  if constexpr (N < index_count_v<PatternMatrix>)
322  return std::tuple_cat(std::forward_as_tuple(std::get<N>(descriptor_collection)), make_dynamic_dimensions_tuple<N + 1>());
323  else
324  return std::tuple {};
325  }
326 
327 
328  template<std::size_t N = 0, typename D, typename...Ds>
329  constexpr auto make_dynamic_dimensions_tuple(D&& d, Ds&&...ds)
330  {
331  if constexpr (dynamic_pattern<std::tuple_element_t<N, DescriptorCollection>>)
332  return std::tuple_cat(std::forward_as_tuple(std::forward<D>(d)),
333  make_dynamic_dimensions_tuple<N + 1>(std::forward<Ds>(ds)...));
334  else
335  return std::tuple_cat(std::forward_as_tuple(std::get<N>(descriptor_collection)),
336  make_dynamic_dimensions_tuple<N + 1>(std::forward<D>(d), std::forward<Ds>(ds)...));
337  }
338 
339  public:
340 
355 #ifdef __cpp_concepts
356  template<values::scalar C, dynamic_pattern...Ds> requires
357  pattern_tuple<DescriptorCollection> and
358  (dynamic_index_count_v<PatternMatrix> != dynamic_size) and
359  (sizeof...(Ds) == dynamic_index_count_v<PatternMatrix>) and
360  std::constructible_from<MyConstant, C&&>
361 #else
362  template<typename C, typename...Ds, std::enable_if_t<
363  values::scalar<C> and (dynamic_pattern<Ds> and ...) and
364  pattern_tuple<DescriptorCollection> and
365  (dynamic_index_count_v<PatternMatrix> != dynamic_size) and
366  (sizeof...(Ds) == dynamic_index_count_v<PatternMatrix>) and
367  std::is_constructible_v<MyConstant, C&&>, int> = 0>
368 #endif
369  explicit constexpr ConstantAdapter(C&& c, Ds&&...ds)
370  : ConstantAdapter(std::forward<C>(c), make_dynamic_dimensions_tuple(std::forward<Ds>(ds)...)) {}
371 
372 
384 #ifdef __cpp_concepts
385  template<dynamic_pattern...Ds> requires
386  pattern_tuple<DescriptorCollection> and
387  (dynamic_index_count_v<PatternMatrix> != dynamic_size) and
388  (sizeof...(Ds) == dynamic_index_count_v<PatternMatrix>) and
389  values::fixed<MyConstant>
390 #else
391  template<typename...Ds, std::enable_if_t<
392  values::scalar<C> and (dynamic_pattern<Ds> and ...) and
393  pattern_tuple<DescriptorCollection> and
394  (dynamic_index_count_v<PatternMatrix> != dynamic_size) and
395  (sizeof...(Ds) == dynamic_index_count_v<PatternMatrix>) and
396  values::fixed<MyConstant>, int> = 0>
397 #endif
398  explicit constexpr ConstantAdapter(Ds&&...ds)
399  : ConstantAdapter(make_dynamic_dimensions_tuple(std::forward<Ds>(ds)...)) {}
400 
401 
405 #ifdef __cpp_concepts
406  template<constant_matrix Arg> requires
407  (not std::derived_from<Arg, ConstantAdapter>) and
408  vector_space_descriptors_may_match_with<Arg, PatternMatrix> and
409  std::assignable_from<MyConstant, constant_coefficient<Arg>>
410 #else
411  template<typename Arg, std::enable_if_t<constant_matrix<Arg> and
412  (not std::is_base_of_v<ConstantAdapter, Arg>) and
413  vector_space_descriptors_may_match_with<Arg, PatternMatrix> and
414  std::is_assignable_v<MyConstant, constant_coefficient<Arg>>, int> = 0>
415 #endif
416  constexpr auto& operator=(const Arg& arg)
417  {
418  if constexpr (not vector_space_descriptors_match_with<Arg, PatternMatrix>)
419  if (not vector_space_descriptors_match(*this, arg)) throw std::invalid_argument {
420  "Argument to ConstantAdapter assignment operator has non-matching vector space descriptors."};
421  my_constant = constant_coefficient {arg};
422  return *this;
423  }
424 
425 
429 #ifdef __cpp_concepts
430  template<indexible Arg>
431 #else
432  template<typename Arg, std::enable_if_t<indexible<Arg>, int> = 0>
433 #endif
434  constexpr bool operator==(const Arg& arg) const
435  {
436  if constexpr (not vector_space_descriptors_may_match_with<Arg, PatternMatrix>)
437  return false;
438  else if constexpr (constant_matrix<Arg>)
439  return values::to_number(constant_coefficient{arg}) == values::to_number(my_constant) and vector_space_descriptors_match(*this, arg);
440  else
441  {
442  auto c = to_native_matrix<PatternMatrix>(*this);
443  static_assert(not std::is_same_v<decltype(c), ConstantAdapter>,
444  "interface::library_interface<PatternMatrix>::to_native_matrix(*this) must define an object within the library of Arg");
445  return std::move(c) == arg;
446  }
447  }
448 
449 
450 #ifndef __cpp_impl_three_way_comparison
451 
454 #ifdef __cpp_concepts
455  template<indexible Arg> (not constant_adapter<Arg>)
456 #else
457  template<typename Arg, std::enable_if_t<indexible<Arg> and not constant_adapter<Arg>, int> = 0>
458 #endif
459  friend constexpr bool operator==(const Arg& arg, const ConstantAdapter& c)
460  {
461  if constexpr (not vector_space_descriptors_may_match_with<Arg, PatternMatrix>)
462  return false;
463  else if constexpr (constant_matrix<Arg>)
465  else
466  {
467  auto new_c = to_native_matrix<Arg>(c);
468  static_assert(not std::is_same_v<decltype(new_c), ConstantAdapter>,
469  "interface::library_interface<Arg>::to_native_matrix(c) must define an object within the library of Arg");
470  return arg == std::move(new_c);
471  }
472  }
473 
474 
475 #ifdef __cpp_concepts
476  template<indexible Arg>
477 #else
478  template<typename Arg, std::enable_if_t<indexible<Arg>, int> = 0>
479 #endif
480  constexpr bool operator!=(const Arg& arg) const { return not (*this == arg); }
481 
482 
483 #ifdef __cpp_concepts
484  template<indexible Arg> (not std::same_as<Arg, ConstantAdapter>)
485 #else
486  template<typename Arg, std::enable_if_t<indexible<Arg> and not std::is_same_v<Arg, ConstantAdapter>, int> = 0>
487 #endif
488  friend constexpr bool operator!=(const Arg& arg, const ConstantAdapter& c) { return not (arg == c); }
489 #endif
490 
491 
496 #ifdef __cpp_lib_ranges
497  template<index_range_for<PatternMatrix> Indices> requires (not empty_object<PatternMatrix>)
498  constexpr values::scalar auto
499 #else
500  template<typename Indices, std::enable_if_t<
501  index_range_for<Indices, PatternMatrix> and (not empty_object<PatternMatrix>), int> = 0>
502  constexpr auto
503 #endif
504  operator[](const Indices& indices) const
505  {
506  return values::to_number(my_constant);
507  }
508 
509 
513 #ifdef __cpp_concepts
514  constexpr values::scalar auto
515 #else
516  constexpr auto
517 #endif
519  {
520  return my_constant;
521  }
522 
523 
524  friend auto operator-(const ConstantAdapter& arg)
525  {
526  if constexpr (zero<ConstantAdapter>) return arg;
527  else
528  {
529  values::operation op {std::negate{}, constant_coefficient{arg}};
530  return make_constant(arg, op);
531  }
532  }
533 
534 
535 #ifdef __cpp_concepts
536  friend auto operator*(const ConstantAdapter& arg, values::scalar auto s)
537 #else
538  template<typename S, std::enable_if_t<values::scalar<S>, int> = 0>
539  friend auto operator*(const ConstantAdapter& arg, S s)
540 #endif
541  {
542  if constexpr (zero<decltype(arg)>) return arg;
543  else
544  {
545  return make_constant(arg, constant_coefficient{arg} * s);
546  }
547  }
548 
549 
550 #ifdef __cpp_concepts
551  friend auto operator*(values::scalar auto s, const ConstantAdapter& arg)
552 #else
553  template<typename S, std::enable_if_t<values::scalar<S>, int> = 0>
554  friend auto operator*(S s, const ConstantAdapter& arg)
555 #endif
556  {
557  if constexpr (zero<decltype(arg)>) return arg;
558  else
559  {
560  return make_constant(arg, s * constant_coefficient{arg});
561  }
562  }
563 
564 
565 #ifdef __cpp_concepts
566  friend auto operator/(const ConstantAdapter& arg, values::scalar auto s)
567 #else
568  template<typename S, std::enable_if_t<values::scalar<S>, int> = 0>
569  friend auto operator/(const ConstantAdapter& arg, S s)
570 #endif
571  {
572  return make_constant(arg, constant_coefficient{arg} / s);
573  }
574 
575  protected:
576 
577  MyConstant my_constant;
578 
579  DescriptorCollection descriptor_collection;
580 
581  friend struct interface::indexible_object_traits<ConstantAdapter>;
582  friend struct interface::library_interface<ConstantAdapter>;
583 
584  };
585 
586 
587  // ------------------ //
588  // Deduction guides //
589  // ------------------ //
590 
591 #ifdef __cpp_concepts
592  template<values::scalar C, indexible Arg>
593 #else
594  template<typename C, typename Arg, std::enable_if_t<values::scalar<C> and indexible<Arg>, int> = 0>
595 #endif
596  ConstantAdapter(const C&, const Arg&) -> ConstantAdapter<Arg, C>;
597 
598 
599 #ifdef __cpp_concepts
600  template<constant_matrix Arg> requires (not constant_adapter<Arg>)
601 #else
602  template<typename Arg, std::enable_if_t<constant_matrix<Arg> and (not constant_adapter<Arg>), int> = 0>
603 #endif
605 
606 
607  // ------------ //
608  // Interfaces //
609  // ------------ //
610 
611  namespace interface
612  {
613  template<typename PatternMatrix, typename Scalar, auto...constant>
614  struct indexible_object_traits<ConstantAdapter<PatternMatrix, Scalar, constant...>>
615  {
616  private:
617 
618  using XprType = ConstantAdapter<PatternMatrix, Scalar, constant...>;
619 
620  public:
621 
622  using scalar_type = typename XprType::MyScalarType;
623  using MyDims = typename XprType::MyDimensions_t;
624 
625 
626  template<typename Arg>
627  static constexpr auto count_indices(const Arg& arg)
628  {
629  if constexpr (index_count_v<PatternMatrix> == dynamic_size)
630  return std::forward<Arg>(arg).descriptor_collection.size();
631  else
632  return std::tuple_size<MyDims>{};
633  }
634 
635 
636  template<typename Arg, typename N>
637  static constexpr auto get_vector_space_descriptor(Arg&& arg, const N& n)
638  {
639  if constexpr (index_count_v<PatternMatrix> == dynamic_size)
640  {
641  return std::forward<Arg>(arg).descriptor_collection[static_cast<typename MyDims::size_type>(n)];
642  }
643  else if constexpr (values::fixed<N>)
644  {
645  if constexpr (N::value >= index_count_v<PatternMatrix>) return Dimensions<1>{};
646  else return std::get<N::value>(std::forward<Arg>(arg).descriptor_collection);
647  }
648  else if (n >= std::tuple_size_v<MyDims>)
649  {
650  return 1_uz;
651  }
652  else
653  {
654  return std::apply(
655  [](auto&&...ds){ return std::array<std::size_t, std::tuple_size_v<MyDims>> {std::forward<decltype(ds)>(ds)...}; },
656  std::forward<Arg>(arg).descriptor_collection)[n];
657  }
658  }
659 
660 
661  // No nested_object defined
662 
663 
664  template<typename Arg>
665  static constexpr auto get_constant(const Arg& arg) { return arg.get_scalar_constant(); }
666 
667 
668  // No get_constant_diagonal defined
669 
670 
671  template<Applicability b>
672  static constexpr bool one_dimensional = OpenKalman::one_dimensional<PatternMatrix, b>;
673 
674 
675  template<Applicability b>
676  static constexpr bool is_square = OpenKalman::square_shaped<PatternMatrix, b>;
677 
678 
679  // No is_triangular, is_triangular_adapter, is_hermitian, or hermitian_adapter_type defined
680 
681 
682  static constexpr bool is_writable = false;
683 
684 
685  // No raw_data, layout, or strides defined.
686 
687  };
688 
689 
690  template<typename PatternMatrix, typename Scalar, auto...constant>
691  struct library_interface<ConstantAdapter<PatternMatrix, Scalar, constant...>>
692  {
693  template<typename Derived>
694  using LibraryBase = internal::library_base_t<Derived, PatternMatrix>;
695 
696 
697  template<typename Arg, typename Indices>
698  static constexpr auto
699  get_component(Arg&& arg, const Indices&) { return std::forward<Arg>(arg).get_scalar_constant(); }
700 
701 
702  // No set_component defined because ConstantAdapter is not writable.
703 
704 
705  template<typename Arg>
706  static decltype(auto)
707  to_native_matrix(Arg&& arg)
708  {
709  return OpenKalman::to_native_matrix<PatternMatrix>(std::forward<Arg>(arg));
710  }
711 
712 
713  template<Layout layout, typename S, typename D>
714  static auto
715  make_default(D&& d)
716  {
717  return make_dense_object<PatternMatrix, layout, S>(std::forward<D>(d));
718  }
719 
720 
721  // fill_components not necessary because T is not a dense writable matrix.
722 
723 
724  template<typename C, typename D>
725  static constexpr auto
726  make_constant(C&& c, D&& d)
727  {
728  return OpenKalman::make_constant<PatternMatrix>(std::forward<C>(c), std::forward<D>(d));
729  }
730 
731 
732  template<typename S, typename D>
733  static constexpr auto
734  make_identity_matrix(D&& d)
735  {
736  return make_identity_matrix_like<PatternMatrix, S>(std::forward<D>(d));
737  }
738 
739 
740  // no get_slice
741  // no set_slice
742  // no set_triangle
743  // no to_diagonal
744  // no diagonal_of
745 
746 
747  template<typename...Ds, typename Arg>
748  static decltype(auto)
749  replicate(const std::tuple<Ds...>& tup, Arg&& arg)
750  {
751  return library_interface<PatternMatrix>::replicate(tup, std::forward<Arg>(arg));
752  }
753 
754 
755  template<typename...Ds, typename Op, typename...Args>
756  static constexpr decltype(auto)
757  n_ary_operation(const std::tuple<Ds...>& d_tup, Op&& op, Args&&...args)
758  {
759  return library_interface<PatternMatrix>::n_ary_operation(d_tup, std::forward<Op>(op), std::forward<Args>(args)...);
760  }
761 
762 
763  template<std::size_t...indices, typename BinaryFunction, typename Arg>
764  static constexpr decltype(auto)
765  reduce(BinaryFunction&& b, Arg&& arg)
766  {
767  return library_interface<PatternMatrix>::template reduce<indices...>(std::forward<BinaryFunction>(b), std::forward<Arg>(arg));
768  }
769 
770 
771  // no to_euclidean
772  // no from_euclidean
773  // no wrap_angles
774 
775  // conjugate is not necessary because it is handled by the general conjugate function.
776  // transpose is not necessary because it is handled by the general transpose function.
777  // adjoint is not necessary because it is handled by the general adjoint function.
778  // determinant is not necessary because it is handled by the general determinant function.
779 
780 
781  template<typename A, typename B>
782  static constexpr auto sum(A&& a, B&& b)
783  {
784  return library_interface<PatternMatrix>::sum(std::forward<A>(a), std::forward<B>(b));
785  }
786 
787 
788  template<typename A, typename B>
789  static constexpr auto contract(A&& a, B&& b)
790  {
791  return library_interface<PatternMatrix>::contract(std::forward<A>(a), std::forward<B>(b));
792  }
793 
794 
795  // contract_in_place is not necessary because the argument will not be writable.
796 
797  // cholesky_factor is not necessary because it is handled by the general cholesky_factor function.
798 
799 
800  template<HermitianAdapterType significant_triangle, typename A, typename U, typename Alpha>
801  static decltype(auto) rank_update_hermitian(A&& a, U&& u, const Alpha alpha)
802  {
804  return Trait::template rank_update_hermitian<significant_triangle>(std::forward<A>(a), std::forward<U>(u), alpha);
805  }
806 
807 
808  // rank_update_triangular is not necessary because it is handled by the general rank_update_triangular function.
809 
810  // solve is not necessary because it is handled by the general solve function.
811 
812  // LQ_decomposition is not necessary because it is handled by the general LQ_decomposition function.
813 
814  // QR_decomposition is not necessary because it is handled by the general QR_decomposition function.
815 
816  };
817 
818  } // namespace interface
819 
820 
821 } // namespace OpenKalman
822 
823 
824 #endif //OPENKALMAN_CONSTANTADAPTER_HPP
constexpr auto count_indices(const T &t)
Get the number of indices available to address the components of an indexible object.
Definition: count_indices.hpp:33
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:319
constexpr bool one_dimensional
Specifies that a type is one-dimensional in every index.
Definition: one_dimensional.hpp:83
decltype(auto) constexpr contract(A &&a, B &&b)
Matrix multiplication of A * B.
Definition: contract.hpp:54
Definition: indexible_object_traits.hpp:36
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
An operation involving some number of values.
Definition: operation.hpp:69
constexpr auto & operator=(const Arg &arg)
Assign from a compatible constant_matrix.
Definition: ConstantAdapter.hpp:416
constexpr ConstantAdapter(Descriptors &&descriptors)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: ConstantAdapter.hpp:202
constexpr bool indexible
T is a generalized tensor type.
Definition: indexible.hpp:32
decltype(auto) to_native_matrix(Arg &&arg)
If it isn&#39;t already, convert Arg to a native object in the library associated with LibraryObject...
Definition: to_native_matrix.hpp:35
Definition: tuple_reverse.hpp:103
constexpr auto operator[](const Indices &indices) const
Access a component at a set of indices.
Definition: ConstantAdapter.hpp:504
constexpr bool value
T is numerical value or is reducible to a numerical value.
Definition: value.hpp:31
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
constexpr auto to_number(Arg arg)
Convert any values::value to a values::number.
Definition: to_number.hpp:34
The constant associated with T, assuming T is a constant_matrix.
Definition: constant_coefficient.hpp:36
decltype(auto) constexpr all_vector_space_descriptors(const T &t)
Return a collection of coordinates::pattern objects associated with T.
Definition: all_vector_space_descriptors.hpp:52
constexpr detail::replicate_adaptor replicate
a std::ranges::range_adaptor_closure associated with replicate_view.
Definition: replicate.hpp:430
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:37
constexpr bool zero
Specifies that a type is known at compile time to be a constant matrix of value zero.
Definition: zero.hpp:43
constexpr ConstantAdapter(C &&c, Ds &&...ds)
Construct using a full set of coordinates::pattern objects.
Definition: ConstantAdapter.hpp:286
constexpr bool vector_space_descriptors_match(const Ts &...ts)
Return true if every set of coordinates::pattern of a set of objects match.
Definition: vector_space_descriptors_match.hpp:62
constexpr ConstantAdapter(C &&c, Descriptors &&descriptors)
Construct from values::scalar and a pattern_collection.
Definition: ConstantAdapter.hpp:183
constexpr ConstantAdapter(Ds &&...ds)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: ConstantAdapter.hpp:313
constexpr ConstantAdapter(const Arg &arg)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: ConstantAdapter.hpp:244
decltype(auto) constexpr sum(Ts &&...ts)
Element-by-element sum of one or more objects.
Definition: sum.hpp:112
Definition: Fixed.hpp:36
A tensor or other matrix in which all elements are a constant scalar value.
Definition: ConstantAdapter.hpp:34
std::decay_t< decltype(values::to_number(std::declval< T >()))> number_type_of_t
Obtain the values::number type associated with avalues::value.
Definition: number_type_of_t.hpp:34
constexpr auto make_constant(C &&c, Descriptors &&descriptors)
Make a constant object based on a particular library object.
Definition: make_constant.hpp:37
decltype(auto) constexpr get_component(Arg &&arg, const Indices &indices)
Get a component of an object at a particular set of indices.
Definition: get_component.hpp:54
constexpr bool compatible_with_vector_space_descriptor_collection
indexible T is compatible with pattern_collection D.
Definition: compatible_with_vector_space_descriptor_collection.hpp:74
constexpr ConstantAdapter(C &&c, const Arg &arg)
Construct based on a values::scalar and the shape of an indexible reference object.
Definition: ConstantAdapter.hpp:225
constexpr std::size_t dynamic_size
A constant indicating that a size or index is dynamic.
Definition: global-definitions.hpp:33
constexpr bool operator==(const Arg &arg) const
Comparison operator.
Definition: ConstantAdapter.hpp:434
A matrix with typed rows and columns.
Definition: forward-class-declarations.hpp:448
constexpr auto get_vector_space_descriptor(const T &t, const N &n)
Get the coordinates::pattern object for index N of indexible object T.
Definition: get_vector_space_descriptor.hpp:56
constexpr auto get_scalar_constant() const
Get the values::scalar associated with this object.
Definition: ConstantAdapter.hpp:518