Lemming - 5 months ago 89

C++ Question

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`

`B`

`C_expect`

`C_actual = A * B`

`C_expect`

`C_actual`

`#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`

`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

Please note, that I cannot just handle the data-pointers as C-style arrays, because the storage layout might differ between

`C_expect`

`C_actual`

Answer

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.