8#ifndef INCLUDED_BSLH_WYHASHINCREMENTALALGORITHM
9#define INCLUDED_BSLH_WYHASHINCREMENTALALGORITHM
396#include <bslscm_version.h>
413#if defined(_MSC_VER) && defined(_M_X64)
415#pragma intrinsic(_umul128)
425#undef BSLH_WYHASHINCREMENTALALGORITHM_WYMUM_XOR
426#define BSLH_WYHASHINCREMENTALALGORITHM_WYMUM_XOR 0
433#undef BSLH_WYHASHINCREMENTALALGORITHM_WYMUM_PSEUDO_MULTIPLY
434#define BSLH_WYHASHINCREMENTALALGORITHM_WYMUM_PSEUDO_MULTIPLY 0
451 enum { k_PREPAD_LENGTH = 16,
452 k_PREPAD_LENGTH_RAW = k_PREPAD_LENGTH - 1,
453 k_REPEAT_LENGTH = 48 };
465 uint64_t d_initialSeed, d_seed, d_see1, d_see2;
472 uint8_t d_buffer[k_PREPAD_LENGTH_RAW + k_REPEAT_LENGTH];
487 static const uint64_t s_secret0 = 0xa0761d6478bd642full;
488 static const uint64_t s_secret1 = 0xe7037ed1a0b428dbull;
489 static const uint64_t s_secret2 = 0x8ebc6af09c88c6e3ull;
490 static const uint64_t s_secret3 = 0x589965cc75374cc3ull;
501#if BSLH_WYHASHINCREMENTALALGORITHM_WYMUM_PSEUDO_MULTIPLY
502 static uint64_t _wyrot(uint64_t x);
512 static void _wymum(uint64_t *a_p, uint64_t *b_p);
516 static uint64_t _wymix(uint64_t a, uint64_t b);
519 static uint64_t _wyr8(
const uint8_t *p);
522 static uint64_t _wyr4(
const uint8_t *p);
526 static uint64_t _wyr3(
const uint8_t *p,
size_t k);
533 uint8_t *prePadAt(ptrdiff_t offset);
538 void process48ByteSection(
const uint8_t *buffer);
541 uint8_t *repeatBufferBegin();
544 uint8_t *repeatBufferEnd();
575 void operator()(
const void *data,
size_t numBytes);
595#if BSLH_WYHASHINCREMENTALALGORITHM_WYMUM_PSEUDO_MULTIPLY
597uint64_t WyHashIncrementalAlgorithm::_wyrot(uint64_t x)
599 return (x >> 32) | (x << 32);
604void WyHashIncrementalAlgorithm::_wymum(uint64_t *a_p, uint64_t *b_p)
606#if BSLH_WYHASHINCREMENTALALGORITHM_WYMUM_PSEUDO_MULTIPLY
607 const uint64_t hh = (*a_p >> 32) * (*b_p >> 32);
608 const uint64_t hl = (*a_p >> 32) *
static_cast<uint32_t
>(*b_p);
609 const uint64_t lh =
static_cast<uint32_t
>(*a_p) * (*b_p >> 32);
610 const uint64_t ll =
static_cast<uint64_t
>(
static_cast<uint32_t
>(*a_p)) *
611 static_cast<uint32_t
>(*b_p);
613#if BSLH_WYHASHINCREMENTALALGORITHM_WYMUM_XOR
616 *a_p ^= _wyrot(hl) ^ hh;
617 *b_p ^= _wyrot(lh) ^ ll;
621 *a_p = _wyrot(hl) ^ hh;
622 *b_p = _wyrot(lh) ^ ll;
624#elif defined(__SIZEOF_INT128__)
625 __uint128_t r = *a_p;
628#if BSLH_WYHASHINCREMENTALALGORITHM_WYMUM_XOR
631 *a_p ^=
static_cast<uint64_t
>(r);
632 *b_p ^=
static_cast<uint64_t
>(r >> 64);
636 *a_p =
static_cast<uint64_t
>(r);
637 *b_p =
static_cast<uint64_t
>(r >> 64);
639#elif defined(_MSC_VER) && defined(_M_X64)
640#if BSLH_WYHASHINCREMENTALALGORITHM_WYMUM_XOR
644 a = _umul128(*a_p, *b_p, &b);
650 *a_p = _umul128(*a_p, *b_p, b_p);
653 const uint64_t ha = *a_p >> 32, hb = *b_p >> 32;
654 const uint64_t la =
static_cast<uint32_t
>(*a_p);
655 const uint64_t lb =
static_cast<uint32_t
>(*b_p);
657 const uint64_t rh = ha * hb, rl = la * lb;
658 const uint64_t rm0 = ha * lb, rm1 = hb * la;
659 const uint64_t t = rl + (rm0 << 32);
661 const uint64_t lo = t + (rm1 << 32);
662 const uint64_t hi = rh + (rm0 >> 32) + (rm1 >> 32) + (t < rl) + (lo < t);
664#if BSLH_WYHASHINCREMENTALALGORITHM_WYMUM_XOR
680uint64_t WyHashIncrementalAlgorithm::_wymix(uint64_t a, uint64_t b)
688uint64_t WyHashIncrementalAlgorithm::_wyr8(
const uint8_t *p)
696uint64_t WyHashIncrementalAlgorithm::_wyr4(
const uint8_t *p)
706uint64_t WyHashIncrementalAlgorithm::_wyr3(
const uint8_t *p,
size_t k)
710 return (
static_cast<uint64_t
>(p[0]) << 16) |
711 (
static_cast<uint64_t
>(p[k >> 1]) << 8) |
717uint8_t *WyHashIncrementalAlgorithm::prePadAt(ptrdiff_t offset)
722 return d_buffer + offset - 1;
726void WyHashIncrementalAlgorithm::process48ByteSection(
const uint8_t *buffer)
728 d_seed = _wymix(_wyr8(buffer) ^ s_secret1,
729 _wyr8(buffer + 8) ^ d_seed);
730 d_see1 = _wymix(_wyr8(buffer + 16) ^ s_secret2,
731 _wyr8(buffer + 24) ^ d_see1);
732 d_see2 = _wymix(_wyr8(buffer + 32) ^ s_secret3,
733 _wyr8(buffer + 40) ^ d_see2);
737uint8_t *WyHashIncrementalAlgorithm::repeatBufferBegin()
739 return d_buffer + k_PREPAD_LENGTH_RAW;
743uint8_t *WyHashIncrementalAlgorithm::repeatBufferEnd()
745 return d_buffer +
sizeof(d_buffer);
751: d_initialSeed(0x50defacedfacade5ULL)
752, d_last16AtEnd(false)
756 sizeof(*
this) == 12 *
sizeof(uint64_t) +
sizeof(
size_t));
758 d_seed = d_initialSeed ^ s_secret0;
764, d_last16AtEnd(false)
768 d_seed = d_initialSeed ^ s_secret0;
773: d_last16AtEnd(false)
778 memcpy(&d_initialSeed, seed,
sizeof(d_initialSeed));
780 d_seed = d_initialSeed ^ s_secret0;
800 const uint8_t *p =
static_cast<const uint8_t *
>(data);
801 const uint8_t *end = p + numBytes;
803 const size_t origLen = d_totalLen;
804 size_t repeatBufNumBytes = origLen % k_REPEAT_LENGTH;
808 repeatBufNumBytes = k_REPEAT_LENGTH;
811 d_totalLen = origLen + numBytes;
813 if (0 != repeatBufNumBytes) {
814 const ptrdiff_t remainingSpaceInBuf = k_REPEAT_LENGTH -
817 remainingSpaceInBuf)) {
818 memcpy(repeatBufferBegin() + repeatBufNumBytes, p, end - p);
827 if (origLen <= k_REPEAT_LENGTH) {
828 d_see1 = d_see2 = d_seed;
831 memcpy(repeatBufferBegin() + repeatBufNumBytes,
833 remainingSpaceInBuf);
835 p += remainingSpaceInBuf;
836 process48ByteSection(repeatBufferBegin());
838 d_last16AtEnd =
true;
846 d_see1 = d_see2 = d_seed;
850 process48ByteSection(p);
851 p += k_REPEAT_LENGTH;
852 }
while (k_REPEAT_LENGTH < end - p);
854 d_last16AtEnd =
false;
856 const ptrdiff_t remOffset = end - p;
857 if (remOffset < 16) {
864 memcpy(prePadAt(remOffset), p + remOffset - 16, 16);
870 memcpy(repeatBufferBegin(), p, end - p);
879 uint8_t *p = repeatBufferBegin();
881 uint64_t a, b, seed = d_seed;
883 const size_t len = d_totalLen;
886 const size_t subLen = (len >> 3) << 2;
888 a = (_wyr4(p) << 32) | _wyr4(p + subLen);
889 b = (_wyr4(p + len - 4) << 32) | _wyr4(p + len - 4 - subLen);
904 size_t totalLenRemainder = len % k_REPEAT_LENGTH;
908 totalLenRemainder = k_REPEAT_LENGTH;
910 uint8_t *end = p + totalLenRemainder;
915 seed ^= d_see1 ^ d_see2;
921 seed = _wymix(_wyr8(p) ^ s_secret1, _wyr8(p + 8) ^ seed);
925 const ptrdiff_t offset = end - repeatBufferBegin() - k_PREPAD_LENGTH;
931 memcpy(repeatBufferBegin() + offset,
932 repeatBufferEnd() + offset,
940 return d_initialSeed ^ _wymix(s_secret1 ^ len,
941 _wymix(a ^ s_secret1, b ^ seed));
960#undef BSLH_WYHASHINCREMENTALALGORITHM_WYMUM_PSEUDO_MULTIPLY
961#undef BSLH_WYHASHINCREMENTALALGORITHM_WYMUM_XOR
Definition bslh_wyhashincrementalalgorithm.h:447
result_type computeHash()
Definition bslh_wyhashincrementalalgorithm.h:875
void operator()(const void *data, size_t numBytes)
Definition bslh_wyhashincrementalalgorithm.h:785
~WyHashIncrementalAlgorithm()=default
WyHashIncrementalAlgorithm()
Create a WyHashIncrementalAlgorithm using a default initial seed.
Definition bslh_wyhashincrementalalgorithm.h:750
@ k_SEED_LENGTH
Definition bslh_wyhashincrementalalgorithm.h:461
bsls::Types::Uint64 result_type
Typedef indicating the value type returned by this algorithm.
Definition bslh_wyhashincrementalalgorithm.h:459
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:229
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1762
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_KEYWORD_DELETED
Definition bsls_keyword.h:609
Definition bslh_defaulthashalgorithm.h:339
Definition bdlbb_blob.h:576
Definition bslmf_isbitwisecopyable.h:298
unsigned long long Uint64
Definition bsls_types.h:137