Skip to content

Instantly share code, notes, and snippets.

@chappjc
Created October 29, 2014 17:14
Show Gist options
  • Save chappjc/bee3224045c4f92a4698 to your computer and use it in GitHub Desktop.
Save chappjc/bee3224045c4f92a4698 to your computer and use it in GitHub Desktop.
MEX solution based on Amro's, but manually doing an "atoi", also with OpenMP
// solution_mex_chappjc_vc12.cpp
// mex -v -largeArrayDims COMPFLAGS="$COMPFLAGS /openmp" ...
// LINKFLAGS="$LINKFLAGS /openmp" solution_mex_chappjc_vc12.cpp ...
// -output solution_mex_chappjc_vc12_omp.mexw64
#include "mex.h"
#include <string>
#include <sstream>
#include <algorithm>
extern "C" {
mxArray *mxCreateSharedDataCopy(const mxArray *pr);
mxArray *mxCreateUninitNumericMatrix(mwSize m, mwSize n, mxClassID classid, mxComplexity ComplexFlag);
mxArray *mxFastZeros(mxComplexity ComplexFlag, mwSize m, mwSize n);
}
namespace {
// get i-th string from cell-array of strings
std::string getString(const mxArray *cellstr, const mwIndex idx)
{
const mxArray *arr = mxGetCell(cellstr, idx);
if (arr == NULL) mexErrMsgIdAndTxt("mex:err", "null/uninitialized");
if (!mxIsChar(arr)) mexErrMsgIdAndTxt("mex:err", "not a string");
char *cstr = mxArrayToString(arr);
if (cstr == NULL) mexErrMsgIdAndTxt("mex:err", "null");
std::string str(cstr);
mxFree(cstr);
return str;
}
// count of numbers in char-delimited string
mwSize count_numbers(const std::string &s)
{
return std::count(s.begin(), s.end(), '_') + 1;
}
};
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
// validate inputs
if (nrhs!=1 || nlhs>1) mexErrMsgIdAndTxt("mex:err", "wrong num args");
if (!mxIsCell(prhs[0])) mexErrMsgIdAndTxt("mex:err", "not a cell");
// determine sizes
const mxArray *cellstr = prhs[0];
const mwSize n_words = mxGetNumberOfElements(cellstr);
const mwSize n_nums = (n_words > 0) ? count_numbers(getString(cellstr,0)) : 0;
// allocate output numeric matrix
plhs[0] = mxCreateDoubleMatrix(n_nums, n_words, mxREAL);
mxArray *mxUnmanaged = mxFastZeros(mxREAL,n_nums, n_words);
plhs[0] = mxCreateSharedDataCopy(mxUnmanaged);
mxDestroyArray(mxUnmanaged);
//plhs[0] = mxCreateUninitNumericMatrix(n_nums, n_words, mxDOUBLE_CLASS, mxREAL);
if (plhs[0] == NULL) mexErrMsgIdAndTxt("mex:err", "null");
if (n_words == 0 || n_nums == 0) return;
double *out = mxGetPr(plhs[0]);
// extract numbers from strings
#pragma omp parallel for num_threads(4)
for (mwSignedIndex idx=0; idx<n_words; ++idx) {
mwIndex i = idx * n_nums;
std::string str = getString(cellstr, idx);
std::string::const_iterator istr = str.cbegin();
for (; istr != str.cend(); ++istr) {
if (*istr < '0' || *istr > '9')
{
++i;
continue;
}
out[i] *= 10;
out[i] += *istr - '0';
}
++i;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment