Chris
Chris

Reputation: 31206

Eigen: passing SparseMatrix in column or row order to the same function

Suppose I write the following:

func(Eigen::SparseMatrixBase<double> & A){
    for(int i = 0; i < A.outerSize(); i++)
        for(Eigen::SparseMatrixBase<double>::InnerIterator it(A,i);it;++it)
            // do something
}

This function does not work, since SparseMatrixBase cannot initialize an inner iterator.

So, I define the function for both RowMajor and ColMajor, then I try to template these functions:

template<class Mat, class MatI>
func(Mat & A){
    for(int i = 0; i < A.outerSize(); i++)
        for(MatI it(A,i);it;++it)
            //do something

func<Eigen::SparseMatrix<double,Eigen::RowMajor>,ditto::InnerIterator>(Arowmajor);
func<...,...>(Acolmajor);

And when I compile:

error: cannot convert Eigen::SparseMatrix<double,RowMajor> & 
to Eigen::SparseMatrix<double,0,int> &

Then, I change the types:

func<Eigen::SparseMatrix<double,0,int>,ditto::InnerIterator>(Arowmajor)

And the error? the inverse of the previous:

error: cannot convert Eigen::SparseMatrix<double,0,int> & 
to Eigen::SparseMatrix<double,RowMajor> & 


What is the proper way to handle iteration and templating with the Eigen classes?

Upvotes: 0

Views: 255

Answers (1)

Avi Ginsburg
Avi Ginsburg

Reputation: 10596

Instead of explicitly using two template parameters, you can use a single one to represent the SparseMatrix type and use its InnerIterator as so:

#include <Eigen/SparseCore>
#include <iostream>

using namespace Eigen;

template<class Mat>
void func(Mat & A, double d)
{
    for (int i = 0; i < A.outerSize(); i++)
        for (typename Mat::InnerIterator it(A, i); it; ++it)
            it.valueRef() = d;
}

int main()
{
    SparseMatrix<double> sm(3, 3);
    sm.setIdentity();

    std::cout << sm << "\n\n";

    func(sm, 3.2);

    std::cout << sm << "\n\n";

    return 0;
}

Note that this will not compile for expressions, such as func(sm * 2.0, 3.2); as that is an expression template and does not have an InnerIterator. There are ways to write templated functions that will accept an expression, but those are more complicated and tend to require more knowledge of the inner workings of Eigen (see e.g. here).

Upvotes: 2

Related Questions