/** @brief MEX driver entry point **/ void mexFunction (int nout, mxArray * out[], int nin, const mxArray * in[]) { enum {IN_TREE = 0, IN_DATA, IN_END} ; enum {OUT_ASGN = 0} ; vl_uint8 const *data; int opt ; int next = IN_END ; mxArray const *optarg ; int N = 0 ; int method_type = VL_IKM_LLOYD ; int verb = 0 ; /* ----------------------------------------------------------------- * Check the arguments * -------------------------------------------------------------- */ if (nin < 2) mexErrMsgTxt ("At least two arguments required."); else if (nout > 1) mexErrMsgTxt ("Too many output arguments."); if (mxGetClassID (in[IN_DATA]) != mxUINT8_CLASS) { mexErrMsgTxt ("DATA must be of class UINT8"); } N = mxGetN (in[IN_DATA]); /* n of elements */ data = (vl_uint8 *) mxGetPr (in[IN_DATA]); while ((opt = uNextOption(in, nin, options, &next, &optarg)) >= 0) { char buf [1024] ; switch (opt) { case opt_verbose : ++ verb ; break ; case opt_method : if (!uIsString (optarg, -1)) { mexErrMsgTxt("'Method' must be a string.") ; } if (mxGetString (optarg, buf, sizeof(buf))) { mexErrMsgTxt("Option argument too long.") ; } if (strcmp("lloyd", buf) == 0) { method_type = VL_IKM_LLOYD ; } else if (strcmp("elkan", buf) == 0) { method_type = VL_IKM_ELKAN ; } else { mexErrMsgTxt("Unknown cost type.") ; } break ; default : assert(0) ; break ; } } /* ----------------------------------------------------------------- * Do the job * -------------------------------------------------------------- */ { VlHIKMTree *tree ; vl_uint *ids ; int j; int depth ; tree = matlab_to_hikm (in[IN_TREE], method_type) ; depth = vl_hikm_get_depth (tree) ; if (verb) { mexPrintf("hikmeanspush: ndims: %d K: %d depth: %d\n", vl_hikm_get_ndims (tree), vl_hikm_get_K (tree), depth) ; } out[OUT_ASGN] = mxCreateNumericMatrix (depth, N, mxUINT32_CLASS, mxREAL) ; ids = mxGetData (out[OUT_ASGN]) ; vl_hikm_push (tree, ids, data, N) ; vl_hikm_delete (tree) ; for (j = 0 ; j < N*depth ; j++) ids [j] ++ ; } }
void mexFunction(int nout, mxArray *out[], int nin, const mxArray *in[]) { enum {IN_GRAD=0,IN_FRAMES,IN_END} ; enum {OUT_DESCRIPTORS} ; int verbose = 0 ; int opt ; int next = IN_END ; mxArray const *optarg ; mxArray *grad_array ; vl_sift_pix *grad ; int M, N ; double magnif = -1 ; double *ikeys = 0 ; int nikeys = 0 ; int i,j ; VL_USE_MATLAB_ENV ; /* ----------------------------------------------------------------- * Check the arguments * -------------------------------------------------------------- */ if (nin < 2) { mexErrMsgTxt("Two arguments required.") ; } else if (nout > 1) { mexErrMsgTxt("Too many output arguments."); } if (mxGetNumberOfDimensions (in[IN_GRAD]) != 3 || mxGetClassID (in[IN_GRAD]) != mxSINGLE_CLASS || mxGetDimensions (in[IN_GRAD])[0] != 2 ) { mexErrMsgTxt("GRAD must be a 2xMxN matrix of class SINGLE.") ; } if (!uIsRealMatrix(in[IN_FRAMES], 4, -1)) { mexErrMsgTxt("FRAMES must be a 4xN matrix.") ; } nikeys = mxGetN (in[IN_FRAMES]) ; ikeys = mxGetPr(in[IN_FRAMES]) ; while ((opt = uNextOption(in, nin, options, &next, &optarg)) >= 0) { switch (opt) { case opt_verbose : ++ verbose ; break ; case opt_magnif : if (!uIsRealScalar(optarg) || (magnif = *mxGetPr(optarg)) < 0) { mexErrMsgTxt("MAGNIF must be a non-negative scalar.") ; } break ; default : assert(0) ; break ; } } grad_array = mxDuplicateArray(in[IN_GRAD]) ; grad = (vl_sift_pix*) mxGetData (grad_array) ; M = mxGetDimensions(in[IN_GRAD])[1] ; N = mxGetDimensions(in[IN_GRAD])[2] ; /* transpose angles */ for (i = 1 ; i < 2*M*N ; i+=2) { grad [i] = VL_PI/2 - grad [i] ; } /* ----------------------------------------------------------------- * Do job * -------------------------------------------------------------- */ { VlSiftFilt *filt = 0 ; vl_uint8 *descr = 0 ; /* create a filter to process the image */ filt = vl_sift_new (M, N, -1, -1, 0) ; if (magnif >= 0) vl_sift_set_magnif (filt, magnif) ; if (verbose) { mexPrintf("siftdescriptor: filter settings:\n") ; mexPrintf("siftdescriptor: magnif = %g\n", vl_sift_get_magnif (filt)) ; mexPrintf("siftdescriptor: num of frames = %d\n", nikeys) ; } { mwSize dims [2] ; dims [0] = 128 ; dims [1] = nikeys ; out[OUT_DESCRIPTORS]= mxCreateNumericArray (2, dims, mxUINT8_CLASS, mxREAL) ; descr = mxGetData(out[OUT_DESCRIPTORS]) ; } /* ............................................................... * Process each octave * ............................................................ */ for (i = 0 ; i < nikeys ; ++i) { vl_sift_pix buf [128], rbuf [128] ; double y = *ikeys++ - 1 ; double x = *ikeys++ - 1 ; double s = *ikeys++ ; double th = VL_PI / 2 - *ikeys++ ; vl_sift_calc_raw_descriptor (filt, grad, buf, M, N, x, y, s, th) ; transpose_descriptor (rbuf, buf) ; for (j = 0 ; j < 128 ; ++j) { double x = 512.0 * rbuf [j] ; x = (x < 255.0) ? x : 255.0 ; *descr++ = (vl_uint8) (x) ; } } /* cleanup */ mxDestroyArray (grad_array) ; vl_sift_delete (filt) ; } /* job done */ }
/** @brief MEX entry point */ void mexFunction(int nout, mxArray *out[], int nin, const mxArray *in[]) { enum {IN_I = 0, IN_END } ; enum {OUT_SEEDS = 0, OUT_FRAMES } ; int verbose = 0 ; int opt ; int next = IN_END ; mxArray const *optarg ; /* algorithm parameters */ double delta = -1 ; double max_area = -1 ; double min_area = -1 ; double max_variation = -1 ; double min_diversity = -1 ; int nel ; int ndims ; mwSize const* dims ; vl_mser_pix const *data ; VL_USE_MATLAB_ENV ; /** ----------------------------------------------------------------- ** Check the arguments ** -------------------------------------------------------------- */ if (nin < 1) { mexErrMsgTxt("At least one input argument is required.") ; } if (nout > 2) { mexErrMsgTxt("Too many output arguments."); } if(mxGetClassID(in[IN_I]) != mxUINT8_CLASS) { mexErrMsgTxt("I must be of class UINT8") ; } /* get dimensions */ nel = mxGetNumberOfElements(in[IN_I]) ; ndims = mxGetNumberOfDimensions(in[IN_I]) ; dims = mxGetDimensions(in[IN_I]) ; data = mxGetData(in[IN_I]) ; while ((opt = uNextOption(in, nin, options, &next, &optarg)) >= 0) { switch (opt) { case opt_verbose : ++ verbose ; break ; case opt_delta : if (!uIsRealScalar(optarg) || (delta = *mxGetPr(optarg)) < 0) { mexErrMsgTxt("'Delta' must be non-negative.") ; } break ; case opt_max_area : if (!uIsRealScalar(optarg) || (max_area = *mxGetPr(optarg)) < 0 || max_area > 1) { mexErrMsgTxt("'MaxArea' must be in the range [0,1].") ; } break ; case opt_min_area : if (!uIsRealScalar(optarg) || (min_area = *mxGetPr(optarg)) < 0 || min_area > 1) { mexErrMsgTxt("'MinArea' must be in the range [0,1].") ; } break ; case opt_max_variation : if (!uIsRealScalar(optarg) || (max_variation = *mxGetPr(optarg)) < 0) { mexErrMsgTxt("'MaxVariation' must be non negative.") ; } break ; case opt_min_diversity : if (!uIsRealScalar(optarg) || (min_diversity = *mxGetPr(optarg)) < 0 || min_diversity > 1.0) { mexErrMsgTxt("'MinDiversity' must be in the [0,1] range.") ; } break ; default : assert(0) ; break ; } } /* ----------------------------------------------------------------- * Run algorithm * -------------------------------------------------------------- */ { VlMserFilt *filt ; vl_uint const *regions ; float const *frames ; int i, j, nregions, nframes, dof ; mwSize odims [2] ; double *pt ; /* new filter */ { int * vlDims = mxMalloc(sizeof(int) * ndims) ; for (i = 0 ; i < ndims ; ++i) vlDims [i] = dims [i] ; filt = vl_mser_new (ndims, vlDims) ; mxFree(vlDims) ; } if (!filt) { mexErrMsgTxt("Could not create an MSER filter.") ; } if (delta >= 0) vl_mser_set_delta (filt, (vl_mser_pix) delta) ; if (max_area >= 0) vl_mser_set_max_area (filt, max_area) ; if (min_area >= 0) vl_mser_set_min_area (filt, min_area) ; if (max_variation >= 0) vl_mser_set_max_variation (filt, max_variation) ; if (min_diversity >= 0) vl_mser_set_min_diversity (filt, min_diversity) ; if (verbose) { mexPrintf("mser: parameters:\n") ; mexPrintf("mser: delta = %d\n", vl_mser_get_delta (filt)) ; mexPrintf("mser: max_area = %g\n", vl_mser_get_max_area (filt)) ; mexPrintf("mser: min_area = %g\n", vl_mser_get_min_area (filt)) ; mexPrintf("mser: max_variation = %g\n", vl_mser_get_max_variation (filt)) ; mexPrintf("mser: min_diversity = %g\n", vl_mser_get_min_diversity (filt)) ; } /* process the image */ vl_mser_process (filt, data) ; /* save regions back to array */ nregions = vl_mser_get_regions_num (filt) ; regions = vl_mser_get_regions (filt) ; odims [0] = nregions ; out [OUT_SEEDS] = mxCreateNumericArray (1, odims, mxDOUBLE_CLASS,mxREAL) ; pt = mxGetPr (out [OUT_SEEDS]) ; for (i = 0 ; i < nregions ; ++i) pt [i] = regions [i] + 1 ; /* optionally compute and save ellipsoids */ if (nout > 1) { vl_mser_ell_fit (filt) ; nframes = vl_mser_get_ell_num (filt) ; dof = vl_mser_get_ell_dof (filt) ; frames = vl_mser_get_ell (filt) ; odims [0] = dof ; odims [1] = nframes ; out [OUT_FRAMES] = mxCreateNumericArray (2, odims, mxDOUBLE_CLASS, mxREAL) ; pt = mxGetPr (out [OUT_FRAMES]) ; for (i = 0 ; i < nframes ; ++i) { for (j = 0 ; j < dof ; ++j) { pt [i * dof + j] = frames [i * dof + j] + ((j < ndims)?1.0:0.0) ; } } } if (verbose) { VlMserStats const* s = vl_mser_get_stats (filt) ; int tot = s-> num_extremal ; mexPrintf("mser: statistics:\n") ; mexPrintf("mser: %d extremal regions of which\n", tot) ; #define REMAIN(test,num) \ mexPrintf("mser: %5d (%7.3g %% of previous) " test "\n", \ tot-(num),100.0*(double)(tot-(num))/(tot+VL_EPSILON_D)) ; \ tot -= (num) ; REMAIN("maximally stable,", s-> num_unstable ) ; REMAIN("stable enough,", s-> num_abs_unstable) ; REMAIN("small enough,", s-> num_too_big ) ; REMAIN("big enough,", s-> num_too_small ) ; REMAIN("diverse enough.", s-> num_duplicates ) ; } /* cleanup */ vl_mser_delete (filt) ; } }
/* driver */ void mexFunction(int nout, mxArray *out[], int nin, const mxArray *in[]) { enum {IN_X=0,IN_C,IN_END} ; enum {OUT_ASGN=0} ; vl_uint* asgn ; vl_ikm_acc* centers ; vl_uint8* data ; int M,N,j,K=0 ; int opt ; int next = IN_END ; mxArray const *optarg ; int method_type = VL_IKM_LLOYD ; int verb = 0 ; VlIKMFilt *ikmf ; VL_USE_MATLAB_ENV ; /** ----------------------------------------------------------------- ** Check the arguments ** -------------------------------------------------------------- */ if (nin < 2) { mexErrMsgTxt("At least two arguments required.") ; } else if (nout > 2) { mexErrMsgTxt("Too many output arguments.") ; } if(mxGetClassID(in[IN_X]) != mxUINT8_CLASS) { mexErrMsgTxt("X must be of class UINT8") ; } if(mxGetClassID(in[IN_C]) != mxINT32_CLASS) { mexErrMsgTxt("C must be of class INT32") ; } M = mxGetM(in[IN_X]) ; /* n of components */ N = mxGetN(in[IN_X]) ; /* n of elements */ K = mxGetN(in[IN_C]) ; /* n of centers */ if( mxGetM(in[IN_C]) != M ) { mexErrMsgTxt("DATA and CENTERS must have the same number of columns.") ; } while ((opt = uNextOption(in, nin, options, &next, &optarg)) >= 0) { char buf [1024] ; switch (opt) { case opt_verbose : ++ verb ; break ; case opt_method : if (!uIsString (optarg, -1)) { mexErrMsgTxt("'Method' must be a string.") ; } if (mxGetString (optarg, buf, sizeof(buf))) { mexErrMsgTxt("Option argument too long.") ; } if (strcmp("lloyd", buf) == 0) { method_type = VL_IKM_LLOYD ; } else if (strcmp("elkan", buf) == 0) { method_type = VL_IKM_ELKAN ; } else { mexErrMsgTxt("Unknown cost type.") ; } break ; default : assert(0) ; break ; } } /** ----------------------------------------------------------------- ** Check the arguments ** -------------------------------------------------------------- */ if (verb) { char const * method_name = 0 ; switch (method_type) { case VL_IKM_LLOYD: method_name = "Lloyd" ; break ; case VL_IKM_ELKAN: method_name = "Elkan" ; break ; default : assert (0) ; } mexPrintf("ikmeanspush: Method = %s\n", method_name) ; mexPrintf("ikmeanspush: ndata = %d\n", N) ; } out[OUT_ASGN] = mxCreateNumericMatrix (1, N, mxUINT32_CLASS, mxREAL) ; data = (vl_uint8*) mxGetData (in[IN_X]) ; centers = (vl_ikm_acc*) mxGetData (in[IN_C]) ; asgn = (vl_uint*) mxGetData (out[OUT_ASGN]) ; ikmf = vl_ikm_new (method_type) ; vl_ikm_set_verbosity (ikmf, verb) ; vl_ikm_init (ikmf, centers, M, K) ; vl_ikm_push (ikmf, asgn, data, N) ; /* adjust for MATLAB indexing */ for(j = 0 ; j < N ; ++j) ++ asgn[j] ; vl_ikm_delete (ikmf) ; }
void mexFunction(int nout, mxArray *out[], int nin, const mxArray *in[]) { enum {IN_I=0,IN_END} ; enum {OUT_FRAMES=0, OUT_DESCRIPTORS} ; int verbose = 0 ; int opt ; int next = IN_END ; mxArray const *optarg ; vl_sift_pix const *data ; int M, N ; int O = - 1 ; int S = 3 ; int o_min = 0 ; double edge_thresh = -1 ; double peak_thresh = -1 ; double norm_thresh = -1 ; mxArray *ikeys_array = 0 ; double *ikeys = 0 ; int nikeys = -1 ; vl_bool force_orientations = 0 ; VL_USE_MATLAB_ENV ; /* ----------------------------------------------------------------- * Check the arguments * -------------------------------------------------------------- */ if (nin < 1) { mexErrMsgTxt("One argument required.") ; } else if (nout > 2) { mexErrMsgTxt("Too many output arguments."); } if (mxGetNumberOfDimensions (in[IN_I]) != 2 || mxGetClassID (in[IN_I]) != mxSINGLE_CLASS ) { mexErrMsgTxt("I must be a matrix of class SINGLE") ; } data = (vl_sift_pix*) mxGetData (in[IN_I]) ; M = mxGetM (in[IN_I]) ; N = mxGetN (in[IN_I]) ; while ((opt = uNextOption(in, nin, options, &next, &optarg)) >= 0) { switch (opt) { case opt_verbose : ++ verbose ; break ; case opt_octaves : if (!uIsRealScalar(optarg) || (O = (int) *mxGetPr(optarg)) < 0) { mexErrMsgTxt("'Octaves' must be a positive integer.") ; } break ; case opt_levels : if (! uIsRealScalar(optarg) || (S = (int) *mxGetPr(optarg)) < 1) { mexErrMsgTxt("'Levels' must be a positive integer.") ; } break ; case opt_first_octave : if (!uIsRealScalar(optarg)) { mexErrMsgTxt("'FirstOctave' must be an integer") ; } o_min = (int) *mxGetPr(optarg) ; break ; case opt_edge_thresh : if (!uIsRealScalar(optarg) || (edge_thresh = *mxGetPr(optarg)) < 1) { mexErrMsgTxt("'EdgeThresh' must be not smaller than 1.") ; } break ; case opt_peak_thresh : if (!uIsRealScalar(optarg) || (peak_thresh = *mxGetPr(optarg)) < 0) { mexErrMsgTxt("'PeakThresh' must be a non-negative real.") ; } break ; case opt_norm_thresh : if (!uIsRealScalar(optarg) || (norm_thresh = *mxGetPr(optarg)) < 0) { mexErrMsgTxt("'NormThresh' must be a non-negative real.") ; } break ; case opt_frames : if (!uIsRealMatrix(optarg, 4, -1)) { mexErrMsgTxt("'Frames' must be a 4 x N matrix.x") ; } ikeys_array = mxDuplicateArray (optarg) ; nikeys = mxGetN (optarg) ; ikeys = mxGetPr (ikeys_array) ; if (! check_sorted (ikeys, nikeys)) { qsort (ikeys, nikeys, 4 * sizeof(double), korder) ; } break ; case opt_orientations : force_orientations = 1 ; break ; default : assert(0) ; break ; } } /* ----------------------------------------------------------------- * Do job * -------------------------------------------------------------- */ { VlSiftFilt *filt ; vl_bool first ; double *frames = 0 ; vl_uint8 *descr = 0 ; int nframes = 0, reserved = 0, i,j,q ; /* create a filter to process the image */ filt = vl_sift_new (M, N, O, S, o_min) ; if (peak_thresh >= 0) vl_sift_set_peak_thresh (filt, peak_thresh) ; if (edge_thresh >= 0) vl_sift_set_edge_thresh (filt, edge_thresh) ; if (norm_thresh >= 0) vl_sift_set_norm_thresh (filt, norm_thresh) ; if (verbose) { mexPrintf("siftmx: filter settings:\n") ; mexPrintf("siftmx: octaves (O) = %d\n", vl_sift_get_octave_num (filt)) ; mexPrintf("siftmx: levels (S) = %d\n", vl_sift_get_level_num (filt)) ; mexPrintf("siftmx: first octave (o_min) = %d\n", vl_sift_get_octave_first (filt)) ; mexPrintf("siftmx: edge thresh = %g\n", vl_sift_get_edge_thresh (filt)) ; mexPrintf("siftmx: peak thresh = %g\n", vl_sift_get_peak_thresh (filt)) ; mexPrintf("siftmx: norm thresh = %g\n", vl_sift_get_norm_thresh (filt)) ; mexPrintf((nikeys >= 0) ? "siftmx: will source frames? yes (%d)\n" : "siftmx: will source frames? no\n", nikeys) ; mexPrintf("siftmx: will force orientations? %s\n", force_orientations ? "yes" : "no") ; } /* ............................................................... * Process each octave * ............................................................ */ i = 0 ; first = 1 ; while (true) { int err ; VlSiftKeypoint const *keys = 0 ; int nkeys = 0 ; if (verbose) { mexPrintf ("siftmx: processing octave %d\n", vl_sift_get_octave_index (filt)) ; } /* Calculate the GSS for the next octave .................... */ if (first) { err = vl_sift_process_first_octave (filt, data) ; first = 0 ; } else { err = vl_sift_process_next_octave (filt) ; } if (err) break ; if (verbose > 1) { printf("siftmx: GSS octave %d computed\n", vl_sift_get_octave_index (filt)); } /* Run detector ............................................. */ if (nikeys < 0) { vl_sift_detect (filt) ; keys = vl_sift_get_keypoints (filt) ; nkeys = vl_sift_get_keypoints_num (filt) ; i = 0 ; if (verbose > 1) { printf ("siftmx: detected %d (unoriented) keypoints\n", nkeys) ; } } else { nkeys = nikeys ; } /* For each keypoint ........................................ */ for (; i < nkeys ; ++i) { double angles [4] ; int nangles ; VlSiftKeypoint ik ; VlSiftKeypoint const *k ; /* Obtain keypoint orientations ........................... */ if (nikeys >= 0) { vl_sift_keypoint_init (filt, &ik, ikeys [4 * i + 1] - 1, ikeys [4 * i + 0] - 1, ikeys [4 * i + 2]) ; if (ik.o != vl_sift_get_octave_index (filt)) { break ; } k = &ik ; /* optionally compute orientations too */ if (force_orientations) { nangles = vl_sift_calc_keypoint_orientations (filt, angles, k) ; } else { angles [0] = VL_PI / 2 - ikeys [4 * i + 3] ; nangles = 1 ; } } else { k = keys + i ; nangles = vl_sift_calc_keypoint_orientations (filt, angles, k) ; } /* For each orientation ................................... */ for (q = 0 ; q < nangles ; ++q) { vl_sift_pix buf [128] ; vl_sift_pix rbuf [128] ; /* compute descriptor (if necessary) */ if (nout > 1) { vl_sift_calc_keypoint_descriptor (filt, buf, k, angles [q]) ; transpose_descriptor (rbuf, buf) ; } /* make enough room for all these keypoints and more */ if (reserved < nframes + 1) { reserved += 2 * nkeys ; frames = mxRealloc (frames, 4 * sizeof(double) * reserved) ; if (nout > 1) { descr = mxRealloc (descr, 128 * sizeof(double) * reserved) ; } } /* Save back with MATLAB conventions. Notice tha the input * image was the transpose of the actual image. */ frames [4 * nframes + 0] = k -> y + 1 ; frames [4 * nframes + 1] = k -> x + 1 ; frames [4 * nframes + 2] = k -> sigma ; frames [4 * nframes + 3] = VL_PI / 2 - angles [q] ; if (nout > 1) { for (j = 0 ; j < 128 ; ++j) { double x = 512.0 * rbuf [j] ; x = (x < 255.0) ? x : 255.0 ; descr [128 * nframes + j] = (vl_uint8) (x) ; } } ++ nframes ; } /* next orientation */ } /* next keypoint */ } /* next octave */ if (verbose) { mexPrintf ("siftmx: found %d keypoints\n", nframes) ; } /* ............................................................... * Save back * ............................................................ */ { int dims [2] ; /* create an empty array */ dims [0] = 0 ; dims [1] = 0 ; out[OUT_FRAMES] = mxCreateNumericArray (2, dims, mxDOUBLE_CLASS, mxREAL) ; /* set array content to be the frames buffer */ dims [0] = 4 ; dims [1] = nframes ; mxSetDimensions (out[OUT_FRAMES], dims, 2) ; mxSetPr (out[OUT_FRAMES], frames) ; if (nout > 1) { /* create an empty array */ dims [0] = 0 ; dims [1] = 0 ; out[OUT_DESCRIPTORS]= mxCreateNumericArray (2, dims, mxUINT8_CLASS, mxREAL) ; /* set array content to be the descriptors buffer */ dims [0] = 128 ; dims [1] = nframes ; mxSetDimensions (out[OUT_DESCRIPTORS], dims, 2) ; mxSetData (out[OUT_DESCRIPTORS], descr) ; } } /* cleanup */ vl_sift_delete (filt) ; if (ikeys_array) mxDestroyArray(ikeys_array) ; } /* end: do job */ }
/* driver */ void mexFunction(int nout, mxArray *out[], int nin, const mxArray *in[]) { typedef int unsigned data_t ; /* mxClassID data_class = mxINT8_CLASS ;*/ enum {IN_S1,IN_S2} ; enum {OUT_D=0} ; int L,N1,N2 ; int sparse = 0 ; void const * s1_pt ; void const * s2_pt ; mxClassID data_class ; mxClassID acc_class ; mwSize dims [2] ; /* for option parsing */ bool self = 1 ; /* called with one numeric argument? */ int norm = opt_L2 ; /* type of norm to be computed */ int opt ; int next = 1 ; mxArray const *optarg ; /** ----------------------------------------------------------------- ** Check the arguments ** -------------------------------------------------------------- */ if (nout > 1) { mexErrMsgTxt("Too many output arguments."); } if (nin < 1) { mexErrMsgTxt("At leat one argument required.") ; } if(! mxIsNumeric(in[IN_S1])) { mexErrMsgTxt ("X must be numeric") ; } if (nin >= 2 && mxIsNumeric(in[IN_S2])) { self = 0 ; next = 2 ; } sparse = mxIsSparse(in[IN_S1]) ; if (sparse && nin >=2 && mxIsNumeric(in[IN_S2])) { if (! mxIsSparse(in[IN_S2])) { mexErrMsgTxt ("X and Y must be either both full or sparse.") ; } } while ((opt = uNextOption(in, nin, options, &next, &optarg)) >= 0) { switch (opt) { case opt_LINF : case opt_L2 : case opt_L1 : case opt_L0 : case opt_CHI2 : case opt_HELL : case opt_KL2 : case opt_KL1 : case opt_KCHI2 : case opt_KHELL : case opt_MIN : norm = opt ; break ; default: assert(0) ; } } data_class = mxGetClassID(in[IN_S1]) ; if ((!self) && data_class != mxGetClassID(in[IN_S2])) { mexErrMsgTxt("X and Y must have the same numeric class") ; } assert ((! sparse) || (data_class == mxDOUBLE_CLASS)) ; L = mxGetM(in[IN_S1]) ; N1 = mxGetN(in[IN_S1]) ; N2 = self ? N1 : mxGetN(in[IN_S2]) ; dims[0] = N1 ; dims[1] = N2 ; if ((!self) && L != mxGetM(in[IN_S2])) { mexErrMsgTxt("X and Y must have the same number of rows") ; } s1_pt = mxGetData(in[IN_S1]) ; s2_pt = self ? s1_pt : mxGetData(in[IN_S2]) ; #define DISPATCH_CLASS(NORM, DC,AC) \ case mx ## DC ## _CLASS : \ acc_class = mx ## AC ## _CLASS ; \ out[OUT_D] = mxCreateNumericArray(2,dims,acc_class,mxREAL) ; \ dist ## NORM ## _ ## DC ## _ ## AC \ ( (AC ## _t *)mxGetData(out[OUT_D]), \ (DC ## _t *)s1_pt, \ (DC ## _t *)s2_pt, \ L, N1, N2, \ self ) ; \ break ; #define DISPATCH_NORM(NORM) \ case opt_ ## NORM : \ if (sparse) { \ out[OUT_D] = mxCreateNumericArray(2,dims,mxDOUBLE_CLASS,mxREAL) ; \ CORE_SPARSE(NORM, VL_XCAT(F_, NORM)) \ } else { \ switch (data_class) { \ DISPATCH_CLASS(NORM, UINT8 , UINT32) \ DISPATCH_CLASS(NORM, INT8 , INT32) \ DISPATCH_CLASS(NORM, UINT16, UINT32) \ DISPATCH_CLASS(NORM, INT16, INT32) \ DISPATCH_CLASS(NORM, UINT32, UINT32) \ DISPATCH_CLASS(NORM, INT32, INT32) \ DISPATCH_CLASS(NORM, SINGLE, SINGLE) \ DISPATCH_CLASS(NORM, DOUBLE,DOUBLE) \ default: \ mexErrMsgTxt("Data class not supported!") ; \ } \ } \ break ; switch (norm) { DISPATCH_NORM(LINF ) ; DISPATCH_NORM(L2 ) ; DISPATCH_NORM(L1 ) ; DISPATCH_NORM(L0 ) ; DISPATCH_NORM(CHI2 ) ; DISPATCH_NORM(HELL ) ; DISPATCH_NORM(KL2 ) ; DISPATCH_NORM(KL1 ) ; DISPATCH_NORM(KCHI2) ; DISPATCH_NORM(KHELL) ; DISPATCH_NORM(MIN ) ; default: assert(0) ; } }