xref: /freebsd/sys/contrib/openzfs/module/zstd/lib/common/xxhash.c (revision 61145dc2b94f12f6a47344fb9aac702321880e43)
1*61145dc2SMartin Matuska // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only
2c03c5b1cSMartin Matuska /*
3c03c5b1cSMartin Matuska  *  xxHash - Fast Hash algorithm
4c03c5b1cSMartin Matuska  *  Copyright (c) 2012-2020, Yann Collet, Facebook, Inc.
5c03c5b1cSMartin Matuska  *
6c03c5b1cSMartin Matuska  *  You can contact the author at :
7c03c5b1cSMartin Matuska  *  - xxHash homepage: http://www.xxhash.com
8c03c5b1cSMartin Matuska  *  - xxHash source repository : https://github.com/Cyan4973/xxHash
9c03c5b1cSMartin Matuska  *
10c03c5b1cSMartin Matuska  * This source code is licensed under both the BSD-style license (found in the
11c03c5b1cSMartin Matuska  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
12c03c5b1cSMartin Matuska  * in the COPYING file in the root directory of this source tree).
13c03c5b1cSMartin Matuska  * You may select, at your option, one of the above-listed licenses.
14c03c5b1cSMartin Matuska */
15c03c5b1cSMartin Matuska 
16c03c5b1cSMartin Matuska 
17c03c5b1cSMartin Matuska /* *************************************
18c03c5b1cSMartin Matuska *  Tuning parameters
19c03c5b1cSMartin Matuska ***************************************/
20c03c5b1cSMartin Matuska /*!XXH_FORCE_MEMORY_ACCESS :
21c03c5b1cSMartin Matuska  * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.
22c03c5b1cSMartin Matuska  * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.
23c03c5b1cSMartin Matuska  * The below switch allow to select different access method for improved performance.
24c03c5b1cSMartin Matuska  * Method 0 (default) : use `memcpy()`. Safe and portable.
25c03c5b1cSMartin Matuska  * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).
26c03c5b1cSMartin Matuska  *            This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.
27c03c5b1cSMartin Matuska  * Method 2 : direct access. This method doesn't depend on compiler but violate C standard.
28c03c5b1cSMartin Matuska  *            It can generate buggy code on targets which do not support unaligned memory accesses.
29c03c5b1cSMartin Matuska  *            But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)
30c03c5b1cSMartin Matuska  * See http://stackoverflow.com/a/32095106/646947 for details.
31c03c5b1cSMartin Matuska  * Prefer these methods in priority order (0 > 1 > 2)
32c03c5b1cSMartin Matuska  */
33c03c5b1cSMartin Matuska #ifndef XXH_FORCE_MEMORY_ACCESS   /* can be defined externally, on command line for example */
34c03c5b1cSMartin Matuska #  if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) )
35c03c5b1cSMartin Matuska #    define XXH_FORCE_MEMORY_ACCESS 2
36c03c5b1cSMartin Matuska #  elif (defined(__INTEL_COMPILER) && !defined(WIN32)) || \
37c03c5b1cSMartin Matuska   (defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) )) || \
38c03c5b1cSMartin Matuska   defined(__ICCARM__)
39c03c5b1cSMartin Matuska #    define XXH_FORCE_MEMORY_ACCESS 1
40c03c5b1cSMartin Matuska #  endif
41c03c5b1cSMartin Matuska #endif
42c03c5b1cSMartin Matuska 
43c03c5b1cSMartin Matuska /*!XXH_ACCEPT_NULL_INPUT_POINTER :
44c03c5b1cSMartin Matuska  * If the input pointer is a null pointer, xxHash default behavior is to trigger a memory access error, since it is a bad pointer.
45c03c5b1cSMartin Matuska  * When this option is enabled, xxHash output for null input pointers will be the same as a null-length input.
46c03c5b1cSMartin Matuska  * By default, this option is disabled. To enable it, uncomment below define :
47c03c5b1cSMartin Matuska  */
48c03c5b1cSMartin Matuska /* #define XXH_ACCEPT_NULL_INPUT_POINTER 1 */
49c03c5b1cSMartin Matuska 
50c03c5b1cSMartin Matuska /*!XXH_FORCE_NATIVE_FORMAT :
51c03c5b1cSMartin Matuska  * By default, xxHash library provides endian-independent Hash values, based on little-endian convention.
52c03c5b1cSMartin Matuska  * Results are therefore identical for little-endian and big-endian CPU.
53c03c5b1cSMartin Matuska  * This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format.
54c03c5b1cSMartin Matuska  * Should endian-independence be of no importance for your application, you may set the #define below to 1,
55c03c5b1cSMartin Matuska  * to improve speed for Big-endian CPU.
56c03c5b1cSMartin Matuska  * This option has no impact on Little_Endian CPU.
57c03c5b1cSMartin Matuska  */
58c03c5b1cSMartin Matuska #ifndef XXH_FORCE_NATIVE_FORMAT   /* can be defined externally */
59c03c5b1cSMartin Matuska #  define XXH_FORCE_NATIVE_FORMAT 0
60c03c5b1cSMartin Matuska #endif
61c03c5b1cSMartin Matuska 
62c03c5b1cSMartin Matuska /*!XXH_FORCE_ALIGN_CHECK :
63c03c5b1cSMartin Matuska  * This is a minor performance trick, only useful with lots of very small keys.
64c03c5b1cSMartin Matuska  * It means : check for aligned/unaligned input.
65c03c5b1cSMartin Matuska  * The check costs one initial branch per hash; set to 0 when the input data
66c03c5b1cSMartin Matuska  * is guaranteed to be aligned.
67c03c5b1cSMartin Matuska  */
68c03c5b1cSMartin Matuska #ifndef XXH_FORCE_ALIGN_CHECK /* can be defined externally */
69c03c5b1cSMartin Matuska #  if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
70c03c5b1cSMartin Matuska #    define XXH_FORCE_ALIGN_CHECK 0
71c03c5b1cSMartin Matuska #  else
72c03c5b1cSMartin Matuska #    define XXH_FORCE_ALIGN_CHECK 1
73c03c5b1cSMartin Matuska #  endif
74c03c5b1cSMartin Matuska #endif
75c03c5b1cSMartin Matuska 
76c03c5b1cSMartin Matuska 
77c03c5b1cSMartin Matuska /* *************************************
78c03c5b1cSMartin Matuska *  Includes & Memory related functions
79c03c5b1cSMartin Matuska ***************************************/
80c03c5b1cSMartin Matuska /* Modify the local functions below should you wish to use some other memory routines */
81c03c5b1cSMartin Matuska /* for malloc(), free() */
82c03c5b1cSMartin Matuska #include <stdlib.h>
83c03c5b1cSMartin Matuska #include <stddef.h>     /* size_t */
XXH_malloc(size_t s)84c03c5b1cSMartin Matuska static void* XXH_malloc(size_t s) { return malloc(s); }
XXH_free(void * p)85c03c5b1cSMartin Matuska static void  XXH_free  (void* p)  { free(p); }
86c03c5b1cSMartin Matuska /* for memcpy() */
87c03c5b1cSMartin Matuska #include <string.h>
XXH_memcpy(void * dest,const void * src,size_t size)88c03c5b1cSMartin Matuska static void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcpy(dest,src,size); }
89c03c5b1cSMartin Matuska 
90c03c5b1cSMartin Matuska #ifndef XXH_STATIC_LINKING_ONLY
91c03c5b1cSMartin Matuska #  define XXH_STATIC_LINKING_ONLY
92c03c5b1cSMartin Matuska #endif
93c03c5b1cSMartin Matuska #include "xxhash.h"
94c03c5b1cSMartin Matuska 
95c03c5b1cSMartin Matuska 
96c03c5b1cSMartin Matuska /* *************************************
97c03c5b1cSMartin Matuska *  Compiler Specific Options
98c03c5b1cSMartin Matuska ***************************************/
99c03c5b1cSMartin Matuska #if (defined(__GNUC__) && !defined(__STRICT_ANSI__)) || defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */
100c03c5b1cSMartin Matuska #  define INLINE_KEYWORD inline
101c03c5b1cSMartin Matuska #else
102c03c5b1cSMartin Matuska #  define INLINE_KEYWORD
103c03c5b1cSMartin Matuska #endif
104c03c5b1cSMartin Matuska 
105c03c5b1cSMartin Matuska #if defined(__GNUC__) || defined(__ICCARM__)
106c03c5b1cSMartin Matuska #  define FORCE_INLINE_ATTR __attribute__((always_inline))
107c03c5b1cSMartin Matuska #elif defined(_MSC_VER)
108c03c5b1cSMartin Matuska #  define FORCE_INLINE_ATTR __forceinline
109c03c5b1cSMartin Matuska #else
110c03c5b1cSMartin Matuska #  define FORCE_INLINE_ATTR
111c03c5b1cSMartin Matuska #endif
112c03c5b1cSMartin Matuska 
113c03c5b1cSMartin Matuska #define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR
114c03c5b1cSMartin Matuska 
115c03c5b1cSMartin Matuska 
116c03c5b1cSMartin Matuska #ifdef _MSC_VER
117c03c5b1cSMartin Matuska #  pragma warning(disable : 4127)      /* disable: C4127: conditional expression is constant */
118c03c5b1cSMartin Matuska #endif
119c03c5b1cSMartin Matuska 
120c03c5b1cSMartin Matuska 
121c03c5b1cSMartin Matuska /* *************************************
122c03c5b1cSMartin Matuska *  Basic Types
123c03c5b1cSMartin Matuska ***************************************/
124c03c5b1cSMartin Matuska #ifndef MEM_MODULE
125c03c5b1cSMartin Matuska # define MEM_MODULE
126c03c5b1cSMartin Matuska # if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
127c03c5b1cSMartin Matuska #   include <stdint.h>
128c03c5b1cSMartin Matuska     typedef uint8_t  BYTE;
129c03c5b1cSMartin Matuska     typedef uint16_t U16;
130c03c5b1cSMartin Matuska     typedef uint32_t U32;
131c03c5b1cSMartin Matuska     typedef  int32_t S32;
132c03c5b1cSMartin Matuska     typedef uint64_t U64;
133c03c5b1cSMartin Matuska #  else
134c03c5b1cSMartin Matuska     typedef unsigned char      BYTE;
135c03c5b1cSMartin Matuska     typedef unsigned short     U16;
136c03c5b1cSMartin Matuska     typedef unsigned int       U32;
137c03c5b1cSMartin Matuska     typedef   signed int       S32;
138c03c5b1cSMartin Matuska     typedef unsigned long long U64;   /* if your compiler doesn't support unsigned long long, replace by another 64-bit type here. Note that xxhash.h will also need to be updated. */
139c03c5b1cSMartin Matuska #  endif
140c03c5b1cSMartin Matuska #endif
141c03c5b1cSMartin Matuska 
142c03c5b1cSMartin Matuska 
143c03c5b1cSMartin Matuska #if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2))
144c03c5b1cSMartin Matuska 
145c03c5b1cSMartin Matuska /* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */
XXH_read32(const void * memPtr)146c03c5b1cSMartin Matuska static U32 XXH_read32(const void* memPtr) { return *(const U32*) memPtr; }
XXH_read64(const void * memPtr)147c03c5b1cSMartin Matuska static U64 XXH_read64(const void* memPtr) { return *(const U64*) memPtr; }
148c03c5b1cSMartin Matuska 
149c03c5b1cSMartin Matuska #elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1))
150c03c5b1cSMartin Matuska 
151c03c5b1cSMartin Matuska /* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
152c03c5b1cSMartin Matuska /* currently only defined for gcc and icc */
153c03c5b1cSMartin Matuska typedef union { U32 u32; U64 u64; } __attribute__((packed)) unalign;
154c03c5b1cSMartin Matuska 
XXH_read32(const void * ptr)155c03c5b1cSMartin Matuska static U32 XXH_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }
XXH_read64(const void * ptr)156c03c5b1cSMartin Matuska static U64 XXH_read64(const void* ptr) { return ((const unalign*)ptr)->u64; }
157c03c5b1cSMartin Matuska 
158c03c5b1cSMartin Matuska #else
159c03c5b1cSMartin Matuska 
160c03c5b1cSMartin Matuska /* portable and safe solution. Generally efficient.
161c03c5b1cSMartin Matuska  * see : http://stackoverflow.com/a/32095106/646947
162c03c5b1cSMartin Matuska  */
163c03c5b1cSMartin Matuska 
XXH_read32(const void * memPtr)164c03c5b1cSMartin Matuska static U32 XXH_read32(const void* memPtr)
165c03c5b1cSMartin Matuska {
166c03c5b1cSMartin Matuska     U32 val;
167c03c5b1cSMartin Matuska     memcpy(&val, memPtr, sizeof(val));
168c03c5b1cSMartin Matuska     return val;
169c03c5b1cSMartin Matuska }
170c03c5b1cSMartin Matuska 
XXH_read64(const void * memPtr)171c03c5b1cSMartin Matuska static U64 XXH_read64(const void* memPtr)
172c03c5b1cSMartin Matuska {
173c03c5b1cSMartin Matuska     U64 val;
174c03c5b1cSMartin Matuska     memcpy(&val, memPtr, sizeof(val));
175c03c5b1cSMartin Matuska     return val;
176c03c5b1cSMartin Matuska }
177c03c5b1cSMartin Matuska 
178c03c5b1cSMartin Matuska #endif   /* XXH_FORCE_DIRECT_MEMORY_ACCESS */
179c03c5b1cSMartin Matuska 
180c03c5b1cSMartin Matuska 
181c03c5b1cSMartin Matuska /* ****************************************
182c03c5b1cSMartin Matuska *  Compiler-specific Functions and Macros
183c03c5b1cSMartin Matuska ******************************************/
184c03c5b1cSMartin Matuska #define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
185c03c5b1cSMartin Matuska 
186c03c5b1cSMartin Matuska /* Note : although _rotl exists for minGW (GCC under windows), performance seems poor */
187c03c5b1cSMartin Matuska #if defined(_MSC_VER)
188c03c5b1cSMartin Matuska #  define XXH_rotl32(x,r) _rotl(x,r)
189c03c5b1cSMartin Matuska #  define XXH_rotl64(x,r) _rotl64(x,r)
190c03c5b1cSMartin Matuska #else
191c03c5b1cSMartin Matuska #if defined(__ICCARM__)
192c03c5b1cSMartin Matuska #  include <intrinsics.h>
193c03c5b1cSMartin Matuska #  define XXH_rotl32(x,r) __ROR(x,(32 - r))
194c03c5b1cSMartin Matuska #else
195c03c5b1cSMartin Matuska #  define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r)))
196c03c5b1cSMartin Matuska #endif
197c03c5b1cSMartin Matuska #  define XXH_rotl64(x,r) ((x << r) | (x >> (64 - r)))
198c03c5b1cSMartin Matuska #endif
199c03c5b1cSMartin Matuska 
200c03c5b1cSMartin Matuska #if defined(_MSC_VER)     /* Visual Studio */
201c03c5b1cSMartin Matuska #  define XXH_swap32 _byteswap_ulong
202c03c5b1cSMartin Matuska #  define XXH_swap64 _byteswap_uint64
203c03c5b1cSMartin Matuska #elif GCC_VERSION >= 403
204c03c5b1cSMartin Matuska #  define XXH_swap32 __builtin_bswap32
205c03c5b1cSMartin Matuska #  define XXH_swap64 __builtin_bswap64
206c03c5b1cSMartin Matuska #else
XXH_swap32(U32 x)207c03c5b1cSMartin Matuska static U32 XXH_swap32 (U32 x)
208c03c5b1cSMartin Matuska {
209c03c5b1cSMartin Matuska     return  ((x << 24) & 0xff000000 ) |
210c03c5b1cSMartin Matuska             ((x <<  8) & 0x00ff0000 ) |
211c03c5b1cSMartin Matuska             ((x >>  8) & 0x0000ff00 ) |
212c03c5b1cSMartin Matuska             ((x >> 24) & 0x000000ff );
213c03c5b1cSMartin Matuska }
XXH_swap64(U64 x)214c03c5b1cSMartin Matuska static U64 XXH_swap64 (U64 x)
215c03c5b1cSMartin Matuska {
216c03c5b1cSMartin Matuska     return  ((x << 56) & 0xff00000000000000ULL) |
217c03c5b1cSMartin Matuska             ((x << 40) & 0x00ff000000000000ULL) |
218c03c5b1cSMartin Matuska             ((x << 24) & 0x0000ff0000000000ULL) |
219c03c5b1cSMartin Matuska             ((x << 8)  & 0x000000ff00000000ULL) |
220c03c5b1cSMartin Matuska             ((x >> 8)  & 0x00000000ff000000ULL) |
221c03c5b1cSMartin Matuska             ((x >> 24) & 0x0000000000ff0000ULL) |
222c03c5b1cSMartin Matuska             ((x >> 40) & 0x000000000000ff00ULL) |
223c03c5b1cSMartin Matuska             ((x >> 56) & 0x00000000000000ffULL);
224c03c5b1cSMartin Matuska }
225c03c5b1cSMartin Matuska #endif
226c03c5b1cSMartin Matuska 
227c03c5b1cSMartin Matuska 
228c03c5b1cSMartin Matuska /* *************************************
229c03c5b1cSMartin Matuska *  Architecture Macros
230c03c5b1cSMartin Matuska ***************************************/
231c03c5b1cSMartin Matuska typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess;
232c03c5b1cSMartin Matuska 
233c03c5b1cSMartin Matuska /* XXH_CPU_LITTLE_ENDIAN can be defined externally, for example on the compiler command line */
234c03c5b1cSMartin Matuska #ifndef XXH_CPU_LITTLE_ENDIAN
235c03c5b1cSMartin Matuska     static const int g_one = 1;
236c03c5b1cSMartin Matuska #   define XXH_CPU_LITTLE_ENDIAN   (*(const char*)(&g_one))
237c03c5b1cSMartin Matuska #endif
238c03c5b1cSMartin Matuska 
239c03c5b1cSMartin Matuska 
240c03c5b1cSMartin Matuska /* ***************************
241c03c5b1cSMartin Matuska *  Memory reads
242c03c5b1cSMartin Matuska *****************************/
243c03c5b1cSMartin Matuska typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment;
244c03c5b1cSMartin Matuska 
XXH_readLE32_align(const void * ptr,XXH_endianess endian,XXH_alignment align)245c03c5b1cSMartin Matuska FORCE_INLINE_TEMPLATE U32 XXH_readLE32_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
246c03c5b1cSMartin Matuska {
247c03c5b1cSMartin Matuska     if (align==XXH_unaligned)
248c03c5b1cSMartin Matuska         return endian==XXH_littleEndian ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr));
249c03c5b1cSMartin Matuska     else
250c03c5b1cSMartin Matuska         return endian==XXH_littleEndian ? *(const U32*)ptr : XXH_swap32(*(const U32*)ptr);
251c03c5b1cSMartin Matuska }
252c03c5b1cSMartin Matuska 
XXH_readLE32(const void * ptr,XXH_endianess endian)253c03c5b1cSMartin Matuska FORCE_INLINE_TEMPLATE U32 XXH_readLE32(const void* ptr, XXH_endianess endian)
254c03c5b1cSMartin Matuska {
255c03c5b1cSMartin Matuska     return XXH_readLE32_align(ptr, endian, XXH_unaligned);
256c03c5b1cSMartin Matuska }
257c03c5b1cSMartin Matuska 
XXH_readBE32(const void * ptr)258c03c5b1cSMartin Matuska static U32 XXH_readBE32(const void* ptr)
259c03c5b1cSMartin Matuska {
260c03c5b1cSMartin Matuska     return XXH_CPU_LITTLE_ENDIAN ? XXH_swap32(XXH_read32(ptr)) : XXH_read32(ptr);
261c03c5b1cSMartin Matuska }
262c03c5b1cSMartin Matuska 
XXH_readLE64_align(const void * ptr,XXH_endianess endian,XXH_alignment align)263c03c5b1cSMartin Matuska FORCE_INLINE_TEMPLATE U64 XXH_readLE64_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
264c03c5b1cSMartin Matuska {
265c03c5b1cSMartin Matuska     if (align==XXH_unaligned)
266c03c5b1cSMartin Matuska         return endian==XXH_littleEndian ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr));
267c03c5b1cSMartin Matuska     else
268c03c5b1cSMartin Matuska         return endian==XXH_littleEndian ? *(const U64*)ptr : XXH_swap64(*(const U64*)ptr);
269c03c5b1cSMartin Matuska }
270c03c5b1cSMartin Matuska 
XXH_readLE64(const void * ptr,XXH_endianess endian)271c03c5b1cSMartin Matuska FORCE_INLINE_TEMPLATE U64 XXH_readLE64(const void* ptr, XXH_endianess endian)
272c03c5b1cSMartin Matuska {
273c03c5b1cSMartin Matuska     return XXH_readLE64_align(ptr, endian, XXH_unaligned);
274c03c5b1cSMartin Matuska }
275c03c5b1cSMartin Matuska 
XXH_readBE64(const void * ptr)276c03c5b1cSMartin Matuska static U64 XXH_readBE64(const void* ptr)
277c03c5b1cSMartin Matuska {
278c03c5b1cSMartin Matuska     return XXH_CPU_LITTLE_ENDIAN ? XXH_swap64(XXH_read64(ptr)) : XXH_read64(ptr);
279c03c5b1cSMartin Matuska }
280c03c5b1cSMartin Matuska 
281c03c5b1cSMartin Matuska 
282c03c5b1cSMartin Matuska /* *************************************
283c03c5b1cSMartin Matuska *  Macros
284c03c5b1cSMartin Matuska ***************************************/
285c03c5b1cSMartin Matuska #define XXH_STATIC_ASSERT(c)   { enum { XXH_static_assert = 1/(int)(!!(c)) }; }    /* use only *after* variable declarations */
286c03c5b1cSMartin Matuska 
287c03c5b1cSMartin Matuska 
288c03c5b1cSMartin Matuska /* *************************************
289c03c5b1cSMartin Matuska *  Constants
290c03c5b1cSMartin Matuska ***************************************/
291c03c5b1cSMartin Matuska static const U32 PRIME32_1 = 2654435761U;
292c03c5b1cSMartin Matuska static const U32 PRIME32_2 = 2246822519U;
293c03c5b1cSMartin Matuska static const U32 PRIME32_3 = 3266489917U;
294c03c5b1cSMartin Matuska static const U32 PRIME32_4 =  668265263U;
295c03c5b1cSMartin Matuska static const U32 PRIME32_5 =  374761393U;
296c03c5b1cSMartin Matuska 
297c03c5b1cSMartin Matuska static const U64 PRIME64_1 = 11400714785074694791ULL;
298c03c5b1cSMartin Matuska static const U64 PRIME64_2 = 14029467366897019727ULL;
299c03c5b1cSMartin Matuska static const U64 PRIME64_3 =  1609587929392839161ULL;
300c03c5b1cSMartin Matuska static const U64 PRIME64_4 =  9650029242287828579ULL;
301c03c5b1cSMartin Matuska static const U64 PRIME64_5 =  2870177450012600261ULL;
302c03c5b1cSMartin Matuska 
XXH_versionNumber(void)303c03c5b1cSMartin Matuska XXH_PUBLIC_API unsigned XXH_versionNumber (void) { return XXH_VERSION_NUMBER; }
304c03c5b1cSMartin Matuska 
305c03c5b1cSMartin Matuska 
306c03c5b1cSMartin Matuska /* **************************
307c03c5b1cSMartin Matuska *  Utils
308c03c5b1cSMartin Matuska ****************************/
XXH32_copyState(XXH32_state_t * restrict dstState,const XXH32_state_t * restrict srcState)309c03c5b1cSMartin Matuska XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* restrict dstState, const XXH32_state_t* restrict srcState)
310c03c5b1cSMartin Matuska {
311c03c5b1cSMartin Matuska     memcpy(dstState, srcState, sizeof(*dstState));
312c03c5b1cSMartin Matuska }
313c03c5b1cSMartin Matuska 
XXH64_copyState(XXH64_state_t * restrict dstState,const XXH64_state_t * restrict srcState)314c03c5b1cSMartin Matuska XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* restrict dstState, const XXH64_state_t* restrict srcState)
315c03c5b1cSMartin Matuska {
316c03c5b1cSMartin Matuska     memcpy(dstState, srcState, sizeof(*dstState));
317c03c5b1cSMartin Matuska }
318c03c5b1cSMartin Matuska 
319c03c5b1cSMartin Matuska 
320c03c5b1cSMartin Matuska /* ***************************
321c03c5b1cSMartin Matuska *  Simple Hash Functions
322c03c5b1cSMartin Matuska *****************************/
323c03c5b1cSMartin Matuska 
XXH32_round(U32 seed,U32 input)324c03c5b1cSMartin Matuska static U32 XXH32_round(U32 seed, U32 input)
325c03c5b1cSMartin Matuska {
326c03c5b1cSMartin Matuska     seed += input * PRIME32_2;
327c03c5b1cSMartin Matuska     seed  = XXH_rotl32(seed, 13);
328c03c5b1cSMartin Matuska     seed *= PRIME32_1;
329c03c5b1cSMartin Matuska     return seed;
330c03c5b1cSMartin Matuska }
331c03c5b1cSMartin Matuska 
XXH32_endian_align(const void * input,size_t len,U32 seed,XXH_endianess endian,XXH_alignment align)332c03c5b1cSMartin Matuska FORCE_INLINE_TEMPLATE U32 XXH32_endian_align(const void* input, size_t len, U32 seed, XXH_endianess endian, XXH_alignment align)
333c03c5b1cSMartin Matuska {
334c03c5b1cSMartin Matuska     const BYTE* p = (const BYTE*)input;
335c03c5b1cSMartin Matuska     const BYTE* bEnd = p + len;
336c03c5b1cSMartin Matuska     U32 h32;
337c03c5b1cSMartin Matuska #define XXH_get32bits(p) XXH_readLE32_align(p, endian, align)
338c03c5b1cSMartin Matuska 
339c03c5b1cSMartin Matuska #ifdef XXH_ACCEPT_NULL_INPUT_POINTER
340c03c5b1cSMartin Matuska     if (p==NULL) {
341c03c5b1cSMartin Matuska         len=0;
342c03c5b1cSMartin Matuska         bEnd=p=(const BYTE*)(size_t)16;
343c03c5b1cSMartin Matuska     }
344c03c5b1cSMartin Matuska #endif
345c03c5b1cSMartin Matuska 
346c03c5b1cSMartin Matuska     if (len>=16) {
347c03c5b1cSMartin Matuska         const BYTE* const limit = bEnd - 16;
348c03c5b1cSMartin Matuska         U32 v1 = seed + PRIME32_1 + PRIME32_2;
349c03c5b1cSMartin Matuska         U32 v2 = seed + PRIME32_2;
350c03c5b1cSMartin Matuska         U32 v3 = seed + 0;
351c03c5b1cSMartin Matuska         U32 v4 = seed - PRIME32_1;
352c03c5b1cSMartin Matuska 
353c03c5b1cSMartin Matuska         do {
354c03c5b1cSMartin Matuska             v1 = XXH32_round(v1, XXH_get32bits(p)); p+=4;
355c03c5b1cSMartin Matuska             v2 = XXH32_round(v2, XXH_get32bits(p)); p+=4;
356c03c5b1cSMartin Matuska             v3 = XXH32_round(v3, XXH_get32bits(p)); p+=4;
357c03c5b1cSMartin Matuska             v4 = XXH32_round(v4, XXH_get32bits(p)); p+=4;
358c03c5b1cSMartin Matuska         } while (p<=limit);
359c03c5b1cSMartin Matuska 
360c03c5b1cSMartin Matuska         h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);
361c03c5b1cSMartin Matuska     } else {
362c03c5b1cSMartin Matuska         h32  = seed + PRIME32_5;
363c03c5b1cSMartin Matuska     }
364c03c5b1cSMartin Matuska 
365c03c5b1cSMartin Matuska     h32 += (U32) len;
366c03c5b1cSMartin Matuska 
367c03c5b1cSMartin Matuska     while (p+4<=bEnd) {
368c03c5b1cSMartin Matuska         h32 += XXH_get32bits(p) * PRIME32_3;
369c03c5b1cSMartin Matuska         h32  = XXH_rotl32(h32, 17) * PRIME32_4 ;
370c03c5b1cSMartin Matuska         p+=4;
371c03c5b1cSMartin Matuska     }
372c03c5b1cSMartin Matuska 
373c03c5b1cSMartin Matuska     while (p<bEnd) {
374c03c5b1cSMartin Matuska         h32 += (*p) * PRIME32_5;
375c03c5b1cSMartin Matuska         h32 = XXH_rotl32(h32, 11) * PRIME32_1 ;
376c03c5b1cSMartin Matuska         p++;
377c03c5b1cSMartin Matuska     }
378c03c5b1cSMartin Matuska 
379c03c5b1cSMartin Matuska     h32 ^= h32 >> 15;
380c03c5b1cSMartin Matuska     h32 *= PRIME32_2;
381c03c5b1cSMartin Matuska     h32 ^= h32 >> 13;
382c03c5b1cSMartin Matuska     h32 *= PRIME32_3;
383c03c5b1cSMartin Matuska     h32 ^= h32 >> 16;
384c03c5b1cSMartin Matuska 
385c03c5b1cSMartin Matuska     return h32;
386c03c5b1cSMartin Matuska }
387c03c5b1cSMartin Matuska 
388c03c5b1cSMartin Matuska 
XXH32(const void * input,size_t len,unsigned int seed)389c03c5b1cSMartin Matuska XXH_PUBLIC_API unsigned int XXH32 (const void* input, size_t len, unsigned int seed)
390c03c5b1cSMartin Matuska {
391c03c5b1cSMartin Matuska #if 0
392c03c5b1cSMartin Matuska     /* Simple version, good for code maintenance, but unfortunately slow for small inputs */
393c03c5b1cSMartin Matuska     XXH32_CREATESTATE_STATIC(state);
394c03c5b1cSMartin Matuska     XXH32_reset(state, seed);
395c03c5b1cSMartin Matuska     XXH32_update(state, input, len);
396c03c5b1cSMartin Matuska     return XXH32_digest(state);
397c03c5b1cSMartin Matuska #else
398c03c5b1cSMartin Matuska     XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
399c03c5b1cSMartin Matuska 
400c03c5b1cSMartin Matuska     if (XXH_FORCE_ALIGN_CHECK) {
401c03c5b1cSMartin Matuska         if ((((size_t)input) & 3) == 0) {   /* Input is 4-bytes aligned, leverage the speed benefit */
402c03c5b1cSMartin Matuska             if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
403c03c5b1cSMartin Matuska                 return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
404c03c5b1cSMartin Matuska             else
405c03c5b1cSMartin Matuska                 return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
406c03c5b1cSMartin Matuska     }   }
407c03c5b1cSMartin Matuska 
408c03c5b1cSMartin Matuska     if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
409c03c5b1cSMartin Matuska         return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
410c03c5b1cSMartin Matuska     else
411c03c5b1cSMartin Matuska         return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
412c03c5b1cSMartin Matuska #endif
413c03c5b1cSMartin Matuska }
414c03c5b1cSMartin Matuska 
415c03c5b1cSMartin Matuska 
XXH64_round(U64 acc,U64 input)416c03c5b1cSMartin Matuska static U64 XXH64_round(U64 acc, U64 input)
417c03c5b1cSMartin Matuska {
418c03c5b1cSMartin Matuska     acc += input * PRIME64_2;
419c03c5b1cSMartin Matuska     acc  = XXH_rotl64(acc, 31);
420c03c5b1cSMartin Matuska     acc *= PRIME64_1;
421c03c5b1cSMartin Matuska     return acc;
422c03c5b1cSMartin Matuska }
423c03c5b1cSMartin Matuska 
XXH64_mergeRound(U64 acc,U64 val)424c03c5b1cSMartin Matuska static U64 XXH64_mergeRound(U64 acc, U64 val)
425c03c5b1cSMartin Matuska {
426c03c5b1cSMartin Matuska     val  = XXH64_round(0, val);
427c03c5b1cSMartin Matuska     acc ^= val;
428c03c5b1cSMartin Matuska     acc  = acc * PRIME64_1 + PRIME64_4;
429c03c5b1cSMartin Matuska     return acc;
430c03c5b1cSMartin Matuska }
431c03c5b1cSMartin Matuska 
XXH64_endian_align(const void * input,size_t len,U64 seed,XXH_endianess endian,XXH_alignment align)432c03c5b1cSMartin Matuska FORCE_INLINE_TEMPLATE U64 XXH64_endian_align(const void* input, size_t len, U64 seed, XXH_endianess endian, XXH_alignment align)
433c03c5b1cSMartin Matuska {
434c03c5b1cSMartin Matuska     const BYTE* p = (const BYTE*)input;
435c03c5b1cSMartin Matuska     const BYTE* const bEnd = p + len;
436c03c5b1cSMartin Matuska     U64 h64;
437c03c5b1cSMartin Matuska #define XXH_get64bits(p) XXH_readLE64_align(p, endian, align)
438c03c5b1cSMartin Matuska 
439c03c5b1cSMartin Matuska #ifdef XXH_ACCEPT_NULL_INPUT_POINTER
440c03c5b1cSMartin Matuska     if (p==NULL) {
441c03c5b1cSMartin Matuska         len=0;
442c03c5b1cSMartin Matuska         bEnd=p=(const BYTE*)(size_t)32;
443c03c5b1cSMartin Matuska     }
444c03c5b1cSMartin Matuska #endif
445c03c5b1cSMartin Matuska 
446c03c5b1cSMartin Matuska     if (len>=32) {
447c03c5b1cSMartin Matuska         const BYTE* const limit = bEnd - 32;
448c03c5b1cSMartin Matuska         U64 v1 = seed + PRIME64_1 + PRIME64_2;
449c03c5b1cSMartin Matuska         U64 v2 = seed + PRIME64_2;
450c03c5b1cSMartin Matuska         U64 v3 = seed + 0;
451c03c5b1cSMartin Matuska         U64 v4 = seed - PRIME64_1;
452c03c5b1cSMartin Matuska 
453c03c5b1cSMartin Matuska         do {
454c03c5b1cSMartin Matuska             v1 = XXH64_round(v1, XXH_get64bits(p)); p+=8;
455c03c5b1cSMartin Matuska             v2 = XXH64_round(v2, XXH_get64bits(p)); p+=8;
456c03c5b1cSMartin Matuska             v3 = XXH64_round(v3, XXH_get64bits(p)); p+=8;
457c03c5b1cSMartin Matuska             v4 = XXH64_round(v4, XXH_get64bits(p)); p+=8;
458c03c5b1cSMartin Matuska         } while (p<=limit);
459c03c5b1cSMartin Matuska 
460c03c5b1cSMartin Matuska         h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);
461c03c5b1cSMartin Matuska         h64 = XXH64_mergeRound(h64, v1);
462c03c5b1cSMartin Matuska         h64 = XXH64_mergeRound(h64, v2);
463c03c5b1cSMartin Matuska         h64 = XXH64_mergeRound(h64, v3);
464c03c5b1cSMartin Matuska         h64 = XXH64_mergeRound(h64, v4);
465c03c5b1cSMartin Matuska 
466c03c5b1cSMartin Matuska     } else {
467c03c5b1cSMartin Matuska         h64  = seed + PRIME64_5;
468c03c5b1cSMartin Matuska     }
469c03c5b1cSMartin Matuska 
470c03c5b1cSMartin Matuska     h64 += (U64) len;
471c03c5b1cSMartin Matuska 
472c03c5b1cSMartin Matuska     while (p+8<=bEnd) {
473c03c5b1cSMartin Matuska         U64 const k1 = XXH64_round(0, XXH_get64bits(p));
474c03c5b1cSMartin Matuska         h64 ^= k1;
475c03c5b1cSMartin Matuska         h64  = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4;
476c03c5b1cSMartin Matuska         p+=8;
477c03c5b1cSMartin Matuska     }
478c03c5b1cSMartin Matuska 
479c03c5b1cSMartin Matuska     if (p+4<=bEnd) {
480c03c5b1cSMartin Matuska         h64 ^= (U64)(XXH_get32bits(p)) * PRIME64_1;
481c03c5b1cSMartin Matuska         h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
482c03c5b1cSMartin Matuska         p+=4;
483c03c5b1cSMartin Matuska     }
484c03c5b1cSMartin Matuska 
485c03c5b1cSMartin Matuska     while (p<bEnd) {
486c03c5b1cSMartin Matuska         h64 ^= (*p) * PRIME64_5;
487c03c5b1cSMartin Matuska         h64 = XXH_rotl64(h64, 11) * PRIME64_1;
488c03c5b1cSMartin Matuska         p++;
489c03c5b1cSMartin Matuska     }
490c03c5b1cSMartin Matuska 
491c03c5b1cSMartin Matuska     h64 ^= h64 >> 33;
492c03c5b1cSMartin Matuska     h64 *= PRIME64_2;
493c03c5b1cSMartin Matuska     h64 ^= h64 >> 29;
494c03c5b1cSMartin Matuska     h64 *= PRIME64_3;
495c03c5b1cSMartin Matuska     h64 ^= h64 >> 32;
496c03c5b1cSMartin Matuska 
497c03c5b1cSMartin Matuska     return h64;
498c03c5b1cSMartin Matuska }
499c03c5b1cSMartin Matuska 
500c03c5b1cSMartin Matuska 
XXH64(const void * input,size_t len,unsigned long long seed)501c03c5b1cSMartin Matuska XXH_PUBLIC_API unsigned long long XXH64 (const void* input, size_t len, unsigned long long seed)
502c03c5b1cSMartin Matuska {
503c03c5b1cSMartin Matuska #if 0
504c03c5b1cSMartin Matuska     /* Simple version, good for code maintenance, but unfortunately slow for small inputs */
505c03c5b1cSMartin Matuska     XXH64_CREATESTATE_STATIC(state);
506c03c5b1cSMartin Matuska     XXH64_reset(state, seed);
507c03c5b1cSMartin Matuska     XXH64_update(state, input, len);
508c03c5b1cSMartin Matuska     return XXH64_digest(state);
509c03c5b1cSMartin Matuska #else
510c03c5b1cSMartin Matuska     XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
511c03c5b1cSMartin Matuska 
512c03c5b1cSMartin Matuska     if (XXH_FORCE_ALIGN_CHECK) {
513c03c5b1cSMartin Matuska         if ((((size_t)input) & 7)==0) {  /* Input is aligned, let's leverage the speed advantage */
514c03c5b1cSMartin Matuska             if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
515c03c5b1cSMartin Matuska                 return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
516c03c5b1cSMartin Matuska             else
517c03c5b1cSMartin Matuska                 return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
518c03c5b1cSMartin Matuska     }   }
519c03c5b1cSMartin Matuska 
520c03c5b1cSMartin Matuska     if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
521c03c5b1cSMartin Matuska         return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
522c03c5b1cSMartin Matuska     else
523c03c5b1cSMartin Matuska         return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
524c03c5b1cSMartin Matuska #endif
525c03c5b1cSMartin Matuska }
526c03c5b1cSMartin Matuska 
527c03c5b1cSMartin Matuska 
528c03c5b1cSMartin Matuska /* **************************************************
529c03c5b1cSMartin Matuska *  Advanced Hash Functions
530c03c5b1cSMartin Matuska ****************************************************/
531c03c5b1cSMartin Matuska 
XXH32_createState(void)532c03c5b1cSMartin Matuska XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void)
533c03c5b1cSMartin Matuska {
534c03c5b1cSMartin Matuska     return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t));
535c03c5b1cSMartin Matuska }
XXH32_freeState(XXH32_state_t * statePtr)536c03c5b1cSMartin Matuska XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr)
537c03c5b1cSMartin Matuska {
538c03c5b1cSMartin Matuska     XXH_free(statePtr);
539c03c5b1cSMartin Matuska     return XXH_OK;
540c03c5b1cSMartin Matuska }
541c03c5b1cSMartin Matuska 
XXH64_createState(void)542c03c5b1cSMartin Matuska XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void)
543c03c5b1cSMartin Matuska {
544c03c5b1cSMartin Matuska     return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t));
545c03c5b1cSMartin Matuska }
XXH64_freeState(XXH64_state_t * statePtr)546c03c5b1cSMartin Matuska XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr)
547c03c5b1cSMartin Matuska {
548c03c5b1cSMartin Matuska     XXH_free(statePtr);
549c03c5b1cSMartin Matuska     return XXH_OK;
550c03c5b1cSMartin Matuska }
551c03c5b1cSMartin Matuska 
552c03c5b1cSMartin Matuska 
553c03c5b1cSMartin Matuska /*** Hash feed ***/
554c03c5b1cSMartin Matuska 
XXH32_reset(XXH32_state_t * statePtr,unsigned int seed)555c03c5b1cSMartin Matuska XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, unsigned int seed)
556c03c5b1cSMartin Matuska {
557c03c5b1cSMartin Matuska     XXH32_state_t state;   /* using a local state to memcpy() in order to avoid strict-aliasing warnings */
558c03c5b1cSMartin Matuska     memset(&state, 0, sizeof(state)-4);   /* do not write into reserved, for future removal */
559c03c5b1cSMartin Matuska     state.v1 = seed + PRIME32_1 + PRIME32_2;
560c03c5b1cSMartin Matuska     state.v2 = seed + PRIME32_2;
561c03c5b1cSMartin Matuska     state.v3 = seed + 0;
562c03c5b1cSMartin Matuska     state.v4 = seed - PRIME32_1;
563c03c5b1cSMartin Matuska     memcpy(statePtr, &state, sizeof(state));
564c03c5b1cSMartin Matuska     return XXH_OK;
565c03c5b1cSMartin Matuska }
566c03c5b1cSMartin Matuska 
567c03c5b1cSMartin Matuska 
XXH64_reset(XXH64_state_t * statePtr,unsigned long long seed)568c03c5b1cSMartin Matuska XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH64_state_t* statePtr, unsigned long long seed)
569c03c5b1cSMartin Matuska {
570c03c5b1cSMartin Matuska     XXH64_state_t state;   /* using a local state to memcpy() in order to avoid strict-aliasing warnings */
571c03c5b1cSMartin Matuska     memset(&state, 0, sizeof(state)-8);   /* do not write into reserved, for future removal */
572c03c5b1cSMartin Matuska     state.v1 = seed + PRIME64_1 + PRIME64_2;
573c03c5b1cSMartin Matuska     state.v2 = seed + PRIME64_2;
574c03c5b1cSMartin Matuska     state.v3 = seed + 0;
575c03c5b1cSMartin Matuska     state.v4 = seed - PRIME64_1;
576c03c5b1cSMartin Matuska     memcpy(statePtr, &state, sizeof(state));
577c03c5b1cSMartin Matuska     return XXH_OK;
578c03c5b1cSMartin Matuska }
579c03c5b1cSMartin Matuska 
580c03c5b1cSMartin Matuska 
XXH32_update_endian(XXH32_state_t * state,const void * input,size_t len,XXH_endianess endian)581c03c5b1cSMartin Matuska FORCE_INLINE_TEMPLATE XXH_errorcode XXH32_update_endian (XXH32_state_t* state, const void* input, size_t len, XXH_endianess endian)
582c03c5b1cSMartin Matuska {
583c03c5b1cSMartin Matuska     const BYTE* p = (const BYTE*)input;
584c03c5b1cSMartin Matuska     const BYTE* const bEnd = p + len;
585c03c5b1cSMartin Matuska 
586c03c5b1cSMartin Matuska #ifdef XXH_ACCEPT_NULL_INPUT_POINTER
587c03c5b1cSMartin Matuska     if (input==NULL) return XXH_ERROR;
588c03c5b1cSMartin Matuska #endif
589c03c5b1cSMartin Matuska 
590c03c5b1cSMartin Matuska     state->total_len_32 += (unsigned)len;
591c03c5b1cSMartin Matuska     state->large_len |= (len>=16) | (state->total_len_32>=16);
592c03c5b1cSMartin Matuska 
593c03c5b1cSMartin Matuska     if (state->memsize + len < 16)  {   /* fill in tmp buffer */
594c03c5b1cSMartin Matuska         XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, len);
595c03c5b1cSMartin Matuska         state->memsize += (unsigned)len;
596c03c5b1cSMartin Matuska         return XXH_OK;
597c03c5b1cSMartin Matuska     }
598c03c5b1cSMartin Matuska 
599c03c5b1cSMartin Matuska     if (state->memsize) {   /* some data left from previous update */
600c03c5b1cSMartin Matuska         XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, 16-state->memsize);
601c03c5b1cSMartin Matuska         {   const U32* p32 = state->mem32;
602c03c5b1cSMartin Matuska             state->v1 = XXH32_round(state->v1, XXH_readLE32(p32, endian)); p32++;
603c03c5b1cSMartin Matuska             state->v2 = XXH32_round(state->v2, XXH_readLE32(p32, endian)); p32++;
604c03c5b1cSMartin Matuska             state->v3 = XXH32_round(state->v3, XXH_readLE32(p32, endian)); p32++;
605c03c5b1cSMartin Matuska             state->v4 = XXH32_round(state->v4, XXH_readLE32(p32, endian)); p32++;
606c03c5b1cSMartin Matuska         }
607c03c5b1cSMartin Matuska         p += 16-state->memsize;
608c03c5b1cSMartin Matuska         state->memsize = 0;
609c03c5b1cSMartin Matuska     }
610c03c5b1cSMartin Matuska 
611c03c5b1cSMartin Matuska     if (p <= bEnd-16) {
612c03c5b1cSMartin Matuska         const BYTE* const limit = bEnd - 16;
613c03c5b1cSMartin Matuska         U32 v1 = state->v1;
614c03c5b1cSMartin Matuska         U32 v2 = state->v2;
615c03c5b1cSMartin Matuska         U32 v3 = state->v3;
616c03c5b1cSMartin Matuska         U32 v4 = state->v4;
617c03c5b1cSMartin Matuska 
618c03c5b1cSMartin Matuska         do {
619c03c5b1cSMartin Matuska             v1 = XXH32_round(v1, XXH_readLE32(p, endian)); p+=4;
620c03c5b1cSMartin Matuska             v2 = XXH32_round(v2, XXH_readLE32(p, endian)); p+=4;
621c03c5b1cSMartin Matuska             v3 = XXH32_round(v3, XXH_readLE32(p, endian)); p+=4;
622c03c5b1cSMartin Matuska             v4 = XXH32_round(v4, XXH_readLE32(p, endian)); p+=4;
623c03c5b1cSMartin Matuska         } while (p<=limit);
624c03c5b1cSMartin Matuska 
625c03c5b1cSMartin Matuska         state->v1 = v1;
626c03c5b1cSMartin Matuska         state->v2 = v2;
627c03c5b1cSMartin Matuska         state->v3 = v3;
628c03c5b1cSMartin Matuska         state->v4 = v4;
629c03c5b1cSMartin Matuska     }
630c03c5b1cSMartin Matuska 
631c03c5b1cSMartin Matuska     if (p < bEnd) {
632c03c5b1cSMartin Matuska         XXH_memcpy(state->mem32, p, (size_t)(bEnd-p));
633c03c5b1cSMartin Matuska         state->memsize = (unsigned)(bEnd-p);
634c03c5b1cSMartin Matuska     }
635c03c5b1cSMartin Matuska 
636c03c5b1cSMartin Matuska     return XXH_OK;
637c03c5b1cSMartin Matuska }
638c03c5b1cSMartin Matuska 
XXH32_update(XXH32_state_t * state_in,const void * input,size_t len)639c03c5b1cSMartin Matuska XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* state_in, const void* input, size_t len)
640c03c5b1cSMartin Matuska {
641c03c5b1cSMartin Matuska     XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
642c03c5b1cSMartin Matuska 
643c03c5b1cSMartin Matuska     if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
644c03c5b1cSMartin Matuska         return XXH32_update_endian(state_in, input, len, XXH_littleEndian);
645c03c5b1cSMartin Matuska     else
646c03c5b1cSMartin Matuska         return XXH32_update_endian(state_in, input, len, XXH_bigEndian);
647c03c5b1cSMartin Matuska }
648c03c5b1cSMartin Matuska 
649c03c5b1cSMartin Matuska 
650c03c5b1cSMartin Matuska 
XXH32_digest_endian(const XXH32_state_t * state,XXH_endianess endian)651c03c5b1cSMartin Matuska FORCE_INLINE_TEMPLATE U32 XXH32_digest_endian (const XXH32_state_t* state, XXH_endianess endian)
652c03c5b1cSMartin Matuska {
653c03c5b1cSMartin Matuska     const BYTE * p = (const BYTE*)state->mem32;
654c03c5b1cSMartin Matuska     const BYTE* const bEnd = (const BYTE*)(state->mem32) + state->memsize;
655c03c5b1cSMartin Matuska     U32 h32;
656c03c5b1cSMartin Matuska 
657c03c5b1cSMartin Matuska     if (state->large_len) {
658c03c5b1cSMartin Matuska         h32 = XXH_rotl32(state->v1, 1) + XXH_rotl32(state->v2, 7) + XXH_rotl32(state->v3, 12) + XXH_rotl32(state->v4, 18);
659c03c5b1cSMartin Matuska     } else {
660c03c5b1cSMartin Matuska         h32 = state->v3 /* == seed */ + PRIME32_5;
661c03c5b1cSMartin Matuska     }
662c03c5b1cSMartin Matuska 
663c03c5b1cSMartin Matuska     h32 += state->total_len_32;
664c03c5b1cSMartin Matuska 
665c03c5b1cSMartin Matuska     while (p+4<=bEnd) {
666c03c5b1cSMartin Matuska         h32 += XXH_readLE32(p, endian) * PRIME32_3;
667c03c5b1cSMartin Matuska         h32  = XXH_rotl32(h32, 17) * PRIME32_4;
668c03c5b1cSMartin Matuska         p+=4;
669c03c5b1cSMartin Matuska     }
670c03c5b1cSMartin Matuska 
671c03c5b1cSMartin Matuska     while (p<bEnd) {
672c03c5b1cSMartin Matuska         h32 += (*p) * PRIME32_5;
673c03c5b1cSMartin Matuska         h32  = XXH_rotl32(h32, 11) * PRIME32_1;
674c03c5b1cSMartin Matuska         p++;
675c03c5b1cSMartin Matuska     }
676c03c5b1cSMartin Matuska 
677c03c5b1cSMartin Matuska     h32 ^= h32 >> 15;
678c03c5b1cSMartin Matuska     h32 *= PRIME32_2;
679c03c5b1cSMartin Matuska     h32 ^= h32 >> 13;
680c03c5b1cSMartin Matuska     h32 *= PRIME32_3;
681c03c5b1cSMartin Matuska     h32 ^= h32 >> 16;
682c03c5b1cSMartin Matuska 
683c03c5b1cSMartin Matuska     return h32;
684c03c5b1cSMartin Matuska }
685c03c5b1cSMartin Matuska 
686c03c5b1cSMartin Matuska 
XXH32_digest(const XXH32_state_t * state_in)687c03c5b1cSMartin Matuska XXH_PUBLIC_API unsigned int XXH32_digest (const XXH32_state_t* state_in)
688c03c5b1cSMartin Matuska {
689c03c5b1cSMartin Matuska     XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
690c03c5b1cSMartin Matuska 
691c03c5b1cSMartin Matuska     if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
692c03c5b1cSMartin Matuska         return XXH32_digest_endian(state_in, XXH_littleEndian);
693c03c5b1cSMartin Matuska     else
694c03c5b1cSMartin Matuska         return XXH32_digest_endian(state_in, XXH_bigEndian);
695c03c5b1cSMartin Matuska }
696c03c5b1cSMartin Matuska 
697c03c5b1cSMartin Matuska 
698c03c5b1cSMartin Matuska 
699c03c5b1cSMartin Matuska /* **** XXH64 **** */
700c03c5b1cSMartin Matuska 
XXH64_update_endian(XXH64_state_t * state,const void * input,size_t len,XXH_endianess endian)701c03c5b1cSMartin Matuska FORCE_INLINE_TEMPLATE XXH_errorcode XXH64_update_endian (XXH64_state_t* state, const void* input, size_t len, XXH_endianess endian)
702c03c5b1cSMartin Matuska {
703c03c5b1cSMartin Matuska     const BYTE* p = (const BYTE*)input;
704c03c5b1cSMartin Matuska     const BYTE* const bEnd = p + len;
705c03c5b1cSMartin Matuska 
706c03c5b1cSMartin Matuska #ifdef XXH_ACCEPT_NULL_INPUT_POINTER
707c03c5b1cSMartin Matuska     if (input==NULL) return XXH_ERROR;
708c03c5b1cSMartin Matuska #endif
709c03c5b1cSMartin Matuska 
710c03c5b1cSMartin Matuska     state->total_len += len;
711c03c5b1cSMartin Matuska 
712c03c5b1cSMartin Matuska     if (state->memsize + len < 32) {  /* fill in tmp buffer */
713c03c5b1cSMartin Matuska         if (input != NULL) {
714c03c5b1cSMartin Matuska             XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, len);
715c03c5b1cSMartin Matuska         }
716c03c5b1cSMartin Matuska         state->memsize += (U32)len;
717c03c5b1cSMartin Matuska         return XXH_OK;
718c03c5b1cSMartin Matuska     }
719c03c5b1cSMartin Matuska 
720c03c5b1cSMartin Matuska     if (state->memsize) {   /* tmp buffer is full */
721c03c5b1cSMartin Matuska         XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, 32-state->memsize);
722c03c5b1cSMartin Matuska         state->v1 = XXH64_round(state->v1, XXH_readLE64(state->mem64+0, endian));
723c03c5b1cSMartin Matuska         state->v2 = XXH64_round(state->v2, XXH_readLE64(state->mem64+1, endian));
724c03c5b1cSMartin Matuska         state->v3 = XXH64_round(state->v3, XXH_readLE64(state->mem64+2, endian));
725c03c5b1cSMartin Matuska         state->v4 = XXH64_round(state->v4, XXH_readLE64(state->mem64+3, endian));
726c03c5b1cSMartin Matuska         p += 32-state->memsize;
727c03c5b1cSMartin Matuska         state->memsize = 0;
728c03c5b1cSMartin Matuska     }
729c03c5b1cSMartin Matuska 
730c03c5b1cSMartin Matuska     if (p+32 <= bEnd) {
731c03c5b1cSMartin Matuska         const BYTE* const limit = bEnd - 32;
732c03c5b1cSMartin Matuska         U64 v1 = state->v1;
733c03c5b1cSMartin Matuska         U64 v2 = state->v2;
734c03c5b1cSMartin Matuska         U64 v3 = state->v3;
735c03c5b1cSMartin Matuska         U64 v4 = state->v4;
736c03c5b1cSMartin Matuska 
737c03c5b1cSMartin Matuska         do {
738c03c5b1cSMartin Matuska             v1 = XXH64_round(v1, XXH_readLE64(p, endian)); p+=8;
739c03c5b1cSMartin Matuska             v2 = XXH64_round(v2, XXH_readLE64(p, endian)); p+=8;
740c03c5b1cSMartin Matuska             v3 = XXH64_round(v3, XXH_readLE64(p, endian)); p+=8;
741c03c5b1cSMartin Matuska             v4 = XXH64_round(v4, XXH_readLE64(p, endian)); p+=8;
742c03c5b1cSMartin Matuska         } while (p<=limit);
743c03c5b1cSMartin Matuska 
744c03c5b1cSMartin Matuska         state->v1 = v1;
745c03c5b1cSMartin Matuska         state->v2 = v2;
746c03c5b1cSMartin Matuska         state->v3 = v3;
747c03c5b1cSMartin Matuska         state->v4 = v4;
748c03c5b1cSMartin Matuska     }
749c03c5b1cSMartin Matuska 
750c03c5b1cSMartin Matuska     if (p < bEnd) {
751c03c5b1cSMartin Matuska         XXH_memcpy(state->mem64, p, (size_t)(bEnd-p));
752c03c5b1cSMartin Matuska         state->memsize = (unsigned)(bEnd-p);
753c03c5b1cSMartin Matuska     }
754c03c5b1cSMartin Matuska 
755c03c5b1cSMartin Matuska     return XXH_OK;
756c03c5b1cSMartin Matuska }
757c03c5b1cSMartin Matuska 
XXH64_update(XXH64_state_t * state_in,const void * input,size_t len)758c03c5b1cSMartin Matuska XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* state_in, const void* input, size_t len)
759c03c5b1cSMartin Matuska {
760c03c5b1cSMartin Matuska     XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
761c03c5b1cSMartin Matuska 
762c03c5b1cSMartin Matuska     if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
763c03c5b1cSMartin Matuska         return XXH64_update_endian(state_in, input, len, XXH_littleEndian);
764c03c5b1cSMartin Matuska     else
765c03c5b1cSMartin Matuska         return XXH64_update_endian(state_in, input, len, XXH_bigEndian);
766c03c5b1cSMartin Matuska }
767c03c5b1cSMartin Matuska 
768c03c5b1cSMartin Matuska 
769c03c5b1cSMartin Matuska 
XXH64_digest_endian(const XXH64_state_t * state,XXH_endianess endian)770c03c5b1cSMartin Matuska FORCE_INLINE_TEMPLATE U64 XXH64_digest_endian (const XXH64_state_t* state, XXH_endianess endian)
771c03c5b1cSMartin Matuska {
772c03c5b1cSMartin Matuska     const BYTE * p = (const BYTE*)state->mem64;
773c03c5b1cSMartin Matuska     const BYTE* const bEnd = (const BYTE*)state->mem64 + state->memsize;
774c03c5b1cSMartin Matuska     U64 h64;
775c03c5b1cSMartin Matuska 
776c03c5b1cSMartin Matuska     if (state->total_len >= 32) {
777c03c5b1cSMartin Matuska         U64 const v1 = state->v1;
778c03c5b1cSMartin Matuska         U64 const v2 = state->v2;
779c03c5b1cSMartin Matuska         U64 const v3 = state->v3;
780c03c5b1cSMartin Matuska         U64 const v4 = state->v4;
781c03c5b1cSMartin Matuska 
782c03c5b1cSMartin Matuska         h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);
783c03c5b1cSMartin Matuska         h64 = XXH64_mergeRound(h64, v1);
784c03c5b1cSMartin Matuska         h64 = XXH64_mergeRound(h64, v2);
785c03c5b1cSMartin Matuska         h64 = XXH64_mergeRound(h64, v3);
786c03c5b1cSMartin Matuska         h64 = XXH64_mergeRound(h64, v4);
787c03c5b1cSMartin Matuska     } else {
788c03c5b1cSMartin Matuska         h64  = state->v3 + PRIME64_5;
789c03c5b1cSMartin Matuska     }
790c03c5b1cSMartin Matuska 
791c03c5b1cSMartin Matuska     h64 += (U64) state->total_len;
792c03c5b1cSMartin Matuska 
793c03c5b1cSMartin Matuska     while (p+8<=bEnd) {
794c03c5b1cSMartin Matuska         U64 const k1 = XXH64_round(0, XXH_readLE64(p, endian));
795c03c5b1cSMartin Matuska         h64 ^= k1;
796c03c5b1cSMartin Matuska         h64  = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4;
797c03c5b1cSMartin Matuska         p+=8;
798c03c5b1cSMartin Matuska     }
799c03c5b1cSMartin Matuska 
800c03c5b1cSMartin Matuska     if (p+4<=bEnd) {
801c03c5b1cSMartin Matuska         h64 ^= (U64)(XXH_readLE32(p, endian)) * PRIME64_1;
802c03c5b1cSMartin Matuska         h64  = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
803c03c5b1cSMartin Matuska         p+=4;
804c03c5b1cSMartin Matuska     }
805c03c5b1cSMartin Matuska 
806c03c5b1cSMartin Matuska     while (p<bEnd) {
807c03c5b1cSMartin Matuska         h64 ^= (*p) * PRIME64_5;
808c03c5b1cSMartin Matuska         h64  = XXH_rotl64(h64, 11) * PRIME64_1;
809c03c5b1cSMartin Matuska         p++;
810c03c5b1cSMartin Matuska     }
811c03c5b1cSMartin Matuska 
812c03c5b1cSMartin Matuska     h64 ^= h64 >> 33;
813c03c5b1cSMartin Matuska     h64 *= PRIME64_2;
814c03c5b1cSMartin Matuska     h64 ^= h64 >> 29;
815c03c5b1cSMartin Matuska     h64 *= PRIME64_3;
816c03c5b1cSMartin Matuska     h64 ^= h64 >> 32;
817c03c5b1cSMartin Matuska 
818c03c5b1cSMartin Matuska     return h64;
819c03c5b1cSMartin Matuska }
820c03c5b1cSMartin Matuska 
821c03c5b1cSMartin Matuska 
XXH64_digest(const XXH64_state_t * state_in)822c03c5b1cSMartin Matuska XXH_PUBLIC_API unsigned long long XXH64_digest (const XXH64_state_t* state_in)
823c03c5b1cSMartin Matuska {
824c03c5b1cSMartin Matuska     XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
825c03c5b1cSMartin Matuska 
826c03c5b1cSMartin Matuska     if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
827c03c5b1cSMartin Matuska         return XXH64_digest_endian(state_in, XXH_littleEndian);
828c03c5b1cSMartin Matuska     else
829c03c5b1cSMartin Matuska         return XXH64_digest_endian(state_in, XXH_bigEndian);
830c03c5b1cSMartin Matuska }
831c03c5b1cSMartin Matuska 
832c03c5b1cSMartin Matuska 
833c03c5b1cSMartin Matuska /* **************************
834c03c5b1cSMartin Matuska *  Canonical representation
835c03c5b1cSMartin Matuska ****************************/
836c03c5b1cSMartin Matuska 
837c03c5b1cSMartin Matuska /*! Default XXH result types are basic unsigned 32 and 64 bits.
838c03c5b1cSMartin Matuska *   The canonical representation follows human-readable write convention, aka big-endian (large digits first).
839c03c5b1cSMartin Matuska *   These functions allow transformation of hash result into and from its canonical format.
840c03c5b1cSMartin Matuska *   This way, hash values can be written into a file or buffer, and remain comparable across different systems and programs.
841c03c5b1cSMartin Matuska */
842c03c5b1cSMartin Matuska 
XXH32_canonicalFromHash(XXH32_canonical_t * dst,XXH32_hash_t hash)843c03c5b1cSMartin Matuska XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash)
844c03c5b1cSMartin Matuska {
845c03c5b1cSMartin Matuska     XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t));
846c03c5b1cSMartin Matuska     if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap32(hash);
847c03c5b1cSMartin Matuska     memcpy(dst, &hash, sizeof(*dst));
848c03c5b1cSMartin Matuska }
849c03c5b1cSMartin Matuska 
XXH64_canonicalFromHash(XXH64_canonical_t * dst,XXH64_hash_t hash)850c03c5b1cSMartin Matuska XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash)
851c03c5b1cSMartin Matuska {
852c03c5b1cSMartin Matuska     XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t));
853c03c5b1cSMartin Matuska     if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap64(hash);
854c03c5b1cSMartin Matuska     memcpy(dst, &hash, sizeof(*dst));
855c03c5b1cSMartin Matuska }
856c03c5b1cSMartin Matuska 
XXH32_hashFromCanonical(const XXH32_canonical_t * src)857c03c5b1cSMartin Matuska XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src)
858c03c5b1cSMartin Matuska {
859c03c5b1cSMartin Matuska     return XXH_readBE32(src);
860c03c5b1cSMartin Matuska }
861c03c5b1cSMartin Matuska 
XXH64_hashFromCanonical(const XXH64_canonical_t * src)862c03c5b1cSMartin Matuska XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src)
863c03c5b1cSMartin Matuska {
864c03c5b1cSMartin Matuska     return XXH_readBE64(src);
865c03c5b1cSMartin Matuska }
866