File indexing completed on 2025-01-18 09:30:23
0001
0002
0003
0004
0005 #ifndef BOOST_HASH_DETAIL_HASH_INTEGRAL_HPP
0006 #define BOOST_HASH_DETAIL_HASH_INTEGRAL_HPP
0007
0008 #include <boost/container_hash/detail/hash_mix.hpp>
0009 #include <type_traits>
0010 #include <cstddef>
0011 #include <climits>
0012
0013 namespace boost
0014 {
0015 namespace hash_detail
0016 {
0017
0018
0019
0020 template<class T> struct is_integral: public std::is_integral<T>
0021 {
0022 };
0023
0024 template<class T> struct is_unsigned: public std::is_unsigned<T>
0025 {
0026 };
0027
0028 template<class T> struct make_unsigned: public std::make_unsigned<T>
0029 {
0030 };
0031
0032 #if defined(__SIZEOF_INT128__)
0033
0034 template<> struct is_integral<__int128_t>: public std::true_type
0035 {
0036 };
0037
0038 template<> struct is_integral<__uint128_t>: public std::true_type
0039 {
0040 };
0041
0042 template<> struct is_unsigned<__int128_t>: public std::false_type
0043 {
0044 };
0045
0046 template<> struct is_unsigned<__uint128_t>: public std::true_type
0047 {
0048 };
0049
0050 template<> struct make_unsigned<__int128_t>
0051 {
0052 typedef __uint128_t type;
0053 };
0054
0055 template<> struct make_unsigned<__uint128_t>
0056 {
0057 typedef __uint128_t type;
0058 };
0059
0060 #endif
0061
0062 template<class T,
0063 bool bigger_than_size_t = (sizeof(T) > sizeof(std::size_t)),
0064 bool is_unsigned = is_unsigned<T>::value,
0065 std::size_t size_t_bits = sizeof(std::size_t) * CHAR_BIT,
0066 std::size_t type_bits = sizeof(T) * CHAR_BIT>
0067 struct hash_integral_impl;
0068
0069 template<class T, bool is_unsigned, std::size_t size_t_bits, std::size_t type_bits> struct hash_integral_impl<T, false, is_unsigned, size_t_bits, type_bits>
0070 {
0071 static std::size_t fn( T v )
0072 {
0073 return static_cast<std::size_t>( v );
0074 }
0075 };
0076
0077 template<class T, std::size_t size_t_bits, std::size_t type_bits> struct hash_integral_impl<T, true, false, size_t_bits, type_bits>
0078 {
0079 static std::size_t fn( T v )
0080 {
0081 typedef typename make_unsigned<T>::type U;
0082
0083 if( v >= 0 )
0084 {
0085 return hash_integral_impl<U>::fn( static_cast<U>( v ) );
0086 }
0087 else
0088 {
0089 return ~hash_integral_impl<U>::fn( static_cast<U>( ~static_cast<U>( v ) ) );
0090 }
0091 }
0092 };
0093
0094 template<class T> struct hash_integral_impl<T, true, true, 32, 64>
0095 {
0096 static std::size_t fn( T v )
0097 {
0098 std::size_t seed = 0;
0099
0100 seed = static_cast<std::size_t>( v >> 32 ) + hash_detail::hash_mix( seed );
0101 seed = static_cast<std::size_t>( v & 0xFFFFFFFF ) + hash_detail::hash_mix( seed );
0102
0103 return seed;
0104 }
0105 };
0106
0107 template<class T> struct hash_integral_impl<T, true, true, 32, 128>
0108 {
0109 static std::size_t fn( T v )
0110 {
0111 std::size_t seed = 0;
0112
0113 seed = static_cast<std::size_t>( v >> 96 ) + hash_detail::hash_mix( seed );
0114 seed = static_cast<std::size_t>( v >> 64 ) + hash_detail::hash_mix( seed );
0115 seed = static_cast<std::size_t>( v >> 32 ) + hash_detail::hash_mix( seed );
0116 seed = static_cast<std::size_t>( v ) + hash_detail::hash_mix( seed );
0117
0118 return seed;
0119 }
0120 };
0121
0122 template<class T> struct hash_integral_impl<T, true, true, 64, 128>
0123 {
0124 static std::size_t fn( T v )
0125 {
0126 std::size_t seed = 0;
0127
0128 seed = static_cast<std::size_t>( v >> 64 ) + hash_detail::hash_mix( seed );
0129 seed = static_cast<std::size_t>( v ) + hash_detail::hash_mix( seed );
0130
0131 return seed;
0132 }
0133 };
0134
0135 }
0136
0137 template <typename T>
0138 typename std::enable_if<hash_detail::is_integral<T>::value, std::size_t>::type
0139 hash_value( T v )
0140 {
0141 return hash_detail::hash_integral_impl<T>::fn( v );
0142 }
0143
0144 }
0145
0146 #endif