Reputation: 31206
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
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