Compare commits

...

8 Commits

Author SHA1 Message Date
Glen Fernandes
f86cdfe502 Simplify and generalize hash_integral_impl 2022-06-27 13:25:02 -04:00
Peter Dimov
c28d0b813b Directly cast to size_t all integrals no wider than size_t 2022-06-26 01:25:45 +03:00
Peter Dimov
e39bf42dfc Update hash_string_test2.cpp 2022-06-15 22:56:57 +03:00
Peter Dimov
58502fddca Add hash_container_test.cpp 2022-06-15 22:52:56 +03:00
Peter Dimov
5701dd3119 Merge branch 'master' into develop 2022-06-14 15:38:19 +03:00
Peter Dimov
53c12550fa Define _SILENCE_NONFLOATING_COMPLEX_DEPRECATION_WARNING in hash_reference_values.cpp (refs #23) 2022-06-14 14:42:22 +03:00
Peter Dimov
561cc5d010 Merge branch 'master' into develop 2022-06-13 14:26:03 +03:00
Peter Dimov
bdf4bfe910 Disable C4996 in hash_complex_test.cpp (refs #23) 2022-06-13 14:05:35 +03:00
6 changed files with 111 additions and 42 deletions

View File

@@ -1,5 +1,6 @@
// Copyright 2005-2014 Daniel James.
// Copyright 2021 Peter Dimov.
// Copyright 2022 Glen Joseph Fernandes (glenjofe@gmail.com)
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
@@ -77,11 +78,11 @@ namespace boost
{
template<class T,
bool bigger_than_size_t = (sizeof(T) > sizeof(std::size_t)),
std::size_t size_t_bits = sizeof(std::size_t) * CHAR_BIT,
std::size_t type_bits = sizeof(T) * CHAR_BIT>
bool is_unsigned = boost::is_unsigned<T>::value,
std::size_t blocks = sizeof(T) / sizeof(std::size_t)>
struct hash_integral_impl;
template<class T, std::size_t size_t_bits, std::size_t type_bits> struct hash_integral_impl<T, false, size_t_bits, type_bits>
template<class T, bool is_unsigned, std::size_t blocks> struct hash_integral_impl<T, false, is_unsigned, blocks>
{
static std::size_t fn( T v )
{
@@ -89,41 +90,53 @@ namespace boost
}
};
template<class T> struct hash_integral_impl<T, true, 32, 64>
template<class T, std::size_t blocks> struct hash_integral_impl<T, true, false, blocks>
{
static std::size_t fn( T v )
{
typedef typename boost::make_unsigned<T>::type U;
if( v >= 0 )
{
return hash_integral_impl<U>::fn( static_cast<U>( v ) );
}
else
{
return ~hash_integral_impl<U>::fn( static_cast<U>( ~static_cast<U>( v ) ) );
}
}
};
template<class T> struct hash_integral_impl<T, true, true, 2>
{
static std::size_t fn( T v )
{
enum {
M = sizeof(std::size_t) * CHAR_BIT
};
std::size_t seed = 0;
seed ^= static_cast<std::size_t>( v >> 32 ) + ( seed << 6 ) + ( seed >> 2 );
seed ^= static_cast<std::size_t>( v >> M ) + ( seed << 6 ) + ( seed >> 2 );
seed ^= static_cast<std::size_t>( v ) + ( seed << 6 ) + ( seed >> 2 );
return seed;
}
};
template<class T> struct hash_integral_impl<T, true, 32, 128>
template<class T> struct hash_integral_impl<T, true, true, 4>
{
static std::size_t fn( T v )
{
enum {
M1 = sizeof(std::size_t) * CHAR_BIT,
M2 = M1 + M1,
M3 = M2 + M1
};
std::size_t seed = 0;
seed ^= static_cast<std::size_t>( v >> 96 ) + ( seed << 6 ) + ( seed >> 2 );
seed ^= static_cast<std::size_t>( v >> 64 ) + ( seed << 6 ) + ( seed >> 2 );
seed ^= static_cast<std::size_t>( v >> 32 ) + ( seed << 6 ) + ( seed >> 2 );
seed ^= static_cast<std::size_t>( v ) + ( seed << 6 ) + ( seed >> 2 );
return seed;
}
};
template<class T> struct hash_integral_impl<T, true, 64, 128>
{
static std::size_t fn( T v )
{
std::size_t seed = 0;
seed ^= static_cast<std::size_t>( v >> 64 ) + ( seed << 6 ) + ( seed >> 2 );
seed ^= static_cast<std::size_t>( v >> M3 ) + ( seed << 6 ) + ( seed >> 2 );
seed ^= static_cast<std::size_t>( v >> M2 ) + ( seed << 6 ) + ( seed >> 2 );
seed ^= static_cast<std::size_t>( v >> M1 ) + ( seed << 6 ) + ( seed >> 2 );
seed ^= static_cast<std::size_t>( v ) + ( seed << 6 ) + ( seed >> 2 );
return seed;
@@ -133,28 +146,12 @@ namespace boost
} // namespace hash_detail
template <typename T>
typename boost::enable_if_<boost::conjunction<boost::is_integral<T>, boost::is_unsigned<T> >::value, std::size_t>::type
typename boost::enable_if_<boost::is_integral<T>::value, std::size_t>::type
hash_value( T v )
{
return hash_detail::hash_integral_impl<T>::fn( v );
}
template <typename T>
typename boost::enable_if_<boost::conjunction<boost::is_integral<T>, boost::is_signed<T> >::value, std::size_t>::type
hash_value( T v )
{
typedef typename boost::make_unsigned<T>::type U;
if( v >= 0 )
{
return hash_value( static_cast<U>( v ) );
}
else
{
return ~hash_value( static_cast<U>( ~static_cast<U>( v ) ) );
}
}
// enumeration types
template <typename T>

View File

@@ -79,3 +79,5 @@ local fs-path-req = "-<toolset>gcc:<cxxflags>-Wshadow" "-<toolset>gcc:<cxxflags>
run hash_fs_path_test.cpp /boost//filesystem/<warnings>off : : : $(fs-path-req) <toolset>msvc-14.0,<cxxstd>latest:<build>no ;
run detail_is_range_test2.cpp : : : $(fs-path-req) ;
run hash_container_test.cpp ;

View File

@@ -29,6 +29,7 @@ int main() {}
// 'const std::complex<float>::_Ty'
#pragma warning(disable:4309) // truncation of constant value
#pragma warning(disable:4512) // assignment operator could not be generated
#pragma warning(disable:4996) // std::complex<Integer> is deprecated
#if BOOST_MSVC < 1400
#pragma warning(disable:4267) // conversion from 'size_t' to 'unsigned int',
// possible loss of data

View File

@@ -0,0 +1,52 @@
// Copyright 2022 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/container_hash/hash.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/config.hpp>
#include <vector>
#include <deque>
#include <list>
#if !defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)
# include <forward_list>
#endif
template<class T> std::size_t hv( T const& t )
{
return boost::hash<T>()( t );
}
template<class T> void test()
{
for( std::size_t i = 0; i < 8; ++i )
{
std::vector<T> v( i );
std::size_t h0 = hv( v );
std::deque<T> d( v.begin(), v.end() );
BOOST_TEST_EQ( h0, hv( d ) );
std::list<T> l( v.begin(), v.end() );
BOOST_TEST_EQ( h0, hv( l ) );
#if !defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)
std::forward_list<T> f( v.begin(), v.end() );
BOOST_TEST_EQ( h0, hv( f ) );
#endif
}
}
int main()
{
test<char>();
test<unsigned char>();
test<signed char>();
test<int>();
test<float>();
test<double>();
return boost::report_errors();
}

View File

@@ -2,6 +2,8 @@
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#define _SILENCE_NONFLOATING_COMPLEX_DEPRECATION_WARNING
#include <boost/config/pragma_message.hpp>
#if defined(__GNUC__) && !defined(__clang__) && __cplusplus < 201100L

View File

@@ -11,6 +11,12 @@
#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
#include <string_view>
#endif
#include <vector>
#include <deque>
#include <list>
#if !defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)
# include <forward_list>
#endif
// Test whether the hash values of a string and a
// string_view that refers to it match. This is
@@ -24,12 +30,21 @@ template<class T> std::size_t hv( T const& t )
int main()
{
std::string s( "Test." );
std::size_t h0 = hv( s );
BOOST_TEST_EQ( hv( s ), hv( boost::string_view( s ) ) );
BOOST_TEST_EQ( hv( s ), hv( boost::core::string_view( s ) ) );
BOOST_TEST_EQ( h0, hv( boost::string_view( s ) ) );
BOOST_TEST_EQ( h0, hv( boost::core::string_view( s ) ) );
#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
BOOST_TEST_EQ( hv( s ), hv( std::string_view( s ) ) );
BOOST_TEST_EQ( h0, hv( std::string_view( s ) ) );
#endif
BOOST_TEST_EQ( h0, hv( std::vector<char>( s.begin(), s.end() ) ) );
BOOST_TEST_EQ( h0, hv( std::deque<char>( s.begin(), s.end() ) ) );
BOOST_TEST_EQ( h0, hv( std::list<char>( s.begin(), s.end() ) ) );
#if !defined(BOOST_NO_CXX11_HDR_FORWARD_LIST)
BOOST_TEST_EQ( h0, hv( std::forward_list<char>( s.begin(), s.end() ) ) );
#endif
return boost::report_errors();