diff --git a/parallel_hashmap/phmap.h b/parallel_hashmap/phmap.h index b1b3245..9bf5aa0 100644 --- a/parallel_hashmap/phmap.h +++ b/parallel_hashmap/phmap.h @@ -60,28 +60,6 @@ namespace phmap { // --------------------------------------------------------------- -// phmap::Hash -// --------------------------------------------------------------- -template -struct Hash -{ - inline size_t operator()(const T& __v) const - { - return std::hash()(__v); - } -}; - -template -struct Hash -{ - inline size_t operator()(const T *__v) const noexcept - { - static const size_t shift = 3; - const uintptr_t i = (const uintptr_t)__v; - return static_cast(i >> shift); - } -}; - // from http://burtleburtle.net/bob/hash/integer.html // fast and efficient for power of two table sizes where we always // consider the last bits. @@ -94,20 +72,36 @@ inline size_t phmap_mix_32(uint32_t a) return static_cast(a); } -// More thorough scrambling as described in -// https://gist.github.com/badboy/6267743 -// ---------------------------------------- +// Very fast mixing: https://godbolt.org/z/3F709Y +// ---------------------------------------------- inline size_t phmap_mix_64(uint64_t a) { - a = (~a) + (a << 21); // a = (a << 21) - a - 1; - a = a ^ (a >> 24); - a = (a + (a << 3)) + (a << 8); // a * 265 - a = a ^ (a >> 14); - a = (a + (a << 2)) + (a << 4); // a * 21 - a = a ^ (a >> 28); - a = a + (a << 31); - return static_cast(a); + static constexpr uint64_t k = UINT64_C(0xde5fb9d2630458e9); + uint64_t h; + uint64_t l = umul128(a, k, &h); + return static_cast(h + l); } +// --------------------------------------------------------------- +// phmap::Hash +// --------------------------------------------------------------- +template +struct Hash +{ + inline size_t operator()(const T& __v) const + { + // we mix for safety in case std::hash broken. + return phmap_mix_64(std::hash()(__v)); + } +}; + +template +struct Hash +{ + inline size_t operator()(const T *__v) const noexcept + { + return phmap_mix_64(static_cast(__v)); + } +}; template struct phmap_unary_function @@ -155,28 +149,28 @@ template <> struct Hash : public phmap_unary_function { inline size_t operator()(int16_t __v) const noexcept - { return phmap_mix_32(static_cast(__v)); } + { return phmap_mix_64(static_cast(__v)); } }; template <> struct Hash : public phmap_unary_function { inline size_t operator()(uint16_t __v) const noexcept - { return phmap_mix_32(static_cast(__v)); } + { return phmap_mix_64(static_cast(__v)); } }; template <> struct Hash : public phmap_unary_function { inline size_t operator()(int32_t __v) const noexcept - { return phmap_mix_32(static_cast(__v)); } + { return phmap_mix_64(static_cast(__v)); } }; template <> struct Hash : public phmap_unary_function { inline size_t operator()(uint32_t __v) const noexcept - { return phmap_mix_32(static_cast(__v)); } + { return phmap_mix_64(static_cast(__v)); } }; template <> @@ -200,7 +194,7 @@ struct Hash : public phmap_unary_function { // -0.0 and 0.0 should return same hash uint32_t *as_int = reinterpret_cast(&__v); - return (__v == 0) ? static_cast(0) : phmap_mix_32(*as_int); + return (__v == 0) ? static_cast(0) : phmap_mix_64(*as_int); } }; diff --git a/parallel_hashmap/phmap_bits.h b/parallel_hashmap/phmap_bits.h index c8e0d7a..ac1a677 100644 --- a/parallel_hashmap/phmap_bits.h +++ b/parallel_hashmap/phmap_bits.h @@ -467,6 +467,21 @@ PHMAP_BASE_INTERNAL_FORCEINLINE int CountTrailingZerosNonZero32(uint32_t n) { #define PHMAP_BLOCK_TAIL_CALL_OPTIMIZATION() if (volatile int x = 0) { (void)x; } #endif +#ifdef PHMAP_HAVE_INTRINSIC_INT128 + inline uint64_t umul128(uint64_t a, uint64_t b, uint64_t* high) + { + auto result = static_cast(a) * static_cast(b); + *high = static_cast(result >> 64); + return static_cast(result); + } +#elif (defined(_MSC_VER)) + #pragma intrinsic(_umul128) + inline uint64_t umul128(uint64_t a, uint64_t b, uint64_t* high) + { + return _umul128(a, b, high); + } +#endif + #if defined(__GNUC__) // Cache line alignment #if defined(__i386__) || defined(__x86_64__)