Search code examples
c++eigeneigen3

Apply function to all elements in Eigen Matrix without loop


I have an Eigen::Matrix and I would like to generate a new matrix where all its elements are generated by the some function call to the elements of the matrix:

Matrix< Foo,2,2 > m = ...;
Matrix< int, 2, 2> new_m;

for each m[i][j]:
  new_m[i][j] = m[i][j].member_of_foo_returns_int()

I had a look on Eigen::unaryExpr but the elements changed and the return have to be the same. However, I have Foo objects in the first matrix, and an int returned in the new matrix. Is this possible without a vanilla loop?


Solution

  • You can pass a lambda expression to unaryExpr, like so:

    Eigen::Matrix<int,2,2> new_m = m.unaryExpr(
        [](const Foo& x) {
            return x.member_of_foo_returns_int();
        });
    

    If you can't use c++11, you need to write a small helper function:

    int func_wrapper(const Foo& x) {
        return x.member_of_foo_returns_int();
    }
    

    and pass that using std::ptr_fun:

    Eigen::Matrix<int,2,2> new_m = m.unaryExpr(std::ptr_fun(func_wrapper));
    

    For calling member functions there is actually a nice helper function already implemented named std::mem_fun_ref (this takes a member function pointer and returns a functor object which is accepted by unaryExpr):

    Eigen::Matrix<int,2,2> new_m = m.unaryExpr(
        std::mem_fun_ref(&Foo::member_of_foo_returns_int));
    

    All these variants are type safe, i.e., trying to store the result in a non-int-Matrix will not compile.