I have written a mex file for MATLAB. It calls MATLAB pinv function to calculate the Moore Penrose pseudoinverse. I named this function my_pinv. my_pinv gets an array and returns its pseudoinverse, exactly similar to pinv:
A = magic(8); A = A(:,1:6)
b = 260*ones(8,1)
x = my_pinv(A)*b
In the mex file, however, I have to copy the values of the input array to be able to use mexCallMATLAB. Here is the content of my_pinv.cpp:
#include <matrix.h>
#include <mex.h>
#include <string.h>
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
#define PRHS_A prhs[0]
#define PLHS_X plhs[0]
int M = mxGetM( PRHS_A ); // Get the dimensions of A.
int N = mxGetN( PRHS_A );
double *A_ptr = mxGetPr( PRHS_A );
mxArray *PINV_A = mxCreateDoubleMatrix(M, N, mxREAL); /* Put input in an mxArray */
memcpy(mxGetPr(PINV_A), A_ptr, sizeof(double)*M*N);
PLHS_X = mxCreateDoubleMatrix(N, M, mxREAL); // Create the output matrix.
mexCallMATLAB(1, &PLHS_X, 1, &PINV_A, "pinv");
}
Is there anyway that I skip using memcpy and directly use the input array, prhs[0], in mexCallMATLAB? I actually don't like the fact that the values of input array needs to be copied especially when the input array is very large.
In fact, I would like to be able to use something like
mexCallMATLAB(1, &PLHS_X, 1, &RHS_A, "pinv"); // (I know it is not right and the compiler would not like it but it is for the sake of example)
rather than
mexCallMATLAB(1, &PLHS_X, 1, &PINV_A, "pinv");
Could someone share his/her experiences in this regard?
mexCallMATLAB has the following signature:
int mexCallMATLAB(int nlhs, mxArray *plhs[], int nrhs,
mxArray *prhs[], const char *functionName);
For some reason, the RHS array is not marked with the const qualifier. I dont know why... This explains why you get a compilation error:
// this is from Visual C++ 2013
error C2664: 'int mexCallMATLAB(int,mxArray*[],int,mxArray *[],const char *)' :
cannot convert argument 4 from 'const mxArray *[]' to 'mxArray *[]'
Conversion loses qualifiers
The solution is to explicitly cast away the constant-ness telling the compiler that we know what we're doing:
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
// validate arguments
if(nrhs != 1 || nlhs > 1)
mexErrMsgIdAndTxt("mex:error", "Wrong number of arguments.");
//perhaps do more validations here..
// out = pinv(in)
mexCallMATLAB(1, plhs, 1, const_cast<mxArray**>(prhs), "pinv");
}
Now in MATLAB:
>> x = rand(4,3);
>> my_pinv(x) - pinv(x)
ans =
0 0 0 0
0 0 0 0
0 0 0 0
If for some reason and in some corner case this proves problematic (I doubt it), the safer way is to just duplicate the array using:
mxArray *in = mxDuplicateArray(prhs[0]);
mexCallMATLAB(1, plhs, 1, &in, "pinv");
mxDestroyArray(in);
If you absolutely want to avoid creating a deep copy, there are undocumented functions that create a shared-data copy (where only a new array header is created, but the data is shared).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With