OpenKalman
trace.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-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_TRACE_HPP
17 #define OPENKALMAN_TRACE_HPP
18 
19 namespace OpenKalman
20 {
28 #ifdef __cpp_concepts
29  template<indexible Arg> requires (max_tensor_order_v<Arg> <= 2)
30  constexpr std::convertible_to<scalar_type_of_t<Arg>> decltype(auto)
31 #else
32  template<typename Arg, std::enable_if_t<(indexible<Arg>) and (max_tensor_order_v<Arg> <= 2), int> = 0>
33  constexpr decltype(auto)
34 #endif
35  trace(Arg&& arg)
36  {
37  using Scalar = scalar_type_of_t<Arg>;
38 
39  if constexpr (zero<Arg> or empty_object<Arg>)
40  {
41  return values::Fixed<Scalar, 0>{};
42  }
43  else if constexpr (identity_matrix<Arg>)
44  {
45  return values::cast_to<Scalar>(
46  internal::smallest_vector_space_descriptor<Scalar>(get_index_dimension_of<0>(arg), get_index_dimension_of<1>(arg)));
47  }
48  else if constexpr (one_dimensional<Arg>)
49  {
50  return internal::get_singular_component(std::forward<Arg>(arg));
51  }
52  else if constexpr (constant_matrix<Arg>)
53  {
54  std::multiplies<Scalar> op;
55  auto n = values::cast_to<Scalar>(
56  internal::smallest_vector_space_descriptor<Scalar>(get_index_dimension_of<0>(arg), get_index_dimension_of<1>(arg)));;
57  return values::operation{op, constant_coefficient{std::forward<Arg>(arg)}, n};
58  }
59  else if constexpr (constant_diagonal_matrix<Arg>)
60  {
61  std::multiplies<scalar_type_of_t<Arg>> op;
62  auto n = values::cast_to<Scalar>(
63  internal::smallest_vector_space_descriptor<Scalar>(get_index_dimension_of<0>(arg), get_index_dimension_of<1>(arg)));;
64  return values::operation{op, constant_diagonal_coefficient{std::forward<Arg>(arg)}, n};
65  }
66  else if constexpr (triangular_matrix<Arg>) // Includes the diagonal case.
67  {
68  return reduce(std::plus<Scalar>{}, diagonal_of(std::forward<Arg>(arg)));
69  }
70  else // General case in which we have to add up the diagonal elements.
71  {
72  decltype(auto) diag {diagonal_of(std::forward<Arg>(arg))};
73  if constexpr(dynamic_dimension<decltype(diag), 0>)
74  {
75  auto dim = get_index_dimension_of<0>(diag);
76  if (dim >= 2) return static_cast<Scalar>(reduce(std::plus<Scalar>{}, std::forward<decltype(diag)>(diag)));
77  else if (dim == 1) return static_cast<Scalar>(internal::get_singular_component(std::forward<decltype(diag)>(diag)));
78  else return static_cast<Scalar>(0); // d == 0 (empty vector)
79  }
80  else if constexpr (index_dimension_of_v<decltype(diag), 0> == 1)
81  {
82  return internal::get_singular_component(std::forward<decltype(diag)>(diag));
83  }
84  else
85  {
86  return reduce(std::plus<Scalar>{}, std::forward<decltype(diag)>(diag));
87  }
88  }
89  }
90 
91 } // namespace OpenKalman
92 
93 
94 #endif //OPENKALMAN_TRACE_HPP
typename scalar_type_of< T >::type scalar_type_of_t
helper template for scalar_type_of.
Definition: scalar_type_of.hpp:54
Definition: tuple_reverse.hpp:103
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
The root namespace for OpenKalman.
Definition: basics.hpp:34