int main (int argc, char** argv) { float * X ; float * Y ; vl_size numDimensions = 1000 ; vl_size numSamples = 2000 ; float * result = vl_malloc (sizeof(float) * numSamples * numSamples) ; VlFloatVectorComparisonFunction f ; init_data (numDimensions, numSamples, &X, &Y) ; X+=1 ; Y+=1 ; vl_set_simd_enabled (VL_FALSE) ; f = vl_get_vector_comparison_function_f (VlDistanceL2) ; vl_tic () ; vl_eval_vector_comparison_on_all_pairs_f (result, numDimensions, X, numSamples, Y, numSamples, f) ; VL_PRINTF("Float L2 distnace: %.3f s\n", vl_toc ()) ; vl_set_simd_enabled (VL_TRUE) ; f = vl_get_vector_comparison_function_f (VlDistanceL2) ; vl_tic () ; vl_eval_vector_comparison_on_all_pairs_f (result, numDimensions, X, numSamples, Y, numSamples, f) ; VL_PRINTF("Float L2 distance (SIMD): %.3f s\n", vl_toc ()) ; X-- ; Y-- ; vl_free (X) ; vl_free (Y) ; vl_free (result) ; return 0 ; }
/* driver */ void mexFunction(int nout, mxArray *out[], int nin, const mxArray *in[]) { typedef int unsigned data_t ; vl_bool autoComparison = VL_TRUE ; VlVectorComparisonType comparisonType = VlDistanceL2 ; enum {IN_X = 0, IN_Y} ; enum {OUT_D = 0} ; mwSize numDataX = 0 ; mwSize numDataY = 0 ; mwSize dimension ; mxClassID classId ; /* for option parsing */ int opt ; int next ; mxArray const *optarg ; VL_USE_MATLAB_ENV ; if (nout > 1) { vlmxError(vlmxErrTooManyOutputArguments, NULL) ; } if (nin < 1) { vlmxError(vlmxErrNotEnoughInputArguments, NULL) ; } if (! (vlmxIsMatrix (in[IN_X],-1,-1) && vlmxIsReal(in[IN_X]))) { vlmxError(vlmxErrInvalidArgument, "X must be a real matrix.") ; } next = 1 ; classId = mxGetClassID(in[IN_X]) ; dimension = mxGetM(in[IN_X]) ; numDataX = mxGetN(in[IN_X]) ; if (nin > 1 && vlmxIsMatrix (in[IN_Y],-1,-1) && vlmxIsReal(in[IN_Y])) { next = 2 ; autoComparison = VL_FALSE ; numDataY = mxGetN(in[IN_Y]) ; if (mxGetClassID(in[IN_Y]) != classId) { vlmxError(vlmxErrInvalidArgument, "X and Y must have the same class.") ; } if (dimension != mxGetM(in[IN_Y])) { vlmxError(vlmxErrInvalidArgument, "X and Y must have the same number of rows.") ; } } if (classId != mxSINGLE_CLASS && classId != mxDOUBLE_CLASS) { vlmxError(vlmxErrInvalidArgument, "X must be either of class SINGLE or DOUBLE."); } while ((opt = vlmxNextOption (in, nin, options, &next, &optarg)) >= 0) { switch (opt) { case opt_L2 : comparisonType = VlDistanceL2 ; break ; case opt_L1 : comparisonType = VlDistanceL1 ; break ; case opt_CHI2 : comparisonType = VlDistanceChi2 ; break ; case opt_HELL : comparisonType = VlDistanceHellinger ; break ; case opt_JS : comparisonType = VlDistanceJS ; break ; case opt_KL2 : comparisonType = VlKernelL2 ; break ; case opt_KL1 : comparisonType = VlKernelL1 ; break ; case opt_KCHI2 : comparisonType = VlKernelChi2 ; break ; case opt_KHELL : comparisonType = VlKernelHellinger ; break ; case opt_KJS : comparisonType = VlKernelJS ; break ; default: abort() ; } } /* allocate output */ { mwSize dims [2] ; dims[0] = numDataX ; dims[1] = autoComparison ? numDataX : numDataY ; out[OUT_D] = mxCreateNumericArray (2, dims, classId, mxREAL) ; } /* If either numDataX or numDataY are null, their data pointers are null as well. This may confuse vl_eval_vector_comparison_on_all_pairs_*, so we intercept this as a special case. The same is true if dimension is null. */ if (numDataX == 0 || (! autoComparison && numDataY == 0)) { return ; } if (dimension == 0) { return ; } /* make calculation */ switch (classId) { case mxSINGLE_CLASS: { VlFloatVectorComparisonFunction f = vl_get_vector_comparison_function_f (comparisonType) ; if (autoComparison) { vl_eval_vector_comparison_on_all_pairs_f ((float*)mxGetData(out[OUT_D]), dimension, (float*)mxGetData(in[IN_X]), numDataX, 0, 0, f) ; } else { vl_eval_vector_comparison_on_all_pairs_f ((float*)mxGetData(out[OUT_D]), dimension, (float*)mxGetData(in[IN_X]), numDataX, (float*)mxGetData(in[IN_Y]), numDataY, f) ; } } break ; case mxDOUBLE_CLASS: { VlDoubleVectorComparisonFunction f = vl_get_vector_comparison_function_d (comparisonType) ; if (autoComparison) { vl_eval_vector_comparison_on_all_pairs_d ((double*)mxGetData(out[OUT_D]), dimension, (double*)mxGetData(in[IN_X]), numDataX, 0, 0, f) ; } else { vl_eval_vector_comparison_on_all_pairs_d ((double*)mxGetData(out[OUT_D]), dimension, (double*)mxGetData(in[IN_X]), numDataX, (double*)mxGetData(in[IN_Y]), numDataY, f) ; } } break ; default: abort() ; } }