53 constexpr int cpp_version_major = 0;
54 constexpr int cpp_version_minor = 7;
55 constexpr int cpp_version_release = 3;
58 constexpr uint32_t version_number() {
59 return version::cpp_version_major * 10000 + version::cpp_version_minor * 100 + version::cpp_version_release;
73 return (low64 == other.low64 && high64 == other.high64);
77 return (high64 > other.high64 || low64 > other.low64);
81 return (*
this > other || *
this == other);
85 return !(*
this >= other);
89 return !(*
this > other);
93 return !(*
this == other);
96 uint128_t(uint64_t low, uint64_t high) : low64(low), high64(high) {}
116#ifndef XXH_CPU_LITTLE_ENDIAN
117#define XXH_CPU_LITTLE_ENDIAN 1
130#elif defined(__SSE2__) || defined(_M_AMD64) || defined(_M_X64) || (defined(_M_IX86_FP) && (_M_IX86_FP == 2))
137 constexpr int vector_mode = XXH_VECTOR;
140 constexpr int acc_align = 32;
141 using avx2_underlying = __m256i;
142 using sse2_underlying = __m128i;
144 using avx2_underlying = void;
145 using sse2_underlying = __m128i;
146 constexpr int acc_align = 16;
148 using avx2_underlying = void;
149 using sse2_underlying = void;
150 constexpr int acc_align = 8;
157#ifdef XXH_FORCE_INLINE
158#undef XXH_FORCE_INLINE
165 #pragma warning(disable : 4127)
166#define XXH_FORCE_INLINE static __forceinline
167#define XXH_NO_INLINE static __declspec(noinline)
169#elif defined(__GNUC__)
170#define XXH_FORCE_INLINE static inline __attribute__((always_inline))
171#define XXH_NO_INLINE static __attribute__((noinline))
174 #define XXH_FORCE_INLINE static inline
175#define XXH_NO_INLINE static
182#if defined(XXH_NO_PREFETCH)
183 XXH_FORCE_INLINE
void prefetch(
const void *ptr) {}
184#elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86))
185 XXH_FORCE_INLINE
void prefetch(
const void *ptr) { _mm_prefetch((
const char *) (ptr), _MM_HINT_T0); }
186#elif defined(__GNUC__)
187 XXH_FORCE_INLINE
void prefetch(
const void *ptr) { __builtin_prefetch((ptr), 0, 3); }
189 XXH_FORCE_INLINE
void prefetch(
const void *ptr) {}
201#if (defined(__GNUC__) || defined(_MSC_VER)) && defined(__cplusplus) && !defined(XXH_NO_RESTRICT)
202#define XXH_RESTRICT __restrict
213#if ((defined(__GNUC__) && (__GNUC__ >= 3)) || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) || defined(__clang__)) && !defined(XXH_NO_BRANCH_HINTS)
214#define XXH_likely(x) __builtin_expect(x, 1)
215#define XXH_unlikely(x) __builtin_expect(x, 0)
217 #define XXH_likely(x) (x)
218#define XXH_unlikely(x) (x)
224 static inline uint32_t rotl32(uint32_t x, int32_t r) {
return _rotl(x, r); }
225 static inline uint64_t rotl64(uint64_t x, int32_t r) {
return _rotl64(x, r); }
226 static inline uint32_t rotr32(uint32_t x, int32_t r) {
return _rotr(x, r); }
227 static inline uint64_t rotr64(uint64_t x, int32_t r) {
return _rotr64(x, r); }
229 static inline uint32_t rotl32(uint32_t x, int32_t r) {
return ((x << r) | (x >> (32 - r))); }
230 static inline uint64_t rotl64(uint64_t x, int32_t r) {
return ((x << r) | (x >> (64 - r))); }
231 static inline uint32_t rotr32(uint32_t x, int32_t r) {
return ((x >> r) | (x << (32 - r))); }
232 static inline uint64_t rotr64(uint64_t x, int32_t r) {
return ((x >> r) | (x << (64 - r))); }
237 static inline uint32_t swap32(uint32_t x) {
return _byteswap_ulong(x); }
238 static inline uint64_t swap64(uint64_t x) {
return _byteswap_uint64(x); }
239#elif defined(__GNUC__)
240 static inline uint32_t swap32(uint32_t x) {
return __builtin_bswap32(x); }
241 static inline uint64_t swap64(uint64_t x) {
return __builtin_bswap64(x); }
243 static inline uint32_t swap32(uint32_t x) {
return ((x << 24) & 0xff000000) | ((x << 8) & 0x00ff0000) | ((x >> 8) & 0x0000ff00) | ((x >> 24) & 0x000000ff); }
244 static inline uint64_t swap64(uint64_t x) {
return ((x << 56) & 0xff00000000000000ULL) | ((x << 40) & 0x00ff000000000000ULL) | ((x << 24) & 0x0000ff0000000000ULL) | ((x << 8) & 0x000000ff00000000ULL) | ((x >> 8) & 0x00000000ff000000ULL) | ((x >> 24) & 0x0000000000ff0000ULL) | ((x >> 40) & 0x000000000000ff00ULL) | ((x >> 56) & 0x00000000000000ffULL); }
248#if defined(_MSC_VER) && defined(_M_IX86)
249 XXH_FORCE_INLINE uint64_t mult32to64(uint32_t x, uint32_t y) {
return __emulu(x, y); }
251 XXH_FORCE_INLINE uint64_t mult32to64(uint32_t x, uint32_t y) {
return (uint64_t)(uint32_t)(x) * (uint64_t)(uint32_t)(y); }
255#if defined(__GNUC__) && !defined(__clang__) && defined(__i386__)
256 __attribute__((__target__(
"no-sse")))
258 static inline uint128_t
259 mult64to128(uint64_t lhs, uint64_t rhs) {
261#if defined(__GNUC__) && !defined(__wasm__) && defined(__SIZEOF_INT128__) || (defined(_INTEGRAL_MAX_BITS) && _INTEGRAL_MAX_BITS >= 128)
263 __uint128_t product = (__uint128_t) lhs * (__uint128_t) rhs;
264 uint128_t
const r128 = {(uint64_t)(product), (uint64_t)(product >> 64)};
267#elif defined(_M_X64) || defined(_M_IA64)
270#pragma intrinsic(_umul128)
272 uint64_t product_high;
273 uint64_t
const product_low = _umul128(lhs, rhs, &product_high);
274 return uint128_t{product_low, product_high};
276 uint64_t
const lo_lo = bit_ops::mult32to64(lhs & 0xFFFFFFFF, rhs & 0xFFFFFFFF);
277 uint64_t
const hi_lo = bit_ops::mult32to64(lhs >> 32, rhs & 0xFFFFFFFF);
278 uint64_t
const lo_hi = bit_ops::mult32to64(lhs & 0xFFFFFFFF, rhs >> 32);
279 uint64_t
const hi_hi = bit_ops::mult32to64(lhs >> 32, rhs >> 32);
282 uint64_t
const cross = (lo_lo >> 32) + (hi_lo & 0xFFFFFFFF) + lo_hi;
283 uint64_t
const upper = (hi_lo >> 32) + (cross >> 32) + hi_hi;
284 uint64_t
const lower = (cross << 32) | (lo_lo & 0xFFFFFFFF);
286 uint128_t r128 = {lower, upper};
310 using type = uint32_t;
315 using type = uint64_t;
331 using type = uint64_t;
336 using type = intrin::sse2_underlying;
341 using type = intrin::avx2_underlying;
358 using type = uint32_t;
363 using type = uint64_t;
373 using hash_t =
typename typedefs::hash_type<N>::type;
374 using hash32_t = hash_t<32>;
375 using hash64_t = hash_t<64>;
376 using hash128_t = hash_t<128>;
379 using vec_t =
typename typedefs::vec_type<N>::type;
380 using vec64_t = vec_t<64>;
381 using vec128_t = vec_t<128>;
382 using vec256_t = vec_t<256>;
385 using uint_t =
typename typedefs::uint_type<N>::type;
398 static inline uint_t<N> rotl(uint_t<N> n, int32_t r) {
399 if constexpr (N == 32) {
400 return intrin::bit_ops::rotl32(n, r);
403 if constexpr (N == 64) {
404 return intrin::bit_ops::rotl64(n, r);
409 static inline uint_t<N> rotr(uint_t<N> n, int32_t r) {
410 if constexpr (N == 32) {
411 return intrin::bit_ops::rotr32(n, r);
414 if constexpr (N == 64) {
415 return intrin::bit_ops::rotr64(n, r);
420 static inline uint_t<N> swap(uint_t<N> n) {
421 if constexpr (N == 32) {
422 return intrin::bit_ops::swap32(n);
425 if constexpr (N == 64) {
426 return intrin::bit_ops::swap64(n);
430 static inline uint64_t mul32to64(uint32_t x, uint32_t y) {
431 return intrin::bit_ops::mult32to64(x, y);
434 static inline uint128_t mul64to128(uint64_t x, uint64_t y) {
435 return intrin::bit_ops::mult64to128(x, y);
438 static inline uint64_t mul128fold64(uint64_t x, uint64_t y) {
439 uint128_t product = mul64to128(x, y);
441 return (product.low64 ^ product.high64);
456 constexpr bool is_little_endian() {
457 return (XXH_CPU_LITTLE_ENDIAN == 1);
466 static inline uint_t<N> read(
const void *memPtr) {
469 memcpy(&val, memPtr,
sizeof(val));
474 static inline uint_t<N> readLE(
const void *ptr) {
475 if constexpr (is_little_endian()) {
478 return bit_ops::swap<N>(read<N>(ptr));
483 static inline uint_t<N> readBE(
const void *ptr) {
484 if constexpr (is_little_endian()) {
485 return bit_ops::swap<N>(read<N>(ptr));
492 static void writeLE(
void *dst, uint_t<N> v) {
493 if constexpr (!is_little_endian()) {
494 v = bit_ops::swap<N>(v);
497 memcpy(dst, &v,
sizeof(v));
508 XXH_FORCE_INLINE vec_t<N> loadu(
const vec_t<N> *input) {
509 static_assert(!(N != 128 && N != 256 && N != 64),
"Invalid template argument passed to xxh::vec_ops::loadu");
511 if constexpr (N == 128) {
512 return _mm_loadu_si128(input);
515 if constexpr (N == 256) {
516 return _mm256_loadu_si256(input);
519 if constexpr (N == 64) {
520 return mem_ops::readLE<64>(input);
527 XXH_FORCE_INLINE vec_t<N> xorv(vec_t<N> a, vec_t<N> b) {
528 static_assert(!(N != 128 && N != 256 && N != 64),
"Invalid argument passed to xxh::vec_ops::xorv");
530 if constexpr (N == 128) {
531 return _mm_xor_si128(a, b);
534 if constexpr (N == 256) {
535 return _mm256_xor_si256(a, b);
538 if constexpr (N == 64) {
545 XXH_FORCE_INLINE vec_t<N> mul(vec_t<N> a, vec_t<N> b) {
546 static_assert(!(N != 128 && N != 256 && N != 64),
"Invalid argument passed to xxh::vec_ops::mul");
548 if constexpr (N == 128) {
549 return _mm_mul_epu32(a, b);
552 if constexpr (N == 256) {
553 return _mm256_mul_epu32(a, b);
556 if constexpr (N == 64) {
563 XXH_FORCE_INLINE vec_t<N> add(vec_t<N> a, vec_t<N> b) {
564 static_assert(!(N != 128 && N != 256 && N != 64),
"Invalid argument passed to xxh::vec_ops::add");
566 if constexpr (N == 128) {
567 return _mm_add_epi64(a, b);
570 if constexpr (N == 256) {
571 return _mm256_add_epi64(a, b);
574 if constexpr (N == 64) {
580 template<
size_t N, u
int8_t S1, u
int8_t S2, u
int8_t S3, u
int8_t S4>
581 XXH_FORCE_INLINE vec_t<N> shuffle(vec_t<N> a) {
582 static_assert(!(N != 128 && N != 256 && N != 64),
"Invalid argument passed to xxh::vec_ops::shuffle");
584 if constexpr (N == 128) {
585 return _mm_shuffle_epi32(a, _MM_SHUFFLE(S1, S2, S3, S4));
588 if constexpr (N == 256) {
589 return _mm256_shuffle_epi32(a, _MM_SHUFFLE(S1, S2, S3, S4));
592 if constexpr (N == 64) {
599 XXH_FORCE_INLINE vec_t<N> set1(
int a) {
600 static_assert(!(N != 128 && N != 256 && N != 64),
"Invalid argument passed to xxh::vec_ops::set1");
602 if constexpr (N == 128) {
603 return _mm_set1_epi32(a);
606 if constexpr (N == 256) {
607 return _mm256_set1_epi32(a);
610 if constexpr (N == 64) {
617 XXH_FORCE_INLINE vec_t<N> srli(vec_t<N> n,
int a) {
618 static_assert(!(N != 128 && N != 256 && N != 64),
"Invalid argument passed to xxh::vec_ops::srli");
620 if constexpr (N == 128) {
621 return _mm_srli_epi64(n, a);
624 if constexpr (N == 256) {
625 return _mm256_srli_epi64(n, a);
628 if constexpr (N == 64) {
635 XXH_FORCE_INLINE vec_t<N> slli(vec_t<N> n,
int a) {
636 static_assert(!(N != 128 && N != 256 && N != 64),
"Invalid argument passed to xxh::vec_ops::slli");
638 if constexpr (N == 128) {
639 return _mm_slli_epi64(n, a);
642 if constexpr (N == 256) {
643 return _mm256_slli_epi64(n, a);
646 if constexpr (N == 64) {
658 using namespace mem_ops;
659 using namespace bit_ops;
666 constexpr static std::array<uint32_t, 5> primes32 = {2654435761U, 2246822519U, 3266489917U, 668265263U, 374761393U};
667 constexpr static std::array<uint64_t, 5> primes64 = {11400714785074694791ULL, 14029467366897019727ULL, 1609587929392839161ULL, 9650029242287828579ULL, 2870177450012600261ULL};
670 constexpr uint_t<N> PRIME(uint64_t n) {
671 if constexpr (N == 32) {
672 return primes32[n - 1];
674 return primes64[n - 1];
684 static inline uint_t<N> round(uint_t<N> seed, uint_t<N> input) {
685 seed += input * PRIME<N>(2);
687 if constexpr (N == 32) {
688 seed = rotl<N>(seed, 13);
690 seed = rotl<N>(seed, 31);
697 static inline uint64_t mergeRound64(hash64_t acc, uint64_t val) {
698 val = round<64>(0, val);
700 acc = acc * PRIME<64>(1) + PRIME<64>(4);
704 static inline void endian_align_sub_mergeround(hash64_t &hash_ret, uint64_t v1, uint64_t v2, uint64_t v3, uint64_t v4) {
705 hash_ret = mergeRound64(hash_ret, v1);
706 hash_ret = mergeRound64(hash_ret, v2);
707 hash_ret = mergeRound64(hash_ret, v3);
708 hash_ret = mergeRound64(hash_ret, v4);
712 static inline hash_t<N> endian_align_sub_ending(hash_t<N> hash_ret,
const uint8_t *p,
const uint8_t *bEnd) {
713 if constexpr (N == 32) {
714 while ((p + 4) <= bEnd) {
715 hash_ret += readLE<32>(p) * PRIME<32>(3);
716 hash_ret = rotl<32>(hash_ret, 17) * PRIME<32>(4);
721 hash_ret += (*p) * PRIME<32>(5);
722 hash_ret = rotl<32>(hash_ret, 11) * PRIME<32>(1);
726 hash_ret ^= hash_ret >> 15;
727 hash_ret *= PRIME<32>(2);
728 hash_ret ^= hash_ret >> 13;
729 hash_ret *= PRIME<32>(3);
730 hash_ret ^= hash_ret >> 16;
734 while (p + 8 <= bEnd) {
735 const uint64_t k1 = round<64>(0, readLE<64>(p));
738 hash_ret = rotl<64>(hash_ret, 27) * PRIME<64>(1) + PRIME<64>(4);
743 hash_ret ^=
static_cast<uint64_t
>(readLE<32>(p)) * PRIME<64>(1);
744 hash_ret = rotl<64>(hash_ret, 23) * PRIME<64>(2) + PRIME<64>(3);
749 hash_ret ^= (*p) * PRIME<64>(5);
750 hash_ret = rotl<64>(hash_ret, 11) * PRIME<64>(1);
754 hash_ret ^= hash_ret >> 33;
755 hash_ret *= PRIME<64>(2);
756 hash_ret ^= hash_ret >> 29;
757 hash_ret *= PRIME<64>(3);
758 hash_ret ^= hash_ret >> 32;
765 static inline hash_t<N> endian_align(
const void *input,
size_t len, uint_t<N> seed) {
766 static_assert(!(N != 32 && N != 64),
"You can only call endian_align in 32 or 64 bit mode.");
768 const uint8_t *p =
static_cast<const uint8_t *
>(input);
769 const uint8_t *bEnd = p + len;
772 if (len >= (N / 2)) {
773 const uint8_t *
const limit = bEnd - (N / 2);
774 uint_t<N> v1 = seed + PRIME<N>(1) + PRIME<N>(2);
775 uint_t<N> v2 = seed + PRIME<N>(2);
776 uint_t<N> v3 = seed + 0;
777 uint_t<N> v4 = seed - PRIME<N>(1);
780 v1 = round<N>(v1, readLE<N>(p));
782 v2 = round<N>(v2, readLE<N>(p));
784 v3 = round<N>(v3, readLE<N>(p));
786 v4 = round<N>(v4, readLE<N>(p));
788 }
while (p <= limit);
790 hash_ret = rotl<N>(v1, 1) + rotl<N>(v2, 7) + rotl<N>(v3, 12) + rotl<N>(v4, 18);
792 if constexpr (N == 64) {
793 endian_align_sub_mergeround(hash_ret, v1, v2, v3, v4);
796 hash_ret = seed + PRIME<N>(5);
799 hash_ret +=
static_cast<hash_t<N>
>(len);
801 return endian_align_sub_ending<N>(hash_ret, p, bEnd);
811 using namespace vec_ops;
812 using namespace detail;
813 using namespace mem_ops;
814 using namespace bit_ops;
821 enum class acc_width : uint8_t { acc_64bits,
823 enum class vec_mode : uint8_t { scalar = 0,
832 constexpr uint64_t secret_default_size = 192;
833 constexpr uint64_t secret_size_min = 136;
834 constexpr uint64_t secret_consume_rate = 8;
835 constexpr uint64_t stripe_len = 64;
836 constexpr uint64_t acc_nb = 8;
837 constexpr uint64_t prefetch_distance = 384;
838 constexpr uint64_t secret_lastacc_start = 7;
839 constexpr uint64_t secret_mergeaccs_start = 11;
840 constexpr uint64_t midsize_max = 240;
841 constexpr uint64_t midsize_startoffset = 3;
842 constexpr uint64_t midsize_lastoffset = 17;
844 constexpr vec_mode vector_mode =
static_cast<vec_mode
>(intrin::vector_mode);
845 constexpr uint64_t acc_align = intrin::acc_align;
846 constexpr std::array<uint64_t, 3> vector_bit_width{64, 128, 256};
853 alignas(64)
constexpr uint8_t default_secret[secret_default_size] = {
1048 constexpr std::array<uint64_t, 8> init_acc = {PRIME<32>(3), PRIME<64>(1), PRIME<64>(2), PRIME<64>(3), PRIME<64>(4), PRIME<32>(2), PRIME<64>(5), PRIME<32>(1)};
1055 static hash_t<64> avalanche(hash_t<64> h64) {
1056 constexpr uint64_t avalanche_mul_prime = 0x165667919E3779F9ULL;
1059 h64 *= avalanche_mul_prime;
1064 template<vec_mode V>
1065 XXH_FORCE_INLINE
void accumulate_512(
void *XXH_RESTRICT acc,
const void *XXH_RESTRICT input,
const void *XXH_RESTRICT secret, acc_width width) {
1066 constexpr uint64_t bits = vector_bit_width[
static_cast<uint8_t
>(V)];
1068 using vec_t = vec_t<bits>;
1070 alignas(
sizeof(vec_t)) vec_t *
const xacc =
static_cast<vec_t *
>(acc);
1071 const vec_t *
const xinput =
static_cast<const vec_t *
>(input);
1072 const vec_t *
const xsecret =
static_cast<const vec_t *
>(secret);
1074 for (
size_t i = 0; i < stripe_len /
sizeof(vec_t); i++) {
1075 vec_t
const data_vec = loadu<bits>(xinput + i);
1076 vec_t
const key_vec = loadu<bits>(xsecret + i);
1077 vec_t
const data_key = xorv<bits>(data_vec, key_vec);
1078 vec_t product = set1<bits>(0);
1080 if constexpr (V != vec_mode::scalar) {
1081 vec_t
const data_key_lo = shuffle<bits, 0, 3, 0, 1>(data_key);
1083 product = mul<bits>(data_key, data_key_lo);
1085 if (width == acc_width::acc_128bits) {
1086 vec_t
const data_swap = shuffle<bits, 1, 0, 3, 2>(data_vec);
1087 vec_t
const sum = add<bits>(xacc[i], data_swap);
1089 xacc[i] = add<bits>(sum, product);
1091 vec_t
const sum = add<bits>(xacc[i], data_vec);
1093 xacc[i] = add<bits>(sum, product);
1096 product = mul32to64(data_key & 0xFFFFFFFF, data_key >> 32);
1098 if (width == acc_width::acc_128bits) {
1099 xacc[i ^ 1] = add<bits>(xacc[i ^ 1], data_vec);
1101 xacc[i] = add<bits>(xacc[i], data_vec);
1104 xacc[i] = add<bits>(xacc[i], product);
1109 template<vec_mode V>
1110 XXH_FORCE_INLINE
void scramble_acc(
void *XXH_RESTRICT acc,
const void *XXH_RESTRICT secret) {
1111 constexpr uint64_t bits = vector_bit_width[
static_cast<uint8_t
>(V)];
1114 using vec_t = vec_t<bits>;
1116 alignas(
sizeof(vec_t)) vec_t *
const xacc = (vec_t *) acc;
1117 const vec_t *
const xsecret = (
const vec_t *) secret;
1119 for (
size_t i = 0; i < stripe_len /
sizeof(vec_t); i++) {
1120 vec_t
const acc_vec = xacc[i];
1121 vec_t
const shifted = srli<bits>(acc_vec, 47);
1122 vec_t
const data_vec = xorv<bits>(acc_vec, shifted);
1123 vec_t
const key_vec = loadu<bits>(xsecret + i);
1124 vec_t
const data_key = xorv<bits>(data_vec, key_vec);
1126 if constexpr (V != vec_mode::scalar) {
1127 vec_t
const prime32 = set1<bits>(PRIME<32>(1));
1128 vec_t
const data_key_hi = shuffle<bits, 0, 3, 0, 1>(data_key);
1129 vec_t
const prod_lo = mul<bits>(data_key, prime32);
1130 vec_t
const prod_hi = mul<bits>(data_key_hi, prime32);
1132 xacc[i] = add<bits>(prod_lo, vec_ops::slli<bits>(prod_hi, 32));
1134 xacc[i] = mul<bits>(data_key, PRIME<32>(1));
1139 XXH_FORCE_INLINE
void accumulate(uint64_t *XXH_RESTRICT acc,
const uint8_t *XXH_RESTRICT input,
const uint8_t *XXH_RESTRICT secret,
size_t nbStripes, acc_width accWidth) {
1140 for (
size_t n = 0; n < nbStripes; n++) {
1141 const uint8_t *
const in = input + n * stripe_len;
1143 intrin::prefetch(in + prefetch_distance);
1144 accumulate_512<vector_mode>(acc, in, secret + n * secret_consume_rate, accWidth);
1148 XXH_FORCE_INLINE
void hash_long_internal_loop(uint64_t *XXH_RESTRICT acc,
const uint8_t *XXH_RESTRICT input,
size_t len,
const uint8_t *XXH_RESTRICT secret,
size_t secretSize, acc_width accWidth) {
1149 size_t const nb_rounds = (secretSize - stripe_len) / secret_consume_rate;
1150 size_t const block_len = stripe_len * nb_rounds;
1151 size_t const nb_blocks = len / block_len;
1153 for (
size_t n = 0; n < nb_blocks; n++) {
1154 accumulate(acc, input + n * block_len, secret, nb_rounds, accWidth);
1155 scramble_acc<vector_mode>(acc, secret + secretSize - stripe_len);
1159 size_t const nbStripes = (len - (block_len * nb_blocks)) / stripe_len;
1161 accumulate(acc, input + nb_blocks * block_len, secret, nbStripes, accWidth);
1164 if (len & (stripe_len - 1)) {
1165 const uint8_t *
const p = input + len - stripe_len;
1167 accumulate_512<vector_mode>(acc, p, secret + secretSize - stripe_len - secret_lastacc_start, accWidth);
1171 XXH_FORCE_INLINE uint64_t mix_2_accs(
const uint64_t *XXH_RESTRICT acc,
const uint8_t *XXH_RESTRICT secret) {
1172 return mul128fold64(acc[0] ^ readLE<64>(secret), acc[1] ^ readLE<64>(secret + 8));
1175 XXH_FORCE_INLINE uint64_t merge_accs(
const uint64_t *XXH_RESTRICT acc,
const uint8_t *XXH_RESTRICT secret, uint64_t start) {
1176 uint64_t result64 = start;
1178 result64 += mix_2_accs(acc + 0, secret + 0);
1179 result64 += mix_2_accs(acc + 2, secret + 16);
1180 result64 += mix_2_accs(acc + 4, secret + 32);
1181 result64 += mix_2_accs(acc + 6, secret + 48);
1183 return avalanche(result64);
1186 XXH_FORCE_INLINE
void init_custom_secret(uint8_t *customSecret, uint64_t seed) {
1187 for (uint64_t i = 0; i < secret_default_size / 16; i++) {
1188 writeLE<64>(customSecret + i * 16, readLE<64>(default_secret + i * 16) + seed);
1189 writeLE<64>(customSecret + i * 16 + 8, readLE<64>(default_secret + i * 16 + 8) - seed);
1194 XXH_FORCE_INLINE hash_t<N> len_1to3(
const uint8_t *input,
size_t len,
const uint8_t *secret, uint64_t seed) {
1195 if constexpr (N == 64) {
1196 uint8_t
const c1 = input[0];
1197 uint8_t
const c2 = input[len >> 1];
1198 uint8_t
const c3 = input[len - 1];
1199 uint32_t
const combined = ((uint32_t) c1 << 16) | (((uint32_t) c2) << 24) | (((uint32_t) c3) << 0) | (((uint32_t) len) << 8);
1200 uint64_t
const bitflip = (readLE<32>(secret) ^ readLE<32>(secret + 4)) + seed;
1201 uint64_t
const keyed = (uint64_t) combined ^ bitflip;
1202 uint64_t
const mixed = keyed * PRIME<64>(1);
1204 return avalanche(mixed);
1206 uint8_t
const c1 = input[0];
1207 uint8_t
const c2 = input[len >> 1];
1208 uint8_t
const c3 = input[len - 1];
1209 uint32_t
const combinedl = ((uint32_t) c1 << 16) + (((uint32_t) c2) << 24) + (((uint32_t) c3) << 0) + (((uint32_t) len) << 8);
1210 uint32_t
const combinedh = rotl<32>(swap<32>(combinedl), 13);
1211 uint64_t
const bitflipl = (readLE<32>(secret) ^ readLE<32>(secret + 4)) + seed;
1212 uint64_t
const bitfliph = (readLE<32>(secret + 8) ^ readLE<32>(secret + 12)) - seed;
1213 uint64_t
const keyed_lo = (uint64_t) combinedl ^ bitflipl;
1214 uint64_t
const keyed_hi = (uint64_t) combinedh ^ bitfliph;
1215 uint64_t
const mixedl = keyed_lo * PRIME<64>(1);
1216 uint64_t
const mixedh = keyed_hi * PRIME<64>(5);
1217 hash128_t
const h128 = {avalanche(mixedl), avalanche(mixedh)};
1224 XXH_FORCE_INLINE hash_t<N> len_4to8(
const uint8_t *input,
size_t len,
const uint8_t *secret, uint64_t seed) {
1225 constexpr uint64_t mix_constant = 0x9FB21C651E98DF25ULL;
1227 seed ^= (uint64_t) swap<32>((uint32_t) seed) << 32;
1229 if constexpr (N == 64) {
1230 uint32_t
const input1 = readLE<32>(input);
1231 uint32_t
const input2 = readLE<32>(input + len - 4);
1232 uint64_t
const bitflip = (readLE<64>(secret + 8) ^ readLE<64>(secret + 16)) - seed;
1233 uint64_t
const input64 = input2 + ((uint64_t) input1 << 32);
1234 uint64_t x = input64 ^ bitflip;
1236 x ^= rotl<64>(x, 49) ^ rotl<64>(x, 24);
1238 x ^= (x >> 35) + len;
1241 return (x ^ (x >> 28));
1243 uint32_t
const input_lo = readLE<32>(input);
1244 uint32_t
const input_hi = readLE<32>(input + len - 4);
1245 uint64_t
const input_64 = input_lo + ((uint64_t) input_hi << 32);
1246 uint64_t
const bitflip = (readLE<64>(secret + 16) ^ readLE<64>(secret + 24)) + seed;
1247 uint64_t
const keyed = input_64 ^ bitflip;
1248 uint128_t m128 = mul64to128(keyed, PRIME<64>(1) + (len << 2));
1250 m128.high64 += (m128.low64 << 1);
1251 m128.low64 ^= (m128.high64 >> 3);
1252 m128.low64 ^= (m128.low64 >> 35);
1253 m128.low64 *= mix_constant;
1254 m128.low64 ^= (m128.low64 >> 28);
1255 m128.high64 = avalanche(m128.high64);
1262 XXH_FORCE_INLINE hash_t<N> len_9to16(
const uint8_t *input,
size_t len,
const uint8_t *secret, uint64_t seed) {
1263 if constexpr (N == 64) {
1264 uint64_t
const bitflip1 = (readLE<64>(secret + 24) ^ readLE<64>(secret + 32)) + seed;
1265 uint64_t
const bitflip2 = (readLE<64>(secret + 40) ^ readLE<64>(secret + 48)) - seed;
1266 uint64_t
const input_lo = readLE<64>(input) ^ bitflip1;
1267 uint64_t
const input_hi = readLE<64>(input + len - 8) ^ bitflip2;
1268 uint64_t
const acc = len + swap<64>(input_lo) + input_hi + mul128fold64(input_lo, input_hi);
1270 return avalanche(acc);
1272 uint64_t
const bitflipl = (readLE<64>(secret + 32) ^ readLE<64>(secret + 40)) - seed;
1273 uint64_t
const bitfliph = (readLE<64>(secret + 48) ^ readLE<64>(secret + 56)) + seed;
1274 uint64_t
const input_lo = readLE<64>(input);
1275 uint64_t input_hi = readLE<64>(input + len - 8);
1276 uint128_t m128 = mul64to128(input_lo ^ input_hi ^ bitflipl, PRIME<64>(1));
1278 m128.low64 += (uint64_t)(len - 1) << 54;
1279 input_hi ^= bitfliph;
1281 if constexpr (
sizeof(
void *) <
sizeof(uint64_t))
1283 m128.high64 += (input_hi & 0xFFFFFFFF00000000) + mul32to64((uint32_t) input_hi, PRIME<32>(2));
1285 m128.high64 += input_hi + mul32to64((uint32_t) input_hi, PRIME<32>(2) - 1);
1288 m128.low64 ^= swap<64>(m128.high64);
1290 hash128_t h128 = mul64to128(m128.low64, PRIME<64>(2));
1292 h128.high64 += m128.high64 * PRIME<64>(2);
1293 h128.low64 = avalanche(h128.low64);
1294 h128.high64 = avalanche(h128.high64);
1301 XXH_FORCE_INLINE hash_t<N> len_0to16(
const uint8_t *input,
size_t len,
const uint8_t *secret, uint64_t seed) {
1302 if (XXH_likely(len > 8)) {
1303 return len_9to16<N>(input, len, secret, seed);
1304 }
else if (XXH_likely(len >= 4)) {
1305 return len_4to8<N>(input, len, secret, seed);
1307 return len_1to3<N>(input, len, secret, seed);
1309 if constexpr (N == 64) {
1310 return avalanche((PRIME<64>(1) + seed) ^ (readLE<64>(secret + 56) ^ readLE<64>(secret + 64)));
1312 uint64_t
const bitflipl = readLE<64>(secret + 64) ^ readLE<64>(secret + 72);
1313 uint64_t
const bitfliph = readLE<64>(secret + 80) ^ readLE<64>(secret + 88);
1315 return hash128_t(avalanche((PRIME<64>(1) + seed) ^ bitflipl), avalanche((PRIME<64>(2) - seed) ^ bitfliph));
1321 XXH_FORCE_INLINE hash_t<N> hash_long_internal(
const uint8_t *XXH_RESTRICT input,
size_t len,
const uint8_t *XXH_RESTRICT secret = default_secret,
size_t secretSize =
sizeof(default_secret)) {
1322 alignas(acc_align) std::array<uint64_t, acc_nb> acc = init_acc;
1324 if constexpr (N == 64) {
1325 hash_long_internal_loop(acc.data(), input, len, secret, secretSize, acc_width::acc_64bits);
1328 return merge_accs(acc.data(), secret + secret_mergeaccs_start, (uint64_t) len * PRIME<64>(1));
1330 hash_long_internal_loop(acc.data(), input, len, secret, secretSize, acc_width::acc_128bits);
1333 uint64_t
const low64 = merge_accs(acc.data(), secret + secret_mergeaccs_start, (uint64_t) len * PRIME<64>(1));
1334 uint64_t
const high64 = merge_accs(acc.data(), secret + secretSize -
sizeof(acc) - secret_mergeaccs_start, ~((uint64_t) len * PRIME<64>(2)));
1336 return hash128_t(low64, high64);
1340 XXH_FORCE_INLINE uint64_t mix_16b(
const uint8_t *XXH_RESTRICT input,
const uint8_t *XXH_RESTRICT secret, uint64_t seed) {
1341 uint64_t
const input_lo = readLE<64>(input);
1342 uint64_t
const input_hi = readLE<64>(input + 8);
1344 return mul128fold64(input_lo ^ (readLE<64>(secret) + seed), input_hi ^ (readLE<64>(secret + 8) - seed));
1347 XXH_FORCE_INLINE uint128_t mix_32b(uint128_t acc,
const uint8_t *input1,
const uint8_t *input2,
const uint8_t *secret, uint64_t seed) {
1348 acc.low64 += mix_16b(input1, secret + 0, seed);
1349 acc.low64 ^= readLE<64>(input2) + readLE<64>(input2 + 8);
1350 acc.high64 += mix_16b(input2, secret + 16, seed);
1351 acc.high64 ^= readLE<64>(input1) + readLE<64>(input1 + 8);
1357 XXH_FORCE_INLINE hash_t<N> len_17to128(
const uint8_t *XXH_RESTRICT input,
size_t len,
const uint8_t *XXH_RESTRICT secret, uint64_t seed) {
1358 if constexpr (N == 64) {
1359 hash64_t acc = len * PRIME<64>(1);
1364 acc += mix_16b(input + 48, secret + 96, seed);
1365 acc += mix_16b(input + len - 64, secret + 112, seed);
1368 acc += mix_16b(input + 32, secret + 64, seed);
1369 acc += mix_16b(input + len - 48, secret + 80, seed);
1372 acc += mix_16b(input + 16, secret + 32, seed);
1373 acc += mix_16b(input + len - 32, secret + 48, seed);
1376 acc += mix_16b(input + 0, secret + 0, seed);
1377 acc += mix_16b(input + len - 16, secret + 16, seed);
1379 return avalanche(acc);
1381 hash128_t acc = {len * PRIME<64>(1), 0};
1386 acc = mix_32b(acc, input + 48, input + len - 64, secret + 96, seed);
1389 acc = mix_32b(acc, input + 32, input + len - 48, secret + 64, seed);
1392 acc = mix_32b(acc, input + 16, input + len - 32, secret + 32, seed);
1395 acc = mix_32b(acc, input, input + len - 16, secret, seed);
1397 uint64_t
const low64 = acc.low64 + acc.high64;
1398 uint64_t
const high64 = (acc.low64 * PRIME<64>(1)) + (acc.high64 * PRIME<64>(4)) + ((len - seed) * PRIME<64>(2));
1400 return {avalanche(low64), (uint64_t) 0 - avalanche(high64)};
1405 XXH_NO_INLINE hash_t<N> len_129to240(
const uint8_t *XXH_RESTRICT input,
size_t len,
const uint8_t *XXH_RESTRICT secret, uint64_t seed) {
1406 if constexpr (N == 64) {
1407 uint64_t acc = len * PRIME<64>(1);
1408 size_t const nbRounds = len / 16;
1410 for (
size_t i = 0; i < 8; i++) {
1411 acc += mix_16b(input + (i * 16), secret + (i * 16), seed);
1414 acc = avalanche(acc);
1416 for (
size_t i = 8; i < nbRounds; i++) {
1417 acc += mix_16b(input + (i * 16), secret + ((i - 8) * 16) + midsize_startoffset, seed);
1421 acc += mix_16b(input + len - 16, secret + secret_size_min - midsize_lastoffset, seed);
1423 return avalanche(acc);
1426 uint64_t
const nbRounds = len / 32;
1428 acc.low64 = len * PRIME<64>(1);
1431 for (
size_t i = 0; i < 4; i++) {
1432 acc = mix_32b(acc, input + (i * 32), input + (i * 32) + 16, secret + (i * 32), seed);
1435 acc.low64 = avalanche(acc.low64);
1436 acc.high64 = avalanche(acc.high64);
1438 for (
size_t i = 4; i < nbRounds; i++) {
1439 acc = mix_32b(acc, input + (i * 32), input + (i * 32) + 16, secret + midsize_startoffset + ((i - 4) * 32), seed);
1443 acc = mix_32b(acc, input + len - 16, input + len - 32, secret + secret_size_min - midsize_lastoffset - 16, 0ULL - seed);
1445 uint64_t
const low64 = acc.low64 + acc.high64;
1446 uint64_t
const high64 = (acc.low64 * PRIME<64>(1)) + (acc.high64 * PRIME<64>(4)) + ((len - seed) * PRIME<64>(2));
1448 return {avalanche(low64), (uint64_t) 0 - avalanche(high64)};
1453 XXH_NO_INLINE hash_t<N> xxhash3_impl(
const void *XXH_RESTRICT input,
size_t len, hash64_t seed,
const void *XXH_RESTRICT secret = default_secret,
size_t secretSize = secret_default_size) {
1454 alignas(8) uint8_t custom_secret[secret_default_size];
1455 const void *short_secret = secret;
1458 init_custom_secret(custom_secret, seed);
1459 secret = custom_secret;
1460 secretSize = secret_default_size;
1461 short_secret = default_secret;
1465 return len_0to16<N>(
static_cast<const uint8_t *
>(input), len,
static_cast<const uint8_t *
>(short_secret), seed);
1466 }
else if (len <= 128) {
1467 return len_17to128<N>(
static_cast<const uint8_t *
>(input), len,
static_cast<const uint8_t *
>(short_secret), seed);
1468 }
else if (len <= midsize_max) {
1469 return len_129to240<N>(
static_cast<const uint8_t *
>(input), len,
static_cast<const uint8_t *
>(short_secret), seed);
1471 return hash_long_internal<N>(
static_cast<const uint8_t *
>(input), len,
static_cast<const uint8_t *
>(secret), secretSize);
1481 template<
size_t bit_mode>
1482 inline hash_t<bit_mode> xxhash(
const void *input,
size_t len, uint_t<bit_mode> seed = 0) {
1483 static_assert(!(bit_mode != 32 && bit_mode != 64),
"xxhash can only be used in 32 and 64 bit modes.");
1484 return detail::endian_align<bit_mode>(input, len, seed);
1487 template<
size_t bit_mode,
typename T>
1488 inline hash_t<bit_mode> xxhash(
const std::basic_string<T> &input, uint_t<bit_mode> seed = 0) {
1489 static_assert(!(bit_mode != 32 && bit_mode != 64),
"xxhash can only be used in 32 and 64 bit modes.");
1490 return detail::endian_align<bit_mode>(
static_cast<const void *
>(input.data()), input.length() *
sizeof(T), seed);
1493 template<
size_t bit_mode,
typename ContiguousIterator>
1494 inline hash_t<bit_mode> xxhash(ContiguousIterator begin, ContiguousIterator end, uint_t<bit_mode> seed = 0) {
1495 static_assert(!(bit_mode != 32 && bit_mode != 64),
"xxhash can only be used in 32 and 64 bit modes.");
1496 using T =
typename std::decay_t<
decltype(*end)>;
1497 return detail::endian_align<bit_mode>(
static_cast<const void *
>(&*begin), (end - begin) *
sizeof(T), seed);
1500 template<
size_t bit_mode,
typename T>
1501 inline hash_t<bit_mode> xxhash(
const std::vector<T> &input, uint_t<bit_mode> seed = 0) {
1502 static_assert(!(bit_mode != 32 && bit_mode != 64),
"xxhash can only be used in 32 and 64 bit modes.");
1503 return detail::endian_align<bit_mode>(
static_cast<const void *
>(input.data()), input.size() *
sizeof(T), seed);
1506 template<
size_t bit_mode,
typename T,
size_t AN>
1507 inline hash_t<bit_mode> xxhash(
const std::array<T, AN> &input, uint_t<bit_mode> seed = 0) {
1508 static_assert(!(bit_mode != 32 && bit_mode != 64),
"xxhash can only be used in 32 and 64 bit modes.");
1509 return detail::endian_align<bit_mode>(
static_cast<const void *
>(input.data()), AN *
sizeof(T), seed);
1512 template<
size_t bit_mode,
typename T>
1513 inline hash_t<bit_mode> xxhash(
const std::initializer_list<T> &input, uint_t<bit_mode> seed = 0) {
1514 static_assert(!(bit_mode != 32 && bit_mode != 64),
"xxhash can only be used in 32 and 64 bit modes.");
1515 return detail::endian_align<bit_mode>(
static_cast<const void *
>(input.begin()), input.size() *
sizeof(T), seed);
1523 template<
size_t bit_mode>
1524 inline hash_t<bit_mode> xxhash3(
const void *input,
size_t len, uint64_t seed = 0) {
1525 static_assert(!(bit_mode != 128 && bit_mode != 64),
"xxhash3 can only be used in 64 and 128 bit modes.");
1526 return detail3::xxhash3_impl<bit_mode>(input, len, seed);
1529 template<
size_t bit_mode>
1530 inline hash_t<bit_mode> xxhash3(
const void *input,
size_t len,
const void *secret,
size_t secretSize) {
1531 static_assert(!(bit_mode != 128 && bit_mode != 64),
"xxhash3 can only be used in 64 and 128 bit modes.");
1532 return detail3::xxhash3_impl<bit_mode>(input, len, 0, secret, secretSize);
1535 template<
size_t bit_mode,
typename T>
1536 inline hash_t<bit_mode> xxhash3(
const std::basic_string<T> &input, uint64_t seed = 0) {
1537 static_assert(!(bit_mode != 128 && bit_mode != 64),
"xxhash3 can only be used in 64 and 128 bit modes.");
1538 return detail3::xxhash3_impl<bit_mode>(
static_cast<const void *
>(input.data()), input.length() *
sizeof(T), seed);
1541 template<
size_t bit_mode,
typename T>
1542 inline hash_t<bit_mode> xxhash3(
const std::basic_string<T> &input,
const void *secret,
size_t secretSize) {
1543 static_assert(!(bit_mode != 128 && bit_mode != 64),
"xxhash3 can only be used in 64 and 128 bit modes.");
1544 return detail3::xxhash3_impl<bit_mode>(
static_cast<const void *
>(input.data()), input.length() *
sizeof(T), 0, secret, secretSize);
1547 template<
size_t N,
typename ContiguousIterator>
1548 inline hash_t<N> xxhash3(ContiguousIterator begin, ContiguousIterator end, uint64_t seed = 0) {
1549 static_assert(!(N != 128 && N != 64),
"xxhash3 can only be used in 64 and 128 bit modes.");
1550 using T =
typename std::decay_t<
decltype(*end)>;
1551 return detail3::xxhash3_impl<N>(
static_cast<const void *
>(&*begin), (end - begin) *
sizeof(T), seed);
1554 template<
size_t bit_mode,
typename ContiguousIterator>
1555 inline hash_t<bit_mode> xxhash3(ContiguousIterator begin, ContiguousIterator end,
const void *secret,
size_t secretSize) {
1556 static_assert(!(bit_mode != 128 && bit_mode != 64),
"xxhash3 can only be used in 64 and 128 bit modes.");
1557 using T =
typename std::decay_t<
decltype(*end)>;
1558 return detail3::xxhash3_impl<bit_mode>(
static_cast<const void *
>(&*begin), (end - begin) *
sizeof(T), 0, secret, secretSize);
1561 template<
size_t bit_mode,
typename T>
1562 inline hash_t<bit_mode> xxhash3(
const std::vector<T> &input, uint64_t seed = 0) {
1563 static_assert(!(bit_mode != 128 && bit_mode != 64),
"xxhash3 can only be used in 64 and 128 bit modes.");
1564 return detail3::xxhash3_impl<bit_mode>(
static_cast<const void *
>(input.data()), input.size() *
sizeof(T), seed);
1567 template<
size_t bit_mode,
typename T>
1568 inline hash_t<bit_mode> xxhash3(
const std::vector<T> &input,
const void *secret,
size_t secretSize) {
1569 static_assert(!(bit_mode != 128 && bit_mode != 64),
"xxhash3 can only be used in 64 and 128 bit modes.");
1570 return detail3::xxhash3_impl<bit_mode>(
static_cast<const void *
>(input.data()), input.size() *
sizeof(T), 0, secret, secretSize);
1573 template<
size_t bit_mode,
typename T,
size_t AN>
1574 inline hash_t<bit_mode> xxhash3(
const std::array<T, AN> &input, uint64_t seed = 0) {
1575 static_assert(!(bit_mode != 128 && bit_mode != 64),
"xxhash3 can only be used in 64 and 128 bit modes.");
1576 return detail3::xxhash3_impl<bit_mode>(
static_cast<const void *
>(input.data()), AN *
sizeof(T), seed);
1579 template<
size_t bit_mode,
typename T,
size_t AN>
1580 inline hash_t<bit_mode> xxhash3(
const std::array<T, AN> &input,
const void *secret,
size_t secretSize) {
1581 static_assert(!(bit_mode != 128 && bit_mode != 64),
"xxhash3 can only be used in 64 and 128 bit modes.");
1582 return detail3::xxhash3_impl<bit_mode>(
static_cast<const void *
>(input.data()), AN *
sizeof(T), 0, secret, secretSize);
1585 template<
size_t bit_mode,
typename T>
1586 inline hash_t<bit_mode> xxhash3(
const std::initializer_list<T> &input, uint64_t seed = 0) {
1587 static_assert(!(bit_mode != 128 && bit_mode != 64),
"xxhash3 can only be used in 64 and 128 bit modes.");
1588 return detail3::xxhash3_impl<bit_mode>(
static_cast<const void *
>(input.begin()), input.size() *
sizeof(T), seed);
1591 template<
size_t bit_mode,
typename T>
1592 inline hash_t<bit_mode> xxhash3(
const std::initializer_list<T> &input,
const void *secret,
size_t secretSize) {
1593 static_assert(!(bit_mode != 128 && bit_mode != 64),
"xxhash3 can only be used in 64 and 128 bit modes.");
1594 return detail3::xxhash3_impl<bit_mode>(
static_cast<const void *
>(input.begin()), input.size() *
sizeof(T), 0, secret, secretSize);
1602 template<
size_t bit_mode>
1604 uint64_t total_len = 0;
1605 uint_t<bit_mode> v1 = 0, v2 = 0, v3 = 0, v4 = 0;
1606 std::array<hash_t<bit_mode>, 4> mem = {0, 0, 0, 0};
1607 uint32_t memsize = 0;
1609 inline void update_impl(
const void *input,
size_t length) {
1610 const uint8_t *p =
reinterpret_cast<const uint8_t *
>(input);
1611 const uint8_t *
const bEnd = p + length;
1613 total_len += length;
1615 if (memsize + length < (bit_mode / 2)) {
1616 memcpy(
reinterpret_cast<uint8_t *
>(mem.data()) + memsize, input, length);
1617 memsize +=
static_cast<uint32_t
>(length);
1622 memcpy(
reinterpret_cast<uint8_t *
>(mem.data()) + memsize, input, (bit_mode / 2) - memsize);
1624 const uint_t<bit_mode> *ptr = mem.data();
1626 v1 = detail::round<bit_mode>(v1, mem_ops::readLE<bit_mode>(ptr));
1628 v2 = detail::round<bit_mode>(v2, mem_ops::readLE<bit_mode>(ptr));
1630 v3 = detail::round<bit_mode>(v3, mem_ops::readLE<bit_mode>(ptr));
1632 v4 = detail::round<bit_mode>(v4, mem_ops::readLE<bit_mode>(ptr));
1634 p += (bit_mode / 2) - memsize;
1638 if (p <= bEnd - (bit_mode / 2)) {
1639 const uint8_t *
const limit = bEnd - (bit_mode / 2);
1642 v1 = detail::round<bit_mode>(v1, mem_ops::readLE<bit_mode>(p));
1643 p += (bit_mode / 8);
1644 v2 = detail::round<bit_mode>(v2, mem_ops::readLE<bit_mode>(p));
1645 p += (bit_mode / 8);
1646 v3 = detail::round<bit_mode>(v3, mem_ops::readLE<bit_mode>(p));
1647 p += (bit_mode / 8);
1648 v4 = detail::round<bit_mode>(v4, mem_ops::readLE<bit_mode>(p));
1649 p += (bit_mode / 8);
1650 }
while (p <= limit);
1654 memcpy(mem.data(), p,
static_cast<size_t>(bEnd - p));
1655 memsize =
static_cast<uint32_t
>(bEnd - p);
1659 inline hash_t<bit_mode> digest_impl()
const {
1660 const uint8_t *p =
reinterpret_cast<const uint8_t *
>(mem.data());
1661 const uint8_t *
const bEnd =
reinterpret_cast<const uint8_t *
>(mem.data()) + memsize;
1662 hash_t<bit_mode> hash_ret;
1664 if (total_len >= (bit_mode / 2)) {
1665 hash_ret = bit_ops::rotl<bit_mode>(v1, 1) + bit_ops::rotl<bit_mode>(v2, 7) + bit_ops::rotl<bit_mode>(v3, 12) + bit_ops::rotl<bit_mode>(v4, 18);
1667 if constexpr (bit_mode == 64) {
1668 detail::endian_align_sub_mergeround(hash_ret, v1, v2, v3, v4);
1671 hash_ret = v3 + detail::PRIME<bit_mode>(5);
1674 hash_ret +=
static_cast<hash_t<bit_mode>
>(total_len);
1676 return detail::endian_align_sub_ending<bit_mode>(hash_ret, p, bEnd);
1681 static_assert(!(bit_mode != 32 && bit_mode != 64),
"xxhash streaming can only be used in 32 and 64 bit modes.");
1682 v1 = seed + detail::PRIME<bit_mode>(1) + detail::PRIME<bit_mode>(2);
1683 v2 = seed + detail::PRIME<bit_mode>(2);
1685 v4 = seed - detail::PRIME<bit_mode>(1);
1692 void reset(uint_t<bit_mode> seed = 0) {
1694 v1 = seed + detail::PRIME<bit_mode>(1) + detail::PRIME<bit_mode>(2);
1695 v2 = seed + detail::PRIME<bit_mode>(2);
1697 v4 = seed - detail::PRIME<bit_mode>(1);
1700 void update(
const void *input,
size_t length) {
1701 return update_impl(input, length);
1704 template<
typename T>
1705 void update(
const std::basic_string<T> &input) {
1706 return update_impl(
static_cast<const void *
>(input.data()), input.length() *
sizeof(T));
1709 template<
typename ContiguousIterator>
1710 void update(ContiguousIterator begin, ContiguousIterator end) {
1711 using T =
typename std::decay_t<
decltype(*end)>;
1712 return update_impl(
static_cast<const void *
>(&*begin), (end - begin) *
sizeof(T));
1715 template<
typename T>
1716 void update(
const std::vector<T> &input) {
1717 return update_impl(
static_cast<const void *
>(input.data()), input.size() *
sizeof(T));
1720 template<
typename T,
size_t AN>
1721 void update(
const std::array<T, AN> &input) {
1722 return update_impl(
static_cast<const void *
>(input.data()), AN *
sizeof(T));
1725 template<
typename T>
1726 void update(
const std::initializer_list<T> &input) {
1727 return update_impl(
static_cast<const void *
>(input.begin()), input.size() *
sizeof(T));
1730 hash_t<bit_mode> digest()
const {
1731 return digest_impl();
1743 template<
size_t bit_mode>
1745 constexpr static int internal_buffer_size = 256;
1746 constexpr static int internal_buffer_stripes = (internal_buffer_size / detail3::stripe_len);
1747 constexpr static detail3::acc_width accWidth = (bit_mode == 64) ? detail3::acc_width::acc_64bits : detail3::acc_width::acc_128bits;
1749 alignas(64) uint64_t acc[8];
1750 alignas(64) uint8_t customSecret[detail3::secret_default_size];
1751 alignas(64) uint8_t buffer[internal_buffer_size];
1752 uint32_t bufferedSize = 0;
1753 uint32_t nbStripesPerBlock = 0;
1754 uint32_t nbStripesSoFar = 0;
1755 uint32_t secretLimit = 0;
1756 uint32_t reserved32 = 0;
1757 uint32_t reserved32_2 = 0;
1758 uint64_t totalLen = 0;
1760 uint64_t reserved64 = 0;
1761 const uint8_t *secret =
nullptr;
1764 void consume_stripes(uint64_t *acc, uint32_t &nbStripesSoFar,
size_t totalStripes,
const uint8_t *input, detail3::acc_width accWidth) {
1765 if (nbStripesPerBlock - nbStripesSoFar <= totalStripes)
1767 size_t const nbStripes = nbStripesPerBlock - nbStripesSoFar;
1769 detail3::accumulate(acc, input, secret + (nbStripesSoFar * detail3::secret_consume_rate), nbStripes, accWidth);
1770 detail3::scramble_acc<detail3::vector_mode>(acc, secret + secretLimit);
1771 detail3::accumulate(acc, input + nbStripes * detail3::stripe_len, secret, totalStripes - nbStripes, accWidth);
1772 nbStripesSoFar = (uint32_t)(totalStripes - nbStripes);
1774 detail3::accumulate(acc, input, secret + (nbStripesSoFar * detail3::secret_consume_rate), totalStripes, accWidth);
1775 nbStripesSoFar += (uint32_t) totalStripes;
1779 void update_impl(
const void *input_,
size_t len) {
1780 const uint8_t *input =
static_cast<const uint8_t *
>(input_);
1781 const uint8_t *
const bEnd = input + len;
1785 if (bufferedSize + len <= internal_buffer_size) {
1786 memcpy(buffer + bufferedSize, input, len);
1787 bufferedSize += (uint32_t) len;
1792 if (bufferedSize > 0) {
1793 size_t const loadSize = internal_buffer_size - bufferedSize;
1795 memcpy(buffer + bufferedSize, input, loadSize);
1797 consume_stripes(acc, nbStripesSoFar, internal_buffer_stripes, buffer, accWidth);
1802 if (input + internal_buffer_size <= bEnd) {
1803 const uint8_t *
const limit = bEnd - internal_buffer_size;
1806 consume_stripes(acc, nbStripesSoFar, internal_buffer_stripes, input, accWidth);
1807 input += internal_buffer_size;
1808 }
while (input <= limit);
1812 memcpy(buffer, input, (
size_t)(bEnd - input));
1813 bufferedSize = (uint32_t)(bEnd - input);
1817 void digest_long(uint64_t *acc_, detail3::acc_width accWidth) {
1818 memcpy(acc_, acc,
sizeof(acc));
1820 if (bufferedSize >= detail3::stripe_len) {
1821 size_t const totalNbStripes = bufferedSize / detail3::stripe_len;
1822 uint32_t nbStripesSoFar = this->nbStripesSoFar;
1824 consume_stripes(acc_, nbStripesSoFar, totalNbStripes, buffer, accWidth);
1826 if (bufferedSize % detail3::stripe_len) {
1827 detail3::accumulate_512<detail3::vector_mode>(acc_, buffer + bufferedSize - detail3::stripe_len, secret + secretLimit - detail3::secret_lastacc_start, accWidth);
1830 if (bufferedSize > 0) {
1831 uint8_t lastStripe[detail3::stripe_len];
1832 size_t const catchupSize = detail3::stripe_len - bufferedSize;
1833 memcpy(lastStripe, buffer +
sizeof(buffer) - catchupSize, catchupSize);
1834 memcpy(lastStripe + catchupSize, buffer, bufferedSize);
1835 detail3::accumulate_512<detail3::vector_mode>(acc_, lastStripe, secret + secretLimit - detail3::secret_lastacc_start, accWidth);
1846 static_assert(!(bit_mode != 128 && bit_mode != 64),
"xxhash3 streaming can only be used in 64 and 128 bit modes.");
1851 static_assert(!(bit_mode != 128 && bit_mode != 64),
"xxhash3 streaming can only be used in 64 and 128 bit modes.");
1852 reset(secret, secretSize);
1855 void reset(uint64_t seed = 0) {
1856 memset(
this, 0,
sizeof(*
this));
1857 memcpy(acc, detail3::init_acc.data(),
sizeof(detail3::init_acc));
1858 (*this).seed = seed;
1861 secret = detail3::default_secret;
1863 detail3::init_custom_secret(customSecret, seed);
1864 secret = customSecret;
1867 secretLimit = (uint32_t)(detail3::secret_default_size - detail3::stripe_len);
1868 nbStripesPerBlock = secretLimit / detail3::secret_consume_rate;
1871 void reset(
const void *secret,
size_t secretSize) {
1872 memset(
this, 0,
sizeof(*
this));
1873 memcpy(acc, detail3::init_acc.data(),
sizeof(detail3::init_acc));
1876 (*this).secret = (
const uint8_t *) secret;
1877 secretLimit = (uint32_t)(secretSize - detail3::stripe_len);
1878 nbStripesPerBlock = secretLimit / detail3::secret_consume_rate;
1881 void update(
const void *input,
size_t len) {
1882 return update_impl(
static_cast<const void *
>(input), len);
1885 template<
typename T>
1886 void update(
const std::basic_string<T> &input) {
1887 return update_impl(
static_cast<const void *
>(input.data()), input.length() *
sizeof(T));
1890 template<
typename ContiguousIterator>
1891 void update(ContiguousIterator begin, ContiguousIterator end) {
1892 using T =
typename std::decay_t<
decltype(*end)>;
1893 return update_impl(
static_cast<const void *
>(&*begin), (end - begin) *
sizeof(T));
1896 template<
typename T>
1897 void update(
const std::vector<T> &input) {
1898 return update_impl(
static_cast<const void *
>(input.data()), input.size() *
sizeof(T));
1901 template<
typename T,
size_t AN>
1902 void update(
const std::array<T, AN> &input) {
1903 return update_impl(
static_cast<const void *
>(input.data()), AN *
sizeof(T));
1906 template<
typename T>
1907 void update(
const std::initializer_list<T> &input) {
1908 return update_impl(
static_cast<const void *
>(input.begin()), input.size() *
sizeof(T));
1911 hash_t<bit_mode> digest() {
1912 if (totalLen > detail3::midsize_max) {
1913 alignas(detail3::acc_align) hash64_t acc[detail3::acc_nb];
1915 digest_long(acc, accWidth);
1917 if constexpr (bit_mode == 64) {
1918 return detail3::merge_accs(acc, secret + detail3::secret_mergeaccs_start, (uint64_t) totalLen * detail::PRIME<64>(1));
1920 uint64_t
const low64 = detail3::merge_accs(acc, secret + detail3::secret_mergeaccs_start, (uint64_t) totalLen * detail::PRIME<64>(1));
1921 uint64_t
const high64 = detail3::merge_accs(acc, secret + secretLimit + detail3::stripe_len -
sizeof(acc) - detail3::secret_mergeaccs_start, ~((uint64_t) totalLen * detail::PRIME<64>(2)));
1923 return {low64, high64};
1926 return detail3::xxhash3_impl<bit_mode>(buffer, totalLen, seed, secret, secretLimit + detail3::stripe_len);
1939 template<
size_t bit_mode>
1941 std::array<uint8_t, bit_mode / 8> digest{0};
1944 if constexpr (bit_mode < 128) {
1945 if (mem_ops::is_little_endian()) {
1946 hash = bit_ops::swap<bit_mode>(hash);
1951 if (mem_ops::is_little_endian()) {
1952 hash.low64 = bit_ops::swap<64>(hash.low64);
1953 hash.high64 = bit_ops::swap<64>(hash.high64);
1956 memcpy(digest.data(), &hash.high64,
sizeof(hash.high64));
1957 memcpy(digest.data() +
sizeof(hash.high64), &hash.low64,
sizeof(hash.low64));
1961 hash_t<bit_mode> get_hash()
const {
1962 if constexpr (bit_mode < 128) {
1963 return mem_ops::readBE<bit_mode>(&digest);
1965 return {mem_ops::readBE<64>(&digest[8]), mem_ops::readBE<64>(&digest)};
Definition xxhash.hpp:1744
Definition xxhash.hpp:1603
Definition xxhash.hpp:1940
Definition xxhash.hpp:304
Definition xxhash.hpp:352
Definition xxhash.hpp:325