2013-04-17 43 views
1

我正在使用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发生,但我缺乏这方面的知识。任何人都可以启发我吗?

回答

2

你可以在eigen/unsupported/Eigen/OpenGLSupport模块中找到这种模板kung-fu。在这里你可以找到OpenGL函数的包装器,它通过原始的C指针获取向量和矩阵。最关键的是在本次测试,我们检查表达式类型是否兼容OpenGL:

bool IsGLCompatible = bool(XprType::Flags&LinearAccessBit)            
        && bool(XprType::Flags&DirectAccessBit)            
        && (XprType::IsVectorAtCompileTime || (XprType::Flags&RowMajorBit)==0) 

LinearAccessBit意味着没有“跨越”,DirectAccessBit意味着有一个。数据()可用。另外两个是显而易见的,也许在你的情况下不相关。

对于您来说,另一个选择可能更简单一些,就是使用devel分支的新类Ref。有关此方法的详细信息,请参阅doc

+0

啊,我*想*我看到表达式是如何工作的......它是在编译时计算的,如果'IsGLCompatible'是'false',那么在调用函数之前有一个专门化“修正”参数。我没有看到我可以使用'Ref'模板类。 –

+0

假设你只能映射顺序存储的列主矩阵,然后你声明'vMAT_cast'函数为'vMAT_cast(参考>矩阵);'任何不与' MatrixXd'将被评估。如果'vMAT_Array'支持跨度,则将其声明为:'vMAT_cast(Ref matrix)'。 – ggael

+0

谢谢澄清...我的困难是我不知道什么类型的矩阵库用户可能想投。我的** Objective-C **库试图使用'vMAT_Array *'作为“ref”类型,您可以轻松地将它传递给函数,方法等等。所以,我可能需要挖掘源代码** Eigen **'Ref'在某个点上的东西?但是因为我可以(大部分)理解你所描述的第一种方法是如何工作的,所以我想我会先尝试。 (目前我仍在向所有地方喷洒'.eval()'......) –

相关问题