Commit b2b96f59 authored by Xiao Shi's avatar Xiao Shi Committed by Facebook Github Bot

add hashers for __int128 and unsigned __int128

Summary: Add hashers for signed and unsigned int128 for platforms that have them.

Reviewed By: yfeldblum

Differential Revision: D7101875

fbshipit-source-id: ab5df6d06c7f292204318e479d172560ae2a4ec6
parent b4881fa5
...@@ -375,14 +375,19 @@ namespace detail { ...@@ -375,14 +375,19 @@ namespace detail {
struct integral_hasher { struct integral_hasher {
template <typename I> template <typename I>
size_t operator()(I const& i) const { size_t operator()(I const& i) const {
static_assert(sizeof(I) <= 8, "Input type is too wide"); static_assert(sizeof(I) <= 16, "Input type is too wide");
/* constexpr */ if (sizeof(I) <= 4) { /* constexpr */ if (sizeof(I) <= 4) {
auto const i32 = static_cast<int32_t>(i); // impl accident: sign-extends auto const i32 = static_cast<int32_t>(i); // impl accident: sign-extends
auto const u32 = static_cast<uint32_t>(i32); auto const u32 = static_cast<uint32_t>(i32);
return static_cast<size_t>(hash::jenkins_rev_mix32(u32)); return static_cast<size_t>(hash::jenkins_rev_mix32(u32));
} else { } else if (sizeof(I) <= 8) {
auto const u64 = static_cast<uint64_t>(i); auto const u64 = static_cast<uint64_t>(i);
return static_cast<size_t>(hash::twang_mix64(u64)); return static_cast<size_t>(hash::twang_mix64(u64));
} else {
auto const u = to_unsigned(i);
auto const hi = static_cast<uint64_t>(u >> sizeof(I) * 4);
auto const lo = static_cast<uint64_t>(u);
return hash::hash_128_to_64(hi, lo);
} }
} }
}; };
...@@ -466,6 +471,14 @@ struct hasher<signed char> : detail::integral_hasher {}; ...@@ -466,6 +471,14 @@ struct hasher<signed char> : detail::integral_hasher {};
template <> // char is a different type from both signed char and unsigned char template <> // char is a different type from both signed char and unsigned char
struct hasher<char> : detail::integral_hasher {}; struct hasher<char> : detail::integral_hasher {};
#if FOLLY_HAVE_INT128_T
template <>
struct hasher<signed __int128> : detail::integral_hasher {};
template <>
struct hasher<unsigned __int128> : detail::integral_hasher {};
#endif
template <> template <>
struct hasher<float> : detail::float_hasher {}; struct hasher<float> : detail::float_hasher {};
...@@ -524,25 +537,33 @@ struct TupleHasher<0, Ts...> { ...@@ -524,25 +537,33 @@ struct TupleHasher<0, Ts...> {
// Custom hash functions. // Custom hash functions.
namespace std { namespace std {
// Hash function for pairs. Requires default hash functions for both #if FOLLY_SUPPLY_MISSING_INT128_TRAITS
// items in the pair. template <>
template <typename T1, typename T2> struct hash<__int128> : folly::detail::integral_hasher {};
struct hash<std::pair<T1, T2> > {
public:
size_t operator()(const std::pair<T1, T2>& x) const {
return folly::hash::hash_combine(x.first, x.second);
}
};
// Hash function for tuples. Requires default hash functions for all types. template <>
template <typename... Ts> struct hash<unsigned __int128> : folly::detail::integral_hasher {};
struct hash<std::tuple<Ts...>> { #endif
size_t operator()(std::tuple<Ts...> const& key) const {
folly::TupleHasher<
std::tuple_size<std::tuple<Ts...>>::value - 1, // start index
Ts...> hasher;
return hasher(key); // Hash function for pairs. Requires default hash functions for both
} // items in the pair.
}; template <typename T1, typename T2>
struct hash<std::pair<T1, T2> > {
public:
size_t operator()(const std::pair<T1, T2>& x) const {
return folly::hash::hash_combine(x.first, x.second);
}
};
// Hash function for tuples. Requires default hash functions for all types.
template <typename... Ts>
struct hash<std::tuple<Ts...>> {
size_t operator()(std::tuple<Ts...> const& key) const {
folly::TupleHasher<
std::tuple_size<std::tuple<Ts...>>::value - 1, // start index
Ts...> hasher;
return hasher(key);
}
};
} // namespace std } // namespace std
...@@ -214,8 +214,29 @@ TEST(Hash, integral_types) { ...@@ -214,8 +214,29 @@ TEST(Hash, integral_types) {
hashes.insert(hasher((int64_t)22)); hashes.insert(hasher((int64_t)22));
hashes.insert(hasher((uint64_t)23)); hashes.insert(hasher((uint64_t)23));
hashes.insert(hasher((size_t)24)); hashes.insert(hasher((size_t)24));
EXPECT_EQ(24, hashes.size());
size_t setSize = 24;
#if FOLLY_HAVE_INT128_T
hashes.insert(hasher((__int128_t)25));
hashes.insert(hasher((__uint128_t)26));
setSize += 2;
#endif
EXPECT_EQ(setSize, hashes.size());
}
#if FOLLY_HAVE_INT128_T
TEST(Hash, int128_std_hash) {
std::unordered_set<__int128> hs;
hs.insert(__int128_t{1});
hs.insert(__int128_t{2});
EXPECT_EQ(2, hs.size());
std::set<unsigned __int128> s;
s.insert(static_cast<unsigned __int128>(1));
s.insert(static_cast<unsigned __int128>(2));
EXPECT_EQ(2, s.size());
} }
#endif
TEST(Hash, float_types) { TEST(Hash, float_types) {
folly::Hash hasher; folly::Hash hasher;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment