Blender V4.3
BLI_heap.c
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11#include <stdlib.h>
12#include <string.h>
13
14#include "MEM_guardedalloc.h"
15
16#include "BLI_heap.h"
17#include "BLI_utildefines.h"
18
19#include "BLI_strict_flags.h" /* Keep last. */
20
21/***/
22
23struct HeapNode {
24 float value;
26 void *ptr;
27};
28
35
43#define HEAP_CHUNK_DEFAULT_NUM \
44 (uint)(MEM_SIZE_OPTIMAL((1 << 16) - sizeof(struct HeapNode_Chunk)) / sizeof(HeapNode))
45
46struct Heap {
50
51 struct {
52 /* Always keep at least one chunk (never NULL) */
54 /* when NULL, allocate a new chunk */
57};
58
59/* -------------------------------------------------------------------- */
63#define HEAP_PARENT(i) (((i)-1) >> 1)
64#define HEAP_LEFT(i) (((i) << 1) + 1)
65#define HEAP_RIGHT(i) (((i) << 1) + 2)
66#define HEAP_COMPARE(a, b) ((a)->value < (b)->value)
67
68#if 0 /* UNUSED */
69# define HEAP_EQUALS(a, b) ((a)->value == (b)->value)
70#endif
71
72BLI_INLINE void heap_swap(Heap *heap, const uint i, const uint j)
73{
74 HeapNode **tree = heap->tree;
75 HeapNode *pi = tree[i], *pj = tree[j];
76 pi->index = j;
77 tree[j] = pi;
78 pj->index = i;
79 tree[i] = pj;
80}
81
82static void heap_down(Heap *heap, uint i)
83{
84 /* size won't change in the loop */
85 HeapNode **const tree = heap->tree;
86 const uint size = heap->size;
87
88 while (1) {
89 const uint l = HEAP_LEFT(i);
90 const uint r = HEAP_RIGHT(i);
91 uint smallest = i;
92
93 if (LIKELY(l < size) && HEAP_COMPARE(tree[l], tree[smallest])) {
94 smallest = l;
95 }
96 if (LIKELY(r < size) && HEAP_COMPARE(tree[r], tree[smallest])) {
97 smallest = r;
98 }
99
100 if (UNLIKELY(smallest == i)) {
101 break;
102 }
103
104 heap_swap(heap, i, smallest);
105 i = smallest;
106 }
107}
108
109static void heap_up(Heap *heap, uint i)
110{
111 HeapNode **const tree = heap->tree;
112
113 while (LIKELY(i > 0)) {
114 const uint p = HEAP_PARENT(i);
115
116 if (HEAP_COMPARE(tree[p], tree[i])) {
117 break;
118 }
119 heap_swap(heap, p, i);
120 i = p;
121 }
122}
123
126/* -------------------------------------------------------------------- */
131 struct HeapNode_Chunk *chunk_prev)
132{
133 struct HeapNode_Chunk *chunk = MEM_mallocN(
134 sizeof(struct HeapNode_Chunk) + (sizeof(HeapNode) * nodes_num), __func__);
135 chunk->prev = chunk_prev;
136 chunk->bufsize = nodes_num;
137 chunk->size = 0;
138 return chunk;
139}
140
142{
143 HeapNode *node;
144
145 if (heap->nodes.free) {
146 node = heap->nodes.free;
147 heap->nodes.free = heap->nodes.free->ptr;
148 }
149 else {
150 struct HeapNode_Chunk *chunk = heap->nodes.chunk;
151 if (UNLIKELY(chunk->size == chunk->bufsize)) {
153 }
154 node = &chunk->buf[chunk->size++];
155 }
156
157 return node;
158}
159
160static void heap_node_free(Heap *heap, HeapNode *node)
161{
162 node->ptr = heap->nodes.free;
163 heap->nodes.free = node;
164}
165
168/* -------------------------------------------------------------------- */
173{
174 Heap *heap = MEM_mallocN(sizeof(Heap), __func__);
175 /* ensure we have at least one so we can keep doubling it */
176 heap->size = 0;
177 heap->bufsize = MAX2(1u, reserve_num);
178 heap->tree = MEM_mallocN(heap->bufsize * sizeof(HeapNode *), "BLIHeapTree");
179
181 (reserve_num > 1) ? reserve_num : HEAP_CHUNK_DEFAULT_NUM, NULL);
182 heap->nodes.free = NULL;
183
184 return heap;
185}
186
188{
189 return BLI_heap_new_ex(1);
190}
191
192void BLI_heap_free(Heap *heap, HeapFreeFP ptrfreefp)
193{
194 if (ptrfreefp) {
195 uint i;
196
197 for (i = 0; i < heap->size; i++) {
198 ptrfreefp(heap->tree[i]->ptr);
199 }
200 }
201
202 struct HeapNode_Chunk *chunk = heap->nodes.chunk;
203 do {
204 struct HeapNode_Chunk *chunk_prev;
205 chunk_prev = chunk->prev;
206 MEM_freeN(chunk);
207 chunk = chunk_prev;
208 } while (chunk);
209
210 MEM_freeN(heap->tree);
211 MEM_freeN(heap);
212}
213
214void BLI_heap_clear(Heap *heap, HeapFreeFP ptrfreefp)
215{
216 if (ptrfreefp) {
217 uint i;
218
219 for (i = 0; i < heap->size; i++) {
220 ptrfreefp(heap->tree[i]->ptr);
221 }
222 }
223 heap->size = 0;
224
225 /* Remove all except the last chunk */
226 while (heap->nodes.chunk->prev) {
227 struct HeapNode_Chunk *chunk_prev = heap->nodes.chunk->prev;
228 MEM_freeN(heap->nodes.chunk);
229 heap->nodes.chunk = chunk_prev;
230 }
231 heap->nodes.chunk->size = 0;
232 heap->nodes.free = NULL;
233}
234
235HeapNode *BLI_heap_insert(Heap *heap, float value, void *ptr)
236{
237 HeapNode *node;
238
239 if (UNLIKELY(heap->size >= heap->bufsize)) {
240 heap->bufsize *= 2;
241 heap->tree = MEM_reallocN(heap->tree, heap->bufsize * sizeof(*heap->tree));
242 }
243
244 node = heap_node_alloc(heap);
245
246 node->ptr = ptr;
247 node->value = value;
248 node->index = heap->size;
249
250 heap->tree[node->index] = node;
251
252 heap->size++;
253
254 heap_up(heap, node->index);
255
256 return node;
257}
258
259void BLI_heap_insert_or_update(Heap *heap, HeapNode **node_p, float value, void *ptr)
260{
261 if (*node_p == NULL) {
262 *node_p = BLI_heap_insert(heap, value, ptr);
263 }
264 else {
265 BLI_heap_node_value_update_ptr(heap, *node_p, value, ptr);
266 }
267}
268
269bool BLI_heap_is_empty(const Heap *heap)
270{
271 return (heap->size == 0);
272}
273
275{
276 return heap->size;
277}
278
280{
281 return heap->tree[0];
282}
283
284float BLI_heap_top_value(const Heap *heap)
285{
286 BLI_assert(heap->size != 0);
287
288 return heap->tree[0]->value;
289}
290
292{
293 BLI_assert(heap->size != 0);
294
295 void *ptr = heap->tree[0]->ptr;
296
297 heap_node_free(heap, heap->tree[0]);
298
299 if (--heap->size) {
300 heap_swap(heap, 0, heap->size);
301 heap_down(heap, 0);
302 }
303
304 return ptr;
305}
306
307void BLI_heap_remove(Heap *heap, HeapNode *node)
308{
309 BLI_assert(heap->size != 0);
310
311 uint i = node->index;
312
313 while (i > 0) {
314 uint p = HEAP_PARENT(i);
315 heap_swap(heap, p, i);
316 i = p;
317 }
318
319 BLI_heap_pop_min(heap);
320}
321
322void BLI_heap_node_value_update(Heap *heap, HeapNode *node, float value)
323{
324 if (value < node->value) {
325 node->value = value;
326 heap_up(heap, node->index);
327 }
328 else if (value > node->value) {
329 node->value = value;
330 heap_down(heap, node->index);
331 }
332}
333
334void BLI_heap_node_value_update_ptr(Heap *heap, HeapNode *node, float value, void *ptr)
335{
336 node->ptr = ptr; /* only difference */
337 if (value < node->value) {
338 node->value = value;
339 heap_up(heap, node->index);
340 }
341 else if (value > node->value) {
342 node->value = value;
343 heap_down(heap, node->index);
344 }
345}
346
348{
349 return heap->value;
350}
351
352void *BLI_heap_node_ptr(const HeapNode *heap)
353{
354 return heap->ptr;
355}
356
357static bool heap_is_minheap(const Heap *heap, uint root)
358{
359 if (root < heap->size) {
360 if (heap->tree[root]->index != root) {
361 return false;
362 }
363 const uint l = HEAP_LEFT(root);
364 if (l < heap->size) {
365 if (HEAP_COMPARE(heap->tree[l], heap->tree[root]) || !heap_is_minheap(heap, l)) {
366 return false;
367 }
368 }
369 const uint r = HEAP_RIGHT(root);
370 if (r < heap->size) {
371 if (HEAP_COMPARE(heap->tree[r], heap->tree[root]) || !heap_is_minheap(heap, r)) {
372 return false;
373 }
374 }
375 }
376 return true;
377}
378bool BLI_heap_is_valid(const Heap *heap)
379{
380 return heap_is_minheap(heap, 0);
381}
382
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_INLINE
void * BLI_heap_node_ptr(const HeapNode *heap)
Definition BLI_heap.c:352
bool BLI_heap_is_valid(const Heap *heap)
Definition BLI_heap.c:378
void BLI_heap_insert_or_update(Heap *heap, HeapNode **node_p, float value, void *ptr)
Definition BLI_heap.c:259
void BLI_heap_node_value_update_ptr(Heap *heap, HeapNode *node, float value, void *ptr)
Definition BLI_heap.c:334
BLI_INLINE void heap_swap(Heap *heap, const uint i, const uint j)
Definition BLI_heap.c:72
void * BLI_heap_pop_min(Heap *heap)
Definition BLI_heap.c:291
void BLI_heap_free(Heap *heap, HeapFreeFP ptrfreefp)
Definition BLI_heap.c:192
static void heap_down(Heap *heap, uint i)
Definition BLI_heap.c:82
#define HEAP_PARENT(i)
Definition BLI_heap.c:63
void BLI_heap_clear(Heap *heap, HeapFreeFP ptrfreefp)
Definition BLI_heap.c:214
bool BLI_heap_is_empty(const Heap *heap)
Definition BLI_heap.c:269
void BLI_heap_remove(Heap *heap, HeapNode *node)
Definition BLI_heap.c:307
static struct HeapNode_Chunk * heap_node_alloc_chunk(uint nodes_num, struct HeapNode_Chunk *chunk_prev)
Definition BLI_heap.c:130
static void heap_up(Heap *heap, uint i)
Definition BLI_heap.c:109
uint BLI_heap_len(const Heap *heap)
Definition BLI_heap.c:274
HeapNode * BLI_heap_top(const Heap *heap)
Definition BLI_heap.c:279
static void heap_node_free(Heap *heap, HeapNode *node)
Definition BLI_heap.c:160
HeapNode * BLI_heap_insert(Heap *heap, float value, void *ptr)
Definition BLI_heap.c:235
static bool heap_is_minheap(const Heap *heap, uint root)
Definition BLI_heap.c:357
Heap * BLI_heap_new_ex(uint reserve_num)
Definition BLI_heap.c:172
float BLI_heap_node_value(const HeapNode *heap)
Definition BLI_heap.c:347
static HeapNode * heap_node_alloc(Heap *heap)
Definition BLI_heap.c:141
#define HEAP_CHUNK_DEFAULT_NUM
Definition BLI_heap.c:43
Heap * BLI_heap_new(void)
Definition BLI_heap.c:187
#define HEAP_RIGHT(i)
Definition BLI_heap.c:65
#define HEAP_LEFT(i)
Definition BLI_heap.c:64
#define HEAP_COMPARE(a, b)
Definition BLI_heap.c:66
void BLI_heap_node_value_update(Heap *heap, HeapNode *node, float value)
Definition BLI_heap.c:322
float BLI_heap_top_value(const Heap *heap)
Definition BLI_heap.c:284
A min-heap / priority queue ADT.
void(* HeapFreeFP)(void *ptr)
Definition BLI_heap.h:23
unsigned int uint
#define MAX2(a, b)
#define UNLIKELY(x)
#define LIKELY(x)
Read Guarded memory(de)allocation.
#define MEM_reallocN(vmemh, len)
ATTR_WARN_UNUSED_RESULT const BMLoop * l
OperationNode * node
#define NULL
KDTree_3d * tree
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
HeapNode buf[0]
Definition BLI_heap.c:33
struct HeapNode_Chunk * prev
Definition BLI_heap.c:30
void * ptr
Definition BLI_heap.c:26
float value
Definition BLI_heap.c:24
uint index
Definition BLI_heap.c:25
HeapNode ** tree
Definition BLI_heap.c:49
struct HeapNode_Chunk * chunk
Definition BLI_heap.c:53
uint size
Definition BLI_heap.c:47
struct Heap::@117 nodes
HeapNode * free
Definition BLI_heap.c:55
uint bufsize
Definition BLI_heap.c:48
PointerRNA * ptr
Definition wm_files.cc:4126