From 8d9130fc685f2955657ee43ed53cc3019ce3faa8 Mon Sep 17 00:00:00 2001 From: Sergey Fedorov Date: Thu, 1 Aug 2024 07:21:48 +0800 Subject: [PATCH] Unbreak MurmurHash: revert 1110819343455b5f698e8d01a951b9da1b3b9c5a --- folly/hash/BUCK | 1 - folly/hash/MurmurHash.h | 27 +++--------- folly/hash/test/MurmurHashTest.cpp | 69 ++++++++++++------------------ 3 files changed, 32 insertions(+), 65 deletions(-) diff --git folly/hash/BUCK folly/hash/BUCK index af523d04a..e2f156106 100644 --- folly/hash/BUCK +++ folly/hash/BUCK @@ -67,6 +67,5 @@ cpp_library( exported_deps = [ "//folly:c_portability", "//folly/lang:bits", - "//folly/portability:constexpr", ], ) diff --git folly/hash/MurmurHash.h folly/hash/MurmurHash.h index 8bdf9e526..82854e72e 100644 --- folly/hash/MurmurHash.h +++ folly/hash/MurmurHash.h @@ -20,7 +20,6 @@ #include #include -#include namespace folly { namespace hash { @@ -32,17 +31,6 @@ FOLLY_ALWAYS_INLINE constexpr std::uint64_t shiftMix(std::uint64_t v) { return v ^ (v >> kShift); } -FOLLY_ALWAYS_INLINE constexpr std::uint64_t constexprLoad64( - const char* s, std::size_t l) { - static_assert(kIsLittleEndian); - - std::uint64_t ret = 0; - for (std::size_t i = 0; i < l; ++i) { - ret |= std::uint64_t(static_cast(s[i])) << (i * 8); - } - return ret; -} - } // namespace detail /* @@ -51,7 +39,7 @@ FOLLY_ALWAYS_INLINE constexpr std::uint64_t constexprLoad64( * * https://en.wikipedia.org/wiki/MurmurHash */ -constexpr std::uint64_t murmurHash64( +inline std::uint64_t murmurHash64( const char* key, std::size_t len, std::uint64_t seed) noexcept { constexpr std::uint64_t kMul = 0xc6a4a7935bd1e995UL; @@ -59,19 +47,14 @@ constexpr std::uint64_t murmurHash64( const char* beg = key; const char* end = beg + (len & ~0x7); - const std::size_t tail = len & 0x7; - for (const char* p = beg; p != end; p += 8) { - const std::uint64_t k = folly::is_constant_evaluated_or(false) - ? detail::constexprLoad64(p, 8) - : loadUnaligned(p); + for (const char* p = beg; p != end; p += sizeof(std::uint64_t)) { + const std::uint64_t k = loadUnaligned(p); hash = (hash ^ detail::shiftMix(k * kMul) * kMul) * kMul; } - if (tail != 0) { - const std::uint64_t k = folly::is_constant_evaluated_or(false) - ? detail::constexprLoad64(end, tail) - : partialLoadUnaligned(end, tail); + if ((len & 0x7) != 0) { + const std::uint64_t k = partialLoadUnaligned(end, len & 0x7); hash ^= k; hash *= kMul; } diff --git folly/hash/test/MurmurHashTest.cpp folly/hash/test/MurmurHashTest.cpp index 8cd0e5a58..e6e2487eb 100644 --- folly/hash/test/MurmurHashTest.cpp +++ folly/hash/test/MurmurHashTest.cpp @@ -21,56 +21,41 @@ #include -#define TEST_CASES(X) \ - /* Empty string */ \ - X("", UINT64_C(0)) \ - /* Short sequences, no execution of primary loop, only tail handling. */ \ - X("0", UINT64_C(5533571732986600803)) \ - X("01", UINT64_C(2988402087957123519)) \ - X("012", UINT64_C(18121251311279197961)) \ - X("0123", UINT64_C(3086299600550921888)) \ - X("01234", UINT64_C(12373468686010462630)) \ - X("012345", UINT64_C(8037360064841115407)) \ - X("0123456", UINT64_C(12284635732915976134)) \ - /* Only primary loop. */ \ - X("01234567", UINT64_C(9778579411364587418)) \ - X("0123456789ABCDEF", UINT64_C(8277819783762704778)) \ - X("0123456789ABCDEF01234567", UINT64_C(9980960296277708772)) \ - /* Primary loop and tail. */ \ - X("0123456789ABCDEF0", UINT64_C(654503456484488283)) \ - X("0123456789ABCDEF01", UINT64_C(10240825431821950816)) \ - X("0123456789ABCDEF012", UINT64_C(6811778381211949987)) \ - X("0123456789ABCDEF0123", UINT64_C(10791461727592423385)) \ - X("0123456789ABCDEF01234", UINT64_C(11236139906480711106)) \ - X("0123456789ABCDEF012345", UINT64_C(8264417865430344363)) \ - X("0123456789ABCDEF0123456", UINT64_C(2915833106541791378)) \ - /* Sequences with bytes represented as negative chars. */ \ - X("\x80", UINT64_C(13393303071874499911)) \ - X("\x80\x81", UINT64_C(3896321919913970216)) \ - X("\x80\x81\x82\x83\x84\x85\x86\x87", UINT64_C(2468552239318681156)) \ - X("\x61\x80\x81\x82\x83\x84\x85\x86\x87\x62", UINT64_C(836019401831928519)) - namespace { -constexpr std::uint64_t murmurHash64(std::string_view input) { +std::uint64_t murmurHash64(std::string_view input) { return folly::hash::murmurHash64(input.data(), input.size(), /* seed */ 0); } } // namespace -TEST(MurmurHash, Runtime){ -#define X(s, expected) EXPECT_EQ(murmurHash64(s), expected); - TEST_CASES(X) -#undef X +TEST(MurmurHash, Empty) { + EXPECT_EQ(murmurHash64(""), 0ULL); +} + +TEST(MurmurHash, Tail) { + // Short sequences, no execution of primary loop, only tail handling. + EXPECT_EQ(murmurHash64("0"), 5533571732986600803ULL); + EXPECT_EQ(murmurHash64("01"), 2988402087957123519ULL); + EXPECT_EQ(murmurHash64("012"), 18121251311279197961ULL); + EXPECT_EQ(murmurHash64("0123"), 3086299600550921888ULL); + EXPECT_EQ(murmurHash64("01234"), 12373468686010462630ULL); + EXPECT_EQ(murmurHash64("012345"), 8037360064841115407ULL); + EXPECT_EQ(murmurHash64("0123456"), 12284635732915976134ULL); } -TEST(MurmurHash, Constexpr) { -#define X(s, expected) \ - { \ - constexpr uint64_t h = murmurHash64(s); \ - static_assert(h == expected); \ - } +TEST(MurmurHash, PrimaryLoop) { + EXPECT_EQ(murmurHash64("01234567"), 9778579411364587418ULL); + EXPECT_EQ(murmurHash64("0123456789ABCDEF"), 8277819783762704778ULL); + EXPECT_EQ(murmurHash64("0123456789ABCDEF01234567"), 9980960296277708772ULL); +} - TEST_CASES(X) -#undef X +TEST(MurmurHash, PrimaryLoopAndTail) { + EXPECT_EQ(murmurHash64("0123456789ABCDEF0"), 654503456484488283ULL); + EXPECT_EQ(murmurHash64("0123456789ABCDEF01"), 10240825431821950816ULL); + EXPECT_EQ(murmurHash64("0123456789ABCDEF012"), 6811778381211949987ULL); + EXPECT_EQ(murmurHash64("0123456789ABCDEF0123"), 10791461727592423385ULL); + EXPECT_EQ(murmurHash64("0123456789ABCDEF01234"), 11236139906480711106ULL); + EXPECT_EQ(murmurHash64("0123456789ABCDEF012345"), 8264417865430344363ULL); + EXPECT_EQ(murmurHash64("0123456789ABCDEF0123456"), 2915833106541791378ULL); }