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_value{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  }
40 
41 
50 #ifdef __cpp_concepts
51  template<std::size_t index, std::size_t...indices, internal::has_uniform_patterns<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_patterns<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_patterns Arg>
81 #else
82  template<typename Arg, std::enable_if_t<internal::has_uniform_patterns<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_value{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>>{},
100  constant_diagonal_value{arg},
101  internal::largest_pattern<scalar_type_of_t<Arg>>(get_pattern_collection<0>(arg), get_pattern_collection<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> == stdex::dynamic_extent)
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 }
123 
124 #endif
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
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
constexpr bool indexible
T is a multidimensional array type.
Definition: indexible.hpp:32
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 auto get_dimension(const Arg &arg)
Get the vector dimension of coordinates::pattern Arg.
Definition: get_dimension.hpp:54
The root namespace for OpenKalman.
Definition: basics.hpp:34
constexpr auto constant_value(T &&t)
The constant value associated with a constant_object or constant_diagonal_object. ...
Definition: constant_value.hpp:37
Definition: trait_backports.hpp:64
constexpr auto operation(Operation &&op, Args &&...args)
A potentially constant-evaluated operation involving some number of values.
Definition: operation.hpp:98
constexpr bool index
An object describing a collection of /ref values::index objects.
Definition: index.hpp:77