OpenKalman
average_reduce.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_AVERAGE_REDUCE_HPP
17 #define OPENKALMAN_AVERAGE_REDUCE_HPP
18 
19 namespace OpenKalman
20 {
21  namespace detail
22  {
23  template<typename Arg, std::size_t...indices, std::size_t...Ix>
24  constexpr decltype(auto)
25  average_reduce_impl(Arg&& arg, std::index_sequence<indices...> indices_seq, std::index_sequence<Ix...> seq)
26  {
27  if constexpr (constant_matrix<Arg>)
28  {
29  return make_constant<Arg>(constant_coefficient{arg}, internal::get_reduced_vector_space_descriptor<Ix, indices...>(std::forward<Arg>(arg))...);
30  }
31  else
32  {
33  return scalar_quotient(
34  reduce<indices...>(std::plus<scalar_type_of_t<Arg>> {}, std::forward<Arg>(arg)),
35  internal::count_reduced_dimensions(arg, indices_seq, seq));
36  }
37  }
38 
39  } // namespace detail
40 
41 
50 #ifdef __cpp_concepts
51  template<std::size_t index, std::size_t...indices, internal::has_uniform_static_vector_space_descriptors<index, indices...> Arg> requires
52  (not empty_object<Arg>)
53  constexpr indexible decltype(auto)
54 #else
55  template<std::size_t index, std::size_t...indices, typename Arg, std::enable_if_t<
56  internal::has_uniform_static_vector_space_descriptors<Arg, index, indices...> and (not empty_object<Arg>), int> = 0>
57  constexpr decltype(auto)
58 #endif
59  average_reduce(Arg&& arg)
60  {
61  if constexpr (dimension_size_of_index_is<Arg, index, 1>)
62  {
63  // Check if Arg is already reduced along index.
64  if constexpr (sizeof...(indices) == 0) return std::forward<Arg>(arg);
65  else return average_reduce<indices...>(std::forward<Arg>(arg));
66  }
67  else
68  {
69  return detail::average_reduce_impl(std::forward<Arg>(arg), std::index_sequence<index, indices...>{}, std::make_index_sequence<index_count_v<Arg>>{});
70  }
71  }
72 
73 
79 #ifdef __cpp_concepts
80  template<internal::has_uniform_static_vector_space_descriptors Arg>
81 #else
82  template<typename Arg, std::enable_if_t<internal::has_uniform_static_vector_space_descriptors<Arg>, int> = 0>
83 #endif
84  constexpr scalar_type_of_t<Arg>
85  average_reduce(Arg&& arg)
86  {
87  if constexpr (zero<Arg>)
88  {
89  return 0;
90  }
91  else if constexpr (constant_matrix<Arg>)
92  {
93  return constant_coefficient{arg}();
94  }
95  else if constexpr (constant_diagonal_matrix<Arg>)
96  {
97  // Arg cannot be a zero matrix, so the denominator should never be zero.
98  return values::operation {
99  std::divides<scalar_type_of_t<Arg>>{},
101  internal::largest_vector_space_descriptor<scalar_type_of_t<Arg>>(get_vector_space_descriptor<0>(arg), get_vector_space_descriptor<1>(arg))};
102  }
103  else
104  {
105  auto r = reduce(std::plus<scalar_type_of_t<Arg>>{}, std::forward<Arg>(arg));
106  // Arg cannot be a zero matrix, so the denominator should never be zero.
107  if constexpr (index_count_v<Arg> == dynamic_size)
108  {
109  std::size_t denom = 1;
110  for (std::size_t i = 0; i < count_indices(arg); ++i) denom *= get_index_dimension_of(arg, i);
111  return r / denom;
112  }
113  else
114  {
115  auto denom = (std::apply([](const auto&...d){ return (get_dimension(d) * ...); }, all_vector_space_descriptors(arg)));
116  return r / denom;
117  }
118  }
119  }
120 
121 
122 } // namespace OpenKalman
123 
124 #endif //OPENKALMAN_AVERAGE_REDUCE_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
decltype(auto) constexpr average_reduce(Arg &&arg)
Perform a partial reduction by taking the average along one or more indices.
Definition: average_reduce.hpp:59
An operation involving some number of values.
Definition: operation.hpp:69
typename scalar_type_of< T >::type scalar_type_of_t
helper template for scalar_type_of.
Definition: scalar_type_of.hpp:54
constexpr bool indexible
T is a generalized tensor type.
Definition: indexible.hpp:32
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 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
The root namespace for OpenKalman.
Definition: basics.hpp:34
The constant associated with T, assuming T is a constant_diagonal_matrix.
Definition: constant_diagonal_coefficient.hpp:32
constexpr std::size_t dynamic_size
A constant indicating that a size or index is dynamic.
Definition: global-definitions.hpp:33
constant_coefficient(const T &) -> constant_coefficient< T >
Deduction guide for constant_coefficient.
constexpr auto get_index_dimension_of(const T &t, N n=N{})
Get the runtime dimensions of index N of indexible T.
Definition: get_index_dimension_of.hpp:34
constexpr bool index
An object describing a collection of /ref values::index objects.
Definition: index.hpp:75