Can a MATLAB Mex function accept both single and doubles?

a 夏天 提交于 2019-12-11 08:16:26

问题


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?


回答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


来源:https://stackoverflow.com/questions/26220417/can-a-matlab-mex-function-accept-both-single-and-doubles

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!