Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 在MATLAB R2018a及更新版本中,将复杂对象转换为真实对象,无需数据拷贝_Arrays_Matlab_Types_Casting_Complex Numbers - Fatal编程技术网

Arrays 在MATLAB R2018a及更新版本中,将复杂对象转换为真实对象,无需数据拷贝

Arrays 在MATLAB R2018a及更新版本中,将复杂对象转换为真实对象,无需数据拷贝,arrays,matlab,types,casting,complex-numbers,Arrays,Matlab,Types,Casting,Complex Numbers,因为,复数矩阵作为单个数据块存储在内部,每个矩阵元素的实部和虚部相邻存储——他们称之为“交错复数”。(以前这样的矩阵有两个数据块,一个用于所有实部,一个用于所有虚部--“独立复数”) 我认为,由于存储现在允许,应该可以将复数数组转换为实数数组,其中包含两倍多的元素,而无需复制数据 MATLAB有一个函数,可以将数组强制转换为不同的类型,而无需复制数据。例如,可以使用它将具有16个8位值的数组强制转换为具有2个双浮点数的数组。它在不复制数据的情况下执行此操作,位模式被重新解释为新类型 遗憾的是,这

因为,复数矩阵作为单个数据块存储在内部,每个矩阵元素的实部和虚部相邻存储——他们称之为“交错复数”。(以前这样的矩阵有两个数据块,一个用于所有实部,一个用于所有虚部--“独立复数”)

我认为,由于存储现在允许,应该可以将复数数组转换为实数数组,其中包含两倍多的元素,而无需复制数据

MATLAB有一个函数,可以将数组强制转换为不同的类型,而无需复制数据。例如,可以使用它将具有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
B
具有(在R2018a和更新版本中)完全相同的数据,顺序完全相同。然而,为了到达
B
,我们必须复制两次数据

我尝试创建一个MEX文件来实现这一点,但我不知道如何创建一个引用输入数组中数据的新数组。这个MEX文件可以工作,但在清除变量时会导致MATLAB崩溃,因为有两个数组引用相同的数据,但它们没有意识到它们共享数据(即引用计数不增加)

//使用以下内容构建:
//mex-R2018a typecast_complextoreal.cpp
#包括
#如果MX_具有_交错_复数==0
#错误“此MEX文件必须使用-R2018a标志编译”
#恩迪夫
#包括
void mexFunction(int/*nlhs*/,mxArray*plhs[],int nrhs,const mxArray*prhs[]){
//验证输入
如果(nrhs!=1){
mexErrMsgTxt(“预期一个输入参数”);
}
如果(!mxisDuble(prhs[0])&&!mxIsSingle(prhs[0])){
mexErrMsgTxt(“仅支持浮点数组”);
}
//获取输入数组大小
mwSize nDims=mxGetNumberOfDimensions(prhs[0]);
mwSize const*inSizes=mxGetDimensions(prhs[0]);
//创建同一类型但实值的0x0输出矩阵
std::vector超大(nDims+1,0);
plhs[0]=mxCreateNumericMatrix(0,0,mxGetClassID(prhs[0]),mxREAL);
//将输出数组数据指针设置为输入数组的
//注意!这是非法的,在释放两者时会导致MATLAB崩溃
//输入和输出数组,因为它试图释放相同的数据
//两次
mxSetData(plhs[0],mxGetData(prhs[0]);
//设置输出数组大小
超大型[0]=mxicomplex(prhs[0])?2:1;
用于(尺寸ii=0;ii

我很想听听关于如何从这里开始的想法。我不一定需要修复MEX文件,如果解决方案是纯MATLAB代码,那就更好了。

这个问题让我想起了一些关于通过MEX进行就地内存编辑的博客文章,其中提到:

[M] 不鼓励直接修改原始数据,官方也不支持这样做。如果操作不当,很容易使Matlab崩溃

在最好的情况下,这是一个无法维持的混乱局面

话虽如此,我没有一个解决方案给你,但我可以建议一个解决办法

看看MATLAB如何允许我们调用python库,我们可以在python中执行这些操作,并且只有当我们达到无法或不希望在python中继续的阶段时,才能将数据带回MATLAB。取决于这个阶段的时间,这个想法可能是有效的方法,也可能是完全无用的建议

看一下下面的例子,它应该是不言自明的:

np = py.importlib.import_module('numpy');
sp = py.importlib.import_module('scipy.fftpack');

% Create a double array in python:
arrC = sp.fftn(np.random.rand(uint8(4), uint8(3), uint8(2)));
%{
arrC = 
  Python ndarray with properties:

           T: [1×1 py.numpy.ndarray]
        base: [1×1 py.NoneType]
      ctypes: [1×1 py.numpy.core._internal._ctypes]
        data: [1×4 py.memoryview]
       dtype: [1×1 py.numpy.dtype]
       flags: [1×1 py.numpy.flagsobj]
        flat: [1×1 py.numpy.flatiter]
        imag: [1×1 py.numpy.ndarray]
    itemsize: [1×1 py.int]
      nbytes: [1×1 py.int]
        ndim: [1×1 py.int]
        real: [1×1 py.numpy.ndarray]
       shape: [1×3 py.tuple]
        size: [1×1 py.int]
     strides: [1×3 py.tuple]
    [[[ 13.99586491+0.j           0.70305071+0.j        ]
      [ -1.33719563-1.3820106j   -0.74083670+0.25893033j]
      [ -1.33719563+1.3820106j   -0.74083670-0.25893033j]]

     [[ -0.43914391+0.8336674j    0.08835445-0.50821244j]
      [  1.07089829-0.35245746j   0.44890850-0.9650458j ]
      [  2.09813180+1.34942678j  -1.20877832+0.71191772j]]

     [[ -2.93525342+0.j          -0.69644042+0.j        ]
      [  0.16165913-1.29739125j  -0.84443177+0.26884365j]
      [  0.16165913+1.29739125j  -0.84443177-0.26884365j]]

     [[ -0.43914391-0.8336674j    0.08835445+0.50821244j]
      [  2.09813180-1.34942678j  -1.20877832-0.71191772j]
      [  1.07089829+0.35245746j   0.44890850+0.9650458j ]]]
%}

% Make sure that python sees it as a "complex double" (aka complex128)
assert( isequal(arrC.dtype, np.dtype(np.complex128)) );

% Return a (real) double view:
arrR = arrC.view(np.float64);
%{
arrR = 
  Python ndarray with properties:

           T: [1×1 py.numpy.ndarray]
        base: [1×1 py.numpy.ndarray]
      ctypes: [1×1 py.numpy.core._internal._ctypes]
        data: [1×4 py.memoryview]
       dtype: [1×1 py.numpy.dtype]
       flags: [1×1 py.numpy.flagsobj]
        flat: [1×1 py.numpy.flatiter]
        imag: [1×1 py.numpy.ndarray]
    itemsize: [1×1 py.int]
      nbytes: [1×1 py.int]
        ndim: [1×1 py.int]
        real: [1×1 py.numpy.ndarray]
       shape: [1×3 py.tuple]
        size: [1×1 py.int]
     strides: [1×3 py.tuple]
    [[[ 13.99586491   0.           0.70305071   0.        ]
      [ -1.33719563  -1.3820106   -0.7408367    0.25893033]
      [ -1.33719563   1.3820106   -0.7408367   -0.25893033]]

     [[ -0.43914391   0.8336674    0.08835445  -0.50821244]
      [  1.07089829  -0.35245746   0.4489085   -0.9650458 ]
      [  2.0981318    1.34942678  -1.20877832   0.71191772]]

     [[ -2.93525342   0.          -0.69644042   0.        ]
      [  0.16165913  -1.29739125  -0.84443177   0.26884365]
      [  0.16165913   1.29739125  -0.84443177  -0.26884365]]

     [[ -0.43914391  -0.8336674    0.08835445   0.50821244]
      [  2.0981318   -1.34942678  -1.20877832  -0.71191772]
      [  1.07089829   0.35245746   0.4489085    0.9650458 ]]]
%}

% Do something else with it in python
...

% Bring data to MATLAB:
sz = cellfun(@int64, cell(arrR.shape));
B = permute(reshape(double(py.array.array('d', arrR.flatten('C').tolist())),sz),[2,1,3]);
最后一个阶段的效率可能会很低,无法通过之前不复制数据来抵消性能/内存增益,因此最好将其保留到最后,并在之前尽可能减少数据


在进行这方面的实验时,我意识到将非标量数据从MATLAB传输到Python和Python之间有很多困难(只需比较
np.asarray(1+1i)
vs
np.asarray([1+1i,1+1i])
)。可能是因为python中对
complex
ndarray
的支持有限

如果您(与我相反)知道如何处理对象(即
ndarray
对象的
data
字段的内容),您可以获得一个指针,并可能将其传递给C以获得一些有用的结果



1这是可能的,但您必须
num2cell
您的数据才能作为python列表传输(反之亦然)。这种情况也可以通过以下方式得到改善。

以下是

由于许多数学库使用交错复杂表示法,因此在MEX函数中使用相同的表示法可以消除转换数据的需要。这简化了您的代码,并可能在涉及大型数据集时加快处理速度

根据文档中的说明,每个复杂类型似乎是一个结构,包含两个实部和虚部:

typedef struct {
    double real;
    double imag;
} mxComplexDouble ;
因此,我们希望(重新解释)将
mxComplexDouble
数组强制转换为数学库中使用的其他双复数类型

例如,数学库可能已将其复杂类型定义为:

typedef struct {
    double real;
    double imag;
} other_complex ;
它还定义了一个函数来使用自己复杂类型的数组

void do_something(const other_complex* math_array);
在这里,我们要向数学库发送一个MATLAB复杂数组:

mxComplexDouble matlab_array[5];
other_complex* math_array =  (other_complex*)matlab_array;
do_something(math_array);
因为它只需要一个指针转换,所以可以认为它加快了进程

但是关于*任何使用
math_array
都会导致未定义的行为。即使是铸造到
double* double_array = (double*)matlab_array; 
printf("%f",double_array[0]); // Unedfined behavior