Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:30:23

0001 // Copyright 2021-2023 Peter Dimov
0002 // Distributed under the Boost Software License, Version 1.0.
0003 // https://www.boost.org/LICENSE_1_0.txt
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 // libstdc++ doesn't provide support for __int128 in the standard traits
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 } // namespace hash_detail
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 } // namespace boost
0145 
0146 #endif // #ifndef BOOST_HASH_DETAIL_HASH_INTEGRAL_HPP