OpenKalman
TensorCwiseBinaryOp.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-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_EIGEN_TRAITS_TENSORCWISEBINARYOP_HPP
17 #define OPENKALMAN_EIGEN_TRAITS_TENSORCWISEBINARYOP_HPP
18 
19 
20 namespace OpenKalman::interface
21 {
22  template<typename BinaryOp, typename LhsXprType, typename RhsXprType>
23  struct indexible_object_traits<Eigen::TensorCwiseBinaryOp<BinaryOp, LhsXprType, RhsXprType>>
24  : Eigen3::indexible_object_traits_tensor_base<Eigen::TensorCwiseBinaryOp<BinaryOp, LhsXprType, RhsXprType>>
25  {
26  private:
27 
28  using Xpr = Eigen::TensorCwiseBinaryOp<BinaryOp, LhsXprType, RhsXprType>;
31 
32  public:
33 
34  template<typename Arg, typename N>
35  static constexpr auto
36  get_vector_space_descriptor(const Arg& arg, N n)
37  {
38  if constexpr (values::fixed<N>)
39  {
40  if constexpr (not dynamic_dimension<LhsXprType, n>)
41  return OpenKalman::get_vector_space_descriptor(arg.lhsExpression(), n);
42  else
43  return OpenKalman::get_vector_space_descriptor(arg.rhsExpression(), n);
44  }
45  else return OpenKalman::get_vector_space_descriptor(arg.lhsExpression(), n);
46  }
47 
48 
49  // nested_object() not defined
50 
51  private:
52 
53 #ifndef __cpp_concepts
54  template<typename T = Traits, typename = void>
55  struct custom_get_constant_defined : std::false_type {};
56 
57  template<typename T>
58  struct custom_get_constant_defined<T, std::void_t<decltype(T::template get_constant<LhsXprType, RhsXprType>(std::declval<const Xpr&>()))>>
59  : std::true_type {};
60 
61  template<typename T = Traits, typename = void>
62  struct constexpr_operation_defined : std::false_type {};
63 
64  template<typename T>
65  struct constexpr_operation_defined<T, std::void_t<decltype(T::constexpr_operation())>>
66  : std::true_type {};
67 #endif
68 
69  public:
70 
71  template<typename Arg>
72  static constexpr auto get_constant(const Arg& arg)
73  {
74 #ifdef __cpp_concepts
75  if constexpr (requires { Traits::template get_constant<LhsXprType, RhsXprType>(arg); })
76 #else
78 #endif
79  return Traits::template get_constant<LhsXprType, RhsXprType>(arg);
80  else if constexpr (Traits::binary_functor_type == Eigen3::BinaryFunctorType::sum and zero<LhsXprType>)
81  return constant_coefficient {arg.rhsExpression()};
82  else if constexpr (Traits::binary_functor_type == Eigen3::BinaryFunctorType::sum and zero<RhsXprType>)
83  return constant_coefficient {arg.lhsExpression()};
84  else if constexpr (Traits::binary_functor_type == Eigen3::BinaryFunctorType::product and zero<LhsXprType>)
85  return constant_coefficient {arg.lhsExpression()};
86  else if constexpr (Traits::binary_functor_type == Eigen3::BinaryFunctorType::product and zero<RhsXprType>)
87  return constant_coefficient {arg.rhsExpression()};
88 #ifdef __cpp_concepts
89  else if constexpr (requires { Traits::constexpr_operation(); })
90 #else
91  else if constexpr (constexpr_operation_defined<>::value)
92 #endif
93  return values::operation {Traits::constexpr_operation(),
94  constant_coefficient {arg.lhsExpression()}, constant_coefficient {arg.rhsExpression()}};
95  else
96  return values::operation {arg.functor(),
97  constant_coefficient {arg.lhsExpression()}, constant_coefficient {arg.rhsExpression()}};
98  }
99 
100  private:
101 
102 #ifndef __cpp_concepts
103  template<typename T = Traits, typename = void>
104  struct custom_get_constant_diagonal_defined : std::false_type {};
105 
106  template<typename T>
107  struct custom_get_constant_diagonal_defined<T, std::void_t<decltype(T::template get_constant_diagonal<LhsXprType, RhsXprType>(std::declval<const Xpr&>()))>>
108  : std::true_type {};
109 #endif
110 
111  public:
112 
113  template<typename Arg>
114  static constexpr auto get_constant_diagonal(const Arg& arg)
115  {
116 #ifdef __cpp_concepts
117  if constexpr (requires { Traits::template get_constant_diagonal<LhsXprType, RhsXprType>(arg); })
118 #else
120 #endif
121  return Traits::template get_constant_diagonal<LhsXprType, RhsXprType>(arg);
122  else if constexpr (Traits::binary_functor_type == Eigen3::BinaryFunctorType::sum and zero<LhsXprType>)
123  return constant_diagonal_coefficient {arg.rhsExpression()};
124  else if constexpr (Traits::binary_functor_type == Eigen3::BinaryFunctorType::sum and zero<RhsXprType>)
125  return constant_diagonal_coefficient {arg.lhsExpression()};
126  else if constexpr (Traits::binary_functor_type == Eigen3::BinaryFunctorType::product and zero<LhsXprType>)
127  return constant_coefficient {arg.lhsExpression()};
128  else if constexpr (Traits::binary_functor_type == Eigen3::BinaryFunctorType::product and zero<RhsXprType>)
129  return constant_coefficient {arg.rhsExpression()};
130  else if constexpr (Traits::binary_functor_type == Eigen3::BinaryFunctorType::product)
131  {
132  auto c_left = [](const Arg& arg){
133  if constexpr (constant_matrix<LhsXprType>) return constant_coefficient {arg.lhsExpression()};
134  else return constant_diagonal_coefficient {arg.lhsExpression()};
135  }(arg);
136  auto c_right = [](const Arg& arg){
137  if constexpr (constant_matrix<RhsXprType>) return constant_coefficient {arg.rhsExpression()};
138  else return constant_diagonal_coefficient {arg.rhsExpression()};
139  }(arg);
140 #ifdef __cpp_concepts
141  if constexpr (requires { Traits::constexpr_operation(); })
142 #else
144 #endif
145  return values::operation {Traits::constexpr_operation(), c_left, c_right};
146  else
147  return values::operation {arg.functor(), c_left, c_right};
148  }
149  else if constexpr (Traits::binary_functor_type == Eigen3::BinaryFunctorType::sum or Traits::preserves_constant_diagonal)
150  {
151 #ifdef __cpp_concepts
152  if constexpr (requires { Traits::constexpr_operation(); })
153 #else
155 #endif
156  return values::operation {Traits::constexpr_operation(),
157  constant_diagonal_coefficient {arg.lhsExpression()}, constant_diagonal_coefficient {arg.rhsExpression()}};
158  else
159  return values::operation {arg.functor(),
160  constant_diagonal_coefficient {arg.lhsExpression()}, constant_diagonal_coefficient {arg.rhsExpression()}};
161  }
162  else
163  {
164  return std::monostate{};
165  }
166  }
167 
168 
169  template<Applicability b>
170  static constexpr bool one_dimensional =
171  OpenKalman::one_dimensional<LhsXprType, Applicability::permitted> and OpenKalman::one_dimensional<RhsXprType, Applicability::permitted> and
172  (b != Applicability::guaranteed or not has_dynamic_dimensions<Eigen::CwiseBinaryOp<BinaryOp, LhsXprType, RhsXprType>> or
173  (square_shaped<LhsXprType, b> and (dimension_size_of_index_is<RhsXprType, 0, 1> or dimension_size_of_index_is<RhsXprType, 1, 1>)) or
174  ((dimension_size_of_index_is<LhsXprType, 0, 1> or dimension_size_of_index_is<LhsXprType, 1, 1>) and square_shaped<RhsXprType, b>));
175 
176 
177  template<Applicability b>
178  static constexpr bool is_square =
179  square_shaped<LhsXprType, Applicability::permitted> and square_shaped<RhsXprType, Applicability::permitted> and
180  (b != Applicability::guaranteed or not has_dynamic_dimensions<Eigen::CwiseBinaryOp<BinaryOp, LhsXprType, RhsXprType>> or
181  square_shaped<LhsXprType, b> or square_shaped<RhsXprType, b>);
182 
183 
184  static constexpr bool is_triangular_adapter = false;
185 
186 
187  template<TriangleType t>
188  static constexpr bool is_triangular =
189  Traits::binary_functor_type == Eigen3::BinaryFunctorType::sum ?
190  triangular_matrix<LhsXprType, t> and triangular_matrix<RhsXprType, t> and
191  (t != TriangleType::any or triangle_type_of_v<LhsXprType, RhsXprType> != TriangleType::any) :
192  Traits::binary_functor_type == Eigen3::BinaryFunctorType::product and
193  (triangular_matrix<LhsXprType, t> or triangular_matrix<RhsXprType, t> or
194  (triangular_matrix<LhsXprType, TriangleType::lower> and triangular_matrix<RhsXprType, TriangleType::upper>) or
195  (triangular_matrix<LhsXprType, TriangleType::upper> and triangular_matrix<RhsXprType, TriangleType::lower>));
196 
197 
198  static constexpr bool is_hermitian = Traits::preserves_hermitian and
199  hermitian_matrix<LhsXprType, Applicability::permitted> and hermitian_matrix<RhsXprType, Applicability::permitted>;;
200 
201  };
202 
203 } // namespace OpenKalman::interface
204 
205 #endif //OPENKALMAN_EIGEN_TRAITS_TENSORCWISEBINARYOP_HPP
constexpr bool one_dimensional
Specifies that a type is one-dimensional in every index.
Definition: one_dimensional.hpp:83
Definition: indexible_object_traits.hpp:36
Definition: basics.hpp:41
An operation involving some number of values.
Definition: operation.hpp:69
Lower, upper, or diagonal matrix.
Definition: eigen-comma-initializers.hpp:20
Trait object providing get and set routines for Eigen tensors.
Definition: eigen-tensor-forward-declarations.hpp:114
constexpr bool value
T is numerical value or is reducible to a numerical value.
Definition: value.hpp:31
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: eigen-forward-declarations.hpp:61
constexpr bool has_dynamic_dimensions
Specifies that T has at least one index with dynamic dimensions.
Definition: has_dynamic_dimensions.hpp:29
The concept, trait, or restraint represents a compile-time guarantee.
constexpr auto get_vector_space_descriptor(const T &t, const N &n)
Get the coordinates::pattern object for index N of indexible object T.
Definition: get_vector_space_descriptor.hpp:56