diff --git a/sprout/array/hash.hpp b/sprout/array/hash.hpp index a0c2ff53..03bb3fd7 100644 --- a/sprout/array/hash.hpp +++ b/sprout/array/hash.hpp @@ -3,8 +3,8 @@ #include #include -#include #include +#include namespace sprout { // diff --git a/sprout/complex/hash.hpp b/sprout/complex/hash.hpp index dd93a7a4..dcfc4f89 100644 --- a/sprout/complex/hash.hpp +++ b/sprout/complex/hash.hpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include namespace sprout { // diff --git a/sprout/functional/hash.hpp b/sprout/functional/hash.hpp index f7f3c8c3..2d6de228 100644 --- a/sprout/functional/hash.hpp +++ b/sprout/functional/hash.hpp @@ -2,6 +2,13 @@ #define SPROUT_FUNCTIONAL_HASH_HPP #include +#include +#include +#include #include +#include +#include +#include +#include #endif // #ifndef SPROUT_FUNCTIONAL_HASH_HPP diff --git a/sprout/functional/hash/hash.hpp b/sprout/functional/hash/hash.hpp index 29e00293..e8d27df4 100644 --- a/sprout/functional/hash/hash.hpp +++ b/sprout/functional/hash/hash.hpp @@ -2,212 +2,11 @@ #define SPROUT_FUNCTIONAL_HASH_HASH_HPP #include -#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 // diff --git a/sprout/functional/hash/hash_combine.hpp b/sprout/functional/hash/hash_combine.hpp new file mode 100644 index 00000000..0cd8f1f4 --- /dev/null +++ b/sprout/functional/hash/hash_combine.hpp @@ -0,0 +1,20 @@ +#ifndef SPROUT_FUNCTIONAL_HASH_HASH_COMBINE_HPP +#define SPROUT_FUNCTIONAL_HASH_HASH_COMBINE_HPP + +#include +#include +#include +#include + +namespace sprout { + // + // 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)); + } +} // namespace sprout + +#endif // #ifndef SPROUT_FUNCTIONAL_HASH_HASH_COMBINE_HPP diff --git a/sprout/functional/hash/hash_range.hpp b/sprout/functional/hash/hash_range.hpp new file mode 100644 index 00000000..6048d1db --- /dev/null +++ b/sprout/functional/hash/hash_range.hpp @@ -0,0 +1,29 @@ +#ifndef SPROUT_FUNCTIONAL_HASH_HASH_RANGE_HPP +#define SPROUT_FUNCTIONAL_HASH_HASH_RANGE_HPP + +#include +#include +#include +#include +#include + +namespace sprout { + // + // hash_range + // + template + inline SPROUT_CONSTEXPR std::size_t + hash_range(std::size_t seed, InputIterator first, InputIterator 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(InputIterator first, InputIterator last) { + return sprout::hash_range(0, first, last); + } +} // namespace sprout + +#endif // #ifndef SPROUT_FUNCTIONAL_HASH_HASH_RANGE_HPP diff --git a/sprout/functional/hash/hash_value.hpp b/sprout/functional/hash/hash_value.hpp new file mode 100644 index 00000000..67d3efda --- /dev/null +++ b/sprout/functional/hash/hash_value.hpp @@ -0,0 +1,143 @@ +#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 diff --git a/sprout/functional/hash/hash_values.hpp b/sprout/functional/hash/hash_values.hpp new file mode 100644 index 00000000..81bcf1cc --- /dev/null +++ b/sprout/functional/hash/hash_values.hpp @@ -0,0 +1,20 @@ +#ifndef SPROUT_FUNCTIONAL_HASH_HASH_VALUES_HPP +#define SPROUT_FUNCTIONAL_HASH_HASH_VALUES_HPP + +#include +#include +#include +#include + +namespace sprout { + // + // hash_values + // + template + inline SPROUT_CONSTEXPR std::size_t + hash_values(Args const&... args) { + return sprout::hash_values_combine(0, args...); + } +} // namespace sprout + +#endif // #ifndef SPROUT_FUNCTIONAL_HASH_HASH_VALUES_HPP diff --git a/sprout/functional/hash/hash_values_combine.hpp b/sprout/functional/hash/hash_values_combine.hpp new file mode 100644 index 00000000..5c6d1c11 --- /dev/null +++ b/sprout/functional/hash/hash_values_combine.hpp @@ -0,0 +1,33 @@ +#ifndef SPROUT_FUNCTIONAL_HASH_HASH_VALUES_COMBINE_HPP +#define SPROUT_FUNCTIONAL_HASH_HASH_VALUES_COMBINE_HPP + +#include +#include +#include +#include + +namespace sprout { + 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...); + } +} // namespace sprout + +#endif // #ifndef SPROUT_FUNCTIONAL_HASH_HASH_VALUES_COMBINE_HPP diff --git a/sprout/functional/hash/sscrisk/cel/utility.hpp b/sprout/functional/hash/sscrisk/cel/utility.hpp index 8b39d424..9faa8ea6 100644 --- a/sprout/functional/hash/sscrisk/cel/utility.hpp +++ b/sprout/functional/hash/sscrisk/cel/utility.hpp @@ -13,7 +13,7 @@ namespace sprout { template inline SPROUT_CONSTEXPR std::size_t hash_value(sscrisk::cel::pair const& v) { - return sprout::hash_combine(sprout::hash_combine(0, v.first), v.second); + return sprout::hash_values(v.first, v.second); } } // namespace sprout diff --git a/sprout/functional/hash/to_hash.hpp b/sprout/functional/hash/to_hash.hpp new file mode 100644 index 00000000..c9a6fc84 --- /dev/null +++ b/sprout/functional/hash/to_hash.hpp @@ -0,0 +1,145 @@ +#ifndef SPROUT_FUNCTIONAL_HASH_TO_HASH_HPP +#define SPROUT_FUNCTIONAL_HASH_TO_HASH_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sprout_adl { + sprout::not_found_via_adl hash_value(...); +} // namespace sprout_adl + +namespace sprout_hash_detail { + using sprout::hash_value; + using sprout_adl::hash_value; + + template + struct has_adl_hash_value_test { + public: + template< + typename U = T, + typename sprout::enabler_if< + sprout::is_found_via_adl()))>::value + >::type = sprout::enabler + > + static std::true_type test(int); + static std::false_type test(...); + }; +#if defined(_MSC_VER) + template::test(0))> + struct has_adl_hash_value + : public Base_ + {}; +#else + template + struct has_adl_hash_value + : public decltype(sprout_hash_detail::has_adl_hash_value_test::test(0)) + {}; +#endif + + template + struct select_adl_hash_value; + template + struct select_adl_hash_value< + T, + typename std::enable_if< + sprout_hash_detail::has_adl_hash_value::value + >::type + > + : public std::true_type + {}; + template + struct select_adl_hash_value< + T, + typename std::enable_if::value + )>::type + > + : public std::false_type + {}; + + template + struct select_std_hash; + template + struct select_std_hash< + T, + typename std::enable_if< + !sprout_hash_detail::has_adl_hash_value::value + >::type + > + : public std::true_type + {}; + template + struct select_std_hash< + T, + typename std::enable_if::value + )>::type + > + : public std::false_type + {}; + + template + struct noexcept_to_hash; + template + struct noexcept_to_hash::value>::type> + : public std::integral_constant()), false)> + {}; + template + struct noexcept_to_hash::value>::type> + : public std::integral_constant::type>()(std::declval()), false)> + {}; + + template + struct to_hash_result; + template + struct to_hash_result::value>::type> { + public: + typedef decltype(hash_value(std::declval())) type; + }; + template + struct to_hash_result::value>::type> { + public: + typedef decltype(std::hash::type>()(std::declval())) type; + }; + + template< + typename T, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR typename sprout_hash_detail::to_hash_result::type + to_hash_impl(T&& t) + SPROUT_NOEXCEPT_EXPR((sprout_hash_detail::noexcept_to_hash::value)) + { + return hash_value(sprout::forward(t)); + } + template< + typename T, + typename sprout::enabler_if::value>::type = sprout::enabler + > + inline SPROUT_CONSTEXPR typename sprout_hash_detail::to_hash_result::type + to_hash_impl(T&& t) + SPROUT_NOEXCEPT_EXPR((sprout_hash_detail::noexcept_to_hash::value)) + { + return std::hash::type>()(sprout::forward(t)); + } +} // namespace sprout_hash_detail + +namespace sprout { + // + // to_hash + // + template + inline SPROUT_CONSTEXPR std::size_t + to_hash(T const& v) { + return sprout_hash_detail::to_hash_impl(v); + } +} // namespace sprout + +#endif // #ifndef SPROUT_FUNCTIONAL_HASH_TO_HASH_HPP diff --git a/sprout/logic/tribool/hash.hpp b/sprout/logic/tribool/hash.hpp index 74635deb..66119f8a 100644 --- a/sprout/logic/tribool/hash.hpp +++ b/sprout/logic/tribool/hash.hpp @@ -3,8 +3,8 @@ #include #include -#include #include +#include namespace sprout { // diff --git a/sprout/optional/hash.hpp b/sprout/optional/hash.hpp index 37bf9cbd..d20a8313 100644 --- a/sprout/optional/hash.hpp +++ b/sprout/optional/hash.hpp @@ -3,8 +3,8 @@ #include #include -#include #include +#include namespace sprout { // diff --git a/sprout/pit/hash.hpp b/sprout/pit/hash.hpp index 426bacc4..5963844e 100644 --- a/sprout/pit/hash.hpp +++ b/sprout/pit/hash.hpp @@ -3,8 +3,8 @@ #include #include -#include #include +#include namespace sprout { // diff --git a/sprout/rational/hash.hpp b/sprout/rational/hash.hpp index 6864917a..e9368f32 100644 --- a/sprout/rational/hash.hpp +++ b/sprout/rational/hash.hpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include namespace sprout { // diff --git a/sprout/string/hash.hpp b/sprout/string/hash.hpp index b0ee5354..9c1eb753 100644 --- a/sprout/string/hash.hpp +++ b/sprout/string/hash.hpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include namespace sprout { // diff --git a/sprout/sub_array/hash.hpp b/sprout/sub_array/hash.hpp index d56b9cf6..4cd656bf 100644 --- a/sprout/sub_array/hash.hpp +++ b/sprout/sub_array/hash.hpp @@ -2,8 +2,8 @@ #define SPROUT_SUB_ARRAY_HASH_HPP #include -#include #include +#include namespace sprout { // diff --git a/sprout/tuple/tuple/hash.hpp b/sprout/tuple/tuple/hash.hpp index 3f2a83cd..39bb9bd2 100644 --- a/sprout/tuple/tuple/hash.hpp +++ b/sprout/tuple/tuple/hash.hpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include diff --git a/sprout/utility/pair/hash.hpp b/sprout/utility/pair/hash.hpp index a29d922e..a3d94a8b 100644 --- a/sprout/utility/pair/hash.hpp +++ b/sprout/utility/pair/hash.hpp @@ -3,8 +3,8 @@ #include #include -#include #include +#include namespace sprout { // diff --git a/sprout/utility/value_holder/hash.hpp b/sprout/utility/value_holder/hash.hpp index ab6633b4..4bcd301a 100644 --- a/sprout/utility/value_holder/hash.hpp +++ b/sprout/utility/value_holder/hash.hpp @@ -3,8 +3,8 @@ #include #include -#include #include +#include namespace sprout { // diff --git a/sprout/uuid/hash.hpp b/sprout/uuid/hash.hpp index 08572aa6..b5332b35 100644 --- a/sprout/uuid/hash.hpp +++ b/sprout/uuid/hash.hpp @@ -3,8 +3,8 @@ #include #include -#include #include +#include namespace sprout { // diff --git a/sprout/variant/hash.hpp b/sprout/variant/hash.hpp index 9e1c6bdb..66db3172 100644 --- a/sprout/variant/hash.hpp +++ b/sprout/variant/hash.hpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include #include