Ancient
view release on metacpan or search on metacpan
xs/heap/heap.c view on Meta::CPAN
if (right < size) {
NV right_nv = SvNV(data[right]);
if (right_nv < best_nv) {
best = right;
best_nv = right_nv;
}
}
if (best_nv < val_nv) {
data[idx] = data[best];
idx = best;
} else {
break;
}
}
data[idx] = val;
}
static void heap_sift_down_max(Heap *h, IV idx) {
SV **data = h->data;
IV size = h->size;
SV *val = data[idx];
NV val_nv = SvNV(val);
IV half = size >> 1;
while (idx < half) {
IV left = (idx << 1) + 1;
IV right = left + 1;
IV best = left;
NV best_nv = SvNV(data[left]);
if (right < size) {
NV right_nv = SvNV(data[right]);
if (right_nv > best_nv) {
best = right;
best_nv = right_nv;
}
}
if (best_nv > val_nv) {
data[idx] = data[best];
idx = best;
} else {
break;
}
}
data[idx] = val;
}
/* Custom comparator sift operations */
static bool heap_compare_custom(pTHX_ Heap *h, SV *a, SV *b) {
dSP;
IV result;
int count;
ENTER; SAVETMPS;
PUSHMARK(SP);
XPUSHs(a);
XPUSHs(b);
PUTBACK;
count = call_sv(h->comparator, G_SCALAR);
SPAGAIN;
if (count != 1) croak("Comparator must return exactly one value");
result = POPi;
PUTBACK;
FREETMPS; LEAVE;
return h->type == HEAP_MIN ? result < 0 : result > 0;
}
static void heap_sift_up_custom(pTHX_ Heap *h, IV idx) {
while (idx > 0) {
IV parent = (idx - 1) >> 1;
if (heap_compare_custom(aTHX_ h, h->data[idx], h->data[parent])) {
SV *tmp = h->data[idx];
h->data[idx] = h->data[parent];
h->data[parent] = tmp;
idx = parent;
} else {
break;
}
}
}
static void heap_sift_down_custom(pTHX_ Heap *h, IV idx) {
while (1) {
IV left = (idx << 1) + 1;
IV right = left + 1;
IV best = idx;
if (left < h->size && heap_compare_custom(aTHX_ h, h->data[left], h->data[best])) {
best = left;
}
if (right < h->size && heap_compare_custom(aTHX_ h, h->data[right], h->data[best])) {
best = right;
}
if (best != idx) {
SV *tmp = h->data[idx];
h->data[idx] = h->data[best];
h->data[best] = tmp;
idx = best;
} else {
break;
}
}
}
static void heap_sift_up(pTHX_ Heap *h, IV idx) {
if (h->comparator) {
heap_sift_up_custom(aTHX_ h, idx);
} else if (h->type == HEAP_MIN) {
heap_sift_up_min(h, idx);
} else {
heap_sift_up_max(h, idx);
}
}
static void heap_sift_down(pTHX_ Heap *h, IV idx) {
if (h->comparator) {
heap_sift_down_custom(aTHX_ h, idx);
} else if (h->type == HEAP_MIN) {
heap_sift_down_min(h, idx);
} else {
heap_sift_down_max(h, idx);
( run in 0.730 second using v1.01-cache-2.11-cpan-13bb782fe5a )