How to return a float value from a mex function, and how to retrieve it from m-file? - matlab

I understand that all the returned values of a mex function are stored in plhs array of type mxArray*. I want to return a value of type float. How can I do it?
Some code examples on returning it from the mex function and retrieving it from the m-file is much appreciated.

The MATLAB class name for float type data is "single".
In the MEX-file you could write:
void mexFunction(int nlhs, mxArray * plhs[], int nrhs, const mxArray * prhs[])
{
// Create a 2-by-3 real float
plhs[0] = mxCreateNumericMatrix(2, 3, mxSINGLE_CLASS, mxREAL);
// fill in plhs[0] to contain the same as single([1 2 3; 4 5 6]);
float * data = (float *) mxGetData(plhs[0]);
data[0] = 1; data[1] = 4; data[2] = 2;
data[3] = 5; data[4] = 3; data[5] = 6;
}
Retrieving it from the M-file is pretty much like calling any other function. If you named the MEX-function foo, you'd call it like this:
>> x = foo;
Now x would contain the single-precision value equivalent to single([1 2 3; 4 5 6]) that was stored in plhs[0].

Related

How to read input matrix of a Matlab mex function row-wise?

I need create a Matlab mex function that will take an input matrix and return the matrix diagonal.
Input:
1 2 3
4 5 6
Expected output:
1 2 3 0 0 0
0 0 0 4 5 6
My problem is that since Matlab reads matrices column-wise instead of row-wise, my mex function gives the wrong output.
Current output:
1 4 0 0 0 0
0 0 2 5 0 0
0 0 0 0 3 6
How would you go about changing my code to read the input matrix row-wise so I can have the proper output?
My code is as follows:
#include <matrix.h>
#include <mex.h>
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
mxArray *a_in, *b_out;
const mwSize *dims;
double *a, *b;
int rows, cols;
// Input array:
a_in = mxDuplicateArray(prhs[0]);
// Get dimensions of input array:
dims = mxGetDimensions(prhs[0]);
rows = (int) dims[0];
cols = (int) dims[1];
// Output array:
if(rows == cols){
b_out = plhs[0] = mxCreateDoubleMatrix(rows, rows*cols, mxREAL);
}
else{
b_out = plhs[0] = mxCreateDoubleMatrix(cols, rows*cols, mxREAL);
}
// Access the contents of the input and output arrays:
a = mxGetPr(a_in);
b = mxGetPr(b_out);
// Compute exdiag function of the input array
int count = 0;
for (int i = 0; i < rows; i++) {
for(int j = 0; j<cols;j++){
if(rows == cols){
b[rows*count+count/rows] = a[j + rows * i];
count++;
}
else if(rows < cols){
b[cols*count+count/rows] = a[j + cols * i];
count++;
}
else if(rows>cols){
b[cols*count+count/rows] = a[j + cols * i];
count++;
}
}
}
}
Inside your loops, i is the row index and j is the column index. You do a[j + rows * i], mixing up the two indices. MATLAB stores data column-wise, so you need to do a[i + rows * j] to read the input matrix correctly.
For indexing the output, you want the row to remain i, and you want the column to be i * cols + j:
b[i + rows * (i * cols + j)] = a[i + rows * j];
Note that you don't need to do a_in = mxDuplicateArray(prhs[0]), since you are not writing into a_in. You can directly access the prhs[0] matrix, or do a_in = prhs[0] if you want an alias.
Also, casting array sizes to int will cause trouble if the array is very large. It is best to use mwSize and mwIndex for array sizes and indices.
Finally, you should always check the type of the input array, if you are given an array that is not doubles, you will likely cause a read out of bounds error.
This is my code:
#include <matrix.h>
#include <mex.h>
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
mwSize const* dims;
double *a, *b;
mwSize rows, cols;
if (!mxIsDouble(prhs[0])) {
mexErrMsgTxt("Input must be doubles");
}
// Get dimensions of input array:
dims = mxGetDimensions(prhs[0]);
rows = dims[0];
cols = dims[1];
// Output array:
plhs[0] = mxCreateDoubleMatrix(rows, rows*cols, mxREAL);
// Access the contents of the input and output arrays:
a = mxGetPr(prhs[0]);
b = mxGetPr(plhs[0]);
// Compute exdiag function of the input array
for (mwIndex i = 0; i < rows; i++) {
for (mwIndex j = 0; j < cols; j++) {
b[i + rows * (i * cols + j)] = a[i + rows * j];
}
}
}

Matlab crashed when I call mexCallMATLAB(1,a,1,b,"transpose")

I want to create a new sparse matrix and pass the value of the input sparse matrix to it, and then call Matlab to get its transpose. The code crashed, can you give me some suggestions?
extern void mexFunction(int iNbOut, mxArray *pmxOut[],
int iNbIn, const mxArray *pmxIn[])
{
mxArray *A, *B;
double *d,*p,*pin,*out;
mwSize m,n,nzmax;
mwIndex *ir, *jc;
// get the information of input sparse matrix
m = mxGetM(pmxIn[0]);
n = mxGetN(pmxIn[0]);
nzmax = mxGetNzmax(pmxIn[0]);
ir = mxGetIr(pmxIn[0]);
jc = mxGetJc(pmxIn[0]);
pin = mxGetPr(pmxIn[0]);
// create a new sparse matrix and pass the input matrix to it
A = mxCreateSparse(m, n, nzmax, mxREAL);
mxSetIr(A, ir);
mxSetJc(A, jc);
mxSetPr(A, pin);
d = mxGetPr(A);
B = mxCreateSparse(m, n, nzmax, mxREAL);
// get the transpose of A by call matlab
mexCallMATLAB(1, &B, 1, &A, "transpose");
p = mxGetPr(B);
pmxOut[0] = mxCreateNumericArray(1 , nzmax, mxSINGLE_CLASS,mxREAL);
out = mxGetPr(pmxOut[0]);
for(mwSize i = 0; i < nzmax; i++)
{
out[i] = p[i];
mexPrintf("pmxOut = %f", out[i]);
}
}

How to convert a recursive function to mex code?

I have a recursive function choose in MATLAB code as follows:
function nk=choose(n, k)
if (k == 0)
nk=1;
else
nk=(n * choose(n - 1, k - 1)) / k;
end
end
The code is used to compute the combination between n and k. I want to speed up it by using mex code. I tried to write a mex code as
double choose(double* n, double* k)
{
if (k==0)
return 1;
else
return (n * choose(n - 1, k - 1)) / k;
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double *n, *k, *nk;
int mrows, ncols;
plhs[0] = mxCreateDoubleMatrix(1,1, mxREAL);
/* Assign pointers to each input and output. */
n = mxGetPr(prhs[0]);
k = mxGetPr(prhs[1]);
nk = mxGetPr(plhs[0]);
/* Call the recursive function. */
nk=choose(n,k);
}
However, it does not work. Could you help me to modify the mex code which can implement the above MATLAB code? Thanks
The following code fixes your C mex implementation.
The problem is not the recursion of course...
Your code uses pointers instead of values (in C it's important to use pointers only in the right places).
You can use Matlab build in function: nchoosek
See: http://www.mathworks.com/help/matlab/ref/nchoosek.html
The following code works:
//choose.c
#include "mex.h"
double choose(double n, double k)
{
if (k==0)
{
return 1;
}
else
{
return (n * choose(n - 1, k - 1)) / k;
}
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double *n, *k, *nk;
int mrows, ncols;
plhs[0] = mxCreateDoubleMatrix(1,1, mxREAL);
/* Assign pointers to each input and output. */
n = mxGetPr(prhs[0]);
k = mxGetPr(prhs[1]);
nk = mxGetPr(plhs[0]);
/* Call the recursive function. */
//nk=choose(n,k);
*nk = choose(*n, *k);
}
Compile it within Matlab:
mex choose.c
Execute:
choose(10,5)
ans =
252
It is not inefficient implementation...
I am helping fixing your implementation, to be used as "inefficient example".
Measure execution of rahnema1's implementation:
tic;n = 1000000;k = 500000;nk = prod((k+1:n) .* prod((1:n-k).^ (-1/(n-k))));toc
Elapsed time is 0.022855 seconds.
Measure execution of choose.mexw64 implementation:
tic;n = 1000000;k = 500000;nk = choose(1000000, 500000);toc
Elapsed time is 0.007952 seconds.
(took a little less time than prod((k+1:n) .* prod((1:n-k).^ (-1/(n-k))))).
Measure Matlab recursion, getting error (even for n=700 and k=500):
ic;n = 700;k = 500;nk = RecursiveFunctionTest(n, k);toc
Maximum recursion limit of 500 reached. Use set(0,'RecursionLimit',N) to change the limit. Be aware that exceeding your available stack space can
crash MATLAB and/or your computer.
tic;n = 700;k = 400;nk = RecursiveFunctionTest(n, k);toc
Elapsed time is 0.005635 seconds.
Very inefficient...
Measuring Matlab build in function nchoosek:
tic;nchoosek(1000000, 500000);toc
Warning: Result may not be exact. Coefficient is greater than 9.007199e+15 and is only accurate to 15 digits
In nchoosek at 92
Elapsed time is 0.005081 seconds.
Conclusion:
You need to implement the C mex file without using recursion, and take a measure.
Measure without recursion:
static double factorial(double number)
{
int x;
double fac = 1;
if (number == 0)
{
return 1.0;
}
for (x = 2; x <= (int)number; x++)
{
fac = fac * x;
}
return fac;
}
double choose(double n, double k)
{
if (k == 0)
{
return 1.0;
}
else
{
//n!/((n–k)! k!)
return factorial(n)/(factorial(n-k)*factorial(k));
}
}
tic;choose(1000000, 500000);toc
Elapsed time is 0.003079 seconds.
Faster...
no need to mex binomial coefficients can be implemented in Matlab:
function nk=nchoosek2(n, k)
if n-k > k
nk = prod((k+1:n) .* prod((1:n-k).^ (-1/(n-k))));
else
nk = prod((n-k+1:n) .* prod((1:k).^ (-1/k)) ) ;
end
end

Most Efficient Way of Using mexCallMATLAB in Converting Double* to mxArray*

I am writing a MEX code in which I need to use pinv function. I am trying to find a way to pass the array of type double to pinv using mexCallMATLAB in the most efficient way. Let's for the sake of example say the array is named G and its size is 100.
double *G = (double*) mxMalloc( 100 * sizeof(double) );
where
G[0] = G11; G[1] = G12;
G[2] = G21; G[3] = G22;
Which means every four consecutive elements of G is a 2×2 matrix. G stores 25 different values of this 2×2 matrix.
I should note that these 2×2 matrices are not well-conditioned and they may contain all zero in their element. How can I use pinv function to calculate the pseudoinverse in the elements of G? For example, how can I pass the array to mexCallMATLAB in order to calculate the pseudoinverse of the first 2×2 matrix in G?
I thought of the following approach:
mxArray *G_PINV_input = mxCreateDoubleMatrix(2, 2, mxREAL);
mxArray *G_PINV_output = mxCreateDoubleMatrix(2, 2, mxREAL);
double *G_PINV_input_ptr = mxGetPr(G_PINV_input);
memcpy( G_PINV_input_ptr, &G[0], 4 * sizeof(double));
mexCallMATLAB(1, G_PINV_output, 1, G_PINV_input, "pinv");
I am not sure how good this approach is. Copying the values is not economical at all because the total number of elements in G in my actual application is large. Is there anyway to skip this copying?
Here is my implementation of the MEX-function:
my_pinv.cpp
#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");
if (!mxIsDouble(prhs[0]) || mxIsComplex(prhs[0]) || mxIsSparse(prhs[0]))
mexErrMsgIdAndTxt("mex:error", "Input isnt real dense double array");
if (mxGetNumberOfElements(prhs[0]) != 100)
mexErrMsgIdAndTxt("mex:error", "numel() != 100");
// create necessary arrays
mxArray *rhs[1], *lhs[1];
plhs[0] = mxCreateDoubleMatrix(100, 1, mxREAL);
rhs[0] = mxCreateDoubleMatrix(2, 2, mxREAL);
double *in = mxGetPr(prhs[0]);
double *out = mxGetPr(plhs[0]);
double *x = mxGetPr(rhs[0]), *y;
// for each 2x2 matrix
for (mwIndex i=0; i<100; i+=4) {
// copy 2x2 matrix into rhs
x[0] = in[i+0];
x[2] = in[i+1];
x[1] = in[i+2];
x[3] = in[i+3];
// lhs = pinv(rhs)
mexCallMATLAB(1, lhs, 1, rhs, "pinv");
// copy 2x2 matrix from lhs
y = mxGetPr(lhs[0]);
out[i+0] = y[0];
out[i+1] = y[1];
out[i+2] = y[2];
out[i+3] = y[3];
// free array
mxDestroyArray(lhs[0]);
}
// cleanup
mxDestroyArray(rhs[0]);
}
Here is a baseline implementation in MATLAB so that we can verify the results are correct:
my_pinv0.m
function y = my_pinv0(x)
y = zeros(size(x));
for i=1:4:numel(x)
y(i:i+3) = pinv(x([0 1; 2 3]+i));
end
end
Now we test the MEX-function:
% some vector
x = randn(100,1);
% MEX vs. MATLAB function
y = my_pinv0(x);
yy = my_pinv(x);
% compare
assert(isequal(y,yy))
EDIT:
Here is an another implementation:
my_pinv2.cpp
#include "mex.h"
inline void call_pinv(const double &a, const double &b, const double &c,
const double &d, double *out)
{
mxArray *rhs[1], *lhs[1];
// create input matrix [a b; c d]
rhs[0] = mxCreateDoubleMatrix(2, 2, mxREAL);
double *x = mxGetPr(rhs[0]);
x[0] = a;
x[1] = c;
x[2] = b;
x[3] = d;
// lhs = pinv(rhs)
mexCallMATLAB(1, lhs, 1, rhs, "pinv");
// get values from output matrix
const double *y = mxGetPr(lhs[0]);
out[0] = y[0];
out[1] = y[1];
out[2] = y[2];
out[3] = y[3];
// cleanup
mxDestroyArray(lhs[0]);
mxDestroyArray(rhs[0]);
}
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");
if (!mxIsDouble(prhs[0]) || mxIsComplex(prhs[0]) || mxIsSparse(prhs[0]))
mexErrMsgIdAndTxt("mex:error", "Input isnt real dense double array");
if (mxGetNumberOfElements(prhs[0]) != 100)
mexErrMsgIdAndTxt("mex:error", "numel() != 100");
// allocate output
plhs[0] = mxCreateDoubleMatrix(100, 1, mxREAL);
double *out = mxGetPr(plhs[0]);
const double *in = mxGetPr(prhs[0]);
// for each 2x2 matrix
for (mwIndex i=0; i<100; i+=4) {
// 2x2 input matrix [a b; c d], and its determinant
const double a = in[i+0];
const double b = in[i+1];
const double c = in[i+2];
const double d = in[i+3];
const double det = (a*d - b*c);
if (det != 0) {
// inverse of 2x2 matrix [d -b; -c a]/det
out[i+0] = d/det;
out[i+1] = -c/det;
out[i+2] = -b/det;
out[i+3] = a/det;
}
else {
// singular matrix, fallback to pseudo-inverse
call_pinv(a, b, c, d, &out[i]);
}
}
}
This time we compute the determinant of the 2x2 matrix, if is non-zero, we calculate the inverse ourselves according to:
Otherwise we fallback to invoking PINV from MATLAB for the pseudo-inverse.
Here is quick benchmark:
% 100x1 vector
x = randn(100,1); % average case, with normal 2x2 matrices
% running time
funcs = {#my_pinv0, #my_pinv1, #my_pinv2};
t = cellfun(#(f) timeit(#() f(x)), funcs, 'Uniform',true);
% compare results
y = cellfun(#(f) f(x), funcs, 'Uniform',false);
assert(isequal(y{1},y{2}))
I get the following timings:
>> fprintf('%.6f\n', t);
0.002111 % MATLAB function
0.001498 % first MEX-file with mexCallMATLAB
0.000010 % second MEX-file with "unrolled" matrix inverse (+ PINV as fallback)
The error is acceptable and within machine precision:
>> norm(y{1}-y{3})
ans =
2.1198e-14
You could also test the worst case, when many of the 2x2 matrices are singular:
x = randi([0 1], [100 1]);
You don't need to allocate the output. Just make the pointer and let pinv create the mxArray automatically.
mxArray *lhs;
Then just use & like,
mexCallMATLAB(1, &lhs, 1, &rhs, "pinv");

Can a MATLAB Mex function accept both single and doubles?

I have a mex function that accepts double matrices as the input, but I just realized that the code this function is used for, can have single precision matrices as well. Is it possible to allow the function to accept either?
Or if not, what is an alternative way to fix this issue?
The simple solution would be to convert the inputs in MATLAB to a consistent type (presumably double), but if you would like to have your MEX function handle multiple types, here is one way.
Check the input type with mxIsSingle and mxIsDouble (or mxIsClass) and handle it accordingly. You might have an ifstatement in mexFunction that sets up the inputs and outputs and then calls a template function. See the example below, which thresholds all the values in an array using the C++ standard library function template std::min<T> without requiring any data conversion.
flexibleFunction.cpp
#include "mex.h"
#include <algorithm> // std::min
template <typename T>
void threshArrayLT(T *out, const T *arr, mwSize n, T c)
{ // you allocate out
for (mwSize i = 0; i < n; ++i)
out[i] = std::min<T>(arr[i], c);
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
if (nlhs > 1 || nrhs != 2)
mexErrMsgTxt("Syntax:\n\tH = flexibleFunction(arr,c)");
if (!mxIsDouble(prhs[0]) && !mxIsSingle(prhs[0]))
mexErrMsgTxt("Array must be double or single.");
if ((mxIsDouble(prhs[0]) && !mxIsDouble(prhs[1])) ||
(mxIsSingle(prhs[0]) && !mxIsSingle(prhs[1])))
mexErrMsgTxt("Arguments must have same type.");
const mwSize* dims = mxGetDimensions(prhs[0]);
int ndims = static_cast<int>(mxGetNumberOfDimensions(prhs[0]));
size_t numel = mxGetNumberOfElements(prhs[0]);
if (mxIsDouble(prhs[0])) {
double *arr = mxGetPr(prhs[0]);
double c = mxGetScalar(prhs[1]);
plhs[0] = mxCreateNumericArray(ndims,dims,mxDOUBLE_CLASS,mxREAL);
threshArrayLT(mxGetPr(plhs[0]),arr,numel,c);
// In reality, if it's this simple, use std::transform with lambda or bind:
//std::transform(arr, arr+numel, mxGetPr(plhs[0]),
// [&](double s){ return std::min(s,c); });
} else if (mxIsSingle(prhs[0])) {
float *arr = (float*)mxGetData(prhs[0]);
float c = static_cast<float>(mxGetScalar(prhs[1]));
plhs[0] = mxCreateNumericArray(ndims,dims,mxSINGLE_CLASS,mxREAL);
threshArrayLT((float*)mxGetData(plhs[0]),arr,numel,c);
}
}
You can also use function overloading in C++ (same name, different argument types).
Example
>> v = rand(1,8); c = 0.5;
>> whos v c
Name Size Bytes Class Attributes
c 1x1 8 double
v 1x8 64 double
>> flexibleFunction(v,c)
ans =
0.2760 0.5000 0.5000 0.1626 0.1190 0.4984 0.5000 0.3404
>> flexibleFunction(single(v),single(c))
ans =
0.2760 0.5000 0.5000 0.1626 0.1190 0.4984 0.5000 0.3404