diff --git a/src/cyclic.c b/src/cyclic.c index 6715437414f8189aa6bfe79a565a23669ac0a242..f09f86fb1b4e496eb487d865e485330c0fa5f239 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)