C++的特征复制?

C++的特征复制?,c++,eigen,symmetric,C++,Eigen,Symmetric,设A为对称矩阵,v为向量。我从一个由n列组成的块中提取,从j开始,然后使用 VectorXd a; a = A.middleCols(j,n).selfadjointView<Lower>() * v // does not compile 事实上,A是通过const引用传递的函数的参数,使用 const MatrixXd& A const Ref<const MatrixXd>& A 以下是一个例子: // this version doesn't

设A为对称矩阵,v为向量。我从一个由n列组成的块中提取,从j开始,然后使用

VectorXd a;
a = A.middleCols(j,n).selfadjointView<Lower>() * v // does not compile
事实上,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;
}
关于我最初的问题和我在编辑部分添加的示例,我对复制有点困惑。正如我所理解的工作版本和非工作版本之间的区别,这一行

Matrix(M.block(1, 2, 3, 4).triangularView<Lower>()) += B.selfadjointView<Lower>();  

之所以有效,是因为它的lhs告诉Eigen M.block1,2,3,4.triangularView实际上是一个矩阵,而不是对矩阵的引用。否则,运算符+=将执行一个错误,该运算符没有为.block重载。所以我最初的问题是矩阵是否。。。只告诉我们它是一个矩阵,用来进行计算,或者说是复制。。。变成矩阵?谢谢

以下表达式:

A.middleCols(j,n).selfadjointView<Lower>() 
这仅适用于立即分配稠密积,以允许以下代码:

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

在本例中,triangularView的行为就像一个书写掩码。

该表达式对我来说编译并运行良好。你能再次检查并添加任何需要的额外信息吗?是的,第一个应该可以很好地工作,我看到它使用的是M而不是A…你能把它具体化为A吗?非常感谢.noalias的提醒,但是在这种情况下,我真的不明白为什么需要.noalias,因为我计算的是A=Mv而不是A=Ma。我并不是在试图避免a的存储,因为我真的需要它来进行未来的计算。然而,我试图避免使用A.middleColsj,n.selfadjointView的副本,我仍然不明白为什么第一个版本适用于您,因为它不适用于我,是的,M代替A在这里是一个打字错误,而不是在我的代码中。这是因为我们无法在编译时知道您是在做A=Mv还是A=Ma,即使在运行时,这在一般情况下也是非常困难的。因此,在默认情况下,a=Mv的计算就像a和M或v之间存在混叠一样,因此:tmp=M*v;a=tmp;。谢谢你的建议。差不多了,但还有一点,我在EDIT2部分添加了它。非常感谢!我对.selfadjointView的用法感到困惑。我想它也处理存储问题。所以我的目标确实是用B的三角形填充A的下三角部分,我想我是在警告Eigen B是对称的。
A.middleCols(j,n).selfadjointView<Lower>() 
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;
}
MatrixXd(M.block(1, 2, 3, 4).triangularView<Lower>()) += B.selfadjointView<Lower>();
M.block(1, 2, 3, 4).triangularView<Lower>() += B;