2 xxHash - Fast Hash algorithm
\r
3 Copyright (C) 2012-2014, Yann Collet.
\r
4 BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
\r
6 Redistribution and use in source and binary forms, with or without
\r
7 modification, are permitted provided that the following conditions are
\r
10 * Redistributions of source code must retain the above copyright
\r
11 notice, this list of conditions and the following disclaimer.
\r
12 * Redistributions in binary form must reproduce the above
\r
13 copyright notice, this list of conditions and the following disclaimer
\r
14 in the documentation and/or other materials provided with the
\r
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
\r
18 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
\r
19 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
\r
20 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
\r
21 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
\r
22 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
\r
23 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
\r
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
\r
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
\r
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
\r
27 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
29 You can contact the author at :
\r
30 - xxHash source repository : http://code.google.com/p/xxhash/
\r
34 //**************************************
\r
35 // Tuning parameters
\r
36 //**************************************
\r
37 // Unaligned memory access is automatically enabled for "common" CPU, such as x86.
\r
38 // For others CPU, the compiler will be more cautious, and insert extra code to ensure aligned access is respected.
\r
39 // If you know your target CPU supports unaligned memory access, you want to force this option manually to improve performance.
\r
40 // You can also enable this parameter if you know your input data will always be aligned (boundaries of 4, for uint32_t).
\r
41 #if defined(__ARM_FEATURE_UNALIGNED) || defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
\r
42 # define XXH_USE_UNALIGNED_ACCESS 1
\r
45 // XXH_ACCEPT_NULL_INPUT_POINTER :
\r
46 // If the input pointer is a null pointer, xxHash default behavior is to trigger a memory access error, since it is a bad pointer.
\r
47 // When this option is enabled, xxHash output for null input pointers will be the same as a null-length input.
\r
48 // This option has a very small performance cost (only measurable on small inputs).
\r
49 // By default, this option is disabled. To enable it, uncomment below define :
\r
50 //#define XXH_ACCEPT_NULL_INPUT_POINTER 1
\r
52 // XXH_FORCE_NATIVE_FORMAT :
\r
53 // By default, xxHash library provides endian-independant Hash values, based on little-endian convention.
\r
54 // Results are therefore identical for little-endian and big-endian CPU.
\r
55 // This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format.
\r
56 // Should endian-independance be of no importance for your application, you may set the #define below to 1.
\r
57 // It will improve speed for Big-endian CPU.
\r
58 // This option has no impact on Little_Endian CPU.
\r
59 #define XXH_FORCE_NATIVE_FORMAT 0
\r
62 //**************************************
\r
63 // Includes & Memory related functions
\r
64 //**************************************
\r
66 // Modify the local functions below should you wish to use some other memory related routines
\r
67 // for malloc(), free()
\r
69 void* XXH_malloc(size_t s) { return malloc(s); }
\r
70 void XXH_free (void* p) { free(p); }
\r
73 void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcpy(dest,src,size); }
\r
76 #if defined(__GNUC__) && !defined(XXH_USE_UNALIGNED_ACCESS)
\r
77 # define _PACKED __attribute__ ((packed))
\r
82 #if !defined(XXH_USE_UNALIGNED_ACCESS) && !defined(__GNUC__)
\r
86 # pragma pack(push, 1)
\r
90 typedef struct _uint32_t_S { uint32_t v; } _PACKED uint32_t_S;
\r
92 #if !defined(XXH_USE_UNALIGNED_ACCESS) && !defined(__GNUC__)
\r
96 #define A32(x) (((uint32_t_S *)(x))->v)
\r
99 //***************************************
\r
100 // Compiler-specific Functions and Macros
\r
101 //***************************************
\r
102 #define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
\r
104 // Note : although _rotl exists for minGW (GCC under windows), performance seems poor
\r
105 #if defined(_MSC_VER)
\r
106 # define XXH_rotl32(x,r) _rotl(x,r)
\r
108 # define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r)))
\r
111 #if defined(_MSC_VER) // Visual Studio
\r
112 # define XXH_swap32 _byteswap_ulong
\r
113 #elif GCC_VERSION >= 403
\r
114 # define XXH_swap32 __builtin_bswap32
\r
116 static inline uint32_t XXH_swap32 (uint32_t x) {
\r
117 return ((x << 24) & 0xff000000 ) |
\r
118 ((x << 8) & 0x00ff0000 ) |
\r
119 ((x >> 8) & 0x0000ff00 ) |
\r
120 ((x >> 24) & 0x000000ff );}
\r
124 //**************************************
\r
126 //**************************************
\r
127 #define PRIME32_1 2654435761U
\r
128 #define PRIME32_2 2246822519U
\r
129 #define PRIME32_3 3266489917U
\r
130 #define PRIME32_4 668265263U
\r
131 #define PRIME32_5 374761393U
\r
134 //**************************************
\r
135 // Architecture Macros
\r
136 //**************************************
\r
137 typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess;
\r
138 #ifndef XXH_CPU_LITTLE_ENDIAN // It is possible to define XXH_CPU_LITTLE_ENDIAN externally, for example using a compiler switch
\r
139 static const int one = 1;
\r
140 # define XXH_CPU_LITTLE_ENDIAN (*(char*)(&one))
\r
144 //**************************************
\r
146 //**************************************
\r
147 #define XXH_STATIC_ASSERT(c) { enum { XXH_static_assert = 1/(!!(c)) }; } // use only *after* variable declarations
\r
150 //****************************
\r
152 //****************************
\r
153 typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment;
\r
155 uint32_t XXH_readLE32_align(const uint32_t* ptr, XXH_endianess endian, XXH_alignment align)
\r
157 if (align==XXH_unaligned)
\r
158 return endian==XXH_littleEndian ? A32(ptr) : XXH_swap32(A32(ptr));
\r
160 return endian==XXH_littleEndian ? *ptr : XXH_swap32(*ptr);
\r
163 uint32_t XXH_readLE32(const uint32_t* ptr, XXH_endianess endian) { return XXH_readLE32_align(ptr, endian, XXH_unaligned); }
\r
166 //****************************
\r
167 // Simple Hash Functions
\r
168 //****************************
\r
169 uint32_t XXH32_endian_align(const void* input, int len, uint32_t seed, XXH_endianess endian, XXH_alignment align)
\r
171 const uint8_t *p = (const uint8_t *)input;
\r
172 const uint8_t * const bEnd = p + len;
\r
175 #ifdef XXH_ACCEPT_NULL_INPUT_POINTER
\r
176 if (p==NULL) { len=0; p=(const uint8_t *)(size_t)16; }
\r
181 const uint8_t * const limit = bEnd - 16;
\r
182 uint32_t v1 = seed + PRIME32_1 + PRIME32_2;
\r
183 uint32_t v2 = seed + PRIME32_2;
\r
184 uint32_t v3 = seed + 0;
\r
185 uint32_t v4 = seed - PRIME32_1;
\r
189 v1 += XXH_readLE32_align((const uint32_t*)p, endian, align) * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; p+=4;
\r
190 v2 += XXH_readLE32_align((const uint32_t*)p, endian, align) * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; p+=4;
\r
191 v3 += XXH_readLE32_align((const uint32_t*)p, endian, align) * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; p+=4;
\r
192 v4 += XXH_readLE32_align((const uint32_t*)p, endian, align) * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; p+=4;
\r
193 } while (p<=limit);
\r
195 h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);
\r
199 h32 = seed + PRIME32_5;
\r
202 h32 += (uint32_t) len;
\r
206 h32 += XXH_readLE32_align((const uint32_t*)p, endian, align) * PRIME32_3;
\r
207 h32 = XXH_rotl32(h32, 17) * PRIME32_4 ;
\r
213 h32 += (*p) * PRIME32_5;
\r
214 h32 = XXH_rotl32(h32, 11) * PRIME32_1 ;
\r
228 uint32_t XXH32(const void* input, int len, uint32_t seed)
\r
231 // Simple version, good for code maintenance, but unfortunately slow for small inputs
\r
232 void* state = XXH32_init(seed);
\r
233 XXH32_update(state, input, len);
\r
234 return XXH32_digest(state);
\r
236 XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
\r
238 # if !defined(XXH_USE_UNALIGNED_ACCESS)
\r
239 if ((((size_t)input) & 3)) // Input is aligned, let's leverage the speed advantage
\r
241 if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
\r
242 return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
\r
244 return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
\r
248 if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
\r
249 return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
\r
251 return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
\r
256 //****************************
\r
257 // Advanced Hash Functions
\r
258 //****************************
\r
260 int XXH32_sizeofState()
\r
262 XXH_STATIC_ASSERT(XXH32_SIZEOFSTATE >= sizeof(struct XXH_state32_t)); // A compilation error here means XXH32_SIZEOFSTATE is not large enough
\r
263 return sizeof(struct XXH_state32_t);
\r
267 XXH_errorcode XXH32_resetState(void* state_in, uint32_t seed)
\r
269 struct XXH_state32_t * state = (struct XXH_state32_t *) state_in;
\r
270 state->seed = seed;
\r
271 state->v1 = seed + PRIME32_1 + PRIME32_2;
\r
272 state->v2 = seed + PRIME32_2;
\r
273 state->v3 = seed + 0;
\r
274 state->v4 = seed - PRIME32_1;
\r
275 state->total_len = 0;
\r
276 state->memsize = 0;
\r
281 void* XXH32_init (uint32_t seed)
\r
283 void* state = XXH_malloc (sizeof(struct XXH_state32_t));
\r
284 XXH32_resetState(state, seed);
\r
289 XXH_errorcode XXH32_update_endian (void* state_in, const void* input, int len, XXH_endianess endian)
\r
291 struct XXH_state32_t * state = (struct XXH_state32_t *) state_in;
\r
292 const uint8_t *p = (const uint8_t *)input;
\r
293 const uint8_t * const bEnd = p + len;
\r
295 #ifdef XXH_ACCEPT_NULL_INPUT_POINTER
\r
296 if (input==NULL) return XXH_ERROR;
\r
299 state->total_len += len;
\r
301 if (state->memsize + len < 16) // fill in tmp buffer
\r
303 XXH_memcpy(state->memory + state->memsize, input, len);
\r
304 state->memsize += len;
\r
308 if (state->memsize) // some data left from previous update
\r
310 XXH_memcpy(state->memory + state->memsize, input, 16-state->memsize);
\r
312 const uint32_t* p32 = (const uint32_t*)state->memory;
\r
313 state->v1 += XXH_readLE32(p32, endian) * PRIME32_2; state->v1 = XXH_rotl32(state->v1, 13); state->v1 *= PRIME32_1; p32++;
\r
314 state->v2 += XXH_readLE32(p32, endian) * PRIME32_2; state->v2 = XXH_rotl32(state->v2, 13); state->v2 *= PRIME32_1; p32++;
\r
315 state->v3 += XXH_readLE32(p32, endian) * PRIME32_2; state->v3 = XXH_rotl32(state->v3, 13); state->v3 *= PRIME32_1; p32++;
\r
316 state->v4 += XXH_readLE32(p32, endian) * PRIME32_2; state->v4 = XXH_rotl32(state->v4, 13); state->v4 *= PRIME32_1; p32++;
\r
318 p += 16-state->memsize;
\r
319 state->memsize = 0;
\r
324 const uint8_t * const limit = bEnd - 16;
\r
325 uint32_t v1 = state->v1;
\r
326 uint32_t v2 = state->v2;
\r
327 uint32_t v3 = state->v3;
\r
328 uint32_t v4 = state->v4;
\r
332 v1 += XXH_readLE32((const uint32_t*)p, endian) * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; p+=4;
\r
333 v2 += XXH_readLE32((const uint32_t*)p, endian) * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; p+=4;
\r
334 v3 += XXH_readLE32((const uint32_t*)p, endian) * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; p+=4;
\r
335 v4 += XXH_readLE32((const uint32_t*)p, endian) * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; p+=4;
\r
336 } while (p<=limit);
\r
346 XXH_memcpy(state->memory, p, bEnd-p);
\r
347 state->memsize = (int)(bEnd-p);
\r
353 XXH_errorcode XXH32_update (void* state_in, const void* input, int len)
\r
355 XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
\r
357 if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
\r
358 return XXH32_update_endian(state_in, input, len, XXH_littleEndian);
\r
360 return XXH32_update_endian(state_in, input, len, XXH_bigEndian);
\r
365 uint32_t XXH32_intermediateDigest_endian (void* state_in, XXH_endianess endian)
\r
367 struct XXH_state32_t * state = (struct XXH_state32_t *) state_in;
\r
368 const uint8_t *p = (const uint8_t *)state->memory;
\r
369 uint8_t * bEnd = (uint8_t *)state->memory + state->memsize;
\r
372 if (state->total_len >= 16)
\r
374 h32 = XXH_rotl32(state->v1, 1) + XXH_rotl32(state->v2, 7) + XXH_rotl32(state->v3, 12) + XXH_rotl32(state->v4, 18);
\r
378 h32 = state->seed + PRIME32_5;
\r
381 h32 += (uint32_t) state->total_len;
\r
385 h32 += XXH_readLE32((const uint32_t*)p, endian) * PRIME32_3;
\r
386 h32 = XXH_rotl32(h32, 17) * PRIME32_4;
\r
392 h32 += (*p) * PRIME32_5;
\r
393 h32 = XXH_rotl32(h32, 11) * PRIME32_1;
\r
407 uint32_t XXH32_intermediateDigest (void* state_in)
\r
409 XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
\r
411 if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
\r
412 return XXH32_intermediateDigest_endian(state_in, XXH_littleEndian);
\r
414 return XXH32_intermediateDigest_endian(state_in, XXH_bigEndian);
\r
418 uint32_t XXH32_digest (void* state_in)
\r
420 uint32_t h32 = XXH32_intermediateDigest(state_in);
\r
422 XXH_free(state_in);
\r