我想编写一个例程,使用 Eigen3 (在 RcppEigen 内)创建矩阵转置为行主要双矩阵。在主要内容中,我将它用于不同大小的矩阵。
在Eigen3中,模板Matrix
有6个参数:
三个是强制性的:
(Scalar,RowsAtCompileTime和ColsAtCompileTime)
三个是可选的:
(Options,MaxRowsAtCompileTime和MaxColsAtCompileTime)
选项可以是 RowMajor 或 ColMajor
我更喜欢动态地将维度分配给矩阵,因为我使用大型数据集而且我想避免浪费RAM。
所以,我写了以下内容
Eigen::MatrixXd mktrasp(Eigen::MatrixXd X const int n, const int p){
Eigen::Matrix<double, p, n, RowMajor> T;
T = X.transpose();
return T;
}
但我得到了编译器错误
错误:'p'不能出现在常量表达式中 错误:'n'不能出现在常量表达式
中
我想这是因为n
和p
在编译时是未知的。
所以我尝试了这个解决方案
Eigen::MatrixXd mktrasp(Eigen::MatrixXd X, const int n, const int p){
Eigen::Matrix<double, Dynamic, Dynamic, RowMajor> T(p, n);
T = X.transpose();
return T;
}
这有效,但我完全失去了情节。 T
现在是动态矩阵还是固定大小?这样做安全吗?有人可以提出更好的方法吗?
答案 0 :(得分:4)
在许多情况下,动态分配数组/矩阵很有意义。除了不过度声称内存的优点之外,我会说最大的优点是矩阵的维度通过代码传播,因为它是矩阵的属性。对于您的示例,您可以随时通过
获取尺寸A.rows(); // number of rows (at runtime)
A.cols(); // number of columns (at runtime)
A.size(); // total size of the 'plain storage' (at runtime)
您的示例现在变得像
一样简单#include <iostream>
#include <Eigen/Eigen>
typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> MatD;
MatD mktrasp(const MatD &X)
{
return X.transpose();
}
int main()
{
MatD A = MatD::Random(5,5);
MatD B = mktrasp(A);
std::cout << "A = " << std::endl << A << std::endl;
std::cout << "B = " << std::endl << B << std::endl;
}
如果您想使用某个临时变量(如示例中所示),您还可以使用:
MatD mktrasp(const MatD &X)
{
// copies the transpose of "X" -> T
// N.B. the dimensions (and possible other attributes) are also copied
// you would thus find that "T.rows() == X.cols()"
// (or if you would do "MatD A = X": "T.rows() == X.rows()")
MatD T = X.transpose();
return T;
}
BTW你非常接近,但你过度复杂/过度思考。在许多(几乎所有)情况下,您可以而且应该真正避免在C ++中传递数组大小。它使您的代码更易读,更易于维护,并且更不容易出错。