Search code examples
c++eigen

Eigen function that does array operations on Matrix<> or Block<>


I'd like to make a function that can take both a Matrix<> or a Block<> object.

Example:

#include <iostream>
#include <Eigen/Dense>

//A simplified example of the function I'm making
double example_function(const Eigen::MatrixXd & input){
    double d1 = input.array().pow(2).sum();
    double d2 = input.rowwise().norm().sum();
    return d1 + d2;
}


int main(){
    Eigen::MatrixXd m1(3,2);
    m1.setRandom();

    // This works
    example_function(m1);

    // I'd like to make this work
    example_function(m1.block(1,0,2,2));

    return 0;
}

The following does not work, because DenseBase does not have the 'array' method:

template<typename Derived>
double example_function(const Eigen::DenseBase<Derived> & input){
    double d1 = input.array().pow(2).sum();  // array() method invalid 
    double d2 = input.rowwise().norm().sum();
    return d1 + d2;
}

How would I go about this?


Solution

  • First of all, your original code (with const MatrixXd&) does work, but it can generate an unnecessary copy. To accept both Matrix<...> and Block<Matrix<...> > objects via a templated function, use MatrixBase instead of DenseBase:

    template<class Derived>
    double example_function(const Eigen::MatrixBase<Derived> & input){
        double d1 = input.array().abs2().sum(); // abs2() is simpler/more efficient than pow(2)
        double d2 = input.rowwise().norm().sum();
        return d1 + d2;
    }
    

    However, in your example code m1.block(1,0) is invalid, as you need to specify the size as well as the start-index, e.g., these work:

    m1.block<1,2>(1,0);
    m1.block(1,0, 1,2);
    

    and m1.Random() should be m1.setRandom().