c++ 自己制作拷贝?
c++ Eigen making copy?
设A为对称矩阵,v为向量。我从 A 中提取一个从 j 开始的 n 列块,然后使用
将其乘以 v
VectorXd a;
a = A.middleCols(j,n).selfadjointView<Lower>() * v // does not compile
因为这不能编译,而这
a = MatrixXd(A.middleCols(j,n).selfadjointView<Lower>()) * v
可以,我想知道第二个版本是否复制了
A.middleCols(j,n).selfadjointView<Lower>()
还是直接计算?
感谢任何提示。
编辑: 我怀疑问题与参数类型有关,因为我收到错误:
invalid argument type 'typename ConstSelfAdjointViewReturnType.... to unary expression'
确实,A 是使用
之一通过 const 引用传递的函数的参数
const MatrixXd& A
const Ref<const MatrixXd>& A
这是一个例子:
// this version doesn't compile
MatrixXd returnSymmetricMatrix(const MatrixXd& A, const VectorXd& v, const MatrixXd& B){
// B is a symmetric matrix
VectorXd a;
a = A.middleCols(3, 4).selfadjointView<Lower>() * v;
MatrixXd M(code_fill(){...});
// code_fill is the function filling the lower triangular part of a symmetric matrix
M.block(1, 2, 3, 4).triangularView<Lower>() += B.selfadjointView<Lower>();
return M;
}
// this version compiles
MatrixXd returnSymmetricMatrix(const MatrixXd& A, const VectorXd& v, const MatrixXd& B){
// B is a symmetric matrix
VectorXd a;
a = MatrixXd(A.middleCols(3, 4).selfadjointView<Lower>()) * v;
MatrixXd M(code_fill(){...});
// code_fill is the function filling the lower triangular part of a symmetric matrix
Matrix(M.block(1, 2, 3, 4).triangularView<Lower>()) += B.selfadjointView<Lower>();
return M;
}
EDIT2 关于我最初的问题和我在编辑部分添加的示例,我对复制有点困惑。据我了解工作版本和非工作版本之间的区别,行
Matrix(M.block(1, 2, 3, 4).triangularView<Lower>()) += B.selfadjointView<Lower>();
有效是因为它的 lhs 告诉 Eigen M.block(1, 2, 3, 4).triangularView() 实际上是一个矩阵而不是对矩阵的引用。否则,运算符 += 会报错,表明该运算符没有为 .block() 重载。所以我最初的问题是 Matrix(...) 是否只告诉它是一个启用计算的矩阵,或者更确切地说是将 ... 复制到矩阵中?谢谢!
下面的表达式:
A.middleCols(j,n).selfadjointView<Lower>()
不创建任何副本。
另一方面,为避免乘积结果临时出现,您可以添加 .noalias()
:
a.noalias() = M.middleCols(j,n).selfadjointView<Lower>() * v;
只有立即分配密集产品才需要这样的代码:
a = M * a;
按预期行事。
编辑:
关于您的编译问题,以下编译正常:
#include <Eigen/Dense>
using namespace Eigen;
int main()
{
int n = 10;
MatrixXd M = MatrixXd::Random(n,2*n);
VectorXd v = VectorXd::Random(n);
VectorXd a;
a.noalias() = M.middleCols(2,n).selfadjointView<Upper>() * v;
const Ref<const MatrixXd>& A = M;
a.noalias() = A.middleCols(2,n).selfadjointView<Upper>() * v;
}
EDIT2
下一行:
MatrixXd(M.block(1, 2, 3, 4).triangularView<Lower>()) += B.selfadjointView<Lower>();
没有任何意义,因为您正在创建要分配给的临时副本。回想一下,这里 MatrixXd(whatever)
调用了 Eigen::Matrix
构造函数。将 selfadjoint-view 分配给 triangular-view 也是没有意义的。我什至无法考虑什么是合理的行为。如果你只想更新下三角部分,那么做:
M.block(1, 2, 3, 4).triangularView<Lower>() += B;
在这种情况下,triangularView
用作书写掩码。
设A为对称矩阵,v为向量。我从 A 中提取一个从 j 开始的 n 列块,然后使用
将其乘以 vVectorXd a;
a = A.middleCols(j,n).selfadjointView<Lower>() * v // does not compile
因为这不能编译,而这
a = MatrixXd(A.middleCols(j,n).selfadjointView<Lower>()) * v
可以,我想知道第二个版本是否复制了
A.middleCols(j,n).selfadjointView<Lower>()
还是直接计算?
感谢任何提示。
编辑: 我怀疑问题与参数类型有关,因为我收到错误:
invalid argument type 'typename ConstSelfAdjointViewReturnType.... to unary expression'
确实,A 是使用
之一通过 const 引用传递的函数的参数const MatrixXd& A
const Ref<const MatrixXd>& A
这是一个例子:
// this version doesn't compile
MatrixXd returnSymmetricMatrix(const MatrixXd& A, const VectorXd& v, const MatrixXd& B){
// B is a symmetric matrix
VectorXd a;
a = A.middleCols(3, 4).selfadjointView<Lower>() * v;
MatrixXd M(code_fill(){...});
// code_fill is the function filling the lower triangular part of a symmetric matrix
M.block(1, 2, 3, 4).triangularView<Lower>() += B.selfadjointView<Lower>();
return M;
}
// this version compiles
MatrixXd returnSymmetricMatrix(const MatrixXd& A, const VectorXd& v, const MatrixXd& B){
// B is a symmetric matrix
VectorXd a;
a = MatrixXd(A.middleCols(3, 4).selfadjointView<Lower>()) * v;
MatrixXd M(code_fill(){...});
// code_fill is the function filling the lower triangular part of a symmetric matrix
Matrix(M.block(1, 2, 3, 4).triangularView<Lower>()) += B.selfadjointView<Lower>();
return M;
}
EDIT2 关于我最初的问题和我在编辑部分添加的示例,我对复制有点困惑。据我了解工作版本和非工作版本之间的区别,行
Matrix(M.block(1, 2, 3, 4).triangularView<Lower>()) += B.selfadjointView<Lower>();
有效是因为它的 lhs 告诉 Eigen M.block(1, 2, 3, 4).triangularView() 实际上是一个矩阵而不是对矩阵的引用。否则,运算符 += 会报错,表明该运算符没有为 .block() 重载。所以我最初的问题是 Matrix(...) 是否只告诉它是一个启用计算的矩阵,或者更确切地说是将 ... 复制到矩阵中?谢谢!
下面的表达式:
A.middleCols(j,n).selfadjointView<Lower>()
不创建任何副本。
另一方面,为避免乘积结果临时出现,您可以添加 .noalias()
:
a.noalias() = M.middleCols(j,n).selfadjointView<Lower>() * v;
只有立即分配密集产品才需要这样的代码:
a = M * a;
按预期行事。
编辑:
关于您的编译问题,以下编译正常:
#include <Eigen/Dense>
using namespace Eigen;
int main()
{
int n = 10;
MatrixXd M = MatrixXd::Random(n,2*n);
VectorXd v = VectorXd::Random(n);
VectorXd a;
a.noalias() = M.middleCols(2,n).selfadjointView<Upper>() * v;
const Ref<const MatrixXd>& A = M;
a.noalias() = A.middleCols(2,n).selfadjointView<Upper>() * v;
}
EDIT2
下一行:
MatrixXd(M.block(1, 2, 3, 4).triangularView<Lower>()) += B.selfadjointView<Lower>();
没有任何意义,因为您正在创建要分配给的临时副本。回想一下,这里 MatrixXd(whatever)
调用了 Eigen::Matrix
构造函数。将 selfadjoint-view 分配给 triangular-view 也是没有意义的。我什至无法考虑什么是合理的行为。如果你只想更新下三角部分,那么做:
M.block(1, 2, 3, 4).triangularView<Lower>() += B;
在这种情况下,triangularView
用作书写掩码。