murmur.h 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. #pragma once
  2. #include <util/system/defaults.h>
  3. #include <util/system/unaligned_mem.h>
  4. /*
  5. * https://sites.google.com/site/murmurhash/
  6. */
  7. namespace NMurmurPrivate {
  8. template <size_t>
  9. struct TMurmurHash2ATraits;
  10. template <>
  11. struct TMurmurHash2ATraits<32> {
  12. using TValue = ui32;
  13. static const TValue Multiplier = 0x5bd1e995;
  14. enum { R1 = 24,
  15. R2 = 13,
  16. R3 = 15 };
  17. };
  18. template <>
  19. struct TMurmurHash2ATraits<64> {
  20. using TValue = ui64;
  21. static const TValue Multiplier = ULL(0xc6a4a7935bd1e995);
  22. enum { R1 = 47,
  23. R2 = 47,
  24. R3 = 47 };
  25. };
  26. }
  27. template <class T>
  28. class TMurmurHash2A {
  29. private:
  30. using TTraits = typename NMurmurPrivate::TMurmurHash2ATraits<8 * sizeof(T)>;
  31. using TValue = typename TTraits::TValue;
  32. public:
  33. inline TMurmurHash2A(TValue seed = 0)
  34. : Hash(seed)
  35. {
  36. }
  37. inline TMurmurHash2A& Update(const void* buf, size_t len) noexcept {
  38. Size += len;
  39. MixTail(buf, len);
  40. while (len >= sizeof(TValue)) {
  41. Hash = Mix(Hash, ReadUnaligned<TValue>(buf));
  42. buf = static_cast<const char*>(buf) + sizeof(TValue);
  43. len -= sizeof(TValue);
  44. }
  45. MixTail(buf, len);
  46. return *this;
  47. }
  48. inline TValue Value() const noexcept {
  49. TValue hash = Mix(Mix(Hash, Tail), (TValue)Size);
  50. hash ^= hash >> TTraits::R2;
  51. hash *= TTraits::Multiplier;
  52. hash ^= hash >> TTraits::R3;
  53. return hash;
  54. }
  55. private:
  56. static inline TValue Mix(TValue h, TValue k) noexcept {
  57. k *= TTraits::Multiplier;
  58. k ^= k >> TTraits::R1;
  59. k *= TTraits::Multiplier;
  60. h *= TTraits::Multiplier;
  61. h ^= k;
  62. return h;
  63. }
  64. inline void MixTail(const void*& buf, size_t& len) noexcept {
  65. while (len && (len < sizeof(TValue) || Count)) {
  66. Tail |= (TValue) * ((const unsigned char*&)buf)++ << (Count++ * 8);
  67. --len;
  68. if (Count == sizeof(TValue)) {
  69. Hash = Mix(Hash, Tail);
  70. Tail = 0;
  71. Count = 0;
  72. }
  73. }
  74. }
  75. private:
  76. TValue Hash = 0;
  77. TValue Tail = 0;
  78. size_t Count = 0;
  79. size_t Size = 0;
  80. };