forked from boostorg/container_hash
Fix hash_combine_impl to only test for a specific bit width and not for concrete types
This commit is contained in:
@@ -26,6 +26,7 @@
|
|||||||
#include <boost/type_traits/is_integral.hpp>
|
#include <boost/type_traits/is_integral.hpp>
|
||||||
#include <boost/core/enable_if.hpp>
|
#include <boost/core/enable_if.hpp>
|
||||||
#include <boost/cstdint.hpp>
|
#include <boost/cstdint.hpp>
|
||||||
|
#include <climits>
|
||||||
|
|
||||||
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||||
#include <boost/type_traits/is_pointer.hpp>
|
#include <boost/type_traits/is_pointer.hpp>
|
||||||
@@ -307,52 +308,56 @@ namespace boost
|
|||||||
return seed;
|
return seed;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename SizeT>
|
template<int Bits> struct hash_combine_impl
|
||||||
inline void hash_combine_impl(SizeT& seed, SizeT value)
|
|
||||||
{
|
{
|
||||||
seed ^= value + 0x9e3779b9 + (seed<<6) + (seed>>2);
|
template <typename SizeT>
|
||||||
}
|
inline static SizeT fn(SizeT seed, SizeT value)
|
||||||
|
{
|
||||||
|
seed ^= value + 0x9e3779b9 + (seed<<6) + (seed>>2);
|
||||||
|
return seed;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
inline void hash_combine_impl(boost::uint32_t& h1,
|
template<> struct hash_combine_impl<32>
|
||||||
boost::uint32_t k1)
|
|
||||||
{
|
{
|
||||||
const uint32_t c1 = 0xcc9e2d51;
|
inline static boost::uint32_t fn(boost::uint32_t h1, boost::uint32_t k1)
|
||||||
const uint32_t c2 = 0x1b873593;
|
{
|
||||||
|
const boost::uint32_t c1 = 0xcc9e2d51;
|
||||||
|
const boost::uint32_t c2 = 0x1b873593;
|
||||||
|
|
||||||
k1 *= c1;
|
k1 *= c1;
|
||||||
k1 = BOOST_FUNCTIONAL_HASH_ROTL32(k1,15);
|
k1 = BOOST_FUNCTIONAL_HASH_ROTL32(k1,15);
|
||||||
k1 *= c2;
|
k1 *= c2;
|
||||||
|
|
||||||
h1 ^= k1;
|
h1 ^= k1;
|
||||||
h1 = BOOST_FUNCTIONAL_HASH_ROTL32(h1,13);
|
h1 = BOOST_FUNCTIONAL_HASH_ROTL32(h1,13);
|
||||||
h1 = h1*5+0xe6546b64;
|
h1 = h1*5+0xe6546b64;
|
||||||
}
|
|
||||||
|
|
||||||
|
return h1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Don't define 64-bit hash combine on platforms without 64 bit integers,
|
template<> struct hash_combine_impl<64>
|
||||||
// and also not for 32-bit gcc as it warns about the 64-bit constant.
|
|
||||||
#if !defined(BOOST_NO_INT64_T) && \
|
|
||||||
!(defined(__GNUC__) && ULONG_MAX == 0xffffffff)
|
|
||||||
|
|
||||||
inline void hash_combine_impl(boost::uint64_t& h,
|
|
||||||
boost::uint64_t k)
|
|
||||||
{
|
{
|
||||||
const boost::uint64_t m = UINT64_C(0xc6a4a7935bd1e995);
|
inline static boost::uint64_t fn(boost::uint64_t h, boost::uint64_t k)
|
||||||
const int r = 47;
|
{
|
||||||
|
const boost::uint64_t m = (boost::uint64_t(0xc6a4a793) << 32) + 0x5bd1e995;
|
||||||
|
const int r = 47;
|
||||||
|
|
||||||
k *= m;
|
k *= m;
|
||||||
k ^= k >> r;
|
k ^= k >> r;
|
||||||
k *= m;
|
k *= m;
|
||||||
|
|
||||||
h ^= k;
|
h ^= k;
|
||||||
h *= m;
|
h *= m;
|
||||||
|
|
||||||
// Completely arbitrary number, to prevent 0's
|
// Completely arbitrary number, to prevent 0's
|
||||||
// from hashing to 0.
|
// from hashing to 0.
|
||||||
h += 0xe6546b64;
|
h += 0xe6546b64;
|
||||||
}
|
|
||||||
|
|
||||||
#endif // BOOST_NO_INT64_T
|
return h;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -413,7 +418,7 @@ namespace boost
|
|||||||
inline void hash_combine(std::size_t& seed, T const& v)
|
inline void hash_combine(std::size_t& seed, T const& v)
|
||||||
{
|
{
|
||||||
boost::hash<T> hasher;
|
boost::hash<T> hasher;
|
||||||
return boost::hash_detail::hash_combine_impl(seed, hasher(v));
|
seed = boost::hash_detail::hash_combine_impl<sizeof(std::size_t) * CHAR_BIT>::fn(seed, hasher(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(BOOST_MSVC)
|
#if defined(BOOST_MSVC)
|
||||||
|
Reference in New Issue
Block a user