Explorar el Código

structure: CHash: add CHash_MultiplyBuckets()

ambrop7 hace 13 años
padre
commit
113fd7c0b9
Se han modificado 4 ficheros con 70 adiciones y 0 borrados
  1. 1 0
      structure/CHash_decl.h
  2. 1 0
      structure/CHash_footer.h
  3. 1 0
      structure/CHash_header.h
  4. 67 0
      structure/CHash_impl.h

+ 1 - 0
structure/CHash_decl.h

@@ -53,5 +53,6 @@ static void CHash_InsertMulti (CHash *o, CHashArg arg, CHashRef entry);
 static void CHash_Remove (CHash *o, CHashArg arg, CHashRef entry);
 static CHashRef CHash_Lookup (const CHash *o, CHashArg arg, CHashKey key);
 static CHashRef CHash_GetNextEqual (const CHash *o, CHashArg arg, CHashRef entry);
+static int CHash_MultiplyBuckets (CHash *o, CHashArg arg, int exp);
 
 #include "CHash_footer.h"

+ 1 - 0
structure/CHash_footer.h

@@ -66,6 +66,7 @@
 #undef CHash_Remove
 #undef CHash_Lookup
 #undef CHash_GetNextEqual
+#undef CHash_MultiplyBuckets
 
 // private things
 #undef CHash_next

+ 1 - 0
structure/CHash_header.h

@@ -66,6 +66,7 @@
 #define CHash_Remove MERGE(CHash, _Remove)
 #define CHash_Lookup MERGE(CHash, _Lookup)
 #define CHash_GetNextEqual MERGE(CHash, _GetNextEqual)
+#define CHash_MultiplyBuckets MERGE(CHash, _MultiplyBuckets)
 
 // private things
 #define CHash_next(entry) ((entry).ptr->CHASH_PARAM_ENTRY_NEXT)

+ 67 - 0
structure/CHash_impl.h

@@ -214,4 +214,71 @@ static CHashRef CHash_GetNextEqual (const CHash *o, CHashArg arg, CHashRef entry
     return next_ref;
 }
 
+static int CHash_MultiplyBuckets (CHash *o, CHashArg arg, int exp)
+{
+    ASSERT(exp > 0)
+    
+    size_t new_num_buckets = o->num_buckets;
+    while (exp-- > 0) {
+        if (new_num_buckets > SIZE_MAX / 2) {
+            return 0;
+        }
+        new_num_buckets *= 2;
+    }
+    
+    CHashLink *new_buckets = (CHashLink *)BReallocArray(o->buckets, new_num_buckets, sizeof(new_buckets[0]));
+    if (!new_buckets) {
+        return 0;
+    }
+    o->buckets = new_buckets;
+    
+    for (size_t i = o->num_buckets; i < new_num_buckets; i++) {
+        o->buckets[i] = CHashNullLink();
+    }
+    
+    for (size_t i = 0; i < o->num_buckets; i++) {
+        CHashRef prev = CHashNullRef();
+        CHashLink link = o->buckets[i];
+        
+        while (link != CHashNullLink()) {
+            CHashRef cur = CHashDerefNonNull(arg, link);
+            link = CHash_next(cur);
+            
+            size_t new_index = CHASH_PARAM_ENTRYHASH(arg, cur) % new_num_buckets;
+            if (new_index == i) {
+                prev = cur;
+                continue;
+            }
+            
+            if (CHashIsNullRef(prev)) {
+                o->buckets[i] = CHash_next(cur);
+            } else {
+                CHash_next(prev) = CHash_next(cur);
+            }
+            
+            CHash_next(cur) = o->buckets[new_index];
+            o->buckets[new_index] = cur.link;
+        }
+    }
+    
+    for (size_t i = o->num_buckets; i < new_num_buckets; i++) {
+        CHashLink new_bucket_link = CHashNullLink();
+        
+        CHashLink link = o->buckets[i];
+        while (link != CHashNullLink()) {
+            CHashRef cur = CHashDerefNonNull(arg, link);
+            link = CHash_next(cur);
+            
+            CHash_next(cur) = new_bucket_link;
+            new_bucket_link = cur.link;
+        }
+        
+        o->buckets[i] = new_bucket_link;
+    }
+    
+    o->num_buckets = new_num_buckets;
+    
+    return 1;
+}
+
 #include "CHash_footer.h"