#ifndef LIGHTNING_PLUGINS_RENEPAY_HEAP_H #define LIGHTNING_PLUGINS_RENEPAY_HEAP_H #include "config.h" #include #include #include /* A functionality missing in gheap that can be used to update elements. * Input: item * Output: the position of the smallest element p, such is greater equal item. * Formally: * Let X={x in heap: !(xdistance, db = ((struct heap_data*)b)->distance; u32 ia = ((struct heap_data*)a)->idx, ib = ((struct heap_data*)b)->idx; return da==db ? ia > ib : da > db; } static void item_mover(void *const dst, const void *const src) { *(struct heap_data*)dst = *(struct heap_data*)src; } struct heap* heap_new(const tal_t *ctx, const size_t max_capacity) { struct heap* heap = tal(ctx,struct heap); heap->size=0; heap->data = tal_arr(heap,struct heap_data,max_capacity); heap->max_size = max_capacity; heap->gheap_ctx.fanout=2; heap->gheap_ctx.page_chunks=1; heap->gheap_ctx.item_size= sizeof(struct heap_data); heap->gheap_ctx.less_comparer=less_comparer; heap->gheap_ctx.less_comparer_ctx=heap; heap->gheap_ctx.item_mover=item_mover; return heap; } void heap_insert(struct heap* heap, u32 idx, s64 distance) { heap->data[heap->size].idx=idx; heap->data[heap->size].distance=distance; heap->size++; assert(heap->size<=heap->max_size); gheap_restore_heap_after_item_increase(&heap->gheap_ctx, heap->data, heap->size, heap->size-1); } bool heap_empty(const struct heap* heap) { return heap->size==0; } struct heap_data * heap_top(const struct heap * heap) { return &heap->data[0]; } void heap_pop(struct heap* heap) { if(heap->size>0) gheap_pop_heap(&heap->gheap_ctx,heap->data,heap->size--); } /* Input: item * Output: the smallest x such that !(xfanout; const size_t item_size = ctx->item_size; const void*const less_comparer_ctx = ctx->less_comparer_ctx; const gheap_less_comparer_t less_comparer = ctx->less_comparer; if(less_comparer(less_comparer_ctx,base,item)) { // root=heap_size) break; if(!less_comparer(less_comparer_ctx, ((char*)base) + child*item_size, item)) { // satisfies the condition, // is it the smallest one? if(!less_comparer(less_comparer_ctx, ((char*)base) + best_child*item_size, ((char*)base) + child*item_size)) { // child <= best_child, so child is a // better upper bound best_child = child; } } } if(best_child==last) { // no change, we stop break; } last = best_child; } return last; } void heap_update(struct heap* heap, u32 idx, s64 old_distance, s64 new_distance) { const gheap_less_comparer_t less_comparer = heap->gheap_ctx.less_comparer; const void *const less_comparer_ctx = heap->gheap_ctx.less_comparer_ctx; struct heap_data old_item = (struct heap_data){.idx=idx, .distance=old_distance}; size_t pos = gheap_upper_bound(&heap->gheap_ctx,heap->data,heap->size,&old_item); if(pos>=heap->size || heap->data[pos].idx!=idx) { heap_insert(heap,idx,new_distance); } else { struct heap_data new_item = (struct heap_data){.idx=idx, .distance=new_distance}; if(less_comparer(less_comparer_ctx,&new_item,&heap->data[pos])) { heap->data[pos].distance = new_distance; gheap_restore_heap_after_item_decrease( &heap->gheap_ctx, heap->data, heap->size, pos); }else { heap->data[pos].distance = new_distance; gheap_restore_heap_after_item_increase( &heap->gheap_ctx, heap->data, heap->size, pos); } } } #endif /* LIGHTNING_PLUGINS_RENEPAY_HEAP_H */