1 /* Copyright 2015 The TensorFlow Authors. All Rights Reserved.
2
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15
16 // Simple hash functions used for internal data structures
17
18 #ifndef TENSORFLOW_CORE_LIB_HASH_HASH_H_
19 #define TENSORFLOW_CORE_LIB_HASH_HASH_H_
20
21 #include <stddef.h>
22 #include <stdint.h>
23
24 #include <functional>
25 #include <string>
26
27 #include "tensorflow/core/lib/core/stringpiece.h"
28 #include "tensorflow/core/platform/types.h"
29
30 namespace tensorflow {
31
32 extern uint32 Hash32(const char* data, size_t n, uint32 seed);
33 extern uint64 Hash64(const char* data, size_t n, uint64 seed);
34
Hash64(const char * data,size_t n)35 inline uint64 Hash64(const char* data, size_t n) {
36 return Hash64(data, n, 0xDECAFCAFFE);
37 }
38
Hash64(const string & str)39 inline uint64 Hash64(const string& str) {
40 return Hash64(str.data(), str.size());
41 }
42
Hash64Combine(uint64 a,uint64 b)43 inline uint64 Hash64Combine(uint64 a, uint64 b) {
44 return a ^ (b + 0x9e3779b97f4a7800ULL + (a << 10) + (a >> 4));
45 }
46
47 // Combine two hashes in an order-independent way. This operation should be
48 // associative and compute the same hash for a collection of elements
49 // independent of traversal order. Note that it is better to combine hashes
50 // symmetrically with addition rather than XOR, since (x^x) == 0 but (x+x) != 0.
Hash64CombineUnordered(uint64 a,uint64 b)51 inline uint64 Hash64CombineUnordered(uint64 a, uint64 b) { return a + b; }
52
53 // Hash functor suitable for use with power-of-two sized hashtables. Use
54 // instead of std::hash<T>.
55 //
56 // In particular, tensorflow::hash is not the identity function for pointers.
57 // This is important for power-of-two sized hashtables like FlatMap and FlatSet,
58 // because otherwise they waste the majority of their hash buckets.
59 //
60 // The second type argument is only used for SFNIAE below.
61 template <typename T, typename = void>
62 struct hash {
operatorhash63 size_t operator()(const T& t) const { return std::hash<T>()(t); }
64 };
65
66 template <typename T>
67 struct hash<T, typename std::enable_if<std::is_enum<T>::value>::type> {
68 size_t operator()(T value) const {
69 // This works around a defect in the std::hash C++ spec that isn't fixed in
70 // (at least) gcc 4.8.4:
71 // http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2148
72 //
73 // We should be able to remove this and use the default
74 // tensorflow::hash<EnumTy>() once we stop building with GCC versions old
75 // enough to not have this defect fixed.
76 return std::hash<uint64>()(static_cast<uint64>(value));
77 }
78 };
79
80 template <typename T>
81 struct hash<T*> {
82 size_t operator()(const T* t) const {
83 // Hash pointers as integers, but bring more entropy to the lower bits.
84 size_t k = static_cast<size_t>(reinterpret_cast<uintptr_t>(t));
85 return k + (k >> 6);
86 }
87 };
88
89 template <>
90 struct hash<string> {
91 size_t operator()(const string& s) const {
92 return static_cast<size_t>(Hash64(s));
93 }
94 };
95
96 template <>
97 struct hash<StringPiece> {
98 size_t operator()(StringPiece sp) const {
99 return static_cast<size_t>(Hash64(sp.data(), sp.size()));
100 }
101 };
102 using StringPieceHasher = ::tensorflow::hash<StringPiece>;
103
104 template <typename T, typename U>
105 struct hash<std::pair<T, U>> {
106 size_t operator()(const std::pair<T, U>& p) const {
107 return Hash64Combine(hash<T>()(p.first), hash<U>()(p.second));
108 }
109 };
110
111 } // namespace tensorflow
112
113 #endif // TENSORFLOW_CORE_LIB_HASH_HASH_H_
114