Go to the documentation of this file.00001
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include <mexutils.h>
00016 #include <vl/generic.h>
00017
00018 #include <string.h>
00019
00020
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
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
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
00136 last = res ;
00137 for (i = 0 ; i < res ; ++i) last = VL_MAX(last, next [i]) ;
00138
00139
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
00150
00151
00152 for (i = 0 ; i < N ; ++i) {
00153
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 ;
00164
00165
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
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
00182 if (is_equal(id + p * ndims, x + i * ndims, ndims)) {
00183
00184 *sel++ = p + 1 ;
00185 } else {
00186
00187 *sel++ = 0 ;
00188 }
00189 }
00190 }