2

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?

G Boggs
  • 381
  • 1
  • 6
  • 19
  • Convert the input, have different code paths in MEX, and/or try to use C++ templates. Can you give more specifics? – chappjc Oct 06 '14 at 16:39
  • @chappjc Its just as it sounds, I have one mex function, that should either take a single or a double, but I'm not sure how to allow it to accept both. For instance, as of now it only accepts doubles as an input, meaning if I try to input a single-precision matrix, it will error. – G Boggs Oct 06 '14 at 17:09

1 Answers1

1

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
chappjc
  • 30,359
  • 6
  • 75
  • 132
  • But what if I am using the MATLAB's coder toolkit to create the mex file directly from matlab code. The builder requires that I define an input type before it can be converted to mex. Is there a way to do what you described, but with the coder toolkit? Eliminating the middle C++ portion. – G Boggs Oct 06 '14 at 18:21
  • @GBoggs I'm not very familiar with Coder, but it sounds like it can't handle it. In your question, you didn't mention coder, so I assumed you were writing the MEX function. I wouldn't hack the coder output source. – chappjc Oct 06 '14 at 18:33