2017-07-19 20 views
1

我正在嘗試編寫一個C++ mex函數來遍歷矩陣的單元數組,每個矩陣的大小不同。在Matlab中,我可以做到這一點使用以下代碼:在mex函數中索引和訪問單元格數組和矩陣的元素

function Z = myFunction(X, Z, B) 

for i = 1:size(X, 1) 
    for j = 1:size(X, 2) 
     for k = 1:size(X, 3) 
      temp = X{i, j, k}; 
      for m = 1:size(temp, 1) 
       Z{temp(m, 1)}(temp(m, 2)) = Z{temp(m, 1)}(temp(m, 2)) + B(i, j, k); 
      end 
     end 
    end 
end 

這裏X是一個3維單元陣列,其中每個單元包含行的可變數目和2列的矩陣。這兩列允許我索引另一個向量Z的單元陣列,其中每個向量具有不同的長度。

#include "mex.h" 

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) 
{ 
    const mxArray* X = prhs[0]; 
    const mxArray* Z = prhs[1]; 
    const mxArray* B = prhs[2]; 

    const int* pDims = mxGetDimensions(X); 

    mwSize nsubs = mxGetNumberOfDimensions(X); 

    for (size_t i = 0; i < pDims[0]; i++) { 
     for (size_t j = 0; j < pDims[1]; j++) { 
      for (size_t k = 0; k < pDims[2]; k++) { 
       int subs [] = {i, j, k}; 
       mxArray* temp = mxGetCell(X, mxCalcSingleSubscript(X, nsubs, subs)); 

       const int* matDims = mxGetDimensions(temp); 
       for (size_t m = 0; m < matDims[0]; m++) { 

       } 
      } 
     } 
    } 
} 
:Z中的載體的元素被索引通過從3維矩陣B.

到目前爲止,I(前我從未編碼在C++)在C以下代碼++元素遞增

問題:

  1. 要訪問矩陣B的元素,我可以使用我一樣訪問單元陣列X的元素相同的功能mxCalcSingleSubscript?如果不是,我該怎麼做?
  2. 如何訪問temp的元素並執行索引,正如我在Matlab代碼中所做的那樣?

回答

2

- 由於所有輸入數組都是const,所以您應該複製Z

- mxCalcSingleSubscript可以用於包括單元陣列的任何類型的陣列。在這裏,我將它重命名爲sub2ind

- mxGetPr用於訪問數組的元素。

這裏(尚未在實際測試數據)的實現:

#include "mex.h" 
#define sub2ind mxCalcSingleSubscript 
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) 
{ 
    const mxArray* X = prhs[0]; 
    const mxArray* Z = prhs[1]; 
    const mxArray* B = prhs[2]; 
    mxArray * out = mxDuplicateArray (Z); 
    const int* pDims = mxGetDimensions(X); 

    mwSize nsubs = mxGetNumberOfDimensions(X); 
    double* B_arr = mxGetPr(B); 
    for (size_t i = 0; i < pDims[0]; i++) { 
     for (size_t j = 0; j < pDims[1]; j++) { 
      for (size_t k = 0; k < pDims[2]; k++) { 
       int subs [] = {i, j, k}; 
       mwIndex idx = sub2ind(X, nsubs, subs); 
       mxArray* temp = mxGetCell(X, idx); 
       double* temp_arr = mxGetPr(temp); 

       const int* matDims = mxGetDimensions(temp); 
       mwSize nsubs_temp = mxGetNumberOfDimensions(temp); 
       for (size_t m = 0; m < matDims[0]; m++) { 
        int subs_out_1 [] = {m,0}; 
        int subs_out_2 [] = {m,1}; 
        mwIndex temp_m_1 = temp_arr[sub2ind(temp, nsubs_temp, subs_out_1)]-1; 
        mwIndex temp_m_2 = temp_arr[sub2ind(temp, nsubs_temp, subs_out_2)]-1; 
        double* Z_out = mxGetPr (mxGetCell(out,temp_m_1)); 
        Z_out[temp_m_2] += B_arr[idx]; 
       } 
      } 
     } 
    } 
    plhs[0] = out; 
} 

但是MATLAB和C實現都可以改爲使用線性索引:

function Z = myFunction(X, Z, B) 
    for k = 1:numel(X) 
     for m = 1:size(X{k}, 1) 
      Z{X{k}(m, 1)}(X{k}(m, 2)) = Z{X{k}(m, 1)}(X{k}(m, 2)) + B(k); 
     end 
    end 
end 


#include "mex.h" 
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) 
{ 
    const mxArray* X = prhs[0]; 
    const mxArray* Z = prhs[1]; 
    const mxArray* B = prhs[2]; 
    mxArray * out = mxDuplicateArray (Z); 

    mwSize n_X = mxGetNumberOfElements(X); 
    double* B_arr = mxGetPr(B); 
    for (size_t k = 0; k < n_X; k++) { 
     mxArray* temp = mxGetCell(X, k); 
     double* temp_arr = mxGetPr(temp); 

     const int* matDims = mxGetDimensions(temp); 
     size_t rows = matDims[0]; 
     for (size_t m = 0; m < rows; m++) { 
      mwIndex temp_m_1 = temp_arr[m]-1; 
      mwIndex temp_m_2 = temp_arr[m+rows]-1; 
      double* Z_out = mxGetPr (mxGetCell(out,temp_m_1)); 
      Z_out[temp_m_2] += B_arr[k]; 
     } 
    } 
    plhs[0] = out; 
} 
+0

太謝謝你了對於有用的評論!完美的作品。我只是想知道,如果我刪除'X','Z'和'B'的聲明前面的'const',並用第27行和第33行中的'Z'替換'out',爲什麼'Z'沒有被修改?現在'Z_out'沒有指向'Z'的元素而不是'out'的元素,因此第28行直接修改了'Z'?這會比複製數組快嗎? –

+0

此外,避免使用'mxCalcSingleSubscript' /'sub2ind'並使用'i','j','k'和'​​m'直接對'X'和'temp'進行索引會更快嗎? –

+0

所有到mex函數(包括X,Z和B)的輸入都是常量,必須/不能修改。所以你應該創建一個副本並進行更改。 'Z_out'指向'out'的元素 – rahnema1

相關問題