#include #include #include #include #include "compiler.h" #if defined (COMPILER_MSVC) #include #define isnan _isnan #define INFINITY (HUGE_VAL+HUGE_VAL) #define NAN (INFINITY - INFINITY) #elif defined(COMPILER_LCC) #include #define INFINITY (DBL_MAX+DBL_MAX) #define NAN (INFINITY - INFINITY) #else #include #endif void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { /* declare variables */ const mwSize *dims; mwSize *dimsout; mwIndex indx; int i, numdims, dim; int numelin, numelout, x0, x1, y1; mxClassID classid; /* used with double precision input */ double *inputr_p, *inputi_p, *output1r_p, *cnt, *ssqr, *ssqi, *sumi, biasterm; /* used with single precision input */ float *inputr_ps, *inputi_ps, *output1r_ps, *cnts, *ssqrs, *ssqis, *sumis, biasterms; /* figure out the classid */ classid = mxGetClassID(prhs[0]); /* check inputs */ if (nrhs > 3) { mexErrMsgTxt("Too many input arguments."); } else if (nrhs == 3) { if (~mxIsEmpty(prhs[2]) && (mxGetM(prhs[2])!=1 || mxGetN(prhs[2])!=1)) { mexErrMsgTxt("Invalid dimension for input argument 2, must be scalar. Weights vector is not supported in this implementation of nanvar."); } if (mxGetScalar(prhs[2]) <= 0) { mexErrMsgTxt("Invalid value for input argument 2."); } } else if (nrhs < 1) { mexErrMsgTxt("Too few input arguments, at least 1 required."); } if (mxIsEmpty(prhs[0])) { plhs[0] = mxCreateDoubleScalar(NAN); return; } else if (!mxIsNumeric(prhs[0]) && !mxIsLogical(prhs[0]) && !mxIsChar(prhs[0])) { mexErrMsgTxt ("Input argument 1 should be either numeric or logical."); } /* figure out dimension info and number of elements */ dims = mxGetDimensions(prhs[0]); numdims = mxGetNumberOfDimensions(prhs[0]); numelin = mxGetNumberOfElements(prhs[0]); /* extract dimension for standard deviation */ if (nrhs==3) { dim = mxGetScalar(prhs[2]) - 1; } else { /* figure out the averaging dimension when only 1 input argument is given */ dim = 0; for (i=0; i1) { dim = i; break; } } } /* determine the normalisation term (either N or N-1), this depends on the numeric precision */ if (classid==mxDOUBLE_CLASS) { if (nrhs==1) { biasterm = 1.0; } else if (mxIsEmpty(prhs[1])) { biasterm = 1.0; } else if (mxGetScalar(prhs[1])==1) { biasterm = 0.0; } else if (mxGetScalar(prhs[1])==0) { biasterm = 1.0; } else { mexErrMsgTxt("Invalid value for second input argument: this should either be [], 0, or 1."); } } else if (classid==mxSINGLE_CLASS) { if (nrhs==1) { biasterms = 1.0; } else if (mxIsEmpty(prhs[1])) { biasterms = 1.0; } else if (mxGetScalar(prhs[1])==1) { biasterms = 0.0; } else if (mxGetScalar(prhs[1])==0) { biasterms = 1.0; } else { mexErrMsgTxt("Invalid value for second input argument: this should either be [], 0, or 1."); } } /* helper variable needed to kick out the last dimension, if this is the averaging dimension */ x0 = 0; if (numdims==dim+1) { x0 = -1; } /* create the vector which contains the dimensionality of the output */ dimsout = mxMalloc((numdims+x0) * sizeof(mwSize)); for (i=0; idim+1) { dimsout[dim] = 1; } /* compute the number of output elements */ if (numdims>=dim+1) { numelout = numelin / dims[dim]; } else { numelout = numelin; } /* compute helper variables x1 and y1 needed for the indexing */ if (dim+1>numdims) /* this essentially means that no averaging is done */ { x1 = numelin; y1 = numelin; } else { x1 = 1; for (i=0; inumdims) { output1r_p[i] = inputr_p[i]; ssqr[i] = inputr_p[i]*inputr_p[i]; cnt[i] = 1.0; } } /* compute the variance */ for (i=0; inumdims) { output1r_p[i] = inputr_p[i]; sumi[i] = inputi_p[i]; ssqr[i] = inputr_p[i]*inputr_p[i]; ssqi[i] = inputi_p[i]*inputi_p[i]; cnt[i] = 1.0; } } /* compute the variance */ for (i=0; inumdims) { output1r_ps[i] = inputr_ps[i]; ssqrs[i] = inputr_ps[i]*inputr_ps[i]; cnts[i] = 1.0; } } /* compute the variance */ for (i=0; inumdims) { output1r_ps[i] = inputr_ps[i]; sumis[i] = inputi_ps[i]; ssqrs[i] = inputr_ps[i]*inputr_ps[i]; ssqis[i] = inputi_ps[i]*inputi_ps[i]; cnts[i] = 1.0; } } /* compute the variance */ for (i=0; i