/*********************************************** !!!! DO NOT EDIT THIS FILE !!!! This file was auto-generated by Build.PL from lib/KinoSearch/Util/PriorityQueue.pm See KinoSearch::Docs::DevGuide for details. ***********************************************/ #line 178 "lib/KinoSearch/Util/PriorityQueue.pm" #include "KinoSearchUtilPriorityQueue.h" static void Kino_PriQ_put(PriorityQueue*, SV*); static SV* Kino_PriQ_top(PriorityQueue*); static void Kino_PriQ_adjust_top(PriorityQueue*); static void Kino_PriQ_clear(PriorityQueue*); static void Kino_PriQ_up_heap(PriorityQueue*); static void Kino_PriQ_down_heap(PriorityQueue*); PriorityQueue* Kino_PriQ_new (U32 max_size) { PriorityQueue *pq; U32 i, heap_size; Kino_New(0, pq, 1, PriorityQueue); pq->size = 0; pq->max_size = max_size; pq->less_than = Kino_PriQ_default_less_than; /* allocate space for the heap, assign all slots to Nullsv */ heap_size = max_size + 1; Kino_New(0, pq->heap, heap_size, SV*); for (i = 0; i < heap_size; i++) { pq->heap[i] = Nullsv; } return pq; } /* Add an element to the heap. Throw an error if too many elements * are added. */ static void Kino_PriQ_put(PriorityQueue *pq, SV *element) { /* extend heap */ if (pq->size >= pq->max_size) { Kino_confess("PriorityQueue exceeded max_size: %d %d", pq->size, pq->max_size); } pq->size++; /* put element into heap */ pq->heap[ pq->size ] = newSVsv(element); /* adjust heap */ Kino_PriQ_up_heap(pq); } bool Kino_PriQ_insert(PriorityQueue *pq, SV *element) { SV *scratch_sv; /* absorb element if there's a vacancy */ if (pq->size < pq->max_size) { Kino_PriQ_put(pq, element); return 1; } /* otherwise, compete for the slot */ else { scratch_sv = Kino_PriQ_top(pq); if( pq->size > 0 && !pq->less_than(element, scratch_sv)) { /* if the new element belongs in the queue, replace something */ scratch_sv = pq->heap[1]; SvREFCNT_dec(scratch_sv); pq->heap[1] = newSVsv(element); Kino_PriQ_adjust_top(pq); return 1; } else { return 0; } } } /* Return the least item in the queue, or Nullsv if queue is empty. */ static SV* Kino_PriQ_top(PriorityQueue *pq) { if (pq->size > 0) { return pq->heap[1]; /* note: no refcount manip */ } else { return Nullsv; } } SV* Kino_PriQ_pop(PriorityQueue *pq) { SV *result; if (pq->size > 0) { /* mortalize the first value and save it */ result = sv_2mortal( pq->heap[1] ); /* move last to first and adjust heap */ pq->heap[1] = pq->heap[ pq->size ]; pq->heap[ pq->size ] = Nullsv; pq->size--; Kino_PriQ_down_heap(pq); return result; } else { return Nullsv; } } SV* Kino_PriQ_peek(PriorityQueue *pq) { if (pq->size > 0) { return pq->heap[1]; } else { return Nullsv; } } AV* Kino_PriQ_pop_all(PriorityQueue *pq) { AV* out_av; I32 i; SV* element; /* allocate an empty AV; return immediately if the queue is empty */ out_av = newAV(); if (pq->size == 0) { return out_av; } /* map the queue nodes onto the array in reverse order */ av_extend(out_av, pq->size - 1); for (i = pq->size - 1; i >= 0; i--) { element = newSVsv( Kino_PriQ_pop(pq) ); av_store(out_av, i, element); } return out_av; } /* Alias for down_heap. Should be called when the item at the top changes. */ static void Kino_PriQ_adjust_top(PriorityQueue *pq) { Kino_PriQ_down_heap(pq); } /* Free all the elements in the heap and set size to 0. */ static void Kino_PriQ_clear(PriorityQueue *pq) { U32 i; SV **sv_ptr; sv_ptr = (pq->heap + 1); /* node 0 is held empty, to make the algo clearer */ for (i = 1; i <= pq->size; i++) { SvREFCNT_dec(*sv_ptr); *sv_ptr = Nullsv; sv_ptr++; } pq->size = 0; } /* Heap adjuster. */ static void Kino_PriQ_up_heap(PriorityQueue *pq) { U32 i, j; SV *node; i = pq->size; node = pq->heap[i]; /* save bottom node */ j = i >> 1; while ( j > 0 && pq->less_than(node, pq->heap[j]) ) { pq->heap[i] = pq->heap[j]; i = j; j = j >> 1; } pq->heap[i] = node; } /* Heap adjuster. */ static void Kino_PriQ_down_heap(PriorityQueue *pq) { U32 i, j, k; SV *node; /* save top node */ i = 1; node = pq->heap[i]; /* find smaller child */ j = i << 1; k = j + 1; if ( k <= pq->size && pq->less_than(pq->heap[k], pq->heap[j]) ) { j = k; } while ( j <= pq->size && pq->less_than(pq->heap[j], node) ) { pq->heap[i] = pq->heap[j]; i = j; j = i << 1; k = j + 1; if ( k <= pq->size && pq->less_than(pq->heap[k], pq->heap[j]) ) { j = k; } } pq->heap[i] = node; } /* Compare the integer values of two scalars. */ bool Kino_PriQ_default_less_than(SV* a, SV* b) { if ( SvIV(a) < SvIV(b) ) { return 1; } else { return 0; } } void Kino_PriQ_destroy(PriorityQueue *pq) { Kino_PriQ_clear(pq); Kino_Safefree(pq->heap); Kino_Safefree(pq); } /* Print integer values for all items in the Queue. */ void Kino_PriQ_dump(PriorityQueue *pq) { U32 i; SV **sv_ptr; sv_ptr = (pq->heap + 1); for (i = 1; i <= pq->size; i++) { IV j = SvIV(*sv_ptr); fprintf(stderr, "%"IVdf" ", j); sv_ptr++; } fprintf(stderr, "\n"); }