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 | |