#ifndef SPROUT_FUNCTIONAL_HASH_HASH_HPP #define SPROUT_FUNCTIONAL_HASH_HASH_HPP #include #include #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); } // // to_hash // template inline SPROUT_CONSTEXPR std::size_t to_hash(T const& v) { using sprout::hash_value; return hash_value(v); } // // hash_combine // template inline SPROUT_CONSTEXPR std::size_t hash_combine(std::size_t seed, T const& v) { return seed ^ (sprout::to_hash(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2)); } // // hash_range // template inline SPROUT_CONSTEXPR std::size_t hash_range(std::size_t seed, Iterator first, Iterator last) { return first != last ? sprout::hash_range(sprout::hash_combine(seed, *first), sprout::next(first), last) : seed ; } template inline SPROUT_CONSTEXPR std::size_t hash_range(Iterator first, Iterator last) { return sprout::hash_range(0, first, last); } namespace detail { template inline SPROUT_CONSTEXPR std::size_t hash_values_combine_impl(std::size_t seed, T const& v) { return sprout::hash_combine(seed, v); } template inline SPROUT_CONSTEXPR std::size_t hash_values_combine_impl(std::size_t seed, Head const& head, Tail const&... tail) { return sprout::detail::hash_values_combine_impl(sprout::hash_combine(seed, head), tail...); } } // namespace detail // // hash_values_combine // template inline SPROUT_CONSTEXPR std::size_t hash_values_combine(std::size_t seed, Args const&... args) { return sprout::detail::hash_values_combine_impl(seed, args...); } // // hash_values // template inline SPROUT_CONSTEXPR std::size_t hash_values(Args const&... args) { return sprout::hash_values_combine(0, args...); } // // hash // template struct hash { public: typedef T argument_type; typedef std::size_t result_type; public: SPROUT_CONSTEXPR std::size_t operator()(T const& v) const { return sprout::to_hash(v); } }; template struct hash : public sprout::hash {}; template struct hash : public sprout::hash {}; template struct hash : public sprout::hash {}; #define SPROUT_HASH_SPECIALIZE(type) \ template<> \ struct hash { \ public: \ typedef type argument_type; \ typedef std::size_t result_type; \ public: \ SPROUT_CONSTEXPR std::size_t operator()(type v) const { \ return sprout::to_hash(v); \ } \ } #define SPROUT_HASH_SPECIALIZE_REF(type) \ template<> \ struct hash { \ public: \ typedef type argument_type; \ typedef std::size_t result_type; \ public: \ SPROUT_CONSTEXPR std::size_t operator()(type const& v) const { \ return sprout::to_hash(v); \ } \ } SPROUT_HASH_SPECIALIZE(bool); SPROUT_HASH_SPECIALIZE(char); SPROUT_HASH_SPECIALIZE(signed char); SPROUT_HASH_SPECIALIZE(unsigned char); SPROUT_HASH_SPECIALIZE(char16_t); SPROUT_HASH_SPECIALIZE(char32_t); SPROUT_HASH_SPECIALIZE(wchar_t); SPROUT_HASH_SPECIALIZE(short); SPROUT_HASH_SPECIALIZE(unsigned short); SPROUT_HASH_SPECIALIZE(int); SPROUT_HASH_SPECIALIZE(unsigned int); SPROUT_HASH_SPECIALIZE(long); SPROUT_HASH_SPECIALIZE(unsigned long); SPROUT_HASH_SPECIALIZE(long long); SPROUT_HASH_SPECIALIZE(unsigned long long); #undef SPROUT_HASH_SPECIALIZE #undef SPROUT_HASH_SPECIALIZE_REF template struct hash { public: typedef T* argument_type; typedef std::size_t result_type; public: std::size_t operator()(T* v) const { return sprout::to_hash(v); } }; } // namespace sprout #endif // #ifndef SPROUT_FUNCTIONAL_HASH_HASH_HPP