From 16b4af3b138fa58614fc7452614802b71a0c2236 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Grubbstr=C3=B6m=20=28Grubba=29?= <grubba@grubba.org> Date: Wed, 27 Aug 2014 21:06:41 +0200 Subject: [PATCH] Cyclic: Change to a power of two hash table. The hash table used by BEGIN_CYCLIC() et al now has a size that is a power of 2, so that we can avoid the modulo operation. The hash function is also modified somewhat to improve its entropy. --- src/cyclic.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/cyclic.c b/src/cyclic.c index 6715437414..f09f86fb1b 100644 --- a/src/cyclic.c +++ b/src/cyclic.c @@ -7,7 +7,7 @@ #include "global.h" #include "cyclic.h" -#define CYCLIC_HASH_SIZE 4711 +#define CYCLIC_HASH_SIZE 0x1000 static CYCLIC *cyclic_hash[CYCLIC_HASH_SIZE]; @@ -22,9 +22,25 @@ static size_t cyclic_hash_func(CYCLIC *c) h ^= PTR_TO_INT(c->b); h *= 33; h ^= PTR_TO_INT(c->th); - h *= 33; - return h % CYCLIC_HASH_SIZE; +#if SIZEOF_CHAR_P > 4 + h ^= h>>8; +#endif + /* Fold h. This is to retain as many bits of h as possible. + * + * NB: The "magic" constant below has a 1 bit every 10 bits + * starting at the least significant, and is == 1 when + * shifted right 20 bits. Note also that 32 - 20 == 12 + * and 1<<12 == 0x1000 == CYCLIC_HASH_SIZE. + * + * The multiplication has the effect of accumulating + * the segments of 10 bits of h in the most significant + * segment, which is then shifted down. + */ + h *= 0x100401; + h >>= 20; + + return h & (CYCLIC_HASH_SIZE-1); } static void low_unlink_cyclic(CYCLIC *c) -- GitLab