From e04ca1f4427f5900595ae95cc03e073d9395627f Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 30 May 2022 02:35:00 +0300 Subject: [PATCH] Match floating point hash values in 32 bit mode --- include/boost/container_hash/hash.hpp | 88 ++++++++++++++++++++++++--- 1 file changed, 80 insertions(+), 8 deletions(-) diff --git a/include/boost/container_hash/hash.hpp b/include/boost/container_hash/hash.hpp index 7c6223d..da346a3 100644 --- a/include/boost/container_hash/hash.hpp +++ b/include/boost/container_hash/hash.hpp @@ -168,34 +168,54 @@ namespace boost namespace hash_detail { - template::digits> struct hash_float_impl; + template::digits, + std::size_t size_t_bits = sizeof(std::size_t) * CHAR_BIT> + struct hash_float_impl; // float - template struct hash_float_impl + template struct hash_float_impl { static std::size_t fn( T v ) { boost::uint32_t w; std::memcpy( &w, &v, sizeof( v ) ); - return boost::hash_value( w ); + return w; } }; // double - template struct hash_float_impl + template struct hash_float_impl { static std::size_t fn( T v ) { boost::uint64_t w; std::memcpy( &w, &v, sizeof( v ) ); - return boost::hash_value( w ); + return w; + } + }; + + template struct hash_float_impl + { + static std::size_t fn( T v ) + { + boost::uint32_t w[ 2 ]; + std::memcpy( &w, &v, sizeof( v ) ); + + std::size_t seed = 0; + + seed ^= static_cast( w[0] ) + ( seed << 6 ) + ( seed >> 2 ); + seed ^= static_cast( w[1] ) + ( seed << 6 ) + ( seed >> 2 ); + + return seed; } }; // 80 bit long double in 12 bytes - template struct hash_float_impl + template struct hash_float_impl { static std::size_t fn( T v ) { @@ -211,8 +231,25 @@ namespace boost } }; + template struct hash_float_impl + { + static std::size_t fn( T v ) + { + boost::uint32_t w[ 3 ] = {}; + std::memcpy( &w, &v, 80 / CHAR_BIT ); + + std::size_t seed = 0; + + seed ^= static_cast( w[0] ) + ( seed << 6 ) + ( seed >> 2 ); + seed ^= static_cast( w[1] ) + ( seed << 6 ) + ( seed >> 2 ); + seed ^= static_cast( w[2] ) + ( seed << 6 ) + ( seed >> 2 ); + + return seed; + } + }; + // 80 bit long double in 16 bytes - template struct hash_float_impl + template struct hash_float_impl { static std::size_t fn( T v ) { @@ -228,8 +265,25 @@ namespace boost } }; + template struct hash_float_impl + { + static std::size_t fn( T v ) + { + boost::uint32_t w[ 3 ] = {}; + std::memcpy( &w, &v, 80 / CHAR_BIT ); + + std::size_t seed = 0; + + seed ^= static_cast( w[0] ) + ( seed << 6 ) + ( seed >> 2 ); + seed ^= static_cast( w[1] ) + ( seed << 6 ) + ( seed >> 2 ); + seed ^= static_cast( w[2] ) + ( seed << 6 ) + ( seed >> 2 ); + + return seed; + } + }; + // 128 bit long double - template struct hash_float_impl + template struct hash_float_impl { static std::size_t fn( T v ) { @@ -245,6 +299,24 @@ namespace boost } }; + template struct hash_float_impl + { + static std::size_t fn( T v ) + { + boost::uint32_t w[ 4 ]; + std::memcpy( &w, &v, sizeof( v ) ); + + std::size_t seed = 0; + + seed ^= static_cast( w[0] ) + ( seed << 6 ) + ( seed >> 2 ); + seed ^= static_cast( w[1] ) + ( seed << 6 ) + ( seed >> 2 ); + seed ^= static_cast( w[2] ) + ( seed << 6 ) + ( seed >> 2 ); + seed ^= static_cast( w[3] ) + ( seed << 6 ) + ( seed >> 2 ); + + return seed; + } + }; + } // namespace hash_detail template