Blender V2.61 - r43446
|
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