1

私は、Eigenを広範囲に使用するライブラリのコードに取り組んでおり、頻繁にEigen::MatrixオブジェクトをNSObject自分の設計のサブクラスにマップしています ( vMAT_Array)。ライブラリを操作するには、多くの場合、マトリックスをvMAT_Arrayインスタンスにマーシャリングして、それらを渡すことができるようにする必要があります。

これを処理するvMAT_castテンプレート関数があります。

template <typename EigenObjectType>
vMAT_Array * vMAT_cast(EigenObjectType matrix)
{
    return Map<EigenObjectType>(matrix).matA;
}

この関数の問題は、 Eigenの遅延評価セマンティクスと正しく相互作用しないことです。たとえば、以下の単体テスト コードを見てください。

vMAT_Array * matM = vMAT_cast(VectorXd::LinSpaced(40, 1.0, 40.0).eval());
[matM reshape:vMAT_MakeSize(5, 8)];
Mat<double> M = matM;
Array<bool, Dynamic, Dynamic> sel = M.unaryExpr([](double elt) { return (int)elt % 3 == 0; }).cast<bool>();
vMAT_Array * vecN = vMAT_pick(matM, vMAT_cast(sel));
NSLog(@"%@", vecN.dump);
vMAT_Array * vecNv = vMAT_cast(VectorXd::LinSpaced(13, 3.0, 39.0).eval());
STAssertEqualObjects(vecN, vecNv, @"Logical indexing broken");

.eval()へのほとんどの引数の明示的な呼び出しに注意してくださいvMAT_cast。これらが必要なのは、テンプレート関数が (コンパイル時に) Eigenの遅延式テンプレートの 1 つを使用してコードに展開しようとするためです。これにより、次のような素敵なエラー メッセージが生成されます。

/Users/Shared/Source/vMAT/vMATTests/EigenTests.mm:25:35: note: in instantiation of member function 'Eigen::DenseBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >::LinSpaced' requested here
    vMAT_Array * matM = vMAT_cast(VectorXd::LinSpaced(40, 1.0, 40.0));
                                  ^
In file included from /Users/Shared/Source/vMAT/vMATTests/EigenTests.mm:11:
In file included from /Users/Shared/Source/vMAT/vMAT/vMAT.h:51:
/Users/Shared/Source/vMAT/vMAT/vMAT_Array.h:122:82: error: no member named 'data' in 'Eigen::CwiseNullaryOp<Eigen::internal::linspaced_op<double, true>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >'
                                        data:[NSMutableData dataWithBytes:matrix.data()
                                                                          ~~~~~~ ^

を「強制」する template-fu があるのではMatrixBase::evalないかと思いますが、それについての知識がありません。誰でも私を啓発できますか?

4

1 に答える 1