2017-01-30 22 views
0

Aを対称行列とし、vをベクトルとする。私はこのC++固有作成コピー?

a = MatrixXd(A.middleCols(j,n).selfadjointView<Lower>()) * v 

がないのに対し、私は第二のバージョンが行うかどうかを疑問に思って、Jから始まるn列のブロックから抽出し、コンパイルされないこのよう

VectorXd a; 
a = A.middleCols(j,n).selfadjointView<Lower>() * v // does not compile 

を用いて、Vを掛け

A.middleCols(j,n).selfadjointView<Lower>() 

または直接計算を実行しますか?

ありがとうございます。

EDIT:私はエラーを取得するなどの問題が、引数の型とは何かを持っている疑いがある:

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私の最初の質問と私が編集セクションで追加した例については、私はコピーについて少し混乱しています。そのLHSそのM.block(1、2、3、4).triangularView()が実際に固有に伝えるので、私は作業と非稼働バージョン、ライン

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

作品の違いを理解するように行列への参照ではなく行列である。さもなければ、演算子+ =は、この演算子が.block()に対して多重定義されていないというエラーによって発生します。ですから、私の元来の質問は、Matrix(...)は計算を有効にするためにMatrixであることを伝えるのか、それとも...をMatrixにコピーするのかということだけです。ありがとう!

+0

私のために、式はコンパイル(および実行)されます。追加の情報を確認して追加することができますか? –

+0

はい、最初のものはうまくいくはずです。私は 'A'の代わりに' M'を使っているのを見ています... – ggael

+0

[MCVE]に肉付けできますか? –

答えて

1

次の式:

A.middleCols(j,n).selfadjointView<Lower>() 

は、任意のコピーを作成しません。一方

、積の結果のために一時的に回避するために、あなたは.noalias()を追加することができます。

a.noalias() = M.middleCols(j,n).selfadjointView<Lower>() * v; 

これだけのようなコードできるように密集し、製品の即時割り当てのために必要とされている:

a = M * a; 

期待どおりに動作します。

EDIT:あなたのコンパイルの問題に関して

、以下の罰金コンパイル:

#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コンストラクタを呼び出します。自己アジャストビューを三角ビューに割り当てることも意味をなさない。私はこれについて妥当な行動であるかもしれないことについて考えることさえできません。あなただけの下三角部分を更新したい場合は、その後の操作を行います。この場合

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

を、書き込みマスクとしてtriangularView振る舞います。

+0

.noalias()のリマインダーに感謝しますが、この場合、a = M * v(a = M * aではなく)を計算するので、なぜ.noalias()が必要なのかは分かりません。私は将来の計算のために本当に必要なので、私の記憶を避けようとしていません。しかし、私はA.middleCols(j、n).selfadjointView ()のコピーを避けようとしています。なぜなら、それは私のためではないのでAは私のコードではなくタイプミスです)。 – itQ

+0

これは、コンパイル時に= Mvかa = Maを実行しているかどうかを知ることができず、実行時にも一般的には非常に困難なためです。したがって、デフォルトでは、a = MvはaとMまたはvとの間にエイリアシングがあるかのように評価されるので、 'tmp = M * v; a = tmp; ' – ggael

+0

多くの感謝!私は.noalias()の問題を手に入れました! – itQ

関連する問題