Compare commits

...

3 Commits

Author SHA1 Message Date
Peter Dimov
789261c68c Update 32 bit float reference values (for GCC) 2022-09-20 15:23:13 +03:00
Peter Dimov
29ee19ee7f Update 32 bit float reference values (for MSVC) 2022-09-20 15:08:21 +03:00
Peter Dimov
8bb7d43646 Simplify hash_value for floating point 2022-09-20 15:01:45 +03:00
2 changed files with 40 additions and 93 deletions

View File

@@ -176,12 +176,11 @@ namespace boost
{
template<class T,
std::size_t Bits = sizeof(T) * CHAR_BIT,
int Digits = std::numeric_limits<T>::digits,
std::size_t size_t_bits = sizeof(std::size_t) * CHAR_BIT>
int Digits = std::numeric_limits<T>::digits>
struct hash_float_impl;
// float
template<class T, int Digits, std::size_t size_t_bits> struct hash_float_impl<T, 32, Digits, size_t_bits>
template<class T, int Digits> struct hash_float_impl<T, 32, Digits>
{
static std::size_t fn( T v )
{
@@ -193,35 +192,19 @@ namespace boost
};
// double
template<class T, int Digits> struct hash_float_impl<T, 64, Digits, 64>
template<class T, int Digits> struct hash_float_impl<T, 64, Digits>
{
static std::size_t fn( T v )
{
boost::uint64_t w;
std::memcpy( &w, &v, sizeof( v ) );
return w;
}
};
template<class T, int Digits> struct hash_float_impl<T, 64, Digits, 32>
{
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<std::size_t>( w[0] ) + hash_detail::hash_mix( seed );
seed = static_cast<std::size_t>( w[1] ) + hash_detail::hash_mix( seed );
return seed;
return hash_value( w );
}
};
// 80 bit long double in 12 bytes
template<class T> struct hash_float_impl<T, 96, 64, 64>
template<class T> struct hash_float_impl<T, 96, 64>
{
static std::size_t fn( T v )
{
@@ -230,32 +213,15 @@ namespace boost
std::size_t seed = 0;
seed = static_cast<std::size_t>( w[0] ) + hash_detail::hash_mix( seed );
seed = static_cast<std::size_t>( w[1] ) + hash_detail::hash_mix( seed );
return seed;
}
};
template<class T> struct hash_float_impl<T, 96, 64, 32>
{
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<std::size_t>( w[0] ) + hash_detail::hash_mix( seed );
seed = static_cast<std::size_t>( w[1] ) + hash_detail::hash_mix( seed );
seed = static_cast<std::size_t>( w[2] ) + hash_detail::hash_mix( seed );
seed = hash_value( w[0] ) + hash_detail::hash_mix( seed );
seed = hash_value( w[1] ) + hash_detail::hash_mix( seed );
return seed;
}
};
// 80 bit long double in 16 bytes
template<class T> struct hash_float_impl<T, 128, 64, 64>
template<class T> struct hash_float_impl<T, 128, 64>
{
static std::size_t fn( T v )
{
@@ -264,32 +230,15 @@ namespace boost
std::size_t seed = 0;
seed = static_cast<std::size_t>( w[0] ) + hash_detail::hash_mix( seed );
seed = static_cast<std::size_t>( w[1] ) + hash_detail::hash_mix( seed );
return seed;
}
};
template<class T> struct hash_float_impl<T, 128, 64, 32>
{
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<std::size_t>( w[0] ) + hash_detail::hash_mix( seed );
seed = static_cast<std::size_t>( w[1] ) + hash_detail::hash_mix( seed );
seed = static_cast<std::size_t>( w[2] ) + hash_detail::hash_mix( seed );
seed = hash_value( w[0] ) + hash_detail::hash_mix( seed );
seed = hash_value( w[1] ) + hash_detail::hash_mix( seed );
return seed;
}
};
// 128 bit long double
template<class T, int Digits, std::size_t size_t_bits> struct hash_float_impl<T, 128, Digits, size_t_bits>
template<class T, int Digits> struct hash_float_impl<T, 128, Digits>
{
static std::size_t fn( T v )
{
@@ -630,6 +579,4 @@ namespace boost
#endif
}
#undef BOOST_FUNCTIONAL_HASH_ROTL32
#endif // #ifndef BOOST_FUNCTIONAL_HASH_HASH_HPP

View File

@@ -171,16 +171,16 @@ int main()
#if SIZE_MAX == 4294967295U
BOOST_TEST_EQ( hv(1.0), 1072693248U );
BOOST_TEST_EQ( hv(-1.0), 3220176896U );
BOOST_TEST_EQ( hv(3.14), 3972386992U );
BOOST_TEST_EQ( hv(-3.14), 1824903344U );
BOOST_TEST_EQ( hv(1e-308), 2213556530U );
BOOST_TEST_EQ( hv(-1e-308), 66072882U );
BOOST_TEST_EQ( hv(1e+308), 2623678890U );
BOOST_TEST_EQ( hv(-1e+308), 476195242U );
BOOST_TEST_EQ( hv(std::numeric_limits<double>::infinity()), 2146435072U );
BOOST_TEST_EQ( hv(-std::numeric_limits<double>::infinity()), 4293918720U );
BOOST_TEST_EQ( hv(1.0), 2619008688U );
BOOST_TEST_EQ( hv(-1.0), 146497060U );
BOOST_TEST_EQ( hv(3.14), 101651732U );
BOOST_TEST_EQ( hv(-3.14), 210858151U );
BOOST_TEST_EQ( hv(1e-308), 3911789313U );
BOOST_TEST_EQ( hv(-1e-308), 1812507313U );
BOOST_TEST_EQ( hv(1e+308), 987802568U );
BOOST_TEST_EQ( hv(-1e+308), 1639042439U );
BOOST_TEST_EQ( hv(std::numeric_limits<double>::infinity()), 3227645345U );
BOOST_TEST_EQ( hv(-std::numeric_limits<double>::infinity()), 2247339177U );
#else
@@ -207,21 +207,23 @@ int main()
if( ldbits == 64 )
{
BOOST_TEST_EQ( hv(1.0L), 1072693248U );
BOOST_TEST_EQ( hv(-1.0L), 3220176896U );
BOOST_TEST_EQ( hv(3.14L), 3972386992U );
BOOST_TEST_EQ( hv(-3.14L), 1824903344U );
BOOST_TEST_EQ( hv(std::numeric_limits<long double>::infinity()), 2146435072U );
BOOST_TEST_EQ( hv(-std::numeric_limits<long double>::infinity()), 4293918720U );
BOOST_TEST_EQ( hv(1.0L), hv(1.0) );
BOOST_TEST_EQ( hv(-1.0L), hv(-1.0) );
BOOST_TEST_EQ( hv(3.14L), hv(3.14) );
BOOST_TEST_EQ( hv(-3.14L), hv(-3.14) );
BOOST_TEST_EQ( hv(std::numeric_limits<long double>::infinity()), hv(std::numeric_limits<double>::infinity()) );
BOOST_TEST_EQ( hv(-std::numeric_limits<long double>::infinity()), hv(-std::numeric_limits<double>::infinity()) );
}
else
{
BOOST_TEST_EQ( hv(1.0L), 3770520689U );
BOOST_TEST_EQ( hv(-1.0L), 3770553457U );
BOOST_TEST_EQ( hv(3.14L), 1150018772U );
BOOST_TEST_EQ( hv(-3.14L), 1150051540U );
BOOST_TEST_EQ( hv(std::numeric_limits<long double>::infinity()), 3770537073U );
BOOST_TEST_EQ( hv(-std::numeric_limits<long double>::infinity()), 3770569841U );
// ldbits == 96
BOOST_TEST_EQ( hv(1.0L), 3632050780U );
BOOST_TEST_EQ( hv(-1.0L), 3632083548U );
BOOST_TEST_EQ( hv(3.14L), 1742026549U );
BOOST_TEST_EQ( hv(-3.14L), 1742059317U );
BOOST_TEST_EQ( hv(std::numeric_limits<long double>::infinity()), 3632067164U );
BOOST_TEST_EQ( hv(-std::numeric_limits<long double>::infinity()), 3632099932U );
}
#else
@@ -246,9 +248,7 @@ int main()
}
else
{
// ldbits == 128 && std::numeric_limits<long double>::digits == 113
// under ARM64 and S390x, but the values differ presumably because of
// __FLOAT_WORD_ORDER__
// ldbits == 128 && std::numeric_limits<long double>::digits == 113
BOOST_TEST_EQ( hv(1.0L), 4611404543450677248ULL );
BOOST_TEST_EQ( hv(-1.0L), 13834776580305453056ULL );
@@ -344,10 +344,10 @@ int main()
#if SIZE_MAX == 4294967295U
BOOST_TEST_EQ( hv(std::complex<double>(+1.0, 0.0)), 1072693248U );
BOOST_TEST_EQ( hv(std::complex<double>(-1.0, 0.0)), 3220176896U );
BOOST_TEST_EQ( hv(std::complex<double>(0.0, +1.0)), 2619008688U );
BOOST_TEST_EQ( hv(std::complex<double>(0.0, -1.0)), 146497060U );
BOOST_TEST_EQ( hv(std::complex<double>(+1.0, 0.0)), 2619008688U );
BOOST_TEST_EQ( hv(std::complex<double>(-1.0, 0.0)), 146497060U );
BOOST_TEST_EQ( hv(std::complex<double>(0.0, +1.0)), 22395692U );
BOOST_TEST_EQ( hv(std::complex<double>(0.0, -1.0)), 1449221192U );
#else