Unravel Engine C++ Reference
Loading...
Searching...
No Matches
xxhash.h
Go to the documentation of this file.
1/*
2 * xxHash - Extremely Fast Hash algorithm
3 * Header File
4 * Copyright (C) 2012-2023 Yann Collet
5 *
6 * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php)
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above
15 * copyright notice, this list of conditions and the following disclaimer
16 * in the documentation and/or other materials provided with the
17 * distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 * You can contact the author at:
32 * - xxHash homepage: https://www.xxhash.com
33 * - xxHash source repository: https://github.com/Cyan4973/xxHash
34 */
35
244#if defined(__cplusplus) && !defined(XXH_NO_EXTERNC_GUARD)
245extern "C" {
246#endif
247
248/* ****************************
249 * INLINE mode
250 ******************************/
256#ifdef XXH_DOXYGEN
268# define XXH_STATIC_LINKING_ONLY
269/* Do not undef XXH_STATIC_LINKING_ONLY for Doxygen */
270
281# define XXH_IMPLEMENTATION
282/* Do not undef XXH_IMPLEMENTATION for Doxygen */
283
302# define XXH_INLINE_ALL
303# undef XXH_INLINE_ALL
307# define XXH_PRIVATE_API
308# undef XXH_PRIVATE_API
322# define XXH_NAMESPACE /* YOUR NAME HERE */
323# undef XXH_NAMESPACE
324#endif
325
326#define XXH_CAT(A,B) A##B
327#define XXH_NAME2(A,B) XXH_CAT(A,B)
328#define XXH_IPREF(Id) XXH_NAME2(XXH_NAMESPACE, Id)
329
330#if (defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API)) \
331 && !defined(XXH_INLINE_ALL_31684351384)
332 /* this section should be traversed only once */
333# define XXH_INLINE_ALL_31684351384
334 /* give access to the advanced API, required to compile implementations */
335# undef XXH_STATIC_LINKING_ONLY /* avoid macro redef */
336# define XXH_STATIC_LINKING_ONLY
337 /* make all functions private */
338# undef XXH_PUBLIC_API
339# if defined(__GNUC__)
340# define XXH_PUBLIC_API static __inline __attribute__((__unused__))
341# elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
342# define XXH_PUBLIC_API static inline
343# elif defined(_MSC_VER)
344# define XXH_PUBLIC_API static __inline
345# else
346 /* note: this version may generate warnings for unused static functions */
347# define XXH_PUBLIC_API static
348# endif
349
350 /*
351 * This part deals with the special case where a unit wants to inline xxHash,
352 * but "xxhash.h" has previously been included without XXH_INLINE_ALL,
353 * such as part of some previously included *.h header file.
354 * Without further action, the new include would just be ignored,
355 * and functions would effectively _not_ be inlined (silent failure).
356 * The following macros solve this situation by prefixing all inlined names,
357 * avoiding naming collision with previous inclusions.
358 */
359 /* Before that, we unconditionally #undef all symbols,
360 * in case they were already defined with XXH_NAMESPACE.
361 * They will then be redefined for XXH_INLINE_ALL
362 */
363# undef XXH_versionNumber
364 /* XXH32 */
365# undef XXH32
366# undef XXH32_createState
367# undef XXH32_freeState
368# undef XXH32_reset
369# undef XXH32_update
370# undef XXH32_digest
371# undef XXH32_copyState
372# undef XXH32_canonicalFromHash
373# undef XXH32_hashFromCanonical
374 /* XXH64 */
375# undef XXH64
376# undef XXH64_createState
377# undef XXH64_freeState
378# undef XXH64_reset
379# undef XXH64_update
380# undef XXH64_digest
381# undef XXH64_copyState
382# undef XXH64_canonicalFromHash
383# undef XXH64_hashFromCanonical
384 /* XXH3_64bits */
385# undef XXH3_64bits
386# undef XXH3_64bits_withSecret
387# undef XXH3_64bits_withSeed
388# undef XXH3_64bits_withSecretandSeed
389# undef XXH3_createState
390# undef XXH3_freeState
391# undef XXH3_copyState
392# undef XXH3_64bits_reset
393# undef XXH3_64bits_reset_withSeed
394# undef XXH3_64bits_reset_withSecret
395# undef XXH3_64bits_update
396# undef XXH3_64bits_digest
397# undef XXH3_generateSecret
398 /* XXH3_128bits */
399# undef XXH128
400# undef XXH3_128bits
401# undef XXH3_128bits_withSeed
402# undef XXH3_128bits_withSecret
403# undef XXH3_128bits_reset
404# undef XXH3_128bits_reset_withSeed
405# undef XXH3_128bits_reset_withSecret
406# undef XXH3_128bits_reset_withSecretandSeed
407# undef XXH3_128bits_update
408# undef XXH3_128bits_digest
409# undef XXH128_isEqual
410# undef XXH128_cmp
411# undef XXH128_canonicalFromHash
412# undef XXH128_hashFromCanonical
413 /* Finally, free the namespace itself */
414# undef XXH_NAMESPACE
415
416 /* employ the namespace for XXH_INLINE_ALL */
417# define XXH_NAMESPACE XXH_INLINE_
418 /*
419 * Some identifiers (enums, type names) are not symbols,
420 * but they must nonetheless be renamed to avoid redeclaration.
421 * Alternative solution: do not redeclare them.
422 * However, this requires some #ifdefs, and has a more dispersed impact.
423 * Meanwhile, renaming can be achieved in a single place.
424 */
425# define XXH_OK XXH_IPREF(XXH_OK)
426# define XXH_ERROR XXH_IPREF(XXH_ERROR)
427# define XXH_errorcode XXH_IPREF(XXH_errorcode)
428# define XXH32_canonical_t XXH_IPREF(XXH32_canonical_t)
429# define XXH64_canonical_t XXH_IPREF(XXH64_canonical_t)
430# define XXH128_canonical_t XXH_IPREF(XXH128_canonical_t)
431# define XXH32_state_s XXH_IPREF(XXH32_state_s)
432# define XXH32_state_t XXH_IPREF(XXH32_state_t)
433# define XXH64_state_s XXH_IPREF(XXH64_state_s)
434# define XXH64_state_t XXH_IPREF(XXH64_state_t)
435# define XXH3_state_s XXH_IPREF(XXH3_state_s)
436# define XXH3_state_t XXH_IPREF(XXH3_state_t)
437# define XXH128_hash_t XXH_IPREF(XXH128_hash_t)
438 /* Ensure the header is parsed again, even if it was previously included */
439# undef XXHASH_H_5627135585666179
440# undef XXHASH_H_STATIC_13879238742
441#endif /* XXH_INLINE_ALL || XXH_PRIVATE_API */
442
443/* ****************************************************************
444 * Stable API
445 *****************************************************************/
446#ifndef XXHASH_H_5627135585666179
447#define XXHASH_H_5627135585666179 1
448
450#if !defined(XXH_INLINE_ALL) && !defined(XXH_PRIVATE_API)
451# if defined(_WIN32) && defined(_MSC_VER) && (defined(XXH_IMPORT) || defined(XXH_EXPORT))
452# ifdef XXH_EXPORT
453# define XXH_PUBLIC_API __declspec(dllexport)
454# elif XXH_IMPORT
455# define XXH_PUBLIC_API __declspec(dllimport)
456# endif
457# else
458# define XXH_PUBLIC_API /* do nothing */
459# endif
460#endif
461
462#ifdef XXH_NAMESPACE
463# define XXH_versionNumber XXH_IPREF(XXH_versionNumber)
464/* XXH32 */
465# define XXH32 XXH_IPREF(XXH32)
466# define XXH32_createState XXH_IPREF(XXH32_createState)
467# define XXH32_freeState XXH_IPREF(XXH32_freeState)
468# define XXH32_reset XXH_IPREF(XXH32_reset)
469# define XXH32_update XXH_IPREF(XXH32_update)
470# define XXH32_digest XXH_IPREF(XXH32_digest)
471# define XXH32_copyState XXH_IPREF(XXH32_copyState)
472# define XXH32_canonicalFromHash XXH_IPREF(XXH32_canonicalFromHash)
473# define XXH32_hashFromCanonical XXH_IPREF(XXH32_hashFromCanonical)
474/* XXH64 */
475# define XXH64 XXH_IPREF(XXH64)
476# define XXH64_createState XXH_IPREF(XXH64_createState)
477# define XXH64_freeState XXH_IPREF(XXH64_freeState)
478# define XXH64_reset XXH_IPREF(XXH64_reset)
479# define XXH64_update XXH_IPREF(XXH64_update)
480# define XXH64_digest XXH_IPREF(XXH64_digest)
481# define XXH64_copyState XXH_IPREF(XXH64_copyState)
482# define XXH64_canonicalFromHash XXH_IPREF(XXH64_canonicalFromHash)
483# define XXH64_hashFromCanonical XXH_IPREF(XXH64_hashFromCanonical)
484/* XXH3_64bits */
485# define XXH3_64bits XXH_IPREF(XXH3_64bits)
486# define XXH3_64bits_withSecret XXH_IPREF(XXH3_64bits_withSecret)
487# define XXH3_64bits_withSeed XXH_IPREF(XXH3_64bits_withSeed)
488# define XXH3_64bits_withSecretandSeed XXH_IPREF(XXH3_64bits_withSecretandSeed)
489# define XXH3_createState XXH_IPREF(XXH3_createState)
490# define XXH3_freeState XXH_IPREF(XXH3_freeState)
491# define XXH3_copyState XXH_IPREF(XXH3_copyState)
492# define XXH3_64bits_reset XXH_IPREF(XXH3_64bits_reset)
493# define XXH3_64bits_reset_withSeed XXH_IPREF(XXH3_64bits_reset_withSeed)
494# define XXH3_64bits_reset_withSecret XXH_IPREF(XXH3_64bits_reset_withSecret)
495# define XXH3_64bits_reset_withSecretandSeed XXH_IPREF(XXH3_64bits_reset_withSecretandSeed)
496# define XXH3_64bits_update XXH_IPREF(XXH3_64bits_update)
497# define XXH3_64bits_digest XXH_IPREF(XXH3_64bits_digest)
498# define XXH3_generateSecret XXH_IPREF(XXH3_generateSecret)
499# define XXH3_generateSecret_fromSeed XXH_IPREF(XXH3_generateSecret_fromSeed)
500/* XXH3_128bits */
501# define XXH128 XXH_IPREF(XXH128)
502# define XXH3_128bits XXH_IPREF(XXH3_128bits)
503# define XXH3_128bits_withSeed XXH_IPREF(XXH3_128bits_withSeed)
504# define XXH3_128bits_withSecret XXH_IPREF(XXH3_128bits_withSecret)
505# define XXH3_128bits_withSecretandSeed XXH_IPREF(XXH3_128bits_withSecretandSeed)
506# define XXH3_128bits_reset XXH_IPREF(XXH3_128bits_reset)
507# define XXH3_128bits_reset_withSeed XXH_IPREF(XXH3_128bits_reset_withSeed)
508# define XXH3_128bits_reset_withSecret XXH_IPREF(XXH3_128bits_reset_withSecret)
509# define XXH3_128bits_reset_withSecretandSeed XXH_IPREF(XXH3_128bits_reset_withSecretandSeed)
510# define XXH3_128bits_update XXH_IPREF(XXH3_128bits_update)
511# define XXH3_128bits_digest XXH_IPREF(XXH3_128bits_digest)
512# define XXH128_isEqual XXH_IPREF(XXH128_isEqual)
513# define XXH128_cmp XXH_IPREF(XXH128_cmp)
514# define XXH128_canonicalFromHash XXH_IPREF(XXH128_canonicalFromHash)
515# define XXH128_hashFromCanonical XXH_IPREF(XXH128_hashFromCanonical)
516#endif
517
518
519/* *************************************
520* Compiler specifics
521***************************************/
522
523/* specific declaration modes for Windows */
524#if !defined(XXH_INLINE_ALL) && !defined(XXH_PRIVATE_API)
525# if defined(_WIN32) && defined(_MSC_VER) && (defined(XXH_IMPORT) || defined(XXH_EXPORT))
526# ifdef XXH_EXPORT
527# define XXH_PUBLIC_API __declspec(dllexport)
528# elif XXH_IMPORT
529# define XXH_PUBLIC_API __declspec(dllimport)
530# endif
531# else
532# define XXH_PUBLIC_API /* do nothing */
533# endif
534#endif
535
536#if defined (__GNUC__)
537# define XXH_CONSTF __attribute__((__const__))
538# define XXH_PUREF __attribute__((__pure__))
539# define XXH_MALLOCF __attribute__((__malloc__))
540#else
541# define XXH_CONSTF /* disable */
542# define XXH_PUREF
543# define XXH_MALLOCF
544#endif
545
546/* *************************************
547* Version
548***************************************/
549#define XXH_VERSION_MAJOR 0
550#define XXH_VERSION_MINOR 8
551#define XXH_VERSION_RELEASE 3
553#define XXH_VERSION_NUMBER (XXH_VERSION_MAJOR *100*100 + XXH_VERSION_MINOR *100 + XXH_VERSION_RELEASE)
554
564
565
566/* ****************************
567* Common basic types
568******************************/
569#include <stddef.h> /* size_t */
573typedef enum {
574 XXH_OK = 0,
575 XXH_ERROR
577
578
579/*-**********************************************************************
580* 32-bit hash
581************************************************************************/
582#if defined(XXH_DOXYGEN) /* Don't show <stdint.h> include */
588typedef uint32_t XXH32_hash_t;
589
590#elif !defined (__VMS) \
591 && (defined (__cplusplus) \
592 || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
593# ifdef _AIX
594# include <inttypes.h>
595# else
596# include <stdint.h>
597# endif
598 typedef uint32_t XXH32_hash_t;
599
600#else
601# include <limits.h>
602# if UINT_MAX == 0xFFFFFFFFUL
603 typedef unsigned int XXH32_hash_t;
604# elif ULONG_MAX == 0xFFFFFFFFUL
605 typedef unsigned long XXH32_hash_t;
606# else
607# error "unsupported platform: need a 32-bit type"
608# endif
609#endif
610
644XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32 (const void* input, size_t length, XXH32_hash_t seed);
645
646#ifndef XXH_NO_STREAM
654typedef struct XXH32_state_s XXH32_state_t;
655
689
707
729XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length);
730
747XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32_digest (const XXH32_state_t* statePtr);
748#endif /* !XXH_NO_STREAM */
749
750/******* Canonical representation *******/
751
755typedef struct {
756 unsigned char digest[4];
758
771
785
786
788#ifdef __has_attribute
789# define XXH_HAS_ATTRIBUTE(x) __has_attribute(x)
790#else
791# define XXH_HAS_ATTRIBUTE(x) 0
792#endif
796/* C-language Attributes are added in C23. */
797#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 202311L) && defined(__has_c_attribute)
798# define XXH_HAS_C_ATTRIBUTE(x) __has_c_attribute(x)
799#else
800# define XXH_HAS_C_ATTRIBUTE(x) 0
801#endif
805#if defined(__cplusplus) && defined(__has_cpp_attribute)
806# define XXH_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
807#else
808# define XXH_HAS_CPP_ATTRIBUTE(x) 0
809#endif
813/*
814 * Define XXH_FALLTHROUGH macro for annotating switch case with the 'fallthrough' attribute
815 * introduced in CPP17 and C23.
816 * CPP17 : https://en.cppreference.com/w/cpp/language/attributes/fallthrough
817 * C23 : https://en.cppreference.com/w/c/language/attributes/fallthrough
818 */
819#if XXH_HAS_C_ATTRIBUTE(fallthrough) || XXH_HAS_CPP_ATTRIBUTE(fallthrough)
820# define XXH_FALLTHROUGH [[fallthrough]]
821#elif XXH_HAS_ATTRIBUTE(__fallthrough__)
822# define XXH_FALLTHROUGH __attribute__ ((__fallthrough__))
823#else
824# define XXH_FALLTHROUGH /* fallthrough */
825#endif
829/*
830 * Define XXH_NOESCAPE for annotated pointers in public API.
831 * https://clang.llvm.org/docs/AttributeReference.html#noescape
832 * As of writing this, only supported by clang.
833 */
834#if XXH_HAS_ATTRIBUTE(noescape)
835# define XXH_NOESCAPE __attribute__((__noescape__))
836#else
837# define XXH_NOESCAPE
838#endif
848#ifndef XXH_NO_LONG_LONG
849/*-**********************************************************************
850* 64-bit hash
851************************************************************************/
852#if defined(XXH_DOXYGEN) /* don't include <stdint.h> */
858typedef uint64_t XXH64_hash_t;
859#elif !defined (__VMS) \
860 && (defined (__cplusplus) \
861 || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
862# ifdef _AIX
863# include <inttypes.h>
864# else
865# include <stdint.h>
866# endif
867 typedef uint64_t XXH64_hash_t;
868#else
869# include <limits.h>
870# if defined(__LP64__) && ULONG_MAX == 0xFFFFFFFFFFFFFFFFULL
871 /* LP64 ABI says uint64_t is unsigned long */
872 typedef unsigned long XXH64_hash_t;
873# else
874 /* the following type must have a width of 64-bit */
875 typedef unsigned long long XXH64_hash_t;
876# endif
877#endif
878
909XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64(XXH_NOESCAPE const void* input, size_t length, XXH64_hash_t seed);
910
911/******* Streaming *******/
912#ifndef XXH_NO_STREAM
919typedef struct XXH64_state_s XXH64_state_t; /* incomplete type */
920
932
945
954XXH_PUBLIC_API void XXH64_copyState(XXH_NOESCAPE XXH64_state_t* dst_state, const XXH64_state_t* src_state);
955
973
995XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH_NOESCAPE XXH64_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length);
996
1014#endif /* !XXH_NO_STREAM */
1015/******* Canonical representation *******/
1016
1020typedef struct { unsigned char digest[sizeof(XXH64_hash_t)]; } XXH64_canonical_t;
1021
1034
1048
1049#ifndef XXH_NO_XXH3
1050
1112# define XXH_SCALAR 0
1113# define XXH_SSE2 1
1114# define XXH_AVX2 2
1115# define XXH_AVX512 3
1116# define XXH_NEON 4
1117# define XXH_VSX 5
1118# define XXH_SVE 6
1119# define XXH_LSX 7
1120# define XXH_LASX 8
1121# define XXH_RVV 9
1123/*-**********************************************************************
1124* XXH3 64-bit variant
1125************************************************************************/
1126
1149XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits(XXH_NOESCAPE const void* input, size_t length);
1150
1175XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_withSeed(XXH_NOESCAPE const void* input, size_t length, XXH64_hash_t seed);
1176
1184#define XXH3_SECRET_SIZE_MIN 136
1185
1218XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_withSecret(XXH_NOESCAPE const void* data, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize);
1219
1220
1221/******* Streaming *******/
1222#ifndef XXH_NO_STREAM
1223/*
1224 * Streaming requires state maintenance.
1225 * This operation costs memory and CPU.
1226 * As a consequence, streaming is slower than one-shot hashing.
1227 * For better performance, prefer one-shot functions whenever applicable.
1228 */
1229
1236typedef struct XXH3_state_s XXH3_state_t;
1239
1248XXH_PUBLIC_API void XXH3_copyState(XXH_NOESCAPE XXH3_state_t* dst_state, XXH_NOESCAPE const XXH3_state_t* src_state);
1249
1270
1292
1317XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize);
1318
1340XXH_PUBLIC_API XXH_errorcode XXH3_64bits_update (XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length);
1341
1359#endif /* !XXH_NO_STREAM */
1360
1361/* note : canonical representation of XXH3 is the same as XXH64
1362 * since they both produce XXH64_hash_t values */
1363
1364
1365/*-**********************************************************************
1366* XXH3 128-bit variant
1367************************************************************************/
1368
1379
1398XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits(XXH_NOESCAPE const void* data, size_t len);
1418XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_withSeed(XXH_NOESCAPE const void* data, size_t len, XXH64_hash_t seed);
1446XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_withSecret(XXH_NOESCAPE const void* data, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize);
1447
1448/******* Streaming *******/
1449#ifndef XXH_NO_STREAM
1450/*
1451 * Streaming requires state maintenance.
1452 * This operation costs memory and CPU.
1453 * As a consequence, streaming is slower than one-shot hashing.
1454 * For better performance, prefer one-shot functions whenever applicable.
1455 *
1456 * XXH3_128bits uses the same XXH3_state_t as XXH3_64bits().
1457 * Use already declared XXH3_createState() and XXH3_freeState().
1458 *
1459 * All reset and streaming functions have same meaning as their 64-bit counterpart.
1460 */
1461
1481
1524XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize);
1525
1547XXH_PUBLIC_API XXH_errorcode XXH3_128bits_update (XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length);
1548
1565#endif /* !XXH_NO_STREAM */
1566
1567/* Following helper functions make it possible to compare XXH128_hast_t values.
1568 * Since XXH128_hash_t is a structure, this capability is not offered by the language.
1569 * Note: For better performance, these functions can be inlined using XXH_INLINE_ALL */
1570
1581
1594XXH_PUBLIC_API XXH_PUREF int XXH128_cmp(XXH_NOESCAPE const void* h128_1, XXH_NOESCAPE const void* h128_2);
1595
1596
1597/******* Canonical representation *******/
1598typedef struct { unsigned char digest[sizeof(XXH128_hash_t)]; } XXH128_canonical_t;
1599
1600
1612
1625
1626
1627#endif /* !XXH_NO_XXH3 */
1628#endif /* XXH_NO_LONG_LONG */
1629
1633#endif /* XXHASH_H_5627135585666179 */
1634
1635
1636
1637#if defined(XXH_STATIC_LINKING_ONLY) && !defined(XXHASH_H_STATIC_13879238742)
1638#define XXHASH_H_STATIC_13879238742
1639/* ****************************************************************************
1640 * This section contains declarations which are not guaranteed to remain stable.
1641 * They may change in future versions, becoming incompatible with a different
1642 * version of the library.
1643 * These declarations should only be used with static linking.
1644 * Never use them in association with dynamic linking!
1645 ***************************************************************************** */
1646
1647/*
1648 * These definitions are only present to allow static allocation
1649 * of XXH states, on stack or in a struct, for example.
1650 * Never **ever** access their members directly.
1651 */
1652
1665struct XXH32_state_s {
1666 XXH32_hash_t total_len_32;
1667 XXH32_hash_t large_len;
1668 XXH32_hash_t acc[4];
1669 unsigned char buffer[16];
1670 XXH32_hash_t bufferedSize;
1671 XXH32_hash_t reserved;
1672}; /* typedef'd to XXH32_state_t */
1673
1674
1675#ifndef XXH_NO_LONG_LONG /* defined when there is no 64-bit support */
1676
1689struct XXH64_state_s {
1691 XXH64_hash_t acc[4];
1692 unsigned char buffer[32];
1693 XXH32_hash_t bufferedSize;
1694 XXH32_hash_t reserved32;
1695 XXH64_hash_t reserved64;
1696}; /* typedef'd to XXH64_state_t */
1697
1698#ifndef XXH_NO_XXH3
1699
1700#if defined(__cplusplus) && (__cplusplus >= 201103L) /* >= C++11 */
1701/* In C++ alignas() is a keyword */
1702# define XXH_ALIGN(n) alignas(n)
1703#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* > C11 */
1704# define XXH_ALIGN(n) _Alignas(n)
1705#elif defined(__GNUC__)
1706# define XXH_ALIGN(n) __attribute__ ((aligned(n)))
1707#elif defined(_MSC_VER)
1708# define XXH_ALIGN(n) __declspec(align(n))
1709#else
1710# define XXH_ALIGN(n) /* disabled */
1711#endif
1712
1713/* Old GCC versions only accept the attribute after the type in structures. */
1714#if !(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) /* C11+ */ \
1715 && ! (defined(__cplusplus) && (__cplusplus >= 201103L)) /* >= C++11 */ \
1716 && defined(__GNUC__)
1717# define XXH_ALIGN_MEMBER(align, type) type XXH_ALIGN(align)
1718#else
1719# define XXH_ALIGN_MEMBER(align, type) XXH_ALIGN(align) type
1720#endif
1721
1730#define XXH3_INTERNALBUFFER_SIZE 256
1731
1741#define XXH3_SECRET_DEFAULT_SIZE 192
1742
1765struct XXH3_state_s {
1766 XXH_ALIGN_MEMBER(64, XXH64_hash_t acc[8]);
1768 XXH_ALIGN_MEMBER(64, unsigned char customSecret[XXH3_SECRET_DEFAULT_SIZE]);
1770 XXH_ALIGN_MEMBER(64, unsigned char buffer[XXH3_INTERNALBUFFER_SIZE]);
1772 XXH32_hash_t bufferedSize;
1774 XXH32_hash_t useSeed;
1776 size_t nbStripesSoFar;
1778 XXH64_hash_t totalLen;
1780 size_t nbStripesPerBlock;
1782 size_t secretLimit;
1784 XXH64_hash_t seed;
1786 XXH64_hash_t reserved64;
1788 const unsigned char* extSecret;
1791 /* note: there may be some padding at the end due to alignment on 64 bytes */
1792}; /* typedef'd to XXH3_state_t */
1793
1794#undef XXH_ALIGN_MEMBER
1795
1807#define XXH3_INITSTATE(XXH3_state_ptr) \
1808 do { \
1809 XXH3_state_t* tmp_xxh3_state_ptr = (XXH3_state_ptr); \
1810 tmp_xxh3_state_ptr->seed = 0; \
1811 tmp_xxh3_state_ptr->extSecret = NULL; \
1812 } while(0)
1813
1814
1831XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH128(XXH_NOESCAPE const void* data, size_t len, XXH64_hash_t seed);
1832
1833
1834/* === Experimental API === */
1835/* Symbols defined below must be considered tied to a specific library version. */
1836
1895XXH_PUBLIC_API XXH_errorcode XXH3_generateSecret(XXH_NOESCAPE void* secretBuffer, size_t secretSize, XXH_NOESCAPE const void* customSeed, size_t customSeedSize);
1896
1935XXH_PUBLIC_API void XXH3_generateSecret_fromSeed(XXH_NOESCAPE void* secretBuffer, XXH64_hash_t seed);
1936
1940#define XXH3_MIDSIZE_MAX 240
1941
1977XXH3_64bits_withSecretandSeed(XXH_NOESCAPE const void* data, size_t len,
1978 XXH_NOESCAPE const void* secret, size_t secretSize,
1979 XXH64_hash_t seed);
1980
1996XXH3_128bits_withSecretandSeed(XXH_NOESCAPE const void* input, size_t length,
1997 XXH_NOESCAPE const void* secret, size_t secretSize,
1998 XXH64_hash_t seed64);
1999
2000#ifndef XXH_NO_STREAM
2015XXH3_64bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr,
2016 XXH_NOESCAPE const void* secret, size_t secretSize,
2017 XXH64_hash_t seed64);
2018
2041XXH3_128bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr,
2042 XXH_NOESCAPE const void* secret, size_t secretSize,
2043 XXH64_hash_t seed64);
2044
2045#endif /* !XXH_NO_STREAM */
2046
2047#endif /* !XXH_NO_XXH3 */
2048#endif /* XXH_NO_LONG_LONG */
2049#if defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API)
2050# define XXH_IMPLEMENTATION
2051#endif
2052
2053#endif /* defined(XXH_STATIC_LINKING_ONLY) && !defined(XXHASH_H_STATIC_13879238742) */
2054
2055
2056/* ======================================================================== */
2057/* ======================================================================== */
2058/* ======================================================================== */
2059
2060
2061/*-**********************************************************************
2062 * xxHash implementation
2063 *-**********************************************************************
2064 * xxHash's implementation used to be hosted inside xxhash.c.
2065 *
2066 * However, inlining requires implementation to be visible to the compiler,
2067 * hence be included alongside the header.
2068 * Previously, implementation was hosted inside xxhash.c,
2069 * which was then #included when inlining was activated.
2070 * This construction created issues with a few build and install systems,
2071 * as it required xxhash.c to be stored in /include directory.
2072 *
2073 * xxHash implementation is now directly integrated within xxhash.h.
2074 * As a consequence, xxhash.c is no longer needed in /include.
2075 *
2076 * xxhash.c is still available and is still useful.
2077 * In a "normal" setup, when xxhash is not inlined,
2078 * xxhash.h only exposes the prototypes and public symbols,
2079 * while xxhash.c can be built into an object file xxhash.o
2080 * which can then be linked into the final binary.
2081 ************************************************************************/
2082
2083#if ( defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API) \
2084 || defined(XXH_IMPLEMENTATION) ) && !defined(XXH_IMPLEM_13a8737387)
2085# define XXH_IMPLEM_13a8737387
2086
2087/* *************************************
2088* Tuning parameters
2089***************************************/
2090
2097#ifdef XXH_DOXYGEN
2103# define XXH_NO_LONG_LONG
2104# undef XXH_NO_LONG_LONG /* don't actually */
2155# define XXH_FORCE_MEMORY_ACCESS 0
2156
2183# define XXH_SIZE_OPT 0
2184
2213# define XXH_FORCE_ALIGN_CHECK 0
2214
2235# define XXH_NO_INLINE_HINTS 0
2236
2252# define XXH3_INLINE_SECRET 0
2253
2264# define XXH32_ENDJMP 0
2265
2273# define XXH_OLD_NAMES
2274# undef XXH_OLD_NAMES /* don't actually use, it is ugly. */
2275
2284# define XXH_NO_STREAM
2285# undef XXH_NO_STREAM /* don't actually */
2286#endif /* XXH_DOXYGEN */
2291#ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */
2292 /* prefer __packed__ structures (method 1) for GCC
2293 * < ARMv7 with unaligned access (e.g. Raspbian armhf) still uses byte shifting, so we use memcpy
2294 * which for some reason does unaligned loads. */
2295# if defined(__GNUC__) && !(defined(__ARM_ARCH) && __ARM_ARCH < 7 && defined(__ARM_FEATURE_UNALIGNED))
2296# define XXH_FORCE_MEMORY_ACCESS 1
2297# endif
2298#endif
2299
2300#ifndef XXH_SIZE_OPT
2301 /* default to 1 for -Os or -Oz */
2302# if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE_SIZE__)
2303# define XXH_SIZE_OPT 1
2304# else
2305# define XXH_SIZE_OPT 0
2306# endif
2307#endif
2308
2309#ifndef XXH_FORCE_ALIGN_CHECK /* can be defined externally */
2310 /* don't check on sizeopt, x86, aarch64, or arm when unaligned access is available */
2311# if XXH_SIZE_OPT >= 1 || \
2312 defined(__i386) || defined(__x86_64__) || defined(__aarch64__) || defined(__ARM_FEATURE_UNALIGNED) \
2313 || defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM64) || defined(_M_ARM) /* visual */
2314# define XXH_FORCE_ALIGN_CHECK 0
2315# else
2316# define XXH_FORCE_ALIGN_CHECK 1
2317# endif
2318#endif
2319
2320#ifndef XXH_NO_INLINE_HINTS
2321# if XXH_SIZE_OPT >= 1 || defined(__NO_INLINE__) /* -O0, -fno-inline */
2322# define XXH_NO_INLINE_HINTS 1
2323# else
2324# define XXH_NO_INLINE_HINTS 0
2325# endif
2326#endif
2327
2328#ifndef XXH3_INLINE_SECRET
2329# if (defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 12) \
2330 || !defined(XXH_INLINE_ALL)
2331# define XXH3_INLINE_SECRET 0
2332# else
2333# define XXH3_INLINE_SECRET 1
2334# endif
2335#endif
2336
2337#ifndef XXH32_ENDJMP
2338/* generally preferable for performance */
2339# define XXH32_ENDJMP 0
2340#endif
2341
2348/* *************************************
2349* Includes & Memory related functions
2350***************************************/
2351#if defined(XXH_NO_STREAM)
2352/* nothing */
2353#elif defined(XXH_NO_STDLIB)
2354
2355/* When requesting to disable any mention of stdlib,
2356 * the library loses the ability to invoked malloc / free.
2357 * In practice, it means that functions like `XXH*_createState()`
2358 * will always fail, and return NULL.
2359 * This flag is useful in situations where
2360 * xxhash.h is integrated into some kernel, embedded or limited environment
2361 * without access to dynamic allocation.
2362 */
2363
2364static XXH_CONSTF void* XXH_malloc(size_t s) { (void)s; return NULL; }
2365static void XXH_free(void* p) { (void)p; }
2366
2367#else
2368
2369/*
2370 * Modify the local functions below should you wish to use
2371 * different memory routines for malloc() and free()
2372 */
2373#include <stdlib.h>
2374
2379static XXH_MALLOCF void* XXH_malloc(size_t s) { return malloc(s); }
2380
2385static void XXH_free(void* p) { free(p); }
2386
2387#endif /* XXH_NO_STDLIB */
2388
2389#ifndef XXH_memcpy
2394# include <string.h>
2395# define XXH_memcpy memcpy
2396#endif
2397
2398#ifndef XXH_memset
2403# include <string.h>
2404# define XXH_memset memset
2405#endif
2406
2407#ifndef XXH_memcmp
2413# include <string.h>
2414# define XXH_memcmp memcmp
2415#endif
2416
2417
2418
2419#include <limits.h> /* ULLONG_MAX */
2420
2421
2422/* *************************************
2423* Compiler Specific Options
2424***************************************/
2425#ifdef _MSC_VER /* Visual Studio warning fix */
2426# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
2427#endif
2428
2429#if XXH_NO_INLINE_HINTS /* disable inlining hints */
2430# if defined(__GNUC__) || defined(__clang__)
2431# define XXH_FORCE_INLINE static __attribute__((__unused__))
2432# else
2433# define XXH_FORCE_INLINE static
2434# endif
2435# define XXH_NO_INLINE static
2436/* enable inlining hints */
2437#elif defined(__GNUC__) || defined(__clang__)
2438# define XXH_FORCE_INLINE static __inline__ __attribute__((__always_inline__, __unused__))
2439# define XXH_NO_INLINE static __attribute__((__noinline__))
2440#elif defined(_MSC_VER) /* Visual Studio */
2441# define XXH_FORCE_INLINE static __forceinline
2442# define XXH_NO_INLINE static __declspec(noinline)
2443#elif defined (__cplusplus) \
2444 || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) /* C99 */
2445# define XXH_FORCE_INLINE static inline
2446# define XXH_NO_INLINE static
2447#else
2448# define XXH_FORCE_INLINE static
2449# define XXH_NO_INLINE static
2450#endif
2451
2452#if defined(XXH_INLINE_ALL)
2453# define XXH_STATIC XXH_FORCE_INLINE
2454#else
2455# define XXH_STATIC static
2456#endif
2457
2458#if XXH3_INLINE_SECRET
2459# define XXH3_WITH_SECRET_INLINE XXH_FORCE_INLINE
2460#else
2461# define XXH3_WITH_SECRET_INLINE XXH_NO_INLINE
2462#endif
2463
2464/* Solaris includes __STDC_VERSION__ with C++. Tested with GCC 5.5 */
2465#if ((defined(sun) || defined(__sun)) && defined(__cplusplus))
2466# define XXH_RESTRICT /* disable */
2467#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* >= C99 */
2468# define XXH_RESTRICT restrict
2469#elif (defined (__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))) \
2470 || (defined (__clang__)) \
2471 || (defined (_MSC_VER) && (_MSC_VER >= 1400)) \
2472 || (defined (__INTEL_COMPILER) && (__INTEL_COMPILER >= 1300))
2473/*
2474 * There are a LOT more compilers that recognize __restrict but this
2475 * covers the major ones.
2476 */
2477# define XXH_RESTRICT __restrict
2478#else
2479# define XXH_RESTRICT /* disable */
2480#endif
2481
2482/* *************************************
2483* Debug
2484***************************************/
2493#ifndef XXH_DEBUGLEVEL
2494# ifdef DEBUGLEVEL /* backwards compat */
2495# define XXH_DEBUGLEVEL DEBUGLEVEL
2496# else
2497# define XXH_DEBUGLEVEL 0
2498# endif
2499#endif
2500
2501#if (XXH_DEBUGLEVEL>=1)
2502# include <assert.h> /* note: can still be disabled with NDEBUG */
2503# define XXH_ASSERT(c) assert(c)
2504#else
2505# if defined(__INTEL_COMPILER)
2506# define XXH_ASSERT(c) XXH_ASSUME((unsigned char) (c))
2507# else
2508# define XXH_ASSERT(c) XXH_ASSUME(c)
2509# endif
2510#endif
2511
2512/* note: use after variable declarations */
2513#ifndef XXH_STATIC_ASSERT
2514# if defined(__cplusplus) && (__cplusplus >= 201103L) /* C++11 */
2515# define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { static_assert((c),m); } while(0)
2516# elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */
2517# define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { _Static_assert((c),m); } while(0)
2518# else
2519# define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { struct xxh_sa { char x[(c) ? 1 : -1]; }; } while(0)
2520# endif
2521# define XXH_STATIC_ASSERT(c) XXH_STATIC_ASSERT_WITH_MESSAGE((c),#c)
2522#endif
2523
2540#if defined(__GNUC__) || defined(__clang__)
2541# define XXH_COMPILER_GUARD(var) __asm__("" : "+r" (var))
2542#else
2543# define XXH_COMPILER_GUARD(var) ((void)0)
2544#endif
2545
2546/* Specifically for NEON vectors which use the "w" constraint, on
2547 * Clang. */
2548#if defined(__clang__) && defined(__ARM_ARCH) && !defined(__wasm__)
2549# define XXH_COMPILER_GUARD_CLANG_NEON(var) __asm__("" : "+w" (var))
2550#else
2551# define XXH_COMPILER_GUARD_CLANG_NEON(var) ((void)0)
2552#endif
2553
2554/* *************************************
2555* Basic Types
2556***************************************/
2557#if !defined (__VMS) \
2558 && (defined (__cplusplus) \
2559 || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
2560# ifdef _AIX
2561# include <inttypes.h>
2562# else
2563# include <stdint.h>
2564# endif
2565 typedef uint8_t xxh_u8;
2566#else
2567 typedef unsigned char xxh_u8;
2568#endif
2569typedef XXH32_hash_t xxh_u32;
2570
2571#ifdef XXH_OLD_NAMES
2572# warning "XXH_OLD_NAMES is planned to be removed starting v0.9. If the program depends on it, consider moving away from it by employing newer type names directly"
2573# define BYTE xxh_u8
2574# define U8 xxh_u8
2575# define U32 xxh_u32
2576#endif
2577
2578/* *** Memory access *** */
2579
2630#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3))
2631/*
2632 * Manual byteshift. Best for old compilers which don't inline memcpy.
2633 * We actually directly use XXH_readLE32 and XXH_readBE32.
2634 */
2635#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2))
2636
2637/*
2638 * Force direct memory access. Only works on CPU which support unaligned memory
2639 * access in hardware.
2640 */
2641static xxh_u32 XXH_read32(const void* memPtr) { return *(const xxh_u32*) memPtr; }
2642
2643#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1))
2644
2645/*
2646 * __attribute__((aligned(1))) is supported by gcc and clang. Originally the
2647 * documentation claimed that it only increased the alignment, but actually it
2648 * can decrease it on gcc, clang, and icc:
2649 * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69502,
2650 * https://gcc.godbolt.org/z/xYez1j67Y.
2651 */
2652#ifdef XXH_OLD_NAMES
2653typedef union { xxh_u32 u32; } __attribute__((__packed__)) unalign;
2654#endif
2655static xxh_u32 XXH_read32(const void* ptr)
2656{
2657 typedef __attribute__((__aligned__(1))) __attribute__((__may_alias__)) xxh_u32 xxh_unalign32;
2658 return *((const xxh_unalign32*)ptr);
2659}
2660
2661#else
2662
2663/*
2664 * Portable and safe solution. Generally efficient.
2665 * see: https://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html
2666 */
2667static xxh_u32 XXH_read32(const void* memPtr)
2668{
2669 xxh_u32 val;
2670 XXH_memcpy(&val, memPtr, sizeof(val));
2671 return val;
2672}
2673
2674#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */
2675
2676
2677/* *** Endianness *** */
2678
2695#ifndef XXH_CPU_LITTLE_ENDIAN
2696/*
2697 * Try to detect endianness automatically, to avoid the nonstandard behavior
2698 * in `XXH_isLittleEndian()`
2699 */
2700# if defined(_WIN32) /* Windows is always little endian */ \
2701 || defined(__LITTLE_ENDIAN__) \
2702 || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
2703# define XXH_CPU_LITTLE_ENDIAN 1
2704# elif defined(__BIG_ENDIAN__) \
2705 || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
2706# define XXH_CPU_LITTLE_ENDIAN 0
2707# else
2714static int XXH_isLittleEndian(void)
2715{
2716 /*
2717 * Portable and well-defined behavior.
2718 * Don't use static: it is detrimental to performance.
2719 */
2720 const union { xxh_u32 u; xxh_u8 c[4]; } one = { 1 };
2721 return one.c[0];
2722}
2723# define XXH_CPU_LITTLE_ENDIAN XXH_isLittleEndian()
2724# endif
2725#endif
2726
2727
2728
2729
2730/* ****************************************
2731* Compiler-specific Functions and Macros
2732******************************************/
2733#define XXH_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
2734
2735#ifdef __has_builtin
2736# define XXH_HAS_BUILTIN(x) __has_builtin(x)
2737#else
2738# define XXH_HAS_BUILTIN(x) 0
2739#endif
2740
2741
2742
2743/*
2744 * C23 and future versions have standard "unreachable()".
2745 * Once it has been implemented reliably we can add it as an
2746 * additional case:
2747 *
2748 * ```
2749 * #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 202311L)
2750 * # include <stddef.h>
2751 * # ifdef unreachable
2752 * # define XXH_UNREACHABLE() unreachable()
2753 * # endif
2754 * #endif
2755 * ```
2756 *
2757 * Note C++23 also has std::unreachable() which can be detected
2758 * as follows:
2759 * ```
2760 * #if defined(__cpp_lib_unreachable) && (__cpp_lib_unreachable >= 202202L)
2761 * # include <utility>
2762 * # define XXH_UNREACHABLE() std::unreachable()
2763 * #endif
2764 * ```
2765 * NB: `__cpp_lib_unreachable` is defined in the `<version>` header.
2766 * We don't use that as including `<utility>` in `extern "C"` blocks
2767 * doesn't work on GCC12
2768 */
2769
2770#if XXH_HAS_BUILTIN(__builtin_unreachable)
2771# define XXH_UNREACHABLE() __builtin_unreachable()
2772
2773#elif defined(_MSC_VER)
2774# define XXH_UNREACHABLE() __assume(0)
2775
2776#else
2777# define XXH_UNREACHABLE()
2778#endif
2779
2780#if XXH_HAS_BUILTIN(__builtin_assume)
2781# define XXH_ASSUME(c) __builtin_assume(c)
2782#else
2783# define XXH_ASSUME(c) if (!(c)) { XXH_UNREACHABLE(); }
2784#endif
2785
2799#if !defined(NO_CLANG_BUILTIN) && XXH_HAS_BUILTIN(__builtin_rotateleft32) \
2800 && XXH_HAS_BUILTIN(__builtin_rotateleft64)
2801# define XXH_rotl32 __builtin_rotateleft32
2802# define XXH_rotl64 __builtin_rotateleft64
2803#elif XXH_HAS_BUILTIN(__builtin_stdc_rotate_left)
2804# define XXH_rotl32 __builtin_stdc_rotate_left
2805# define XXH_rotl64 __builtin_stdc_rotate_left
2806/* Note: although _rotl exists for minGW (GCC under windows), performance seems poor */
2807#elif defined(_MSC_VER)
2808# define XXH_rotl32(x,r) _rotl(x,r)
2809# define XXH_rotl64(x,r) _rotl64(x,r)
2810#else
2811# define XXH_rotl32(x,r) (((x) << (r)) | ((x) >> (32 - (r))))
2812# define XXH_rotl64(x,r) (((x) << (r)) | ((x) >> (64 - (r))))
2813#endif
2814
2823#if defined(_MSC_VER) /* Visual Studio */
2824# define XXH_swap32 _byteswap_ulong
2825#elif XXH_GCC_VERSION >= 403
2826# define XXH_swap32 __builtin_bswap32
2827#else
2828static xxh_u32 XXH_swap32 (xxh_u32 x)
2829{
2830 return ((x << 24) & 0xff000000 ) |
2831 ((x << 8) & 0x00ff0000 ) |
2832 ((x >> 8) & 0x0000ff00 ) |
2833 ((x >> 24) & 0x000000ff );
2834}
2835#endif
2836
2837
2838/* ***************************
2839* Memory reads
2840*****************************/
2841
2846typedef enum {
2847 XXH_aligned,
2848 XXH_unaligned
2849} XXH_alignment;
2850
2851/*
2852 * XXH_FORCE_MEMORY_ACCESS==3 is an endian-independent byteshift load.
2853 *
2854 * This is ideal for older compilers which don't inline memcpy.
2855 */
2856#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3))
2857
2858XXH_FORCE_INLINE xxh_u32 XXH_readLE32(const void* memPtr)
2859{
2860 const xxh_u8* bytePtr = (const xxh_u8 *)memPtr;
2861 return bytePtr[0]
2862 | ((xxh_u32)bytePtr[1] << 8)
2863 | ((xxh_u32)bytePtr[2] << 16)
2864 | ((xxh_u32)bytePtr[3] << 24);
2865}
2866
2867XXH_FORCE_INLINE xxh_u32 XXH_readBE32(const void* memPtr)
2868{
2869 const xxh_u8* bytePtr = (const xxh_u8 *)memPtr;
2870 return bytePtr[3]
2871 | ((xxh_u32)bytePtr[2] << 8)
2872 | ((xxh_u32)bytePtr[1] << 16)
2873 | ((xxh_u32)bytePtr[0] << 24);
2874}
2875
2876#else
2877XXH_FORCE_INLINE xxh_u32 XXH_readLE32(const void* ptr)
2878{
2879 return XXH_CPU_LITTLE_ENDIAN ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr));
2880}
2881
2882static xxh_u32 XXH_readBE32(const void* ptr)
2883{
2884 return XXH_CPU_LITTLE_ENDIAN ? XXH_swap32(XXH_read32(ptr)) : XXH_read32(ptr);
2885}
2886#endif
2887
2888XXH_FORCE_INLINE xxh_u32
2889XXH_readLE32_align(const void* ptr, XXH_alignment align)
2890{
2891 if (align==XXH_unaligned) {
2892 return XXH_readLE32(ptr);
2893 } else {
2894 return XXH_CPU_LITTLE_ENDIAN ? *(const xxh_u32*)ptr : XXH_swap32(*(const xxh_u32*)ptr);
2895 }
2896}
2897
2898
2899/* *************************************
2900* Misc
2901***************************************/
2903XXH_PUBLIC_API unsigned XXH_versionNumber (void) { return XXH_VERSION_NUMBER; }
2904
2905
2906/* *******************************************************************
2907* 32-bit hash functions
2908*********************************************************************/
2917 /* #define instead of static const, to be used as initializers */
2918#define XXH_PRIME32_1 0x9E3779B1U
2919#define XXH_PRIME32_2 0x85EBCA77U
2920#define XXH_PRIME32_3 0xC2B2AE3DU
2921#define XXH_PRIME32_4 0x27D4EB2FU
2922#define XXH_PRIME32_5 0x165667B1U
2924#ifdef XXH_OLD_NAMES
2925# define PRIME32_1 XXH_PRIME32_1
2926# define PRIME32_2 XXH_PRIME32_2
2927# define PRIME32_3 XXH_PRIME32_3
2928# define PRIME32_4 XXH_PRIME32_4
2929# define PRIME32_5 XXH_PRIME32_5
2930#endif
2931
2943static xxh_u32 XXH32_round(xxh_u32 acc, xxh_u32 input)
2944{
2945 acc += input * XXH_PRIME32_2;
2946 acc = XXH_rotl32(acc, 13);
2947 acc *= XXH_PRIME32_1;
2948#if (defined(__SSE4_1__) || defined(__aarch64__) || defined(__wasm_simd128__)) && !defined(XXH_ENABLE_AUTOVECTORIZE)
2949 /*
2950 * UGLY HACK:
2951 * A compiler fence is used to prevent GCC and Clang from
2952 * autovectorizing the XXH32 loop (pragmas and attributes don't work for some
2953 * reason) without globally disabling SSE4.1.
2954 *
2955 * The reason we want to avoid vectorization is because despite working on
2956 * 4 integers at a time, there are multiple factors slowing XXH32 down on
2957 * SSE4:
2958 * - There's a ridiculous amount of lag from pmulld (10 cycles of latency on
2959 * newer chips!) making it slightly slower to multiply four integers at
2960 * once compared to four integers independently. Even when pmulld was
2961 * fastest, Sandy/Ivy Bridge, it is still not worth it to go into SSE
2962 * just to multiply unless doing a long operation.
2963 *
2964 * - Four instructions are required to rotate,
2965 * movqda tmp, v // not required with VEX encoding
2966 * pslld tmp, 13 // tmp <<= 13
2967 * psrld v, 19 // x >>= 19
2968 * por v, tmp // x |= tmp
2969 * compared to one for scalar:
2970 * roll v, 13 // reliably fast across the board
2971 * shldl v, v, 13 // Sandy Bridge and later prefer this for some reason
2972 *
2973 * - Instruction level parallelism is actually more beneficial here because
2974 * the SIMD actually serializes this operation: While v1 is rotating, v2
2975 * can load data, while v3 can multiply. SSE forces them to operate
2976 * together.
2977 *
2978 * This is also enabled on AArch64, as Clang is *very aggressive* in vectorizing
2979 * the loop. NEON is only faster on the A53, and with the newer cores, it is less
2980 * than half the speed.
2981 *
2982 * Additionally, this is used on WASM SIMD128 because it JITs to the same
2983 * SIMD instructions and has the same issue.
2984 */
2985 XXH_COMPILER_GUARD(acc);
2986#endif
2987 return acc;
2988}
2989
3000static xxh_u32 XXH32_avalanche(xxh_u32 hash)
3001{
3002 hash ^= hash >> 15;
3003 hash *= XXH_PRIME32_2;
3004 hash ^= hash >> 13;
3005 hash *= XXH_PRIME32_3;
3006 hash ^= hash >> 16;
3007 return hash;
3008}
3009
3010#define XXH_get32bits(p) XXH_readLE32_align(p, align)
3011
3016XXH_FORCE_INLINE void
3017XXH32_initAccs(xxh_u32 *acc, xxh_u32 seed)
3018{
3019 XXH_ASSERT(acc != NULL);
3020 acc[0] = seed + XXH_PRIME32_1 + XXH_PRIME32_2;
3021 acc[1] = seed + XXH_PRIME32_2;
3022 acc[2] = seed + 0;
3023 acc[3] = seed - XXH_PRIME32_1;
3024}
3025
3032XXH_FORCE_INLINE const xxh_u8 *
3033XXH32_consumeLong(
3034 xxh_u32 *XXH_RESTRICT acc,
3035 xxh_u8 const *XXH_RESTRICT input,
3036 size_t len,
3037 XXH_alignment align
3038)
3039{
3040 const xxh_u8* const bEnd = input + len;
3041 const xxh_u8* const limit = bEnd - 15;
3042 XXH_ASSERT(acc != NULL);
3043 XXH_ASSERT(input != NULL);
3044 XXH_ASSERT(len >= 16);
3045 do {
3046 acc[0] = XXH32_round(acc[0], XXH_get32bits(input)); input += 4;
3047 acc[1] = XXH32_round(acc[1], XXH_get32bits(input)); input += 4;
3048 acc[2] = XXH32_round(acc[2], XXH_get32bits(input)); input += 4;
3049 acc[3] = XXH32_round(acc[3], XXH_get32bits(input)); input += 4;
3050 } while (input < limit);
3051
3052 return input;
3053}
3054
3059XXH_FORCE_INLINE XXH_PUREF xxh_u32
3060XXH32_mergeAccs(const xxh_u32 *acc)
3061{
3062 XXH_ASSERT(acc != NULL);
3063 return XXH_rotl32(acc[0], 1) + XXH_rotl32(acc[1], 7)
3064 + XXH_rotl32(acc[2], 12) + XXH_rotl32(acc[3], 18);
3065}
3066
3082static XXH_PUREF xxh_u32
3083XXH32_finalize(xxh_u32 hash, const xxh_u8* ptr, size_t len, XXH_alignment align)
3084{
3085#define XXH_PROCESS1 do { \
3086 hash += (*ptr++) * XXH_PRIME32_5; \
3087 hash = XXH_rotl32(hash, 11) * XXH_PRIME32_1; \
3088} while (0)
3089
3090#define XXH_PROCESS4 do { \
3091 hash += XXH_get32bits(ptr) * XXH_PRIME32_3; \
3092 ptr += 4; \
3093 hash = XXH_rotl32(hash, 17) * XXH_PRIME32_4; \
3094} while (0)
3095
3096 if (ptr==NULL) XXH_ASSERT(len == 0);
3097
3098 /* Compact rerolled version; generally faster */
3099 if (!XXH32_ENDJMP) {
3100 len &= 15;
3101 while (len >= 4) {
3102 XXH_PROCESS4;
3103 len -= 4;
3104 }
3105 while (len > 0) {
3106 XXH_PROCESS1;
3107 --len;
3108 }
3109 return XXH32_avalanche(hash);
3110 } else {
3111 switch(len&15) /* or switch(bEnd - p) */ {
3112 case 12: XXH_PROCESS4;
3113 XXH_FALLTHROUGH; /* fallthrough */
3114 case 8: XXH_PROCESS4;
3115 XXH_FALLTHROUGH; /* fallthrough */
3116 case 4: XXH_PROCESS4;
3117 return XXH32_avalanche(hash);
3118
3119 case 13: XXH_PROCESS4;
3120 XXH_FALLTHROUGH; /* fallthrough */
3121 case 9: XXH_PROCESS4;
3122 XXH_FALLTHROUGH; /* fallthrough */
3123 case 5: XXH_PROCESS4;
3124 XXH_PROCESS1;
3125 return XXH32_avalanche(hash);
3126
3127 case 14: XXH_PROCESS4;
3128 XXH_FALLTHROUGH; /* fallthrough */
3129 case 10: XXH_PROCESS4;
3130 XXH_FALLTHROUGH; /* fallthrough */
3131 case 6: XXH_PROCESS4;
3132 XXH_PROCESS1;
3133 XXH_PROCESS1;
3134 return XXH32_avalanche(hash);
3135
3136 case 15: XXH_PROCESS4;
3137 XXH_FALLTHROUGH; /* fallthrough */
3138 case 11: XXH_PROCESS4;
3139 XXH_FALLTHROUGH; /* fallthrough */
3140 case 7: XXH_PROCESS4;
3141 XXH_FALLTHROUGH; /* fallthrough */
3142 case 3: XXH_PROCESS1;
3143 XXH_FALLTHROUGH; /* fallthrough */
3144 case 2: XXH_PROCESS1;
3145 XXH_FALLTHROUGH; /* fallthrough */
3146 case 1: XXH_PROCESS1;
3147 XXH_FALLTHROUGH; /* fallthrough */
3148 case 0: return XXH32_avalanche(hash);
3149 }
3150 XXH_ASSERT(0);
3151 return hash; /* reaching this point is deemed impossible */
3152 }
3153}
3154
3155#ifdef XXH_OLD_NAMES
3156# define PROCESS1 XXH_PROCESS1
3157# define PROCESS4 XXH_PROCESS4
3158#else
3159# undef XXH_PROCESS1
3160# undef XXH_PROCESS4
3161#endif
3162
3171XXH_FORCE_INLINE XXH_PUREF xxh_u32
3172XXH32_endian_align(const xxh_u8* input, size_t len, xxh_u32 seed, XXH_alignment align)
3173{
3174 xxh_u32 h32;
3175
3176 if (input==NULL) XXH_ASSERT(len == 0);
3177
3178 if (len>=16) {
3179 xxh_u32 acc[4];
3180 XXH32_initAccs(acc, seed);
3181
3182 input = XXH32_consumeLong(acc, input, len, align);
3183
3184 h32 = XXH32_mergeAccs(acc);
3185 } else {
3186 h32 = seed + XXH_PRIME32_5;
3187 }
3188
3189 h32 += (xxh_u32)len;
3190
3191 return XXH32_finalize(h32, input, len&15, align);
3192}
3193
3195XXH_PUBLIC_API XXH32_hash_t XXH32 (const void* input, size_t len, XXH32_hash_t seed)
3196{
3197#if !defined(XXH_NO_STREAM) && XXH_SIZE_OPT >= 2
3198 /* Simple version, good for code maintenance, but unfortunately slow for small inputs */
3199 XXH32_state_t state;
3200 XXH32_reset(&state, seed);
3201 XXH32_update(&state, (const xxh_u8*)input, len);
3202 return XXH32_digest(&state);
3203#else
3204 if (XXH_FORCE_ALIGN_CHECK) {
3205 if ((((size_t)input) & 3) == 0) { /* Input is 4-bytes aligned, leverage the speed benefit */
3206 return XXH32_endian_align((const xxh_u8*)input, len, seed, XXH_aligned);
3207 } }
3208
3209 return XXH32_endian_align((const xxh_u8*)input, len, seed, XXH_unaligned);
3210#endif
3211}
3212
3213
3214
3215/******* Hash streaming *******/
3216#ifndef XXH_NO_STREAM
3219{
3220 return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t));
3221}
3224{
3225 XXH_free(statePtr);
3226 return XXH_OK;
3227}
3228
3230XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dstState, const XXH32_state_t* srcState)
3231{
3232 XXH_memcpy(dstState, srcState, sizeof(*dstState));
3233}
3234
3236XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, XXH32_hash_t seed)
3237{
3238 XXH_ASSERT(statePtr != NULL);
3239 XXH_memset(statePtr, 0, sizeof(*statePtr));
3240 XXH32_initAccs(statePtr->acc, seed);
3241 return XXH_OK;
3242}
3243
3244
3247XXH32_update(XXH32_state_t* state, const void* input, size_t len)
3248{
3249 if (input==NULL) {
3250 XXH_ASSERT(len == 0);
3251 return XXH_OK;
3252 }
3253
3254 state->total_len_32 += (XXH32_hash_t)len;
3255 state->large_len |= (XXH32_hash_t)((len>=16) | (state->total_len_32>=16));
3256
3257 XXH_ASSERT(state->bufferedSize < sizeof(state->buffer));
3258 if (len < sizeof(state->buffer) - state->bufferedSize) { /* fill in tmp buffer */
3259 XXH_memcpy(state->buffer + state->bufferedSize, input, len);
3260 state->bufferedSize += (XXH32_hash_t)len;
3261 return XXH_OK;
3262 }
3263
3264 { const xxh_u8* xinput = (const xxh_u8*)input;
3265 const xxh_u8* const bEnd = xinput + len;
3266
3267 if (state->bufferedSize) { /* non-empty buffer: complete first */
3268 XXH_memcpy(state->buffer + state->bufferedSize, xinput, sizeof(state->buffer) - state->bufferedSize);
3269 xinput += sizeof(state->buffer) - state->bufferedSize;
3270 /* then process one round */
3271 (void)XXH32_consumeLong(state->acc, state->buffer, sizeof(state->buffer), XXH_aligned);
3272 state->bufferedSize = 0;
3273 }
3274
3275 XXH_ASSERT(xinput <= bEnd);
3276 if ((size_t)(bEnd - xinput) >= sizeof(state->buffer)) {
3277 /* Process the remaining data */
3278 xinput = XXH32_consumeLong(state->acc, xinput, (size_t)(bEnd - xinput), XXH_unaligned);
3279 }
3280
3281 if (xinput < bEnd) {
3282 /* Copy the leftover to the tmp buffer */
3283 XXH_memcpy(state->buffer, xinput, (size_t)(bEnd-xinput));
3284 state->bufferedSize = (unsigned)(bEnd-xinput);
3285 }
3286 }
3287
3288 return XXH_OK;
3289}
3290
3291
3293XXH_PUBLIC_API XXH32_hash_t XXH32_digest(const XXH32_state_t* state)
3294{
3295 xxh_u32 h32;
3296
3297 if (state->large_len) {
3298 h32 = XXH32_mergeAccs(state->acc);
3299 } else {
3300 h32 = state->acc[2] /* == seed */ + XXH_PRIME32_5;
3301 }
3302
3303 h32 += state->total_len_32;
3304
3305 return XXH32_finalize(h32, state->buffer, state->bufferedSize, XXH_aligned);
3306}
3307#endif /* !XXH_NO_STREAM */
3308
3309/******* Canonical representation *******/
3310
3312XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash)
3313{
3314 XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t));
3315 if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap32(hash);
3316 XXH_memcpy(dst, &hash, sizeof(*dst));
3317}
3320{
3321 return XXH_readBE32(src);
3322}
3323
3324
3325#ifndef XXH_NO_LONG_LONG
3326
3327/* *******************************************************************
3328* 64-bit hash functions
3329*********************************************************************/
3335/******* Memory access *******/
3336
3337typedef XXH64_hash_t xxh_u64;
3338
3339#ifdef XXH_OLD_NAMES
3340# define U64 xxh_u64
3341#endif
3342
3343#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3))
3344/*
3345 * Manual byteshift. Best for old compilers which don't inline memcpy.
3346 * We actually directly use XXH_readLE64 and XXH_readBE64.
3347 */
3348#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2))
3349
3350/* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */
3351static xxh_u64 XXH_read64(const void* memPtr)
3352{
3353 return *(const xxh_u64*) memPtr;
3354}
3355
3356#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1))
3357
3358/*
3359 * __attribute__((aligned(1))) is supported by gcc and clang. Originally the
3360 * documentation claimed that it only increased the alignment, but actually it
3361 * can decrease it on gcc, clang, and icc:
3362 * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69502,
3363 * https://gcc.godbolt.org/z/xYez1j67Y.
3364 */
3365#ifdef XXH_OLD_NAMES
3366typedef union { xxh_u32 u32; xxh_u64 u64; } __attribute__((__packed__)) unalign64;
3367#endif
3368static xxh_u64 XXH_read64(const void* ptr)
3369{
3370 typedef __attribute__((__aligned__(1))) __attribute__((__may_alias__)) xxh_u64 xxh_unalign64;
3371 return *((const xxh_unalign64*)ptr);
3372}
3373
3374#else
3375
3376/*
3377 * Portable and safe solution. Generally efficient.
3378 * see: https://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html
3379 */
3380static xxh_u64 XXH_read64(const void* memPtr)
3381{
3382 xxh_u64 val;
3383 XXH_memcpy(&val, memPtr, sizeof(val));
3384 return val;
3385}
3386
3387#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */
3388
3389#if defined(_MSC_VER) /* Visual Studio */
3390# define XXH_swap64 _byteswap_uint64
3391#elif XXH_GCC_VERSION >= 403
3392# define XXH_swap64 __builtin_bswap64
3393#else
3394static xxh_u64 XXH_swap64(xxh_u64 x)
3395{
3396 return ((x << 56) & 0xff00000000000000ULL) |
3397 ((x << 40) & 0x00ff000000000000ULL) |
3398 ((x << 24) & 0x0000ff0000000000ULL) |
3399 ((x << 8) & 0x000000ff00000000ULL) |
3400 ((x >> 8) & 0x00000000ff000000ULL) |
3401 ((x >> 24) & 0x0000000000ff0000ULL) |
3402 ((x >> 40) & 0x000000000000ff00ULL) |
3403 ((x >> 56) & 0x00000000000000ffULL);
3404}
3405#endif
3406
3407
3408/* XXH_FORCE_MEMORY_ACCESS==3 is an endian-independent byteshift load. */
3409#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3))
3410
3411XXH_FORCE_INLINE xxh_u64 XXH_readLE64(const void* memPtr)
3412{
3413 const xxh_u8* bytePtr = (const xxh_u8 *)memPtr;
3414 return bytePtr[0]
3415 | ((xxh_u64)bytePtr[1] << 8)
3416 | ((xxh_u64)bytePtr[2] << 16)
3417 | ((xxh_u64)bytePtr[3] << 24)
3418 | ((xxh_u64)bytePtr[4] << 32)
3419 | ((xxh_u64)bytePtr[5] << 40)
3420 | ((xxh_u64)bytePtr[6] << 48)
3421 | ((xxh_u64)bytePtr[7] << 56);
3422}
3423
3424XXH_FORCE_INLINE xxh_u64 XXH_readBE64(const void* memPtr)
3425{
3426 const xxh_u8* bytePtr = (const xxh_u8 *)memPtr;
3427 return bytePtr[7]
3428 | ((xxh_u64)bytePtr[6] << 8)
3429 | ((xxh_u64)bytePtr[5] << 16)
3430 | ((xxh_u64)bytePtr[4] << 24)
3431 | ((xxh_u64)bytePtr[3] << 32)
3432 | ((xxh_u64)bytePtr[2] << 40)
3433 | ((xxh_u64)bytePtr[1] << 48)
3434 | ((xxh_u64)bytePtr[0] << 56);
3435}
3436
3437#else
3438XXH_FORCE_INLINE xxh_u64 XXH_readLE64(const void* ptr)
3439{
3440 return XXH_CPU_LITTLE_ENDIAN ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr));
3441}
3442
3443static xxh_u64 XXH_readBE64(const void* ptr)
3444{
3445 return XXH_CPU_LITTLE_ENDIAN ? XXH_swap64(XXH_read64(ptr)) : XXH_read64(ptr);
3446}
3447#endif
3448
3449XXH_FORCE_INLINE xxh_u64
3450XXH_readLE64_align(const void* ptr, XXH_alignment align)
3451{
3452 if (align==XXH_unaligned)
3453 return XXH_readLE64(ptr);
3454 else
3455 return XXH_CPU_LITTLE_ENDIAN ? *(const xxh_u64*)ptr : XXH_swap64(*(const xxh_u64*)ptr);
3456}
3457
3458
3459/******* xxh64 *******/
3468/* #define rather that static const, to be used as initializers */
3469#define XXH_PRIME64_1 0x9E3779B185EBCA87ULL
3470#define XXH_PRIME64_2 0xC2B2AE3D27D4EB4FULL
3471#define XXH_PRIME64_3 0x165667B19E3779F9ULL
3472#define XXH_PRIME64_4 0x85EBCA77C2B2AE63ULL
3473#define XXH_PRIME64_5 0x27D4EB2F165667C5ULL
3475#ifdef XXH_OLD_NAMES
3476# define PRIME64_1 XXH_PRIME64_1
3477# define PRIME64_2 XXH_PRIME64_2
3478# define PRIME64_3 XXH_PRIME64_3
3479# define PRIME64_4 XXH_PRIME64_4
3480# define PRIME64_5 XXH_PRIME64_5
3481#endif
3482
3484static xxh_u64 XXH64_round(xxh_u64 acc, xxh_u64 input)
3485{
3486 acc += input * XXH_PRIME64_2;
3487 acc = XXH_rotl64(acc, 31);
3488 acc *= XXH_PRIME64_1;
3489#if (defined(__AVX512F__)) && !defined(XXH_ENABLE_AUTOVECTORIZE)
3490 /*
3491 * DISABLE AUTOVECTORIZATION:
3492 * A compiler fence is used to prevent GCC and Clang from
3493 * autovectorizing the XXH64 loop (pragmas and attributes don't work for some
3494 * reason) without globally disabling AVX512.
3495 *
3496 * Autovectorization of XXH64 tends to be detrimental,
3497 * though the exact outcome may change depending on exact cpu and compiler version.
3498 * For information, it has been reported as detrimental for Skylake-X,
3499 * but possibly beneficial for Zen4.
3500 *
3501 * The default is to disable auto-vectorization,
3502 * but you can select to enable it instead using `XXH_ENABLE_AUTOVECTORIZE` build variable.
3503 */
3504 XXH_COMPILER_GUARD(acc);
3505#endif
3506 return acc;
3507}
3508
3509static xxh_u64 XXH64_mergeRound(xxh_u64 acc, xxh_u64 val)
3510{
3511 val = XXH64_round(0, val);
3512 acc ^= val;
3513 acc = acc * XXH_PRIME64_1 + XXH_PRIME64_4;
3514 return acc;
3515}
3516
3518static xxh_u64 XXH64_avalanche(xxh_u64 hash)
3519{
3520 hash ^= hash >> 33;
3521 hash *= XXH_PRIME64_2;
3522 hash ^= hash >> 29;
3523 hash *= XXH_PRIME64_3;
3524 hash ^= hash >> 32;
3525 return hash;
3526}
3527
3528
3529#define XXH_get64bits(p) XXH_readLE64_align(p, align)
3530
3535XXH_FORCE_INLINE void
3536XXH64_initAccs(xxh_u64 *acc, xxh_u64 seed)
3537{
3538 XXH_ASSERT(acc != NULL);
3539 acc[0] = seed + XXH_PRIME64_1 + XXH_PRIME64_2;
3540 acc[1] = seed + XXH_PRIME64_2;
3541 acc[2] = seed + 0;
3542 acc[3] = seed - XXH_PRIME64_1;
3543}
3544
3551XXH_FORCE_INLINE const xxh_u8 *
3552XXH64_consumeLong(
3553 xxh_u64 *XXH_RESTRICT acc,
3554 xxh_u8 const *XXH_RESTRICT input,
3555 size_t len,
3556 XXH_alignment align
3557)
3558{
3559 const xxh_u8* const bEnd = input + len;
3560 const xxh_u8* const limit = bEnd - 31;
3561 XXH_ASSERT(acc != NULL);
3562 XXH_ASSERT(input != NULL);
3563 XXH_ASSERT(len >= 32);
3564 do {
3565 /* reroll on 32-bit */
3566 if (sizeof(void *) < sizeof(xxh_u64)) {
3567 size_t i;
3568 for (i = 0; i < 4; i++) {
3569 acc[i] = XXH64_round(acc[i], XXH_get64bits(input));
3570 input += 8;
3571 }
3572 } else {
3573 acc[0] = XXH64_round(acc[0], XXH_get64bits(input)); input += 8;
3574 acc[1] = XXH64_round(acc[1], XXH_get64bits(input)); input += 8;
3575 acc[2] = XXH64_round(acc[2], XXH_get64bits(input)); input += 8;
3576 acc[3] = XXH64_round(acc[3], XXH_get64bits(input)); input += 8;
3577 }
3578 } while (input < limit);
3579
3580 return input;
3581}
3582
3587XXH_FORCE_INLINE XXH_PUREF xxh_u64
3588XXH64_mergeAccs(const xxh_u64 *acc)
3589{
3590 XXH_ASSERT(acc != NULL);
3591 {
3592 xxh_u64 h64 = XXH_rotl64(acc[0], 1) + XXH_rotl64(acc[1], 7)
3593 + XXH_rotl64(acc[2], 12) + XXH_rotl64(acc[3], 18);
3594 /* reroll on 32-bit */
3595 if (sizeof(void *) < sizeof(xxh_u64)) {
3596 size_t i;
3597 for (i = 0; i < 4; i++) {
3598 h64 = XXH64_mergeRound(h64, acc[i]);
3599 }
3600 } else {
3601 h64 = XXH64_mergeRound(h64, acc[0]);
3602 h64 = XXH64_mergeRound(h64, acc[1]);
3603 h64 = XXH64_mergeRound(h64, acc[2]);
3604 h64 = XXH64_mergeRound(h64, acc[3]);
3605 }
3606 return h64;
3607 }
3608}
3609
3625XXH_STATIC XXH_PUREF xxh_u64
3626XXH64_finalize(xxh_u64 hash, const xxh_u8* ptr, size_t len, XXH_alignment align)
3627{
3628 if (ptr==NULL) XXH_ASSERT(len == 0);
3629 len &= 31;
3630 while (len >= 8) {
3631 xxh_u64 const k1 = XXH64_round(0, XXH_get64bits(ptr));
3632 ptr += 8;
3633 hash ^= k1;
3634 hash = XXH_rotl64(hash,27) * XXH_PRIME64_1 + XXH_PRIME64_4;
3635 len -= 8;
3636 }
3637 if (len >= 4) {
3638 hash ^= (xxh_u64)(XXH_get32bits(ptr)) * XXH_PRIME64_1;
3639 ptr += 4;
3640 hash = XXH_rotl64(hash, 23) * XXH_PRIME64_2 + XXH_PRIME64_3;
3641 len -= 4;
3642 }
3643 while (len > 0) {
3644 hash ^= (*ptr++) * XXH_PRIME64_5;
3645 hash = XXH_rotl64(hash, 11) * XXH_PRIME64_1;
3646 --len;
3647 }
3648 return XXH64_avalanche(hash);
3649}
3650
3651#ifdef XXH_OLD_NAMES
3652# define PROCESS1_64 XXH_PROCESS1_64
3653# define PROCESS4_64 XXH_PROCESS4_64
3654# define PROCESS8_64 XXH_PROCESS8_64
3655#else
3656# undef XXH_PROCESS1_64
3657# undef XXH_PROCESS4_64
3658# undef XXH_PROCESS8_64
3659#endif
3660
3669XXH_FORCE_INLINE XXH_PUREF xxh_u64
3670XXH64_endian_align(const xxh_u8* input, size_t len, xxh_u64 seed, XXH_alignment align)
3671{
3672 xxh_u64 h64;
3673 if (input==NULL) XXH_ASSERT(len == 0);
3674
3675 if (len>=32) { /* Process a large block of data */
3676 xxh_u64 acc[4];
3677 XXH64_initAccs(acc, seed);
3678
3679 input = XXH64_consumeLong(acc, input, len, align);
3680
3681 h64 = XXH64_mergeAccs(acc);
3682 } else {
3683 h64 = seed + XXH_PRIME64_5;
3684 }
3685
3686 h64 += (xxh_u64) len;
3687
3688 return XXH64_finalize(h64, input, len, align);
3689}
3690
3691
3693XXH_PUBLIC_API XXH64_hash_t XXH64 (XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed)
3694{
3695#if !defined(XXH_NO_STREAM) && XXH_SIZE_OPT >= 2
3696 /* Simple version, good for code maintenance, but unfortunately slow for small inputs */
3697 XXH64_state_t state;
3698 XXH64_reset(&state, seed);
3699 XXH64_update(&state, (const xxh_u8*)input, len);
3700 return XXH64_digest(&state);
3701#else
3702 if (XXH_FORCE_ALIGN_CHECK) {
3703 if ((((size_t)input) & 7)==0) { /* Input is aligned, let's leverage the speed advantage */
3704 return XXH64_endian_align((const xxh_u8*)input, len, seed, XXH_aligned);
3705 } }
3706
3707 return XXH64_endian_align((const xxh_u8*)input, len, seed, XXH_unaligned);
3708
3709#endif
3710}
3711
3712/******* Hash Streaming *******/
3713#ifndef XXH_NO_STREAM
3716{
3717 return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t));
3718}
3721{
3722 XXH_free(statePtr);
3723 return XXH_OK;
3724}
3725
3727XXH_PUBLIC_API void XXH64_copyState(XXH_NOESCAPE XXH64_state_t* dstState, const XXH64_state_t* srcState)
3728{
3729 XXH_memcpy(dstState, srcState, sizeof(*dstState));
3730}
3731
3734{
3735 XXH_ASSERT(statePtr != NULL);
3736 XXH_memset(statePtr, 0, sizeof(*statePtr));
3737 XXH64_initAccs(statePtr->acc, seed);
3738 return XXH_OK;
3739}
3740
3743XXH64_update (XXH_NOESCAPE XXH64_state_t* state, XXH_NOESCAPE const void* input, size_t len)
3744{
3745 if (input==NULL) {
3746 XXH_ASSERT(len == 0);
3747 return XXH_OK;
3748 }
3749
3750 state->total_len += len;
3751
3752 XXH_ASSERT(state->bufferedSize <= sizeof(state->buffer));
3753 if (len < sizeof(state->buffer) - state->bufferedSize) { /* fill in tmp buffer */
3754 XXH_memcpy(state->buffer + state->bufferedSize, input, len);
3755 state->bufferedSize += (XXH32_hash_t)len;
3756 return XXH_OK;
3757 }
3758
3759 { const xxh_u8* xinput = (const xxh_u8*)input;
3760 const xxh_u8* const bEnd = xinput + len;
3761
3762 if (state->bufferedSize) { /* non-empty buffer => complete first */
3763 XXH_memcpy(state->buffer + state->bufferedSize, xinput, sizeof(state->buffer) - state->bufferedSize);
3764 xinput += sizeof(state->buffer) - state->bufferedSize;
3765 /* and process one round */
3766 (void)XXH64_consumeLong(state->acc, state->buffer, sizeof(state->buffer), XXH_aligned);
3767 state->bufferedSize = 0;
3768 }
3769
3770 XXH_ASSERT(xinput <= bEnd);
3771 if ((size_t)(bEnd - xinput) >= sizeof(state->buffer)) {
3772 /* Process the remaining data */
3773 xinput = XXH64_consumeLong(state->acc, xinput, (size_t)(bEnd - xinput), XXH_unaligned);
3774 }
3775
3776 if (xinput < bEnd) {
3777 /* Copy the leftover to the tmp buffer */
3778 XXH_memcpy(state->buffer, xinput, (size_t)(bEnd-xinput));
3779 state->bufferedSize = (unsigned)(bEnd-xinput);
3780 }
3781 }
3782
3783 return XXH_OK;
3784}
3785
3786
3788XXH_PUBLIC_API XXH64_hash_t XXH64_digest(XXH_NOESCAPE const XXH64_state_t* state)
3789{
3790 xxh_u64 h64;
3791
3792 if (state->total_len >= 32) {
3793 h64 = XXH64_mergeAccs(state->acc);
3794 } else {
3795 h64 = state->acc[2] /*seed*/ + XXH_PRIME64_5;
3796 }
3797
3798 h64 += (xxh_u64) state->total_len;
3799
3800 return XXH64_finalize(h64, state->buffer, (size_t)state->total_len, XXH_aligned);
3801}
3802#endif /* !XXH_NO_STREAM */
3803
3804/******* Canonical representation *******/
3805
3808{
3809 XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t));
3810 if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap64(hash);
3811 XXH_memcpy(dst, &hash, sizeof(*dst));
3812}
3813
3816{
3817 return XXH_readBE64(src);
3818}
3819
3820#ifndef XXH_NO_XXH3
3821
3822/* *********************************************************************
3823* XXH3
3824* New generation hash designed for speed on small keys and vectorization
3825************************************************************************ */
3833/* === Compiler specifics === */
3834
3835
3836#if (defined(__GNUC__) && (__GNUC__ >= 3)) \
3837 || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) \
3838 || defined(__clang__)
3839# define XXH_likely(x) __builtin_expect(x, 1)
3840# define XXH_unlikely(x) __builtin_expect(x, 0)
3841#else
3842# define XXH_likely(x) (x)
3843# define XXH_unlikely(x) (x)
3844#endif
3845
3846#ifndef XXH_HAS_INCLUDE
3847# ifdef __has_include
3848/*
3849 * Not defined as XXH_HAS_INCLUDE(x) (function-like) because
3850 * this causes segfaults in Apple Clang 4.2 (on Mac OS X 10.7 Lion)
3851 */
3852# define XXH_HAS_INCLUDE __has_include
3853# else
3854# define XXH_HAS_INCLUDE(x) 0
3855# endif
3856#endif
3857
3858#if defined(__GNUC__) || defined(__clang__)
3859# if defined(__ARM_FEATURE_SVE)
3860# include <arm_sve.h>
3861# endif
3862# if defined(__ARM_NEON__) || defined(__ARM_NEON) \
3863 || (defined(_M_ARM) && _M_ARM >= 7) \
3864 || defined(_M_ARM64) || defined(_M_ARM64EC) \
3865 || (defined(__wasm_simd128__) && XXH_HAS_INCLUDE(<arm_neon.h>)) /* WASM SIMD128 via SIMDe */
3866# define inline __inline__ /* circumvent a clang bug */
3867# include <arm_neon.h>
3868# undef inline
3869# elif defined(__AVX2__)
3870# include <immintrin.h>
3871# elif defined(__SSE2__)
3872# include <emmintrin.h>
3873# elif defined(__loongarch_asx)
3874# include <lasxintrin.h>
3875# include <lsxintrin.h>
3876# elif defined(__loongarch_sx)
3877# include <lsxintrin.h>
3878# elif defined(__riscv_vector)
3879# include <riscv_vector.h>
3880# endif
3881#endif
3882
3883#if defined(_MSC_VER)
3884# include <intrin.h>
3885#endif
3886
3887/*
3888 * One goal of XXH3 is to make it fast on both 32-bit and 64-bit, while
3889 * remaining a true 64-bit/128-bit hash function.
3890 *
3891 * This is done by prioritizing a subset of 64-bit operations that can be
3892 * emulated without too many steps on the average 32-bit machine.
3893 *
3894 * For example, these two lines seem similar, and run equally fast on 64-bit:
3895 *
3896 * xxh_u64 x;
3897 * x ^= (x >> 47); // good
3898 * x ^= (x >> 13); // bad
3899 *
3900 * However, to a 32-bit machine, there is a major difference.
3901 *
3902 * x ^= (x >> 47) looks like this:
3903 *
3904 * x.lo ^= (x.hi >> (47 - 32));
3905 *
3906 * while x ^= (x >> 13) looks like this:
3907 *
3908 * // note: funnel shifts are not usually cheap.
3909 * x.lo ^= (x.lo >> 13) | (x.hi << (32 - 13));
3910 * x.hi ^= (x.hi >> 13);
3911 *
3912 * The first one is significantly faster than the second, simply because the
3913 * shift is larger than 32. This means:
3914 * - All the bits we need are in the upper 32 bits, so we can ignore the lower
3915 * 32 bits in the shift.
3916 * - The shift result will always fit in the lower 32 bits, and therefore,
3917 * we can ignore the upper 32 bits in the xor.
3918 *
3919 * Thanks to this optimization, XXH3 only requires these features to be efficient:
3920 *
3921 * - Usable unaligned access
3922 * - A 32-bit or 64-bit ALU
3923 * - If 32-bit, a decent ADC instruction
3924 * - A 32 or 64-bit multiply with a 64-bit result
3925 * - For the 128-bit variant, a decent byteswap helps short inputs.
3926 *
3927 * The first two are already required by XXH32, and almost all 32-bit and 64-bit
3928 * platforms which can run XXH32 can run XXH3 efficiently.
3929 *
3930 * Thumb-1, the classic 16-bit only subset of ARM's instruction set, is one
3931 * notable exception.
3932 *
3933 * First of all, Thumb-1 lacks support for the UMULL instruction which
3934 * performs the important long multiply. This means numerous __aeabi_lmul
3935 * calls.
3936 *
3937 * Second of all, the 8 functional registers are just not enough.
3938 * Setup for __aeabi_lmul, byteshift loads, pointers, and all arithmetic need
3939 * Lo registers, and this shuffling results in thousands more MOVs than A32.
3940 *
3941 * A32 and T32 don't have this limitation. They can access all 14 registers,
3942 * do a 32->64 multiply with UMULL, and the flexible operand allowing free
3943 * shifts is helpful, too.
3944 *
3945 * Therefore, we do a quick sanity check.
3946 *
3947 * If compiling Thumb-1 for a target which supports ARM instructions, we will
3948 * emit a warning, as it is not a "sane" platform to compile for.
3949 *
3950 * Usually, if this happens, it is because of an accident and you probably need
3951 * to specify -march, as you likely meant to compile for a newer architecture.
3952 *
3953 * Credit: large sections of the vectorial and asm source code paths
3954 * have been contributed by @easyaspi314
3955 */
3956#if defined(__thumb__) && !defined(__thumb2__) && defined(__ARM_ARCH_ISA_ARM)
3957# warning "XXH3 is highly inefficient without ARM or Thumb-2."
3958#endif
3959
3960/* ==========================================
3961 * Vectorization detection
3962 * ========================================== */
3963
3964#ifdef XXH_DOXYGEN
3975# define XXH_VECTOR XXH_SCALAR
3985# define XXH_ACC_ALIGN 8
3986#endif
3987
3988/* Actual definition */
3989#ifndef XXH_DOXYGEN
3990#endif
3991
3992#ifndef XXH_VECTOR /* can be defined on command line */
3993# if ( \
3994 defined(__ARM_NEON__) || defined(__ARM_NEON) /* gcc */ \
3995 || defined(_M_ARM) || defined(_M_ARM64) || defined(_M_ARM64EC) /* msvc */ \
3996 || (defined(__wasm_simd128__) && XXH_HAS_INCLUDE(<arm_neon.h>)) /* wasm simd128 via SIMDe */ \
3997 ) && ( \
3998 defined(_WIN32) || defined(__LITTLE_ENDIAN__) /* little endian only */ \
3999 || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) \
4000 )
4001# define XXH_VECTOR XXH_NEON
4002# elif defined(__ARM_FEATURE_SVE)
4003# define XXH_VECTOR XXH_SVE
4004# elif defined(__AVX512F__)
4005# define XXH_VECTOR XXH_AVX512
4006# elif defined(__AVX2__)
4007# define XXH_VECTOR XXH_AVX2
4008# elif defined(__SSE2__) || defined(_M_X64) || (defined(_M_IX86_FP) && (_M_IX86_FP == 2))
4009# define XXH_VECTOR XXH_SSE2
4010# elif (defined(__PPC64__) && defined(__POWER8_VECTOR__)) \
4011 || (defined(__s390x__) && defined(__VEC__)) \
4012 && defined(__GNUC__) /* TODO: IBM XL */
4013# define XXH_VECTOR XXH_VSX
4014# elif defined(__loongarch_asx)
4015# define XXH_VECTOR XXH_LASX
4016# elif defined(__loongarch_sx)
4017# define XXH_VECTOR XXH_LSX
4018# elif defined(__riscv_vector)
4019# define XXH_VECTOR XXH_RVV
4020# else
4021# define XXH_VECTOR XXH_SCALAR
4022# endif
4023#endif
4024
4025/* __ARM_FEATURE_SVE is only supported by GCC & Clang. */
4026#if (XXH_VECTOR == XXH_SVE) && !defined(__ARM_FEATURE_SVE)
4027# ifdef _MSC_VER
4028# pragma warning(once : 4606)
4029# else
4030# warning "__ARM_FEATURE_SVE isn't supported. Use SCALAR instead."
4031# endif
4032# undef XXH_VECTOR
4033# define XXH_VECTOR XXH_SCALAR
4034#endif
4035
4036/*
4037 * Controls the alignment of the accumulator,
4038 * for compatibility with aligned vector loads, which are usually faster.
4039 */
4040#ifndef XXH_ACC_ALIGN
4041# if defined(XXH_X86DISPATCH)
4042# define XXH_ACC_ALIGN 64 /* for compatibility with avx512 */
4043# elif XXH_VECTOR == XXH_SCALAR /* scalar */
4044# define XXH_ACC_ALIGN 8
4045# elif XXH_VECTOR == XXH_SSE2 /* sse2 */
4046# define XXH_ACC_ALIGN 16
4047# elif XXH_VECTOR == XXH_AVX2 /* avx2 */
4048# define XXH_ACC_ALIGN 32
4049# elif XXH_VECTOR == XXH_NEON /* neon */
4050# define XXH_ACC_ALIGN 16
4051# elif XXH_VECTOR == XXH_VSX /* vsx */
4052# define XXH_ACC_ALIGN 16
4053# elif XXH_VECTOR == XXH_AVX512 /* avx512 */
4054# define XXH_ACC_ALIGN 64
4055# elif XXH_VECTOR == XXH_SVE /* sve */
4056# define XXH_ACC_ALIGN 64
4057# elif XXH_VECTOR == XXH_LASX /* lasx */
4058# define XXH_ACC_ALIGN 64
4059# elif XXH_VECTOR == XXH_LSX /* lsx */
4060# define XXH_ACC_ALIGN 64
4061# elif XXH_VECTOR == XXH_RVV /* rvv */
4062# define XXH_ACC_ALIGN 64 /* could be 8, but 64 may be faster */
4063# endif
4064#endif
4065
4066#if defined(XXH_X86DISPATCH) || XXH_VECTOR == XXH_SSE2 \
4067 || XXH_VECTOR == XXH_AVX2 || XXH_VECTOR == XXH_AVX512
4068# define XXH_SEC_ALIGN XXH_ACC_ALIGN
4069#elif XXH_VECTOR == XXH_SVE
4070# define XXH_SEC_ALIGN XXH_ACC_ALIGN
4071#elif XXH_VECTOR == XXH_RVV
4072# define XXH_SEC_ALIGN XXH_ACC_ALIGN
4073#else
4074# define XXH_SEC_ALIGN 8
4075#endif
4076
4077#if defined(__GNUC__) || defined(__clang__)
4078# define XXH_ALIASING __attribute__((__may_alias__))
4079#else
4080# define XXH_ALIASING /* nothing */
4081#endif
4082
4083/*
4084 * UGLY HACK:
4085 * GCC usually generates the best code with -O3 for xxHash.
4086 *
4087 * However, when targeting AVX2, it is overzealous in its unrolling resulting
4088 * in code roughly 3/4 the speed of Clang.
4089 *
4090 * There are other issues, such as GCC splitting _mm256_loadu_si256 into
4091 * _mm_loadu_si128 + _mm256_inserti128_si256. This is an optimization which
4092 * only applies to Sandy and Ivy Bridge... which don't even support AVX2.
4093 *
4094 * That is why when compiling the AVX2 version, it is recommended to use either
4095 * -O2 -mavx2 -march=haswell
4096 * or
4097 * -O2 -mavx2 -mno-avx256-split-unaligned-load
4098 * for decent performance, or to use Clang instead.
4099 *
4100 * Fortunately, we can control the first one with a pragma that forces GCC into
4101 * -O2, but the other one we can't control without "failed to inline always
4102 * inline function due to target mismatch" warnings.
4103 */
4104#if XXH_VECTOR == XXH_AVX2 /* AVX2 */ \
4105 && defined(__GNUC__) && !defined(__clang__) /* GCC, not Clang */ \
4106 && defined(__OPTIMIZE__) && XXH_SIZE_OPT <= 0 /* respect -O0 and -Os */
4107# pragma GCC push_options
4108# pragma GCC optimize("-O2")
4109#endif
4110
4111#if XXH_VECTOR == XXH_NEON
4112
4113/*
4114 * UGLY HACK: While AArch64 GCC on Linux does not seem to care, on macOS, GCC -O3
4115 * optimizes out the entire hashLong loop because of the aliasing violation.
4116 *
4117 * However, GCC is also inefficient at load-store optimization with vld1q/vst1q,
4118 * so the only option is to mark it as aliasing.
4119 */
4120typedef uint64x2_t xxh_aliasing_uint64x2_t XXH_ALIASING;
4121
4135#if defined(__aarch64__) && defined(__GNUC__) && !defined(__clang__)
4136XXH_FORCE_INLINE uint64x2_t XXH_vld1q_u64(void const* ptr) /* silence -Wcast-align */
4137{
4138 return *(xxh_aliasing_uint64x2_t const *)ptr;
4139}
4140#else
4141XXH_FORCE_INLINE uint64x2_t XXH_vld1q_u64(void const* ptr)
4142{
4143 return vreinterpretq_u64_u8(vld1q_u8((uint8_t const*)ptr));
4144}
4145#endif
4146
4155#if defined(__aarch64__) && defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 11
4156XXH_FORCE_INLINE uint64x2_t
4157XXH_vmlal_low_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs)
4158{
4159 /* Inline assembly is the only way */
4160 __asm__("umlal %0.2d, %1.2s, %2.2s" : "+w" (acc) : "w" (lhs), "w" (rhs));
4161 return acc;
4162}
4163XXH_FORCE_INLINE uint64x2_t
4164XXH_vmlal_high_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs)
4165{
4166 /* This intrinsic works as expected */
4167 return vmlal_high_u32(acc, lhs, rhs);
4168}
4169#else
4170/* Portable intrinsic versions */
4171XXH_FORCE_INLINE uint64x2_t
4172XXH_vmlal_low_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs)
4173{
4174 return vmlal_u32(acc, vget_low_u32(lhs), vget_low_u32(rhs));
4175}
4178XXH_FORCE_INLINE uint64x2_t
4179XXH_vmlal_high_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs)
4180{
4181 return vmlal_u32(acc, vget_high_u32(lhs), vget_high_u32(rhs));
4182}
4183#endif
4184
4223# ifndef XXH3_NEON_LANES
4224# if (defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64) || defined(_M_ARM64EC)) \
4225 && !defined(__APPLE__) && XXH_SIZE_OPT <= 0
4226# define XXH3_NEON_LANES 6
4227# else
4228# define XXH3_NEON_LANES XXH_ACC_NB
4229# endif
4230# endif
4231#endif /* XXH_VECTOR == XXH_NEON */
4232
4233/*
4234 * VSX and Z Vector helpers.
4235 *
4236 * This is very messy, and any pull requests to clean this up are welcome.
4237 *
4238 * There are a lot of problems with supporting VSX and s390x, due to
4239 * inconsistent intrinsics, spotty coverage, and multiple endiannesses.
4240 */
4241#if XXH_VECTOR == XXH_VSX
4242/* Annoyingly, these headers _may_ define three macros: `bool`, `vector`,
4243 * and `pixel`. This is a problem for obvious reasons.
4244 *
4245 * These keywords are unnecessary; the spec literally says they are
4246 * equivalent to `__bool`, `__vector`, and `__pixel` and may be undef'd
4247 * after including the header.
4248 *
4249 * We use pragma push_macro/pop_macro to keep the namespace clean. */
4250# pragma push_macro("bool")
4251# pragma push_macro("vector")
4252# pragma push_macro("pixel")
4253/* silence potential macro redefined warnings */
4254# undef bool
4255# undef vector
4256# undef pixel
4257
4258# if defined(__s390x__)
4259# include <s390intrin.h>
4260# else
4261# include <altivec.h>
4262# endif
4263
4264/* Restore the original macro values, if applicable. */
4265# pragma pop_macro("pixel")
4266# pragma pop_macro("vector")
4267# pragma pop_macro("bool")
4268
4269typedef __vector unsigned long long xxh_u64x2;
4270typedef __vector unsigned char xxh_u8x16;
4271typedef __vector unsigned xxh_u32x4;
4272
4273/*
4274 * UGLY HACK: Similar to aarch64 macOS GCC, s390x GCC has the same aliasing issue.
4275 */
4276typedef xxh_u64x2 xxh_aliasing_u64x2 XXH_ALIASING;
4277
4278# ifndef XXH_VSX_BE
4279# if defined(__BIG_ENDIAN__) \
4280 || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
4281# define XXH_VSX_BE 1
4282# elif defined(__VEC_ELEMENT_REG_ORDER__) && __VEC_ELEMENT_REG_ORDER__ == __ORDER_BIG_ENDIAN__
4283# warning "-maltivec=be is not recommended. Please use native endianness."
4284# define XXH_VSX_BE 1
4285# else
4286# define XXH_VSX_BE 0
4287# endif
4288# endif /* !defined(XXH_VSX_BE) */
4289
4290# if XXH_VSX_BE
4291# if defined(__POWER9_VECTOR__) || (defined(__clang__) && defined(__s390x__))
4292# define XXH_vec_revb vec_revb
4293# else
4297XXH_FORCE_INLINE xxh_u64x2 XXH_vec_revb(xxh_u64x2 val)
4298{
4299 xxh_u8x16 const vByteSwap = { 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
4300 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08 };
4301 return vec_perm(val, val, vByteSwap);
4302}
4303# endif
4304# endif /* XXH_VSX_BE */
4305
4309XXH_FORCE_INLINE xxh_u64x2 XXH_vec_loadu(const void *ptr)
4310{
4311 xxh_u64x2 ret;
4312 XXH_memcpy(&ret, ptr, sizeof(xxh_u64x2));
4313# if XXH_VSX_BE
4314 ret = XXH_vec_revb(ret);
4315# endif
4316 return ret;
4317}
4318
4319/*
4320 * vec_mulo and vec_mule are very problematic intrinsics on PowerPC
4321 *
4322 * These intrinsics weren't added until GCC 8, despite existing for a while,
4323 * and they are endian dependent. Also, their meaning swap depending on version.
4324 * */
4325# if defined(__s390x__)
4326 /* s390x is always big endian, no issue on this platform */
4327# define XXH_vec_mulo vec_mulo
4328# define XXH_vec_mule vec_mule
4329# elif defined(__clang__) && XXH_HAS_BUILTIN(__builtin_altivec_vmuleuw) && !defined(__ibmxl__)
4330/* Clang has a better way to control this, we can just use the builtin which doesn't swap. */
4331 /* The IBM XL Compiler (which defined __clang__) only implements the vec_* operations */
4332# define XXH_vec_mulo __builtin_altivec_vmulouw
4333# define XXH_vec_mule __builtin_altivec_vmuleuw
4334# else
4335/* gcc needs inline assembly */
4336/* Adapted from https://github.com/google/highwayhash/blob/master/highwayhash/hh_vsx.h. */
4337XXH_FORCE_INLINE xxh_u64x2 XXH_vec_mulo(xxh_u32x4 a, xxh_u32x4 b)
4338{
4339 xxh_u64x2 result;
4340 __asm__("vmulouw %0, %1, %2" : "=v" (result) : "v" (a), "v" (b));
4341 return result;
4342}
4343XXH_FORCE_INLINE xxh_u64x2 XXH_vec_mule(xxh_u32x4 a, xxh_u32x4 b)
4344{
4345 xxh_u64x2 result;
4346 __asm__("vmuleuw %0, %1, %2" : "=v" (result) : "v" (a), "v" (b));
4347 return result;
4348}
4349# endif /* XXH_vec_mulo, XXH_vec_mule */
4350#endif /* XXH_VECTOR == XXH_VSX */
4351
4352#if XXH_VECTOR == XXH_SVE
4353#define ACCRND(acc, offset) \
4354do { \
4355 svuint64_t input_vec = svld1_u64(mask, xinput + offset); \
4356 svuint64_t secret_vec = svld1_u64(mask, xsecret + offset); \
4357 svuint64_t mixed = sveor_u64_x(mask, secret_vec, input_vec); \
4358 svuint64_t swapped = svtbl_u64(input_vec, kSwap); \
4359 svuint64_t mixed_lo = svextw_u64_x(mask, mixed); \
4360 svuint64_t mixed_hi = svlsr_n_u64_x(mask, mixed, 32); \
4361 svuint64_t mul = svmad_u64_x(mask, mixed_lo, mixed_hi, swapped); \
4362 acc = svadd_u64_x(mask, acc, mul); \
4363} while (0)
4364#endif /* XXH_VECTOR == XXH_SVE */
4365
4366/* prefetch
4367 * can be disabled, by declaring XXH_NO_PREFETCH build macro */
4368#if defined(XXH_NO_PREFETCH)
4369# define XXH_PREFETCH(ptr) (void)(ptr) /* disabled */
4370#else
4371# if XXH_SIZE_OPT >= 1
4372# define XXH_PREFETCH(ptr) (void)(ptr)
4373# elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86)) /* _mm_prefetch() not defined outside of x86/x64 */
4374# include <mmintrin.h> /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */
4375# define XXH_PREFETCH(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T0)
4376# elif defined(__GNUC__) && ( (__GNUC__ >= 4) || ( (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) ) )
4377# define XXH_PREFETCH(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 3 /* locality */)
4378# else
4379# define XXH_PREFETCH(ptr) (void)(ptr) /* disabled */
4380# endif
4381#endif /* XXH_NO_PREFETCH */
4382
4383
4384/* ==========================================
4385 * XXH3 default settings
4386 * ========================================== */
4387
4388#define XXH_SECRET_DEFAULT_SIZE 192 /* minimum XXH3_SECRET_SIZE_MIN */
4389
4390#if (XXH_SECRET_DEFAULT_SIZE < XXH3_SECRET_SIZE_MIN)
4391# error "default keyset is not large enough"
4392#endif
4393
4398XXH_ALIGN(64) static const xxh_u8 XXH3_kSecret[XXH_SECRET_DEFAULT_SIZE] = {
4399 0xb8, 0xfe, 0x6c, 0x39, 0x23, 0xa4, 0x4b, 0xbe, 0x7c, 0x01, 0x81, 0x2c, 0xf7, 0x21, 0xad, 0x1c,
4400 0xde, 0xd4, 0x6d, 0xe9, 0x83, 0x90, 0x97, 0xdb, 0x72, 0x40, 0xa4, 0xa4, 0xb7, 0xb3, 0x67, 0x1f,
4401 0xcb, 0x79, 0xe6, 0x4e, 0xcc, 0xc0, 0xe5, 0x78, 0x82, 0x5a, 0xd0, 0x7d, 0xcc, 0xff, 0x72, 0x21,
4402 0xb8, 0x08, 0x46, 0x74, 0xf7, 0x43, 0x24, 0x8e, 0xe0, 0x35, 0x90, 0xe6, 0x81, 0x3a, 0x26, 0x4c,
4403 0x3c, 0x28, 0x52, 0xbb, 0x91, 0xc3, 0x00, 0xcb, 0x88, 0xd0, 0x65, 0x8b, 0x1b, 0x53, 0x2e, 0xa3,
4404 0x71, 0x64, 0x48, 0x97, 0xa2, 0x0d, 0xf9, 0x4e, 0x38, 0x19, 0xef, 0x46, 0xa9, 0xde, 0xac, 0xd8,
4405 0xa8, 0xfa, 0x76, 0x3f, 0xe3, 0x9c, 0x34, 0x3f, 0xf9, 0xdc, 0xbb, 0xc7, 0xc7, 0x0b, 0x4f, 0x1d,
4406 0x8a, 0x51, 0xe0, 0x4b, 0xcd, 0xb4, 0x59, 0x31, 0xc8, 0x9f, 0x7e, 0xc9, 0xd9, 0x78, 0x73, 0x64,
4407 0xea, 0xc5, 0xac, 0x83, 0x34, 0xd3, 0xeb, 0xc3, 0xc5, 0x81, 0xa0, 0xff, 0xfa, 0x13, 0x63, 0xeb,
4408 0x17, 0x0d, 0xdd, 0x51, 0xb7, 0xf0, 0xda, 0x49, 0xd3, 0x16, 0x55, 0x26, 0x29, 0xd4, 0x68, 0x9e,
4409 0x2b, 0x16, 0xbe, 0x58, 0x7d, 0x47, 0xa1, 0xfc, 0x8f, 0xf8, 0xb8, 0xd1, 0x7a, 0xd0, 0x31, 0xce,
4410 0x45, 0xcb, 0x3a, 0x8f, 0x95, 0x16, 0x04, 0x28, 0xaf, 0xd7, 0xfb, 0xca, 0xbb, 0x4b, 0x40, 0x7e,
4411};
4412
4413static const xxh_u64 PRIME_MX1 = 0x165667919E3779F9ULL;
4414static const xxh_u64 PRIME_MX2 = 0x9FB21C651E98DF25ULL;
4416#ifdef XXH_OLD_NAMES
4417# define kSecret XXH3_kSecret
4418#endif
4419
4420#ifdef XXH_DOXYGEN
4437XXH_FORCE_INLINE xxh_u64
4438XXH_mult32to64(xxh_u64 x, xxh_u64 y)
4439{
4440 return (x & 0xFFFFFFFF) * (y & 0xFFFFFFFF);
4441}
4442#elif defined(_MSC_VER) && defined(_M_IX86)
4443# define XXH_mult32to64(x, y) __emulu((unsigned)(x), (unsigned)(y))
4444#else
4445/*
4446 * Downcast + upcast is usually better than masking on older compilers like
4447 * GCC 4.2 (especially 32-bit ones), all without affecting newer compilers.
4448 *
4449 * The other method, (x & 0xFFFFFFFF) * (y & 0xFFFFFFFF), will AND both operands
4450 * and perform a full 64x64 multiply -- entirely redundant on 32-bit.
4451 */
4452# define XXH_mult32to64(x, y) ((xxh_u64)(xxh_u32)(x) * (xxh_u64)(xxh_u32)(y))
4453#endif
4454
4464static XXH128_hash_t
4465XXH_mult64to128(xxh_u64 lhs, xxh_u64 rhs)
4466{
4467 /*
4468 * GCC/Clang __uint128_t method.
4469 *
4470 * On most 64-bit targets, GCC and Clang define a __uint128_t type.
4471 * This is usually the best way as it usually uses a native long 64-bit
4472 * multiply, such as MULQ on x86_64 or MUL + UMULH on aarch64.
4473 *
4474 * Usually.
4475 *
4476 * Despite being a 32-bit platform, Clang (and emscripten) define this type
4477 * despite not having the arithmetic for it. This results in a laggy
4478 * compiler builtin call which calculates a full 128-bit multiply.
4479 * In that case it is best to use the portable one.
4480 * https://github.com/Cyan4973/xxHash/issues/211#issuecomment-515575677
4481 */
4482#if (defined(__GNUC__) || defined(__clang__)) && !defined(__wasm__) \
4483 && defined(__SIZEOF_INT128__) \
4484 || (defined(_INTEGRAL_MAX_BITS) && _INTEGRAL_MAX_BITS >= 128)
4485
4486 __uint128_t const product = (__uint128_t)lhs * (__uint128_t)rhs;
4487 XXH128_hash_t r128;
4488 r128.low64 = (xxh_u64)(product);
4489 r128.high64 = (xxh_u64)(product >> 64);
4490 return r128;
4491
4492 /*
4493 * MSVC for x64's _umul128 method.
4494 *
4495 * xxh_u64 _umul128(xxh_u64 Multiplier, xxh_u64 Multiplicand, xxh_u64 *HighProduct);
4496 *
4497 * This compiles to single operand MUL on x64.
4498 */
4499#elif (defined(_M_X64) || defined(_M_IA64)) && !defined(_M_ARM64EC)
4500
4501#ifndef _MSC_VER
4502# pragma intrinsic(_umul128)
4503#endif
4504 xxh_u64 product_high;
4505 xxh_u64 const product_low = _umul128(lhs, rhs, &product_high);
4506 XXH128_hash_t r128;
4507 r128.low64 = product_low;
4508 r128.high64 = product_high;
4509 return r128;
4510
4511 /*
4512 * MSVC for ARM64's __umulh method.
4513 *
4514 * This compiles to the same MUL + UMULH as GCC/Clang's __uint128_t method.
4515 */
4516#elif defined(_M_ARM64) || defined(_M_ARM64EC)
4517
4518#ifndef _MSC_VER
4519# pragma intrinsic(__umulh)
4520#endif
4521 XXH128_hash_t r128;
4522 r128.low64 = lhs * rhs;
4523 r128.high64 = __umulh(lhs, rhs);
4524 return r128;
4525
4526#else
4527 /*
4528 * Portable scalar method. Optimized for 32-bit and 64-bit ALUs.
4529 *
4530 * This is a fast and simple grade school multiply, which is shown below
4531 * with base 10 arithmetic instead of base 0x100000000.
4532 *
4533 * 9 3 // D2 lhs = 93
4534 * x 7 5 // D2 rhs = 75
4535 * ----------
4536 * 1 5 // D2 lo_lo = (93 % 10) * (75 % 10) = 15
4537 * 4 5 | // D2 hi_lo = (93 / 10) * (75 % 10) = 45
4538 * 2 1 | // D2 lo_hi = (93 % 10) * (75 / 10) = 21
4539 * + 6 3 | | // D2 hi_hi = (93 / 10) * (75 / 10) = 63
4540 * ---------
4541 * 2 7 | // D2 cross = (15 / 10) + (45 % 10) + 21 = 27
4542 * + 6 7 | | // D2 upper = (27 / 10) + (45 / 10) + 63 = 67
4543 * ---------
4544 * 6 9 7 5 // D4 res = (27 * 10) + (15 % 10) + (67 * 100) = 6975
4545 *
4546 * The reasons for adding the products like this are:
4547 * 1. It avoids manual carry tracking. Just like how
4548 * (9 * 9) + 9 + 9 = 99, the same applies with this for UINT64_MAX.
4549 * This avoids a lot of complexity.
4550 *
4551 * 2. It hints for, and on Clang, compiles to, the powerful UMAAL
4552 * instruction available in ARM's Digital Signal Processing extension
4553 * in 32-bit ARMv6 and later, which is shown below:
4554 *
4555 * void UMAAL(xxh_u32 *RdLo, xxh_u32 *RdHi, xxh_u32 Rn, xxh_u32 Rm)
4556 * {
4557 * xxh_u64 product = (xxh_u64)*RdLo * (xxh_u64)*RdHi + Rn + Rm;
4558 * *RdLo = (xxh_u32)(product & 0xFFFFFFFF);
4559 * *RdHi = (xxh_u32)(product >> 32);
4560 * }
4561 *
4562 * This instruction was designed for efficient long multiplication, and
4563 * allows this to be calculated in only 4 instructions at speeds
4564 * comparable to some 64-bit ALUs.
4565 *
4566 * 3. It isn't terrible on other platforms. Usually this will be a couple
4567 * of 32-bit ADD/ADCs.
4568 */
4569
4570 /* First calculate all of the cross products. */
4571 xxh_u64 const lo_lo = XXH_mult32to64(lhs & 0xFFFFFFFF, rhs & 0xFFFFFFFF);
4572 xxh_u64 const hi_lo = XXH_mult32to64(lhs >> 32, rhs & 0xFFFFFFFF);
4573 xxh_u64 const lo_hi = XXH_mult32to64(lhs & 0xFFFFFFFF, rhs >> 32);
4574 xxh_u64 const hi_hi = XXH_mult32to64(lhs >> 32, rhs >> 32);
4575
4576 /* Now add the products together. These will never overflow. */
4577 xxh_u64 const cross = (lo_lo >> 32) + (hi_lo & 0xFFFFFFFF) + lo_hi;
4578 xxh_u64 const upper = (hi_lo >> 32) + (cross >> 32) + hi_hi;
4579 xxh_u64 const lower = (cross << 32) | (lo_lo & 0xFFFFFFFF);
4580
4581 XXH128_hash_t r128;
4582 r128.low64 = lower;
4583 r128.high64 = upper;
4584 return r128;
4585#endif
4586}
4587
4598static xxh_u64
4599XXH3_mul128_fold64(xxh_u64 lhs, xxh_u64 rhs)
4600{
4601 XXH128_hash_t product = XXH_mult64to128(lhs, rhs);
4602 return product.low64 ^ product.high64;
4603}
4604
4606XXH_FORCE_INLINE XXH_CONSTF xxh_u64 XXH_xorshift64(xxh_u64 v64, int shift)
4607{
4608 XXH_ASSERT(0 <= shift && shift < 64);
4609 return v64 ^ (v64 >> shift);
4610}
4611
4612/*
4613 * This is a fast avalanche stage,
4614 * suitable when input bits are already partially mixed
4615 */
4616static XXH64_hash_t XXH3_avalanche(xxh_u64 h64)
4617{
4618 h64 = XXH_xorshift64(h64, 37);
4619 h64 *= PRIME_MX1;
4620 h64 = XXH_xorshift64(h64, 32);
4621 return h64;
4622}
4623
4624/*
4625 * This is a stronger avalanche,
4626 * inspired by Pelle Evensen's rrmxmx
4627 * preferable when input has not been previously mixed
4628 */
4629static XXH64_hash_t XXH3_rrmxmx(xxh_u64 h64, xxh_u64 len)
4630{
4631 /* this mix is inspired by Pelle Evensen's rrmxmx */
4632 h64 ^= XXH_rotl64(h64, 49) ^ XXH_rotl64(h64, 24);
4633 h64 *= PRIME_MX2;
4634 h64 ^= (h64 >> 35) + len ;
4635 h64 *= PRIME_MX2;
4636 return XXH_xorshift64(h64, 28);
4637}
4638
4639
4640/* ==========================================
4641 * Short keys
4642 * ==========================================
4643 * One of the shortcomings of XXH32 and XXH64 was that their performance was
4644 * sub-optimal on short lengths. It used an iterative algorithm which strongly
4645 * favored lengths that were a multiple of 4 or 8.
4646 *
4647 * Instead of iterating over individual inputs, we use a set of single shot
4648 * functions which piece together a range of lengths and operate in constant time.
4649 *
4650 * Additionally, the number of multiplies has been significantly reduced. This
4651 * reduces latency, especially when emulating 64-bit multiplies on 32-bit.
4652 *
4653 * Depending on the platform, this may or may not be faster than XXH32, but it
4654 * is almost guaranteed to be faster than XXH64.
4655 */
4656
4657/*
4658 * At very short lengths, there isn't enough input to fully hide secrets, or use
4659 * the entire secret.
4660 *
4661 * There is also only a limited amount of mixing we can do before significantly
4662 * impacting performance.
4663 *
4664 * Therefore, we use different sections of the secret and always mix two secret
4665 * samples with an XOR. This should have no effect on performance on the
4666 * seedless or withSeed variants because everything _should_ be constant folded
4667 * by modern compilers.
4668 *
4669 * The XOR mixing hides individual parts of the secret and increases entropy.
4670 *
4671 * This adds an extra layer of strength for custom secrets.
4672 */
4673XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t
4674XXH3_len_1to3_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed)
4675{
4676 XXH_ASSERT(input != NULL);
4677 XXH_ASSERT(1 <= len && len <= 3);
4678 XXH_ASSERT(secret != NULL);
4679 /*
4680 * len = 1: combined = { input[0], 0x01, input[0], input[0] }
4681 * len = 2: combined = { input[1], 0x02, input[0], input[1] }
4682 * len = 3: combined = { input[2], 0x03, input[0], input[1] }
4683 */
4684 { xxh_u8 const c1 = input[0];
4685 xxh_u8 const c2 = input[len >> 1];
4686 xxh_u8 const c3 = input[len - 1];
4687 xxh_u32 const combined = ((xxh_u32)c1 << 16) | ((xxh_u32)c2 << 24)
4688 | ((xxh_u32)c3 << 0) | ((xxh_u32)len << 8);
4689 xxh_u64 const bitflip = (XXH_readLE32(secret) ^ XXH_readLE32(secret+4)) + seed;
4690 xxh_u64 const keyed = (xxh_u64)combined ^ bitflip;
4691 return XXH64_avalanche(keyed);
4692 }
4693}
4694
4695XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t
4696XXH3_len_4to8_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed)
4697{
4698 XXH_ASSERT(input != NULL);
4699 XXH_ASSERT(secret != NULL);
4700 XXH_ASSERT(4 <= len && len <= 8);
4701 seed ^= (xxh_u64)XXH_swap32((xxh_u32)seed) << 32;
4702 { xxh_u32 const input1 = XXH_readLE32(input);
4703 xxh_u32 const input2 = XXH_readLE32(input + len - 4);
4704 xxh_u64 const bitflip = (XXH_readLE64(secret+8) ^ XXH_readLE64(secret+16)) - seed;
4705 xxh_u64 const input64 = input2 + (((xxh_u64)input1) << 32);
4706 xxh_u64 const keyed = input64 ^ bitflip;
4707 return XXH3_rrmxmx(keyed, len);
4708 }
4709}
4710
4711XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t
4712XXH3_len_9to16_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed)
4713{
4714 XXH_ASSERT(input != NULL);
4715 XXH_ASSERT(secret != NULL);
4716 XXH_ASSERT(9 <= len && len <= 16);
4717 { xxh_u64 const bitflip1 = (XXH_readLE64(secret+24) ^ XXH_readLE64(secret+32)) + seed;
4718 xxh_u64 const bitflip2 = (XXH_readLE64(secret+40) ^ XXH_readLE64(secret+48)) - seed;
4719 xxh_u64 const input_lo = XXH_readLE64(input) ^ bitflip1;
4720 xxh_u64 const input_hi = XXH_readLE64(input + len - 8) ^ bitflip2;
4721 xxh_u64 const acc = len
4722 + XXH_swap64(input_lo) + input_hi
4723 + XXH3_mul128_fold64(input_lo, input_hi);
4724 return XXH3_avalanche(acc);
4725 }
4726}
4727
4728XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t
4729XXH3_len_0to16_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed)
4730{
4731 XXH_ASSERT(len <= 16);
4732 { if (XXH_likely(len > 8)) return XXH3_len_9to16_64b(input, len, secret, seed);
4733 if (XXH_likely(len >= 4)) return XXH3_len_4to8_64b(input, len, secret, seed);
4734 if (len) return XXH3_len_1to3_64b(input, len, secret, seed);
4735 return XXH64_avalanche(seed ^ (XXH_readLE64(secret+56) ^ XXH_readLE64(secret+64)));
4736 }
4737}
4738
4739/*
4740 * DISCLAIMER: There are known *seed-dependent* multicollisions here due to
4741 * multiplication by zero, affecting hashes of lengths 17 to 240.
4742 *
4743 * However, they are very unlikely.
4744 *
4745 * Keep this in mind when using the unseeded XXH3_64bits() variant: As with all
4746 * unseeded non-cryptographic hashes, it does not attempt to defend itself
4747 * against specially crafted inputs, only random inputs.
4748 *
4749 * Compared to classic UMAC where a 1 in 2^31 chance of 4 consecutive bytes
4750 * cancelling out the secret is taken an arbitrary number of times (addressed
4751 * in XXH3_accumulate_512), this collision is very unlikely with random inputs
4752 * and/or proper seeding:
4753 *
4754 * This only has a 1 in 2^63 chance of 8 consecutive bytes cancelling out, in a
4755 * function that is only called up to 16 times per hash with up to 240 bytes of
4756 * input.
4757 *
4758 * This is not too bad for a non-cryptographic hash function, especially with
4759 * only 64 bit outputs.
4760 *
4761 * The 128-bit variant (which trades some speed for strength) is NOT affected
4762 * by this, although it is always a good idea to use a proper seed if you care
4763 * about strength.
4764 */
4765XXH_FORCE_INLINE xxh_u64 XXH3_mix16B(const xxh_u8* XXH_RESTRICT input,
4766 const xxh_u8* XXH_RESTRICT secret, xxh_u64 seed64)
4767{
4768#if defined(__GNUC__) && !defined(__clang__) /* GCC, not Clang */ \
4769 && defined(__i386__) && defined(__SSE2__) /* x86 + SSE2 */ \
4770 && !defined(XXH_ENABLE_AUTOVECTORIZE) /* Define to disable like XXH32 hack */
4771 /*
4772 * UGLY HACK:
4773 * GCC for x86 tends to autovectorize the 128-bit multiply, resulting in
4774 * slower code.
4775 *
4776 * By forcing seed64 into a register, we disrupt the cost model and
4777 * cause it to scalarize. See `XXH32_round()`
4778 *
4779 * FIXME: Clang's output is still _much_ faster -- On an AMD Ryzen 3600,
4780 * XXH3_64bits @ len=240 runs at 4.6 GB/s with Clang 9, but 3.3 GB/s on
4781 * GCC 9.2, despite both emitting scalar code.
4782 *
4783 * GCC generates much better scalar code than Clang for the rest of XXH3,
4784 * which is why finding a more optimal codepath is an interest.
4785 */
4786 XXH_COMPILER_GUARD(seed64);
4787#endif
4788 { xxh_u64 const input_lo = XXH_readLE64(input);
4789 xxh_u64 const input_hi = XXH_readLE64(input+8);
4790 return XXH3_mul128_fold64(
4791 input_lo ^ (XXH_readLE64(secret) + seed64),
4792 input_hi ^ (XXH_readLE64(secret+8) - seed64)
4793 );
4794 }
4795}
4796
4797/* For mid range keys, XXH3 uses a Mum-hash variant. */
4798XXH_FORCE_INLINE XXH_PUREF XXH64_hash_t
4799XXH3_len_17to128_64b(const xxh_u8* XXH_RESTRICT input, size_t len,
4800 const xxh_u8* XXH_RESTRICT secret, size_t secretSize,
4801 XXH64_hash_t seed)
4802{
4803 XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize;
4804 XXH_ASSERT(16 < len && len <= 128);
4805
4806 { xxh_u64 acc = len * XXH_PRIME64_1;
4807#if XXH_SIZE_OPT >= 1
4808 /* Smaller and cleaner, but slightly slower. */
4809 unsigned int i = (unsigned int)(len - 1) / 32;
4810 do {
4811 acc += XXH3_mix16B(input+16 * i, secret+32*i, seed);
4812 acc += XXH3_mix16B(input+len-16*(i+1), secret+32*i+16, seed);
4813 } while (i-- != 0);
4814#else
4815 if (len > 32) {
4816 if (len > 64) {
4817 if (len > 96) {
4818 acc += XXH3_mix16B(input+48, secret+96, seed);
4819 acc += XXH3_mix16B(input+len-64, secret+112, seed);
4820 }
4821 acc += XXH3_mix16B(input+32, secret+64, seed);
4822 acc += XXH3_mix16B(input+len-48, secret+80, seed);
4823 }
4824 acc += XXH3_mix16B(input+16, secret+32, seed);
4825 acc += XXH3_mix16B(input+len-32, secret+48, seed);
4826 }
4827 acc += XXH3_mix16B(input+0, secret+0, seed);
4828 acc += XXH3_mix16B(input+len-16, secret+16, seed);
4829#endif
4830 return XXH3_avalanche(acc);
4831 }
4832}
4833
4834XXH_NO_INLINE XXH_PUREF XXH64_hash_t
4835XXH3_len_129to240_64b(const xxh_u8* XXH_RESTRICT input, size_t len,
4836 const xxh_u8* XXH_RESTRICT secret, size_t secretSize,
4837 XXH64_hash_t seed)
4838{
4839 XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize;
4840 XXH_ASSERT(128 < len && len <= XXH3_MIDSIZE_MAX);
4841
4842 #define XXH3_MIDSIZE_STARTOFFSET 3
4843 #define XXH3_MIDSIZE_LASTOFFSET 17
4844
4845 { xxh_u64 acc = len * XXH_PRIME64_1;
4846 xxh_u64 acc_end;
4847 unsigned int const nbRounds = (unsigned int)len / 16;
4848 unsigned int i;
4849 XXH_ASSERT(128 < len && len <= XXH3_MIDSIZE_MAX);
4850 for (i=0; i<8; i++) {
4851 acc += XXH3_mix16B(input+(16*i), secret+(16*i), seed);
4852 }
4853 /* last bytes */
4854 acc_end = XXH3_mix16B(input + len - 16, secret + XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET, seed);
4855 XXH_ASSERT(nbRounds >= 8);
4856 acc = XXH3_avalanche(acc);
4857#if defined(__clang__) /* Clang */ \
4858 && (defined(__ARM_NEON) || defined(__ARM_NEON__)) /* NEON */ \
4859 && !defined(XXH_ENABLE_AUTOVECTORIZE) /* Define to disable */
4860 /*
4861 * UGLY HACK:
4862 * Clang for ARMv7-A tries to vectorize this loop, similar to GCC x86.
4863 * In everywhere else, it uses scalar code.
4864 *
4865 * For 64->128-bit multiplies, even if the NEON was 100% optimal, it
4866 * would still be slower than UMAAL (see XXH_mult64to128).
4867 *
4868 * Unfortunately, Clang doesn't handle the long multiplies properly and
4869 * converts them to the nonexistent "vmulq_u64" intrinsic, which is then
4870 * scalarized into an ugly mess of VMOV.32 instructions.
4871 *
4872 * This mess is difficult to avoid without turning autovectorization
4873 * off completely, but they are usually relatively minor and/or not
4874 * worth it to fix.
4875 *
4876 * This loop is the easiest to fix, as unlike XXH32, this pragma
4877 * _actually works_ because it is a loop vectorization instead of an
4878 * SLP vectorization.
4879 */
4880 #pragma clang loop vectorize(disable)
4881#endif
4882 for (i=8 ; i < nbRounds; i++) {
4883 /*
4884 * Prevents clang for unrolling the acc loop and interleaving with this one.
4885 */
4886 XXH_COMPILER_GUARD(acc);
4887 acc_end += XXH3_mix16B(input+(16*i), secret+(16*(i-8)) + XXH3_MIDSIZE_STARTOFFSET, seed);
4888 }
4889 return XXH3_avalanche(acc + acc_end);
4890 }
4891}
4892
4893
4894/* ======= Long Keys ======= */
4895
4896#define XXH_STRIPE_LEN 64
4897#define XXH_SECRET_CONSUME_RATE 8 /* nb of secret bytes consumed at each accumulation */
4898#define XXH_ACC_NB (XXH_STRIPE_LEN / sizeof(xxh_u64))
4899
4900#ifdef XXH_OLD_NAMES
4901# define STRIPE_LEN XXH_STRIPE_LEN
4902# define ACC_NB XXH_ACC_NB
4903#endif
4904
4905#ifndef XXH_PREFETCH_DIST
4906# ifdef __clang__
4907# define XXH_PREFETCH_DIST 320
4908# else
4909# if (XXH_VECTOR == XXH_AVX512)
4910# define XXH_PREFETCH_DIST 512
4911# else
4912# define XXH_PREFETCH_DIST 384
4913# endif
4914# endif /* __clang__ */
4915#endif /* XXH_PREFETCH_DIST */
4916
4917/*
4918 * These macros are to generate an XXH3_accumulate() function.
4919 * The two arguments select the name suffix and target attribute.
4920 *
4921 * The name of this symbol is XXH3_accumulate_<name>() and it calls
4922 * XXH3_accumulate_512_<name>().
4923 *
4924 * It may be useful to hand implement this function if the compiler fails to
4925 * optimize the inline function.
4926 */
4927#define XXH3_ACCUMULATE_TEMPLATE(name) \
4928void \
4929XXH3_accumulate_##name(xxh_u64* XXH_RESTRICT acc, \
4930 const xxh_u8* XXH_RESTRICT input, \
4931 const xxh_u8* XXH_RESTRICT secret, \
4932 size_t nbStripes) \
4933{ \
4934 size_t n; \
4935 for (n = 0; n < nbStripes; n++ ) { \
4936 const xxh_u8* const in = input + n*XXH_STRIPE_LEN; \
4937 XXH_PREFETCH(in + XXH_PREFETCH_DIST); \
4938 XXH3_accumulate_512_##name( \
4939 acc, \
4940 in, \
4941 secret + n*XXH_SECRET_CONSUME_RATE); \
4942 } \
4943}
4944
4945
4946XXH_FORCE_INLINE void XXH_writeLE64(void* dst, xxh_u64 v64)
4947{
4948 if (!XXH_CPU_LITTLE_ENDIAN) v64 = XXH_swap64(v64);
4949 XXH_memcpy(dst, &v64, sizeof(v64));
4950}
4951
4952/* Several intrinsic functions below are supposed to accept __int64 as argument,
4953 * as documented in https://software.intel.com/sites/landingpage/IntrinsicsGuide/ .
4954 * However, several environments do not define __int64 type,
4955 * requiring a workaround.
4956 */
4957#if !defined (__VMS) \
4958 && (defined (__cplusplus) \
4959 || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
4960 typedef int64_t xxh_i64;
4961#else
4962 /* the following type must have a width of 64-bit */
4963 typedef long long xxh_i64;
4964#endif
4965
4966
4967/*
4968 * XXH3_accumulate_512 is the tightest loop for long inputs, and it is the most optimized.
4969 *
4970 * It is a hardened version of UMAC, based off of FARSH's implementation.
4971 *
4972 * This was chosen because it adapts quite well to 32-bit, 64-bit, and SIMD
4973 * implementations, and it is ridiculously fast.
4974 *
4975 * We harden it by mixing the original input to the accumulators as well as the product.
4976 *
4977 * This means that in the (relatively likely) case of a multiply by zero, the
4978 * original input is preserved.
4979 *
4980 * On 128-bit inputs, we swap 64-bit pairs when we add the input to improve
4981 * cross-pollination, as otherwise the upper and lower halves would be
4982 * essentially independent.
4983 *
4984 * This doesn't matter on 64-bit hashes since they all get merged together in
4985 * the end, so we skip the extra step.
4986 *
4987 * Both XXH3_64bits and XXH3_128bits use this subroutine.
4988 */
4989
4990#if (XXH_VECTOR == XXH_AVX512) \
4991 || (defined(XXH_DISPATCH_AVX512) && XXH_DISPATCH_AVX512 != 0)
4992
4993#ifndef XXH_TARGET_AVX512
4994# define XXH_TARGET_AVX512 /* disable attribute target */
4995#endif
4996
4997XXH_FORCE_INLINE XXH_TARGET_AVX512 void
4998XXH3_accumulate_512_avx512(void* XXH_RESTRICT acc,
4999 const void* XXH_RESTRICT input,
5000 const void* XXH_RESTRICT secret)
5001{
5002 __m512i* const xacc = (__m512i *) acc;
5003 XXH_ASSERT((((size_t)acc) & 63) == 0);
5004 XXH_STATIC_ASSERT(XXH_STRIPE_LEN == sizeof(__m512i));
5005
5006 {
5007 /* data_vec = input[0]; */
5008 __m512i const data_vec = _mm512_loadu_si512 (input);
5009 /* key_vec = secret[0]; */
5010 __m512i const key_vec = _mm512_loadu_si512 (secret);
5011 /* data_key = data_vec ^ key_vec; */
5012 __m512i const data_key = _mm512_xor_si512 (data_vec, key_vec);
5013 /* data_key_lo = data_key >> 32; */
5014 __m512i const data_key_lo = _mm512_srli_epi64 (data_key, 32);
5015 /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */
5016 __m512i const product = _mm512_mul_epu32 (data_key, data_key_lo);
5017 /* xacc[0] += swap(data_vec); */
5018 __m512i const data_swap = _mm512_shuffle_epi32(data_vec, (_MM_PERM_ENUM)_MM_SHUFFLE(1, 0, 3, 2));
5019 __m512i const sum = _mm512_add_epi64(*xacc, data_swap);
5020 /* xacc[0] += product; */
5021 *xacc = _mm512_add_epi64(product, sum);
5022 }
5023}
5024XXH_FORCE_INLINE XXH_TARGET_AVX512 XXH3_ACCUMULATE_TEMPLATE(avx512)
5025
5026/*
5027 * XXH3_scrambleAcc: Scrambles the accumulators to improve mixing.
5028 *
5029 * Multiplication isn't perfect, as explained by Google in HighwayHash:
5030 *
5031 * // Multiplication mixes/scrambles bytes 0-7 of the 64-bit result to
5032 * // varying degrees. In descending order of goodness, bytes
5033 * // 3 4 2 5 1 6 0 7 have quality 228 224 164 160 100 96 36 32.
5034 * // As expected, the upper and lower bytes are much worse.
5035 *
5036 * Source: https://github.com/google/highwayhash/blob/0aaf66b/highwayhash/hh_avx2.h#L291
5037 *
5038 * Since our algorithm uses a pseudorandom secret to add some variance into the
5039 * mix, we don't need to (or want to) mix as often or as much as HighwayHash does.
5040 *
5041 * This isn't as tight as XXH3_accumulate, but still written in SIMD to avoid
5042 * extraction.
5043 *
5044 * Both XXH3_64bits and XXH3_128bits use this subroutine.
5045 */
5046
5047XXH_FORCE_INLINE XXH_TARGET_AVX512 void
5048XXH3_scrambleAcc_avx512(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret)
5049{
5050 XXH_ASSERT((((size_t)acc) & 63) == 0);
5051 XXH_STATIC_ASSERT(XXH_STRIPE_LEN == sizeof(__m512i));
5052 { __m512i* const xacc = (__m512i*) acc;
5053 const __m512i prime32 = _mm512_set1_epi32((int)XXH_PRIME32_1);
5054
5055 /* xacc[0] ^= (xacc[0] >> 47) */
5056 __m512i const acc_vec = *xacc;
5057 __m512i const shifted = _mm512_srli_epi64 (acc_vec, 47);
5058 /* xacc[0] ^= secret; */
5059 __m512i const key_vec = _mm512_loadu_si512 (secret);
5060 __m512i const data_key = _mm512_ternarylogic_epi32(key_vec, acc_vec, shifted, 0x96 /* key_vec ^ acc_vec ^ shifted */);
5061
5062 /* xacc[0] *= XXH_PRIME32_1; */
5063 __m512i const data_key_hi = _mm512_srli_epi64 (data_key, 32);
5064 __m512i const prod_lo = _mm512_mul_epu32 (data_key, prime32);
5065 __m512i const prod_hi = _mm512_mul_epu32 (data_key_hi, prime32);
5066 *xacc = _mm512_add_epi64(prod_lo, _mm512_slli_epi64(prod_hi, 32));
5067 }
5068}
5069
5070XXH_FORCE_INLINE XXH_TARGET_AVX512 void
5071XXH3_initCustomSecret_avx512(void* XXH_RESTRICT customSecret, xxh_u64 seed64)
5072{
5073 XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 63) == 0);
5074 XXH_STATIC_ASSERT(XXH_SEC_ALIGN == 64);
5075 XXH_ASSERT(((size_t)customSecret & 63) == 0);
5076 (void)(&XXH_writeLE64);
5077 { int const nbRounds = XXH_SECRET_DEFAULT_SIZE / sizeof(__m512i);
5078 __m512i const seed_pos = _mm512_set1_epi64((xxh_i64)seed64);
5079 __m512i const seed = _mm512_mask_sub_epi64(seed_pos, 0xAA, _mm512_set1_epi8(0), seed_pos);
5080
5081 const __m512i* const src = (const __m512i*) ((const void*) XXH3_kSecret);
5082 __m512i* const dest = ( __m512i*) customSecret;
5083 int i;
5084 XXH_ASSERT(((size_t)src & 63) == 0); /* control alignment */
5085 XXH_ASSERT(((size_t)dest & 63) == 0);
5086 for (i=0; i < nbRounds; ++i) {
5087 dest[i] = _mm512_add_epi64(_mm512_load_si512(src + i), seed);
5088 } }
5089}
5090
5091#endif
5092
5093#if (XXH_VECTOR == XXH_AVX2) \
5094 || (defined(XXH_DISPATCH_AVX2) && XXH_DISPATCH_AVX2 != 0)
5095
5096#ifndef XXH_TARGET_AVX2
5097# define XXH_TARGET_AVX2 /* disable attribute target */
5098#endif
5099
5100XXH_FORCE_INLINE XXH_TARGET_AVX2 void
5101XXH3_accumulate_512_avx2( void* XXH_RESTRICT acc,
5102 const void* XXH_RESTRICT input,
5103 const void* XXH_RESTRICT secret)
5104{
5105 XXH_ASSERT((((size_t)acc) & 31) == 0);
5106 { __m256i* const xacc = (__m256i *) acc;
5107 /* Unaligned. This is mainly for pointer arithmetic, and because
5108 * _mm256_loadu_si256 requires a const __m256i * pointer for some reason. */
5109 const __m256i* const xinput = (const __m256i *) input;
5110 /* Unaligned. This is mainly for pointer arithmetic, and because
5111 * _mm256_loadu_si256 requires a const __m256i * pointer for some reason. */
5112 const __m256i* const xsecret = (const __m256i *) secret;
5113
5114 size_t i;
5115 for (i=0; i < XXH_STRIPE_LEN/sizeof(__m256i); i++) {
5116 /* data_vec = xinput[i]; */
5117 __m256i const data_vec = _mm256_loadu_si256 (xinput+i);
5118 /* key_vec = xsecret[i]; */
5119 __m256i const key_vec = _mm256_loadu_si256 (xsecret+i);
5120 /* data_key = data_vec ^ key_vec; */
5121 __m256i const data_key = _mm256_xor_si256 (data_vec, key_vec);
5122 /* data_key_lo = data_key >> 32; */
5123 __m256i const data_key_lo = _mm256_srli_epi64 (data_key, 32);
5124 /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */
5125 __m256i const product = _mm256_mul_epu32 (data_key, data_key_lo);
5126 /* xacc[i] += swap(data_vec); */
5127 __m256i const data_swap = _mm256_shuffle_epi32(data_vec, _MM_SHUFFLE(1, 0, 3, 2));
5128 __m256i const sum = _mm256_add_epi64(xacc[i], data_swap);
5129 /* xacc[i] += product; */
5130 xacc[i] = _mm256_add_epi64(product, sum);
5131 } }
5132}
5133XXH_FORCE_INLINE XXH_TARGET_AVX2 XXH3_ACCUMULATE_TEMPLATE(avx2)
5134
5135XXH_FORCE_INLINE XXH_TARGET_AVX2 void
5136XXH3_scrambleAcc_avx2(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret)
5137{
5138 XXH_ASSERT((((size_t)acc) & 31) == 0);
5139 { __m256i* const xacc = (__m256i*) acc;
5140 /* Unaligned. This is mainly for pointer arithmetic, and because
5141 * _mm256_loadu_si256 requires a const __m256i * pointer for some reason. */
5142 const __m256i* const xsecret = (const __m256i *) secret;
5143 const __m256i prime32 = _mm256_set1_epi32((int)XXH_PRIME32_1);
5144
5145 size_t i;
5146 for (i=0; i < XXH_STRIPE_LEN/sizeof(__m256i); i++) {
5147 /* xacc[i] ^= (xacc[i] >> 47) */
5148 __m256i const acc_vec = xacc[i];
5149 __m256i const shifted = _mm256_srli_epi64 (acc_vec, 47);
5150 __m256i const data_vec = _mm256_xor_si256 (acc_vec, shifted);
5151 /* xacc[i] ^= xsecret; */
5152 __m256i const key_vec = _mm256_loadu_si256 (xsecret+i);
5153 __m256i const data_key = _mm256_xor_si256 (data_vec, key_vec);
5154
5155 /* xacc[i] *= XXH_PRIME32_1; */
5156 __m256i const data_key_hi = _mm256_srli_epi64 (data_key, 32);
5157 __m256i const prod_lo = _mm256_mul_epu32 (data_key, prime32);
5158 __m256i const prod_hi = _mm256_mul_epu32 (data_key_hi, prime32);
5159 xacc[i] = _mm256_add_epi64(prod_lo, _mm256_slli_epi64(prod_hi, 32));
5160 }
5161 }
5162}
5163
5164XXH_FORCE_INLINE XXH_TARGET_AVX2 void XXH3_initCustomSecret_avx2(void* XXH_RESTRICT customSecret, xxh_u64 seed64)
5165{
5166 XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 31) == 0);
5167 XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE / sizeof(__m256i)) == 6);
5168 XXH_STATIC_ASSERT(XXH_SEC_ALIGN <= 64);
5169 (void)(&XXH_writeLE64);
5170 XXH_PREFETCH(customSecret);
5171 { __m256i const seed = _mm256_set_epi64x((xxh_i64)(0U - seed64), (xxh_i64)seed64, (xxh_i64)(0U - seed64), (xxh_i64)seed64);
5172
5173 const __m256i* const src = (const __m256i*) ((const void*) XXH3_kSecret);
5174 __m256i* dest = ( __m256i*) customSecret;
5175
5176# if defined(__GNUC__) || defined(__clang__)
5177 /*
5178 * On GCC & Clang, marking 'dest' as modified will cause the compiler:
5179 * - do not extract the secret from sse registers in the internal loop
5180 * - use less common registers, and avoid pushing these reg into stack
5181 */
5182 XXH_COMPILER_GUARD(dest);
5183# endif
5184 XXH_ASSERT(((size_t)src & 31) == 0); /* control alignment */
5185 XXH_ASSERT(((size_t)dest & 31) == 0);
5186
5187 /* GCC -O2 need unroll loop manually */
5188 dest[0] = _mm256_add_epi64(_mm256_load_si256(src+0), seed);
5189 dest[1] = _mm256_add_epi64(_mm256_load_si256(src+1), seed);
5190 dest[2] = _mm256_add_epi64(_mm256_load_si256(src+2), seed);
5191 dest[3] = _mm256_add_epi64(_mm256_load_si256(src+3), seed);
5192 dest[4] = _mm256_add_epi64(_mm256_load_si256(src+4), seed);
5193 dest[5] = _mm256_add_epi64(_mm256_load_si256(src+5), seed);
5194 }
5195}
5196
5197#endif
5198
5199/* x86dispatch always generates SSE2 */
5200#if (XXH_VECTOR == XXH_SSE2) || defined(XXH_X86DISPATCH)
5201
5202#ifndef XXH_TARGET_SSE2
5203# define XXH_TARGET_SSE2 /* disable attribute target */
5204#endif
5205
5206XXH_FORCE_INLINE XXH_TARGET_SSE2 void
5207XXH3_accumulate_512_sse2( void* XXH_RESTRICT acc,
5208 const void* XXH_RESTRICT input,
5209 const void* XXH_RESTRICT secret)
5210{
5211 /* SSE2 is just a half-scale version of the AVX2 version. */
5212 XXH_ASSERT((((size_t)acc) & 15) == 0);
5213 { __m128i* const xacc = (__m128i *) acc;
5214 /* Unaligned. This is mainly for pointer arithmetic, and because
5215 * _mm_loadu_si128 requires a const __m128i * pointer for some reason. */
5216 const __m128i* const xinput = (const __m128i *) input;
5217 /* Unaligned. This is mainly for pointer arithmetic, and because
5218 * _mm_loadu_si128 requires a const __m128i * pointer for some reason. */
5219 const __m128i* const xsecret = (const __m128i *) secret;
5220
5221 size_t i;
5222 for (i=0; i < XXH_STRIPE_LEN/sizeof(__m128i); i++) {
5223 /* data_vec = xinput[i]; */
5224 __m128i const data_vec = _mm_loadu_si128 (xinput+i);
5225 /* key_vec = xsecret[i]; */
5226 __m128i const key_vec = _mm_loadu_si128 (xsecret+i);
5227 /* data_key = data_vec ^ key_vec; */
5228 __m128i const data_key = _mm_xor_si128 (data_vec, key_vec);
5229 /* data_key_lo = data_key >> 32; */
5230 __m128i const data_key_lo = _mm_shuffle_epi32 (data_key, _MM_SHUFFLE(0, 3, 0, 1));
5231 /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */
5232 __m128i const product = _mm_mul_epu32 (data_key, data_key_lo);
5233 /* xacc[i] += swap(data_vec); */
5234 __m128i const data_swap = _mm_shuffle_epi32(data_vec, _MM_SHUFFLE(1,0,3,2));
5235 __m128i const sum = _mm_add_epi64(xacc[i], data_swap);
5236 /* xacc[i] += product; */
5237 xacc[i] = _mm_add_epi64(product, sum);
5238 } }
5239}
5240XXH_FORCE_INLINE XXH_TARGET_SSE2 XXH3_ACCUMULATE_TEMPLATE(sse2)
5241
5242XXH_FORCE_INLINE XXH_TARGET_SSE2 void
5243XXH3_scrambleAcc_sse2(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret)
5244{
5245 XXH_ASSERT((((size_t)acc) & 15) == 0);
5246 { __m128i* const xacc = (__m128i*) acc;
5247 /* Unaligned. This is mainly for pointer arithmetic, and because
5248 * _mm_loadu_si128 requires a const __m128i * pointer for some reason. */
5249 const __m128i* const xsecret = (const __m128i *) secret;
5250 const __m128i prime32 = _mm_set1_epi32((int)XXH_PRIME32_1);
5251
5252 size_t i;
5253 for (i=0; i < XXH_STRIPE_LEN/sizeof(__m128i); i++) {
5254 /* xacc[i] ^= (xacc[i] >> 47) */
5255 __m128i const acc_vec = xacc[i];
5256 __m128i const shifted = _mm_srli_epi64 (acc_vec, 47);
5257 __m128i const data_vec = _mm_xor_si128 (acc_vec, shifted);
5258 /* xacc[i] ^= xsecret[i]; */
5259 __m128i const key_vec = _mm_loadu_si128 (xsecret+i);
5260 __m128i const data_key = _mm_xor_si128 (data_vec, key_vec);
5261
5262 /* xacc[i] *= XXH_PRIME32_1; */
5263 __m128i const data_key_hi = _mm_shuffle_epi32 (data_key, _MM_SHUFFLE(0, 3, 0, 1));
5264 __m128i const prod_lo = _mm_mul_epu32 (data_key, prime32);
5265 __m128i const prod_hi = _mm_mul_epu32 (data_key_hi, prime32);
5266 xacc[i] = _mm_add_epi64(prod_lo, _mm_slli_epi64(prod_hi, 32));
5267 }
5268 }
5269}
5270
5271XXH_FORCE_INLINE XXH_TARGET_SSE2 void XXH3_initCustomSecret_sse2(void* XXH_RESTRICT customSecret, xxh_u64 seed64)
5272{
5273 XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 15) == 0);
5274 (void)(&XXH_writeLE64);
5275 { int const nbRounds = XXH_SECRET_DEFAULT_SIZE / sizeof(__m128i);
5276
5277# if defined(_MSC_VER) && defined(_M_IX86) && _MSC_VER <= 1900
5278 /* MSVC 32bit mode does not support _mm_set_epi64x before 2015
5279 * and some specific variants of 2015 may also lack it */
5280 /* Cast to unsigned 64-bit first to avoid signed arithmetic issues */
5281 xxh_u64 const seed64_unsigned = (xxh_u64)seed64;
5282 xxh_u64 const neg_seed64 = (xxh_u64)(0ULL - seed64_unsigned);
5283 __m128i const seed = _mm_set_epi32(
5284 (int)(neg_seed64 >> 32), /* high 32 bits of negated seed */
5285 (int)(neg_seed64), /* low 32 bits of negated seed */
5286 (int)(seed64_unsigned >> 32), /* high 32 bits of original seed */
5287 (int)(seed64_unsigned) /* low 32 bits of original seed */
5288 );
5289# else
5290 __m128i const seed = _mm_set_epi64x((xxh_i64)(0U - seed64), (xxh_i64)seed64);
5291# endif
5292 int i;
5293
5294 const void* const src16 = XXH3_kSecret;
5295 __m128i* dst16 = (__m128i*) customSecret;
5296# if defined(__GNUC__) || defined(__clang__)
5297 /*
5298 * On GCC & Clang, marking 'dest' as modified will cause the compiler:
5299 * - do not extract the secret from sse registers in the internal loop
5300 * - use less common registers, and avoid pushing these reg into stack
5301 */
5302 XXH_COMPILER_GUARD(dst16);
5303# endif
5304 XXH_ASSERT(((size_t)src16 & 15) == 0); /* control alignment */
5305 XXH_ASSERT(((size_t)dst16 & 15) == 0);
5306
5307 for (i=0; i < nbRounds; ++i) {
5308 dst16[i] = _mm_add_epi64(_mm_load_si128((const __m128i *)src16+i), seed);
5309 } }
5310}
5311
5312#endif
5313
5314#if (XXH_VECTOR == XXH_NEON)
5315
5316/* forward declarations for the scalar routines */
5317XXH_FORCE_INLINE void
5318XXH3_scalarRound(void* XXH_RESTRICT acc, void const* XXH_RESTRICT input,
5319 void const* XXH_RESTRICT secret, size_t lane);
5320
5321XXH_FORCE_INLINE void
5322XXH3_scalarScrambleRound(void* XXH_RESTRICT acc,
5323 void const* XXH_RESTRICT secret, size_t lane);
5324
5349XXH_FORCE_INLINE void
5350XXH3_accumulate_512_neon( void* XXH_RESTRICT acc,
5351 const void* XXH_RESTRICT input,
5352 const void* XXH_RESTRICT secret)
5353{
5354 XXH_ASSERT((((size_t)acc) & 15) == 0);
5355 XXH_STATIC_ASSERT(XXH3_NEON_LANES > 0 && XXH3_NEON_LANES <= XXH_ACC_NB && XXH3_NEON_LANES % 2 == 0);
5356 { /* GCC for darwin arm64 does not like aliasing here */
5357 xxh_aliasing_uint64x2_t* const xacc = (xxh_aliasing_uint64x2_t*) acc;
5358 /* We don't use a uint32x4_t pointer because it causes bus errors on ARMv7. */
5359 uint8_t const* xinput = (const uint8_t *) input;
5360 uint8_t const* xsecret = (const uint8_t *) secret;
5361
5362 size_t i;
5363#ifdef __wasm_simd128__
5364 /*
5365 * On WASM SIMD128, Clang emits direct address loads when XXH3_kSecret
5366 * is constant propagated, which results in it converting it to this
5367 * inside the loop:
5368 *
5369 * a = v128.load(XXH3_kSecret + 0 + $secret_offset, offset = 0)
5370 * b = v128.load(XXH3_kSecret + 16 + $secret_offset, offset = 0)
5371 * ...
5372 *
5373 * This requires a full 32-bit address immediate (and therefore a 6 byte
5374 * instruction) as well as an add for each offset.
5375 *
5376 * Putting an asm guard prevents it from folding (at the cost of losing
5377 * the alignment hint), and uses the free offset in `v128.load` instead
5378 * of adding secret_offset each time which overall reduces code size by
5379 * about a kilobyte and improves performance.
5380 */
5381 XXH_COMPILER_GUARD(xsecret);
5382#endif
5383 /* Scalar lanes use the normal scalarRound routine */
5384 for (i = XXH3_NEON_LANES; i < XXH_ACC_NB; i++) {
5385 XXH3_scalarRound(acc, input, secret, i);
5386 }
5387 i = 0;
5388 /* 4 NEON lanes at a time. */
5389 for (; i+1 < XXH3_NEON_LANES / 2; i+=2) {
5390 /* data_vec = xinput[i]; */
5391 uint64x2_t data_vec_1 = XXH_vld1q_u64(xinput + (i * 16));
5392 uint64x2_t data_vec_2 = XXH_vld1q_u64(xinput + ((i+1) * 16));
5393 /* key_vec = xsecret[i]; */
5394 uint64x2_t key_vec_1 = XXH_vld1q_u64(xsecret + (i * 16));
5395 uint64x2_t key_vec_2 = XXH_vld1q_u64(xsecret + ((i+1) * 16));
5396 /* data_swap = swap(data_vec) */
5397 uint64x2_t data_swap_1 = vextq_u64(data_vec_1, data_vec_1, 1);
5398 uint64x2_t data_swap_2 = vextq_u64(data_vec_2, data_vec_2, 1);
5399 /* data_key = data_vec ^ key_vec; */
5400 uint64x2_t data_key_1 = veorq_u64(data_vec_1, key_vec_1);
5401 uint64x2_t data_key_2 = veorq_u64(data_vec_2, key_vec_2);
5402
5403 /*
5404 * If we reinterpret the 64x2 vectors as 32x4 vectors, we can use a
5405 * de-interleave operation for 4 lanes in 1 step with `vuzpq_u32` to
5406 * get one vector with the low 32 bits of each lane, and one vector
5407 * with the high 32 bits of each lane.
5408 *
5409 * The intrinsic returns a double vector because the original ARMv7-a
5410 * instruction modified both arguments in place. AArch64 and SIMD128 emit
5411 * two instructions from this intrinsic.
5412 *
5413 * [ dk11L | dk11H | dk12L | dk12H ] -> [ dk11L | dk12L | dk21L | dk22L ]
5414 * [ dk21L | dk21H | dk22L | dk22H ] -> [ dk11H | dk12H | dk21H | dk22H ]
5415 */
5416 uint32x4x2_t unzipped = vuzpq_u32(
5417 vreinterpretq_u32_u64(data_key_1),
5418 vreinterpretq_u32_u64(data_key_2)
5419 );
5420 /* data_key_lo = data_key & 0xFFFFFFFF */
5421 uint32x4_t data_key_lo = unzipped.val[0];
5422 /* data_key_hi = data_key >> 32 */
5423 uint32x4_t data_key_hi = unzipped.val[1];
5424 /*
5425 * Then, we can split the vectors horizontally and multiply which, as for most
5426 * widening intrinsics, have a variant that works on both high half vectors
5427 * for free on AArch64. A similar instruction is available on SIMD128.
5428 *
5429 * sum = data_swap + (u64x2) data_key_lo * (u64x2) data_key_hi
5430 */
5431 uint64x2_t sum_1 = XXH_vmlal_low_u32(data_swap_1, data_key_lo, data_key_hi);
5432 uint64x2_t sum_2 = XXH_vmlal_high_u32(data_swap_2, data_key_lo, data_key_hi);
5433 /*
5434 * Clang reorders
5435 * a += b * c; // umlal swap.2d, dkl.2s, dkh.2s
5436 * c += a; // add acc.2d, acc.2d, swap.2d
5437 * to
5438 * c += a; // add acc.2d, acc.2d, swap.2d
5439 * c += b * c; // umlal acc.2d, dkl.2s, dkh.2s
5440 *
5441 * While it would make sense in theory since the addition is faster,
5442 * for reasons likely related to umlal being limited to certain NEON
5443 * pipelines, this is worse. A compiler guard fixes this.
5444 */
5445 XXH_COMPILER_GUARD_CLANG_NEON(sum_1);
5446 XXH_COMPILER_GUARD_CLANG_NEON(sum_2);
5447 /* xacc[i] = acc_vec + sum; */
5448 xacc[i] = vaddq_u64(xacc[i], sum_1);
5449 xacc[i+1] = vaddq_u64(xacc[i+1], sum_2);
5450 }
5451 /* Operate on the remaining NEON lanes 2 at a time. */
5452 for (; i < XXH3_NEON_LANES / 2; i++) {
5453 /* data_vec = xinput[i]; */
5454 uint64x2_t data_vec = XXH_vld1q_u64(xinput + (i * 16));
5455 /* key_vec = xsecret[i]; */
5456 uint64x2_t key_vec = XXH_vld1q_u64(xsecret + (i * 16));
5457 /* acc_vec_2 = swap(data_vec) */
5458 uint64x2_t data_swap = vextq_u64(data_vec, data_vec, 1);
5459 /* data_key = data_vec ^ key_vec; */
5460 uint64x2_t data_key = veorq_u64(data_vec, key_vec);
5461 /* For two lanes, just use VMOVN and VSHRN. */
5462 /* data_key_lo = data_key & 0xFFFFFFFF; */
5463 uint32x2_t data_key_lo = vmovn_u64(data_key);
5464 /* data_key_hi = data_key >> 32; */
5465 uint32x2_t data_key_hi = vshrn_n_u64(data_key, 32);
5466 /* sum = data_swap + (u64x2) data_key_lo * (u64x2) data_key_hi; */
5467 uint64x2_t sum = vmlal_u32(data_swap, data_key_lo, data_key_hi);
5468 /* Same Clang workaround as before */
5469 XXH_COMPILER_GUARD_CLANG_NEON(sum);
5470 /* xacc[i] = acc_vec + sum; */
5471 xacc[i] = vaddq_u64 (xacc[i], sum);
5472 }
5473 }
5474}
5475XXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(neon)
5476
5477XXH_FORCE_INLINE void
5478XXH3_scrambleAcc_neon(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret)
5479{
5480 XXH_ASSERT((((size_t)acc) & 15) == 0);
5481
5482 { xxh_aliasing_uint64x2_t* xacc = (xxh_aliasing_uint64x2_t*) acc;
5483 uint8_t const* xsecret = (uint8_t const*) secret;
5484
5485 size_t i;
5486 /* WASM uses operator overloads and doesn't need these. */
5487#ifndef __wasm_simd128__
5488 /* { prime32_1, prime32_1 } */
5489 uint32x2_t const kPrimeLo = vdup_n_u32(XXH_PRIME32_1);
5490 /* { 0, prime32_1, 0, prime32_1 } */
5491 uint32x4_t const kPrimeHi = vreinterpretq_u32_u64(vdupq_n_u64((xxh_u64)XXH_PRIME32_1 << 32));
5492#endif
5493
5494 /* AArch64 uses both scalar and neon at the same time */
5495 for (i = XXH3_NEON_LANES; i < XXH_ACC_NB; i++) {
5496 XXH3_scalarScrambleRound(acc, secret, i);
5497 }
5498 for (i=0; i < XXH3_NEON_LANES / 2; i++) {
5499 /* xacc[i] ^= (xacc[i] >> 47); */
5500 uint64x2_t acc_vec = xacc[i];
5501 uint64x2_t shifted = vshrq_n_u64(acc_vec, 47);
5502 uint64x2_t data_vec = veorq_u64(acc_vec, shifted);
5503
5504 /* xacc[i] ^= xsecret[i]; */
5505 uint64x2_t key_vec = XXH_vld1q_u64(xsecret + (i * 16));
5506 uint64x2_t data_key = veorq_u64(data_vec, key_vec);
5507 /* xacc[i] *= XXH_PRIME32_1 */
5508#ifdef __wasm_simd128__
5509 /* SIMD128 has multiply by u64x2, use it instead of expanding and scalarizing */
5510 xacc[i] = data_key * XXH_PRIME32_1;
5511#else
5512 /*
5513 * Expanded version with portable NEON intrinsics
5514 *
5515 * lo(x) * lo(y) + (hi(x) * lo(y) << 32)
5516 *
5517 * prod_hi = hi(data_key) * lo(prime) << 32
5518 *
5519 * Since we only need 32 bits of this multiply a trick can be used, reinterpreting the vector
5520 * as a uint32x4_t and multiplying by { 0, prime, 0, prime } to cancel out the unwanted bits
5521 * and avoid the shift.
5522 */
5523 uint32x4_t prod_hi = vmulq_u32 (vreinterpretq_u32_u64(data_key), kPrimeHi);
5524 /* Extract low bits for vmlal_u32 */
5525 uint32x2_t data_key_lo = vmovn_u64(data_key);
5526 /* xacc[i] = prod_hi + lo(data_key) * XXH_PRIME32_1; */
5527 xacc[i] = vmlal_u32(vreinterpretq_u64_u32(prod_hi), data_key_lo, kPrimeLo);
5528#endif
5529 }
5530 }
5531}
5532#endif
5533
5534#if (XXH_VECTOR == XXH_VSX)
5535
5536XXH_FORCE_INLINE void
5537XXH3_accumulate_512_vsx( void* XXH_RESTRICT acc,
5538 const void* XXH_RESTRICT input,
5539 const void* XXH_RESTRICT secret)
5540{
5541 /* presumed aligned */
5542 xxh_aliasing_u64x2* const xacc = (xxh_aliasing_u64x2*) acc;
5543 xxh_u8 const* const xinput = (xxh_u8 const*) input; /* no alignment restriction */
5544 xxh_u8 const* const xsecret = (xxh_u8 const*) secret; /* no alignment restriction */
5545 xxh_u64x2 const v32 = { 32, 32 };
5546 size_t i;
5547 for (i = 0; i < XXH_STRIPE_LEN / sizeof(xxh_u64x2); i++) {
5548 /* data_vec = xinput[i]; */
5549 xxh_u64x2 const data_vec = XXH_vec_loadu(xinput + 16*i);
5550 /* key_vec = xsecret[i]; */
5551 xxh_u64x2 const key_vec = XXH_vec_loadu(xsecret + 16*i);
5552 xxh_u64x2 const data_key = data_vec ^ key_vec;
5553 /* shuffled = (data_key << 32) | (data_key >> 32); */
5554 xxh_u32x4 const shuffled = (xxh_u32x4)vec_rl(data_key, v32);
5555 /* product = ((xxh_u64x2)data_key & 0xFFFFFFFF) * ((xxh_u64x2)shuffled & 0xFFFFFFFF); */
5556 xxh_u64x2 const product = XXH_vec_mulo((xxh_u32x4)data_key, shuffled);
5557 /* acc_vec = xacc[i]; */
5558 xxh_u64x2 acc_vec = xacc[i];
5559 acc_vec += product;
5560
5561 /* swap high and low halves */
5562#ifdef __s390x__
5563 acc_vec += vec_permi(data_vec, data_vec, 2);
5564#else
5565 acc_vec += vec_xxpermdi(data_vec, data_vec, 2);
5566#endif
5567 xacc[i] = acc_vec;
5568 }
5569}
5570XXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(vsx)
5571
5572XXH_FORCE_INLINE void
5573XXH3_scrambleAcc_vsx(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret)
5574{
5575 XXH_ASSERT((((size_t)acc) & 15) == 0);
5576
5577 { xxh_aliasing_u64x2* const xacc = (xxh_aliasing_u64x2*) acc;
5578 const xxh_u8* const xsecret = (const xxh_u8*) secret;
5579 /* constants */
5580 xxh_u64x2 const v32 = { 32, 32 };
5581 xxh_u64x2 const v47 = { 47, 47 };
5582 xxh_u32x4 const prime = { XXH_PRIME32_1, XXH_PRIME32_1, XXH_PRIME32_1, XXH_PRIME32_1 };
5583 size_t i;
5584 for (i = 0; i < XXH_STRIPE_LEN / sizeof(xxh_u64x2); i++) {
5585 /* xacc[i] ^= (xacc[i] >> 47); */
5586 xxh_u64x2 const acc_vec = xacc[i];
5587 xxh_u64x2 const data_vec = acc_vec ^ (acc_vec >> v47);
5588
5589 /* xacc[i] ^= xsecret[i]; */
5590 xxh_u64x2 const key_vec = XXH_vec_loadu(xsecret + 16*i);
5591 xxh_u64x2 const data_key = data_vec ^ key_vec;
5592
5593 /* xacc[i] *= XXH_PRIME32_1 */
5594 /* prod_lo = ((xxh_u64x2)data_key & 0xFFFFFFFF) * ((xxh_u64x2)prime & 0xFFFFFFFF); */
5595 xxh_u64x2 const prod_even = XXH_vec_mule((xxh_u32x4)data_key, prime);
5596 /* prod_hi = ((xxh_u64x2)data_key >> 32) * ((xxh_u64x2)prime >> 32); */
5597 xxh_u64x2 const prod_odd = XXH_vec_mulo((xxh_u32x4)data_key, prime);
5598 xacc[i] = prod_odd + (prod_even << v32);
5599 } }
5600}
5601
5602#endif
5603
5604#if (XXH_VECTOR == XXH_SVE)
5605
5606XXH_FORCE_INLINE void
5607XXH3_accumulate_512_sve( void* XXH_RESTRICT acc,
5608 const void* XXH_RESTRICT input,
5609 const void* XXH_RESTRICT secret)
5610{
5611 uint64_t *xacc = (uint64_t *)acc;
5612 const uint64_t *xinput = (const uint64_t *)(const void *)input;
5613 const uint64_t *xsecret = (const uint64_t *)(const void *)secret;
5614 svuint64_t kSwap = sveor_n_u64_z(svptrue_b64(), svindex_u64(0, 1), 1);
5615 uint64_t element_count = svcntd();
5616 if (element_count >= 8) {
5617 svbool_t mask = svptrue_pat_b64(SV_VL8);
5618 svuint64_t vacc = svld1_u64(mask, xacc);
5619 ACCRND(vacc, 0);
5620 svst1_u64(mask, xacc, vacc);
5621 } else if (element_count == 2) { /* sve128 */
5622 svbool_t mask = svptrue_pat_b64(SV_VL2);
5623 svuint64_t acc0 = svld1_u64(mask, xacc + 0);
5624 svuint64_t acc1 = svld1_u64(mask, xacc + 2);
5625 svuint64_t acc2 = svld1_u64(mask, xacc + 4);
5626 svuint64_t acc3 = svld1_u64(mask, xacc + 6);
5627 ACCRND(acc0, 0);
5628 ACCRND(acc1, 2);
5629 ACCRND(acc2, 4);
5630 ACCRND(acc3, 6);
5631 svst1_u64(mask, xacc + 0, acc0);
5632 svst1_u64(mask, xacc + 2, acc1);
5633 svst1_u64(mask, xacc + 4, acc2);
5634 svst1_u64(mask, xacc + 6, acc3);
5635 } else {
5636 svbool_t mask = svptrue_pat_b64(SV_VL4);
5637 svuint64_t acc0 = svld1_u64(mask, xacc + 0);
5638 svuint64_t acc1 = svld1_u64(mask, xacc + 4);
5639 ACCRND(acc0, 0);
5640 ACCRND(acc1, 4);
5641 svst1_u64(mask, xacc + 0, acc0);
5642 svst1_u64(mask, xacc + 4, acc1);
5643 }
5644}
5645
5646XXH_FORCE_INLINE void
5647XXH3_accumulate_sve(xxh_u64* XXH_RESTRICT acc,
5648 const xxh_u8* XXH_RESTRICT input,
5649 const xxh_u8* XXH_RESTRICT secret,
5650 size_t nbStripes)
5651{
5652 if (nbStripes != 0) {
5653 uint64_t *xacc = (uint64_t *)acc;
5654 const uint64_t *xinput = (const uint64_t *)(const void *)input;
5655 const uint64_t *xsecret = (const uint64_t *)(const void *)secret;
5656 svuint64_t kSwap = sveor_n_u64_z(svptrue_b64(), svindex_u64(0, 1), 1);
5657 uint64_t element_count = svcntd();
5658 if (element_count >= 8) {
5659 svbool_t mask = svptrue_pat_b64(SV_VL8);
5660 svuint64_t vacc = svld1_u64(mask, xacc + 0);
5661 do {
5662 /* svprfd(svbool_t, void *, enum svfprop); */
5663 svprfd(mask, xinput + 128, SV_PLDL1STRM);
5664 ACCRND(vacc, 0);
5665 xinput += 8;
5666 xsecret += 1;
5667 nbStripes--;
5668 } while (nbStripes != 0);
5669
5670 svst1_u64(mask, xacc + 0, vacc);
5671 } else if (element_count == 2) { /* sve128 */
5672 svbool_t mask = svptrue_pat_b64(SV_VL2);
5673 svuint64_t acc0 = svld1_u64(mask, xacc + 0);
5674 svuint64_t acc1 = svld1_u64(mask, xacc + 2);
5675 svuint64_t acc2 = svld1_u64(mask, xacc + 4);
5676 svuint64_t acc3 = svld1_u64(mask, xacc + 6);
5677 do {
5678 svprfd(mask, xinput + 128, SV_PLDL1STRM);
5679 ACCRND(acc0, 0);
5680 ACCRND(acc1, 2);
5681 ACCRND(acc2, 4);
5682 ACCRND(acc3, 6);
5683 xinput += 8;
5684 xsecret += 1;
5685 nbStripes--;
5686 } while (nbStripes != 0);
5687
5688 svst1_u64(mask, xacc + 0, acc0);
5689 svst1_u64(mask, xacc + 2, acc1);
5690 svst1_u64(mask, xacc + 4, acc2);
5691 svst1_u64(mask, xacc + 6, acc3);
5692 } else {
5693 svbool_t mask = svptrue_pat_b64(SV_VL4);
5694 svuint64_t acc0 = svld1_u64(mask, xacc + 0);
5695 svuint64_t acc1 = svld1_u64(mask, xacc + 4);
5696 do {
5697 svprfd(mask, xinput + 128, SV_PLDL1STRM);
5698 ACCRND(acc0, 0);
5699 ACCRND(acc1, 4);
5700 xinput += 8;
5701 xsecret += 1;
5702 nbStripes--;
5703 } while (nbStripes != 0);
5704
5705 svst1_u64(mask, xacc + 0, acc0);
5706 svst1_u64(mask, xacc + 4, acc1);
5707 }
5708 }
5709}
5710
5711#endif
5712
5713#if (XXH_VECTOR == XXH_LSX)
5714#define _LSX_SHUFFLE(z, y, x, w) (((z) << 6) | ((y) << 4) | ((x) << 2) | (w))
5715
5716XXH_FORCE_INLINE void
5717XXH3_accumulate_512_lsx( void* XXH_RESTRICT acc,
5718 const void* XXH_RESTRICT input,
5719 const void* XXH_RESTRICT secret)
5720{
5721 XXH_ASSERT((((size_t)acc) & 15) == 0);
5722 {
5723 __m128i* const xacc = (__m128i *) acc;
5724 const __m128i* const xinput = (const __m128i *) input;
5725 const __m128i* const xsecret = (const __m128i *) secret;
5726 size_t i;
5727
5728 for (i = 0; i < XXH_STRIPE_LEN / sizeof(__m128i); i++) {
5729 /* data_vec = xinput[i]; */
5730 __m128i const data_vec = __lsx_vld(xinput + i, 0);
5731 /* key_vec = xsecret[i]; */
5732 __m128i const key_vec = __lsx_vld(xsecret + i, 0);
5733 /* data_key = data_vec ^ key_vec; */
5734 __m128i const data_key = __lsx_vxor_v(data_vec, key_vec);
5735 /* data_key_lo = data_key >> 32; */
5736 __m128i const data_key_lo = __lsx_vsrli_d(data_key, 32);
5737 // __m128i const data_key_lo = __lsx_vsrli_d(data_key, 32);
5738 /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */
5739 __m128i const product = __lsx_vmulwev_d_wu(data_key, data_key_lo);
5740 /* xacc[i] += swap(data_vec); */
5741 __m128i const data_swap = __lsx_vshuf4i_w(data_vec, _LSX_SHUFFLE(1, 0, 3, 2));
5742 __m128i const sum = __lsx_vadd_d(xacc[i], data_swap);
5743 /* xacc[i] += product; */
5744 xacc[i] = __lsx_vadd_d(product, sum);
5745 }
5746 }
5747}
5748XXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(lsx)
5749
5750XXH_FORCE_INLINE void
5751XXH3_scrambleAcc_lsx(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret)
5752{
5753 XXH_ASSERT((((size_t)acc) & 15) == 0);
5754 {
5755 __m128i* const xacc = (__m128i*) acc;
5756 const __m128i* const xsecret = (const __m128i *) secret;
5757 const __m128i prime32 = __lsx_vreplgr2vr_d(XXH_PRIME32_1);
5758 size_t i;
5759
5760 for (i = 0; i < XXH_STRIPE_LEN / sizeof(__m128i); i++) {
5761 /* xacc[i] ^= (xacc[i] >> 47) */
5762 __m128i const acc_vec = xacc[i];
5763 __m128i const shifted = __lsx_vsrli_d(acc_vec, 47);
5764 __m128i const data_vec = __lsx_vxor_v(acc_vec, shifted);
5765 /* xacc[i] ^= xsecret[i]; */
5766 __m128i const key_vec = __lsx_vld(xsecret + i, 0);
5767 __m128i const data_key = __lsx_vxor_v(data_vec, key_vec);
5768
5769 /* xacc[i] *= XXH_PRIME32_1; */
5770 xacc[i] = __lsx_vmul_d(data_key, prime32);
5771 }
5772 }
5773}
5774
5775#endif
5776
5777#if (XXH_VECTOR == XXH_LASX)
5778#define _LASX_SHUFFLE(z, y, x, w) (((z) << 6) | ((y) << 4) | ((x) << 2) | (w))
5779
5780XXH_FORCE_INLINE void
5781XXH3_accumulate_512_lasx( void* XXH_RESTRICT acc,
5782 const void* XXH_RESTRICT input,
5783 const void* XXH_RESTRICT secret)
5784{
5785 XXH_ASSERT((((size_t)acc) & 31) == 0);
5786 {
5787 size_t i;
5788 __m256i* const xacc = (__m256i *) acc;
5789 const __m256i* const xinput = (const __m256i *) input;
5790 const __m256i* const xsecret = (const __m256i *) secret;
5791
5792 for (i = 0; i < XXH_STRIPE_LEN / sizeof(__m256i); i++) {
5793 /* data_vec = xinput[i]; */
5794 __m256i const data_vec = __lasx_xvld(xinput + i, 0);
5795 /* key_vec = xsecret[i]; */
5796 __m256i const key_vec = __lasx_xvld(xsecret + i, 0);
5797 /* data_key = data_vec ^ key_vec; */
5798 __m256i const data_key = __lasx_xvxor_v(data_vec, key_vec);
5799 /* data_key_lo = data_key >> 32; */
5800 __m256i const data_key_lo = __lasx_xvsrli_d(data_key, 32);
5801 // __m256i const data_key_lo = __lasx_xvsrli_d(data_key, 32);
5802 /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */
5803 __m256i const product = __lasx_xvmulwev_d_wu(data_key, data_key_lo);
5804 /* xacc[i] += swap(data_vec); */
5805 __m256i const data_swap = __lasx_xvshuf4i_w(data_vec, _LASX_SHUFFLE(1, 0, 3, 2));
5806 __m256i const sum = __lasx_xvadd_d(xacc[i], data_swap);
5807 /* xacc[i] += product; */
5808 xacc[i] = __lasx_xvadd_d(product, sum);
5809 }
5810 }
5811}
5812XXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(lasx)
5813
5814XXH_FORCE_INLINE void
5815XXH3_scrambleAcc_lasx(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret)
5816{
5817 XXH_ASSERT((((size_t)acc) & 31) == 0);
5818 {
5819 __m256i* const xacc = (__m256i*) acc;
5820 const __m256i* const xsecret = (const __m256i *) secret;
5821 const __m256i prime32 = __lasx_xvreplgr2vr_d(XXH_PRIME32_1);
5822 size_t i;
5823
5824 for (i = 0; i < XXH_STRIPE_LEN / sizeof(__m256i); i++) {
5825 /* xacc[i] ^= (xacc[i] >> 47) */
5826 __m256i const acc_vec = xacc[i];
5827 __m256i const shifted = __lasx_xvsrli_d(acc_vec, 47);
5828 __m256i const data_vec = __lasx_xvxor_v(acc_vec, shifted);
5829 /* xacc[i] ^= xsecret[i]; */
5830 __m256i const key_vec = __lasx_xvld(xsecret + i, 0);
5831 __m256i const data_key = __lasx_xvxor_v(data_vec, key_vec);
5832
5833 /* xacc[i] *= XXH_PRIME32_1; */
5834 xacc[i] = __lasx_xvmul_d(data_key, prime32);
5835 }
5836 }
5837}
5838
5839#endif
5840
5841#if (XXH_VECTOR == XXH_RVV)
5842 #define XXH_CONCAT2(X, Y) X ## Y
5843 #define XXH_CONCAT(X, Y) XXH_CONCAT2(X, Y)
5844#if ((defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 13) || \
5845 (defined(__clang__) && __clang_major__ < 16))
5846 #define XXH_RVOP(op) op
5847 #define XXH_RVCAST(op) XXH_CONCAT(vreinterpret_v_, op)
5848#else
5849 #define XXH_RVOP(op) XXH_CONCAT(__riscv_, op)
5850 #define XXH_RVCAST(op) XXH_CONCAT(__riscv_vreinterpret_v_, op)
5851#endif
5852XXH_FORCE_INLINE void
5853XXH3_accumulate_512_rvv( void* XXH_RESTRICT acc,
5854 const void* XXH_RESTRICT input,
5855 const void* XXH_RESTRICT secret)
5856{
5857 XXH_ASSERT((((size_t)acc) & 63) == 0);
5858 {
5859 // Try to set vector lenght to 512 bits.
5860 // If this length is unavailable, then maximum available will be used
5861 size_t vl = XXH_RVOP(vsetvl_e64m2)(8);
5862
5863 uint64_t* xacc = (uint64_t*) acc;
5864 const uint64_t* xinput = (const uint64_t*) input;
5865 const uint64_t* xsecret = (const uint64_t*) secret;
5866 static const uint64_t swap_mask[16] = {1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14};
5867 vuint64m2_t xswap_mask = XXH_RVOP(vle64_v_u64m2)(swap_mask, vl);
5868
5869 size_t i;
5870 for (i = 0; i < XXH_STRIPE_LEN/8; i += vl) {
5871 /* data_vec = xinput[i]; */
5872 vuint64m2_t data_vec = XXH_RVCAST(u8m2_u64m2)(XXH_RVOP(vle8_v_u8m2)((const uint8_t*)(xinput + i), vl * 8));
5873 /* key_vec = xsecret[i]; */
5874 vuint64m2_t key_vec = XXH_RVCAST(u8m2_u64m2)(XXH_RVOP(vle8_v_u8m2)((const uint8_t*)(xsecret + i), vl * 8));
5875 /* acc_vec = xacc[i]; */
5876 vuint64m2_t acc_vec = XXH_RVOP(vle64_v_u64m2)(xacc + i, vl);
5877 /* data_key = data_vec ^ key_vec; */
5878 vuint64m2_t data_key = XXH_RVOP(vxor_vv_u64m2)(data_vec, key_vec, vl);
5879 /* data_key_hi = data_key >> 32; */
5880 vuint64m2_t data_key_hi = XXH_RVOP(vsrl_vx_u64m2)(data_key, 32, vl);
5881 /* data_key_lo = data_key & 0xffffffff; */
5882 vuint64m2_t data_key_lo = XXH_RVOP(vand_vx_u64m2)(data_key, 0xffffffff, vl);
5883 /* swap high and low halves */
5884 vuint64m2_t data_swap = XXH_RVOP(vrgather_vv_u64m2)(data_vec, xswap_mask, vl);
5885 /* acc_vec += data_key_lo * data_key_hi; */
5886 acc_vec = XXH_RVOP(vmacc_vv_u64m2)(acc_vec, data_key_lo, data_key_hi, vl);
5887 /* acc_vec += data_swap; */
5888 acc_vec = XXH_RVOP(vadd_vv_u64m2)(acc_vec, data_swap, vl);
5889 /* xacc[i] = acc_vec; */
5890 XXH_RVOP(vse64_v_u64m2)(xacc + i, acc_vec, vl);
5891 }
5892 }
5893}
5894
5895XXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(rvv)
5896
5897XXH_FORCE_INLINE void
5898XXH3_scrambleAcc_rvv(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret)
5899{
5900 XXH_ASSERT((((size_t)acc) & 15) == 0);
5901 {
5902 size_t count = XXH_STRIPE_LEN/8;
5903 uint64_t* xacc = (uint64_t*)acc;
5904 const uint8_t* xsecret = (const uint8_t *)secret;
5905 size_t vl;
5906 for (; count > 0; count -= vl, xacc += vl, xsecret += vl*8) {
5907 vl = XXH_RVOP(vsetvl_e64m2)(count);
5908 {
5909 /* key_vec = xsecret[i]; */
5910 vuint64m2_t key_vec = XXH_RVCAST(u8m2_u64m2)(XXH_RVOP(vle8_v_u8m2)(xsecret, vl*8));
5911 /* acc_vec = xacc[i]; */
5912 vuint64m2_t acc_vec = XXH_RVOP(vle64_v_u64m2)(xacc, vl);
5913 /* acc_vec ^= acc_vec >> 47; */
5914 vuint64m2_t vsrl = XXH_RVOP(vsrl_vx_u64m2)(acc_vec, 47, vl);
5915 acc_vec = XXH_RVOP(vxor_vv_u64m2)(acc_vec, vsrl, vl);
5916 /* acc_vec ^= key_vec; */
5917 acc_vec = XXH_RVOP(vxor_vv_u64m2)(acc_vec, key_vec, vl);
5918 /* acc_vec *= XXH_PRIME32_1; */
5919 acc_vec = XXH_RVOP(vmul_vx_u64m2)(acc_vec, XXH_PRIME32_1, vl);
5920 /* xacc[i] *= acc_vec; */
5921 XXH_RVOP(vse64_v_u64m2)(xacc, acc_vec, vl);
5922 }
5923 }
5924 }
5925}
5926
5927XXH_FORCE_INLINE void
5928XXH3_initCustomSecret_rvv(void* XXH_RESTRICT customSecret, xxh_u64 seed64)
5929{
5930 XXH_STATIC_ASSERT(XXH_SEC_ALIGN >= 8);
5931 XXH_ASSERT(((size_t)customSecret & 7) == 0);
5932 (void)(&XXH_writeLE64);
5933 {
5934 size_t count = XXH_SECRET_DEFAULT_SIZE/8;
5935 size_t vl;
5936 size_t VLMAX = XXH_RVOP(vsetvlmax_e64m2)();
5937 int64_t* cSecret = (int64_t*)customSecret;
5938 const int64_t* kSecret = (const int64_t*)(const void*)XXH3_kSecret;
5939
5940#if __riscv_v_intrinsic >= 1000000
5941 // ratified v1.0 intrinics version
5942 vbool32_t mneg = XXH_RVCAST(u8m1_b32)(
5943 XXH_RVOP(vmv_v_x_u8m1)(0xaa, XXH_RVOP(vsetvlmax_e8m1)()));
5944#else
5945 // support pre-ratification intrinics, which lack mask to vector casts
5946 size_t vlmax = XXH_RVOP(vsetvlmax_e8m1)();
5947 vbool32_t mneg = XXH_RVOP(vmseq_vx_u8mf4_b32)(
5948 XXH_RVOP(vand_vx_u8mf4)(
5949 XXH_RVOP(vid_v_u8mf4)(vlmax), 1, vlmax), 1, vlmax);
5950#endif
5951 vint64m2_t seed = XXH_RVOP(vmv_v_x_i64m2)((int64_t)seed64, VLMAX);
5952 seed = XXH_RVOP(vneg_v_i64m2_mu)(mneg, seed, seed, VLMAX);
5953
5954 for (; count > 0; count -= vl, cSecret += vl, kSecret += vl) {
5955 /* make sure vl=VLMAX until last iteration */
5956 vl = XXH_RVOP(vsetvl_e64m2)(count < VLMAX ? count : VLMAX);
5957 {
5958 vint64m2_t src = XXH_RVOP(vle64_v_i64m2)(kSecret, vl);
5959 vint64m2_t res = XXH_RVOP(vadd_vv_i64m2)(src, seed, vl);
5960 XXH_RVOP(vse64_v_i64m2)(cSecret, res, vl);
5961 }
5962 }
5963 }
5964}
5965#endif
5966
5967
5968/* scalar variants - universal */
5969
5970#if defined(__aarch64__) && (defined(__GNUC__) || defined(__clang__))
5971/*
5972 * In XXH3_scalarRound(), GCC and Clang have a similar codegen issue, where they
5973 * emit an excess mask and a full 64-bit multiply-add (MADD X-form).
5974 *
5975 * While this might not seem like much, as AArch64 is a 64-bit architecture, only
5976 * big Cortex designs have a full 64-bit multiplier.
5977 *
5978 * On the little cores, the smaller 32-bit multiplier is used, and full 64-bit
5979 * multiplies expand to 2-3 multiplies in microcode. This has a major penalty
5980 * of up to 4 latency cycles and 2 stall cycles in the multiply pipeline.
5981 *
5982 * Thankfully, AArch64 still provides the 32-bit long multiply-add (UMADDL) which does
5983 * not have this penalty and does the mask automatically.
5984 */
5985XXH_FORCE_INLINE xxh_u64
5986XXH_mult32to64_add64(xxh_u64 lhs, xxh_u64 rhs, xxh_u64 acc)
5987{
5988 xxh_u64 ret;
5989 /* note: %x = 64-bit register, %w = 32-bit register */
5990 __asm__("umaddl %x0, %w1, %w2, %x3" : "=r" (ret) : "r" (lhs), "r" (rhs), "r" (acc));
5991 return ret;
5992}
5993#else
5994XXH_FORCE_INLINE xxh_u64
5995XXH_mult32to64_add64(xxh_u64 lhs, xxh_u64 rhs, xxh_u64 acc)
5996{
5997 return XXH_mult32to64((xxh_u32)lhs, (xxh_u32)rhs) + acc;
5998}
5999#endif
6000
6008XXH_FORCE_INLINE void
6009XXH3_scalarRound(void* XXH_RESTRICT acc,
6010 void const* XXH_RESTRICT input,
6011 void const* XXH_RESTRICT secret,
6012 size_t lane)
6013{
6014 xxh_u64* xacc = (xxh_u64*) acc;
6015 xxh_u8 const* xinput = (xxh_u8 const*) input;
6016 xxh_u8 const* xsecret = (xxh_u8 const*) secret;
6017 XXH_ASSERT(lane < XXH_ACC_NB);
6018 XXH_ASSERT(((size_t)acc & (XXH_ACC_ALIGN-1)) == 0);
6019 {
6020 xxh_u64 const data_val = XXH_readLE64(xinput + lane * 8);
6021 xxh_u64 const data_key = data_val ^ XXH_readLE64(xsecret + lane * 8);
6022 xacc[lane ^ 1] += data_val; /* swap adjacent lanes */
6023 xacc[lane] = XXH_mult32to64_add64(data_key /* & 0xFFFFFFFF */, data_key >> 32, xacc[lane]);
6024 }
6025}
6026
6031XXH_FORCE_INLINE void
6032XXH3_accumulate_512_scalar(void* XXH_RESTRICT acc,
6033 const void* XXH_RESTRICT input,
6034 const void* XXH_RESTRICT secret)
6035{
6036 size_t i;
6037 /* ARM GCC refuses to unroll this loop, resulting in a 24% slowdown on ARMv6. */
6038#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 8 \
6039 && (defined(__arm__) || defined(__thumb2__)) \
6040 && defined(__ARM_FEATURE_UNALIGNED) /* no unaligned access just wastes bytes */ \
6041 && XXH_SIZE_OPT <= 0
6042# pragma GCC unroll 8
6043#endif
6044 for (i=0; i < XXH_ACC_NB; i++) {
6045 XXH3_scalarRound(acc, input, secret, i);
6046 }
6047}
6048XXH_FORCE_INLINE XXH3_ACCUMULATE_TEMPLATE(scalar)
6049
6050
6057XXH_FORCE_INLINE void
6058XXH3_scalarScrambleRound(void* XXH_RESTRICT acc,
6059 void const* XXH_RESTRICT secret,
6060 size_t lane)
6061{
6062 xxh_u64* const xacc = (xxh_u64*) acc; /* presumed aligned */
6063 const xxh_u8* const xsecret = (const xxh_u8*) secret; /* no alignment restriction */
6064 XXH_ASSERT((((size_t)acc) & (XXH_ACC_ALIGN-1)) == 0);
6065 XXH_ASSERT(lane < XXH_ACC_NB);
6066 {
6067 xxh_u64 const key64 = XXH_readLE64(xsecret + lane * 8);
6068 xxh_u64 acc64 = xacc[lane];
6069 acc64 = XXH_xorshift64(acc64, 47);
6070 acc64 ^= key64;
6071 acc64 *= XXH_PRIME32_1;
6072 xacc[lane] = acc64;
6073 }
6074}
6075
6080XXH_FORCE_INLINE void
6081XXH3_scrambleAcc_scalar(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret)
6082{
6083 size_t i;
6084 for (i=0; i < XXH_ACC_NB; i++) {
6085 XXH3_scalarScrambleRound(acc, secret, i);
6086 }
6087}
6088
6089XXH_FORCE_INLINE void
6090XXH3_initCustomSecret_scalar(void* XXH_RESTRICT customSecret, xxh_u64 seed64)
6091{
6092 /*
6093 * We need a separate pointer for the hack below,
6094 * which requires a non-const pointer.
6095 * Any decent compiler will optimize this out otherwise.
6096 */
6097 const xxh_u8* kSecretPtr = XXH3_kSecret;
6098 XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 15) == 0);
6099
6100#if defined(__GNUC__) && defined(__aarch64__)
6101 /*
6102 * UGLY HACK:
6103 * GCC and Clang generate a bunch of MOV/MOVK pairs for aarch64, and they are
6104 * placed sequentially, in order, at the top of the unrolled loop.
6105 *
6106 * While MOVK is great for generating constants (2 cycles for a 64-bit
6107 * constant compared to 4 cycles for LDR), it fights for bandwidth with
6108 * the arithmetic instructions.
6109 *
6110 * I L S
6111 * MOVK
6112 * MOVK
6113 * MOVK
6114 * MOVK
6115 * ADD
6116 * SUB STR
6117 * STR
6118 * By forcing loads from memory (as the asm line causes the compiler to assume
6119 * that XXH3_kSecretPtr has been changed), the pipelines are used more
6120 * efficiently:
6121 * I L S
6122 * LDR
6123 * ADD LDR
6124 * SUB STR
6125 * STR
6126 *
6127 * See XXH3_NEON_LANES for details on the pipeline.
6128 *
6129 * XXH3_64bits_withSeed, len == 256, Snapdragon 835
6130 * without hack: 2654.4 MB/s
6131 * with hack: 3202.9 MB/s
6132 */
6133 XXH_COMPILER_GUARD(kSecretPtr);
6134#endif
6135 { int const nbRounds = XXH_SECRET_DEFAULT_SIZE / 16;
6136 int i;
6137 for (i=0; i < nbRounds; i++) {
6138 /*
6139 * The asm hack causes the compiler to assume that kSecretPtr aliases with
6140 * customSecret, and on aarch64, this prevented LDP from merging two
6141 * loads together for free. Putting the loads together before the stores
6142 * properly generates LDP.
6143 */
6144 xxh_u64 lo = XXH_readLE64(kSecretPtr + 16*i) + seed64;
6145 xxh_u64 hi = XXH_readLE64(kSecretPtr + 16*i + 8) - seed64;
6146 XXH_writeLE64((xxh_u8*)customSecret + 16*i, lo);
6147 XXH_writeLE64((xxh_u8*)customSecret + 16*i + 8, hi);
6148 } }
6149}
6150
6151
6152typedef void (*XXH3_f_accumulate)(xxh_u64* XXH_RESTRICT, const xxh_u8* XXH_RESTRICT, const xxh_u8* XXH_RESTRICT, size_t);
6153typedef void (*XXH3_f_scrambleAcc)(void* XXH_RESTRICT, const void*);
6154typedef void (*XXH3_f_initCustomSecret)(void* XXH_RESTRICT, xxh_u64);
6155
6156
6157#if (XXH_VECTOR == XXH_AVX512)
6158
6159#define XXH3_accumulate_512 XXH3_accumulate_512_avx512
6160#define XXH3_accumulate XXH3_accumulate_avx512
6161#define XXH3_scrambleAcc XXH3_scrambleAcc_avx512
6162#define XXH3_initCustomSecret XXH3_initCustomSecret_avx512
6163
6164#elif (XXH_VECTOR == XXH_AVX2)
6165
6166#define XXH3_accumulate_512 XXH3_accumulate_512_avx2
6167#define XXH3_accumulate XXH3_accumulate_avx2
6168#define XXH3_scrambleAcc XXH3_scrambleAcc_avx2
6169#define XXH3_initCustomSecret XXH3_initCustomSecret_avx2
6170
6171#elif (XXH_VECTOR == XXH_SSE2)
6172
6173#define XXH3_accumulate_512 XXH3_accumulate_512_sse2
6174#define XXH3_accumulate XXH3_accumulate_sse2
6175#define XXH3_scrambleAcc XXH3_scrambleAcc_sse2
6176#define XXH3_initCustomSecret XXH3_initCustomSecret_sse2
6177
6178#elif (XXH_VECTOR == XXH_NEON)
6179
6180#define XXH3_accumulate_512 XXH3_accumulate_512_neon
6181#define XXH3_accumulate XXH3_accumulate_neon
6182#define XXH3_scrambleAcc XXH3_scrambleAcc_neon
6183#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar
6184
6185#elif (XXH_VECTOR == XXH_VSX)
6186
6187#define XXH3_accumulate_512 XXH3_accumulate_512_vsx
6188#define XXH3_accumulate XXH3_accumulate_vsx
6189#define XXH3_scrambleAcc XXH3_scrambleAcc_vsx
6190#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar
6191
6192#elif (XXH_VECTOR == XXH_SVE)
6193#define XXH3_accumulate_512 XXH3_accumulate_512_sve
6194#define XXH3_accumulate XXH3_accumulate_sve
6195#define XXH3_scrambleAcc XXH3_scrambleAcc_scalar
6196#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar
6197
6198#elif (XXH_VECTOR == XXH_LASX)
6199#define XXH3_accumulate_512 XXH3_accumulate_512_lasx
6200#define XXH3_accumulate XXH3_accumulate_lasx
6201#define XXH3_scrambleAcc XXH3_scrambleAcc_lasx
6202#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar
6203
6204#elif (XXH_VECTOR == XXH_LSX)
6205#define XXH3_accumulate_512 XXH3_accumulate_512_lsx
6206#define XXH3_accumulate XXH3_accumulate_lsx
6207#define XXH3_scrambleAcc XXH3_scrambleAcc_lsx
6208#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar
6209
6210#elif (XXH_VECTOR == XXH_RVV)
6211#define XXH3_accumulate_512 XXH3_accumulate_512_rvv
6212#define XXH3_accumulate XXH3_accumulate_rvv
6213#define XXH3_scrambleAcc XXH3_scrambleAcc_rvv
6214#define XXH3_initCustomSecret XXH3_initCustomSecret_rvv
6215
6216#else /* scalar */
6217
6218#define XXH3_accumulate_512 XXH3_accumulate_512_scalar
6219#define XXH3_accumulate XXH3_accumulate_scalar
6220#define XXH3_scrambleAcc XXH3_scrambleAcc_scalar
6221#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar
6222
6223#endif
6224
6225#if XXH_SIZE_OPT >= 1 /* don't do SIMD for initialization */
6226# undef XXH3_initCustomSecret
6227# define XXH3_initCustomSecret XXH3_initCustomSecret_scalar
6228#endif
6229
6230XXH_FORCE_INLINE void
6231XXH3_hashLong_internal_loop(xxh_u64* XXH_RESTRICT acc,
6232 const xxh_u8* XXH_RESTRICT input, size_t len,
6233 const xxh_u8* XXH_RESTRICT secret, size_t secretSize,
6234 XXH3_f_accumulate f_acc,
6235 XXH3_f_scrambleAcc f_scramble)
6236{
6237 size_t const nbStripesPerBlock = (secretSize - XXH_STRIPE_LEN) / XXH_SECRET_CONSUME_RATE;
6238 size_t const block_len = XXH_STRIPE_LEN * nbStripesPerBlock;
6239 size_t const nb_blocks = (len - 1) / block_len;
6240
6241 size_t n;
6242
6243 XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN);
6244
6245 for (n = 0; n < nb_blocks; n++) {
6246 f_acc(acc, input + n*block_len, secret, nbStripesPerBlock);
6247 f_scramble(acc, secret + secretSize - XXH_STRIPE_LEN);
6248 }
6249
6250 /* last partial block */
6251 XXH_ASSERT(len > XXH_STRIPE_LEN);
6252 { size_t const nbStripes = ((len - 1) - (block_len * nb_blocks)) / XXH_STRIPE_LEN;
6253 XXH_ASSERT(nbStripes <= (secretSize / XXH_SECRET_CONSUME_RATE));
6254 f_acc(acc, input + nb_blocks*block_len, secret, nbStripes);
6255
6256 /* last stripe */
6257 { const xxh_u8* const p = input + len - XXH_STRIPE_LEN;
6258#define XXH_SECRET_LASTACC_START 7 /* not aligned on 8, last secret is different from acc & scrambler */
6259 XXH3_accumulate_512(acc, p, secret + secretSize - XXH_STRIPE_LEN - XXH_SECRET_LASTACC_START);
6260 } }
6261}
6262
6263XXH_FORCE_INLINE xxh_u64
6264XXH3_mix2Accs(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret)
6265{
6266 return XXH3_mul128_fold64(
6267 acc[0] ^ XXH_readLE64(secret),
6268 acc[1] ^ XXH_readLE64(secret+8) );
6269}
6270
6272XXH3_mergeAccs(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret, xxh_u64 start)
6273{
6274 xxh_u64 result64 = start;
6275 size_t i = 0;
6276
6277 for (i = 0; i < 4; i++) {
6278 result64 += XXH3_mix2Accs(acc+2*i, secret + 16*i);
6279#if defined(__clang__) /* Clang */ \
6280 && (defined(__arm__) || defined(__thumb__)) /* ARMv7 */ \
6281 && (defined(__ARM_NEON) || defined(__ARM_NEON__)) /* NEON */ \
6282 && !defined(XXH_ENABLE_AUTOVECTORIZE) /* Define to disable */
6283 /*
6284 * UGLY HACK:
6285 * Prevent autovectorization on Clang ARMv7-a. Exact same problem as
6286 * the one in XXH3_len_129to240_64b. Speeds up shorter keys > 240b.
6287 * XXH3_64bits, len == 256, Snapdragon 835:
6288 * without hack: 2063.7 MB/s
6289 * with hack: 2560.7 MB/s
6290 */
6291 XXH_COMPILER_GUARD(result64);
6292#endif
6293 }
6294
6295 return XXH3_avalanche(result64);
6296}
6297
6298/* do not align on 8, so that the secret is different from the accumulator */
6299#define XXH_SECRET_MERGEACCS_START 11
6300
6302XXH3_finalizeLong_64b(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret, xxh_u64 len)
6303{
6304 return XXH3_mergeAccs(acc, secret + XXH_SECRET_MERGEACCS_START, len * XXH_PRIME64_1);
6305}
6306
6307#define XXH3_INIT_ACC { XXH_PRIME32_3, XXH_PRIME64_1, XXH_PRIME64_2, XXH_PRIME64_3, \
6308 XXH_PRIME64_4, XXH_PRIME32_2, XXH_PRIME64_5, XXH_PRIME32_1 }
6309
6310XXH_FORCE_INLINE XXH64_hash_t
6311XXH3_hashLong_64b_internal(const void* XXH_RESTRICT input, size_t len,
6312 const void* XXH_RESTRICT secret, size_t secretSize,
6313 XXH3_f_accumulate f_acc,
6314 XXH3_f_scrambleAcc f_scramble)
6315{
6316 XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[XXH_ACC_NB] = XXH3_INIT_ACC;
6317
6318 XXH3_hashLong_internal_loop(acc, (const xxh_u8*)input, len, (const xxh_u8*)secret, secretSize, f_acc, f_scramble);
6319
6320 /* converge into final hash */
6321 XXH_STATIC_ASSERT(sizeof(acc) == 64);
6322 XXH_ASSERT(secretSize >= sizeof(acc) + XXH_SECRET_MERGEACCS_START);
6323 return XXH3_finalizeLong_64b(acc, (const xxh_u8*)secret, (xxh_u64)len);
6324}
6325
6326/*
6327 * It's important for performance to transmit secret's size (when it's static)
6328 * so that the compiler can properly optimize the vectorized loop.
6329 * This makes a big performance difference for "medium" keys (<1 KB) when using AVX instruction set.
6330 * When the secret size is unknown, or on GCC 12 where the mix of NO_INLINE and FORCE_INLINE
6331 * breaks -Og, this is XXH_NO_INLINE.
6332 */
6333XXH3_WITH_SECRET_INLINE XXH64_hash_t
6334XXH3_hashLong_64b_withSecret(const void* XXH_RESTRICT input, size_t len,
6335 XXH64_hash_t seed64, const xxh_u8* XXH_RESTRICT secret, size_t secretLen)
6336{
6337 (void)seed64;
6338 return XXH3_hashLong_64b_internal(input, len, secret, secretLen, XXH3_accumulate, XXH3_scrambleAcc);
6339}
6340
6341/*
6342 * It's preferable for performance that XXH3_hashLong is not inlined,
6343 * as it results in a smaller function for small data, easier to the instruction cache.
6344 * Note that inside this no_inline function, we do inline the internal loop,
6345 * and provide a statically defined secret size to allow optimization of vector loop.
6346 */
6347XXH_NO_INLINE XXH_PUREF XXH64_hash_t
6348XXH3_hashLong_64b_default(const void* XXH_RESTRICT input, size_t len,
6349 XXH64_hash_t seed64, const xxh_u8* XXH_RESTRICT secret, size_t secretLen)
6350{
6351 (void)seed64; (void)secret; (void)secretLen;
6352 return XXH3_hashLong_64b_internal(input, len, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_accumulate, XXH3_scrambleAcc);
6353}
6354
6355/*
6356 * XXH3_hashLong_64b_withSeed():
6357 * Generate a custom key based on alteration of default XXH3_kSecret with the seed,
6358 * and then use this key for long mode hashing.
6359 *
6360 * This operation is decently fast but nonetheless costs a little bit of time.
6361 * Try to avoid it whenever possible (typically when seed==0).
6362 *
6363 * It's important for performance that XXH3_hashLong is not inlined. Not sure
6364 * why (uop cache maybe?), but the difference is large and easily measurable.
6365 */
6366XXH_FORCE_INLINE XXH64_hash_t
6367XXH3_hashLong_64b_withSeed_internal(const void* input, size_t len,
6368 XXH64_hash_t seed,
6369 XXH3_f_accumulate f_acc,
6370 XXH3_f_scrambleAcc f_scramble,
6371 XXH3_f_initCustomSecret f_initSec)
6372{
6373#if XXH_SIZE_OPT <= 0
6374 if (seed == 0)
6375 return XXH3_hashLong_64b_internal(input, len,
6376 XXH3_kSecret, sizeof(XXH3_kSecret),
6377 f_acc, f_scramble);
6378#endif
6379 { XXH_ALIGN(XXH_SEC_ALIGN) xxh_u8 secret[XXH_SECRET_DEFAULT_SIZE];
6380 f_initSec(secret, seed);
6381 return XXH3_hashLong_64b_internal(input, len, secret, sizeof(secret),
6382 f_acc, f_scramble);
6383 }
6384}
6385
6386/*
6387 * It's important for performance that XXH3_hashLong is not inlined.
6388 */
6389XXH_NO_INLINE XXH64_hash_t
6390XXH3_hashLong_64b_withSeed(const void* XXH_RESTRICT input, size_t len,
6391 XXH64_hash_t seed, const xxh_u8* XXH_RESTRICT secret, size_t secretLen)
6392{
6393 (void)secret; (void)secretLen;
6394 return XXH3_hashLong_64b_withSeed_internal(input, len, seed,
6395 XXH3_accumulate, XXH3_scrambleAcc, XXH3_initCustomSecret);
6396}
6397
6398
6399typedef XXH64_hash_t (*XXH3_hashLong64_f)(const void* XXH_RESTRICT, size_t,
6400 XXH64_hash_t, const xxh_u8* XXH_RESTRICT, size_t);
6401
6402XXH_FORCE_INLINE XXH64_hash_t
6403XXH3_64bits_internal(const void* XXH_RESTRICT input, size_t len,
6404 XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen,
6405 XXH3_hashLong64_f f_hashLong)
6406{
6407 XXH_ASSERT(secretLen >= XXH3_SECRET_SIZE_MIN);
6408 /*
6409 * If an action is to be taken if `secretLen` condition is not respected,
6410 * it should be done here.
6411 * For now, it's a contract pre-condition.
6412 * Adding a check and a branch here would cost performance at every hash.
6413 * Also, note that function signature doesn't offer room to return an error.
6414 */
6415 if (len <= 16)
6416 return XXH3_len_0to16_64b((const xxh_u8*)input, len, (const xxh_u8*)secret, seed64);
6417 if (len <= 128)
6418 return XXH3_len_17to128_64b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64);
6419 if (len <= XXH3_MIDSIZE_MAX)
6420 return XXH3_len_129to240_64b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64);
6421 return f_hashLong(input, len, seed64, (const xxh_u8*)secret, secretLen);
6422}
6423
6424
6425/* === Public entry point === */
6426
6428XXH_PUBLIC_API XXH64_hash_t XXH3_64bits(XXH_NOESCAPE const void* input, size_t length)
6429{
6430 return XXH3_64bits_internal(input, length, 0, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_default);
6431}
6432
6435XXH3_64bits_withSecret(XXH_NOESCAPE const void* input, size_t length, XXH_NOESCAPE const void* secret, size_t secretSize)
6436{
6437 return XXH3_64bits_internal(input, length, 0, secret, secretSize, XXH3_hashLong_64b_withSecret);
6438}
6439
6442XXH3_64bits_withSeed(XXH_NOESCAPE const void* input, size_t length, XXH64_hash_t seed)
6443{
6444 return XXH3_64bits_internal(input, length, seed, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_withSeed);
6445}
6446
6448XXH3_64bits_withSecretandSeed(XXH_NOESCAPE const void* input, size_t length, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed)
6449{
6450 if (length <= XXH3_MIDSIZE_MAX)
6451 return XXH3_64bits_internal(input, length, seed, XXH3_kSecret, sizeof(XXH3_kSecret), NULL);
6452 return XXH3_hashLong_64b_withSecret(input, length, seed, (const xxh_u8*)secret, secretSize);
6453}
6454
6455
6456/* === XXH3 streaming === */
6457#ifndef XXH_NO_STREAM
6458/*
6459 * Malloc's a pointer that is always aligned to @align.
6460 *
6461 * This must be freed with `XXH_alignedFree()`.
6462 *
6463 * malloc typically guarantees 16 byte alignment on 64-bit systems and 8 byte
6464 * alignment on 32-bit. This isn't enough for the 32 byte aligned loads in AVX2
6465 * or on 32-bit, the 16 byte aligned loads in SSE2 and NEON.
6466 *
6467 * This underalignment previously caused a rather obvious crash which went
6468 * completely unnoticed due to XXH3_createState() not actually being tested.
6469 * Credit to RedSpah for noticing this bug.
6470 *
6471 * The alignment is done manually: Functions like posix_memalign or _mm_malloc
6472 * are avoided: To maintain portability, we would have to write a fallback
6473 * like this anyways, and besides, testing for the existence of library
6474 * functions without relying on external build tools is impossible.
6475 *
6476 * The method is simple: Overallocate, manually align, and store the offset
6477 * to the original behind the returned pointer.
6478 *
6479 * Align must be a power of 2 and 8 <= align <= 128.
6480 */
6481static XXH_MALLOCF void* XXH_alignedMalloc(size_t s, size_t align)
6482{
6483 XXH_ASSERT(align <= 128 && align >= 8); /* range check */
6484 XXH_ASSERT((align & (align-1)) == 0); /* power of 2 */
6485 XXH_ASSERT(s != 0 && s < (s + align)); /* empty/overflow */
6486 { /* Overallocate to make room for manual realignment and an offset byte */
6487 xxh_u8* base = (xxh_u8*)XXH_malloc(s + align);
6488 if (base != NULL) {
6489 /*
6490 * Get the offset needed to align this pointer.
6491 *
6492 * Even if the returned pointer is aligned, there will always be
6493 * at least one byte to store the offset to the original pointer.
6494 */
6495 size_t offset = align - ((size_t)base & (align - 1)); /* base % align */
6496 /* Add the offset for the now-aligned pointer */
6497 xxh_u8* ptr = base + offset;
6498
6499 XXH_ASSERT((size_t)ptr % align == 0);
6500
6501 /* Store the offset immediately before the returned pointer. */
6502 ptr[-1] = (xxh_u8)offset;
6503 return ptr;
6504 }
6505 return NULL;
6506 }
6507}
6508/*
6509 * Frees an aligned pointer allocated by XXH_alignedMalloc(). Don't pass
6510 * normal malloc'd pointers, XXH_alignedMalloc has a specific data layout.
6511 */
6512static void XXH_alignedFree(void* p)
6513{
6514 if (p != NULL) {
6515 xxh_u8* ptr = (xxh_u8*)p;
6516 /* Get the offset byte we added in XXH_malloc. */
6517 xxh_u8 offset = ptr[-1];
6518 /* Free the original malloc'd pointer */
6519 xxh_u8* base = ptr - offset;
6520 XXH_free(base);
6521 }
6522}
6535{
6536 XXH3_state_t* const state = (XXH3_state_t*)XXH_alignedMalloc(sizeof(XXH3_state_t), 64);
6537 if (state==NULL) return NULL;
6538 XXH3_INITSTATE(state);
6539 return state;
6540}
6541
6555{
6556 XXH_alignedFree(statePtr);
6557 return XXH_OK;
6558}
6559
6561XXH_PUBLIC_API void
6562XXH3_copyState(XXH_NOESCAPE XXH3_state_t* dst_state, XXH_NOESCAPE const XXH3_state_t* src_state)
6563{
6564 XXH_memcpy(dst_state, src_state, sizeof(*dst_state));
6565}
6566
6567static void
6568XXH3_reset_internal(XXH3_state_t* statePtr,
6569 XXH64_hash_t seed,
6570 const void* secret, size_t secretSize)
6571{
6572 size_t const initStart = offsetof(XXH3_state_t, bufferedSize);
6573 size_t const initLength = offsetof(XXH3_state_t, nbStripesPerBlock) - initStart;
6574 XXH_ASSERT(offsetof(XXH3_state_t, nbStripesPerBlock) > initStart);
6575 XXH_ASSERT(statePtr != NULL);
6576 /* set members from bufferedSize to nbStripesPerBlock (excluded) to 0 */
6577 XXH_memset((char*)statePtr + initStart, 0, initLength);
6578 statePtr->acc[0] = XXH_PRIME32_3;
6579 statePtr->acc[1] = XXH_PRIME64_1;
6580 statePtr->acc[2] = XXH_PRIME64_2;
6581 statePtr->acc[3] = XXH_PRIME64_3;
6582 statePtr->acc[4] = XXH_PRIME64_4;
6583 statePtr->acc[5] = XXH_PRIME32_2;
6584 statePtr->acc[6] = XXH_PRIME64_5;
6585 statePtr->acc[7] = XXH_PRIME32_1;
6586 statePtr->seed = seed;
6587 statePtr->useSeed = (seed != 0);
6588 statePtr->extSecret = (const unsigned char*)secret;
6589 XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN);
6590 statePtr->secretLimit = secretSize - XXH_STRIPE_LEN;
6591 statePtr->nbStripesPerBlock = statePtr->secretLimit / XXH_SECRET_CONSUME_RATE;
6592}
6593
6596XXH3_64bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr)
6597{
6598 if (statePtr == NULL) return XXH_ERROR;
6599 XXH3_reset_internal(statePtr, 0, XXH3_kSecret, XXH_SECRET_DEFAULT_SIZE);
6600 return XXH_OK;
6601}
6602
6605XXH3_64bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize)
6606{
6607 if (statePtr == NULL) return XXH_ERROR;
6608 XXH3_reset_internal(statePtr, 0, secret, secretSize);
6609 if (secret == NULL) return XXH_ERROR;
6610 if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR;
6611 return XXH_OK;
6612}
6613
6616XXH3_64bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed)
6617{
6618 if (statePtr == NULL) return XXH_ERROR;
6619 if (seed==0) return XXH3_64bits_reset(statePtr);
6620 if ((seed != statePtr->seed) || (statePtr->extSecret != NULL))
6621 XXH3_initCustomSecret(statePtr->customSecret, seed);
6622 XXH3_reset_internal(statePtr, seed, NULL, XXH_SECRET_DEFAULT_SIZE);
6623 return XXH_OK;
6624}
6625
6628XXH3_64bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed64)
6629{
6630 if (statePtr == NULL) return XXH_ERROR;
6631 if (secret == NULL) return XXH_ERROR;
6632 if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR;
6633 XXH3_reset_internal(statePtr, seed64, secret, secretSize);
6634 statePtr->useSeed = 1; /* always, even if seed64==0 */
6635 return XXH_OK;
6636}
6637
6655XXH_FORCE_INLINE const xxh_u8 *
6656XXH3_consumeStripes(xxh_u64* XXH_RESTRICT acc,
6657 size_t* XXH_RESTRICT nbStripesSoFarPtr, size_t nbStripesPerBlock,
6658 const xxh_u8* XXH_RESTRICT input, size_t nbStripes,
6659 const xxh_u8* XXH_RESTRICT secret, size_t secretLimit,
6660 XXH3_f_accumulate f_acc,
6661 XXH3_f_scrambleAcc f_scramble)
6662{
6663 const xxh_u8* initialSecret = secret + *nbStripesSoFarPtr * XXH_SECRET_CONSUME_RATE;
6664 /* Process full blocks */
6665 if (nbStripes >= (nbStripesPerBlock - *nbStripesSoFarPtr)) {
6666 /* Process the initial partial block... */
6667 size_t nbStripesThisIter = nbStripesPerBlock - *nbStripesSoFarPtr;
6668
6669 do {
6670 /* Accumulate and scramble */
6671 f_acc(acc, input, initialSecret, nbStripesThisIter);
6672 f_scramble(acc, secret + secretLimit);
6673 input += nbStripesThisIter * XXH_STRIPE_LEN;
6674 nbStripes -= nbStripesThisIter;
6675 /* Then continue the loop with the full block size */
6676 nbStripesThisIter = nbStripesPerBlock;
6677 initialSecret = secret;
6678 } while (nbStripes >= nbStripesPerBlock);
6679 *nbStripesSoFarPtr = 0;
6680 }
6681 /* Process a partial block */
6682 if (nbStripes > 0) {
6683 f_acc(acc, input, initialSecret, nbStripes);
6684 input += nbStripes * XXH_STRIPE_LEN;
6685 *nbStripesSoFarPtr += nbStripes;
6686 }
6687 /* Return end pointer */
6688 return input;
6689}
6690
6691#ifndef XXH3_STREAM_USE_STACK
6692# if XXH_SIZE_OPT <= 0 && !defined(__clang__) /* clang doesn't need additional stack space */
6693# define XXH3_STREAM_USE_STACK 1
6694# endif
6695#endif
6696/* This function accepts f_acc and f_scramble as function pointers,
6697 * making it possible to implement multiple variants with different acc & scramble stages.
6698 * This is notably useful to implement multiple vector variants with different intrinsics.
6699 */
6700XXH_FORCE_INLINE XXH_errorcode
6701XXH3_update(XXH3_state_t* XXH_RESTRICT const state,
6702 const xxh_u8* XXH_RESTRICT input, size_t len,
6703 XXH3_f_accumulate f_acc,
6704 XXH3_f_scrambleAcc f_scramble)
6705{
6706 if (input==NULL) {
6707 XXH_ASSERT(len == 0);
6708 return XXH_OK;
6709 }
6710
6711 XXH_ASSERT(state != NULL);
6712 state->totalLen += len;
6713
6714 /* small input : just fill in tmp buffer */
6715 XXH_ASSERT(state->bufferedSize <= XXH3_INTERNALBUFFER_SIZE);
6716 if (len <= XXH3_INTERNALBUFFER_SIZE - state->bufferedSize) {
6717 XXH_memcpy(state->buffer + state->bufferedSize, input, len);
6718 state->bufferedSize += (XXH32_hash_t)len;
6719 return XXH_OK;
6720 }
6721
6722 { const xxh_u8* const bEnd = input + len;
6723 const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret;
6724#if defined(XXH3_STREAM_USE_STACK) && XXH3_STREAM_USE_STACK >= 1
6725 /* For some reason, gcc and MSVC seem to suffer greatly
6726 * when operating accumulators directly into state.
6727 * Operating into stack space seems to enable proper optimization.
6728 * clang, on the other hand, doesn't seem to need this trick */
6729 XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[8];
6730 XXH_memcpy(acc, state->acc, sizeof(acc));
6731#else
6732 xxh_u64* XXH_RESTRICT const acc = state->acc;
6733#endif
6734
6735 /* total input is now > XXH3_INTERNALBUFFER_SIZE */
6736 #define XXH3_INTERNALBUFFER_STRIPES (XXH3_INTERNALBUFFER_SIZE / XXH_STRIPE_LEN)
6737 XXH_STATIC_ASSERT(XXH3_INTERNALBUFFER_SIZE % XXH_STRIPE_LEN == 0); /* clean multiple */
6738
6739 /*
6740 * Internal buffer is partially filled (always, except at beginning)
6741 * Complete it, then consume it.
6742 */
6743 if (state->bufferedSize) {
6744 size_t const loadSize = XXH3_INTERNALBUFFER_SIZE - state->bufferedSize;
6745 XXH_memcpy(state->buffer + state->bufferedSize, input, loadSize);
6746 input += loadSize;
6747 XXH3_consumeStripes(acc,
6748 &state->nbStripesSoFar, state->nbStripesPerBlock,
6749 state->buffer, XXH3_INTERNALBUFFER_STRIPES,
6750 secret, state->secretLimit,
6751 f_acc, f_scramble);
6752 state->bufferedSize = 0;
6753 }
6754 XXH_ASSERT(input < bEnd);
6755 if (bEnd - input > XXH3_INTERNALBUFFER_SIZE) {
6756 size_t nbStripes = (size_t)(bEnd - 1 - input) / XXH_STRIPE_LEN;
6757 input = XXH3_consumeStripes(acc,
6758 &state->nbStripesSoFar, state->nbStripesPerBlock,
6759 input, nbStripes,
6760 secret, state->secretLimit,
6761 f_acc, f_scramble);
6762 XXH_memcpy(state->buffer + sizeof(state->buffer) - XXH_STRIPE_LEN, input - XXH_STRIPE_LEN, XXH_STRIPE_LEN);
6763
6764 }
6765 /* Some remaining input (always) : buffer it */
6766 XXH_ASSERT(input < bEnd);
6767 XXH_ASSERT(bEnd - input <= XXH3_INTERNALBUFFER_SIZE);
6768 XXH_ASSERT(state->bufferedSize == 0);
6769 XXH_memcpy(state->buffer, input, (size_t)(bEnd-input));
6770 state->bufferedSize = (XXH32_hash_t)(bEnd-input);
6771#if defined(XXH3_STREAM_USE_STACK) && XXH3_STREAM_USE_STACK >= 1
6772 /* save stack accumulators into state */
6773 XXH_memcpy(state->acc, acc, sizeof(acc));
6774#endif
6775 }
6776
6777 return XXH_OK;
6778}
6779
6780/*
6781 * Both XXH3_64bits_update and XXH3_128bits_update use this routine.
6782 */
6783XXH_NO_INLINE XXH_errorcode
6784XXH3_update_regular(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len)
6785{
6786 return XXH3_update(state, (const xxh_u8*)input, len,
6787 XXH3_accumulate, XXH3_scrambleAcc);
6788}
6789
6792XXH3_64bits_update(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len)
6793{
6794 return XXH3_update_regular(state, input, len);
6795}
6796
6797
6798XXH_FORCE_INLINE void
6799XXH3_digest_long (XXH64_hash_t* acc,
6800 const XXH3_state_t* state,
6801 const unsigned char* secret)
6802{
6803 xxh_u8 lastStripe[XXH_STRIPE_LEN];
6804 const xxh_u8* lastStripePtr;
6805
6806 /*
6807 * Digest on a local copy. This way, the state remains unaltered, and it can
6808 * continue ingesting more input afterwards.
6809 */
6810 XXH_memcpy(acc, state->acc, sizeof(state->acc));
6811 if (state->bufferedSize >= XXH_STRIPE_LEN) {
6812 /* Consume remaining stripes then point to remaining data in buffer */
6813 size_t const nbStripes = (state->bufferedSize - 1) / XXH_STRIPE_LEN;
6814 size_t nbStripesSoFar = state->nbStripesSoFar;
6815 XXH3_consumeStripes(acc,
6816 &nbStripesSoFar, state->nbStripesPerBlock,
6817 state->buffer, nbStripes,
6818 secret, state->secretLimit,
6819 XXH3_accumulate, XXH3_scrambleAcc);
6820 lastStripePtr = state->buffer + state->bufferedSize - XXH_STRIPE_LEN;
6821 } else { /* bufferedSize < XXH_STRIPE_LEN */
6822 /* Copy to temp buffer */
6823 size_t const catchupSize = XXH_STRIPE_LEN - state->bufferedSize;
6824 XXH_ASSERT(state->bufferedSize > 0); /* there is always some input buffered */
6825 XXH_memcpy(lastStripe, state->buffer + sizeof(state->buffer) - catchupSize, catchupSize);
6826 XXH_memcpy(lastStripe + catchupSize, state->buffer, state->bufferedSize);
6827 lastStripePtr = lastStripe;
6828 }
6829 /* Last stripe */
6830 XXH3_accumulate_512(acc,
6831 lastStripePtr,
6832 secret + state->secretLimit - XXH_SECRET_LASTACC_START);
6833}
6834
6837{
6838 const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret;
6839 if (state->totalLen > XXH3_MIDSIZE_MAX) {
6840 XXH_ALIGN(XXH_ACC_ALIGN) XXH64_hash_t acc[XXH_ACC_NB];
6841 XXH3_digest_long(acc, state, secret);
6842 return XXH3_finalizeLong_64b(acc, secret, (xxh_u64)state->totalLen);
6843 }
6844 /* totalLen <= XXH3_MIDSIZE_MAX: digesting a short input */
6845 if (state->useSeed)
6846 return XXH3_64bits_withSeed(state->buffer, (size_t)state->totalLen, state->seed);
6847 return XXH3_64bits_withSecret(state->buffer, (size_t)(state->totalLen),
6848 secret, state->secretLimit + XXH_STRIPE_LEN);
6849}
6850#endif /* !XXH_NO_STREAM */
6851
6852
6853/* ==========================================
6854 * XXH3 128 bits (a.k.a XXH128)
6855 * ==========================================
6856 * XXH3's 128-bit variant has better mixing and strength than the 64-bit variant,
6857 * even without counting the significantly larger output size.
6858 *
6859 * For example, extra steps are taken to avoid the seed-dependent collisions
6860 * in 17-240 byte inputs (See XXH3_mix16B and XXH128_mix32B).
6861 *
6862 * This strength naturally comes at the cost of some speed, especially on short
6863 * lengths. Note that longer hashes are about as fast as the 64-bit version
6864 * due to it using only a slight modification of the 64-bit loop.
6865 *
6866 * XXH128 is also more oriented towards 64-bit machines. It is still extremely
6867 * fast for a _128-bit_ hash on 32-bit (it usually clears XXH64).
6868 */
6869
6870XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t
6871XXH3_len_1to3_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed)
6872{
6873 /* A doubled version of 1to3_64b with different constants. */
6874 XXH_ASSERT(input != NULL);
6875 XXH_ASSERT(1 <= len && len <= 3);
6876 XXH_ASSERT(secret != NULL);
6877 /*
6878 * len = 1: combinedl = { input[0], 0x01, input[0], input[0] }
6879 * len = 2: combinedl = { input[1], 0x02, input[0], input[1] }
6880 * len = 3: combinedl = { input[2], 0x03, input[0], input[1] }
6881 */
6882 { xxh_u8 const c1 = input[0];
6883 xxh_u8 const c2 = input[len >> 1];
6884 xxh_u8 const c3 = input[len - 1];
6885 xxh_u32 const combinedl = ((xxh_u32)c1 <<16) | ((xxh_u32)c2 << 24)
6886 | ((xxh_u32)c3 << 0) | ((xxh_u32)len << 8);
6887 xxh_u32 const combinedh = XXH_rotl32(XXH_swap32(combinedl), 13);
6888 xxh_u64 const bitflipl = (XXH_readLE32(secret) ^ XXH_readLE32(secret+4)) + seed;
6889 xxh_u64 const bitfliph = (XXH_readLE32(secret+8) ^ XXH_readLE32(secret+12)) - seed;
6890 xxh_u64 const keyed_lo = (xxh_u64)combinedl ^ bitflipl;
6891 xxh_u64 const keyed_hi = (xxh_u64)combinedh ^ bitfliph;
6892 XXH128_hash_t h128;
6893 h128.low64 = XXH64_avalanche(keyed_lo);
6894 h128.high64 = XXH64_avalanche(keyed_hi);
6895 return h128;
6896 }
6897}
6898
6899XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t
6900XXH3_len_4to8_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed)
6901{
6902 XXH_ASSERT(input != NULL);
6903 XXH_ASSERT(secret != NULL);
6904 XXH_ASSERT(4 <= len && len <= 8);
6905 seed ^= (xxh_u64)XXH_swap32((xxh_u32)seed) << 32;
6906 { xxh_u32 const input_lo = XXH_readLE32(input);
6907 xxh_u32 const input_hi = XXH_readLE32(input + len - 4);
6908 xxh_u64 const input_64 = input_lo + ((xxh_u64)input_hi << 32);
6909 xxh_u64 const bitflip = (XXH_readLE64(secret+16) ^ XXH_readLE64(secret+24)) + seed;
6910 xxh_u64 const keyed = input_64 ^ bitflip;
6911
6912 /* Shift len to the left to ensure it is even, this avoids even multiplies. */
6913 XXH128_hash_t m128 = XXH_mult64to128(keyed, XXH_PRIME64_1 + (len << 2));
6914
6915 m128.high64 += (m128.low64 << 1);
6916 m128.low64 ^= (m128.high64 >> 3);
6917
6918 m128.low64 = XXH_xorshift64(m128.low64, 35);
6919 m128.low64 *= PRIME_MX2;
6920 m128.low64 = XXH_xorshift64(m128.low64, 28);
6921 m128.high64 = XXH3_avalanche(m128.high64);
6922 return m128;
6923 }
6924}
6925
6926XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t
6927XXH3_len_9to16_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed)
6928{
6929 XXH_ASSERT(input != NULL);
6930 XXH_ASSERT(secret != NULL);
6931 XXH_ASSERT(9 <= len && len <= 16);
6932 { xxh_u64 const bitflipl = (XXH_readLE64(secret+32) ^ XXH_readLE64(secret+40)) - seed;
6933 xxh_u64 const bitfliph = (XXH_readLE64(secret+48) ^ XXH_readLE64(secret+56)) + seed;
6934 xxh_u64 const input_lo = XXH_readLE64(input);
6935 xxh_u64 input_hi = XXH_readLE64(input + len - 8);
6936 XXH128_hash_t m128 = XXH_mult64to128(input_lo ^ input_hi ^ bitflipl, XXH_PRIME64_1);
6937 /*
6938 * Put len in the middle of m128 to ensure that the length gets mixed to
6939 * both the low and high bits in the 128x64 multiply below.
6940 */
6941 m128.low64 += (xxh_u64)(len - 1) << 54;
6942 input_hi ^= bitfliph;
6943 /*
6944 * Add the high 32 bits of input_hi to the high 32 bits of m128, then
6945 * add the long product of the low 32 bits of input_hi and XXH_PRIME32_2 to
6946 * the high 64 bits of m128.
6947 *
6948 * The best approach to this operation is different on 32-bit and 64-bit.
6949 */
6950 if (sizeof(void *) < sizeof(xxh_u64)) { /* 32-bit */
6951 /*
6952 * 32-bit optimized version, which is more readable.
6953 *
6954 * On 32-bit, it removes an ADC and delays a dependency between the two
6955 * halves of m128.high64, but it generates an extra mask on 64-bit.
6956 */
6957 m128.high64 += (input_hi & 0xFFFFFFFF00000000ULL) + XXH_mult32to64((xxh_u32)input_hi, XXH_PRIME32_2);
6958 } else {
6959 /*
6960 * 64-bit optimized (albeit more confusing) version.
6961 *
6962 * Uses some properties of addition and multiplication to remove the mask:
6963 *
6964 * Let:
6965 * a = input_hi.lo = (input_hi & 0x00000000FFFFFFFF)
6966 * b = input_hi.hi = (input_hi & 0xFFFFFFFF00000000)
6967 * c = XXH_PRIME32_2
6968 *
6969 * a + (b * c)
6970 * Inverse Property: x + y - x == y
6971 * a + (b * (1 + c - 1))
6972 * Distributive Property: x * (y + z) == (x * y) + (x * z)
6973 * a + (b * 1) + (b * (c - 1))
6974 * Identity Property: x * 1 == x
6975 * a + b + (b * (c - 1))
6976 *
6977 * Substitute a, b, and c:
6978 * input_hi.hi + input_hi.lo + ((xxh_u64)input_hi.lo * (XXH_PRIME32_2 - 1))
6979 *
6980 * Since input_hi.hi + input_hi.lo == input_hi, we get this:
6981 * input_hi + ((xxh_u64)input_hi.lo * (XXH_PRIME32_2 - 1))
6982 */
6983 m128.high64 += input_hi + XXH_mult32to64((xxh_u32)input_hi, XXH_PRIME32_2 - 1);
6984 }
6985 /* m128 ^= XXH_swap64(m128 >> 64); */
6986 m128.low64 ^= XXH_swap64(m128.high64);
6987
6988 { /* 128x64 multiply: h128 = m128 * XXH_PRIME64_2; */
6989 XXH128_hash_t h128 = XXH_mult64to128(m128.low64, XXH_PRIME64_2);
6990 h128.high64 += m128.high64 * XXH_PRIME64_2;
6991
6992 h128.low64 = XXH3_avalanche(h128.low64);
6993 h128.high64 = XXH3_avalanche(h128.high64);
6994 return h128;
6995 } }
6996}
6997
6998/*
6999 * Assumption: `secret` size is >= XXH3_SECRET_SIZE_MIN
7000 */
7001XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t
7002XXH3_len_0to16_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed)
7003{
7004 XXH_ASSERT(len <= 16);
7005 { if (len > 8) return XXH3_len_9to16_128b(input, len, secret, seed);
7006 if (len >= 4) return XXH3_len_4to8_128b(input, len, secret, seed);
7007 if (len) return XXH3_len_1to3_128b(input, len, secret, seed);
7008 { XXH128_hash_t h128;
7009 xxh_u64 const bitflipl = XXH_readLE64(secret+64) ^ XXH_readLE64(secret+72);
7010 xxh_u64 const bitfliph = XXH_readLE64(secret+80) ^ XXH_readLE64(secret+88);
7011 h128.low64 = XXH64_avalanche(seed ^ bitflipl);
7012 h128.high64 = XXH64_avalanche( seed ^ bitfliph);
7013 return h128;
7014 } }
7015}
7016
7017/*
7018 * A bit slower than XXH3_mix16B, but handles multiply by zero better.
7019 */
7020XXH_FORCE_INLINE XXH128_hash_t
7021XXH128_mix32B(XXH128_hash_t acc, const xxh_u8* input_1, const xxh_u8* input_2,
7022 const xxh_u8* secret, XXH64_hash_t seed)
7023{
7024 acc.low64 += XXH3_mix16B (input_1, secret+0, seed);
7025 acc.low64 ^= XXH_readLE64(input_2) + XXH_readLE64(input_2 + 8);
7026 acc.high64 += XXH3_mix16B (input_2, secret+16, seed);
7027 acc.high64 ^= XXH_readLE64(input_1) + XXH_readLE64(input_1 + 8);
7028 return acc;
7029}
7030
7031
7032XXH_FORCE_INLINE XXH_PUREF XXH128_hash_t
7033XXH3_len_17to128_128b(const xxh_u8* XXH_RESTRICT input, size_t len,
7034 const xxh_u8* XXH_RESTRICT secret, size_t secretSize,
7035 XXH64_hash_t seed)
7036{
7037 XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize;
7038 XXH_ASSERT(16 < len && len <= 128);
7039
7040 { XXH128_hash_t acc;
7041 acc.low64 = len * XXH_PRIME64_1;
7042 acc.high64 = 0;
7043
7044#if XXH_SIZE_OPT >= 1
7045 {
7046 /* Smaller, but slightly slower. */
7047 unsigned int i = (unsigned int)(len - 1) / 32;
7048 do {
7049 acc = XXH128_mix32B(acc, input+16*i, input+len-16*(i+1), secret+32*i, seed);
7050 } while (i-- != 0);
7051 }
7052#else
7053 if (len > 32) {
7054 if (len > 64) {
7055 if (len > 96) {
7056 acc = XXH128_mix32B(acc, input+48, input+len-64, secret+96, seed);
7057 }
7058 acc = XXH128_mix32B(acc, input+32, input+len-48, secret+64, seed);
7059 }
7060 acc = XXH128_mix32B(acc, input+16, input+len-32, secret+32, seed);
7061 }
7062 acc = XXH128_mix32B(acc, input, input+len-16, secret, seed);
7063#endif
7064 { XXH128_hash_t h128;
7065 h128.low64 = acc.low64 + acc.high64;
7066 h128.high64 = (acc.low64 * XXH_PRIME64_1)
7067 + (acc.high64 * XXH_PRIME64_4)
7068 + ((len - seed) * XXH_PRIME64_2);
7069 h128.low64 = XXH3_avalanche(h128.low64);
7070 h128.high64 = (XXH64_hash_t)0 - XXH3_avalanche(h128.high64);
7071 return h128;
7072 }
7073 }
7074}
7075
7076XXH_NO_INLINE XXH_PUREF XXH128_hash_t
7077XXH3_len_129to240_128b(const xxh_u8* XXH_RESTRICT input, size_t len,
7078 const xxh_u8* XXH_RESTRICT secret, size_t secretSize,
7079 XXH64_hash_t seed)
7080{
7081 XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize;
7082 XXH_ASSERT(128 < len && len <= XXH3_MIDSIZE_MAX);
7083
7084 { XXH128_hash_t acc;
7085 unsigned i;
7086 acc.low64 = len * XXH_PRIME64_1;
7087 acc.high64 = 0;
7088 /*
7089 * We set as `i` as offset + 32. We do this so that unchanged
7090 * `len` can be used as upper bound. This reaches a sweet spot
7091 * where both x86 and aarch64 get simple agen and good codegen
7092 * for the loop.
7093 */
7094 for (i = 32; i < 160; i += 32) {
7095 acc = XXH128_mix32B(acc,
7096 input + i - 32,
7097 input + i - 16,
7098 secret + i - 32,
7099 seed);
7100 }
7101 acc.low64 = XXH3_avalanche(acc.low64);
7102 acc.high64 = XXH3_avalanche(acc.high64);
7103 /*
7104 * NB: `i <= len` will duplicate the last 32-bytes if
7105 * len % 32 was zero. This is an unfortunate necessity to keep
7106 * the hash result stable.
7107 */
7108 for (i=160; i <= len; i += 32) {
7109 acc = XXH128_mix32B(acc,
7110 input + i - 32,
7111 input + i - 16,
7112 secret + XXH3_MIDSIZE_STARTOFFSET + i - 160,
7113 seed);
7114 }
7115 /* last bytes */
7116 acc = XXH128_mix32B(acc,
7117 input + len - 16,
7118 input + len - 32,
7119 secret + XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET - 16,
7120 (XXH64_hash_t)0 - seed);
7121
7122 { XXH128_hash_t h128;
7123 h128.low64 = acc.low64 + acc.high64;
7124 h128.high64 = (acc.low64 * XXH_PRIME64_1)
7125 + (acc.high64 * XXH_PRIME64_4)
7126 + ((len - seed) * XXH_PRIME64_2);
7127 h128.low64 = XXH3_avalanche(h128.low64);
7128 h128.high64 = (XXH64_hash_t)0 - XXH3_avalanche(h128.high64);
7129 return h128;
7130 }
7131 }
7132}
7133
7135XXH3_finalizeLong_128b(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret, size_t secretSize, xxh_u64 len)
7136{
7137 XXH128_hash_t h128;
7138 h128.low64 = XXH3_finalizeLong_64b(acc, secret, len);
7139 h128.high64 = XXH3_mergeAccs(acc, secret + secretSize
7140 - XXH_STRIPE_LEN - XXH_SECRET_MERGEACCS_START,
7141 ~(len * XXH_PRIME64_2));
7142 return h128;
7143}
7144
7145XXH_FORCE_INLINE XXH128_hash_t
7146XXH3_hashLong_128b_internal(const void* XXH_RESTRICT input, size_t len,
7147 const xxh_u8* XXH_RESTRICT secret, size_t secretSize,
7148 XXH3_f_accumulate f_acc,
7149 XXH3_f_scrambleAcc f_scramble)
7150{
7151 XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[XXH_ACC_NB] = XXH3_INIT_ACC;
7152
7153 XXH3_hashLong_internal_loop(acc, (const xxh_u8*)input, len, secret, secretSize, f_acc, f_scramble);
7154
7155 /* converge into final hash */
7156 XXH_STATIC_ASSERT(sizeof(acc) == 64);
7157 XXH_ASSERT(secretSize >= sizeof(acc) + XXH_SECRET_MERGEACCS_START);
7158 return XXH3_finalizeLong_128b(acc, secret, secretSize, (xxh_u64)len);
7159}
7160
7161/*
7162 * It's important for performance that XXH3_hashLong() is not inlined.
7163 */
7164XXH_NO_INLINE XXH_PUREF XXH128_hash_t
7165XXH3_hashLong_128b_default(const void* XXH_RESTRICT input, size_t len,
7166 XXH64_hash_t seed64,
7167 const void* XXH_RESTRICT secret, size_t secretLen)
7168{
7169 (void)seed64; (void)secret; (void)secretLen;
7170 return XXH3_hashLong_128b_internal(input, len, XXH3_kSecret, sizeof(XXH3_kSecret),
7171 XXH3_accumulate, XXH3_scrambleAcc);
7172}
7173
7174/*
7175 * It's important for performance to pass @p secretLen (when it's static)
7176 * to the compiler, so that it can properly optimize the vectorized loop.
7177 *
7178 * When the secret size is unknown, or on GCC 12 where the mix of NO_INLINE and FORCE_INLINE
7179 * breaks -Og, this is XXH_NO_INLINE.
7180 */
7181XXH3_WITH_SECRET_INLINE XXH128_hash_t
7182XXH3_hashLong_128b_withSecret(const void* XXH_RESTRICT input, size_t len,
7183 XXH64_hash_t seed64,
7184 const void* XXH_RESTRICT secret, size_t secretLen)
7185{
7186 (void)seed64;
7187 return XXH3_hashLong_128b_internal(input, len, (const xxh_u8*)secret, secretLen,
7188 XXH3_accumulate, XXH3_scrambleAcc);
7189}
7190
7191XXH_FORCE_INLINE XXH128_hash_t
7192XXH3_hashLong_128b_withSeed_internal(const void* XXH_RESTRICT input, size_t len,
7193 XXH64_hash_t seed64,
7194 XXH3_f_accumulate f_acc,
7195 XXH3_f_scrambleAcc f_scramble,
7196 XXH3_f_initCustomSecret f_initSec)
7197{
7198 if (seed64 == 0)
7199 return XXH3_hashLong_128b_internal(input, len,
7200 XXH3_kSecret, sizeof(XXH3_kSecret),
7201 f_acc, f_scramble);
7202 { XXH_ALIGN(XXH_SEC_ALIGN) xxh_u8 secret[XXH_SECRET_DEFAULT_SIZE];
7203 f_initSec(secret, seed64);
7204 return XXH3_hashLong_128b_internal(input, len, (const xxh_u8*)secret, sizeof(secret),
7205 f_acc, f_scramble);
7206 }
7207}
7208
7209/*
7210 * It's important for performance that XXH3_hashLong is not inlined.
7211 */
7212XXH_NO_INLINE XXH128_hash_t
7213XXH3_hashLong_128b_withSeed(const void* input, size_t len,
7214 XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen)
7215{
7216 (void)secret; (void)secretLen;
7217 return XXH3_hashLong_128b_withSeed_internal(input, len, seed64,
7218 XXH3_accumulate, XXH3_scrambleAcc, XXH3_initCustomSecret);
7219}
7220
7221typedef XXH128_hash_t (*XXH3_hashLong128_f)(const void* XXH_RESTRICT, size_t,
7222 XXH64_hash_t, const void* XXH_RESTRICT, size_t);
7223
7224XXH_FORCE_INLINE XXH128_hash_t
7225XXH3_128bits_internal(const void* input, size_t len,
7226 XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen,
7227 XXH3_hashLong128_f f_hl128)
7228{
7229 XXH_ASSERT(secretLen >= XXH3_SECRET_SIZE_MIN);
7230 /*
7231 * If an action is to be taken if `secret` conditions are not respected,
7232 * it should be done here.
7233 * For now, it's a contract pre-condition.
7234 * Adding a check and a branch here would cost performance at every hash.
7235 */
7236 if (len <= 16)
7237 return XXH3_len_0to16_128b((const xxh_u8*)input, len, (const xxh_u8*)secret, seed64);
7238 if (len <= 128)
7239 return XXH3_len_17to128_128b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64);
7240 if (len <= XXH3_MIDSIZE_MAX)
7241 return XXH3_len_129to240_128b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64);
7242 return f_hl128(input, len, seed64, secret, secretLen);
7243}
7244
7245
7246/* === Public XXH128 API === */
7247
7249XXH_PUBLIC_API XXH128_hash_t XXH3_128bits(XXH_NOESCAPE const void* input, size_t len)
7250{
7251 return XXH3_128bits_internal(input, len, 0,
7252 XXH3_kSecret, sizeof(XXH3_kSecret),
7253 XXH3_hashLong_128b_default);
7254}
7255
7258XXH3_128bits_withSecret(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize)
7259{
7260 return XXH3_128bits_internal(input, len, 0,
7261 (const xxh_u8*)secret, secretSize,
7262 XXH3_hashLong_128b_withSecret);
7263}
7264
7267XXH3_128bits_withSeed(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed)
7268{
7269 return XXH3_128bits_internal(input, len, seed,
7270 XXH3_kSecret, sizeof(XXH3_kSecret),
7271 XXH3_hashLong_128b_withSeed);
7272}
7273
7276XXH3_128bits_withSecretandSeed(XXH_NOESCAPE const void* input, size_t len, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed)
7277{
7278 if (len <= XXH3_MIDSIZE_MAX)
7279 return XXH3_128bits_internal(input, len, seed, XXH3_kSecret, sizeof(XXH3_kSecret), NULL);
7280 return XXH3_hashLong_128b_withSecret(input, len, seed, secret, secretSize);
7281}
7282
7285XXH128(XXH_NOESCAPE const void* input, size_t len, XXH64_hash_t seed)
7286{
7287 return XXH3_128bits_withSeed(input, len, seed);
7288}
7289
7290
7291/* === XXH3 128-bit streaming === */
7292#ifndef XXH_NO_STREAM
7293/*
7294 * All initialization and update functions are identical to 64-bit streaming variant.
7295 * The only difference is the finalization routine.
7296 */
7297
7300XXH3_128bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr)
7301{
7302 return XXH3_64bits_reset(statePtr);
7303}
7304
7307XXH3_128bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize)
7308{
7309 return XXH3_64bits_reset_withSecret(statePtr, secret, secretSize);
7310}
7311
7314XXH3_128bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed)
7315{
7316 return XXH3_64bits_reset_withSeed(statePtr, seed);
7317}
7318
7321XXH3_128bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize, XXH64_hash_t seed)
7322{
7323 return XXH3_64bits_reset_withSecretandSeed(statePtr, secret, secretSize, seed);
7324}
7325
7328XXH3_128bits_update(XXH_NOESCAPE XXH3_state_t* state, XXH_NOESCAPE const void* input, size_t len)
7329{
7330 return XXH3_update_regular(state, input, len);
7331}
7332
7335{
7336 const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret;
7337 if (state->totalLen > XXH3_MIDSIZE_MAX) {
7338 XXH_ALIGN(XXH_ACC_ALIGN) XXH64_hash_t acc[XXH_ACC_NB];
7339 XXH3_digest_long(acc, state, secret);
7340 XXH_ASSERT(state->secretLimit + XXH_STRIPE_LEN >= sizeof(acc) + XXH_SECRET_MERGEACCS_START);
7341 return XXH3_finalizeLong_128b(acc, secret, state->secretLimit + XXH_STRIPE_LEN, (xxh_u64)state->totalLen);
7342 }
7343 /* len <= XXH3_MIDSIZE_MAX : short code */
7344 if (state->useSeed)
7345 return XXH3_128bits_withSeed(state->buffer, (size_t)state->totalLen, state->seed);
7346 return XXH3_128bits_withSecret(state->buffer, (size_t)(state->totalLen),
7347 secret, state->secretLimit + XXH_STRIPE_LEN);
7348}
7349#endif /* !XXH_NO_STREAM */
7350/* 128-bit utility functions */
7351
7352/* return : 1 is equal, 0 if different */
7355{
7356 /* note : XXH128_hash_t is compact, it has no padding byte */
7357 return !(XXH_memcmp(&h1, &h2, sizeof(h1)));
7358}
7359
7360/* This prototype is compatible with stdlib's qsort().
7361 * @return : >0 if *h128_1 > *h128_2
7362 * <0 if *h128_1 < *h128_2
7363 * =0 if *h128_1 == *h128_2 */
7365XXH_PUBLIC_API int XXH128_cmp(XXH_NOESCAPE const void* h128_1, XXH_NOESCAPE const void* h128_2)
7366{
7367 XXH128_hash_t const h1 = *(const XXH128_hash_t*)h128_1;
7368 XXH128_hash_t const h2 = *(const XXH128_hash_t*)h128_2;
7369 int const hcmp = (h1.high64 > h2.high64) - (h2.high64 > h1.high64);
7370 /* note : bets that, in most cases, hash values are different */
7371 if (hcmp) return hcmp;
7372 return (h1.low64 > h2.low64) - (h2.low64 > h1.low64);
7373}
7374
7375
7376/*====== Canonical representation ======*/
7378XXH_PUBLIC_API void
7380{
7381 XXH_STATIC_ASSERT(sizeof(XXH128_canonical_t) == sizeof(XXH128_hash_t));
7382 if (XXH_CPU_LITTLE_ENDIAN) {
7383 hash.high64 = XXH_swap64(hash.high64);
7384 hash.low64 = XXH_swap64(hash.low64);
7385 }
7386 XXH_memcpy(dst, &hash.high64, sizeof(hash.high64));
7387 XXH_memcpy((char*)dst + sizeof(hash.high64), &hash.low64, sizeof(hash.low64));
7388}
7389
7392XXH128_hashFromCanonical(XXH_NOESCAPE const XXH128_canonical_t* src)
7393{
7395 h.high64 = XXH_readBE64(src);
7396 h.low64 = XXH_readBE64(src->digest + 8);
7397 return h;
7398}
7399
7400
7401
7402/* ==========================================
7403 * Secret generators
7404 * ==========================================
7405 */
7406#define XXH_MIN(x, y) (((x) > (y)) ? (y) : (x))
7407
7408XXH_FORCE_INLINE void XXH3_combine16(void* dst, XXH128_hash_t h128)
7409{
7410 XXH_writeLE64( dst, XXH_readLE64(dst) ^ h128.low64 );
7411 XXH_writeLE64( (char*)dst+8, XXH_readLE64((char*)dst+8) ^ h128.high64 );
7412}
7413
7416XXH3_generateSecret(XXH_NOESCAPE void* secretBuffer, size_t secretSize, XXH_NOESCAPE const void* customSeed, size_t customSeedSize)
7417{
7418#if (XXH_DEBUGLEVEL >= 1)
7419 XXH_ASSERT(secretBuffer != NULL);
7420 XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN);
7421#else
7422 /* production mode, assert() are disabled */
7423 if (secretBuffer == NULL) return XXH_ERROR;
7424 if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR;
7425#endif
7426
7427 if (customSeedSize == 0) {
7428 customSeed = XXH3_kSecret;
7429 customSeedSize = XXH_SECRET_DEFAULT_SIZE;
7430 }
7431#if (XXH_DEBUGLEVEL >= 1)
7432 XXH_ASSERT(customSeed != NULL);
7433#else
7434 if (customSeed == NULL) return XXH_ERROR;
7435#endif
7436
7437 /* Fill secretBuffer with a copy of customSeed - repeat as needed */
7438 { size_t pos = 0;
7439 while (pos < secretSize) {
7440 size_t const toCopy = XXH_MIN((secretSize - pos), customSeedSize);
7441 XXH_memcpy((char*)secretBuffer + pos, customSeed, toCopy);
7442 pos += toCopy;
7443 } }
7444
7445 { size_t const nbSeg16 = secretSize / 16;
7446 size_t n;
7447 XXH128_canonical_t scrambler;
7448 XXH128_canonicalFromHash(&scrambler, XXH128(customSeed, customSeedSize, 0));
7449 for (n=0; n<nbSeg16; n++) {
7450 XXH128_hash_t const h128 = XXH128(&scrambler, sizeof(scrambler), n);
7451 XXH3_combine16((char*)secretBuffer + n*16, h128);
7452 }
7453 /* last segment */
7454 XXH3_combine16((char*)secretBuffer + secretSize - 16, XXH128_hashFromCanonical(&scrambler));
7455 }
7456 return XXH_OK;
7457}
7458
7460XXH_PUBLIC_API void
7461XXH3_generateSecret_fromSeed(XXH_NOESCAPE void* secretBuffer, XXH64_hash_t seed)
7462{
7463 XXH_ALIGN(XXH_SEC_ALIGN) xxh_u8 secret[XXH_SECRET_DEFAULT_SIZE];
7464 XXH3_initCustomSecret(secret, seed);
7465 XXH_ASSERT(secretBuffer != NULL);
7466 XXH_memcpy(secretBuffer, secret, XXH_SECRET_DEFAULT_SIZE);
7467}
7468
7469
7470
7471/* Pop our optimization override from above */
7472#if XXH_VECTOR == XXH_AVX2 /* AVX2 */ \
7473 && defined(__GNUC__) && !defined(__clang__) /* GCC, not Clang */ \
7474 && defined(__OPTIMIZE__) && XXH_SIZE_OPT <= 0 /* respect -O0 and -Os */
7475# pragma GCC pop_options
7476#endif
7477
7478#endif /* XXH_NO_LONG_LONG */
7479
7480#endif /* XXH_NO_XXH3 */
7481
7485#endif /* XXH_IMPLEMENTATION */
7486
7487
7488#if defined (__cplusplus) && !defined(XXH_NO_EXTERNC_GUARD)
7489} /* extern "C" */
7490#endif
entt::handle b
entt::handle a
float y
float x
struct XXH32_state_s XXH32_state_t
The opaque state struct for the XXH32 streaming API.
Definition xxhash.h:654
XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32_digest(const XXH32_state_t *statePtr)
Returns the calculated hash value from an XXH32_state_t.
XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32(const void *input, size_t length, XXH32_hash_t seed)
Calculates the 32-bit hash of input using xxHash32.
XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t *statePtr, XXH32_hash_t seed)
Resets an XXH32_state_t to begin a new hash.
XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t *dst_state, const XXH32_state_t *src_state)
Copies one XXH32_state_t to another.
XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t *statePtr)
Frees an XXH32_state_t.
XXH_PUBLIC_API XXH_errorcode XXH32_update(XXH32_state_t *statePtr, const void *input, size_t length)
Consumes a block of input to an XXH32_state_t.
XXH_PUBLIC_API XXH_MALLOCF XXH32_state_t * XXH32_createState(void)
Allocates an XXH32_state_t.
XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t *dst, XXH32_hash_t hash)
Converts an XXH32_hash_t to a big endian XXH32_canonical_t.
XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t *src)
Converts an XXH32_canonical_t to a native XXH32_hash_t.
XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_withSeed(XXH_NOESCAPE const void *input, size_t length, XXH64_hash_t seed)
Calculates 64-bit seeded variant of XXH3 hash of input.
XXH_PUBLIC_API void XXH128_canonicalFromHash(XXH_NOESCAPE XXH128_canonical_t *dst, XXH128_hash_t hash)
Converts an XXH128_hash_t to a big endian XXH128_canonical_t.
XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH128_hashFromCanonical(XXH_NOESCAPE const XXH128_canonical_t *src)
Converts an XXH128_canonical_t to a native XXH128_hash_t.
XXH_PUBLIC_API XXH_errorcode XXH3_64bits_update(XXH_NOESCAPE XXH3_state_t *statePtr, XXH_NOESCAPE const void *input, size_t length)
Consumes a block of input to an XXH3_state_t.
XXH_PUBLIC_API XXH_MALLOCF XXH3_state_t * XXH3_createState(void)
XXH_PUBLIC_API XXH_PUREF int XXH128_cmp(XXH_NOESCAPE const void *h128_1, XXH_NOESCAPE const void *h128_2)
Compares two XXH128_hash_t.
XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset(XXH_NOESCAPE XXH3_state_t *statePtr)
Resets an XXH3_state_t to begin a new hash.
XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_digest(XXH_NOESCAPE const XXH3_state_t *statePtr)
Returns the calculated XXH3 128-bit hash value from an XXH3_state_t.
XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_digest(XXH_NOESCAPE const XXH3_state_t *statePtr)
Returns the calculated XXH3 64-bit hash value from an XXH3_state_t.
XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_withSecret(XXH_NOESCAPE const void *data, size_t len, XXH_NOESCAPE const void *secret, size_t secretSize)
Calculates 128-bit variant of XXH3 with a custom "secret".
XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset(XXH_NOESCAPE XXH3_state_t *statePtr)
Resets an XXH3_state_t to begin a new hash.
XXH_PUBLIC_API XXH_PUREF int XXH128_isEqual(XXH128_hash_t h1, XXH128_hash_t h2)
Check equality of two XXH128_hash_t values.
struct XXH3_state_s XXH3_state_t
The opaque state struct for the XXH3 streaming API.
Definition xxhash.h:1236
XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t *statePtr, XXH64_hash_t seed)
Resets an XXH3_state_t with 64-bit seed to begin a new hash.
XXH_PUBLIC_API XXH_errorcode XXH3_freeState(XXH3_state_t *statePtr)
XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits(XXH_NOESCAPE const void *data, size_t len)
Calculates 128-bit unseeded variant of XXH3 of data.
XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t *statePtr, XXH_NOESCAPE const void *secret, size_t secretSize)
Resets an XXH3_state_t with secret data to begin a new hash.
XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t *statePtr, XXH_NOESCAPE const void *secret, size_t secretSize)
Resets an XXH3_state_t with secret data to begin a new hash.
XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_withSeed(XXH_NOESCAPE const void *data, size_t len, XXH64_hash_t seed)
Calculates 128-bit seeded variant of XXH3 hash of data.
XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t *statePtr, XXH64_hash_t seed)
Resets an XXH3_state_t with 64-bit seed to begin a new hash.
XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_withSecret(XXH_NOESCAPE const void *data, size_t len, XXH_NOESCAPE const void *secret, size_t secretSize)
Calculates 64-bit variant of XXH3 with a custom "secret".
XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits(XXH_NOESCAPE const void *input, size_t length)
Calculates 64-bit unseeded variant of XXH3 hash of input.
XXH_PUBLIC_API void XXH3_copyState(XXH_NOESCAPE XXH3_state_t *dst_state, XXH_NOESCAPE const XXH3_state_t *src_state)
Copies one XXH3_state_t to another.
XXH_PUBLIC_API XXH_errorcode XXH3_128bits_update(XXH_NOESCAPE XXH3_state_t *statePtr, XXH_NOESCAPE const void *input, size_t length)
Consumes a block of input to an XXH3_state_t.
#define XXH3_SECRET_SIZE_MIN
Definition xxhash.h:1184
struct XXH64_state_s XXH64_state_t
The opaque state struct for the XXH64 streaming API.
Definition xxhash.h:919
XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH_NOESCAPE XXH64_state_t *statePtr, XXH64_hash_t seed)
Resets an XXH64_state_t to begin a new hash.
XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64(XXH_NOESCAPE const void *input, size_t length, XXH64_hash_t seed)
Calculates the 64-bit hash of input using xxHash64.
XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH_NOESCAPE XXH64_canonical_t *dst, XXH64_hash_t hash)
Converts an XXH64_hash_t to a big endian XXH64_canonical_t.
XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64_hashFromCanonical(XXH_NOESCAPE const XXH64_canonical_t *src)
Converts an XXH64_canonical_t to a native XXH64_hash_t.
XXH_PUBLIC_API void XXH64_copyState(XXH_NOESCAPE XXH64_state_t *dst_state, const XXH64_state_t *src_state)
Copies one XXH64_state_t to another.
XXH_PUBLIC_API XXH_errorcode XXH64_update(XXH_NOESCAPE XXH64_state_t *statePtr, XXH_NOESCAPE const void *input, size_t length)
Consumes a block of input to an XXH64_state_t.
XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64_digest(XXH_NOESCAPE const XXH64_state_t *statePtr)
Returns the calculated hash value from an XXH64_state_t.
XXH_PUBLIC_API XXH_MALLOCF XXH64_state_t * XXH64_createState(void)
Allocates an XXH64_state_t.
XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t *statePtr)
Frees an XXH64_state_t.
unsigned long long XXH64_hash_t
Definition xxhash.h:875
#define XXH_PUREF
Definition xxhash.h:542
XXH_errorcode
Exit code for the streaming API.
Definition xxhash.h:573
#define XXH_PUBLIC_API
Marks a global symbol.
Definition xxhash.h:458
#define XXH_MALLOCF
Definition xxhash.h:543
#define XXH_VERSION_NUMBER
Version number, encoded as two digits each.
Definition xxhash.h:553
#define XXH_CONSTF
Definition xxhash.h:541
XXH_PUBLIC_API XXH_CONSTF unsigned XXH_versionNumber(void)
Obtains the xxHash version.
@ XXH_ERROR
Definition xxhash.h:575
@ XXH_OK
Definition xxhash.h:574
@ mask
Hard alpha cutoff; casts cutout shadows.
uint32_t count
std::vector< math::vec3 > start
size_t total_len
The return value from 128-bit hashes.
Definition xxhash.h:1375
XXH64_hash_t low64
Definition xxhash.h:1376
XXH64_hash_t high64
Definition xxhash.h:1377
Canonical (big endian) representation of XXH32_hash_t.
Definition xxhash.h:755
Canonical (big endian) representation of XXH64_hash_t.
Definition xxhash.h:1020