I was wondering if there is a good way to test two Eigen matrices for approximate equality using Google Test, or Google Mock.
Take the following test-case as a simplified example: I am multiplying two complex valued matrices A
, and B
, and expect a certain result C_expect
. I calculate the numerical result C_actual = A * B
, using Eigen. Now, I want to compare C_expect
, and C_actual
. Right now, the corresponding code looks like this:
#include <complex>
#include <Eigen/Dense>
#include <gtest/gtest.h>
#include <gmock/gmock.h>
typedef std::complex<double> Complex;
typedef Eigen::Matrix2cd Matrix;
TEST(Eigen, MatrixMultiplication) {
Matrix A, B, C_expect, C_actual;
A << Complex(1, 1), Complex(2, 3),
Complex(3, 2), Complex(4, 4);
B << Complex(4, 4), Complex(3, 2),
Complex(2, 3), Complex(1, 1);
C_expect << Complex(-5, 20), Complex(0, 10),
Complex(0, 40), Complex(5, 20);
C_actual = A * B;
// !!! These are the lines that bother me.
for (int j = 0; j < C_actual.cols(); ++j) {
for (int i = 0; i < C_actual.rows(); ++i) {
EXPECT_NEAR(C_expect(i, j).real(), C_actual(i, j).real(), 1e-7)
<< "Re(" << i << "," << j << ")";
EXPECT_NEAR(C_expect(i, j).imag(), C_actual(i, j).imag(), 1e-7)
<< "Im(" << i << "," << j << ")";
}
}
}
What's wrong with this? Well, I have to manually iterate through all indices of the matrix, and then compare the real-part and imaginary-part individually. I would much prefer something along the lines of Google Mock's ElementsAreArray
matcher. E.g.
EXPECT_THAT(C_actual, ElementsAreArray(C_expect));
// or
EXPECT_THAT(C_actual, Pointwise(MyComplexNear(1e-7), C_expect));
Unfortunately, the built-in capabilities of Google Mock only seem to work on 1-dimensional C-style, or STL-type containers. Furthermore, I need an approximate comparison for the complex values of my matrix.
My question: Do you know if (and how) it is possible to teach Google Mock to iterate over multiple dimensions, and compare complex floating point numbers to approximate equality?
Please note, that I cannot just handle the data-pointers as C-style arrays, because the storage layout might differ between C_expect
, and C_actual
. Also, in reality, the matrices are larger than just 2x2 matrices. I.e. some sort of loop is definitely necessary.
Why not use the isApprox
or isMuchSmallerThan
member functions of Eigen Matrix types?
The documentation of these above functions are available here
So for most cases ASSERT_TRUE(C_actual.isApprox(C_expect));
is what you need. You can also provide a precision parameter as the second arguement to isApprox.