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