void heap_heapify(heap_t* h, int i) { int l, r; int largest; double tmp; double* tmp_data; // FIXME: void* if (i < h->len/2) { l = HEAP_LEFT(i); r = HEAP_RIGHT(i); if((l < h->len) && (h->A[l] > h->A[i])) largest = l; else largest = i; if((r < h->len) && (h->A[r] > h->A[largest])) largest = r; if(largest != i) { tmp = h->A[i]; tmp_data = h->data[i]; h->A[i] = h->A[largest]; h->data[i] = h->data[largest]; h->A[largest] = tmp; h->data[largest] = tmp_data; heap_heapify(h,largest); } } }
void heap_deletehead (void *heap, int size, int *num, heap_comp hc) { (*num)--; SWAP (size, heap, (char *) heap + *num * size); heap_heapify (heap, size, *num, 1, hc); }
/************************************************************************ * * NOTE: If you choose to change the comparison function the first thing * you do after changing the function is call heap_build. * */ void heap_build (void *heap, int size, int num, heap_comp hc) { register int i; for (i = num / 2; i > 0; i--) heap_heapify (heap, size, num, i, hc); }
static int heap_heapify(Heap *h,int idx) { int l,r,largest; HeapInternCmp cmp_func; DBG(debug("heap_heapify(h=%p,idx=%d)\n",h,idx)); l = HLEFT(idx); r = HRIGHT(idx); LLOG(l); LLOG(r); if (h->hpMode == HEAP_MAXIMIZE) cmp_func = heap_larger; else cmp_func = heap_smaller; if (l <= HSIZE(h) && cmp_func(h,HARRAY(h,l),HARRAY(h,idx))) largest = l; else largest = idx; if (r <= HSIZE(h) && cmp_func(h,HARRAY(h,r),HARRAY(h,largest))) largest = r; if (largest != idx) { heap_swap(h,idx,largest); return heap_heapify(h,largest); } return 0; }
void test_heapify(void) { size_t i; /* initialize data */ int *array = zmalloc(sizeof(int) * LOTS_OF_INTS); int sum = 0; for (i = 0; i < LOTS_OF_INTS; i++) { array[i] = random() % 123456789; sum += array[i]; } /* construct a heap from our random array */ heap_t *h = heap_heapify(array, LOTS_OF_INTS, sizeof(int), NULL, (cmp_func_t)intcmp); assert(heap_size(h) == LOTS_OF_INTS); int ctrlsum = 0, maxctrl, *e; /* peek head */ if (heap_size(h)) maxctrl = *(int*)heap_get(h, 0); while (heap_size(h)) { e = heap_pop(h); ctrlsum += *e; /* check that elements are in heap order */ assert(*e <= maxctrl); maxctrl = *e; } assert(ctrlsum == sum); heap_destroy(h); free(array); }
static void heap_heapify(struct heap *h, unsigned int i) { unsigned int l, r, smallest; struct heapitem *tmp; l = (2 * i) + 1; /* left child */ r = l + 1; /* right child */ if ((l < h->size) && h->cmp(h->map[l], h->map[i])) smallest = l; else smallest = i; if ((r < h->size) && h->cmp(h->map[r], h->map[smallest])) smallest = r; if (smallest == i) return; /* exchange to maintain heap property */ tmp = h->map[smallest]; h->map[smallest] = h->map[i]; h->map[smallest]->index = smallest; h->map[i] = tmp; h->map[i]->index = i; heap_heapify(h, smallest); }
int heap_build( heap_t *heap_in ) { long j = ( heap_in->size >> 1 ); /* divide by 2... kind of */ while( j >= 0 ) { heap_heapify( heap_in, j ); --j; } return 0; }
/**************************************************** * * NOTE : The heap must be built before heap_sort is called. * This has the effect of reversing the order of the array. * e.g. if your comparison function is designed to pull the * biggest thing off the heap first then the result of * sorting with this function will be to put the bigest * thing at the end of the array. * */ void heap_sort (void *heap, int size, int num, heap_comp hc) { register int i; for (i = num; i > 1; i--) { SWAP (size, heap, (char *) heap + (i - 1) * size); heap_heapify (heap, size, i - 1, 1, hc); } }
void* heap_extract_max(heap_t* h) { void* max; assert(h->len > 0); max = h->data[0]; h->A[0] = h->A[h->len - 1]; h->data[0] = h->data[h->len - 1]; h->len--; heap_heapify(h,0); return(max); }
heapItem heap_delete(heap *h, int i) { heapItem hi; assert(h); assert(h->size>i); // get item hi = h->items[i]; // fill in the gap h->size--; h->items[i] = h->items[h->size]; // reorder heap array heap_heapify(h, i); return hi; }
int heap_pop(struct heap_list *h, TYPE **data) { if (h == NULL || h->heap_keys == 0) { errno = ENOENT; return -1; } if (data != NULL) *data = h->heap_data[0]; if (h->heap_keys < (h->heap_size / 2)) heap_decr(h); h->heap_data[0] = h->heap_data[--h->heap_keys]; heap_heapify(h, 0); return 0; }
struct heapitem *heap_remove(struct heap *h, unsigned int index) { struct heapitem *item; if (index >= h->size) return NULL; item = h->map[index]; h->size--; h->map[index] = h->map[h->size]; heap_heapify(h, index); item->index = 0; item->active = 0; return item; }
struct heapnode heap_extract_min(struct heap *h) { if (h->nnodes == 0) return (struct heapnode){0, NULL}; struct heapnode minnode = h->nodes[1]; h->nodes[1] = h->nodes[h->nnodes]; h->Vtoidx[h->nodes[1].value] = 1; h->nnodes--; heap_heapify(h, 1); return minnode; } void heap_heapify(struct heap *h, int index) { for (;;) { int left = 2 * index; int right = 2 * index + 1; // Find largest key: A[index], A[left] and A[right] int largest = index; if (left <= h->nnodes && h->nodes[largest].key > h->nodes[left].key) { largest = left; } if (right <= h->nnodes && h->nodes[largest].key > h->nodes[right].key) { largest = right; } if (largest == index) break; heap_swap(h, index, largest); index = largest; } } int heap_decrease_key(struct heap *h, int value, int key) { int index = h->Vtoidx[value]; if (h->nodes[index].key < key) return -1; h->nodes[index].key = key; for ( ; index > 1 && h->nodes[index].key < h->nodes[index / 2].key; index = index / 2) { heap_swap(h, index, index / 2); } h->Vtoidx[value] = index; return 0; }
int heap_heapify( heap_t *heap_in, long idx_in ) { byte_t *start = (byte_t*) heap_in->start; int step = heap_in->step; long m = idx_in; const long l = heap_left( idx_in ); const long r = heap_right( idx_in ); if( ( l < heap_in->size ) && heap_in->cmp( start + l * step, start + idx_in * step ) == 1 ) m = l; if( ( r < heap_in->size ) && heap_in->cmp( start + r * step, start + m * step ) == 1 ) m = r; if( m != idx_in ) { if( heap_swap( heap_in, idx_in, m ) != 0 ) return -1; if( heap_heapify( heap_in, m ) != 0 ) return -2; } return 0; }
void heap_heapify(heap *h, int i) { int left, right, largest; heapItem tmp; assert(h); // left and right children left = (i*2)+1; right = left+1; // find "largest" element if(left<h->size && h->comparator(h->items[left], h->items[i])<0) largest = left; else largest = i; if(right<h->size && h->comparator(h->items[right], h->items[largest])<0) largest = right; // swap and recurse, if necessary if(largest!=i) { tmp = h->items[i]; h->items[i] = h->items[largest]; h->items[largest] = tmp; heap_heapify(h, largest); } }
/* * Return an element from the heap, located at the given index */ static HeapElement * heap_delete(Heap * h,int idx) { HeapElement *he,*helast; int pidx; HeapInternCmp cmp_func; DBG(debug("heap_delete(h=%p,idx=%d)\n",h,idx)); LLOG(HSIZE(h)); if (idx < 0 || idx >= HSIZE(h)) { LLOG(idx); return NULL; } if (h->hpMode == HEAP_MAXIMIZE) cmp_func = heap_larger; else cmp_func = heap_smaller; /* Remember the current element */ he = HARRAY(h,idx); /* Remember the last element */ helast = HLAST(h); h->hpFilled--; if (idx == HSIZE(h)) /* This is the last element */ goto end_label; /* Put the last element in the position of the current */ HARRAY(h,idx) = helast; if (h->hpChgFunc) h->hpChgFunc(HARRAY(h,idx)->heData,idx); /* Heapify the new subtree. Then if the root of the subtree * is larger than its parent, propagate it up the tree until * it finds is proper location */ heap_heapify(h,idx); pidx = HPARENT(idx); LLOG(pidx); if (idx > 0) { while (cmp_func(h,HARRAY(h,idx),HARRAY(h,pidx))) { heap_swap(h,idx,pidx); idx = pidx; if (idx == 0) break; pidx = HPARENT(idx); } } end_label: if (NEEDS2SHRINK(h)) heap_shrink(h); return he; }
enum search_ret impact_ord_eval(struct index *idx, struct query *query, struct chash *accumulators, unsigned int acc_limit, struct alloc *alloc, unsigned int mem) { double norm_B; unsigned int i, terms = 0, blockfine, blocks_read, postings_read = 0, postings = 0, bytes = 0, bytes_read = 0; struct term_data *term, *largest; struct disksrc *dsrc; if (query->terms == 0) { /* no terms to process */ return SEARCH_OK; /* allocate space for array */ } else if (!(term = malloc(sizeof(*term) * query->terms))) { return SEARCH_ENOMEM; } /* sort by selectivity (by inverse t_f) */ qsort(query->term, query->terms, sizeof(*query->term), f_t_cmp); norm_B = pow(idx->impact_stats.w_qt_max / idx->impact_stats.w_qt_min, idx->impact_stats.w_qt_min / (idx->impact_stats.w_qt_max - idx->impact_stats.w_qt_min)); /* initialise data for each query term */ for (i = 0; i < query->terms; i++) { unsigned int termfine; double w_qt; /* initialise src/vec for term */ term[i].v.pos = term[i].v.end = NULL; term[i].src = NULL; w_qt = (1 + log(query->term[i].f_qt)) * log(1 + (idx->impact_stats.avg_f_t / query->term[i].f_t)); w_qt = impact_normalise(w_qt, norm_B, idx->impact_stats.slope, idx->impact_stats.w_qt_max, idx->impact_stats.w_qt_min); term[i].w_qt = impact_quantise(w_qt, idx->impact_stats.quant_bits, idx->impact_stats.w_qt_max, idx->impact_stats.w_qt_min); /* apply term fine to term impact */ termfine = (i < 2) ? 0 : i - 2; if (termfine < term[i].w_qt) { term[i].w_qt -= termfine; /* initialise to highest impact, so we'll select and initialise this * term before real processing */ term[i].impact = INT_MAX; terms++; } else { /* we won't use this term */ term[i].w_qt = 0; term[i].impact = 0; } term[i].blocksize = 0; /* XXX */ postings += query->term[i].f_t; bytes += query->term[i].term.vocab.size; } /* get sources for each term (do this in a seperate loop so we've already * excluded lists that we won't use) */ for (i = 0; i < terms; i++) { unsigned int memsize = mem / (terms - i); if (memsize > query->term[i].term.vocab.size) { memsize = query->term[i].term.vocab.size; } if (!(term[i].src = search_term_src(idx, &query->term[i].term, alloc, memsize))) { source_delete(term, terms); free(term); return SEARCH_EINVAL; } mem -= memsize; } blockfine = blocks_read = 0; heap_heapify(term, terms, sizeof(*term), term_data_cmp); do { largest = heap_pop(term, &terms, sizeof(*term), term_data_cmp); if (largest && (largest->impact > blockfine)) { postings_read += largest->blocksize; if (chash_size(accumulators) < acc_limit) { /* reserve enough memory for accumulators and decode */ if (chash_reserve(accumulators, largest->blocksize) >= largest->blocksize) { impact_decode_block(accumulators, largest, blockfine); } else { assert(!CRASH); ERROR("impact_ord_eval()"); source_delete(term, terms); free(term); return SEARCH_EINVAL; } } else { impact_decode_block_and(accumulators, largest, blockfine); } if (VEC_LEN(&largest->v) < 2 * VEC_VBYTE_MAX) { /* need to read more data */ unsigned int bytes; enum search_ret sret; if ((sret = largest->src->readlist(largest->src, VEC_LEN(&largest->v), (void **) &largest->v.pos, &bytes)) == SEARCH_OK) { /* read succeeded */ largest->v.end = largest->v.pos + bytes; } else if (sret == SEARCH_FINISH) { if (VEC_LEN(&largest->v) || largest->blocksize) { /* didn't finish properly */ assert(!CRASH); ERROR("impact_ord_eval()"); source_delete(term, terms); free(term); return SEARCH_EINVAL; } /* otherwise it will be finished below */ } else { assert(!CRASH); ERROR("impact_ord_eval()"); source_delete(term, terms); free(term); return sret; } } if (!largest->blocksize) { /* need to read the start of the next block */ unsigned long int tmp_bsize, tmp_impact; if (vec_vbyte_read(&largest->v, &tmp_bsize) && (vec_vbyte_read(&largest->v, &tmp_impact) /* second read failed, rewind past first vbyte */ || ((largest->v.pos -= vec_vbyte_len(tmp_bsize)), 0))) { blocks_read++; if (blocks_read > terms) { blockfine++; } largest->blocksize = tmp_bsize; largest->impact = (tmp_impact + 1) * largest->w_qt; largest->docno = -1; heap_insert(term, &terms, sizeof(*term), term_data_cmp, largest); } else if (!VEC_LEN(&largest->v)) { /* finished, don't put back on the heap */ dsrc = (void *) largest->src; bytes_read += dsrc->pos; largest->src->delet(largest->src); largest->src = NULL; } else if (largest->impact != INT_MAX) { /* ensure that this vector is chosen next, as we need the * next impact score */ largest->impact = INT_MAX; assert(largest->blocksize == 0); heap_insert(term, &terms, sizeof(*term), term_data_cmp, largest); } else { /* huh? */ assert(!CRASH); ERROR("impact_ord_eval()"); source_delete(term, terms); free(term); return SEARCH_EINVAL; } } else { heap_insert(term, &terms, sizeof(*term), term_data_cmp, largest); } } } while (largest && (largest->impact > blockfine)); for (i = 0; i < terms; i++) { dsrc = (void *) term[i].src; bytes_read += dsrc->pos; } if (largest) { largest->src->delet(largest->src); largest->src = NULL; } /* end of ranking */ source_delete(term, terms); free(term); return SEARCH_OK; }
void heap_changedhead (void *heap, int size, int num, heap_comp hc) { heap_heapify (heap, size, num, 1, hc); }