在mex函数中索引和访问单元格数组和矩阵的元素

时间:2017-07-19 22:37:12

标签: c++ arrays matlab indexing mex

我试图编写一个C ++ mex函数来迭代矩阵的单元格数组,每个矩阵的矩阵大小不同。在Matlab中,我可以使用以下代码执行此操作:

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列的矩阵。这两列允许我索引另一个向量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++) {

                }
            }
        }
    }
}

问题:

  1. 要访问矩阵B的元素,我可以使用与访问单元格数组X的元素相同的mxCalcSingleSubscript函数吗?如果没有,我该怎么做?
  2. 如何访问temp的元素并执行索引,就像我在Matlab代码中所做的那样?

1 个答案:

答案 0 :(得分: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;
}