#ifndef SPROUT_FUNCTIONAL_HASH_HASH_VALUE_HPP #define SPROUT_FUNCTIONAL_HASH_HASH_VALUE_HPP #include #include #include #include #include namespace sprout { namespace hash_detail { template struct is_basic_number : public std::integral_constant< bool, std::is_integral::value && (sizeof(T) <= sizeof(std::size_t)) > {}; template struct is_long_number : public std::integral_constant< bool, std::is_integral::value && (sizeof(T) > sizeof(std::size_t)) && std::is_signed::value > {}; template struct is_ulong_number : public std::integral_constant< bool, std::is_integral::value && (sizeof(T) > sizeof(std::size_t)) && std::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 - std::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 * std::numeric_limits::digits); } template inline SPROUT_CONSTEXPR std::size_t hash_value_signed(T val) { return sprout::hash_detail::hash_value_signed_1( val, (std::numeric_limits::digits - 1) / std::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 - std::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 * std::numeric_limits::digits); } template inline SPROUT_CONSTEXPR std::size_t hash_value_unsigned(T val) { return sprout::hash_detail::hash_value_unsigned_1( val, (std::numeric_limits::digits - 1) / std::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))); } } // namespace hash_detail // // hash_value // template inline SPROUT_CONSTEXPR typename std::enable_if::value, std::size_t>::type hash_value(T v) { return static_cast(v); } template inline SPROUT_CONSTEXPR typename std::enable_if::value, std::size_t>::type hash_value(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(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(T v) { return sprout::hash_value(static_cast::type>(v)); } template inline SPROUT_CONSTEXPR typename std::enable_if::type>::value, std::size_t>::type hash_value(T&& v) { return sprout::hash_detail::hash_value_pointer(v); } template inline SPROUT_CONSTEXPR std::size_t hash_value(T const (&v)[N]) { return sprout::hash_range(&v[0], &v[0] + N); } } // namespace sprout #endif // #ifndef SPROUT_FUNCTIONAL_HASH_HASH_VALUE_HPP