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): Daniel Dunbar, Joseph Eagar 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 * A general (pointer -> pointer) hash table ADT 00027 */ 00028 00034 #include <stdlib.h> 00035 #include <string.h> 00036 00037 #include "MEM_guardedalloc.h" 00038 00039 #include "BLI_utildefines.h" 00040 #include "BLI_edgehash.h" 00041 #include "BLI_mempool.h" 00042 00043 /**************inlined code************/ 00044 static unsigned int _ehash_hashsizes[]= { 00045 1, 3, 5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209, 00046 16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169, 00047 4194319, 8388617, 16777259, 33554467, 67108879, 134217757, 00048 268435459 00049 }; 00050 00051 #define EDGE_HASH(v0, v1) ((v0 * 39)^(v1 * 31)) 00052 00053 /* ensure v0 is smaller */ 00054 #define EDGE_ORD(v0, v1) \ 00055 if (v0 > v1) { \ 00056 v0 ^= v1; \ 00057 v1 ^= v0; \ 00058 v0 ^= v1; \ 00059 } 00060 00061 /***/ 00062 00063 typedef struct EdgeEntry EdgeEntry; 00064 struct EdgeEntry { 00065 EdgeEntry *next; 00066 unsigned int v0, v1; 00067 void *val; 00068 }; 00069 00070 struct EdgeHash { 00071 EdgeEntry **buckets; 00072 BLI_mempool *epool; 00073 int nbuckets, nentries, cursize; 00074 }; 00075 00076 /***/ 00077 00078 EdgeHash *BLI_edgehash_new(void) 00079 { 00080 EdgeHash *eh = MEM_callocN(sizeof(*eh), "EdgeHash"); 00081 eh->cursize = 0; 00082 eh->nentries = 0; 00083 eh->nbuckets = _ehash_hashsizes[eh->cursize]; 00084 00085 eh->buckets = MEM_callocN(eh->nbuckets * sizeof(*eh->buckets), "eh buckets 2"); 00086 eh->epool = BLI_mempool_create(sizeof(EdgeEntry), 512, 512, TRUE, FALSE); 00087 00088 return eh; 00089 } 00090 00091 00092 void BLI_edgehash_insert(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val) 00093 { 00094 unsigned int hash; 00095 EdgeEntry *e = BLI_mempool_alloc(eh->epool); 00096 00097 EDGE_ORD(v0, v1); /* ensure v0 is smaller */ 00098 00099 hash = EDGE_HASH(v0, v1) % eh->nbuckets; 00100 00101 e->v0 = v0; 00102 e->v1 = v1; 00103 e->val = val; 00104 e->next = eh->buckets[hash]; 00105 eh->buckets[hash]= e; 00106 00107 if (++eh->nentries>eh->nbuckets * 3) { 00108 EdgeEntry *e, **old = eh->buckets; 00109 int i, nold = eh->nbuckets; 00110 00111 eh->nbuckets = _ehash_hashsizes[++eh->cursize]; 00112 eh->buckets = MEM_mallocN(eh->nbuckets * sizeof(*eh->buckets), "eh buckets"); 00113 memset(eh->buckets, 0, eh->nbuckets * sizeof(*eh->buckets)); 00114 00115 for (i = 0; i < nold; i++) { 00116 for (e = old[i]; e;) { 00117 EdgeEntry *n = e->next; 00118 00119 hash = EDGE_HASH(e->v0, e->v1) % eh->nbuckets; 00120 e->next = eh->buckets[hash]; 00121 eh->buckets[hash]= e; 00122 00123 e = n; 00124 } 00125 } 00126 00127 MEM_freeN(old); 00128 } 00129 } 00130 00131 void **BLI_edgehash_lookup_p(EdgeHash *eh, unsigned int v0, unsigned int v1) 00132 { 00133 unsigned int hash; 00134 EdgeEntry *e; 00135 00136 EDGE_ORD(v0, v1); /* ensure v0 is smaller */ 00137 00138 hash = EDGE_HASH(v0, v1) % eh->nbuckets; 00139 for (e = eh->buckets[hash]; e; e = e->next) 00140 if (v0 == e->v0 && v1 == e->v1) 00141 return &e->val; 00142 00143 return NULL; 00144 } 00145 00146 void *BLI_edgehash_lookup(EdgeHash *eh, unsigned int v0, unsigned int v1) 00147 { 00148 void **value_p = BLI_edgehash_lookup_p(eh, v0, v1); 00149 00150 return value_p?*value_p:NULL; 00151 } 00152 00153 int BLI_edgehash_haskey(EdgeHash *eh, unsigned int v0, unsigned int v1) 00154 { 00155 return BLI_edgehash_lookup_p(eh, v0, v1) != NULL; 00156 } 00157 00158 int BLI_edgehash_size(EdgeHash *eh) 00159 { 00160 return eh->nentries; 00161 } 00162 00163 void BLI_edgehash_clear(EdgeHash *eh, EdgeHashFreeFP valfreefp) 00164 { 00165 int i; 00166 00167 for (i = 0; i<eh->nbuckets; i++) { 00168 EdgeEntry *e; 00169 00170 for (e = eh->buckets[i]; e; ) { 00171 EdgeEntry *n = e->next; 00172 00173 if (valfreefp) valfreefp(e->val); 00174 BLI_mempool_free(eh->epool, e); 00175 00176 e = n; 00177 } 00178 eh->buckets[i] = NULL; 00179 } 00180 00181 eh->nentries = 0; 00182 } 00183 00184 void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP valfreefp) 00185 { 00186 BLI_edgehash_clear(eh, valfreefp); 00187 00188 BLI_mempool_destroy(eh->epool); 00189 00190 MEM_freeN(eh->buckets); 00191 MEM_freeN(eh); 00192 } 00193 00194 00195 /***/ 00196 00197 struct EdgeHashIterator { 00198 EdgeHash *eh; 00199 int curBucket; 00200 EdgeEntry *curEntry; 00201 }; 00202 00203 EdgeHashIterator *BLI_edgehashIterator_new(EdgeHash *eh) 00204 { 00205 EdgeHashIterator *ehi = MEM_mallocN(sizeof(*ehi), "eh iter"); 00206 ehi->eh = eh; 00207 ehi->curEntry = NULL; 00208 ehi->curBucket = -1; 00209 while (!ehi->curEntry) { 00210 ehi->curBucket++; 00211 if (ehi->curBucket == ehi->eh->nbuckets) 00212 break; 00213 ehi->curEntry = ehi->eh->buckets[ehi->curBucket]; 00214 } 00215 return ehi; 00216 } 00217 void BLI_edgehashIterator_free(EdgeHashIterator *ehi) 00218 { 00219 MEM_freeN(ehi); 00220 } 00221 00222 void BLI_edgehashIterator_getKey(EdgeHashIterator *ehi, unsigned int *v0_r, unsigned int *v1_r) 00223 { 00224 if (ehi->curEntry) { 00225 *v0_r = ehi->curEntry->v0; 00226 *v1_r = ehi->curEntry->v1; 00227 } 00228 } 00229 void *BLI_edgehashIterator_getValue(EdgeHashIterator *ehi) 00230 { 00231 return ehi->curEntry?ehi->curEntry->val:NULL; 00232 } 00233 00234 void BLI_edgehashIterator_setValue(EdgeHashIterator *ehi, void *val) 00235 { 00236 if (ehi->curEntry) { 00237 ehi->curEntry->val = val; 00238 } 00239 } 00240 00241 void BLI_edgehashIterator_step(EdgeHashIterator *ehi) 00242 { 00243 if (ehi->curEntry) { 00244 ehi->curEntry = ehi->curEntry->next; 00245 while (!ehi->curEntry) { 00246 ehi->curBucket++; 00247 if (ehi->curBucket == ehi->eh->nbuckets) { 00248 break; 00249 } 00250 00251 ehi->curEntry = ehi->eh->buckets[ehi->curBucket]; 00252 } 00253 } 00254 } 00255 int BLI_edgehashIterator_isDone(EdgeHashIterator *ehi) 00256 { 00257 return !ehi->curEntry; 00258 } 00259