Lemming Lemming - 4 months ago 77
C++ Question

Compare Eigen matrices in Google Test or Google Mock

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

, and
, and expect a certain result
. I calculate the numerical result
C_actual = A * B
, using Eigen. Now, I want to compare
, and
. 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
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
, and
. 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.