1 | /* Copyright 2016 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 | #ifndef TENSORFLOW_TSL_PLATFORM_FINGERPRINT_H_ |
17 | #define TENSORFLOW_TSL_PLATFORM_FINGERPRINT_H_ |
18 | |
19 | #include "tensorflow/tsl/platform/stringpiece.h" |
20 | #include "tensorflow/tsl/platform/types.h" |
21 | |
22 | // The following line is used by copybara to set or unset the USE_OSS_FARMHASH |
23 | // preprocessor symbol as needed. Please do not remove. |
24 | #define USE_OSS_FARMHASH |
25 | |
26 | #ifdef USE_OSS_FARMHASH |
27 | #include <farmhash.h> |
28 | #else |
29 | #include "util/hash/farmhash_fingerprint.h" |
30 | #endif |
31 | |
32 | namespace tsl { |
33 | |
34 | struct Fprint128 { |
35 | uint64_t low64; |
36 | uint64_t high64; |
37 | }; |
38 | |
39 | inline bool operator==(const Fprint128& lhs, const Fprint128& rhs) { |
40 | return lhs.low64 == rhs.low64 && lhs.high64 == rhs.high64; |
41 | } |
42 | |
43 | struct Fprint128Hasher { |
44 | size_t operator()(const Fprint128& v) const { |
45 | // Low64 should be sufficiently mixed to allow use of it as a Hash. |
46 | return static_cast<size_t>(v.low64); |
47 | } |
48 | }; |
49 | |
50 | namespace internal { |
51 | // Mixes some of the bits that got propagated to the high bits back into the |
52 | // low bits. |
53 | inline uint64_t ShiftMix(const uint64_t val) { return val ^ (val >> 47); } |
54 | } // namespace internal |
55 | |
56 | // This concatenates two 64-bit fingerprints. It is a convenience function to |
57 | // get a fingerprint for a combination of already fingerprinted components. For |
58 | // example this code is used to concatenate the hashes from each of the features |
59 | // on sparse crosses. |
60 | // |
61 | // One shouldn't expect FingerprintCat64(Fingerprint64(x), Fingerprint64(y)) |
62 | // to indicate anything about FingerprintCat64(StrCat(x, y)). This operation |
63 | // is not commutative. |
64 | // |
65 | // From a security standpoint, we don't encourage this pattern to be used |
66 | // for everything as it is vulnerable to length-extension attacks and it |
67 | // is easier to compute multicollisions. |
68 | inline uint64_t FingerprintCat64(const uint64_t fp1, const uint64_t fp2) { |
69 | static const uint64_t kMul = 0xc6a4a7935bd1e995ULL; |
70 | uint64_t result = fp1 ^ kMul; |
71 | result ^= internal::ShiftMix(fp2 * kMul) * kMul; |
72 | result *= kMul; |
73 | result = internal::ShiftMix(result) * kMul; |
74 | result = internal::ShiftMix(result); |
75 | return result; |
76 | } |
77 | |
78 | // This is a portable fingerprint interface for strings that will never change. |
79 | // However, it is not suitable for cryptography. |
80 | inline uint64_t Fingerprint64(const tsl::StringPiece s) { |
81 | #ifdef USE_OSS_FARMHASH |
82 | return ::util::Fingerprint64(s.data(), s.size()); |
83 | #else |
84 | // Fingerprint op depends on the fact that Fingerprint64() is implemented by |
85 | // Farmhash. If the implementation ever changes, Fingerprint op should be |
86 | // modified to keep using Farmhash. |
87 | // LINT.IfChange |
88 | return farmhash::Fingerprint64(s.data(), s.size()); |
89 | // LINT.ThenChange(//third_party/tensorflow/core/kernels/fingerprint_op.cc) |
90 | #endif |
91 | } |
92 | |
93 | // 32-bit variant of Fingerprint64 above (same properties and caveats apply). |
94 | inline uint32_t Fingerprint32(const tsl::StringPiece s) { |
95 | #ifdef USE_OSS_FARMHASH |
96 | return ::util::Fingerprint32(s.data(), s.size()); |
97 | #else |
98 | return farmhash::Fingerprint32(s.data(), s.size()); |
99 | #endif |
100 | } |
101 | |
102 | // 128-bit variant of Fingerprint64 above (same properties and caveats apply). |
103 | inline Fprint128 Fingerprint128(const tsl::StringPiece s) { |
104 | #ifdef USE_OSS_FARMHASH |
105 | const auto fingerprint = ::util::Fingerprint128(s.data(), s.size()); |
106 | return {::util::Uint128Low64(fingerprint), |
107 | ::util::Uint128High64(fingerprint)}; |
108 | #else |
109 | const auto fingerprint = farmhash::Fingerprint128(s.data(), s.size()); |
110 | return {absl::Uint128Low64(fingerprint), absl::Uint128High64(fingerprint)}; |
111 | #endif |
112 | } |
113 | |
114 | } // namespace tsl |
115 | |
116 | #endif // TENSORFLOW_TSL_PLATFORM_FINGERPRINT_H_ |
117 | |