我正在使用Eigen广泛使用并经常将Eigen::Matrix
对象与我自己设计的NSObject
子类(vMAT_Array
)映射的库的代码。与库往往需要编组矩阵转换成vMAT_Array
情况下,他们可以通过周围,工作等有没有办法“强制”MatrixBase :: eval发生在模板函数参数上?
我有处理这个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");
通知对大多数的参数vMAT_cast
明确.eval()
电话。这些是必要的,因为模板函数尝试(在编译时),以扩展到使用代码的征懒惰表达式模板,从而产生这样一个可爱的错误消息之一:
/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()
~~~~~~^
我怀疑有模板 - 这会“迫使”MatrixBase::eval
发生,但我缺乏这方面的知识。任何人都可以启发我吗?
啊,我*想*我看到表达式是如何工作的......它是在编译时计算的,如果'IsGLCompatible'是'false',那么在调用函数之前有一个专门化“修正”参数。我没有看到我可以使用'Ref'模板类。 –
假设你只能映射顺序存储的列主矩阵,然后你声明'vMAT_cast'函数为'vMAT_cast(参考>矩阵);'任何不与' MatrixXd'将被评估。如果'vMAT_Array'支持跨度,则将其声明为:'vMAT_cast(Ref matrix)'。 –
ggael
谢谢澄清...我的困难是我不知道什么类型的矩阵库用户可能想投。我的** Objective-C **库试图使用'vMAT_Array *'作为“ref”类型,您可以轻松地将它传递给函数,方法等等。所以,我可能需要挖掘源代码** Eigen **'Ref'在某个点上的东西?但是因为我可以(大部分)理解你所描述的第一种方法是如何工作的,所以我想我会先尝试。 (目前我仍在向所有地方喷洒'.eval()'......) –