OpenKalman
binary.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_FUNCTORS_BINARY_HPP
17 #define OPENKALMAN_EIGEN_TRAITS_FUNCTORS_BINARY_HPP
18 
19 #include <type_traits>
20 
21 namespace OpenKalman::Eigen3
22 {
23 
24  // Default binary functor traits
25  template<typename Operation>
26  struct BinaryFunctorTraits
27  {
29  template<typename...Args>
30  static constexpr auto constexpr_operation() = delete;
31 
33  static constexpr BinaryFunctorType binary_functor_type = BinaryFunctorType::normal;
34 
36  static constexpr bool preserves_hermitian = false;
37  };
38 
39 
40  // --------------- //
41  // stl operators //
42  // --------------- //
43 
44  template<typename Scalar>
45  struct BinaryFunctorTraits<std::plus<Scalar>>
46  {
47  static constexpr auto constexpr_operation() { return std::plus<Scalar>{}; };
48  static constexpr bool preserves_constant_diagonal = true;
49  static constexpr BinaryFunctorType binary_functor_type = BinaryFunctorType::sum;
50  static constexpr bool preserves_hermitian = true;
51  };
52 
53 
54  template<typename Scalar>
55  struct BinaryFunctorTraits<std::minus<Scalar>>
56  {
57  static constexpr auto constexpr_operation() { return std::minus<Scalar>{}; };
58  static constexpr bool preserves_constant_diagonal = true;
59  static constexpr BinaryFunctorType binary_functor_type = BinaryFunctorType::sum;
60  static constexpr bool preserves_hermitian = true;
61  };
62 
63 
64  template<typename Scalar>
65  struct BinaryFunctorTraits<std::multiplies<Scalar>>
66  {
67  static constexpr auto constexpr_operation() { return std::multiplies<Scalar>{}; };
68  static constexpr bool preserves_constant_diagonal = true;
69  static constexpr BinaryFunctorType binary_functor_type = BinaryFunctorType::product;
70  static constexpr bool preserves_hermitian = true;
71  };
72 
73 
74  template<typename Scalar>
75  struct BinaryFunctorTraits<std::divides<Scalar>>
76  {
77  static constexpr auto constexpr_operation() { return std::divides<Scalar>{}; };
78  static constexpr bool preserves_constant_diagonal = false;
79  static constexpr BinaryFunctorType binary_functor_type = BinaryFunctorType::normal;
80  static constexpr bool preserves_hermitian = true;
81  };
82 
83 
84  template<typename Scalar>
85  struct BinaryFunctorTraits<std::logical_and<Scalar>>
86  {
87  static constexpr auto constexpr_operation() { return std::logical_and<Scalar>{}; };
88  static constexpr bool preserves_constant_diagonal = true;
89  static constexpr BinaryFunctorType binary_functor_type = BinaryFunctorType::product;
90  static constexpr bool preserves_hermitian = true;
91  };
92 
93 
94  template<typename Scalar>
95  struct BinaryFunctorTraits<std::logical_or<Scalar>>
96  {
97  static constexpr auto constexpr_operation() { return std::logical_or<Scalar>{}; };
98  static constexpr bool preserves_constant_diagonal = true;
99  static constexpr BinaryFunctorType binary_functor_type = BinaryFunctorType::sum;
100  static constexpr bool preserves_hermitian = true;
101 
102  template<typename LhsType, typename RhsType, typename Arg>
103  static constexpr auto get_constant(const Arg& arg)
104  {
106  {
107  if constexpr (constant_coefficient_v<RhsType> == true) return constant_coefficient {arg.rhs()};
108  else return constant_coefficient {arg.lhs()};
109  }
110  else if constexpr (values::fixed<constant_coefficient<LhsType>>)
111  {
112  if constexpr (constant_coefficient_v<LhsType> == true) return constant_coefficient {arg.lhs()};
113  else return constant_coefficient {arg.rhs()};
114  }
115  else
116  {
117  return std::monostate{};
118  }
119  }
120 
121  template<typename LhsType, typename RhsType, typename Arg>
122  static constexpr auto get_constant_diagonal(const Arg& arg)
123  {
125  {
126  if constexpr (constant_diagonal_coefficient_v<RhsType> == true and diagonal_matrix<LhsType>)
127  return constant_diagonal_coefficient {arg.rhs()};
128  else if constexpr (constant_diagonal_coefficient_v<RhsType> == false)
129  return constant_diagonal_coefficient {arg.lhs()};
130  else
131  return std::monostate{};
132  }
134  {
135  if constexpr (constant_diagonal_coefficient_v<LhsType> == true and diagonal_matrix<RhsType>)
136  return constant_diagonal_coefficient {arg.lhs()};
137  else if constexpr (constant_diagonal_coefficient_v<LhsType> == false)
138  return constant_diagonal_coefficient {arg.rhs()};
139  else
140  return std::monostate{};
141  }
142  else
143  {
144  return std::monostate{};
145  }
146  }
147  };
148 
149 
150  template<typename Scalar>
152  {
153  static constexpr auto constexpr_operation() { return std::equal_to<Scalar>{}; };
154  static constexpr bool preserves_constant_diagonal = false;
155  static constexpr BinaryFunctorType binary_functor_type = BinaryFunctorType::normal;
156  static constexpr bool preserves_hermitian = true;
157  };
158 
159 
160  template<typename Scalar>
162  {
163  static constexpr auto constexpr_operation() { return std::not_equal_to<Scalar>{}; };
164  static constexpr bool preserves_constant_diagonal = true;
165  static constexpr BinaryFunctorType binary_functor_type = BinaryFunctorType::sum;
166  static constexpr bool preserves_hermitian = true;
167  };
168 
169 
170  template<typename Scalar>
171  struct BinaryFunctorTraits<std::greater<Scalar>>
172  {
173  static constexpr auto constexpr_operation() { return std::greater<Scalar>{}; };
174  static constexpr bool preserves_constant_diagonal = true;
175  static constexpr BinaryFunctorType binary_functor_type = BinaryFunctorType::sum;
176  static constexpr bool preserves_hermitian = true;
177  };
178 
179 
180  template<typename Scalar>
181  struct BinaryFunctorTraits<std::less<Scalar>>
182  {
183  static constexpr auto constexpr_operation() { return std::less<Scalar>{}; };
184  static constexpr bool preserves_constant_diagonal = true;
185  static constexpr BinaryFunctorType binary_functor_type = BinaryFunctorType::sum;
186  static constexpr bool preserves_hermitian = true;
187  };
188 
189 
190  template<typename Scalar>
192  {
193  static constexpr auto constexpr_operation() { return std::greater_equal<Scalar>{}; };
194  static constexpr bool preserves_constant_diagonal = false;
195  static constexpr BinaryFunctorType binary_functor_type = BinaryFunctorType::normal;
196  static constexpr bool preserves_hermitian = true;
197  };
198 
199 
200  template<typename Scalar>
202  {
203  static constexpr auto constexpr_operation() { return std::less_equal<Scalar>{}; };
204  static constexpr bool preserves_constant_diagonal = false;
205  static constexpr BinaryFunctorType binary_functor_type = BinaryFunctorType::normal;
206  static constexpr bool preserves_hermitian = true;
207  };
208 
209 
210  // ----------------- //
211  // Eigen operators //
212  // ----------------- //
213 
214  template<typename Scalar1, typename Scalar2>
215  struct BinaryFunctorTraits<Eigen::internal::scalar_sum_op<Scalar1, Scalar2>>
216  : BinaryFunctorTraits<std::plus<std::common_type_t<Scalar1, Scalar2>>> {};
217 
218 
219  template<typename Scalar1, typename Scalar2>
220  struct BinaryFunctorTraits<Eigen::internal::scalar_product_op<Scalar1, Scalar2>>
221  : BinaryFunctorTraits<std::multiplies<std::common_type_t<Scalar1, Scalar2>>> {};
222 
223 
224  template<typename Scalar1, typename Scalar2>
225  struct BinaryFunctorTraits<Eigen::internal::scalar_conj_product_op<Scalar1, Scalar2>>
226  {
227  struct Op { constexpr auto operator()(Scalar1 arg1, Scalar2 arg2) const { return values::conj(arg1) * arg2; } };
228  static constexpr auto constexpr_operation() { return Op{}; }
229  static constexpr bool preserves_constant_diagonal = true;
230  static constexpr BinaryFunctorType binary_functor_type = BinaryFunctorType::product;
231  static constexpr bool preserves_hermitian = true;
232  };
233 
234 
235  template<typename Scalar1, typename Scalar2>
236  struct BinaryFunctorTraits<Eigen::internal::scalar_min_op<Scalar1, Scalar2>>
237  {
238  struct Op { constexpr auto operator()(Scalar1 arg1, Scalar2 arg2) const { return std::min(arg1, arg2); } };
239  static constexpr auto constexpr_operation() { return Op{}; }
240  static constexpr bool preserves_constant_diagonal = true;
241  static constexpr BinaryFunctorType binary_functor_type = BinaryFunctorType::sum;
242  static constexpr bool preserves_hermitian = true;
243 
244  template<typename LhsType, typename RhsType, typename Arg>
245  static constexpr auto get_constant(const Arg& arg)
246  {
248  {
249  if constexpr (constant_coefficient_v<LhsType> < 0 and constant_coefficient_v<LhsType> < constant_diagonal_coefficient_v<RhsType>)
250  return constant_coefficient {arg.lhs()};
251  else return std::monostate{};
252  }
254  {
255  if constexpr (constant_coefficient_v<RhsType> < 0 and constant_coefficient_v<RhsType> < constant_diagonal_coefficient_v<LhsType>)
256  return constant_coefficient {arg.rhs()};
257  else return std::monostate{};
258  }
259  else
260  {
262  }
263  }
264 
265  template<typename LhsType, typename RhsType, typename Arg>
266  static constexpr auto get_constant_diagonal(const Arg& arg)
267  {
269  {
270  if constexpr (constant_coefficient_v<LhsType> > 0 and constant_coefficient_v<LhsType> > constant_diagonal_coefficient_v<RhsType>)
271  return constant_diagonal_coefficient {arg.rhs()};
272  else return std::monostate{};
273  }
275  {
276  if constexpr (constant_coefficient_v<RhsType> > 0 and constant_coefficient_v<RhsType> > constant_diagonal_coefficient_v<LhsType>)
277  return constant_diagonal_coefficient {arg.lhs()};
278  else return std::monostate{};
279  }
280  else
281  {
284  }
285  }
286  };
287 
288 
289  template<typename Scalar1, typename Scalar2>
290  struct BinaryFunctorTraits<Eigen::internal::scalar_max_op<Scalar1, Scalar2>>
291  {
292  struct Op { constexpr auto operator()(Scalar1 arg1, Scalar2 arg2) const { return std::max(arg1, arg2); } };
293  static constexpr auto constexpr_operation() { return Op{}; }
294  static constexpr bool preserves_constant_diagonal = true;
295  static constexpr BinaryFunctorType binary_functor_type = BinaryFunctorType::sum;
296  static constexpr bool preserves_hermitian = true;
297 
298  template<typename LhsType, typename RhsType, typename Arg>
299  static constexpr auto get_constant(const Arg& arg)
300  {
302  {
303  if constexpr (constant_coefficient_v<LhsType> > 0 and constant_coefficient_v<LhsType> > constant_diagonal_coefficient_v<RhsType>)
304  return constant_coefficient {arg.lhs()};
305  else return std::monostate{};
306  }
308  {
309  if constexpr (constant_coefficient_v<RhsType> > 0 and constant_coefficient_v<RhsType> > constant_diagonal_coefficient_v<LhsType>)
310  return constant_coefficient {arg.rhs()};
311  else return std::monostate{};
312  }
313  else
314  {
316  constant_coefficient {arg.lhs()}, constant_coefficient {arg.rhs()}};
317  }
318  }
319 
320  template<typename LhsType, typename RhsType, typename Arg>
321  static constexpr auto get_constant_diagonal(const Arg& arg)
322  {
324  {
325  if constexpr (constant_coefficient_v<LhsType> < 0 and constant_coefficient_v<LhsType> < constant_diagonal_coefficient_v<RhsType>)
326  return constant_diagonal_coefficient {arg.rhs()};
327  else return std::monostate{};
328  }
330  {
331  if constexpr (constant_coefficient_v<RhsType> < 0 and constant_coefficient_v<RhsType> < constant_diagonal_coefficient_v<LhsType>)
332  return constant_diagonal_coefficient {arg.lhs()};
333  else return std::monostate{};
334  }
335  else
336  {
339  }
340  }
341  };
342 
343 
344  template<typename LhsScalar, typename RhsScalar, Eigen::internal::ComparisonName cmp>
345  struct BinaryFunctorTraits<Eigen::internal::scalar_cmp_op<LhsScalar, RhsScalar, cmp>>
346  {
347  struct Op {
348  constexpr auto operator()(LhsScalar a, RhsScalar b) const {
349  if constexpr (cmp == Eigen::internal::ComparisonName::cmp_EQ) return a == b;
350  else if constexpr (cmp == Eigen::internal::ComparisonName::cmp_LT) return a < b;
351  else if constexpr (cmp == Eigen::internal::ComparisonName::cmp_LE) return a <= b;
352  else if constexpr (cmp == Eigen::internal::ComparisonName::cmp_GT) return a > b;
353  else if constexpr (cmp == Eigen::internal::ComparisonName::cmp_GE) return a >= b;
354  else if constexpr (cmp == Eigen::internal::ComparisonName::cmp_NEQ) return a != b;
355  else if constexpr (cmp == Eigen::internal::ComparisonName::cmp_UNORD) return not (a<=b or b<=a);
356  else return Eigen::internal::scalar_cmp_op<LhsScalar, RhsScalar, cmp> {}(a, b); // Failsafe, but not a constexpr function.
357  }
358  };
359  static constexpr auto constexpr_operation() { return Op{}; }
360  static constexpr bool preserves_constant_diagonal = false;
361  static constexpr BinaryFunctorType binary_functor_type = BinaryFunctorType::normal;
362  static constexpr bool preserves_hermitian = true;
363  };
364 
365 
366  template<typename Scalar1, typename Scalar2>
367  struct BinaryFunctorTraits<Eigen::internal::scalar_hypot_op<Scalar1, Scalar2>>
368  {
369  struct Op { constexpr auto operator()(Scalar1 arg1, Scalar2 arg2) const { return values::sqrt(arg1 * arg1 + arg2 * arg2); } };
370  static constexpr auto constexpr_operation() { return Op{}; }
371  static constexpr bool preserves_constant_diagonal = true;
372  static constexpr BinaryFunctorType binary_functor_type = BinaryFunctorType::sum;
373  static constexpr bool preserves_hermitian = true;
374  };
375 
376 
377  template<typename Scalar, typename Exponent>
378  struct BinaryFunctorTraits<Eigen::internal::scalar_pow_op<Scalar, Exponent>>
379  {
380  struct Op { constexpr auto operator()(Scalar arg1, Exponent arg2) const { return values::pow(arg1, arg2); } };
381  static constexpr auto constexpr_operation() { return Op{}; }
382  static constexpr bool preserves_constant_diagonal = false;
383  static constexpr BinaryFunctorType binary_functor_type = BinaryFunctorType::normal;
384  static constexpr bool preserves_hermitian = true;
385  };
386 
387 
388  template<typename Scalar1, typename Scalar2>
389  struct BinaryFunctorTraits<Eigen::internal::scalar_difference_op<Scalar1, Scalar2>>
390  : BinaryFunctorTraits<std::minus<std::common_type_t<Scalar1, Scalar2>>> {};
391 
392 
393  template<typename Scalar1, typename Scalar2>
394  struct BinaryFunctorTraits<Eigen::internal::scalar_quotient_op<Scalar1, Scalar2>>
395  : BinaryFunctorTraits<std::divides<std::common_type_t<Scalar1, Scalar2>>> {};
396 
397 
398  template<>
399  struct BinaryFunctorTraits<Eigen::internal::scalar_boolean_and_op> : BinaryFunctorTraits<std::logical_and<bool>> {};
400 
401 
402  template<>
403  struct BinaryFunctorTraits<Eigen::internal::scalar_boolean_or_op> : BinaryFunctorTraits<std::logical_or<bool>> {};
404 
405 
406  template<>
407  struct BinaryFunctorTraits<Eigen::internal::scalar_boolean_xor_op> : BinaryFunctorTraits<std::not_equal_to<bool>> {};
408 
409 
410  template<typename Scalar>
411  struct BinaryFunctorTraits<Eigen::numext::not_equal_to<Scalar>> : BinaryFunctorTraits<std::not_equal_to<bool>> {};
412 
413 
414  template<typename Scalar>
415  struct BinaryFunctorTraits<Eigen::numext::equal_to<Scalar>> : BinaryFunctorTraits<std::equal_to<bool>> {};
416 
417 
418 #if EIGEN_VERSION_AT_LEAST(3,4,0)
419  template<typename Scalar1, typename Scalar2>
420  struct BinaryFunctorTraits<Eigen::internal::scalar_absolute_difference_op<Scalar1, Scalar2>>
421  {
422  struct Op { constexpr auto operator()(Scalar1 arg1, Scalar2 arg2) const { return arg2 > arg1 ? arg2 - arg1 : arg1 - arg2; } };
423  static constexpr auto constexpr_operation() { return Op{}; }
424  static constexpr bool preserves_constant_diagonal = true;
425  static constexpr BinaryFunctorType binary_functor_type = BinaryFunctorType::sum;
426  static constexpr bool preserves_hermitian = true;
427  };
428 #endif
429 
430 } // namespace OpenKalman::Eigen3
431 
432 #endif //OPENKALMAN_EIGEN_TRAITS_FUNCTORS_BINARY_HPP
A generalization of std::greater in which the arguments may be of different types.
Definition: greater.hpp:29
static constexpr auto constexpr_operation()=delete
Construct Operation or (preferably) an equivalent constexpr operation equivalent to Operation...
An operation involving some number of values.
Definition: operation.hpp:69
A generalization of std::less in which the arguments may be of different types.
Definition: less.hpp:29
Definition: eigen-comma-initializers.hpp:20
Definition: tuple_reverse.hpp:103
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
constexpr auto conj(const Arg &arg)
A constexpr function for the complex conjugate of a (complex) number.
Definition: conj.hpp:39
constexpr auto sqrt(const Arg &arg)
A constexpr alternative to std::sqrt.
Definition: sqrt.hpp:46
Definition: eigen-forward-declarations.hpp:22
Definition: eigen-forward-declarations.hpp:61
A generalization of std::less_equal in which the arguments may be of different types.
Definition: less_equal.hpp:29
constexpr bool fixed
T is a values::value that is determinable at compile time.
Definition: fixed.hpp:60
A generalization of std::equal_to in which the arguments may be of different types.
Definition: equal_to.hpp:29
static constexpr bool preserves_hermitian
Whether the operation applied to a hermitian matrix always yields a hermitian matrix.
Definition: binary.hpp:36
static constexpr BinaryFunctorType binary_functor_type
Whether binary functor type.
Definition: binary.hpp:33
A generalization of std::not_equal_to in which the arguments may be of different types.
Definition: not_equal_to.hpp:29
A generalization of std::less_equal in which the arguments may be of different types.
Definition: greater_equal.hpp:29