File indexing completed on 2025-09-17 08:33:43
0001 #ifndef BOOST_HASH2_GET_INTEGRAL_RESULT_HPP_INCLUDED
0002 #define BOOST_HASH2_GET_INTEGRAL_RESULT_HPP_INCLUDED
0003
0004
0005
0006
0007
0008 #include <boost/hash2/detail/read.hpp>
0009 #include <type_traits>
0010 #include <limits>
0011 #include <cstddef>
0012
0013 namespace boost
0014 {
0015 namespace hash2
0016 {
0017
0018 namespace detail
0019 {
0020
0021
0022
0023
0024 template<class R>
0025 constexpr typename std::enable_if<sizeof(R) <= 4, std::uint32_t>::type
0026 get_result_multiplier()
0027 {
0028 return 0xBF3D6763u;
0029 }
0030
0031
0032 template<class R>
0033 constexpr typename std::enable_if<sizeof(R) == 8, std::uint64_t>::type
0034 get_result_multiplier()
0035 {
0036 return 0x99EBE72FE70129CBull;
0037 }
0038
0039 }
0040
0041
0042
0043 template<class T, class Hash, class R = typename Hash::result_type>
0044 typename std::enable_if<std::is_integral<R>::value && (sizeof(R) > sizeof(T)), T>::type
0045 get_integral_result( Hash& h )
0046 {
0047 static_assert( std::is_integral<T>::value, "T must be integral" );
0048 static_assert( !std::is_same<typename std::remove_cv<T>::type, bool>::value, "T must not be bool" );
0049
0050 static_assert( std::is_unsigned<R>::value, "Hash::result_type must be unsigned" );
0051
0052 typedef typename std::make_unsigned<T>::type U;
0053
0054 constexpr auto m = detail::get_result_multiplier<R>();
0055
0056 auto r = h.result();
0057 return static_cast<T>( static_cast<U>( ( r * m ) >> ( std::numeric_limits<R>::digits - std::numeric_limits<U>::digits ) ) );
0058 }
0059
0060
0061
0062 template<class T, class Hash, class R = typename Hash::result_type>
0063 typename std::enable_if<std::is_integral<R>::value && sizeof(R) == sizeof(T), T>::type
0064 get_integral_result( Hash& h )
0065 {
0066 static_assert( std::is_integral<T>::value, "T must be integral" );
0067 static_assert( !std::is_same<typename std::remove_cv<T>::type, bool>::value, "T must not be bool" );
0068
0069 static_assert( std::is_unsigned<R>::value, "Hash::result_type must be unsigned" );
0070
0071 typedef typename std::make_unsigned<T>::type U;
0072
0073 auto r = h.result();
0074 return static_cast<T>( static_cast<U>( r ) );
0075 }
0076
0077
0078
0079 template<class T, class Hash, class R = typename Hash::result_type>
0080 typename std::enable_if<std::is_integral<R>::value && (sizeof(R) < sizeof(T)), T>::type
0081 get_integral_result( Hash& h )
0082 {
0083 static_assert( std::is_integral<T>::value, "T must be integral" );
0084 static_assert( !std::is_same<typename std::remove_cv<T>::type, bool>::value, "T must not be bool" );
0085
0086 static_assert( std::is_unsigned<R>::value, "Hash::result_type must be unsigned" );
0087
0088 typedef typename std::make_unsigned<T>::type U;
0089
0090 constexpr auto rd = std::numeric_limits<R>::digits;
0091 constexpr auto ud = std::numeric_limits<U>::digits;
0092
0093 U u = 0;
0094
0095 for( int i = 0; i < ud; i += rd )
0096 {
0097 auto r = h.result();
0098 u += static_cast<U>( r ) << i;
0099 }
0100
0101 return static_cast<T>( u );
0102 }
0103
0104
0105
0106 template<class T, class Hash, class R = typename Hash::result_type>
0107 typename std::enable_if< !std::is_integral<R>::value, T >::type
0108 get_integral_result( Hash& h )
0109 {
0110 static_assert( std::is_integral<T>::value, "T must be integral" );
0111 static_assert( !std::is_same<typename std::remove_cv<T>::type, bool>::value, "T must not be bool" );
0112
0113 static_assert( R().size() >= 8, "Array-like result type is too short" );
0114
0115 auto r = h.result();
0116 return static_cast<T>( detail::read64le( r.data() ) );
0117 }
0118
0119 }
0120 }
0121
0122 #endif