Move std::complex support to hash.hpp

This commit is contained in:
Peter Dimov
2021-10-17 02:03:50 +03:00
parent fe66085fbc
commit a0a6fa0616
3 changed files with 41 additions and 17 deletions

View File

@@ -21,7 +21,6 @@
#include <boost/container_hash/hash.hpp> #include <boost/container_hash/hash.hpp>
#include <boost/core/enable_if.hpp> #include <boost/core/enable_if.hpp>
#include <boost/static_assert.hpp> #include <boost/static_assert.hpp>
#include <complex>
#if !defined(BOOST_NO_CXX11_HDR_TUPLE) #if !defined(BOOST_NO_CXX11_HDR_TUPLE)
# include <tuple> # include <tuple>
@@ -36,9 +35,6 @@ namespace boost
template <class A, class B> template <class A, class B>
std::size_t hash_value(std::pair<A, B> const&); std::size_t hash_value(std::pair<A, B> const&);
template <class T>
std::size_t hash_value(std::complex<T> const&);
template <class A, class B> template <class A, class B>
std::size_t hash_value(std::pair<A, B> const& v) std::size_t hash_value(std::pair<A, B> const& v)
{ {
@@ -48,15 +44,6 @@ namespace boost
return seed; return seed;
} }
template <class T>
std::size_t hash_value(std::complex<T> const& v)
{
boost::hash<T> hasher;
std::size_t seed = hasher(v.imag());
seed ^= hasher(v.real()) + (seed<<6) + (seed>>2);
return seed;
}
#if !defined(BOOST_NO_CXX11_HDR_TUPLE) #if !defined(BOOST_NO_CXX11_HDR_TUPLE)
namespace hash_detail { namespace hash_detail {
template <std::size_t I, typename T> template <std::size_t I, typename T>

View File

@@ -30,6 +30,7 @@
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
#include <iterator> #include <iterator>
#include <string> #include <string>
#include <complex>
#include <climits> #include <climits>
#if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX) #if !defined(BOOST_NO_CXX11_HDR_TYPEINDEX)
@@ -153,6 +154,19 @@ namespace boost
return boost::hash_range( x, x + N ); return boost::hash_range( x, x + N );
} }
// complex
template <class T>
std::size_t hash_value( std::complex<T> const& v )
{
std::size_t seed = 0;
boost::hash_combine( seed, v.real() );
boost::hash_combine( seed, v.imag() );
return seed;
}
// ranges (list, set, deque...) // ranges (list, set, deque...)
template <typename T> template <typename T>

View File

@@ -39,9 +39,10 @@ int main() {}
#pragma GCC diagnostic ignored "-Wfloat-equal" #pragma GCC diagnostic ignored "-Wfloat-equal"
#endif #endif
#include <boost/limits.hpp>
#include <complex> #include <complex>
#include <sstream> #include <sstream>
#include <boost/limits.hpp> #include <set>
template <class T> template <class T>
void generic_complex_tests(std::complex<T> v) void generic_complex_tests(std::complex<T> v)
@@ -52,11 +53,11 @@ void generic_complex_tests(std::complex<T> v)
BOOST_HASH_TEST_NAMESPACE::hash<T> real_hasher; BOOST_HASH_TEST_NAMESPACE::hash<T> real_hasher;
T real = v.real(); T real = v.real();
T imag = v.imag(); // T imag = v.imag();
BOOST_TEST(real_hasher(real) == complex_hasher(std::complex<T>(real))); // BOOST_TEST(real_hasher(real) == complex_hasher(std::complex<T>(real)));
if(imag != 0 && real_hasher(real) == complex_hasher(v)) { if(real_hasher(real) == complex_hasher(v)) {
std::ostringstream os; std::ostringstream os;
os<<"real_hasher("<<real<<") == complex_hasher(" os<<"real_hasher("<<real<<") == complex_hasher("
<<v.real()<<" + "<<v.imag()<<"i) == " <<v.real()<<" + "<<v.imag()<<"i) == "
@@ -88,6 +89,23 @@ void complex_integral_tests(Integer*)
generic_complex_tests(complex(Integer(-543),Integer(763))); generic_complex_tests(complex(Integer(-543),Integer(763)));
} }
template<class T> void complex_grid_test()
{
short const N = 16;
std::set<std::size_t> hashes;
for( short i = 0; i < N; ++i )
{
for( short j = 0; j < N; ++j )
{
hashes.insert( boost::hash< std::complex<T> >()( std::complex<T>( i, j ) ) );
}
}
BOOST_TEST_EQ( hashes.size(), N * N );
}
int main() int main()
{ {
// I've comments out the short and unsigned short tests // I've comments out the short and unsigned short tests
@@ -104,6 +122,11 @@ int main()
complex_integral_tests((unsigned int*) 0); complex_integral_tests((unsigned int*) 0);
complex_integral_tests((unsigned long*) 0); complex_integral_tests((unsigned long*) 0);
complex_grid_test<int>();
complex_grid_test<float>();
complex_grid_test<double>();
complex_grid_test<long double>();
return boost::report_errors(); return boost::report_errors();
} }