Curve Fitting: heap reinsertion optimization

This commit is contained in:
Campbell Barton
2017-10-29 16:33:44 +11:00
parent bd0d41059f
commit 560fa6db17
3 changed files with 68 additions and 41 deletions
+6 -11
View File
@@ -324,7 +324,7 @@ static double knot_remove_error_value(
/* Avoid having to re-calculate again */ /* Avoid having to re-calculate again */
double r_handle_factors[2], uint *r_error_index) double r_handle_factors[2], uint *r_error_index)
{ {
double error_sq = FLT_MAX; double error_sq = DBL_MAX;
#ifdef USE_VLA #ifdef USE_VLA
double handle_factor_l[dims]; double handle_factor_l[dims];
@@ -340,7 +340,7 @@ static double knot_remove_error_value(
handle_factor_l, handle_factor_r, handle_factor_l, handle_factor_r,
&error_sq, r_error_index); &error_sq, r_error_index);
assert(error_sq != FLT_MAX); assert(error_sq != DBL_MAX);
isub_vnvn(handle_factor_l, points_offset, dims); isub_vnvn(handle_factor_l, points_offset, dims);
r_handle_factors[0] = dot_vnvn(tan_l, handle_factor_l, dims); r_handle_factors[0] = dot_vnvn(tan_l, handle_factor_l, dims);
@@ -465,7 +465,6 @@ static void knot_remove_error_recalculate(
struct KnotRemoveState *r; struct KnotRemoveState *r;
if (k->heap_node) { if (k->heap_node) {
r = HEAP_node_ptr(k->heap_node); r = HEAP_node_ptr(k->heap_node);
HEAP_remove(p->heap, k->heap_node);
} }
else { else {
#ifdef USE_TPOOL #ifdef USE_TPOOL
@@ -473,14 +472,13 @@ static void knot_remove_error_recalculate(
#else #else
r = malloc(sizeof(*r)); r = malloc(sizeof(*r));
#endif #endif
r->index = k->index; r->index = k->index;
} }
r->handles[0] = handles[0]; r->handles[0] = handles[0];
r->handles[1] = handles[1]; r->handles[1] = handles[1];
k->heap_node = HEAP_insert(p->heap, cost_sq, r); HEAP_insert_or_update(p->heap, &k->heap_node, cost_sq, r);
} }
else { else {
if (k->heap_node) { if (k->heap_node) {
@@ -624,7 +622,6 @@ static void knot_refit_error_recalculate(
struct KnotRefitState *r; struct KnotRefitState *r;
if (k->heap_node) { if (k->heap_node) {
r = HEAP_node_ptr(k->heap_node); r = HEAP_node_ptr(k->heap_node);
HEAP_remove(p->heap, k->heap_node);
} }
else { else {
#ifdef USE_TPOOL #ifdef USE_TPOOL
@@ -645,7 +642,7 @@ static void knot_refit_error_recalculate(
r->error_sq[0] = r->error_sq[1] = cost_sq; r->error_sq[0] = r->error_sq[1] = cost_sq;
/* Always perform removal before refitting, (make a negative number) */ /* Always perform removal before refitting, (make a negative number) */
k->heap_node = HEAP_insert(p->heap, cost_sq - error_sq_max, r); HEAP_insert_or_update(p->heap, &k->heap_node, cost_sq - error_sq_max, r);
return; return;
} }
@@ -689,7 +686,6 @@ static void knot_refit_error_recalculate(
struct KnotRefitState *r; struct KnotRefitState *r;
if (k->heap_node) { if (k->heap_node) {
r = HEAP_node_ptr(k->heap_node); r = HEAP_node_ptr(k->heap_node);
HEAP_remove(p->heap, k->heap_node);
} }
else { else {
#ifdef USE_TPOOL #ifdef USE_TPOOL
@@ -716,7 +712,7 @@ static void knot_refit_error_recalculate(
assert(cost_sq_dst_max < cost_sq_src_max); assert(cost_sq_dst_max < cost_sq_src_max);
/* Weight for the greatest improvement */ /* Weight for the greatest improvement */
k->heap_node = HEAP_insert(p->heap, cost_sq_src_max - cost_sq_dst_max, r); HEAP_insert_or_update(p->heap, &k->heap_node, cost_sq_src_max - cost_sq_dst_max, r);
} }
} }
else { else {
@@ -895,7 +891,6 @@ static void knot_corner_error_recalculate(
struct KnotCornerState *c; struct KnotCornerState *c;
if (k_split->heap_node) { if (k_split->heap_node) {
c = HEAP_node_ptr(k_split->heap_node); c = HEAP_node_ptr(k_split->heap_node);
HEAP_remove(p->heap, k_split->heap_node);
} }
else { else {
#ifdef USE_TPOOL #ifdef USE_TPOOL
@@ -920,7 +915,7 @@ static void knot_corner_error_recalculate(
c->error_sq[1] = cost_sq_dst[1]; c->error_sq[1] = cost_sq_dst[1];
const double cost_max_sq = MAX2(cost_sq_dst[0], cost_sq_dst[1]); const double cost_max_sq = MAX2(cost_sq_dst[0], cost_sq_dst[1]);
k_split->heap_node = HEAP_insert(p->heap, cost_max_sq, c); HEAP_insert_or_update(p->heap, &k_split->heap_node, cost_max_sq, c);
} }
else { else {
if (k_split->heap_node) { if (k_split->heap_node) {
+55 -26
View File
@@ -48,13 +48,14 @@
# define UNLIKELY(x) (x) # define UNLIKELY(x) (x)
#endif #endif
typedef unsigned int uint;
/***/ /***/
struct HeapNode { struct HeapNode {
void *ptr; void *ptr;
double value; double value;
unsigned int index; uint index;
}; };
/* heap_* pool allocator */ /* heap_* pool allocator */
@@ -67,8 +68,8 @@ struct HeapNode {
#undef TPOOL_STRUCT #undef TPOOL_STRUCT
struct Heap { struct Heap {
unsigned int size; uint size;
unsigned int bufsize; uint bufsize;
HeapNode **tree; HeapNode **tree;
struct HeapMemPool pool; struct HeapMemPool pool;
@@ -86,32 +87,32 @@ struct Heap {
#define HEAP_EQUALS(a, b) ((a)->value == (b)->value) #define HEAP_EQUALS(a, b) ((a)->value == (b)->value)
#endif #endif
static void heap_swap(Heap *heap, const unsigned int i, const unsigned int j) static void heap_swap(Heap *heap, const uint i, const uint j)
{ {
#if 0 #if 0
SWAP(unsigned int, heap->tree[i]->index, heap->tree[j]->index); SWAP(uint, heap->tree[i]->index, heap->tree[j]->index);
SWAP(HeapNode *, heap->tree[i], heap->tree[j]); SWAP(HeapNode *, heap->tree[i], heap->tree[j]);
#else #else
HeapNode **tree = heap->tree; HeapNode **tree = heap->tree;
union { union {
unsigned int index; uint index;
HeapNode *node; HeapNode *node;
} tmp; } tmp;
SWAP_TVAL(tmp.index, tree[i]->index, tree[j]->index); SWAP_TVAL(tmp.index, tree[i]->index, tree[j]->index);
SWAP_TVAL(tmp.node, tree[i], tree[j]); SWAP_TVAL(tmp.node, tree[i], tree[j]);
#endif #endif
} }
static void heap_down(Heap *heap, unsigned int i) static void heap_down(Heap *heap, uint i)
{ {
/* size won't change in the loop */ /* size won't change in the loop */
const unsigned int size = heap->size; const uint size = heap->size;
while (1) { while (1) {
const unsigned int l = HEAP_LEFT(i); const uint l = HEAP_LEFT(i);
const unsigned int r = HEAP_RIGHT(i); const uint r = HEAP_RIGHT(i);
unsigned int smallest; uint smallest;
smallest = ((l < size) && HEAP_COMPARE(heap->tree[l], heap->tree[i])) ? l : i; smallest = ((l < size) && HEAP_COMPARE(heap->tree[l], heap->tree[i])) ? l : i;
@@ -128,10 +129,10 @@ static void heap_down(Heap *heap, unsigned int i)
} }
} }
static void heap_up(Heap *heap, unsigned int i) static void heap_up(Heap *heap, uint i)
{ {
while (i > 0) { while (i > 0) {
const unsigned int p = HEAP_PARENT(i); const uint p = HEAP_PARENT(i);
if (HEAP_COMPARE(heap->tree[p], heap->tree[i])) { if (HEAP_COMPARE(heap->tree[p], heap->tree[i])) {
break; break;
@@ -148,7 +149,7 @@ static void heap_up(Heap *heap, unsigned int i)
* \{ */ * \{ */
/* use when the size of the heap is known in advance */ /* use when the size of the heap is known in advance */
Heap *HEAP_new(unsigned int tot_reserve) Heap *HEAP_new(uint tot_reserve)
{ {
Heap *heap = malloc(sizeof(Heap)); Heap *heap = malloc(sizeof(Heap));
/* ensure we have at least one so we can keep doubling it */ /* ensure we have at least one so we can keep doubling it */
@@ -164,7 +165,7 @@ Heap *HEAP_new(unsigned int tot_reserve)
void HEAP_free(Heap *heap, HeapFreeFP ptrfreefp) void HEAP_free(Heap *heap, HeapFreeFP ptrfreefp)
{ {
if (ptrfreefp) { if (ptrfreefp) {
unsigned int i; uint i;
for (i = 0; i < heap->size; i++) { for (i = 0; i < heap->size; i++) {
ptrfreefp(heap->tree[i]->ptr); ptrfreefp(heap->tree[i]->ptr);
@@ -180,7 +181,7 @@ void HEAP_free(Heap *heap, HeapFreeFP ptrfreefp)
void HEAP_clear(Heap *heap, HeapFreeFP ptrfreefp) void HEAP_clear(Heap *heap, HeapFreeFP ptrfreefp)
{ {
if (ptrfreefp) { if (ptrfreefp) {
unsigned int i; uint i;
for (i = 0; i < heap->size; i++) { for (i = 0; i < heap->size; i++) {
ptrfreefp(heap->tree[i]->ptr); ptrfreefp(heap->tree[i]->ptr);
@@ -215,12 +216,22 @@ HeapNode *HEAP_insert(Heap *heap, double value, void *ptr)
return node; return node;
} }
bool HEAP_is_empty(Heap *heap) void HEAP_insert_or_update(Heap *heap, HeapNode **node_p, double value, void *ptr)
{
if (*node_p == NULL) {
*node_p = HEAP_insert(heap, value, ptr);
}
else {
HEAP_node_value_update_ptr(heap, *node_p, value, ptr);
}
}
bool HEAP_is_empty(const Heap *heap)
{ {
return (heap->size == 0); return (heap->size == 0);
} }
unsigned int HEAP_size(Heap *heap) uint HEAP_size(const Heap *heap)
{ {
return heap->size; return heap->size;
} }
@@ -230,7 +241,7 @@ HeapNode *HEAP_top(Heap *heap)
return heap->tree[0]; return heap->tree[0];
} }
double HEAP_top_value(Heap *heap) double HEAP_top_value(const Heap *heap)
{ {
return heap->tree[0]->value; return heap->tree[0]->value;
} }
@@ -253,12 +264,12 @@ void *HEAP_popmin(Heap *heap)
void HEAP_remove(Heap *heap, HeapNode *node) void HEAP_remove(Heap *heap, HeapNode *node)
{ {
unsigned int i = node->index; uint i = node->index;
assert(heap->size != 0); assert(heap->size != 0);
while (i > 0) { while (i > 0) {
unsigned int p = HEAP_PARENT(i); uint p = HEAP_PARENT(i);
heap_swap(heap, p, i); heap_swap(heap, p, i);
i = p; i = p;
@@ -267,7 +278,25 @@ void HEAP_remove(Heap *heap, HeapNode *node)
HEAP_popmin(heap); HEAP_popmin(heap);
} }
double HEAP_node_value(HeapNode *node) void HEAP_node_value_update(Heap *heap, HeapNode *node, double value)
{
assert(heap->size != 0);
if (node->value == value) {
return;
}
node->value = value;
/* Can be called in either order, makes no difference. */
heap_up(heap, node->index);
heap_down(heap, node->index);
}
void HEAP_node_value_update_ptr(Heap *heap, HeapNode *node, double value, void *ptr)
{
node->ptr = ptr;
HEAP_node_value_update(heap, node, value);
}
double HEAP_node_value(const HeapNode *node)
{ {
return node->value; return node->value;
} }
+7 -4
View File
@@ -39,16 +39,19 @@ typedef struct HeapNode HeapNode;
typedef void (*HeapFreeFP)(void *ptr); typedef void (*HeapFreeFP)(void *ptr);
Heap *HEAP_new(unsigned int tot_reserve); Heap *HEAP_new(unsigned int tot_reserve);
bool HEAP_is_empty(Heap *heap); bool HEAP_is_empty(const Heap *heap);
void HEAP_free(Heap *heap, HeapFreeFP ptrfreefp); void HEAP_free(Heap *heap, HeapFreeFP ptrfreefp);
void *HEAP_node_ptr(HeapNode *node); void *HEAP_node_ptr(HeapNode *node);
void HEAP_remove(Heap *heap, HeapNode *node); void HEAP_remove(Heap *heap, HeapNode *node);
HeapNode *HEAP_insert(Heap *heap, double value, void *ptr); HeapNode *HEAP_insert(Heap *heap, double value, void *ptr);
void HEAP_insert_or_update(Heap *heap, HeapNode **node_p, double value, void *ptr);
void *HEAP_popmin(Heap *heap); void *HEAP_popmin(Heap *heap);
void HEAP_clear(Heap *heap, HeapFreeFP ptrfreefp); void HEAP_clear(Heap *heap, HeapFreeFP ptrfreefp);
unsigned int HEAP_size(Heap *heap); unsigned int HEAP_size(const Heap *heap);
HeapNode *HEAP_top(Heap *heap); HeapNode *HEAP_top(Heap *heap);
double HEAP_top_value(Heap *heap); double HEAP_top_value(const Heap *heap);
double HEAP_node_value(HeapNode *node); void HEAP_node_value_update(Heap *heap, HeapNode *node, double value);
void HEAP_node_value_update_ptr(Heap *heap, HeapNode *node, double value, void *ptr);
double HEAP_node_value(const HeapNode *node);
#endif /* __GENERIC_HEAP_IMPL_H__ */ #endif /* __GENERIC_HEAP_IMPL_H__ */