mxMakeArrayComplex() what's for?
Mostrar comentarios más antiguos
Now (since 2018b) that MATLAB introduces complex-interleaved storage, the C-API has two new functions
mxMakeArrayComplex(A); // or mxMakeArrayReal(A)
That two functions will take the mxArray* A and if it's not Complex/Real then it will convert to the requested type (by adding imag=0 or ignoring imaginary respectively).
Now these functions require the input to be unshared, otherwise it returns the error. One cannot apply this function on any PRHS[.] of the MEX, but one must call
TEMP = mxDuplicateArray(A);
mxMakeArrayComplex(TEMP); // or mxMakeArrayReal(TEMP)
This results two successive memory copies : one deep copy (as it-is) followed by one expansion/truncating copy.
If the inputs is from local create mxArray* user might directly create the type he/she wants and not need to call those functions at all.
From these observations, my question is: what those functions are intended for? It looks like they are just badly designed.
Enclose is a mexfile for those who want to investigate to start with:
#include "mex.h"
#include "matrix.h"
/*
* foo.c test condition to call C-API mxMakeArrayComplex()
* inspired from : https://fr.mathworks.com/help/matlab/apiref/mxmakearraycomplex.html
*
* >> mex -O -R2018a foo.c
*
* >> foo([2 3])
* RETURNS
* 2.0000 + 0.0000i 3.0000 + 0.0000i
*/
extern mxArray *mxCreateSharedDataCopy(const mxArray *pr);
#define A_IN prhs[0]
#define AC_OUT plhs[0]
// Main function ===============================================================
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
int status;
mxArray *temp;
if (nlhs >= 1) AC_OUT = mxCreateDoubleMatrix(0,0,mxREAL);
else AC_OUT = NULL;
if (nrhs >= 1)
{
#if MX_HAS_INTERLEAVED_COMPLEX
// if the next statement is replaced by (temp = A_IN), mxMakeArrayComplex(temp) will fail
temp = mxDuplicateArray(A_IN);
status = mxMakeArrayComplex(temp);
if (status == 0) mexPrintf("cannot make array complex\n");
else
{
if (AC_OUT) mxDestroyArray(AC_OUT);
AC_OUT = temp;
}
#endif
}
}
7 comentarios
James Tursa
el 17 de Sept. de 2018
Editada: James Tursa
el 17 de Sept. de 2018
"... One cannot apply this function on any PRHS[.] of the MEX ..."
The mxMakeArrayComplex( ) and mxMakeArrayReal( ) functions operate on an mxArray inplace by design, so one should not expect them to be able to operate on the prhs[ ] variables. Also note that as of R2015b, all input variables are passed into the mex routine as shared data copies. So the prhs[ ] variables will always be shared with something in R2015b and later.
Bruno Luong
el 17 de Sept. de 2018
Editada: Bruno Luong
el 17 de Sept. de 2018
James Tursa
el 17 de Sept. de 2018
"... TMW can certainly design differently to avoid 2 memory copying if one want to apply on the RHS ..."
Yes. I would never want to accept that behavior as a programmer and would end up writing my own functions to avoid that extra copy.
James Tursa
el 17 de Sept. de 2018
Editada: James Tursa
el 17 de Sept. de 2018
One part of the doc I find interesting is this:
"Returns 0 if unsuccessful. The function is unsuccessful if pa is NULL, nonnumeric, or read-only."
How does these functions know if the argument is read-only? And what does this really mean? My guess is they compare the address against some internal list (maybe the caller's workspace), and/or they check for variable sharing, but this is just a guess.
Bruno Luong
el 17 de Sept. de 2018
James Tursa
el 17 de Sept. de 2018
Editada: James Tursa
el 17 de Sept. de 2018
Side Note: Turning a variable from real to complex used to be very easy ... all you needed to do was attach memory behind the pi pointer which could be accomplished with the standard API function mxSetPi( ) or mxSetData( ).
Now it is tricky to do manually since you would have to hack into the mxArray header to set one of the flags bits. So one is forced outside of the official API in order to avoid that extra data copy.
Similar comments for converting from complex to real.
Bruno Luong
el 18 de Sept. de 2018
Editada: Bruno Luong
el 18 de Sept. de 2018
Respuestas (1)
James Tursa
el 17 de Sept. de 2018
Editada: James Tursa
el 17 de Sept. de 2018
0 votos
If it is your own low level code creating and manipulating the mxArray variables, then I agree with you that this function probably isn't needed since the complexity can be managed directly by you the programmer. But the example in the doc uses a mexCallMATLAB call, so it appears that is the intended purpose. E.g. you are calling a function that maybe you didn't write and want to make sure before going downstream in your code that the mxArray in question has the complexity you want. Although the doc doesn't explicitly state so, I would have to assume when changing complexity that you get a temporary bump in memory usage during the process and then the old memory block gets free'd automatically.
2 comentarios
Bruno Luong
el 17 de Sept. de 2018
James Tursa
el 17 de Sept. de 2018
Editada: James Tursa
el 17 de Sept. de 2018
The example in the doc does not appear to be written very well. IMO neither of the mxDuplicateArray( ) calls are needed, and this should work just fine:
mexCallMATLAB(1, plhs, 1, prhs, "sqrt");
if(!mxIsComplex(plhs[0])) {
/* preserve complexity of data */
mxMakeArrayComplex(plhs[0]);
}
Or, to avoid a compiler warning
mexCallMATLAB(1, plhs, 1, (mxArray **)prhs, "sqrt");
I am not sure why that 4th input argument to mexCallMATLAB doesn't have a const in the signature definition, since I wouldn't expect the call to ever modify that argument.
Categorías
Más información sobre Write C Functions Callable from MATLAB (MEX Files) en Centro de ayuda y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!