void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { char cmd[64]; metricTreeCPP *theTree; if(nrhs>4) { mexErrMsgTxt("Too many inputs."); } //Get the command string that is passed. mxGetString(prhs[0], cmd, sizeof(cmd)); //prhs[0] is assumed to be the string telling if(!strcmp("metricTreeCPP", cmd)){ size_t k, N; mxArray *retPtr; k=getSizeTFromMatlab(prhs[1]); N=getSizeTFromMatlab(prhs[2]); theTree = new metricTreeCPP(k,N); //Convert the pointer to a Matlab matrix to return. retPtr=ptr2Matlab<metricTreeCPP*>(theTree); //Lock this mex file so that it can not be cleared until the object //has been deleted (This avoids a memory leak). mexLock(); //Return the pointer to the tree plhs[0]=retPtr; } else if(!strcmp("buildTreeFromBatch",cmd)) { double *dataBatch; //Get the pointer back from Matlab. theTree=Matlab2Ptr<metricTreeCPP*>(prhs[1]); checkRealDoubleArray(prhs[2]); dataBatch=reinterpret_cast<double*>(mxGetData(prhs[2])); theTree->buildTreeFromBatch(dataBatch); } else if(!strcmp("searchRadius",cmd)) { size_t numPoints; ClusterSetCPP<size_t> pointClust; ClusterSetCPP<double> distClust; double *point; double *radius; mxArray *clustParams[3]; //Get the inputs theTree=Matlab2Ptr<metricTreeCPP*>(prhs[1]); checkRealDoubleArray(prhs[2]); checkRealDoubleArray(prhs[3]); point=reinterpret_cast<double*>(mxGetData(prhs[2])); radius=reinterpret_cast<double*>(mxGetData(prhs[3])); numPoints=mxGetN(prhs[2]); if(mxGetM(prhs[2])!=theTree->k){ mexErrMsgTxt("Invalid point size passed."); } //Run the search; rangeCluster now contains the results. theTree->searchRadius(pointClust,distClust,point,radius, numPoints); //Put the results into an instance of the ClusterSet container //class in Matlab. clustParams[0]=unsignedSizeMat2Matlab(pointClust.clusterEls,pointClust.totalNumEl,1); clustParams[1]=unsignedSizeMat2Matlab(pointClust.clusterSizes,pointClust.numClust,1); clustParams[2]=unsignedSizeMat2Matlab(pointClust.offsetArray,pointClust.numClust,1); //Return a ClusterSet containing the appropriate data. mexCallMATLAB(1, &(plhs[0]), 3, clustParams, "ClusterSet"); //If the distances should also be returned. if(nlhs>1) { clustParams[0]=doubleMat2Matlab(distClust.clusterEls,distClust.totalNumEl,1); clustParams[1]=unsignedSizeMat2Matlab(distClust.clusterSizes,distClust.numClust,1); clustParams[2]=unsignedSizeMat2Matlab(distClust.offsetArray,distClust.numClust,1); //Return a ClusterSet containing the appropriate data. mexCallMATLAB(1, &(plhs[1]), 3, clustParams, "ClusterSet"); } } else if(!strcmp("~metricTreeCPP", cmd)){ theTree=Matlab2Ptr<metricTreeCPP*>(prhs[1]); delete theTree; //Unlock the mex file allowing it to be cleared. mexUnlock(); } else if(!strcmp("getAllData", cmd)){ size_t N; size_t k; theTree=Matlab2Ptr<metricTreeCPP*>(prhs[1]); N=theTree->N; k=theTree->k; plhs[0]=unsignedSizeMat2Matlab(theTree->DATAIDX,N, 1); if(nlhs>1) { plhs[1]=signedSizeMat2Matlab(theTree->innerChild,N, 1); if(nlhs>2) { plhs[2]=signedSizeMat2Matlab(theTree->outerChild,N, 1); if(nlhs>3) { plhs[3]=doubleMat2Matlab(theTree->innerRadii,N, 1); if(nlhs>4) { plhs[4]=doubleMat2Matlab(theTree->outerRadii,N, 1); if(nlhs>5) { plhs[5]=doubleMat2Matlab(theTree->data,k, N); } } } } } } else if(!strcmp("getN", cmd)) { theTree=Matlab2Ptr<metricTreeCPP*>(prhs[1]); plhs[0]=unsignedSizeMat2Matlab(&(theTree->N),1,1); } else if(!strcmp("getk", cmd)) { theTree=Matlab2Ptr<metricTreeCPP*>(prhs[1]); plhs[0]=unsignedSizeMat2Matlab(&(theTree->k),1,1); }else { mexErrMsgTxt("Invalid string passed to metricTreeCPPInt."); } }
void mexFunction(const int nlhs, mxArray *plhs[], const int nrhs, const mxArray *prhs[]) { double u, scalFactor; ClusterSetCPP<double> HBar; ClusterSetCPP<double> dHBardu;//The first derivatives ClusterSetCPP<double> d2HBardu2;//The second derivatives size_t M, numH, i; mxArray *CSRetVal; mxArray *clusterElsMATLAB,*clusterSizesMATLAB, *offsetArrayMATLAB; if(nrhs!=3){ mexErrMsgTxt("Incorrect number of inputs."); return; } u=getDoubleFromMatlab(prhs[0]); M=getSizeTFromMatlab(prhs[1]); scalFactor=getDoubleFromMatlab(prhs[2]); if(M<3) { mexErrMsgTxt("The maximum order should be at least 3."); return; } numH=(M+1)*(M+2)/2; //Allocate space for the results. clusterElsMATLAB=mxCreateDoubleMatrix(numH,1,mxREAL); clusterSizesMATLAB=allocUnsignedSizeMatInMatlab(M+1,1); offsetArrayMATLAB=allocUnsignedSizeMatInMatlab(M+1,1); HBar.numClust=M+1; HBar.totalNumEl=numH; HBar.clusterEls=reinterpret_cast<double*>(mxGetData(clusterElsMATLAB)); HBar.offsetArray=reinterpret_cast<size_t*>(mxGetData(offsetArrayMATLAB)); HBar.clusterSizes=reinterpret_cast<size_t*>(mxGetData(clusterSizesMATLAB)); //Initialize the offset array and cluster sizes. HBar.offsetArray[0]=0; HBar.clusterSizes[0]=1; for(i=1;i<=M;i++){ HBar.clusterSizes[i]=i+1; HBar.offsetArray[i]=HBar.offsetArray[i-1]+HBar.clusterSizes[i-1]; } normHelmHoltzCPP(HBar,u,scalFactor); //Set the first return value mexCallMATLAB(1,&CSRetVal,0, 0, "ClusterSet"); mxSetProperty(CSRetVal,0,"clusterEls",clusterElsMATLAB); mxSetProperty(CSRetVal,0,"clusterSizes",clusterSizesMATLAB); mxSetProperty(CSRetVal,0,"offsetArray",offsetArrayMATLAB); plhs[0]=CSRetVal; if(nlhs>1) {//Compute the first derivatives, if they are desired. mxArray *clusterEls1stDerivMATLAB=mxCreateDoubleMatrix(numH,1,mxREAL); dHBardu.numClust=M+1; dHBardu.totalNumEl=numH; dHBardu.clusterEls=reinterpret_cast<double*>(mxGetData(clusterEls1stDerivMATLAB)); dHBardu.offsetArray=reinterpret_cast<size_t*>(mxGetData(offsetArrayMATLAB)); dHBardu.clusterSizes=reinterpret_cast<size_t*>(mxGetData(clusterSizesMATLAB)); normHelmHoltzDerivCPP(dHBardu,HBar); //Set the second return value mexCallMATLAB(1,&CSRetVal,0, 0, "ClusterSet"); mxSetProperty(CSRetVal,0,"clusterEls",clusterEls1stDerivMATLAB); mxSetProperty(CSRetVal,0,"clusterSizes",clusterSizesMATLAB); mxSetProperty(CSRetVal,0,"offsetArray",offsetArrayMATLAB); plhs[1]=CSRetVal; mxDestroyArray(clusterEls1stDerivMATLAB); } if(nlhs>2) {//Compute the second derivatives if they are desired. mxArray *clusterEls2ndDerivMATLAB=mxCreateDoubleMatrix(numH,1,mxREAL); d2HBardu2.numClust=M+1; d2HBardu2.totalNumEl=numH; d2HBardu2.clusterEls=reinterpret_cast<double*>(mxGetData(clusterEls2ndDerivMATLAB)); d2HBardu2.offsetArray=reinterpret_cast<size_t*>(mxGetData(offsetArrayMATLAB)); d2HBardu2.clusterSizes=reinterpret_cast<size_t*>(mxGetData(clusterSizesMATLAB)); normHelmHoltzDeriv2CPP(d2HBardu2,HBar); //Set the third return value mexCallMATLAB(1,&CSRetVal,0, 0, "ClusterSet"); mxSetProperty(CSRetVal,0,"clusterEls",clusterEls2ndDerivMATLAB); mxSetProperty(CSRetVal,0,"clusterSizes",clusterSizesMATLAB); mxSetProperty(CSRetVal,0,"offsetArray",offsetArrayMATLAB); plhs[2]=CSRetVal; mxDestroyArray(clusterEls2ndDerivMATLAB); } //Free the buffers. The mxSetProperty command copied the data. mxDestroyArray(clusterElsMATLAB); mxDestroyArray(clusterSizesMATLAB); mxDestroyArray(offsetArrayMATLAB); }
void mexFunction(const int nlhs, mxArray *plhs[], const int nrhs, const mxArray *prhs[]) { size_t n,j; size_t nCard; bool isLast, lastPassed; mxArray *codeArray; if(nrhs<1){ mexErrMsgTxt("Not enough inputs."); } if(nrhs>2){ mexErrMsgTxt("Too many inputs."); } if(nlhs>4) { mexErrMsgTxt("Too many outputs."); } //If an empty code matrix is passed, then the second argument is //required, and we will return the first gray code in the sequence. if(mxIsEmpty(prhs[0])) { mwSize dims[2]; if(nrhs<2) { mexErrMsgTxt("The second argument is required when an empty code matrix is passed."); } dims[0]=getSizeTFromMatlab(prhs[1]); dims[1]=1; //Allocate the array; this also initializes all of the elements to //0. codeArray=mxCreateLogicalArray(2, dims); //This is the code plhs[0]=codeArray; if(nlhs>1) { //This is nCard plhs[1]=mxCreateDoubleScalar(0.0); if(nlhs>2) { //This is isLast plhs[2]=mxCreateLogicalScalar(false); if(nlhs>3) { //This is j. plhs[3]=mxCreateDoubleMatrix(0, 0, mxREAL); } } } return; } //The code array cannot be complex. if(mxIsComplex(prhs[0])!=false) { mexErrMsgTxt("The code array cannot be complex."); } //Copy the code value so that the input matrix is not modified on //return. { size_t n1,n2; n1=mxGetM(prhs[0]); n2=mxGetN(prhs[0]); if((n1==1&&n2>=1)||(n2==1&&n1>=1)) { n=std::max(n1,n2); codeArray=mxDuplicateArray(prhs[0]); } else { mexErrMsgTxt("The code vector has the wrong dimensionality."); } } if(nrhs>1) { nCard=getSizeTFromMatlab(prhs[1]); } else { mxArray *lhs[1]; //Sum up the ones in codeArray to get nCard if it is not provided. mexCallMATLAB(1,lhs,1, &codeArray, "sum"); nCard=getSizeTFromMatlab(lhs[0]); mxDestroyArray(lhs[0]); } //The type of the data in the code array is whatever the user passed to //the function. The function has to be called with the correct template //value for the type of the code. lastPassed=false; switch(mxGetClassID(codeArray)){ case mxCHAR_CLASS: { mxChar *code=(mxChar*)mxGetData(codeArray); if(nCard==(size_t)code[n-1]&&nCard!=0) { lastPassed=true; } else{ isLast=getNextGrayCodeCPP(n, code, nCard, j); } break; } case mxLOGICAL_CLASS: { mxLogical* code=(mxLogical*)mxGetData(codeArray); if(nCard==(size_t)code[n-1]&&nCard!=0) { lastPassed=true; } else{ isLast=getNextGrayCodeCPP(n, code, nCard, j); } break; } case mxDOUBLE_CLASS: { double* code=(double*)mxGetData(codeArray); if(nCard==(size_t)code[n-1]&&nCard!=0) { lastPassed=true; } else{ isLast=getNextGrayCodeCPP(n, code, nCard, j); } break; } case mxSINGLE_CLASS: { float* code=(float*)mxGetData(codeArray); if(nCard==(size_t)code[n-1]&&nCard!=0) { lastPassed=true; } else{ isLast=getNextGrayCodeCPP(n, code, nCard, j); } break; } case mxINT8_CLASS: { int8_T* code=(int8_T*)mxGetData(codeArray); if(nCard==(size_t)code[n-1]&&nCard!=0) { lastPassed=true; } else{ isLast=getNextGrayCodeCPP(n, code, nCard, j); } break; } case mxUINT8_CLASS: { uint8_T* code=(uint8_T*)mxGetData(codeArray); if(nCard==(size_t)code[n-1]&&nCard!=0) { lastPassed=true; } else{ isLast=getNextGrayCodeCPP(n, code, nCard, j); } break; } case mxINT16_CLASS: { int16_T* code=(int16_T*)mxGetData(codeArray); if(nCard==(size_t)code[n-1]&&nCard!=0) { lastPassed=true; } else{ isLast=getNextGrayCodeCPP(n, code, nCard, j); } break; } case mxUINT16_CLASS: { uint16_T* code=(uint16_T*)mxGetData(codeArray); if(nCard==(size_t)code[n-1]&&nCard!=0) { lastPassed=true; } else{ isLast=getNextGrayCodeCPP(n, code, nCard, j); } break; } case mxINT32_CLASS: { int32_T* code=(int32_T*)mxGetData(codeArray); if(nCard==(size_t)code[n-1]&&nCard!=0) { lastPassed=true; } else{ isLast=getNextGrayCodeCPP(n, code, nCard, j); } break; } case mxUINT32_CLASS: { uint32_T* code=(uint32_T*)mxGetData(codeArray); if(nCard==(size_t)code[n-1]&&nCard!=0) { lastPassed=true; } else{ isLast=getNextGrayCodeCPP(n, code, nCard, j); } break; } case mxINT64_CLASS: { int64_T* code=(int64_T*)mxGetData(codeArray); if(nCard==(size_t)code[n-1]&&nCard!=0) { lastPassed=true; } else{ isLast=getNextGrayCodeCPP(n, code, nCard, j); } break; } case mxUINT64_CLASS: { uint64_T* code=(uint64_T*)mxGetData(codeArray); if(nCard==(size_t)code[n-1]&&nCard!=0) { lastPassed=true; } else{ isLast=getNextGrayCodeCPP(n, code, nCard, j); } break; } default: mexErrMsgTxt("The code vector is of an unknown data type."); } //If the final gray code was passed, then just return empty matrices //and put n in nCard. That way, if called again, the function will //start from the beginning. if(lastPassed==true) { mxDestroyArray(codeArray); plhs[0]=mxCreateDoubleMatrix(0, 0, mxREAL); if(nlhs>1) { mxArray *nCardMat=allocUnsignedSizeMatInMatlab(1, 1); *(size_t*)mxGetData(nCardMat)=n; plhs[1]=nCardMat; if(nlhs>2) { //This is isLast plhs[2]=mxCreateDoubleMatrix(0, 0, mxREAL);; if(nlhs>3) { //This is j plhs[3]=mxCreateDoubleMatrix(0, 0, mxREAL);; } } } return; } //Set the return values for the case when the last code was not passed. plhs[0]=codeArray; if(nlhs>1) { mxArray *nCardMat=allocUnsignedSizeMatInMatlab(1, 1); *(size_t*)mxGetData(nCardMat)=nCard; plhs[1]=nCardMat; if(nlhs>2) { //This is isLast plhs[2]=mxCreateLogicalScalar(isLast); if(nlhs>3) { mxArray *jMat=allocUnsignedSizeMatInMatlab(1, 1); //Increment j to be an index for Matlab. j++; *(size_t*)mxGetData(jMat)=j; plhs[3]=jMat; } } } }