diff options
author | arcadia-devtools <arcadia-devtools@yandex-team.ru> | 2022-02-17 12:04:09 +0300 |
---|---|---|
committer | arcadia-devtools <arcadia-devtools@yandex-team.ru> | 2022-02-17 12:04:09 +0300 |
commit | 2c8e314f8fff8633fe2cf026badfbf6180845ae0 (patch) | |
tree | c3b650d13934ec1315e3660d60fd2275f09b03a7 /library/cpp/digest/murmur/murmur.h | |
parent | a49ae9d891c35087b242c854f69880fd9fecbddd (diff) | |
download | ydb-2c8e314f8fff8633fe2cf026badfbf6180845ae0.tar.gz |
intermediate changes
ref:d5f945ecdc1f5af1ad57e12787c6b8ed1a9f0f12
Diffstat (limited to 'library/cpp/digest/murmur/murmur.h')
-rw-r--r-- | library/cpp/digest/murmur/murmur.h | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/library/cpp/digest/murmur/murmur.h b/library/cpp/digest/murmur/murmur.h new file mode 100644 index 0000000000..cbf2886412 --- /dev/null +++ b/library/cpp/digest/murmur/murmur.h @@ -0,0 +1,100 @@ +#pragma once + +#include <util/system/defaults.h> +#include <util/system/unaligned_mem.h> + +/* + * https://sites.google.com/site/murmurhash/ + */ + +namespace NMurmurPrivate { + template <size_t> + struct TMurmurHash2ATraits; + + template <> + struct TMurmurHash2ATraits<32> { + using TValue = ui32; + static const TValue Multiplier = 0x5bd1e995; + enum { R1 = 24, + R2 = 13, + R3 = 15 }; + }; + + template <> + struct TMurmurHash2ATraits<64> { + using TValue = ui64; + static const TValue Multiplier = ULL(0xc6a4a7935bd1e995); + enum { R1 = 47, + R2 = 47, + R3 = 47 }; + }; +} + +template <class T> +class TMurmurHash2A { +private: + using TTraits = typename NMurmurPrivate::TMurmurHash2ATraits<8 * sizeof(T)>; + using TValue = typename TTraits::TValue; + +public: + inline TMurmurHash2A(TValue seed = 0) + : Hash(seed) + { + } + + inline TMurmurHash2A& Update(const void* buf, size_t len) noexcept { + Size += len; + + MixTail(buf, len); + + while (len >= sizeof(TValue)) { + Hash = Mix(Hash, ReadUnaligned<TValue>(buf)); + buf = static_cast<const char*>(buf) + sizeof(TValue); + len -= sizeof(TValue); + } + + MixTail(buf, len); + + return *this; + } + + inline TValue Value() const noexcept { + TValue hash = Mix(Mix(Hash, Tail), (TValue)Size); + + hash ^= hash >> TTraits::R2; + hash *= TTraits::Multiplier; + hash ^= hash >> TTraits::R3; + + return hash; + } + +private: + static inline TValue Mix(TValue h, TValue k) noexcept { + k *= TTraits::Multiplier; + k ^= k >> TTraits::R1; + k *= TTraits::Multiplier; + h *= TTraits::Multiplier; + h ^= k; + return h; + } + + inline void MixTail(const void*& buf, size_t& len) noexcept { + while (len && (len < sizeof(TValue) || Count)) { + Tail |= (TValue) * ((const unsigned char*&)buf)++ << (Count++ * 8); + + --len; + + if (Count == sizeof(TValue)) { + Hash = Mix(Hash, Tail); + Tail = 0; + Count = 0; + } + } + } + +private: + TValue Hash = 0; + TValue Tail = 0; + size_t Count = 0; + size_t Size = 0; +}; |