OpenKalman
sum.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-2023 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_SUM_HPP
17 #define OPENKALMAN_SUM_HPP
18 
19 #include<complex>
20 
21 
22 namespace OpenKalman
23 {
24  namespace detail
25  {
26  template<std::size_t...Ix, typename T0, typename T1>
27  constexpr auto sum_constants(std::index_sequence<Ix...> seq, T0&& t0, T1&& t1)
28  {
29  auto c = constant_coefficient{t0} + constant_coefficient{t1};
30  return make_constant<T0>(std::move(c), internal::best_vector_space_descriptor(
31  get_vector_space_descriptor<Ix>(t0), get_vector_space_descriptor<Ix>(t1))...);
32  }
33 
34 
35  template<typename T>
36  constexpr T&& sum_impl(T&& t) { return std::forward<T>(t); }
37 
38 
39  template<typename T0, typename T1, typename...Ts>
40  constexpr decltype(auto) sum_impl(T0&& t0, T1&& t1, Ts&&...ts)
41  {
42  if constexpr ((zero<T0> or zero<T1> or (constant_matrix<T0> and constant_matrix<T1>)) and not vector_space_descriptors_match_with<T0, T1>)
43  {
44  if (not vector_space_descriptors_match(t0, t1)) throw std::invalid_argument {"In sum function, vector space descriptors of arguments do not match"};
45  }
46 
47  if constexpr (zero<T0>)
48  {
49  return sum_impl(std::forward<T1>(t1), std::forward<Ts>(ts)...);
50  }
51  else if constexpr (zero<T1>)
52  {
53  return sum_impl(std::forward<T0>(t0), std::forward<Ts>(ts)...);
54  }
55  else if constexpr ((constant_matrix<T0> and constant_matrix<T1>))
56  {
57  constexpr std::make_index_sequence<std::max(index_count_v<T0>, index_count_v<T1>)> seq;
58  auto ret {sum_impl(sum_constants(seq, std::forward<T0>(t0), std::forward<T1>(t1)), std::forward<Ts>(ts)...)};
59  return ret;
60  }
61  else if constexpr (constant_matrix<T0> and sizeof...(Ts) > 0) // Shift T0 right and hope that it will combine with another constant
62  {
63  return sum_impl(std::forward<T1>(t1), sum_impl(std::forward<T0>(t0), std::forward<Ts>(ts)...));
64  }
65  else if constexpr (constant_matrix<T1> and sizeof...(Ts) > 0) // Shift T1 right and hope that it will combine with another constant
66  {
67  return sum_impl(std::forward<T0>(t0), sum_impl(std::forward<T1>(t1), std::forward<Ts>(ts)...));
68  }
69  else if constexpr (diagonal_matrix<T0> and diagonal_matrix<T1>)
70  {
71  auto ret {sum_impl(to_diagonal(sum_impl(diagonal_of(std::forward<T0>(t0)), diagonal_of(std::forward<T1>(t1)))), std::forward<Ts>(ts)...)};
72  return ret;
73  }
74  else if constexpr (interface::sum_defined_for<T0, T0&&, T1&&, Ts&&...>)
75  {
76  return interface::library_interface<std::decay_t<T0>>::sum(std::forward<T0>(t0), std::forward<T1>(t1), std::forward<Ts>(ts)...);
77  }
78  else if constexpr (interface::sum_defined_for<T0, T0&&, T1&&>)
79  {
80  return sum_impl(interface::library_interface<std::decay_t<T0>>::sum(std::forward<T0>(t0), std::forward<T1>(t1)), std::forward<Ts>(ts)...);
81  }
82  else if constexpr (interface::sum_defined_for<T1, T1&&, T0&&>)
83  {
84  return sum_impl(interface::library_interface<std::decay_t<T1>>::sum(std::forward<T1>(t1), std::forward<T0>(t0)), std::forward<Ts>(ts)...);
85  }
86  else if constexpr (interface::sum_defined_for<T0, T0&&, decltype(to_native_matrix<T0>(std::declval<T1&&>()))>)
87  {
88  return sum_impl(interface::library_interface<std::decay_t<T0>>::sum(std::forward<T0>(t0), to_native_matrix<T0>(std::forward<T1>(t1))), std::forward<Ts>(ts)...);
89  }
90  else if constexpr (interface::sum_defined_for<T1, T1&&, decltype(to_native_matrix<T1>(std::declval<T0&&>()))>)
91  {
92  return sum_impl(interface::library_interface<std::decay_t<T1>>::sum(std::forward<T1>(t1), to_native_matrix<T1>(std::forward<T0>(t0))), std::forward<Ts>(ts)...);
93  }
94  else
95  {
96  // \todo Add a default loop in case the library interface does not include sums?
97  }
98  }
99  } // namespace detail
100 
101 
105 #ifdef __cpp_concepts
106  template<indexible...Ts> requires (sizeof...(Ts) > 0) and vector_space_descriptors_may_match_with<Ts...>
107 #else
108  template<typename...Ts, std::enable_if_t<(indexible<Ts> and ...) and (sizeof...(Ts) > 0) and
110 #endif
111  constexpr decltype(auto)
112  sum(Ts&&...ts)
113  {
114  auto s {internal::make_fixed_size_adapter_like<Ts...>(detail::sum_impl(std::forward<Ts>(ts)...))};
115  constexpr auto t = triangle_type_of_v<Ts...>;
116  if constexpr (t != TriangleType::any and not triangular_matrix<decltype(s), t>)
117  return make_triangular_matrix<t>(std::move(s));
118  else if constexpr ((... and hermitian_matrix<Ts>) and not hermitian_matrix<decltype(s)>)
119  return make_hermitian_matrix(std::move(s));
120  else
121  return s;
122  }
123 
124 } // namespace OpenKalman
125 
126 
127 #endif //OPENKALMAN_SUM_HPP
decltype(auto) constexpr make_hermitian_matrix(Arg &&arg)
Creates a hermitian_matrix by, if necessary, wrapping the argument in a hermitian_adapter.
Definition: make_hermitian_matrix.hpp:37
Lower, upper, or diagonal matrix.
constexpr bool indexible
T is a generalized tensor type.
Definition: indexible.hpp:32
decltype(auto) constexpr to_diagonal(Arg &&arg)
Convert an indexible object into a diagonal matrix.
Definition: to_diagonal.hpp:32
constexpr bool triangular_matrix
Specifies that a type is a triangular matrix (upper, lower, or diagonal).
Definition: triangular_matrix.hpp:37
The root namespace for OpenKalman.
Definition: basics.hpp:34
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
decltype(auto) constexpr diagonal_of(Arg &&arg)
Extract a column vector (or column slice for rank>2 tensors) comprising the diagonal elements...
Definition: diagonal_of.hpp:33
constexpr bool vector_space_descriptors_may_match_with
Specifies that indexible objects Ts may have equivalent dimensions and vector-space types...
Definition: vector_space_descriptors_may_match_with.hpp:49
decltype(auto) constexpr sum(Ts &&...ts)
Element-by-element sum of one or more objects.
Definition: sum.hpp:112
constexpr auto triangle_type_of_v
The TriangleType associated with a triangular_matrix.
Definition: triangle_type_of.hpp:41
constant_coefficient(const T &) -> constant_coefficient< T >
Deduction guide for constant_coefficient.
constexpr bool hermitian_matrix
Specifies that a type is a hermitian matrix (assuming it is square_shaped).
Definition: hermitian_matrix.hpp:50