コード例 #1
0
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
    Distance_Mode DISTANCE_FCN = EUCLIDEAN;
    VectorClassNames VECTOR_CLASS;

#ifdef DOUBLE
    char mxIsClassName[] = "double";
#else
    char mxIsClassName [] = "single";
#endif

    /* Check for proper number of arguments. */
    if (nrhs != 2)                                                  { mexErrMsgTxt("Two inputs required."); }
    
    int nfields = mxGetNumberOfFields(prhs[0]);
    if(nfields<5)                                                   { mexErrMsgTxt("First input must have at least 5 fields."); }
    
    // Get theta
    const mxArray* tmp=mxGetField(prhs[0],0,fnames_in[0]);
    if(!mxIsClass(tmp,mxIsClassName))                                { mexErrMsgTxt("input.theta must be double\n"); }
    REAL* ptheta=(REAL*)mxGetData(tmp);
    theta=*ptheta;
    bool val=(theta>0.0)&&(theta<1.0);
    if(!val)                                                        { mexErrMsgTxt("Bad theta\n"); }
    mu=1.0/(1.0-theta);
    
    // Get outparams
    
    tmp=mxGetField(prhs[0],0,fnames_in[1]);
    if(!mxIsClass(tmp,"int32"))                                     { mexErrMsgTxt("input.numlevels must be int32\n"); }
    int* pnumlevels=(int*)mxGetData(tmp);
    int numlevels=(int)*pnumlevels;
    
    // Get minlevel
    tmp=mxGetField(prhs[0],0,fnames_in[2]);
    if(!mxIsClass(tmp,"int32"))                                     { mexErrMsgTxt("input.minlevel must be int32\n"); }
    int* pminlevel=(int*)mxGetData(tmp);
    int minlevel=(int)*pminlevel;
    
    // Get NTHREADS
    tmp=mxGetField(prhs[0],0,fnames_in[3]);
    if(!mxIsClass(tmp,"int32"))                                     { mexErrMsgTxt("input.NTHREADS must be int32\n"); }
    int* pNTHREADS=(int*)mxGetData(tmp);
    int NTHREADS=(int)*pNTHREADS;
    
    // Get BLOCKSIZE
    tmp=mxGetField(prhs[0],0,fnames_in[4]);
    if(!mxIsClass(tmp,"int32"))                                     { mexErrMsgTxt("input.BLOCKSIZE must be int32\n"); }
    int* pBLOCKSIZE=(int*)mxGetData(tmp);
    int BLOCKSIZE=(int)*pBLOCKSIZE;
    
    // Get distancefcn
    tmp=mxGetField(prhs[0],0,fnames_in[5]);
    if(tmp==NULL)   {
        DISTANCE_FCN = EUCLIDEAN;
    }
    else {
        if(!mxIsClass(tmp,"int32")) {
            mexErrMsgTxt("input.distancefcn must be int32\n");
        }
        else    {
            int *pDISTANCE_FCN = (int*)mxGetData(tmp);
            DISTANCE_FCN = (Distance_Mode)(*pDISTANCE_FCN);
        }
    }
    // Get classname
    tmp=mxGetField(prhs[0],0,fnames_in[6]);
    if(tmp==NULL)   {
        DISTANCE_FCN = EUCLIDEAN;
    }
    else {
        if(!mxIsClass(tmp,"int32")) {
            mexErrMsgTxt("input.classname must be int32\n");
        }
        else    {
            int *pVECTOR_CLASS = (int*)mxGetData(tmp);
            VECTOR_CLASS = (VectorClassNames)(*pVECTOR_CLASS);
        }
    }
    
    //mexPrintf("DISTANCE_FCN=%d\n",DISTANCE_FCN);
    
    /* Get dimensions of second field of input */
    
    tmp=prhs[1];
    mwSize ndims_in=mxGetNumberOfDimensions(tmp);
    const mwSize* dims_in=mxGetDimensions(tmp);
    if(!mxIsClass(tmp,mxIsClassName)) {
        mexErrMsgTxt("Second input must be double\n");
    }
    
    
//    mexPrintf("ndims_in=%d\n",ndims_in);
    
    int N=dims_in[ndims_in-1];
    dim=1;
    for(int i=0;i<ndims_in-1;i++) {
        dim*=dims_in[i];
    }
    
//    mexPrintf("dim=%d N=%d\n",dim,N);
    
    // Create Vectors
    REAL* X=(REAL*)mxGetData(tmp);
    Vectors *vectors;
    switch (VECTOR_CLASS)   {
        case VECTORS:
            vectors = new Vectors(X,N,dim,DISTANCE_FCN);
            break;
        default:
            mexErrMsgTxt("\n Invalid classname for Vectors.");
            break;
    }
    
    if( N==1 ) {
        NTHREADS = 0;
    }
    ThreadsWithCounter threads(NTHREADS);
    
    // Construct covertree
    SegList<DLPtrListNode<CoverNode> > seglist(1024);
    const Vector* vector=(vectors->next());
    Cover cover(vector,seglist,numlevels,minlevel);
    EnlargeData enlargedata(&threads,BLOCKSIZE,vectors->getRemaining());
//    Timer timer;
//    timer.on();
    cover.enlargeBy(enlargedata,*vectors);
//    timer.off();
//    timer.printOn(cout);
    
    
    /* Create matrix for the return argument. */
    plhs[0] = mxCreateStructMatrix(1, 1, 5, fnames_out);
    
    mxArray* fout;
    
    dims[0]=1;
    dims[1]=1;
#ifdef DOUBLE
    fout =mxCreateNumericArray(ndims,dims,mxDOUBLE_CLASS,mxREAL);
#else
    fout =mxCreateNumericArray(ndims,dims,mxSINGLE_CLASS,mxREAL);
#endif
    REAL* p=(REAL*)mxGetData(fout);
    mxSetField(plhs[0],0,fnames_out[0],fout);
    p[0]=ptheta[0];
    
    dims[0]=1;
    dims[1]=9;
    fout = mxCreateNumericArray(ndims,dims,mxINT32_CLASS,mxREAL);
    int* outparams=(int*)mxGetData(fout);
    mxSetField(plhs[0],0,fnames_out[1], fout);
    
    outparams[0]=vectors->getIndex(cover.getRoot()->getPoint());
    outparams[1]=cover.getMinLevel();
    outparams[2]=cover.getNumLevels();
    outparams[3]=cover.getCount();
    outparams[4]=cover.getNumberInserted();
    outparams[5]=cover.getNumberDeep();
    outparams[6]=cover.getNumberDuplicates();
    outparams[7]=DISTANCE_FCN;
    outparams[8]=VECTOR_CLASS;
    
    dims[0]=1;
    dims[1]=numlevels;
#ifdef DOUBLE
    fout=mxCreateNumericArray(ndims,dims,mxDOUBLE_CLASS,mxREAL);
#else
    fout=mxCreateNumericArray(ndims,dims,mxSINGLE_CLASS,mxREAL);
#endif
    REAL* pradii=(REAL*)mxGetData(fout);
    pradii[0]=cover.getMaxRadius();
    for(int i=1;i<numlevels;i++) {
        pradii[i]=ptheta[0]*pradii[i-1];
    }
    mxSetField(plhs[0],0,fnames_out[2], fout);
    
    dims[0]=N;
    dims[1]=5;
    fout =mxCreateNumericArray(ndims,dims,mxINT32_CLASS,mxREAL);
    int* base=(int*)mxGetData(fout);
    CoverIndices coverindices(&cover,vectors,base);
    mxSetField(plhs[0],0,fnames_out[3], fout);
    
    dims[0]=1;
    dims[1]=2;
    fout =mxCreateNumericArray(ndims,dims,mxINT64_CLASS,mxREAL);
    long int* pncalls=(long int*)mxGetData(fout);
    mxSetField(plhs[0],0,fnames_out[4], fout);
    pncalls[0]=enlargedata.getMergeNCallsToGetDist();
    pncalls[1]=enlargedata.getThreadNCallsToGetDist();
    
    // Clean up
    delete vectors;
}