mirror of
https://github.com/greg7mdp/parallel-hashmap.git
synced 2026-08-29 16:40:39 +08:00
Fix issue #158 - imperfect hash for tuple of small integers
This commit is contained in:
Vendored
+1
@@ -145,6 +145,7 @@ if (PHMAP_BUILD_EXAMPLES)
|
||||
target_include_directories(ex_serialize PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../cereal/include>)
|
||||
add_executable(ex_hash_std examples/hash_std.cc phmap.natvis)
|
||||
add_executable(ex_hash_value examples/hash_value.cc phmap.natvis)
|
||||
add_executable(ex_hash examples/hash.cc phmap.natvis)
|
||||
add_executable(ex_two_files examples/f1.cc examples/f2.cc phmap.natvis)
|
||||
add_executable(ex_insert_bench examples/insert_bench.cc phmap.natvis)
|
||||
add_executable(ex_knucleotide examples/knucleotide.cc phmap.natvis)
|
||||
|
||||
Vendored
+61
-13
@@ -286,6 +286,13 @@ struct Hash<double> : public phmap_unary_function<double, size_t>
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# define PHMAP_HASH_ROTL32(x, r) _rotl(x,r)
|
||||
#else
|
||||
# define PHMAP_HASH_ROTL32(x, r) (x << r) | (x >> (32 - r))
|
||||
#endif
|
||||
|
||||
|
||||
template <class H, int sz> struct Combiner
|
||||
{
|
||||
H operator()(H seed, size_t value);
|
||||
@@ -293,17 +300,57 @@ template <class H, int sz> struct Combiner
|
||||
|
||||
template <class H> struct Combiner<H, 4>
|
||||
{
|
||||
H operator()(H seed, size_t value)
|
||||
H operator()(H h1, size_t k1)
|
||||
{
|
||||
return seed ^ (value + 0x9e3779b9 + (seed << 6) + (seed >> 2));
|
||||
#if 1
|
||||
// Copyright 2005-2014 Daniel James.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
const uint32_t c1 = 0xcc9e2d51;
|
||||
const uint32_t c2 = 0x1b873593;
|
||||
|
||||
k1 *= c1;
|
||||
k1 = PHMAP_HASH_ROTL32(k1,15);
|
||||
k1 *= c2;
|
||||
|
||||
h1 ^= k1;
|
||||
h1 = PHMAP_HASH_ROTL32(h1,13);
|
||||
h1 = h1*5+0xe6546b64;
|
||||
|
||||
return h1;
|
||||
#else
|
||||
return h1 ^ (k1 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2));
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
template <class H> struct Combiner<H, 8>
|
||||
{
|
||||
H operator()(H seed, size_t value)
|
||||
H operator()(H h, size_t k)
|
||||
{
|
||||
return seed ^ (value + size_t(0xc6a4a7935bd1e995) + (seed << 6) + (seed >> 2));
|
||||
#if 1
|
||||
// Copyright 2005-2014 Daniel James.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
const uint64_t m = (uint64_t(0xc6a4a793) << 32) + 0x5bd1e995;
|
||||
const int r = 47;
|
||||
|
||||
k *= m;
|
||||
k ^= k >> r;
|
||||
k *= m;
|
||||
|
||||
h ^= k;
|
||||
h *= m;
|
||||
|
||||
// Completely arbitrary number, to prevent 0's
|
||||
// from hashing to 0.
|
||||
h += 0xe6546b64;
|
||||
|
||||
return h;
|
||||
#else
|
||||
return h ^ (k + size_t(0xc6a4a7935bd1e995) + (h << 6) + (h >> 2));
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
@@ -347,21 +394,22 @@ struct Hash<std::pair<T1, T2>> {
|
||||
template<class... T>
|
||||
struct Hash<std::tuple<T...>> {
|
||||
size_t operator()(std::tuple<T...> const& t) const noexcept {
|
||||
return _hash_helper(t);
|
||||
size_t seed = 0;
|
||||
return _hash_helper(seed, t);
|
||||
}
|
||||
|
||||
private:
|
||||
template<size_t I = 0, class ...P>
|
||||
typename std::enable_if<I == sizeof...(P), size_t>::type
|
||||
_hash_helper(const std::tuple<P...> &) const noexcept { return 0; }
|
||||
template<size_t I = 0, class TUP>
|
||||
typename std::enable_if<I == std::tuple_size<TUP>::value, size_t>::type
|
||||
_hash_helper(size_t seed, const TUP &) const noexcept { return seed; }
|
||||
|
||||
template<size_t I = 0, class ...P>
|
||||
typename std::enable_if<I < sizeof...(P), size_t>::type
|
||||
_hash_helper(const std::tuple<P...> &t) const noexcept {
|
||||
template<size_t I = 0, class TUP>
|
||||
typename std::enable_if<I < std::tuple_size<TUP>::value, size_t>::type
|
||||
_hash_helper(size_t seed, const TUP &t) const noexcept {
|
||||
const auto &el = std::get<I>(t);
|
||||
using el_type = typename std::remove_cv<typename std::remove_reference<decltype(el)>::type>::type;
|
||||
return Combiner<size_t, sizeof(size_t)>()(
|
||||
phmap::Hash<el_type>()(el), _hash_helper<I + 1>(t));
|
||||
seed = Combiner<size_t, sizeof(size_t)>()(seed, phmap::Hash<el_type>()(el));
|
||||
return _hash_helper<I + 1>(seed, t);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user