2017-07-19 10 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は、各セルは、可変の行の数と2列の行列を含んでいる3次元セルアレイです。これらの2つの列を使用して、ベクトルZの別のセル配列をインデックスできます。各ベクトルの長さは異なります。索引付けさZにおけるベクトルの要素はこれまで3次元マトリクスB.

の要素だけインクリメントされ、私は(私はCでコーディングされたことがない++前)C++で次のコードを持っている:

#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++) { 

       } 
      } 
     } 
    } 
} 

質問:私はセル配列Xの要素にアクセスするために行ったよう

  1. 行列Bの要素にアクセスするには、私は同じ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行目で' out'を 'Z'に置き換えると、なぜでしょうか? 'Z'は変更されませんか? 'Z_out'は' out'の要素ではなく 'Z'の要素を指していないので、28行目は' Z'を直接変更しますか?これは、配列を複製するよりも速いでしょうか? –

+0

また、 'mxCalcSingleSubscript' /' sub2ind'を使わず、 'i'、' j'、 'k'、' m'を使って 'X'と' temp'を直接索引付けする方が早いでしょうか? –

+0

X、Z、Bを含むmex関数へのすべての入力は定数であり、変更することはできません。コピーを作成して変更する必要があります。 'Z_out'が' out'の要素を指しています – rahnema1

関連する問題