merge with trunk at r27259 and commit of a patch by anthony jones to fix msvc (though...
[blender-staging.git] / source / blender / blenlib / BLI_edgehash.h
index e74910ddb0952ae25b8bc0ed5373073dcd0c5cce..50189328e6885cf9feb4927539b9129308bd2db0 100644 (file)
 #ifndef BLI_EDGEHASH_H
 #define BLI_EDGEHASH_H
 
+#include "MEM_guardedalloc.h"
+#include "BKE_utildefines.h"
+#include "BLI_mempool.h"
+
 struct EdgeHash;
 struct EdgeHashIterator;
 typedef struct EdgeHash EdgeHash;
@@ -45,22 +49,22 @@ void                        BLI_edgehash_free               (EdgeHash *eh, EdgeHashFreeFP valfreefp);
        /* Insert edge (v0,v1) into hash with given value, does
         * not check for duplicates.
         */
-void                   BLI_edgehash_insert             (EdgeHash *eh, int v0, int v1, void *val);
+//void                 BLI_edgehash_insert             (EdgeHash *eh, int v0, int v1, void *val);
 
        /* Return value for given edge (v0,v1), or NULL if
         * if key does not exist in hash. (If need exists 
         * to differentiate between key-value being NULL and 
         * lack of key then see BLI_edgehash_lookup_p().
         */
-void*                  BLI_edgehash_lookup             (EdgeHash *eh, int v0, int v1);
+//void*                        BLI_edgehash_lookup             (EdgeHash *eh, int v0, int v1);
 
        /* Return pointer to value for given edge (v0,v1),
         * or NULL if key does not exist in hash.
         */
-void**                 BLI_edgehash_lookup_p   (EdgeHash *eh, int v0, int v1);
+//void**                       BLI_edgehash_lookup_p   (EdgeHash *eh, int v0, int v1);
 
        /* Return boolean true/false if edge (v0,v1) in hash. */
-int                            BLI_edgehash_haskey             (EdgeHash *eh, int v0, int v1);
+//int                          BLI_edgehash_haskey             (EdgeHash *eh, int v0, int v1);
 
        /* Return number of keys in hash. */
 int                            BLI_edgehash_size               (EdgeHash *eh);
@@ -95,5 +99,99 @@ void                         BLI_edgehashIterator_step               (EdgeHashIterator *ehi);
        /* Determine if an iterator is done. */
 int                                    BLI_edgehashIterator_isDone             (EdgeHashIterator *ehi);
 
+/**************inlined code************/
+static unsigned int _ehash_hashsizes[]= {
+       1, 3, 5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209, 
+       16411, 32771, 65537, 131101, 262147, 524309, 1048583, 2097169, 
+       4194319, 8388617, 16777259, 33554467, 67108879, 134217757, 
+       268435459
+};
+
+#define EDGEHASH(v0,v1)                ((v0*39)^(v1*31))
+
+/***/
+
+typedef struct EdgeEntry EdgeEntry;
+struct EdgeEntry {
+       EdgeEntry *next;
+       int v0, v1;
+       void *val;
+};
+
+struct EdgeHash {
+       EdgeEntry **buckets;
+       BLI_mempool *epool;
+       int nbuckets, nentries, cursize;
+};
+
+
+BM_INLINE void BLI_edgehash_insert(EdgeHash *eh, int v0, int v1, void *val) {
+       unsigned int hash;
+       EdgeEntry *e= BLI_mempool_alloc(eh->epool);
+
+       if (v1<v0) {
+               v0 ^= v1;
+               v1 ^= v0;
+               v0 ^= v1;
+       }
+       hash = EDGEHASH(v0,v1)%eh->nbuckets;
+
+       e->v0 = v0;
+       e->v1 = v1;
+       e->val = val;
+       e->next= eh->buckets[hash];
+       eh->buckets[hash]= e;
+       
+       if (++eh->nentries>eh->nbuckets*3) {
+               EdgeEntry *e, **old= eh->buckets;
+               int i, nold= eh->nbuckets;
+               
+               eh->nbuckets= _ehash_hashsizes[++eh->cursize];
+               eh->buckets= MEM_mallocN(eh->nbuckets*sizeof(*eh->buckets), "eh buckets");
+               BMEMSET(eh->buckets, 0, eh->nbuckets*sizeof(*eh->buckets));
+               
+               for (i=0; i<nold; i++) {
+                       for (e= old[i]; e;) {
+                               EdgeEntry *n= e->next;
+                               
+                               hash= EDGEHASH(e->v0,e->v1)%eh->nbuckets;
+                               e->next= eh->buckets[hash];
+                               eh->buckets[hash]= e;
+                               
+                               e= n;
+                       }
+               }
+               
+               MEM_freeN(old);
+       }
+}
+
+BM_INLINE void** BLI_edgehash_lookup_p(EdgeHash *eh, int v0, int v1) {
+       unsigned int hash;
+       EdgeEntry *e;
+
+       if (v1<v0) {
+               v0 ^= v1;
+               v1 ^= v0;
+               v0 ^= v1;
+       }
+       hash = EDGEHASH(v0,v1)%eh->nbuckets;
+       for (e= eh->buckets[hash]; e; e= e->next)
+               if (v0==e->v0 && v1==e->v1)
+                       return &e->val;
+       
+       return NULL;
+}
+
+BM_INLINE void* BLI_edgehash_lookup(EdgeHash *eh, int v0, int v1) {
+       void **value_p = BLI_edgehash_lookup_p(eh,v0,v1);
+
+       return value_p?*value_p:NULL;
+}
+
+BM_INLINE int BLI_edgehash_haskey(EdgeHash *eh, int v0, int v1) {
+       return BLI_edgehash_lookup_p(eh, v0, v1)!=NULL;
+}
+
 #endif