1 | #include <stdint.h>
|
2 | #include <stdlib.h>
|
3 | #include <string.h>
|
4 |
|
5 | #include "murmur3.h"
|
6 |
|
7 | static inline uint32_t
|
8 | read32(const void *src) {
|
9 | #if defined(MRMR_LITTLE_ENDIAN)
|
10 | uint32_t w;
|
11 | memcpy(&w, src, sizeof w);
|
12 | return w;
|
13 | #else
|
14 | const uint8_t *p = (const uint8_t *)src;
|
15 | return ((uint32_t)(p[0]) << 0)
|
16 | | ((uint32_t)(p[1]) << 8)
|
17 | | ((uint32_t)(p[2]) << 16)
|
18 | | ((uint32_t)(p[3]) << 24);
|
19 | #endif
|
20 | }
|
21 |
|
22 | static inline uint32_t
|
23 | rotl32(uint32_t x, int8_t r) {
|
24 | return (x << r) | (x >> (32 - r));
|
25 | }
|
26 |
|
27 | uint32_t
|
28 | mrmr_murmur3_sum(const uint8_t *data, size_t len, uint32_t seed) {
|
29 | uint32_t h1 = seed;
|
30 |
|
31 | if (len > 0) {
|
32 | const uint32_t c1 = 0xcc9e2d51;
|
33 | const uint32_t c2 = 0x1b873593;
|
34 |
|
35 | const int32_t nblocks = len / 4;
|
36 |
|
37 | const uint8_t *blocks = &data[0] + nblocks * 4;
|
38 |
|
39 | for (int32_t i = -nblocks; i; i++) {
|
40 | uint32_t k1 = read32(blocks + i * 4);
|
41 |
|
42 | k1 *= c1;
|
43 | k1 = rotl32(k1, 15);
|
44 | k1 *= c2;
|
45 |
|
46 | h1 ^= k1;
|
47 | h1 = rotl32(h1, 13);
|
48 | h1 = h1 * 5 + 0xe6546b64;
|
49 | }
|
50 |
|
51 | const uint8_t *tail = (const uint8_t *)(&data[0] + nblocks * 4);
|
52 |
|
53 | uint32_t k1 = 0;
|
54 |
|
55 | switch (len & 3) {
|
56 | case 3:
|
57 | k1 ^= tail[2] << 16;
|
58 | case 2:
|
59 | k1 ^= tail[1] << 8;
|
60 | case 1:
|
61 | k1 ^= tail[0];
|
62 | k1 *= c1;
|
63 | k1 = rotl32(k1, 15);
|
64 | k1 *= c2;
|
65 | h1 ^= k1;
|
66 | }
|
67 | }
|
68 |
|
69 | h1 ^= len;
|
70 | h1 ^= h1 >> 16;
|
71 | h1 *= 0x85ebca6b;
|
72 | h1 ^= h1 >> 13;
|
73 | h1 *= 0xc2b2ae35;
|
74 | h1 ^= h1 >> 16;
|
75 |
|
76 | return h1;
|
77 | }
|
78 |
|
79 | uint32_t
|
80 | mrmr_murmur3_tweak(
|
81 | const uint8_t *data,
|
82 | size_t len,
|
83 | uint32_t n,
|
84 | uint32_t tweak
|
85 | ) {
|
86 | uint32_t seed = (n * 0xfba4c795ul) + tweak;
|
87 | return mrmr_murmur3_sum(data, len, seed);
|
88 | }
|