diff options
author | Justus Winter <4winter@informatik.uni-hamburg.de> | 2015-11-27 03:24:24 +0100 |
---|---|---|
committer | Justus Winter <4winter@informatik.uni-hamburg.de> | 2015-11-29 23:57:56 +0100 |
commit | 4e2d5a81bb2834f7393e9847bfa091f8a0a07556 (patch) | |
tree | 87eb878db4a269948a39566f14be9315733f5919 /libihash | |
parent | 1842a9dcd1056dac886e96071e8c5dcd2859d471 (diff) |
libihash: provide a general purpose hash algorithm
* libdiskfs/name-cache.c: Move the Murmur3 algorithm...
* libihash/murmur3.c: ... here, and properly attribute the code.
* libihash/ihash.h (hurd_ihash_hash32): New prototype.
* libihash/Makefile (SRCS): Add new file.
Diffstat (limited to 'libihash')
-rw-r--r-- | libihash/Makefile | 2 | ||||
-rw-r--r-- | libihash/ihash.h | 5 | ||||
-rw-r--r-- | libihash/murmur3.c | 93 |
3 files changed, 99 insertions, 1 deletions
diff --git a/libihash/Makefile b/libihash/Makefile index 09bb1362..3377ef41 100644 --- a/libihash/Makefile +++ b/libihash/Makefile @@ -20,7 +20,7 @@ dir := libihash makemode := library libname := libihash -SRCS = ihash.c +SRCS = ihash.c murmur3.c installhdrs = ihash.h OBJS = $(SRCS:.c=.o) diff --git a/libihash/ihash.h b/libihash/ihash.h index 28fefe80..356f6473 100644 --- a/libihash/ihash.h +++ b/libihash/ihash.h @@ -349,5 +349,10 @@ int hurd_ihash_remove (hurd_ihash_t ht, hurd_ihash_key_t key); was provided to hurd_ihash_add(). This call is faster than hurd_ihash_remove(). */ void hurd_ihash_locp_remove (hurd_ihash_t ht, hurd_ihash_locp_t locp); + +/* We provide a general purpose hash function. This function can be + used with the generalized key interface to use arbitrary data as + keys using this library. */ +uint32_t hurd_ihash_hash32 (const void *buf, size_t len, uint32_t seed); #endif /* _HURD_IHASH_H */ diff --git a/libihash/murmur3.c b/libihash/murmur3.c new file mode 100644 index 00000000..e45180a4 --- /dev/null +++ b/libihash/murmur3.c @@ -0,0 +1,93 @@ +/* This is the Murmur3 hash algorithm. + * + * MurmurHash3 was written by Austin Appleby, and is placed in the public + * domain. The author hereby disclaims copyright to this source code. + */ + +#include <stdint.h> +#include <stdio.h> + +#define FORCE_INLINE static inline __attribute__((always_inline)) + +static inline uint32_t rotl32 ( uint32_t x, int8_t r ) +{ + return (x << r) | (x >> (32 - r)); +} + +#define ROTL32(x,y) rotl32(x,y) + +/* Block read - if your platform needs to do endian-swapping or can + only handle aligned reads, do the conversion here. */ + +FORCE_INLINE uint32_t getblock32 ( const uint32_t * p, int i ) +{ + return p[i]; +} + +/* Finalization mix - force all bits of a hash block to avalanche. */ + +FORCE_INLINE uint32_t fmix32 ( uint32_t h ) +{ + h ^= h >> 16; + h *= 0x85ebca6b; + h ^= h >> 13; + h *= 0xc2b2ae35; + h ^= h >> 16; + + return h; +} + +/* The Murmur3 hash function. */ +static uint32_t +MurmurHash3_x86_32 (const void *key, size_t len, uint32_t seed) +{ + const uint8_t * data = (const uint8_t*)key; + const int nblocks = (int) (len / 4); + + uint32_t h1 = seed; + + const uint32_t c1 = 0xcc9e2d51; + const uint32_t c2 = 0x1b873593; + + /* body */ + + const uint32_t * blocks = (const uint32_t *)(data + nblocks*4); + + for(int i = -nblocks; i; i++) + { + uint32_t k1 = getblock32(blocks,i); + + k1 *= c1; + k1 = ROTL32(k1,15); + k1 *= c2; + + h1 ^= k1; + h1 = ROTL32(h1,13); + h1 = h1*5+0xe6546b64; + } + + /* tail */ + + const uint8_t * tail = (const uint8_t*)(data + nblocks*4); + + uint32_t k1 = 0; + + switch(len & 3) + { + case 3: k1 ^= tail[2] << 16; + case 2: k1 ^= tail[1] << 8; + case 1: k1 ^= tail[0]; + k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1; + }; + + /* finalization */ + + h1 ^= len; + + h1 = fmix32(h1); + + return h1; +} + +uint32_t hurd_ihash_hash32 (const void *, size_t, uint32_t) + __attribute__ ((weak, alias ("MurmurHash3_x86_32"))); |