Blender V2.61 - r43446

edgehash.c

Go to the documentation of this file.
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