shithub: mc

Download patch

ref: 778aadfc5a73c80a9046250b00a085e074a1870f
parent: 336413341a83ffd0294b16e2debe1ec5132fa19b
author: Ori Bernstein <[email protected]>
date: Tue May 24 21:58:52 EDT 2016

Improve hash functions.

--- a/test/runtest.sh
+++ b/test/runtest.sh
@@ -10,6 +10,7 @@
 
 function build {
 	rm -f $1 $1.o $1.s $1.use
+	echo mbld -b $1 -C../6/6m -M../muse/muse -I../lib/std -I../lib/sys -r../rt/_myrrt.o $1.myr
 	mbld -b $1 -C../6/6m -M../muse/muse -I../lib/std -I../lib/sys -r../rt/_myrrt.o $1.myr
 }
 
--- a/util/htab.c
+++ b/util/htab.c
@@ -9,7 +9,10 @@
 #include "util.h"
 
 #define Initsz 16
+#define Seed 2928213749
 
+ulong murmurhash2(void *key, size_t len);
+
 /* Creates a new empty hash table, using 'hash' as the
  * hash funciton, and 'cmp' to verify that there are no
  * hash collisions. */
@@ -210,20 +213,11 @@
 ulong strhash(void *_s)
 {
 	char *s;
-	ulong h;
-	ulong g;
 
 	s = _s;
-	h = 0;
-	while (s && *s) {
-		h = ((h << 4) + *s++);
-
-		if ((g = (h & 0xF0000000)))
-			h ^= (g >> 24);
-
-		h &= ~g;
-	}
-	return h;
+	if (!s)
+		return Seed;
+	return murmurhash2(_s, strlen(_s));
 }
 
 int streq(void *a, void *b)
@@ -238,19 +232,11 @@
 ulong strlithash(void *_s)
 {
 	Str *s;
-	ulong h, g, i;
 
 	s = _s;
-	h = 0;
-	for (i = 0; i < s->len; i++) {
-		h = ((h << 4) + s->buf[i]);
-
-		if ((g = (h & 0xF0000000)))
-			h ^= (g >> 24);
-
-		h &= ~g;
-	}
-	return h;
+	if (!s)
+		return Seed;
+	return murmurhash2(s->buf, s->len);
 }
 
 int strliteq(void *_a, void *_b)
@@ -272,17 +258,58 @@
 
 ulong inthash(uint64_t key)
 {
-	uintptr_t h;
+	return murmurhash2(&key, sizeof key);
+}
 
-	h = (uintptr_t)key;
-	h *= 357913941;
-	h ^= h << 24;
-	h += ~357913941;
-	h ^= h >> 31;
-	h ^= h << 31;
-	return h;
+int inteq(uint64_t a, uint64_t b)
+{
+	return a == b;
 }
 
-int inteq(uint64_t a, uint64_t b) { return a == b; }
+int ptreq(void *a, void *b)
+{
+	return a == b;
+}
 
-int ptreq(void *a, void *b) { return a == b; }
+ulong murmurhash2 (void *ptr, size_t len)
+{
+	uint32_t m = 0x5bd1e995;
+	uint32_t r = 24;
+	uint32_t h, k;
+	uint32_t *data;
+	char *buf;
+	
+	buf = ptr;
+	data = (uint32_t*)buf;
+	h = Seed ^ len;
+	while (len >= 4) {
+		k = *data;
+
+		k *= m;
+		k ^= k >> r;
+		k *= m;
+
+		h *= m;
+		h ^= k;
+		data++;
+		len -= sizeof(*data);
+	}
+
+	switch (len) {
+	case 3:
+		h ^= buf[2] << 16;
+	case 2:
+		h ^= buf[1] << 8;
+	case 1:
+		h ^= buf[0] << 0;
+	default:
+		break;
+	};
+	h *= m;
+
+	h ^= h >> 13;
+	h *= m;
+	h ^= h >> 15;
+
+	return h;
+}