Since MATLAB R2018a https://www.mathworks.com/help/releases/R2018a/matlab/matlab_external/do-i-need-to-upgrade-my-mex-files-to-use-interleaved-complex.html,复值矩阵在内部存储为单个数据块,每个矩阵元素的实部和虚部彼此相邻存储——他们称之为“交错复数”。 (以前,此类矩阵有两个数据块,一个用于所有实数分量,一个用于所有虚数分量——“单独的复数”。)
我认为,由于存储现在允许这样做,因此应该可以将复值数组转换为元素数量是两倍的实值数组,而无需复制数据。
MATLAB有一个函数typecast https://www.mathworks.com/help/matlab/ref/typecast.html,它将数组转换为不同的类型而不复制数据。例如,它可用于将具有 16 个 8 位值的数组转换为具有 2 个双浮点数的数组。它在不复制数据的情况下执行此操作,位模式被重新解释为新类型。
遗憾的是,这个函数在复值数组上根本不起作用。
我正在寻找复制这段代码:
A = fftn(randn(40,60,20)); % some random complex-valued array
assert(~isreal(A))
sz = size(A);
B = reshape(A,1,[]); % make into a vector
B = cat(1,real(B),imag(B)); % interleave real and imaginary values
B = reshape(B,[2,sz]); % reshape back to original shape, with a new first dimension
assert(isreal(B))
矩阵A
and B
(在 R2018a 及更新版本中)具有完全相同的数据,并且顺序完全相同。然而,要到达B
我们必须复制数据两次。
我尝试创建一个 MEX 文件来执行此操作,但我不知道如何创建一个引用输入数组中的数据的新数组。该 MEX 文件可以工作,但会导致 MATLAB 在清除变量时崩溃,因为有两个数组引用相同的数据,而没有意识到它们共享数据(即引用计数未递增)。
// Build with:
// mex -R2018a typecast_complextoreal.cpp
#include <mex.h>
#if MX_HAS_INTERLEAVED_COMPLEX==0
#error "This MEX-file must be compiled with the -R2018a flag"
#endif
#include <vector>
void mexFunction(int /*nlhs*/, mxArray* plhs[], int nrhs, const mxArray* prhs[]) {
// Validate input
if(nrhs != 1) {
mexErrMsgTxt("One input argument expected");
}
if(!mxIsDouble(prhs[0]) && !mxIsSingle(prhs[0])) {
mexErrMsgTxt("Only floating-point arrays are supported");
}
// Get input array sizes
mwSize nDims = mxGetNumberOfDimensions(prhs[0]);
mwSize const* inSizes = mxGetDimensions(prhs[0]);
// Create a 0x0 output matrix of the same type, but real-valued
std::vector<mwSize> outSizes(nDims + 1, 0);
plhs[0] = mxCreateNumericMatrix(0, 0, mxGetClassID(prhs[0]), mxREAL);
// Set the output array data pointer to the input array's
// NOTE! This is illegal, and causes MATLAB to crash when freeing both
// input and output arrays, because it tries to free the same data
// twice
mxSetData(plhs[0], mxGetData(prhs[0]));
// Set the output array sizes
outSizes[0] = mxIsComplex(prhs[0]) ? 2 : 1;
for(size_t ii = 0; ii < nDims; ++ii) {
outSizes[ii + 1] = inSizes[ii];
}
mxSetDimensions(plhs[0], outSizes.data(), outSizes.size());
}
我很想听听关于如何从这里开始的任何想法。我不一定需要修复 MEX 文件,如果解决方案是纯粹的 MATLAB 代码,那就更好了。