| 1 | /* $NetBSD: murmurhash.c,v 1.6 2013/10/26 21:06:38 rmind Exp $ */ |
| 2 | |
| 3 | /* |
| 4 | * MurmurHash2 -- from the original code: |
| 5 | * |
| 6 | * "MurmurHash2 was written by Austin Appleby, and is placed in the public |
| 7 | * domain. The author hereby disclaims copyright to this source code." |
| 8 | * |
| 9 | * References: |
| 10 | * http://code.google.com/p/smhasher/ |
| 11 | * https://sites.google.com/site/murmurhash/ |
| 12 | */ |
| 13 | |
| 14 | #include <sys/cdefs.h> |
| 15 | |
| 16 | #if defined(_KERNEL) || defined(_STANDALONE) |
| 17 | __KERNEL_RCSID(0, "$NetBSD: murmurhash.c,v 1.6 2013/10/26 21:06:38 rmind Exp $" ); |
| 18 | |
| 19 | #else |
| 20 | |
| 21 | #if defined(LIBC_SCCS) && !defined(lint) |
| 22 | __RCSID("$NetBSD: murmurhash.c,v 1.6 2013/10/26 21:06:38 rmind Exp $" ); |
| 23 | #endif /* LIBC_SCCS and not lint */ |
| 24 | |
| 25 | #include "namespace.h" |
| 26 | #endif |
| 27 | |
| 28 | #include <sys/types.h> |
| 29 | #include <sys/param.h> |
| 30 | #include <sys/hash.h> |
| 31 | |
| 32 | #if !defined(_KERNEL) && !defined(_STANDALONE) |
| 33 | #ifdef __weak_alias |
| 34 | __weak_alias(murmurhash2,_murmurhash2) |
| 35 | #endif |
| 36 | #endif |
| 37 | |
| 38 | uint32_t |
| 39 | murmurhash2(const void *key, size_t len, uint32_t seed) |
| 40 | { |
| 41 | /* |
| 42 | * Note: 'm' and 'r' are mixing constants generated offline. |
| 43 | * They're not really 'magic', they just happen to work well. |
| 44 | * Initialize the hash to a 'random' value. |
| 45 | */ |
| 46 | const uint32_t m = 0x5bd1e995; |
| 47 | const int r = 24; |
| 48 | |
| 49 | const uint8_t *data = key; |
| 50 | uint32_t h = seed ^ (uint32_t)len; |
| 51 | |
| 52 | if (__predict_true(ALIGNED_POINTER(key, uint32_t))) { |
| 53 | while (len >= sizeof(uint32_t)) { |
| 54 | uint32_t k = *(const uint32_t *)data; |
| 55 | |
| 56 | k *= m; |
| 57 | k ^= k >> r; |
| 58 | k *= m; |
| 59 | |
| 60 | h *= m; |
| 61 | h ^= k; |
| 62 | |
| 63 | data += sizeof(uint32_t); |
| 64 | len -= sizeof(uint32_t); |
| 65 | } |
| 66 | } else { |
| 67 | while (len >= sizeof(uint32_t)) { |
| 68 | uint32_t k; |
| 69 | |
| 70 | k = data[0]; |
| 71 | k |= data[1] << 8; |
| 72 | k |= data[2] << 16; |
| 73 | k |= data[3] << 24; |
| 74 | |
| 75 | k *= m; |
| 76 | k ^= k >> r; |
| 77 | k *= m; |
| 78 | |
| 79 | h *= m; |
| 80 | h ^= k; |
| 81 | |
| 82 | data += sizeof(uint32_t); |
| 83 | len -= sizeof(uint32_t); |
| 84 | } |
| 85 | } |
| 86 | |
| 87 | /* Handle the last few bytes of the input array. */ |
| 88 | switch (len) { |
| 89 | case 3: |
| 90 | h ^= data[2] << 16; |
| 91 | /* FALLTHROUGH */ |
| 92 | case 2: |
| 93 | h ^= data[1] << 8; |
| 94 | /* FALLTHROUGH */ |
| 95 | case 1: |
| 96 | h ^= data[0]; |
| 97 | h *= m; |
| 98 | } |
| 99 | |
| 100 | /* |
| 101 | * Do a few final mixes of the hash to ensure the last few |
| 102 | * bytes are well-incorporated. |
| 103 | */ |
| 104 | h ^= h >> 13; |
| 105 | h *= m; |
| 106 | h ^= h >> 15; |
| 107 | |
| 108 | return h; |
| 109 | } |
| 110 | |