Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenlib/intern/BLI_heap.c')
-rw-r--r--source/blender/blenlib/intern/BLI_heap.c137
1 files changed, 81 insertions, 56 deletions
diff --git a/source/blender/blenlib/intern/BLI_heap.c b/source/blender/blenlib/intern/BLI_heap.c
index ee7d93ea1a9..dcc028630e2 100644
--- a/source/blender/blenlib/intern/BLI_heap.c
+++ b/source/blender/blenlib/intern/BLI_heap.c
@@ -40,9 +40,9 @@
/***/
struct HeapNode {
- void *ptr;
- float value;
- int index;
+ void *ptr;
+ float value;
+ unsigned int index;
};
struct Heap {
@@ -54,48 +54,43 @@ struct Heap {
HeapNode **tree;
};
+/* internal functions */
+
#define HEAP_PARENT(i) ((i - 1) >> 1)
#define HEAP_LEFT(i) ((i << 1) + 1)
#define HEAP_RIGHT(i) ((i << 1) + 2)
#define HEAP_COMPARE(a, b) (a->value < b->value)
-// #define HEAP_EQUALS(a, b) (a->value == b->value) // UNUSED
-#define HEAP_SWAP(heap, i, j) \
- { \
- SWAP(int, heap->tree[i]->index, heap->tree[j]->index); \
- SWAP(HeapNode *, heap->tree[i], heap->tree[j]); \
- } (void)0
-/***/
+#if 0 /* UNUSED */
+#define HEAP_EQUALS(a, b) (a->value == b->value)
+#endif
-Heap *BLI_heap_new(void)
+BLI_INLINE void heap_swap(Heap *heap, const unsigned int i, const unsigned int j)
{
- Heap *heap = (Heap *)MEM_callocN(sizeof(Heap), __func__);
- heap->bufsize = 1;
- heap->tree = (HeapNode **)MEM_mallocN(sizeof(HeapNode *), "BLIHeapTree");
- heap->arena = BLI_memarena_new(1 << 16, "heap arena");
- return heap;
+#if 0
+ SWAP(unsigned int, heap->tree[i]->index, heap->tree[j]->index);
+ SWAP(HeapNode *, heap->tree[i], heap->tree[j]);
+#else
+ HeapNode **tree = heap->tree;
+ union {
+ unsigned int index;
+ HeapNode *node;
+ } tmp;
+ SWAP_TVAL(tmp.index, tree[i]->index, tree[j]->index);
+ SWAP_TVAL(tmp.node, tree[i], tree[j]);
+#endif
}
-void BLI_heap_free(Heap *heap, HeapFreeFP ptrfreefp)
+static void heap_down(Heap *heap, unsigned int i)
{
- int i;
-
- if (ptrfreefp)
- for (i = 0; i < heap->size; i++)
- ptrfreefp(heap->tree[i]->ptr);
+ /* size won't change in the loop */
+ const unsigned int size = heap->size;
- MEM_freeN(heap->tree);
- BLI_memarena_free(heap->arena);
- MEM_freeN(heap);
-}
-
-static void BLI_heap_down(Heap *heap, int i)
-{
while (1) {
- int size = heap->size, smallest;
- int l = HEAP_LEFT(i);
- int r = HEAP_RIGHT(i);
+ const unsigned int l = HEAP_LEFT(i);
+ const unsigned int r = HEAP_RIGHT(i);
+ unsigned int smallest;
smallest = ((l < size) && HEAP_COMPARE(heap->tree[l], heap->tree[i])) ? l : i;
@@ -105,46 +100,75 @@ static void BLI_heap_down(Heap *heap, int i)
if (smallest == i)
break;
- HEAP_SWAP(heap, i, smallest);
+ heap_swap(heap, i, smallest);
i = smallest;
}
}
-static void BLI_heap_up(Heap *heap, int i)
+static void heap_up(Heap *heap, unsigned int i)
{
while (i > 0) {
- int p = HEAP_PARENT(i);
+ const unsigned int p = HEAP_PARENT(i);
if (HEAP_COMPARE(heap->tree[p], heap->tree[i]))
break;
- HEAP_SWAP(heap, p, i);
+ heap_swap(heap, p, i);
i = p;
}
}
-HeapNode *BLI_heap_insert(Heap *heap, float value, void *ptr)
+
+/***/
+
+/* use when the size of the heap is known in advance */
+Heap *BLI_heap_new_ex(unsigned int tot_reserve)
{
- HeapNode *node;
+ Heap *heap = (Heap *)MEM_callocN(sizeof(Heap), __func__);
+ /* ensure we have at least one so we can keep doubling it */
+ heap->bufsize = MAX2(1, tot_reserve);
+ heap->tree = (HeapNode **)MEM_mallocN(heap->bufsize * sizeof(HeapNode *), "BLIHeapTree");
+ heap->arena = BLI_memarena_new(1 << 16, "heap arena");
- if ((heap->size + 1) > heap->bufsize) {
- int newsize = heap->bufsize * 2;
- HeapNode **newtree;
+ return heap;
+}
+
+Heap *BLI_heap_new(void)
+{
+ return BLI_heap_new_ex(1);
+}
+
+void BLI_heap_free(Heap *heap, HeapFreeFP ptrfreefp)
+{
+ unsigned int i;
+
+ if (ptrfreefp) {
+ for (i = 0; i < heap->size; i++) {
+ ptrfreefp(heap->tree[i]->ptr);
+ }
+ }
- newtree = (HeapNode **)MEM_mallocN(newsize * sizeof(*newtree), __func__);
- memcpy(newtree, heap->tree, sizeof(HeapNode *) * heap->size);
- MEM_freeN(heap->tree);
+ MEM_freeN(heap->tree);
+ BLI_memarena_free(heap->arena);
+ MEM_freeN(heap);
+}
- heap->tree = newtree;
- heap->bufsize = newsize;
+HeapNode *BLI_heap_insert(Heap *heap, float value, void *ptr)
+{
+ HeapNode *node;
+
+ if (UNLIKELY((heap->size + 1) > heap->bufsize)) {
+ heap->bufsize *= 2;
+ heap->tree = MEM_reallocN(heap->tree, heap->bufsize * sizeof(*heap->tree));
}
if (heap->freenodes) {
node = heap->freenodes;
heap->freenodes = (HeapNode *)(((HeapNode *)heap->freenodes)->ptr);
}
- else
+ else {
node = (HeapNode *)BLI_memarena_alloc(heap->arena, sizeof *node);
+ }
node->value = value;
node->ptr = ptr;
@@ -154,17 +178,17 @@ HeapNode *BLI_heap_insert(Heap *heap, float value, void *ptr)
heap->size++;
- BLI_heap_up(heap, heap->size - 1);
+ heap_up(heap, heap->size - 1);
return node;
}
-int BLI_heap_empty(Heap *heap)
+int BLI_heap_is_empty(Heap *heap)
{
return (heap->size == 0);
}
-int BLI_heap_size(Heap *heap)
+unsigned int BLI_heap_size(Heap *heap)
{
return heap->size;
}
@@ -181,13 +205,14 @@ void *BLI_heap_popmin(Heap *heap)
heap->tree[0]->ptr = heap->freenodes;
heap->freenodes = heap->tree[0];
- if (heap->size == 1)
+ if (UNLIKELY(heap->size == 1)) {
heap->size--;
+ }
else {
- HEAP_SWAP(heap, 0, heap->size - 1);
+ heap_swap(heap, 0, heap->size - 1);
heap->size--;
- BLI_heap_down(heap, 0);
+ heap_down(heap, 0);
}
return ptr;
@@ -195,12 +220,12 @@ void *BLI_heap_popmin(Heap *heap)
void BLI_heap_remove(Heap *heap, HeapNode *node)
{
- int i = node->index;
+ unsigned int i = node->index;
while (i > 0) {
- int p = HEAP_PARENT(i);
+ unsigned int p = HEAP_PARENT(i);
- HEAP_SWAP(heap, p, i);
+ heap_swap(heap, p, i);
i = p;
}