/*
- * Copyright 2017 Facebook, Inc.
+ * Copyright 2011-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <type_traits>
#include <utility>
-#include <folly/Bits.h>
#include <folly/functional/ApplyTuple.h>
#include <folly/hash/SpookyHashV1.h>
#include <folly/hash/SpookyHashV2.h>
+#include <folly/lang/Bits.h>
/*
* Various hashing functions.
} // namespace hash
namespace detail {
+
struct integral_hasher {
template <typename I>
size_t operator()(I const& i) const {
- static_assert(sizeof(I) <= 8, "input type is too wide");
- if (sizeof(I) <= 4) { // the branch taken is known at compile time
+ static_assert(sizeof(I) <= 8, "Input type is too wide");
+ /* constexpr */ if (sizeof(I) <= 4) {
auto const i32 = static_cast<int32_t>(i); // impl accident: sign-extends
auto const u32 = static_cast<uint32_t>(i32);
return static_cast<size_t>(hash::jenkins_rev_mix32(u32));
}
}
};
+
+struct float_hasher {
+ template <typename F>
+ size_t operator()(F const& f) const {
+ static_assert(sizeof(F) <= 8, "Input type is too wide");
+
+ if (f == F{}) { // Ensure 0 and -0 get the same hash.
+ return 0;
+ }
+
+ /* constexpr */ if (sizeof(F) <= 4) {
+ uint32_t u32 = 0;
+ memcpy(&u32, &f, sizeof(F));
+ return static_cast<size_t>(hash::jenkins_rev_mix32(u32));
+ } else {
+ uint64_t u64 = 0;
+ memcpy(&u64, &f, sizeof(F));
+ return static_cast<size_t>(hash::twang_mix64(u64));
+ }
+ }
+};
+
} // namespace detail
template <class Key, class Enable = void>
template <> // char is a different type from both signed char and unsigned char
struct hasher<char> : detail::integral_hasher {};
+template <>
+struct hasher<float> : detail::float_hasher {};
+
+template <>
+struct hasher<double> : detail::float_hasher {};
+
template <> struct hasher<std::string> {
size_t operator()(const std::string& key) const {
return static_cast<size_t>(