Eigen:以列或行顺序将SparseMatrix传递给同一个函数

时间:2018-03-09 23:03:26

标签: c++ eigen eigen3

假设我写了以下内容:

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
}

此函数不起作用,因为SparseMatrixBase无法初始化内部迭代器。

所以,我为RowMajorColMajor定义了函数,然后我尝试模拟这些函数:

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);

当我编译时:

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

然后,我改变了类型:

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

错误?与前一个相反:

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

使用Eigen类处理迭代和模板的正确方法是什么?

1 个答案:

答案 0 :(得分:2)

您可以使用一个模板参数代表SparseMatrix类型,而不是显式使用两个模板参数,并使用其InnerIterator

#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;
}

请注意,这不会为表达式编译,例如func(sm * 2.0, 3.2);,因为它是表达式模板,并且没有InnerIterator。有一些方法可以编写接受表达式的模板化函数,但这些函数更复杂,往往需要更多关于Eigen内部运算的知识(参见例如here)。