Blender  V2.59
edgehash.c
Go to the documentation of this file.
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