/*============================================================================= Copyright (c) 2011-2016 Bolero MURAKAMI https://github.com/bolero-MURAKAMI/Sprout Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ #ifndef SPROUT_FUNCTIONAL_HASH_HASH_VALUE_TRAITS_HPP #define SPROUT_FUNCTIONAL_HASH_HASH_VALUE_TRAITS_HPP #include #include #include #include #include #include #include #include #include #include namespace sprout { namespace hash_detail { template struct is_basic_number : public sprout::bool_constant< std::is_integral::value && (sizeof(T) <= sizeof(std::size_t)) > {}; template struct is_long_number : public sprout::bool_constant< std::is_integral::value && (sizeof(T) > sizeof(std::size_t)) && sprout::is_signed::value > {}; template struct is_ulong_number : public sprout::bool_constant< std::is_integral::value && (sizeof(T) > sizeof(std::size_t)) && sprout::is_unsigned::value > {}; template inline SPROUT_CONSTEXPR std::size_t hash_value_signed_2(T val, int length, std::size_t seed, T positive, std::size_t i) { return i > 0 ? hash_value_signed_2( val, length, seed ^ static_cast((positive >> i) + (seed << 6) + (seed >> 2)), positive, i - sprout::numeric_limits::digits ) : seed ^ static_cast(val + (seed << 6) + (seed >> 2)) ; } template inline SPROUT_CONSTEXPR std::size_t hash_value_signed_1(T val, int length, std::size_t seed, T positive) { return hash_value_signed_2(val, length, seed, positive, length * sprout::numeric_limits::digits); } template inline SPROUT_CONSTEXPR std::size_t hash_value_signed(T val) { return sprout::hash_detail::hash_value_signed_1( val, (sprout::numeric_limits::digits - 1) / sprout::numeric_limits::digits, 0, val < 0 ? -1 - val : val ); } template inline SPROUT_CONSTEXPR std::size_t hash_value_unsigned_2(T val, int length, std::size_t seed, std::size_t i) { return i > 0 ? hash_value_unsigned_2( val, length, seed ^ static_cast((val >> i) + (seed << 6) + (seed >> 2)), i - sprout::numeric_limits::digits ) : seed ^ static_cast(val + (seed << 6) + (seed >> 2)) ; } template inline SPROUT_CONSTEXPR std::size_t hash_value_unsigned_1(T val, int length, std::size_t seed) { return hash_value_unsigned_2(val, length, seed, length * sprout::numeric_limits::digits); } template inline SPROUT_CONSTEXPR std::size_t hash_value_unsigned(T val) { return sprout::hash_detail::hash_value_unsigned_1( val, (sprout::numeric_limits::digits - 1) / sprout::numeric_limits::digits, 0 ); } inline std::size_t hash_value_pointer_1(std::size_t x) { return x + (x >> 3); } template std::size_t hash_value_pointer(T const* v) { return sprout::hash_detail::hash_value_pointer_1(static_cast(reinterpret_cast(v))); } template inline SPROUT_CONSTEXPR typename std::enable_if::value, std::size_t>::type hash_value_impl(T v) { return static_cast(v); } template inline SPROUT_CONSTEXPR typename std::enable_if::value, std::size_t>::type hash_value_impl(T v) { return sprout::hash_detail::hash_value_signed(v); } template inline SPROUT_CONSTEXPR typename std::enable_if::value, std::size_t>::type hash_value_impl(T v) { return sprout::hash_detail::hash_value_unsigned(v); } template inline SPROUT_CONSTEXPR typename std::enable_if::value, std::size_t>::type hash_value_impl(T v) { return sprout::hash_detail::hash_value_impl(static_cast::type>(v)); } template inline SPROUT_CONSTEXPR typename std::enable_if::value, std::size_t>::type hash_value_impl(T v) { return sprout::detail::float_hash_value(v); } template inline SPROUT_CONSTEXPR typename std::enable_if::type>::value, std::size_t>::type hash_value_impl(T&& v) { return sprout::hash_detail::hash_value_pointer(v); } template inline SPROUT_CONSTEXPR std::size_t hash_value_impl(T const (& v)[N]) { return sprout::hash_range(v); } template inline SPROUT_CONSTEXPR typename std::enable_if< !std::is_arithmetic::value && !std::is_enum::value && !std::is_pointer::value, std::size_t >::type hash_value_impl(T const& v) { return std::hash::type>()(v); } } // namespace hash_detail // // hash_value_traits // template struct hash_value_traits { public: static SPROUT_CONSTEXPR std::size_t hash_value(T const& v) { return sprout::hash_detail::hash_value_impl(v); } }; template struct hash_value_traits : public sprout::hash_value_traits {}; template struct hash_value_traits : public sprout::hash_value_traits {}; template struct hash_value_traits : public sprout::hash_value_traits {}; } // namespace sprout #include #endif // #ifndef SPROUT_FUNCTIONAL_HASH_HASH_VALUE_TRAITS_HPP