OpenKalman
eigen.gtest.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) 2020-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 
19 #ifndef EIGEN3_GTEST_HPP
20 #define EIGEN3_GTEST_HPP
21 
23 #include "basics/tests/tests.hpp"
24 #include <complex>
25 
26 namespace OpenKalman::test
27 {
28 
29 #ifdef __cpp_concepts
30  template<Eigen3::eigen_dense_general Arg1, Eigen3::eigen_dense_general Arg2, typename Err> requires
31  std::is_arithmetic_v<Err> or Eigen3::eigen_dense_general<Err>
32  struct TestComparison<Arg1, Arg2, Err>
33 #else
34  template<typename Arg1, typename Arg2, typename Err>
35  struct TestComparison<Arg1, Arg2, Err, std::enable_if_t<Eigen3::eigen_dense_general<Arg1> and Eigen3::eigen_dense_general<Arg2> and
36  (std::is_arithmetic_v<Err> or Eigen3::eigen_dense_general<Err>)>>
37 #endif
38  : ::testing::AssertionResult
39  {
40 
41  private:
42 
43  static ::testing::AssertionResult
44  compare(const Arg1& arg1, const Arg2& arg2, const Err& err)
45  {
46  if constexpr (std::is_arithmetic_v<Err>)
47  {
48  if (arg1.matrix().isApprox(arg2.matrix(), err) or (arg1.matrix().isMuchSmallerThan(1., err) and
49  arg2.matrix().isMuchSmallerThan(1., err)))
50  {
51  return ::testing::AssertionSuccess();
52  }
53  }
54  else
55  {
56  if (((arg1.array() - arg2.array()).abs() - err).maxCoeff() <= 0)
57  {
58  return ::testing::AssertionSuccess();
59  }
60  }
61 
62  return ::testing::AssertionFailure() << std::endl << arg1 << std::endl << "is not near" << std::endl <<
63  arg2 << std::endl;
64  }
65 
66  public:
67 
68  TestComparison(const Arg1& arg1, const Arg2& arg2, const Err& err)
69  : ::testing::AssertionResult {compare(arg1, arg2, err)} {};
70 
71  };
72 
73 
74 #ifdef __cpp_concepts
75  template<indexible Arg1, indexible Arg2, typename Err> requires
76  (Eigen3::eigen_general<Arg1> and not Eigen3::eigen_general<Arg2>) or
77  (not Eigen3::eigen_general<Arg1> and Eigen3::eigen_general<Arg2>)
78  struct TestComparison<Arg1, Arg2, Err>
79 #else
80  template<typename Arg1, typename Arg2, typename Err>
81  struct TestComparison<Arg1, Arg2, Err, std::enable_if_t<indexible<Arg1> and indexible<Arg2> and
82  ((Eigen3::eigen_general<Arg1> and not Eigen3::eigen_general<Arg2>) or
83  (not Eigen3::eigen_general<Arg1> and Eigen3::eigen_general<Arg2>))>>
84 #endif
85  : ::testing::AssertionResult
86  {
87  private:
88 
89  using A = std::conditional_t<Eigen3::eigen_general<Arg1>, Arg1, Arg2>;
90 
91  public:
92  TestComparison(const Arg1& arg1, const Arg2& arg2, const Err& err)
93  : ::testing::AssertionResult {is_near(to_native_matrix<A>(arg1), to_native_matrix<A>(arg2), err)} {};
94 
95  };
96 
97  using Mxx = Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>;
98  using Mx0 = Eigen::Matrix<double, Eigen::Dynamic, 0>;
99  using Mx1 = Eigen::Matrix<double, Eigen::Dynamic, 1>;
100  using Mx2 = Eigen::Matrix<double, Eigen::Dynamic, 2>;
101  using Mx3 = Eigen::Matrix<double, Eigen::Dynamic, 3>;
102  using Mx4 = Eigen::Matrix<double, Eigen::Dynamic, 4>;
103  using Mx5 = Eigen::Matrix<double, Eigen::Dynamic, 5>;
104 
105  using M0x = Eigen::Matrix<double, 0, Eigen::Dynamic>;
106  using M00 = Eigen::Matrix<double, 0, 0>;
107  using M01 = Eigen::Matrix<double, 0, 1>;
108  using M02 = Eigen::Matrix<double, 0, 2>;
109  using M03 = Eigen::Matrix<double, 0, 3>;
110  using M04 = Eigen::Matrix<double, 0, 4>;
111 
112  using M1x = Eigen::Matrix<double, 1, Eigen::Dynamic>;
113  using M10 = Eigen::Matrix<double, 1, 0>;
114  using M11 = Eigen::Matrix<double, 1, 1>;
115  using M12 = Eigen::Matrix<double, 1, 2>;
116  using M13 = Eigen::Matrix<double, 1, 3>;
117  using M14 = Eigen::Matrix<double, 1, 4>;
118 
119  using M2x = Eigen::Matrix<double, 2, Eigen::Dynamic>;
120  using M20 = Eigen::Matrix<double, 2, 0>;
121  using M21 = Eigen::Matrix<double, 2, 1>;
122  using M22 = Eigen::Matrix<double, 2, 2>;
123  using M23 = Eigen::Matrix<double, 2, 3>;
124  using M24 = Eigen::Matrix<double, 2, 4>;
125 
126  using M3x = Eigen::Matrix<double, 3, Eigen::Dynamic>;
127  using M30 = Eigen::Matrix<double, 3, 0>;
128  using M31 = Eigen::Matrix<double, 3, 1>;
129  using M32 = Eigen::Matrix<double, 3, 2>;
130  using M33 = Eigen::Matrix<double, 3, 3>;
131  using M34 = Eigen::Matrix<double, 3, 4>;
132  using M35 = Eigen::Matrix<double, 3, 5>;
133 
134  using M4x = Eigen::Matrix<double, 4, Eigen::Dynamic>;
135  using M40 = Eigen::Matrix<double, 4, 0>;
136  using M41 = Eigen::Matrix<double, 4, 1>;
137  using M42 = Eigen::Matrix<double, 4, 2>;
138  using M43 = Eigen::Matrix<double, 4, 3>;
139  using M44 = Eigen::Matrix<double, 4, 4>;
140  using M45 = Eigen::Matrix<double, 4, 5>;
141 
142  using M5x = Eigen::Matrix<double, 5, Eigen::Dynamic>;
143  using M50 = Eigen::Matrix<double, 5, 0>;
144  using M51 = Eigen::Matrix<double, 5, 1>;
145  using M52 = Eigen::Matrix<double, 5, 2>;
146  using M53 = Eigen::Matrix<double, 5, 3>;
147  using M54 = Eigen::Matrix<double, 5, 4>;
148  using M55 = Eigen::Matrix<double, 5, 5>;
149 
150  using cdouble = std::complex<double>;
151 
152  using CM11 = Eigen::Matrix<cdouble, 1, 1>;
153  using CM22 = Eigen::Matrix<cdouble, 2, 2>;
154  using CM23 = Eigen::Matrix<cdouble, 2, 3>;
155  using CM33 = Eigen::Matrix<cdouble, 3, 3>;
156  using CM32 = Eigen::Matrix<cdouble, 3, 2>;
157  using CM34 = Eigen::Matrix<cdouble, 3, 4>;
158  using CM43 = Eigen::Matrix<cdouble, 4, 3>;
159 
160  using CM2x = Eigen::Matrix<cdouble, 2, Eigen::Dynamic>;
161  using CMx2 = Eigen::Matrix<cdouble, Eigen::Dynamic, 2>;
162  using CMxx = Eigen::Matrix<cdouble, Eigen::Dynamic, Eigen::Dynamic>;
163 
164  using Axx = Eigen::Array<double, Eigen::Dynamic, Eigen::Dynamic>;
165  using Ax1 = Eigen::Array<double, Eigen::Dynamic, 1>;
166  using Ax1 = Eigen::Array<double, Eigen::Dynamic, 1>;
167  using Ax2 = Eigen::Array<double, Eigen::Dynamic, 2>;
168 
169  using A1x = Eigen::Array<double, 1, Eigen::Dynamic>;
170  using A11 = Eigen::Array<double, 1, 1>; static_assert(one_dimensional<A11>);
171  using A12 = Eigen::Array<double, 1, 2>;
172 
173  using A2x = Eigen::Array<double, 2, Eigen::Dynamic>;
174  using A21 = Eigen::Array<double, 2, 1>;
175  using A22 = Eigen::Array<double, 2, 2>;
176  using A23 = Eigen::Array<double, 2, 3>;
177  using A32 = Eigen::Array<double, 3, 2>;
178 
179  using CA22 = Eigen::Array<cdouble, 2, 2>;
180 
181  using Ixx = Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<double>, Axx>;
182  using Ix1 = Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<double>, Ax1>;
183  using Ix2 = Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<double>, Ax2>;
184 
185  using I1x = Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<double>, A1x>;
186  using I11 = Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<double>, A11>;
187  using I12 = Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<double>, A12>;
188 
189  using I2x = Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<double>, A2x>;
190  using I21 = Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<double>, A21>;
191  using I22 = Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<double>, A22>;
192  using I23 = Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<double>, A23>;
193  using I32 = Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<double>, A32>;
194 
195  using Z11 = decltype(std::declval<I11>() - std::declval<I11>());
196  using Z22 = decltype(std::declval<I22>() - std::declval<I22>());
197  using Z21 = decltype(std::declval<I21>() - std::declval<I21>());
198  using Z23 = decltype(std::declval<I23>() - std::declval<I23>());
199  using Z12 = decltype(std::declval<I12>() - std::declval<I12>());
200  using Z2x = decltype(std::declval<I2x>() - std::declval<I2x>());
201  using Zx2 = decltype(std::declval<Ix2>() - std::declval<Ix2>());
202  using Zxx = decltype(std::declval<Ixx>() - std::declval<Ixx>());
203  using Z1x = decltype(std::declval<I1x>() - std::declval<I1x>());
204  using Zx1 = decltype(std::declval<Ix1>() - std::declval<Ix1>());
205 
206  using C11_1 = I11;
207  using C22_1 = Eigen::Replicate<C11_1, 2, 2>;
208  using C21_1 = Eigen::Replicate<C11_1, 2, 1>;
209  using C12_1 = Eigen::Replicate<C11_1, 1, 2>;
210  using C2x_1 = Eigen::Replicate<C11_1, 2, Eigen::Dynamic>;
211  using C1x_1 = Eigen::Replicate<C11_1, 1, Eigen::Dynamic>;
212  using Cx1_1 = Eigen::Replicate<C11_1, Eigen::Dynamic, 1>;
213  using Cx2_1 = Eigen::Replicate<C11_1, Eigen::Dynamic, 2>;
214  using Cxx_1 = Eigen::Replicate<C11_1, Eigen::Dynamic, Eigen::Dynamic>;
215 
216  using C11_2 = decltype(std::declval<I11>() + std::declval<I11>());
217  using C22_2 = Eigen::Replicate<C11_2, 2, 2>;
218  using C21_2 = Eigen::Replicate<C11_2, 2, 1>;
219  using C12_2 = Eigen::Replicate<C11_2, 1, 2>;
220  using C2x_2 = Eigen::Replicate<C11_2, 2, Eigen::Dynamic>;
221  using Cx2_2 = Eigen::Replicate<C11_2, Eigen::Dynamic, 2>;
222  using C1x_2 = Eigen::Replicate<C11_2, 1, Eigen::Dynamic>;
223  using Cx1_2 = Eigen::Replicate<C11_2, Eigen::Dynamic, 1>;
224  using Cxx_2 = Eigen::Replicate<C11_2, Eigen::Dynamic, Eigen::Dynamic>;
225 
226  using C11_3 = decltype(std::declval<I11>() + std::declval<I11>() + std::declval<I11>());
227  using C21_3 = Eigen::Replicate<C11_3, 2, 1>;
228  using C2x_3 = Eigen::Replicate<C11_3, 2, Eigen::Dynamic>;
229  using Cx1_3 = Eigen::Replicate<C11_3, Eigen::Dynamic, 1>;
230  using Cxx_3 = Eigen::Replicate<C11_3, Eigen::Dynamic, Eigen::Dynamic>;
231 
232  using C11_m1 = decltype(-std::declval<I11>());
233  using C21_m1 = Eigen::Replicate<C11_m1, 2, 1>;
234  using C2x_m1 = Eigen::Replicate<C11_m1, 2, Eigen::Dynamic>;
235  using Cx1_m1 = Eigen::Replicate<C11_m1, Eigen::Dynamic, 1>;
236  using Cxx_m1 = Eigen::Replicate<C11_m1, Eigen::Dynamic, Eigen::Dynamic>;
237 
238  using C11_m2 = decltype(-(std::declval<I11>() + std::declval<I11>()));
239  using C22_m2 = Eigen::Replicate<C11_m2, 2, 2>;
240  using C21_m2 = Eigen::Replicate<C11_m2, 2, 1>;
241  using C2x_m2 = Eigen::Replicate<C11_m2, 2, Eigen::Dynamic>;
242  using Cx1_m2 = Eigen::Replicate<C11_m2, Eigen::Dynamic, 1>;
243  using Cxx_m2 = Eigen::Replicate<C11_m2, Eigen::Dynamic, Eigen::Dynamic>;
244 
245  using C11_1cx = Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<cdouble>, Eigen::Array<cdouble, 1, 1>>;
246  using C11_2cx = decltype(std::declval<C11_1cx>() + std::declval<C11_1cx>());
247 
248  using B11 = Eigen::Array<bool, 1, 1>;
249  using B1x = Eigen::Array<bool, 1, Eigen::Dynamic>;
250  using Bx1 = Eigen::Array<bool, Eigen::Dynamic, 1>;
251  using B22 = Eigen::Array<bool, 2, 2>;
252  using B2x = Eigen::Array<bool, 2, Eigen::Dynamic>;
253  using Bx2 = Eigen::Array<bool, Eigen::Dynamic, 2>;
254  using Bxx = Eigen::Array<bool, Eigen::Dynamic, Eigen::Dynamic>;
255 
256  using B11_true = Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<bool>, B11>;
257  using B1x_true = Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<bool>, B1x>;
258  using Bx1_true = Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<bool>, Bx1>;
259  using B11_false = decltype(not std::declval<B11_true>());
260  using B1x_false = decltype(not std::declval<B1x_true>());
261  using Bx1_false = decltype(not std::declval<Bx1_true>());
262  using B22_true = decltype(std::declval<B11_true>().replicate<2,2>());
263  using B2x_true = decltype(std::declval<B1x_true>().replicate<2,2>());
264  using Bx2_true = decltype(std::declval<Bx1_true>().replicate<2,2>());
265  using B22_false = decltype(std::declval<B11_false>().replicate<2,2>());
266  using B2x_false = decltype(std::declval<B1x_false>().replicate<2,2>());
267  using Bx2_false = decltype(std::declval<Bx1_false>().replicate<2,2>());
268  using Bxx_true = Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<bool>, Bxx>;
269  using BI22 = Eigen::CwiseNullaryOp<Eigen::internal::scalar_identity_op<bool>, B22>;
270 
271  using Cd22_2 = decltype(std::declval<I22>() + std::declval<I22>());
272  using Cd2x_2 = decltype(std::declval<I2x>() + std::declval<I2x>());
273  using Cdx2_2 = decltype(std::declval<Ix2>() + std::declval<Ix2>());
274  using Cdxx_2 = decltype(std::declval<Ixx>() + std::declval<Ixx>());
275 
276  using Cd22_3 = decltype(std::declval<I22>() + std::declval<I22>() + std::declval<I22>());
277  using Cd2x_3 = decltype(std::declval<I2x>() + std::declval<I2x>() + std::declval<I2x>());
278  using Cdx2_3 = decltype(std::declval<Ix2>() + std::declval<Ix2>() + std::declval<Ix2>());
279  using Cdxx_3 = decltype(std::declval<Ixx>() + std::declval<Ixx>() + std::declval<Ixx>());
280 
281  using Cd22_m1 = decltype(-std::declval<I22>());
282  using Cd2x_m1 = decltype(-std::declval<I2x>());
283  using Cdx2_m1 = decltype(-std::declval<Ix2>());
284  using Cdxx_m1 = decltype(-std::declval<Ixx>());
285 
286  using Cd22_m2 = decltype(-std::declval<Cd22_2>());
287  using Cd2x_m2 = decltype(-std::declval<Cd2x_2>());
288  using Cdx2_m2 = decltype(-std::declval<Cdx2_2>());
289  using Cdxx_m2 = decltype(-std::declval<Cdxx_2>());
290 
293 
298 
303 
308 
313 
318 
323 
324 } // namespace OpenKalman::test
325 
326 #endif //EIGEN3_GTEST_HPP
constexpr partial_ordering compare(const Lhs &lhs, const Rhs &rhs)
Compare two collections.
Definition: compare.hpp:106
Definition: tuple_reverse.hpp:103
Definition: tests.hpp:41
Definition: tests.hpp:27
The comprehensive header file for OpenKalman&#39;s interface to the Eigen3 library.
Definition: forward-class-declarations.hpp:580
inline ::testing::AssertionResult is_near(const Arg1 &arg1, const Arg2 &arg2, const Err &err=1e-6)
Determine if two objects are "near" each other, within a margin of error.
Definition: tests.hpp:60