8#ifndef INCLUDED_BSLH_WYHASHINCREMENTALALGORITHM
9#define INCLUDED_BSLH_WYHASHINCREMENTALALGORITHM
396#include <bslscm_version.h>
411#if defined(_MSC_VER) && defined(_M_X64)
413# pragma intrinsic(_umul128)
416#ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
427#undef BSLH_WYHASHINCREMENTALALGORITHM_WYMUM_XOR
428#define BSLH_WYHASHINCREMENTALALGORITHM_WYMUM_XOR 0
435#undef BSLH_WYHASHINCREMENTALALGORITHM_WYMUM_PSEUDO_MULTIPLY
436#define BSLH_WYHASHINCREMENTALALGORITHM_WYMUM_PSEUDO_MULTIPLY 0
453 enum { k_PREPAD_LENGTH = 16,
454 k_PREPAD_LENGTH_RAW = k_PREPAD_LENGTH - 1,
455 k_REPEAT_LENGTH = 48 };
467 uint64_t d_initialSeed, d_seed, d_see1, d_see2;
474 uint8_t d_buffer[k_PREPAD_LENGTH_RAW + k_REPEAT_LENGTH];
489 static const uint64_t s_secret0 = 0xa0761d6478bd642full;
490 static const uint64_t s_secret1 = 0xe7037ed1a0b428dbull;
491 static const uint64_t s_secret2 = 0x8ebc6af09c88c6e3ull;
492 static const uint64_t s_secret3 = 0x589965cc75374cc3ull;
503#if BSLH_WYHASHINCREMENTALALGORITHM_WYMUM_PSEUDO_MULTIPLY
504 static uint64_t _wyrot(uint64_t x);
514 static void _wymum(uint64_t *a_p, uint64_t *b_p);
518 static uint64_t _wymix(uint64_t a, uint64_t b);
522 static uint64_t _wyr8(
const uint8_t *p);
526 static uint64_t _wyr4(
const uint8_t *p);
530 static uint64_t _wyr3(
const uint8_t *p,
size_t k);
538 uint8_t *prePadAt(ptrdiff_t offset);
544 void process48ByteSection(
const uint8_t *buffer);
547 uint8_t *repeatBufferBegin();
550 uint8_t *repeatBufferEnd();
593 void operator()(
const void *data,
size_t numBytes);
614#if BSLH_WYHASHINCREMENTALALGORITHM_WYMUM_PSEUDO_MULTIPLY
616uint64_t WyHashIncrementalAlgorithm::_wyrot(uint64_t x)
618 return (x >> 32) | (x << 32);
623void WyHashIncrementalAlgorithm::_wymum(uint64_t *a_p, uint64_t *b_p)
625#if BSLH_WYHASHINCREMENTALALGORITHM_WYMUM_PSEUDO_MULTIPLY
626 const uint64_t hh = (*a_p >> 32) * (*b_p >> 32);
627 const uint64_t hl = (*a_p >> 32) *
static_cast<uint32_t
>(*b_p);
628 const uint64_t lh =
static_cast<uint32_t
>(*a_p) * (*b_p >> 32);
629 const uint64_t ll =
static_cast<uint64_t
>(
static_cast<uint32_t
>(*a_p)) *
630 static_cast<uint32_t
>(*b_p);
632#if BSLH_WYHASHINCREMENTALALGORITHM_WYMUM_XOR
635 *a_p ^= _wyrot(hl) ^ hh;
636 *b_p ^= _wyrot(lh) ^ ll;
640 *a_p = _wyrot(hl) ^ hh;
641 *b_p = _wyrot(lh) ^ ll;
643#elif defined(__SIZEOF_INT128__)
644 __uint128_t r = *a_p;
647#if BSLH_WYHASHINCREMENTALALGORITHM_WYMUM_XOR
650 *a_p ^=
static_cast<uint64_t
>(r);
651 *b_p ^=
static_cast<uint64_t
>(r >> 64);
655 *a_p =
static_cast<uint64_t
>(r);
656 *b_p =
static_cast<uint64_t
>(r >> 64);
658#elif defined(_MSC_VER) && defined(_M_X64)
659#if BSLH_WYHASHINCREMENTALALGORITHM_WYMUM_XOR
663 a = _umul128(*a_p, *b_p, &b);
669 *a_p = _umul128(*a_p, *b_p, b_p);
672 const uint64_t ha = *a_p >> 32, hb = *b_p >> 32;
673 const uint64_t la =
static_cast<uint32_t
>(*a_p);
674 const uint64_t lb =
static_cast<uint32_t
>(*b_p);
676 const uint64_t rh = ha * hb, rl = la * lb;
677 const uint64_t rm0 = ha * lb, rm1 = hb * la;
678 const uint64_t t = rl + (rm0 << 32);
680 const uint64_t lo = t + (rm1 << 32);
681 const uint64_t hi = rh + (rm0 >> 32) + (rm1 >> 32) + (t < rl) + (lo < t);
683#if BSLH_WYHASHINCREMENTALALGORITHM_WYMUM_XOR
699uint64_t WyHashIncrementalAlgorithm::_wymix(uint64_t a, uint64_t b)
707uint64_t WyHashIncrementalAlgorithm::_wyr8(
const uint8_t *p)
715uint64_t WyHashIncrementalAlgorithm::_wyr4(
const uint8_t *p)
725uint64_t WyHashIncrementalAlgorithm::_wyr3(
const uint8_t *p,
size_t k)
729 return (
static_cast<uint64_t
>(p[0]) << 16) |
730 (
static_cast<uint64_t
>(p[k >> 1]) << 8) |
736uint8_t *WyHashIncrementalAlgorithm::prePadAt(ptrdiff_t offset)
741 return d_buffer + offset - 1;
745void WyHashIncrementalAlgorithm::process48ByteSection(
const uint8_t *buffer)
747 d_seed = _wymix(_wyr8(buffer) ^ s_secret1,
748 _wyr8(buffer + 8) ^ d_seed);
749 d_see1 = _wymix(_wyr8(buffer + 16) ^ s_secret2,
750 _wyr8(buffer + 24) ^ d_see1);
751 d_see2 = _wymix(_wyr8(buffer + 32) ^ s_secret3,
752 _wyr8(buffer + 40) ^ d_see2);
756uint8_t *WyHashIncrementalAlgorithm::repeatBufferBegin()
758 return d_buffer + k_PREPAD_LENGTH_RAW;
762uint8_t *WyHashIncrementalAlgorithm::repeatBufferEnd()
764 return d_buffer +
sizeof(d_buffer);
770: d_initialSeed(0x50defacedfacade5ULL)
771, d_last16AtEnd(false)
775 sizeof(*
this) == 12 *
sizeof(uint64_t) +
sizeof(
size_t));
777 d_see1 = d_see2 = d_seed = d_initialSeed ^ s_secret0;
783, d_last16AtEnd(false)
787 d_see1 = d_see2 = d_seed = d_initialSeed ^ s_secret0;
792: d_last16AtEnd(false)
797 memcpy(&d_initialSeed, seed,
sizeof(d_initialSeed));
799 d_see1 = d_see2 = d_seed = d_initialSeed ^ s_secret0;
804void WyHashIncrementalAlgorithm::operator()(
const void *data,
size_t numBytes)
819 const uint8_t *p =
static_cast<const uint8_t *
>(
data);
820 const uint8_t *
end = p + numBytes;
822 const size_t origLen = d_totalLen;
823 size_t repeatBufNumBytes = origLen % k_REPEAT_LENGTH;
827 repeatBufNumBytes = k_REPEAT_LENGTH;
830 d_totalLen = origLen + numBytes;
832 if (0 != repeatBufNumBytes) {
833 const ptrdiff_t remainingSpaceInBuf = k_REPEAT_LENGTH -
836 remainingSpaceInBuf)) {
837 memcpy(repeatBufferBegin() + repeatBufNumBytes, p, end - p);
846 memcpy(repeatBufferBegin() + repeatBufNumBytes,
848 remainingSpaceInBuf);
850 p += remainingSpaceInBuf;
851 process48ByteSection(repeatBufferBegin());
853 d_last16AtEnd =
true;
861 process48ByteSection(p);
862 p += k_REPEAT_LENGTH;
863 }
while (k_REPEAT_LENGTH < end - p);
865 d_last16AtEnd =
false;
867 const ptrdiff_t remOffset =
end - p;
868 if (remOffset < 16) {
875 memcpy(prePadAt(remOffset), p + remOffset - 16, 16);
881 memcpy(repeatBufferBegin(), p, end - p);
886WyHashIncrementalAlgorithm::computeHash()
890 uint8_t *p = repeatBufferBegin();
892 uint64_t a, b, seed = d_seed;
894 const size_t len = d_totalLen;
897 const size_t subLen = (len >> 3) << 2;
899 a = (_wyr4(p) << 32) | _wyr4(p + subLen);
900 b = (_wyr4(p + len - 4) << 32) | _wyr4(p + len - 4 - subLen);
915 size_t totalLenRemainder = len % k_REPEAT_LENGTH;
919 totalLenRemainder = k_REPEAT_LENGTH;
921 uint8_t *
end = p + totalLenRemainder;
926 seed ^= d_see1 ^ d_see2;
932 seed = _wymix(_wyr8(p) ^ s_secret1, _wyr8(p + 8) ^ seed);
936 const ptrdiff_t offset =
end - repeatBufferBegin() - k_PREPAD_LENGTH;
942 memcpy(repeatBufferBegin() + offset,
943 repeatBufferEnd() + offset,
951 return d_initialSeed ^ _wymix(s_secret1 ^ len,
952 _wymix(a ^ s_secret1, b ^ seed));
971#undef BSLH_WYHASHINCREMENTALALGORITHM_WYMUM_PSEUDO_MULTIPLY
972#undef BSLH_WYHASHINCREMENTALALGORITHM_WYMUM_XOR
Definition bslh_wyhashincrementalalgorithm.h:449
WyHashIncrementalAlgorithm()
Create a WyHashIncrementalAlgorithm using a default initial seed.
Definition bslh_wyhashincrementalalgorithm.h:769
@ k_SEED_LENGTH
Definition bslh_wyhashincrementalalgorithm.h:463
WyHashIncrementalAlgorithm(const WyHashIncrementalAlgorithm &original) ~WyHashIncrementalAlgorithm()=default
Destroy this object.
bsls::Types::Uint64 result_type
Typedef indicating the value type returned by this algorithm.
Definition bslh_wyhashincrementalalgorithm.h:461
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:231
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1917
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_KEYWORD_DELETED
Definition bsls_keyword.h:651
T::iterator end(T &container)
Definition bslstl_iterator.h:1621
BSLS_KEYWORD_CONSTEXPR CONTAINER::value_type * data(CONTAINER &container)
Definition bslstl_iterator.h:1325
Definition bslh_defaulthashalgorithm.h:339
Definition bdlbb_blob.h:579
Definition bslmf_isbitwisecopyable.h:298
unsigned long long Uint64
Definition bsls_types.h:139