Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00018 #include <mexutils.h>
00019
00020 #include <stdio.h>
00021 #include <stdlib.h>
00022 #include <math.h>
00023 #include <string.h>
00024 #include <assert.h>
00025
00026 #define MIN(x,y) (((x)<(y))?(x):(y))
00027 #define MAX(x,y) (((x)>(y))?(x):(y))
00028
00029 typedef char unsigned val_t ;
00030 typedef int idx_t ;
00031 typedef vl_uint64 acc_t ;
00032
00033
00034 void
00035 adv(mwSize const* dims, int ndims, int* subs_pt)
00036 {
00037 int d = 0 ;
00038 while(d < ndims) {
00039 if( ++subs_pt[d] < (signed) dims[d] ) return ;
00040 subs_pt[d++] = 0 ;
00041 }
00042 }
00043
00044
00045 void
00046 mexFunction(int nout, mxArray *out[],
00047 int nin, const mxArray *in[])
00048 {
00049
00050 enum {IN_I=0, IN_ER} ;
00051 enum {OUT_MEMBERS} ;
00052
00053 idx_t i ;
00054 int k, nel, ndims ;
00055 mwSize const * dims ;
00056 val_t const * I_pt ;
00057 int last = 0 ;
00058 int last_expanded = 0 ;
00059 val_t value = 0 ;
00060
00061 double const * er_pt ;
00062
00063 int* subs_pt ;
00064 int* nsubs_pt ;
00065 idx_t* strides_pt ;
00066 val_t* visited_pt ;
00067 idx_t* members_pt ;
00068 bool invert = VL_FALSE ;
00069
00073 if (nin != 2) {
00074 mexErrMsgTxt("Two arguments required.") ;
00075 } else if (nout > 4) {
00076 mexErrMsgTxt("Too many output arguments.");
00077 }
00078
00079 if(mxGetClassID(in[IN_I]) != mxUINT8_CLASS) {
00080 mexErrMsgTxt("I must be of class UINT8.") ;
00081 }
00082
00083 if(!vlmxIsPlainScalar(in[IN_ER])) {
00084 mexErrMsgTxt("ER must be a DOUBLE scalar.") ;
00085 }
00086
00087
00088 nel = mxGetNumberOfElements(in[IN_I]) ;
00089 ndims = mxGetNumberOfDimensions(in[IN_I]) ;
00090 dims = mxGetDimensions(in[IN_I]) ;
00091 I_pt = mxGetData(in[IN_I]) ;
00092
00093
00094 subs_pt = mxMalloc( sizeof(int) * ndims ) ;
00095 nsubs_pt = mxMalloc( sizeof(int) * ndims ) ;
00096 strides_pt = mxMalloc( sizeof(idx_t) * ndims ) ;
00097 visited_pt = mxMalloc( sizeof(val_t) * nel ) ;
00098 members_pt = mxMalloc( sizeof(idx_t) * nel ) ;
00099
00100 er_pt = mxGetPr(in[IN_ER]) ;
00101
00102
00103 strides_pt [0] = 1 ;
00104 for(k = 1 ; k < ndims ; ++k) {
00105 strides_pt [k] = strides_pt [k-1] * dims [k-1] ;
00106 }
00107
00108
00109 memset(visited_pt, 0, sizeof(val_t) * nel) ;
00110 {
00111 idx_t idx = (idx_t) *er_pt ;
00112 if (idx < 0) {
00113 idx = -idx;
00114 invert = VL_TRUE ;
00115 }
00116 if( idx < 1 || idx > nel ) {
00117 char buff[80] ;
00118 snprintf(buff,80,"ER=%d out of range [1,%d]",idx,nel) ;
00119 mexErrMsgTxt(buff) ;
00120 }
00121 members_pt [last++] = idx - 1 ;
00122 }
00123 value = I_pt[ members_pt[0] ] ;
00124
00125
00126
00127
00128 while(last_expanded < last) {
00129
00130
00131 idx_t index = members_pt[last_expanded++] ;
00132
00133
00134
00135 {
00136 idx_t temp = index ;
00137 for(k = ndims-1 ; k >=0 ; --k) {
00138 nsubs_pt [k] = -1 ;
00139 subs_pt [k] = temp / strides_pt [k] ;
00140 temp = temp % strides_pt [k] ;
00141 }
00142 }
00143
00144
00145 while(VL_TRUE) {
00146 int good = VL_TRUE ;
00147 idx_t nindex = 0 ;
00148
00149
00150
00151 for(k = 0 ; k < ndims && good ; ++k) {
00152 int temp = nsubs_pt [k] + subs_pt [k] ;
00153 good &= 0 <= temp && temp < (signed) dims[k] ;
00154 nindex += temp * strides_pt [k] ;
00155 }
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 if(good
00166 && nindex != index
00167 && ((!invert && I_pt [nindex] <= value) ||
00168 ( invert && I_pt [nindex] >= value))
00169 && ! visited_pt [nindex] ) {
00170
00171
00172 visited_pt [nindex] = 1 ;
00173
00174
00175 members_pt [last++] = nindex ;
00176 }
00177
00178
00179 k = 0 ;
00180 while(++ nsubs_pt [k] > 1) {
00181 nsubs_pt [k++] = -1 ;
00182 if(k == ndims) goto done_all_neighbors ;
00183 }
00184 }
00185 done_all_neighbors : ;
00186 }
00187
00188
00189
00190
00191 {
00192 mwSize dims[2] ;
00193 int unsigned * pt ;
00194 dims[0] = last ;
00195 out[OUT_MEMBERS] = mxCreateNumericArray(1,dims,mxUINT32_CLASS,mxREAL);
00196 pt = mxGetData(out[OUT_MEMBERS]) ;
00197 for (i = 0 ; i < last ; ++i) {
00198 *pt++ = members_pt[i] + 1 ;
00199 }
00200 }
00201
00202
00203 mxFree( members_pt ) ;
00204 mxFree( visited_pt ) ;
00205 mxFree( strides_pt ) ;
00206 mxFree( nsubs_pt ) ;
00207 mxFree( subs_pt ) ;
00208 }