|
Blender
V2.59
|
00001 /* 00002 * $Id: edgehash.c 36826 2011-05-23 08:14:29Z campbellbarton $ 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): Daniel Dunbar 00026 * 00027 * ***** END GPL LICENSE BLOCK ***** 00028 * A general (pointer -> pointer) hash table ADT 00029 */ 00030 00036 #include <stdlib.h> 00037 #include <string.h> 00038 00039 #include "MEM_guardedalloc.h" 00040 #include "BLI_edgehash.h" 00041 00042 /***/ 00043 00044 static unsigned int 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 EDGEHASH(v0,v1) ((v0*39)^(v1*31)) 00052 00053 /***/ 00054 00055 typedef struct Entry Entry; 00056 struct Entry { 00057 Entry *next; 00058 int v0, v1; 00059 void *val; 00060 }; 00061 00062 struct EdgeHash { 00063 Entry **buckets; 00064 int nbuckets, nentries, cursize; 00065 }; 00066 00067 /***/ 00068 00069 EdgeHash *BLI_edgehash_new(void) { 00070 EdgeHash *eh= MEM_mallocN(sizeof(*eh), "EdgeHash"); 00071 eh->cursize= 0; 00072 eh->nentries= 0; 00073 eh->nbuckets= hashsizes[eh->cursize]; 00074 00075 eh->buckets= malloc(eh->nbuckets*sizeof(*eh->buckets)); 00076 memset(eh->buckets, 0, eh->nbuckets*sizeof(*eh->buckets)); 00077 00078 return eh; 00079 } 00080 00081 void BLI_edgehash_insert(EdgeHash *eh, int v0, int v1, void *val) { 00082 unsigned int hash; 00083 Entry *e= malloc(sizeof(*e)); 00084 00085 if (v1<v0) { 00086 v0 ^= v1; 00087 v1 ^= v0; 00088 v0 ^= v1; 00089 } 00090 hash = EDGEHASH(v0,v1)%eh->nbuckets; 00091 00092 e->v0 = v0; 00093 e->v1 = v1; 00094 e->val = val; 00095 e->next= eh->buckets[hash]; 00096 eh->buckets[hash]= e; 00097 00098 if (++eh->nentries>eh->nbuckets*3) { 00099 Entry **old= eh->buckets; 00100 int i, nold= eh->nbuckets; 00101 00102 eh->nbuckets= hashsizes[++eh->cursize]; 00103 eh->buckets= malloc(eh->nbuckets*sizeof(*eh->buckets)); 00104 memset(eh->buckets, 0, eh->nbuckets*sizeof(*eh->buckets)); 00105 00106 for (i=0; i<nold; i++) { 00107 for (e= old[i]; e;) { 00108 Entry *n= e->next; 00109 00110 hash= EDGEHASH(e->v0,e->v1)%eh->nbuckets; 00111 e->next= eh->buckets[hash]; 00112 eh->buckets[hash]= e; 00113 00114 e= n; 00115 } 00116 } 00117 00118 free(old); 00119 } 00120 } 00121 00122 void** BLI_edgehash_lookup_p(EdgeHash *eh, int v0, int v1) { 00123 unsigned int hash; 00124 Entry *e; 00125 00126 if (v1<v0) { 00127 v0 ^= v1; 00128 v1 ^= v0; 00129 v0 ^= v1; 00130 } 00131 hash = EDGEHASH(v0,v1)%eh->nbuckets; 00132 for (e= eh->buckets[hash]; e; e= e->next) 00133 if (v0==e->v0 && v1==e->v1) 00134 return &e->val; 00135 00136 return NULL; 00137 } 00138 00139 void* BLI_edgehash_lookup(EdgeHash *eh, int v0, int v1) { 00140 void **value_p = BLI_edgehash_lookup_p(eh,v0,v1); 00141 00142 return value_p?*value_p:NULL; 00143 } 00144 00145 int BLI_edgehash_haskey(EdgeHash *eh, int v0, int v1) { 00146 return BLI_edgehash_lookup_p(eh, v0, v1)!=NULL; 00147 } 00148 00149 int BLI_edgehash_size(EdgeHash *eh) { 00150 return eh->nentries; 00151 } 00152 00153 void BLI_edgehash_clear(EdgeHash *eh, EdgeHashFreeFP valfreefp) { 00154 int i; 00155 00156 for (i=0; i<eh->nbuckets; i++) { 00157 Entry *e; 00158 00159 for (e= eh->buckets[i]; e; ) { 00160 Entry *n= e->next; 00161 00162 if (valfreefp) valfreefp(e->val); 00163 free(e); 00164 00165 e= n; 00166 } 00167 eh->buckets[i]= NULL; 00168 } 00169 00170 eh->nentries= 0; 00171 } 00172 00173 void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP valfreefp) { 00174 BLI_edgehash_clear(eh, valfreefp); 00175 00176 free(eh->buckets); 00177 MEM_freeN(eh); 00178 } 00179 00180 00181 /***/ 00182 00183 struct EdgeHashIterator { 00184 EdgeHash *eh; 00185 int curBucket; 00186 Entry *curEntry; 00187 }; 00188 00189 EdgeHashIterator *BLI_edgehashIterator_new(EdgeHash *eh) { 00190 EdgeHashIterator *ehi= malloc(sizeof(*ehi)); 00191 ehi->eh= eh; 00192 ehi->curEntry= NULL; 00193 ehi->curBucket= -1; 00194 while (!ehi->curEntry) { 00195 ehi->curBucket++; 00196 if (ehi->curBucket==ehi->eh->nbuckets) 00197 break; 00198 ehi->curEntry= ehi->eh->buckets[ehi->curBucket]; 00199 } 00200 return ehi; 00201 } 00202 void BLI_edgehashIterator_free(EdgeHashIterator *ehi) { 00203 free(ehi); 00204 } 00205 00206 void BLI_edgehashIterator_getKey(EdgeHashIterator *ehi, int *v0_r, int *v1_r) { 00207 if (ehi->curEntry) { 00208 *v0_r = ehi->curEntry->v0; 00209 *v1_r = ehi->curEntry->v1; 00210 } 00211 } 00212 void *BLI_edgehashIterator_getValue(EdgeHashIterator *ehi) { 00213 return ehi->curEntry?ehi->curEntry->val:NULL; 00214 } 00215 00216 void BLI_edgehashIterator_setValue(EdgeHashIterator *ehi, void *val) { 00217 if(ehi->curEntry) 00218 ehi->curEntry->val= val; 00219 } 00220 00221 void BLI_edgehashIterator_step(EdgeHashIterator *ehi) { 00222 if (ehi->curEntry) { 00223 ehi->curEntry= ehi->curEntry->next; 00224 while (!ehi->curEntry) { 00225 ehi->curBucket++; 00226 if (ehi->curBucket==ehi->eh->nbuckets) 00227 break; 00228 ehi->curEntry= ehi->eh->buckets[ehi->curBucket]; 00229 } 00230 } 00231 } 00232 int BLI_edgehashIterator_isDone(EdgeHashIterator *ehi) { 00233 return !ehi->curEntry; 00234 } 00235