Blender  V2.59
BLI_heap.c
Go to the documentation of this file.
00001 /*
00002  * $Id: BLI_heap.c 35246 2011-02-27 20:37:56Z jesterking $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00021  * All rights reserved.
00022  *
00023  * The Original Code is: none of this file.
00024  *
00025  * Contributor(s): Brecht Van Lommel
00026  *
00027  * ***** END GPL LICENSE BLOCK *****
00028  * A heap / priority queue ADT.
00029  */
00030 
00036 #include <string.h>
00037 
00038 #include "MEM_guardedalloc.h"
00039 #include "BLI_memarena.h"
00040 #include "BLI_heap.h"
00041 
00042 /***/
00043 
00044 struct HeapNode {
00045         void *ptr;
00046         float value;
00047         int index;
00048 };
00049 
00050 struct Heap {
00051         unsigned int size;
00052         unsigned int bufsize;
00053         MemArena *arena;
00054         HeapNode *freenodes;
00055         HeapNode *nodes;
00056         HeapNode **tree;
00057 };
00058 
00059 #define SWAP(type, a, b) \
00060         { type sw_ap; sw_ap=(a); (a)=(b); (b)=sw_ap; }
00061 #define HEAP_PARENT(i) ((i-1)>>1)
00062 #define HEAP_LEFT(i)   ((i<<1)+1)
00063 #define HEAP_RIGHT(i)  ((i<<1)+2)
00064 #define HEAP_COMPARE(a, b) (a->value < b->value)
00065 #define HEAP_EQUALS(a, b) (a->value == b->value)
00066 #define HEAP_SWAP(heap, i, j) \
00067         { SWAP(int, heap->tree[i]->index, heap->tree[j]->index); \
00068           SWAP(HeapNode*, heap->tree[i], heap->tree[j]);  }
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