我正在使用Eigen编写一些C++线性代数代码。我需要处理一些不太小的矩阵(大于4x4,但小于50x50,如果这很重要的话),它们的大小在编译时是完全已知的。
我很想受益于Eigen库在编译时对矩阵操作进行的大小检查,只要在代码中发生不同大小的矩阵之间的和,就会触发一个错误,然而我也害怕如果我不对那些相对较大的对象进行dinamically分配,可能会对堆栈造成滥用。性能问题并不影响我。
在这里,我想说的是,如果我不对那些比较大的对象进行分配,我可能会滥用堆栈。本征文件 有一个关于固定和动态大小矩阵的简短段落,其中讨论了我之前关注的问题,但不幸的是,没有强调编译时的检查,而我很想维护这些检查。文档中建议。
在可以的情况下,对很小的尺寸使用固定尺寸,而对较大的尺寸或必须使用动态尺寸。
最后,我的问题是:在Eigen中是否有一种方法可以让编译时已知大小的动态分配矩阵,同时保留标准固定大小矩阵的通常编译时检查?
就像这样。
using MyMatrix = MatrixXd<12, 15>; // Currently I can only do Matrix<double, 12, 15>
using MyVector = MatrixXd<14, 1>;
MyMatrix M;
MyVector v;
auto w = M * v; // This should trigger an INVALID_MATRIX_PRODUCT error
其中 MatrixXd<n, m>
是我想使用的假设的动态分配的、编译时已知大小的矩阵!我使用Eigen来编写一些C++线性代数代码。
你可以从Eigen类中滥用继承,提供类似矩阵的包装器。
Eigen::Block
struct MatrixHelper { Eigen::MatrixXd mat; };
template <int Rows, int Cols>
struct CheckedDynamicMatrix
: MatrixHelper, Eigen::Block<Eigen::MatrixXd, Rows, Cols>
{
using Block = Eigen::Block<Eigen::MatrixXd, Rows, Cols>;
CheckedDynamicMatrix() :
MatrixHelper { Eigen::MatrixXd(Rows, Cols) },
Block { mat.topLeftCorner<Rows, Cols>() }
{}
};
Eigen::Map
template <int Rows, int Cols>
struct CheckedDynamicMatrix
: Eigen::Map<Eigen::Matrix<double, Rows, Cols>>
{
using Map = Eigen::Map<Eigen::Matrix<double, Rows, Cols>>;
std::unique_ptr<double[]> data;
CheckedDynamicMatrix() :
Map { nullptr },
data { new double[Rows * Cols] }
{
new (static_cast<Map*>(this)) Map(data.get(), Rows, Cols);
}
};
为了实现完整的功能,你还应该添加必要的构造函数和赋值操作符,就像下面描述的那样 Eigen: 继承自矩阵
劝也劝不住1 Eigen来实现这两个功能,但你可以动态地分配一个固定大小的矩阵。
using MyMatrix = Matrix<double, 12, 15>;
using MyVector = Matrix<double, 14, 1>;
auto M = std::make_unique<MyMatrix>();
auto v = std::make_unique<MyVector>();
auto w = *M * *v; // compile time error, as desired
脚注1: 没有文档说明如果你设置了 MaxRows
和 MaxCols
定尺 Matrix
所以你可以试试 Matrix<double, 12, 15, 0, Dynamic, Dynamic>
并看看会发生什么,但要注意的行为,可能会改变没有警告,或可能导致未定义的行为。