Blender V2.61 - r43446

BLI_heap.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: none of this file.
00022  *
00023  * Contributor(s): Brecht Van Lommel
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  * A heap / priority queue ADT.
00027  */
00028 
00034 #include <string.h>
00035 
00036 #include "MEM_guardedalloc.h"
00037 #include "BLI_memarena.h"
00038 #include "BLI_heap.h"
00039 
00040 /***/
00041 
00042 struct HeapNode {
00043     void *ptr;
00044     float value;
00045     int index;
00046 };
00047 
00048 struct Heap {
00049     unsigned int size;
00050     unsigned int bufsize;
00051     MemArena *arena;
00052     HeapNode *freenodes;
00053     HeapNode *nodes;
00054     HeapNode **tree;
00055 };
00056 
00057 #define SWAP(type, a, b) \
00058     { type sw_ap; sw_ap=(a); (a)=(b); (b)=sw_ap; }
00059 #define HEAP_PARENT(i) ((i-1)>>1)
00060 #define HEAP_LEFT(i)   ((i<<1)+1)
00061 #define HEAP_RIGHT(i)  ((i<<1)+2)
00062 #define HEAP_COMPARE(a, b) (a->value < b->value)
00063 #define HEAP_EQUALS(a, b) (a->value == b->value)
00064 #define HEAP_SWAP(heap, i, j) \
00065 {                                                                             \
00066     SWAP(int, heap->tree[i]->index, heap->tree[j]->index);                    \
00067     SWAP(HeapNode*, heap->tree[i], heap->tree[j]);                            \
00068 }
00069 
00070 /***/
00071 
00072 Heap *BLI_heap_new(void)
00073 {
00074     Heap *heap = (Heap*)MEM_callocN(sizeof(Heap), "BLIHeap");
00075     heap->bufsize = 1;
00076     heap->tree = (HeapNode**)MEM_mallocN(sizeof(HeapNode*), "BLIHeapTree");
00077     heap->arena = BLI_memarena_new(1<<16, "heap arena");
00078 
00079     return heap;
00080 }
00081 
00082 void BLI_heap_free(Heap *heap, HeapFreeFP ptrfreefp)
00083 {
00084     int i;
00085 
00086     if (ptrfreefp)
00087         for (i = 0; i < heap->size; i++)
00088             ptrfreefp(heap->tree[i]->ptr);
00089     
00090     MEM_freeN(heap->tree);
00091     BLI_memarena_free(heap->arena);
00092     MEM_freeN(heap);
00093 }
00094 
00095 static void BLI_heap_down(Heap *heap, int i)
00096 {
00097     while (1) {
00098         int size = heap->size, smallest;
00099         int l = HEAP_LEFT(i);
00100         int r = HEAP_RIGHT(i);
00101 
00102         smallest = ((l < size) && HEAP_COMPARE(heap->tree[l], heap->tree[i]))? l: i;
00103 
00104         if ((r < size) && HEAP_COMPARE(heap->tree[r], heap->tree[smallest]))
00105             smallest = r;
00106         
00107         if (smallest == i)
00108             break;
00109 
00110         HEAP_SWAP(heap, i, smallest);
00111         i = smallest;
00112     }
00113 }
00114 
00115 static void BLI_heap_up(Heap *heap, int i)
00116 {
00117     while (i > 0) {
00118         int p = HEAP_PARENT(i);
00119 
00120         if (HEAP_COMPARE(heap->tree[p], heap->tree[i]))
00121             break;
00122 
00123         HEAP_SWAP(heap, p, i);
00124         i = p;
00125     }
00126 }
00127 
00128 HeapNode *BLI_heap_insert(Heap *heap, float value, void *ptr)
00129 {
00130     HeapNode *node;
00131 
00132     if ((heap->size + 1) > heap->bufsize) {
00133         int newsize = heap->bufsize*2;
00134         HeapNode **newtree;
00135 
00136         newtree = (HeapNode**)MEM_mallocN(newsize*sizeof(*newtree), "BLIHeapTree");
00137         memcpy(newtree, heap->tree, sizeof(HeapNode*)*heap->size);
00138         MEM_freeN(heap->tree);
00139 
00140         heap->tree = newtree;
00141         heap->bufsize = newsize;
00142     }
00143 
00144     if (heap->freenodes) {
00145         node = heap->freenodes;
00146         heap->freenodes = (HeapNode*)(((HeapNode*)heap->freenodes)->ptr);
00147     }
00148     else
00149         node = (HeapNode*)BLI_memarena_alloc(heap->arena, sizeof *node);
00150 
00151     node->value = value;
00152     node->ptr = ptr;
00153     node->index = heap->size;
00154 
00155     heap->tree[node->index] = node;
00156 
00157     heap->size++;
00158 
00159     BLI_heap_up(heap, heap->size-1);
00160 
00161     return node;
00162 }
00163 
00164 int BLI_heap_empty(Heap *heap)
00165 {
00166     return (heap->size == 0);
00167 }
00168 
00169 int BLI_heap_size(Heap *heap)
00170 {
00171     return heap->size;
00172 }
00173 
00174 HeapNode *BLI_heap_top(Heap *heap)
00175 {
00176     return heap->tree[0];
00177 }
00178 
00179 void *BLI_heap_popmin(Heap *heap)
00180 {
00181     void *ptr = heap->tree[0]->ptr;
00182 
00183     heap->tree[0]->ptr = heap->freenodes;
00184     heap->freenodes = heap->tree[0];
00185 
00186     if (heap->size == 1)
00187         heap->size--;
00188     else {
00189         HEAP_SWAP(heap, 0, heap->size-1);
00190         heap->size--;
00191 
00192         BLI_heap_down(heap, 0);
00193     }
00194 
00195     return ptr;
00196 }
00197 
00198 void BLI_heap_remove(Heap *heap, HeapNode *node)
00199 {
00200     int i = node->index;
00201 
00202     while (i > 0) {
00203         int p = HEAP_PARENT(i);
00204 
00205         HEAP_SWAP(heap, p, i);
00206         i = p;
00207     }
00208 
00209     BLI_heap_popmin(heap);
00210 }
00211 
00212 float BLI_heap_node_value(HeapNode *node)
00213 {
00214     return node->value;
00215 }
00216 
00217 void *BLI_heap_node_ptr(HeapNode *node)
00218 {
00219     return node->ptr;
00220 }
00221