/* Exported functions. */ void fbinheap_add (int k, float * bh_val, int * bh_label, int n, const float * v, const int * label) { int i; bh_val--; /* don't ask why */ bh_label--; float lim=bh_val[1]; for (i = 0 ; i < n; i++) { if(v[i]<lim) { fbinheap_pop (k, bh_val, bh_label); fbinheap_push (k, bh_val, bh_label, v[i], label[i]); lim=bh_val[1]; } } }
void fbinheap_add_label_range (int k, float * bh_val, int * bh_label, int label0, int n, const float * v) { int i; bh_val--; bh_label--; float lim=bh_val[1]; for (i = 0 ; i < n; i++) { /* optimized loop for common case */ if(v[i]<lim) { fbinheap_pop (k, bh_val, bh_label); fbinheap_push (k, bh_val, bh_label, label0+i, v[i]); lim=bh_val[1]; } } }
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; }