特征:按列或行顺序将稀疏矩阵传递给同一函数

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

本文关键字:函数 顺序 特征      更新时间:2023-10-16

假设我写了以下内容:

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 类处理迭代和模板的正确方法是什么?

您可以使用单个模板参数来表示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 << "nn";
func(sm, 3.2);
std::cout << sm << "nn";
return 0;
}

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