/src/php-src/ext/hash/murmur/PMurHash.c
Line | Count | Source |
1 | | /*----------------------------------------------------------------------------- |
2 | | * MurmurHash3 was written by Austin Appleby, and is placed in the public |
3 | | * domain. |
4 | | * |
5 | | * This implementation was written by Shane Day, and is also public domain. |
6 | | * |
7 | | * This is a portable ANSI C implementation of MurmurHash3_x86_32 (Murmur3A) |
8 | | * with support for progressive processing. |
9 | | */ |
10 | | |
11 | | /*----------------------------------------------------------------------------- |
12 | | |
13 | | If you want to understand the MurmurHash algorithm you would be much better |
14 | | off reading the original source. Just point your browser at: |
15 | | http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp |
16 | | |
17 | | |
18 | | What this version provides? |
19 | | |
20 | | 1. Progressive data feeding. Useful when the entire payload to be hashed |
21 | | does not fit in memory or when the data is streamed through the application. |
22 | | Also useful when hashing a number of strings with a common prefix. A partial |
23 | | hash of a prefix string can be generated and reused for each suffix string. |
24 | | |
25 | | How does it work? |
26 | | |
27 | | We can only process entire 32 bit chunks of input, except for the very end |
28 | | that may be shorter. So along with the partial hash we need to give back to |
29 | | the caller a carry containing up to 3 bytes that we were unable to process. |
30 | | This carry also needs to record the number of bytes the carry holds. I use |
31 | | the low 2 bits as a count (0..3) and the carry bytes are shifted into the |
32 | | high byte in stream order. |
33 | | |
34 | | To handle endianess I simply use a macro that reads a uint32_t and define |
35 | | that macro to be a direct read on little endian machines, a read and swap |
36 | | on big endian machines, or a byte-by-byte read if the endianess is unknown. |
37 | | |
38 | | -----------------------------------------------------------------------------*/ |
39 | | |
40 | | |
41 | | #include "PMurHash.h" |
42 | | |
43 | | // /* MSVC warnings we choose to ignore */ |
44 | | // #if defined(_MSC_VER) |
45 | | // #pragma warning(disable: 4127) /* conditional expression is constant */ |
46 | | // #endif |
47 | | |
48 | | /*----------------------------------------------------------------------------- |
49 | | * Endianess, misalignment capabilities and util macros |
50 | | * |
51 | | * The following 3 macros are defined in this section. The other macros defined |
52 | | * are only needed to help derive these 3. |
53 | | * |
54 | | * READ_UINT32(x) Read a little endian unsigned 32-bit int |
55 | | * UNALIGNED_SAFE Defined if READ_UINT32 works on non-word boundaries |
56 | | * ROTL32(x,r) Rotate x left by r bits |
57 | | */ |
58 | | |
59 | | /* I386 or AMD64 */ |
60 | | #if defined(_M_I86) || defined(_M_IX86) || defined(_X86_) || defined(__i386__) || defined(__i386) || defined(i386) \ |
61 | | || defined(_M_X64) || defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) || defined(__amd64) |
62 | | #define UNALIGNED_SAFE |
63 | | #endif |
64 | | /* I386 or AMD64 */ |
65 | | #if defined(_M_I86) || defined(_M_IX86) || defined(_X86_) || defined(__i386__) || defined(__i386) || defined(i386) \ |
66 | | || defined(_M_X64) || defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) || defined(__amd64) |
67 | | #define UNALIGNED_SAFE |
68 | | #endif |
69 | | |
70 | | /* Avoid miscompiled aligned reads with the v142 ARM64 optimizer. */ |
71 | | #if defined(_MSC_VER) && _MSC_VER < 1930 && defined(_M_ARM64) && !defined(__clang__) |
72 | | #define UNALIGNED_SAFE |
73 | | #endif |
74 | | |
75 | | /* Find best way to ROTL */ |
76 | | #if defined(_MSC_VER) |
77 | | #define FORCE_INLINE static __forceinline |
78 | | #include <stdlib.h> /* Microsoft put _rotl declaration in here */ |
79 | | #define ROTL32(x,y) _rotl(x,y) |
80 | | #else |
81 | | #define FORCE_INLINE static inline __attribute__((always_inline)) |
82 | | /* gcc recognises this code and generates a rotate instruction for CPUs with one */ |
83 | 442k | #define ROTL32(x,r) (((uint32_t)x << r) | ((uint32_t)x >> (32 - r))) |
84 | | #endif |
85 | | |
86 | | #include "endianness.h" |
87 | | |
88 | 221k | #define READ_UINT32(ptr) getblock32((uint32_t *)ptr, 0) |
89 | | |
90 | | /*----------------------------------------------------------------------------- |
91 | | * Core murmurhash algorithm macros */ |
92 | | |
93 | | static const uint32_t kC1 = 0xcc9e2d51; |
94 | | static const uint32_t kC2 = 0x1b873593; |
95 | | |
96 | | /* This is the main processing body of the algorithm. It operates |
97 | | * on each full 32-bits of input. */ |
98 | 221k | #define doblock(h1, k1) \ |
99 | 221k | do {\ |
100 | 221k | k1 *= kC1;\ |
101 | 221k | k1 = ROTL32(k1,15);\ |
102 | 221k | k1 *= kC2;\ |
103 | 221k | \ |
104 | 221k | h1 ^= k1;\ |
105 | 221k | h1 = ROTL32(h1,13);\ |
106 | 221k | h1 = h1*5+0xe6546b64;\ |
107 | 221k | } while(0) |
108 | | |
109 | | /* Append unaligned bytes to carry, forcing hash churn if we have 4 bytes */ |
110 | | /* cnt=bytes to process, h1=name of h1 var, c=carry, n=bytes in c, ptr/len=payload */ |
111 | 35 | #define dobytes(cnt, h1, c, n, ptr, len) \ |
112 | 35 | do {\ |
113 | 35 | unsigned __cnt = cnt;\ |
114 | 81 | while(__cnt--) {\ |
115 | 46 | c = c>>8 | (uint32_t)*ptr++<<24;\ |
116 | 46 | n++; len--;\ |
117 | 46 | if(n==4) {\ |
118 | 13 | doblock(h1, c);\ |
119 | 13 | n = 0;\ |
120 | 13 | }\ |
121 | 46 | }\ |
122 | 35 | } while(0) |
123 | | |
124 | | /*---------------------------------------------------------------------------*/ |
125 | | |
126 | | /* Main hashing function. Initialise carry to 0 and h1 to 0 or an initial seed |
127 | | * if wanted. Both ph1 and pcarry are required arguments. */ |
128 | | void PMurHash32_Process(uint32_t *ph1, uint32_t *pcarry, const void *key, int len) |
129 | 22 | { |
130 | 22 | uint32_t h1 = *ph1; |
131 | 22 | uint32_t c = *pcarry; |
132 | | |
133 | 22 | const uint8_t *ptr = (uint8_t*)key; |
134 | 22 | const uint8_t *end; |
135 | | |
136 | | /* Extract carry count from low 2 bits of c value */ |
137 | 22 | int n = c & 3; |
138 | | |
139 | 22 | #if defined(UNALIGNED_SAFE) |
140 | | /* This CPU handles unaligned word access */ |
141 | | // #pragma message ( "UNALIGNED_SAFE" ) |
142 | | /* Consume any carry bytes */ |
143 | 22 | int i = (4-n) & 3; |
144 | 22 | if(i && i <= len) { |
145 | 13 | dobytes(i, h1, c, n, ptr, len); |
146 | 13 | } |
147 | | |
148 | | /* Process 32-bit chunks */ |
149 | 22 | end = ptr + (len & ~3); |
150 | 221k | for( ; ptr < end ; ptr+=4) { |
151 | 221k | uint32_t k1 = READ_UINT32(ptr); |
152 | 221k | doblock(h1, k1); |
153 | 221k | } |
154 | | |
155 | | #else /*UNALIGNED_SAFE*/ |
156 | | /* This CPU does not handle unaligned word access */ |
157 | | // #pragma message ( "ALIGNED" ) |
158 | | /* Consume enough so that the next data byte is word aligned */ |
159 | | int i = -(intptr_t)(void *)ptr & 3; |
160 | | if(i && i <= len) { |
161 | | dobytes(i, h1, c, n, ptr, len); |
162 | | } |
163 | | |
164 | | /* We're now aligned. Process in aligned blocks. Specialise for each possible carry count */ |
165 | | end = ptr + (len & ~3); |
166 | | switch(n) { /* how many bytes in c */ |
167 | | case 0: /* c=[----] w=[3210] b=[3210]=w c'=[----] */ |
168 | | for( ; ptr < end ; ptr+=4) { |
169 | | uint32_t k1 = READ_UINT32(ptr); |
170 | | doblock(h1, k1); |
171 | | } |
172 | | break; |
173 | | case 1: /* c=[0---] w=[4321] b=[3210]=c>>24|w<<8 c'=[4---] */ |
174 | | for( ; ptr < end ; ptr+=4) { |
175 | | uint32_t k1 = c>>24; |
176 | | c = READ_UINT32(ptr); |
177 | | k1 |= c<<8; |
178 | | doblock(h1, k1); |
179 | | } |
180 | | break; |
181 | | case 2: /* c=[10--] w=[5432] b=[3210]=c>>16|w<<16 c'=[54--] */ |
182 | | for( ; ptr < end ; ptr+=4) { |
183 | | uint32_t k1 = c>>16; |
184 | | c = READ_UINT32(ptr); |
185 | | k1 |= c<<16; |
186 | | doblock(h1, k1); |
187 | | } |
188 | | break; |
189 | | case 3: /* c=[210-] w=[6543] b=[3210]=c>>8|w<<24 c'=[654-] */ |
190 | | for( ; ptr < end ; ptr+=4) { |
191 | | uint32_t k1 = c>>8; |
192 | | c = READ_UINT32(ptr); |
193 | | k1 |= c<<24; |
194 | | doblock(h1, k1); |
195 | | } |
196 | | } |
197 | | #endif /*UNALIGNED_SAFE*/ |
198 | | |
199 | | /* Advance over whole 32-bit chunks, possibly leaving 1..3 bytes */ |
200 | 22 | len -= len & ~3; |
201 | | |
202 | | /* Append any remaining bytes into carry */ |
203 | 22 | dobytes(len, h1, c, n, ptr, len); |
204 | | |
205 | | /* Copy out new running hash and carry */ |
206 | 22 | *ph1 = h1; |
207 | 22 | *pcarry = (c & ~0xff) | n; |
208 | 22 | } |
209 | | |
210 | | /*---------------------------------------------------------------------------*/ |
211 | | |
212 | | /* Finalize a hash. To match the original Murmur3A the total_length must be provided */ |
213 | | uint32_t PMurHash32_Result(uint32_t h, uint32_t carry, uint32_t total_length) |
214 | 22 | { |
215 | 22 | uint32_t k1; |
216 | 22 | int n = carry & 3; |
217 | 22 | if(n) { |
218 | 11 | k1 = carry >> (4-n)*8; |
219 | 11 | k1 *= kC1; k1 = ROTL32(k1,15); k1 *= kC2; h ^= k1; |
220 | 11 | } |
221 | 22 | h ^= total_length; |
222 | | |
223 | | /* fmix */ |
224 | 22 | h ^= h >> 16; |
225 | 22 | h *= 0x85ebca6b; |
226 | 22 | h ^= h >> 13; |
227 | 22 | h *= 0xc2b2ae35; |
228 | 22 | h ^= h >> 16; |
229 | | |
230 | 22 | return h; |
231 | 22 | } |