summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Braun <rbraun@sceen.net>2017-05-28 17:48:20 +0200
committerRichard Braun <rbraun@sceen.net>2017-05-28 17:57:29 +0200
commit77ed9c6cb86a97051272175a7426c326edf01bdb (patch)
treea724550dda0c593e179c2252b4b9d5c372531f2e
parenta3c67c1efaf07efe0c28978188153b8ada4f5b8d (diff)
kern/hash: new module
-rw-r--r--Makefrag.am1
-rw-r--r--kern/hash.h112
2 files changed, 113 insertions, 0 deletions
diff --git a/Makefrag.am b/Makefrag.am
index 243c2245..bae713b8 100644
--- a/Makefrag.am
+++ b/Makefrag.am
@@ -27,6 +27,7 @@ x15_SOURCES += \
kern/cpumap.h \
kern/error.c \
kern/error.h \
+ kern/hash.h \
kern/init.h \
kern/intr.c \
kern/intr.h \
diff --git a/kern/hash.h b/kern/hash.h
new file mode 100644
index 00000000..108d4b46
--- /dev/null
+++ b/kern/hash.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2010-2017 Richard Braun.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * Hash functions for integers and strings.
+ *
+ * Integer hashing follows Thomas Wang's paper about his 32/64-bits mix
+ * functions :
+ * - https://gist.github.com/badboy/6267743
+ *
+ * String hashing uses a variant of the djb2 algorithm with k=31, as in
+ * the implementation of the hashCode() method of the Java String class :
+ * - http://www.javamex.com/tutorials/collections/hash_function_technical.shtml
+ *
+ * Note that this algorithm isn't suitable to obtain usable 64-bits hashes
+ * and is expected to only serve as an array index producer.
+ *
+ * These functions all have a bits parameter that indicates the number of
+ * relevant bits the caller is interested in. When returning a hash, its
+ * value must be truncated so that it can fit in the requested bit size.
+ * It can be used by the implementation to select high or low bits, depending
+ * on their relative randomness. To get complete, unmasked hashes, use the
+ * HASH_ALLBITS macro.
+ */
+
+#ifndef _KERN_HASH_H
+#define _KERN_HASH_H
+
+#include <stdint.h>
+#include <string.h>
+
+#include <kern/assert.h>
+
+#ifdef __LP64__
+#define HASH_ALLBITS 64
+#define hash_long(n, bits) hash_int64(n, bits)
+#else /* __LP64__ */
+static_assert(sizeof(long) == 4, "unsupported data model");
+#define HASH_ALLBITS 32
+#define hash_long(n, bits) hash_int32(n, bits)
+#endif
+
+static inline uint32_t
+hash_int32(uint32_t n, unsigned int bits)
+{
+ uint32_t hash;
+
+ hash = n;
+ hash = ~hash + (hash << 15);
+ hash ^= (hash >> 12);
+ hash += (hash << 2);
+ hash ^= (hash >> 4);
+ hash += (hash << 3) + (hash << 11);
+ hash ^= (hash >> 16);
+
+ return hash >> (32 - bits);
+}
+
+static inline uint64_t
+hash_int64(uint64_t n, unsigned int bits)
+{
+ uint64_t hash;
+
+ hash = n;
+ hash = ~hash + (hash << 21);
+ hash ^= (hash >> 24);
+ hash += (hash << 3) + (hash << 8);
+ hash ^= (hash >> 14);
+ hash += (hash << 2) + (hash << 4);
+ hash ^= (hash >> 28);
+ hash += (hash << 31);
+
+ return hash >> (64 - bits);
+}
+
+static inline uintptr_t
+hash_ptr(const void *ptr, unsigned int bits)
+{
+ if (sizeof(uintptr_t) == 8) {
+ return hash_int64((uintptr_t)ptr, bits);
+ } else {
+ return hash_int32((uintptr_t)ptr, bits);
+ }
+}
+
+static inline unsigned long
+hash_str(const char *str, unsigned int bits)
+{
+ unsigned long hash;
+ char c;
+
+ for (hash = 0; (c = *str) != '\0'; str++) {
+ hash = ((hash << 5) - hash) + c;
+ }
+
+ return hash & ((1 << bits) - 1);
+}
+
+#endif /* _KERN_HASH_H */