/src/boost/boost/container_hash/detail/hash_integral.hpp
Line | Count | Source |
1 | | // Copyright 2021-2023 Peter Dimov |
2 | | // Distributed under the Boost Software License, Version 1.0. |
3 | | // https://www.boost.org/LICENSE_1_0.txt |
4 | | |
5 | | #ifndef BOOST_HASH_DETAIL_HASH_INTEGRAL_HPP |
6 | | #define BOOST_HASH_DETAIL_HASH_INTEGRAL_HPP |
7 | | |
8 | | #include <boost/container_hash/detail/hash_mix.hpp> |
9 | | #include <type_traits> |
10 | | #include <cstddef> |
11 | | #include <climits> |
12 | | |
13 | | namespace boost |
14 | | { |
15 | | namespace hash_detail |
16 | | { |
17 | | |
18 | | // libstdc++ doesn't provide support for __int128 in the standard traits |
19 | | |
20 | | template<class T> struct is_integral: public std::is_integral<T> |
21 | | { |
22 | | }; |
23 | | |
24 | | template<class T> struct is_unsigned: public std::is_unsigned<T> |
25 | | { |
26 | | }; |
27 | | |
28 | | template<class T> struct make_unsigned: public std::make_unsigned<T> |
29 | | { |
30 | | }; |
31 | | |
32 | | #if defined(__SIZEOF_INT128__) |
33 | | |
34 | | template<> struct is_integral<__int128_t>: public std::true_type |
35 | | { |
36 | | }; |
37 | | |
38 | | template<> struct is_integral<__uint128_t>: public std::true_type |
39 | | { |
40 | | }; |
41 | | |
42 | | template<> struct is_unsigned<__int128_t>: public std::false_type |
43 | | { |
44 | | }; |
45 | | |
46 | | template<> struct is_unsigned<__uint128_t>: public std::true_type |
47 | | { |
48 | | }; |
49 | | |
50 | | template<> struct make_unsigned<__int128_t> |
51 | | { |
52 | | typedef __uint128_t type; |
53 | | }; |
54 | | |
55 | | template<> struct make_unsigned<__uint128_t> |
56 | | { |
57 | | typedef __uint128_t type; |
58 | | }; |
59 | | |
60 | | #endif |
61 | | |
62 | | template<class T, |
63 | | bool bigger_than_size_t = (sizeof(T) > sizeof(std::size_t)), |
64 | | bool is_unsigned = is_unsigned<T>::value, |
65 | | std::size_t size_t_bits = sizeof(std::size_t) * CHAR_BIT, |
66 | | std::size_t type_bits = sizeof(T) * CHAR_BIT> |
67 | | struct hash_integral_impl; |
68 | | |
69 | | 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> |
70 | | { |
71 | | static std::size_t fn( T v ) |
72 | 0 | { |
73 | 0 | return static_cast<std::size_t>( v ); |
74 | 0 | } Unexecuted instantiation: boost::hash_detail::hash_integral_impl<bool, false, true, 64ul, 8ul>::fn(bool) Unexecuted instantiation: boost::hash_detail::hash_integral_impl<long, false, false, 64ul, 64ul>::fn(long) Unexecuted instantiation: boost::hash_detail::hash_integral_impl<unsigned long, false, true, 64ul, 64ul>::fn(unsigned long) Unexecuted instantiation: boost::hash_detail::hash_integral_impl<int, false, false, 64ul, 32ul>::fn(int) |
75 | | }; |
76 | | |
77 | | 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> |
78 | | { |
79 | | static std::size_t fn( T v ) |
80 | | { |
81 | | typedef typename make_unsigned<T>::type U; |
82 | | |
83 | | if( v >= 0 ) |
84 | | { |
85 | | return hash_integral_impl<U>::fn( static_cast<U>( v ) ); |
86 | | } |
87 | | else |
88 | | { |
89 | | return ~hash_integral_impl<U>::fn( static_cast<U>( ~static_cast<U>( v ) ) ); |
90 | | } |
91 | | } |
92 | | }; |
93 | | |
94 | | template<class T> struct hash_integral_impl<T, true, true, 32, 64> |
95 | | { |
96 | | static std::size_t fn( T v ) |
97 | | { |
98 | | std::size_t seed = 0; |
99 | | |
100 | | seed = static_cast<std::size_t>( v >> 32 ) + hash_detail::hash_mix( seed ); |
101 | | seed = static_cast<std::size_t>( v & 0xFFFFFFFF ) + hash_detail::hash_mix( seed ); |
102 | | |
103 | | return seed; |
104 | | } |
105 | | }; |
106 | | |
107 | | template<class T> struct hash_integral_impl<T, true, true, 32, 128> |
108 | | { |
109 | | static std::size_t fn( T v ) |
110 | | { |
111 | | std::size_t seed = 0; |
112 | | |
113 | | seed = static_cast<std::size_t>( v >> 96 ) + hash_detail::hash_mix( seed ); |
114 | | seed = static_cast<std::size_t>( v >> 64 ) + hash_detail::hash_mix( seed ); |
115 | | seed = static_cast<std::size_t>( v >> 32 ) + hash_detail::hash_mix( seed ); |
116 | | seed = static_cast<std::size_t>( v ) + hash_detail::hash_mix( seed ); |
117 | | |
118 | | return seed; |
119 | | } |
120 | | }; |
121 | | |
122 | | template<class T> struct hash_integral_impl<T, true, true, 64, 128> |
123 | | { |
124 | | static std::size_t fn( T v ) |
125 | | { |
126 | | std::size_t seed = 0; |
127 | | |
128 | | seed = static_cast<std::size_t>( v >> 64 ) + hash_detail::hash_mix( seed ); |
129 | | seed = static_cast<std::size_t>( v ) + hash_detail::hash_mix( seed ); |
130 | | |
131 | | return seed; |
132 | | } |
133 | | }; |
134 | | |
135 | | } // namespace hash_detail |
136 | | |
137 | | template <typename T> |
138 | | typename std::enable_if<hash_detail::is_integral<T>::value, std::size_t>::type |
139 | | hash_value( T v ) |
140 | 0 | { |
141 | 0 | return hash_detail::hash_integral_impl<T>::fn( v ); |
142 | 0 | } Unexecuted instantiation: _ZN5boost10hash_valueIbEENSt3__19enable_ifIXsr11hash_detail11is_integralIT_EE5valueEmE4typeES3_ Unexecuted instantiation: _ZN5boost10hash_valueIlEENSt3__19enable_ifIXsr11hash_detail11is_integralIT_EE5valueEmE4typeES3_ Unexecuted instantiation: _ZN5boost10hash_valueImEENSt3__19enable_ifIXsr11hash_detail11is_integralIT_EE5valueEmE4typeES3_ Unexecuted instantiation: _ZN5boost10hash_valueIiEENSt3__19enable_ifIXsr11hash_detail11is_integralIT_EE5valueEmE4typeES3_ |
143 | | |
144 | | } // namespace boost |
145 | | |
146 | | #endif // #ifndef BOOST_HASH_DETAIL_HASH_INTEGRAL_HPP |