#ifndef BOOST_HASH2_GET_INTEGRAL_RESULT_HPP_INCLUDED #define BOOST_HASH2_GET_INTEGRAL_RESULT_HPP_INCLUDED // Copyright 2017, 2018 Peter Dimov. // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt #include #include #include #include namespace boost { namespace hash2 { namespace detail { // contraction // 2 -> 1, 4 -> x template constexpr typename std::enable_if::type get_result_multiplier() { return 0xBF3D6763u; } // 8 -> x template constexpr typename std::enable_if::type get_result_multiplier() { return 0x99EBE72FE70129CBull; } } // namespace detail // contraction template typename std::enable_if::value && (sizeof(R) > sizeof(T)), T>::type get_integral_result( Hash& h ) { static_assert( std::is_integral::value, "T must be integral" ); static_assert( !std::is_same::type, bool>::value, "T must not be bool" ); static_assert( std::is_unsigned::value, "Hash::result_type must be unsigned" ); typedef typename std::make_unsigned::type U; constexpr auto m = detail::get_result_multiplier(); auto r = h.result(); return static_cast( static_cast( ( r * m ) >> ( std::numeric_limits::digits - std::numeric_limits::digits ) ) ); } // identity template typename std::enable_if::value && sizeof(R) == sizeof(T), T>::type get_integral_result( Hash& h ) { static_assert( std::is_integral::value, "T must be integral" ); static_assert( !std::is_same::type, bool>::value, "T must not be bool" ); static_assert( std::is_unsigned::value, "Hash::result_type must be unsigned" ); typedef typename std::make_unsigned::type U; auto r = h.result(); return static_cast( static_cast( r ) ); } // expansion template typename std::enable_if::value && (sizeof(R) < sizeof(T)), T>::type get_integral_result( Hash& h ) { static_assert( std::is_integral::value, "T must be integral" ); static_assert( !std::is_same::type, bool>::value, "T must not be bool" ); static_assert( std::is_unsigned::value, "Hash::result_type must be unsigned" ); typedef typename std::make_unsigned::type U; constexpr auto rd = std::numeric_limits::digits; constexpr auto ud = std::numeric_limits::digits; U u = 0; for( int i = 0; i < ud; i += rd ) { auto r = h.result(); u += static_cast( r ) << i; } return static_cast( u ); } // array-like R template typename std::enable_if< !std::is_integral::value, T >::type get_integral_result( Hash& h ) { static_assert( std::is_integral::value, "T must be integral" ); static_assert( !std::is_same::type, bool>::value, "T must not be bool" ); static_assert( R().size() >= 8, "Array-like result type is too short" ); auto r = h.result(); return static_cast( detail::read64le( r.data() ) ); } } // namespace hash2 } // namespace boost #endif // #ifndef BOOST_HASH2_GET_INTEGRAL_RESULT_HPP_INCLUDED