2013-04-17 79 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()'......) –

相關問題