/* maxheap version */ static void fvec_k_min_maxheap (const float *val, int n, int *idx, int k) { fbinheap_t *mh = fbinheap_new (k); int i; for (i = 0; i < n; i++) fbinheap_add (mh, i, val[i]); /* -val because we want maxes instead of mins */ fbinheap_sort_labels (mh, idx); fbinheap_delete (mh); }
void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray*prhs[]) { if (nrhs != 4) mexErrMsgTxt ("Invalid number of input arguments: either 2 for initialization or 4 for feeding the heap"); if (nlhs != 2) mexErrMsgTxt ("2 output arguments are expected"); if (mxGetClassID(ARGIN_VAL) != mxSINGLE_CLASS || mxGetClassID(ARGIN_VALH) != mxSINGLE_CLASS) mexErrMsgTxt ("need single precision array for values"); if (mxGetClassID(ARGIN_IDS) != mxUINT32_CLASS || mxGetClassID(ARGIN_IDSH) != mxUINT32_CLASS) mexErrMsgTxt ("need uint32 arrays for indices"); /* Variables defining the heap */ int k = mxGetM (ARGIN_VALH); /* Number of neighbors for the heap */ int nh = mxGetN (ARGIN_VALH); /* Number of heaps */ if (mxGetM(ARGIN_IDSH) != k || mxGetN (ARGIN_IDSH) != nh) mexErrMsgTxt ("Inconsistent sizes for the heap parameters"); /* Values to be considered for being added in the heap */ int n = mxGetM (ARGIN_VAL); int nh2 = mxGetN (ARGIN_VAL); if (mxGetM(ARGIN_IDS) != n || mxGetN (ARGIN_IDS) != 1 || nh2 != nh) mexErrMsgTxt ("Invalid sizes for the values/indexes to be added"); /* Pointer to the data to manipulate */ float * val = (float*) mxGetPr (ARGIN_VAL); int * ids = (int*) mxGetPr (ARGIN_IDS); /* Produce output heap and populate it */ ARGOUT_VAL = mxCreateNumericMatrix (k, nh, mxSINGLE_CLASS, mxREAL); ARGOUT_IDS = mxCreateNumericMatrix (k, nh, mxUINT32_CLASS, mxREAL); float * bh_val = (float*) mxGetPr (ARGOUT_VAL); int * bh_ids = (int*) mxGetPr (ARGOUT_IDS); memcpy (bh_val, mxGetPr (ARGIN_VALH), k * nh * sizeof (*bh_val)); memcpy (bh_ids, mxGetPr (ARGIN_IDSH), k * nh * sizeof (*bh_ids)); int i, j; for (j = 0 ; j < nh ; j++) fbinheap_add (k, bh_val + j * k, bh_ids + j * k, n, val + j * n, ids); }
int merge_ordered_sets (const int **labels,const float **vals, const int *sizes,int k, int **labels_out,float **vals_out) { int i,j; int n_out = ivec_sum (sizes, k); int *all_labels = ivec_new (n_out); float *all_vals = fvec_new (n_out); /* Maxheap: * * maxheap label = index of table in 0..k-1 * * maxheap val = - (label from labels table) * * If maxheap val does not fit in a float (if label>2**24), it * triggers an assertion. Time to implement a maxheap with int * values... */ fbinheap_t *mh = fbinheap_new(k); /* current index on table k */ int indices[k]; for ( i = 0 ; i < k ; i++) { if (sizes[i] == 0) continue; indices[i] = 0; int label = labels[i][0]; float mh_val = -label; assert ((int)(-mh_val) == label || !"lost precision in int->float conversion"); fbinheap_add (mh, i, mh_val); } int all_i = 0; while (mh->k>0) { /* smallest available label */ i = mh->label[1]; /* index of table */ j = (int)(-mh->val[1]); /* label */ /* I don't dare compiling with -DNDEBUG */ /* assert(j==labels[i][indices[i]]); */ all_labels[all_i] = j; all_vals[all_i] = vals[i][indices[i]]; all_i++; /* remove handled label */ fbinheap_pop (mh); indices[i]++; if (indices[i] < sizes[i]) { /* push next label from this table */ int label = labels[i][indices[i]]; float mh_val = -label; assert ((int)(-mh_val) == label || !"lost precision in int->float conversion"); fbinheap_add (mh, i, mh_val); } } fbinheap_delete (mh); assert (all_i == n_out); *labels_out = all_labels; *vals_out = all_vals; return n_out; }