vl_ihashfind.c
Go to the documentation of this file.
00001 
00007 /*
00008 Copyright (C) 2007-12 Andrea Vedaldi and Brian Fulkerson.
00009 All rights reserved.
00010 
00011 This file is part of the VLFeat library and is made available under
00012 the terms of the BSD license (see the COPYING file).
00013 */
00014 
00015 #include <mexutils.h>
00016 #include <vl/generic.h>
00017 
00018 #include <string.h>
00019 
00020 /* hash function */
00021 unsigned int fnv_hash (void const *key, int len)
00022 {
00023   unsigned char const *p = key;
00024   unsigned int h = 2166136261U ;
00025   int i;
00026 
00027   for ( i = 0; i < len; i++ )
00028     h = ( h * 16777619 ) ^ p[i];
00029 
00030   return h;
00031 }
00032 
00033 int
00034 is_null (vl_uint8 const * x, int n)
00035 {
00036   int i ;
00037   for (i = 0 ; i < n ; ++i) {
00038     if (x[i]) return 0 ;
00039   }
00040   return 1 ;
00041 }
00042 
00043 int
00044 is_equal (vl_uint8 const * x, vl_uint8 const * y, int n)
00045 {
00046   int i ;
00047   for (i = 0 ; i < n ; ++i) {
00048     if (x[i] != y[i]) return 0 ;
00049   }
00050   return 1 ;
00051 }
00052 
00053 void
00054 cpy (vl_uint8 * x, vl_uint8 const * y, int n)
00055 {
00056   int i ;
00057   for (i = 0 ; i < n ; ++i){
00058     /*    mexPrintf("cpy:%d %d\n",x[i],y[i]);*/
00059     x[i] = y[i] ;
00060   }
00061 }
00062 
00070 void
00071 mexFunction(int nout, mxArray *out[],
00072             int nin, const mxArray *in[])
00073 {
00074   enum { IN_ID, IN_NEXT, IN_K, IN_X } ;
00075   enum { OUT_SEL } ;
00076 
00077   vl_uint32 const * next ;
00078   vl_uint32 * sel ;
00079   vl_uint8 const  * id ;
00080   vl_uint8 const  * x ;
00081 
00082   unsigned int K, i, N, res, last, ndims ;
00083 
00084   /* -----------------------------------------------------------------
00085    *                                                   Check arguments
00086    * -------------------------------------------------------------- */
00087 
00088   if( nin != 4 ) {
00089     mexErrMsgTxt("Four arguments required") ;
00090   } else if (nout > 1) {
00091     mexErrMsgTxt("At most one output argument.") ;
00092   }
00093 
00094   if(! mxIsNumeric(in[IN_NEXT])|| mxGetClassID(in[IN_NEXT])!= mxUINT32_CLASS) {
00095     mexErrMsgTxt("NEXT must be UINT32.") ;
00096   }
00097 
00098   if(! mxIsNumeric(in[IN_X])   || mxGetClassID(in[IN_X])!= mxUINT8_CLASS) {
00099     mexErrMsgTxt("X must be UINT8") ;
00100   }
00101 
00102   if (mxGetM(in[IN_NEXT]) != 1) {
00103     mexErrMsgTxt("NEXT must be a row vector") ;
00104   }
00105 
00106   if(! mxIsNumeric(in[IN_ID])  || mxGetClassID(in[IN_ID])!= mxUINT8_CLASS) {
00107     mexErrMsgTxt("ID must be UINT8.") ;
00108   }
00109 
00110   ndims = mxGetM(in[IN_ID]) ;
00111   res   = mxGetN(in[IN_ID]) ;
00112 
00113   if(res != mxGetN(in[IN_NEXT])) {
00114     mexErrMsgTxt("ID, NEXT must have the same number of columns") ;
00115   }
00116 
00117   if(ndims != mxGetM(in[IN_X])) {
00118     mexErrMsgTxt("ID and X must havethe same number of rows") ;
00119   }
00120 
00121   if(! vlmxIsPlainScalar(in[IN_K])) {
00122     mexErrMsgTxt("K must be a scalar") ;
00123   }
00124   K     = (unsigned int) *mxGetPr(in[IN_K]) ;
00125 
00126   N    = mxGetN(in[IN_X]) ;
00127   id   = mxGetData(in[IN_ID]) ;
00128   next = mxGetData(in[IN_NEXT]) ;
00129   x    = mxGetData(in[IN_X]) ;
00130 
00131   out[OUT_SEL] = mxCreateNumericMatrix
00132     (1, N, mxUINT32_CLASS, mxREAL) ;
00133 
00134   sel = mxGetData (out[OUT_SEL]) ;
00135   /* search for last occupied slot */
00136   last = res ;
00137   for (i = 0 ; i < res ; ++i) last = VL_MAX(last, next [i]) ;
00138 
00139   /* REMARK: last and next are 1 based */
00140 
00141   if (K > res) {
00142     mexErrMsgTxt("K cannot be larger then the size of H") ;
00143   }
00144   if (last > res) {
00145     mexErrMsgTxt("An element of NEXT is greater than the size of the table") ;
00146   }
00147 
00148   /* -----------------------------------------------------------------
00149    *                                                            Do job
00150    * -------------------------------------------------------------- */
00151 
00152   for (i = 0 ; i < N ; ++i) {
00153     /* hash */
00154     unsigned int h1, h2 ;
00155     unsigned int j, p = 0 ;
00156 
00157     if (is_null (x + i * ndims, ndims)) {
00158       *sel++ = 0 ;
00159       continue ;
00160     }
00161 
00162     h1 = fnv_hash(x + i * ndims, ndims) % K ;
00163     h2 = h1 | 0x1 ; /* this needs to be odd */
00164 
00165     /* search first free or matching position */
00166     p = h1 % K ;
00167     for (j = 0 ; j < K ; ++j) {
00168       if (is_null (id + p * ndims,                ndims) ||
00169           is_equal(id + p * ndims, x + i * ndims, ndims)) break ;
00170       h1 += h2 ;
00171       p = h1 % K ;
00172     }
00173 
00174     /* handle extended table */
00175     while (! is_null (id + p * ndims,                ndims) &&
00176            ! is_equal(id + p * ndims, x + i * ndims, ndims)) {
00177       if (next[p] == 0) break ;
00178       p = next [p] - 1 ;
00179     }
00180 
00181     /* found or not ? */
00182     if (is_equal(id + p * ndims, x + i * ndims, ndims)) {
00183       /* found */
00184       *sel++ = p + 1 ;
00185     } else {
00186       /* not found */
00187       *sel++ = 0 ;
00188     }
00189   } /* next guy to search for */
00190 }


libvlfeat
Author(s): Andrea Vedaldi
autogenerated on Thu Jun 6 2019 20:25:51