在 mex 函数中索引和访问元胞数组和矩阵的元素
Indexing and accessing elements of cell arrays and matrices in mex functions
我正在尝试编写一个 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 是一个 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++) {
}
}
}
}
}
问题:
- 要访问矩阵 B 的元素,我可以使用与访问元胞数组 X 的元素相同的 mxCalcSingleSubscript 函数吗?如果没有,我该怎么做?
- 如何像在 Matlab 代码中那样访问
temp
的元素并执行索引?
-由于所有输入数组都是 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;
}
我正在尝试编写一个 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 是一个 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++) {
}
}
}
}
}
问题:
- 要访问矩阵 B 的元素,我可以使用与访问元胞数组 X 的元素相同的 mxCalcSingleSubscript 函数吗?如果没有,我该怎么做?
- 如何像在 Matlab 代码中那样访问
temp
的元素并执行索引?
-由于所有输入数组都是 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;
}