2015-04-28 55 views
2

我想在使用Eigen :: Matrix3d矩陣的庫中爲Cython創建一個包裝。我如何設置Matrix3d對象的單個元素/係數?在Cython中設置Eigen :: Matrix3d的係數/元素

我知道,我可以用coeff(row, col)方法得到值,但找不到任何函數set_coeff(row, col, value) - 或者可能被稱爲 - 來設置值。

cdef decl_eigen.Matrix3d t = decl_eigen.Matrix3d() 

宣佈將Matrix3D後,我想設置的值,但沒有以下結構的用Cython工作:

t << 1,2,3,4,5,6,7,8,9 
t(0,0) = 1 
t[0][0] = 1 

,我不能用一個構造函數的值,因爲據我所知,不存在任何。

這裏是我想出迄今文件:

decl_eigen.pxd

cdef extern from "Eigen/Dense" namespace "Eigen": 
    cdef cppclass Vector3d: 
     Matrix3d() except + 
     double coeff(int row, int col) 

decl_foo.pxd

cimport decl_eigen 

cdef extern from "../foo.hpp" namespace "MyFoo": 

    cdef cppclass Bar: 
     Bar() except + 
     void transform(decl_eigen.Matrix3d &transformation) 

foo.pyx

import decl_eigen 
cimport decl_foo 

cdef class Bar: 

    cdef decl_foo.Bar *thisptr 

    def __cinit__(self): 
     self.thisptr = new decl_foo.Bar() 

    def __dealloc__(self): 
     del self.thisptr 

    def transform(self, transformation): 
     cdef decl_eigen.Matrix3d t = decl_eigen.Matrix3d() 
     for i in range(3): 
      for j in range(3): 
       k = i*3 + j 
       # Set the coefficient of t(i,j) to transformation[k], but how???? 
     self.thisptr.transform(t) 

謝謝。

+0

我沒有cython的經驗,所以請耐心等待。有'data()'[函數](http://eigen.tuxfamily.org/dox/classEigen_1_1PlainObjectBase。html#a4663159a1450fa89214b1ab71f7ef5bf)它可以讓你訪問一個指向數據的指針。然後,您可以通過數學來分配所需的值。另外,你聲明'cdef decl_eigen.Matrix3d t = decl_eigen.Matrix3d()'不起作用,然後在'foo.pyx'中有'cdef decl_eigen.Matrix3d t = decl_eigen.Matrix3d()'。那是對的嗎? –

+0

謝謝Avi指出這種不一致。 'cdef'聲明確實有效。我重新提出了一些問題。 – HaM

+0

Avi的建議可以進行以下修改: – HaM

回答

4

它不像它應該那樣簡單,但你可以使它工作。在本徵

元素訪問看起來主要是通過operator()來完成:

// (copied from http://eigen.tuxfamily.org/dox/GettingStarted.html) 
MatrixXd m(2,2); 
m(0,0) = 3; 
m(1,0) = 2.5; 
m(0,1) = -1; 
m(1,1) = m(1,0) + m(0,1); 

因此,我們需要定義運算符(),所以你可以用Cython訪問它。我假設它返回一個double& - 我實際上找不到Eigen中的定義,因爲它深埋在模板類層次結構中(它實際上返回的並不是非常重要 - 它的行爲就像返回一個雙重的&,這應該是夠好了)。

不幸的是,operator()在Cython中看起來有些破損(請參閱Cython C++ wrapper operator() overloading error),所以我們必須將它別名爲別的。我用element

cdef extern from "eigen3/Eigen/Dense" namespace "Eigen": 
    # I'm also unsure if you want a Matrix3d or a Vector3d 
    # so I assumed matrix 
    cdef cppclass Matrix3d: 
     Matrix3d() except + 
     double& element "operator()"(int row,int col) 

原則上我們只希望能夠做到m.element(0,0) = 5。但是,Cython不喜歡這樣。因此,我不得不通過對指針類型機制的稍微複雜的賦值來創建一個函數。

cdef void set_matrix_element(Matrix3d& m, int row, int col, double elm): 
    cdef double* d = &(m.element(row,col)) 
    d[0] = elm 

因此,要設置矩陣元素,我們只需調用此函數。這裏是我測試它的功能:

def get_numbers(): 
    cdef Matrix3d m = Matrix3d() 
    cdef int i 
    for i in range(3): 
     set_matrix_element(m,i,i,i) 
    return m.element(0,0),m.element(1,1),m.element(2,2),m.element(1,2) 
    # returns 0,1,2, and something else (I get 0, but in principle 
    # I think it's undefined since it's never been specifically set) 
+0

感謝@DavidW分享你的見解和冗長,但容易遵循,解釋! – HaM