aboutsummaryrefslogtreecommitdiffhomepage
path: root/tensorflow/core/lib/hash/hash.cc
diff options
context:
space:
mode:
Diffstat (limited to 'tensorflow/core/lib/hash/hash.cc')
-rw-r--r--tensorflow/core/lib/hash/hash.cc113
1 files changed, 113 insertions, 0 deletions
diff --git a/tensorflow/core/lib/hash/hash.cc b/tensorflow/core/lib/hash/hash.cc
new file mode 100644
index 0000000000..075d252412
--- /dev/null
+++ b/tensorflow/core/lib/hash/hash.cc
@@ -0,0 +1,113 @@
+#include "tensorflow/core/lib/hash/hash.h"
+
+#include "tensorflow/core/platform/port.h"
+#include "tensorflow/core/lib/core/raw_coding.h"
+
+#include <string.h>
+
+namespace tensorflow {
+
+// 0xff is in case char is signed.
+static inline uint32 ByteAs32(char c) { return static_cast<uint32>(c) & 0xff; }
+static inline uint64 ByteAs64(char c) { return static_cast<uint64>(c) & 0xff; }
+
+uint32 Hash32(const char* data, size_t n, uint32 seed) {
+ // 'm' and 'r' are mixing constants generated offline.
+ // They're not really 'magic', they just happen to work well.
+
+ const uint32 m = 0x5bd1e995;
+ const int r = 24;
+
+ // Initialize the hash to a 'random' value
+ uint32 h = seed ^ n;
+
+ // Mix 4 bytes at a time into the hash
+ while (n >= 4) {
+ uint32 k = core::DecodeFixed32(data);
+
+ k *= m;
+ k ^= k >> r;
+ k *= m;
+
+ h *= m;
+ h ^= k;
+
+ data += 4;
+ n -= 4;
+ }
+
+ // Handle the last few bytes of the input array
+
+ switch (n) {
+ case 3:
+ h ^= ByteAs32(data[2]) << 16;
+ TF_FALLTHROUGH_INTENDED;
+ case 2:
+ h ^= ByteAs32(data[1]) << 8;
+ TF_FALLTHROUGH_INTENDED;
+ case 1:
+ h ^= ByteAs32(data[0]);
+ h *= m;
+ }
+
+ // Do a few final mixes of the hash to ensure the last few
+ // bytes are well-incorporated.
+
+ h ^= h >> 13;
+ h *= m;
+ h ^= h >> 15;
+
+ return h;
+}
+
+uint64 Hash64(const char* data, size_t n, uint64 seed) {
+ const uint64 m = 0xc6a4a7935bd1e995;
+ const int r = 47;
+
+ uint64 h = seed ^ (n * m);
+
+ while (n >= 8) {
+ uint64 k = core::DecodeFixed64(data);
+ data += 8;
+ n -= 8;
+
+ k *= m;
+ k ^= k >> r;
+ k *= m;
+
+ h ^= k;
+ h *= m;
+ }
+
+ switch (n) {
+ case 7:
+ h ^= ByteAs64(data[6]) << 48;
+ TF_FALLTHROUGH_INTENDED;
+ case 6:
+ h ^= ByteAs64(data[5]) << 40;
+ TF_FALLTHROUGH_INTENDED;
+ case 5:
+ h ^= ByteAs64(data[4]) << 32;
+ TF_FALLTHROUGH_INTENDED;
+ case 4:
+ h ^= ByteAs64(data[3]) << 24;
+ TF_FALLTHROUGH_INTENDED;
+ case 3:
+ h ^= ByteAs64(data[2]) << 16;
+ TF_FALLTHROUGH_INTENDED;
+ case 2:
+ h ^= ByteAs64(data[1]) << 8;
+ TF_FALLTHROUGH_INTENDED;
+ case 1:
+ h ^= ByteAs64(data[0]);
+ h *= m;
+ }
+
+ h ^= h >> r;
+ h *= m;
+ h ^= h >> r;
+
+ return h;
+}
+
+} // namespace tensorflow