OpenKalman
PartialReduxExpr.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) 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_EIGEN_PARTIALREDUXEXPR_HPP
17 #define OPENKALMAN_EIGEN_PARTIALREDUXEXPR_HPP
18 
19 #include <type_traits>
20 
22 {
23 #ifdef __cpp_concepts
24  template<typename Dim, typename OtherDim>
25  concept at_least_square = (std::decay_t<Dim>::value >= std::decay_t<OtherDim>::value);
26 #else
27  template<typename Dim, typename OtherDim, typename = void>
28  struct at_least_square_impl : std::false_type {};
29 
30  template<typename Dim, typename OtherDim>
31  struct at_least_square_impl<Dim, OtherDim, std::enable_if_t<
32  values::fixed<Dim> and values::fixed<OtherDim>>>
33  : std::bool_constant<std::decay_t<Dim>::value >= std::decay_t<OtherDim>::value> {};
34 
35  template<typename Dim, typename OtherDim>
36  constexpr bool at_least_square = at_least_square_impl<Dim, OtherDim>::value;
37 #endif
38 
39 
40  template<typename MemberOp, std::size_t direction, typename XprType, typename Factor, typename DirDim, typename Func>
41  constexpr auto get_constant_redux(const XprType& xpr, const Factor& factor, const DirDim& dir_dim, Func&& func)
42  {
43  auto dim = internal::best_vector_space_descriptor(dir_dim, get_index_dimension_of<direction>(xpr));
44 
45  if constexpr (Eigen3::eigen_MatrixWrapper<XprType> or Eigen3::eigen_ArrayWrapper<XprType> or
46  internal::fixed_size_adapter<XprType> or Eigen3::eigen_wrapper<XprType>)
47  {
48  return get_constant_redux<MemberOp, direction>(nested_object(xpr), factor, dim, std::forward<Func>(func));
49  }
50  else if constexpr (Eigen3::eigen_CwiseUnaryOp<XprType> or Eigen3::eigen_CwiseUnaryView<XprType>)
51  {
52  auto new_func = Eigen3::functor_composition {std::forward<Func>(func), xpr.functor()};
53  return get_constant_redux<MemberOp, direction>(xpr.nestedExpression(), factor, dim, std::move(new_func));
54  }
55  else if constexpr (Eigen3::eigen_Replicate<XprType>)
56  {
58  const auto& n_xpr = xpr.nestedExpression();
59  auto n_dim = get_index_dimension_of<direction>(n_xpr);
60 
61  auto f = [](const auto& dim, const auto& n_dim) {
62  if constexpr (F::value != dynamic_size) return F{};
63  else return values::operation {std::divides<std::size_t>{}, dim, n_dim};
64  }(dim, n_dim);
65 
66  auto new_dim = [](const auto& dim, const auto& n_dim) {
67  if constexpr (values::fixed<decltype(dim)> and F::value != dynamic_size and
68  not values::fixed<decltype(n_dim)>)
69  return values::operation {std::divides<std::size_t>{}, dim, F{}};
70  else
71  return n_dim;
72  }(dim, n_dim);
73 
74  auto new_f = values::operation{std::multiplies<std::size_t>{}, factor, f};
75  return get_constant_redux<MemberOp, direction>(n_xpr, new_f, new_dim, std::forward<Func>(func));
76  }
77  else
78  {
79  if constexpr (constant_matrix<XprType>)
80  {
81  auto c = values::operation {std::forward<Func>(func), constant_coefficient {xpr}};
83  }
84  else if constexpr (constant_diagonal_matrix<XprType>)
85  {
86  constexpr bool als = at_least_square<decltype(dim), decltype(get_index_dimension_of<direction == 1 ? 0 : 1>(xpr))>;
87  auto c = values::operation {std::forward<Func>(func), constant_diagonal_coefficient {xpr}};
88  return Eigen3::ReduxTraits<MemberOp, direction>::template get_constant_diagonal<als>(c, factor, dim);
89  }
90  else
91  {
92  return std::monostate {};
93  }
94  }
95  }
96 
97 } // namespace OpenKalman::Eigen3::detail
98 
99 
100 namespace OpenKalman::interface
101 {
102 
103  // ------------------------- //
104  // indexible_object_traits //
105  // ------------------------- //
106 
107  template<typename MatrixType, typename MemberOp, int Direction>
108  struct indexible_object_traits<Eigen::PartialReduxExpr<MatrixType, MemberOp, Direction>>
109  : Eigen3::indexible_object_traits_base<Eigen::PartialReduxExpr<MatrixType, MemberOp, Direction>>
110  {
111  private:
112 
114 
115 #if __cplusplus < 202002L
116  struct Op
117  {
118  template<typename Scalar>
119  constexpr Scalar&& operator()(Scalar&& arg) const { return std::forward<Scalar>(arg); }
120  };
121 #endif
122 
123  public:
124 
125  template<typename Arg>
126  static decltype(auto) nested_object(Arg&& arg)
127  {
128  return std::forward<Arg>(arg).nestedExpression();
129  }
130 
131 
132  // If a partial redux expression needs to be partially evaluated, it's probably faster to do a full evaluation.
133  // Thus, we omit the conversion function.
134 
135  template<typename Arg>
136  static constexpr auto get_constant(const Arg& arg)
137  {
138  // colwise (acting on columns) is Eigen::Vertical and rowwise (acting on rows) is Eigen::Horizontal
139  constexpr std::size_t direction = Direction == Eigen::Horizontal ? 1 : 0;
140  const auto& x = arg.nestedExpression();
141  auto dim = get_index_dimension_of<direction>(x);
142  std::integral_constant<std::size_t, 1> f;
143 #if __cplusplus >= 202002L
144  return OpenKalman::Eigen3::detail::get_constant_redux<MemberOp, direction>(x, f, dim, std::identity{});
145 #else
146  return OpenKalman::Eigen3::detail::get_constant_redux<MemberOp, direction>(x, f, dim, Op{});
147 #endif
148  }
149 
150  };
151 
152 } // namespace OpenKalman::interface
153 
154 #endif //OPENKALMAN_EIGEN_PARTIALREDUXEXPR_HPP
Definition: indexible_object_traits.hpp:36
Definition: basics.hpp:41
An operation involving some number of values.
Definition: operation.hpp:69
Trait object providing get and set routines.
Definition: eigen-forward-declarations.hpp:502
Definition: eigen-comma-initializers.hpp:20
Definition: tuple_reverse.hpp:103
constexpr bool value
T is numerical value or is reducible to a numerical value.
Definition: value.hpp:31
Definition: eigen-forward-declarations.hpp:97
The constant associated with T, assuming T is a constant_matrix.
Definition: constant_coefficient.hpp:36
The constant associated with T, assuming T is a constant_diagonal_matrix.
Definition: constant_diagonal_coefficient.hpp:32
Definition: redux.hpp:26
Definition: PartialReduxExpr.hpp:28
The replication factor for Eigen::Replicate in a given direction.
Definition: eigen-forward-declarations.hpp:310
constexpr bool fixed
T is a values::value that is determinable at compile time.
Definition: fixed.hpp:60
Compose two Eigen functors F1 and F2.
Definition: functor_composition.hpp:29
constexpr std::size_t dynamic_size
A constant indicating that a size or index is dynamic.
Definition: global-definitions.hpp:33
decltype(auto) constexpr nested_object(Arg &&arg)
Retrieve a nested object of Arg, if it exists.
Definition: nested_object.hpp:34