Export of internal Abseil changes.
-- 906c47420646d510edd2479d5542c56f5fa31b65 by CJ Johnson <johnsoncj@google.com>: Import of CCTZ from GitHub. PiperOrigin-RevId: 216573923 -- 74560d4afd2b605909e677c6fc3076049fb3010a by Eric Fiselier <ericwf@google.com>: Avoid -Wformat-pedantic in benchmark. PiperOrigin-RevId: 216523769 -- 9bcc9da8b03e6d1ea43ee78931256c5541cb9686 by Eric Fiselier <ericwf@google.com>: Delete unused CityHash functions. PiperOrigin-RevId: 216464492 -- a42563b394c89fbb4c55cb5a6a5edbf96d271eea by Abseil Team <absl-team@google.com>: Introduce new Abseil interfaces for converting between civil times and absolute times.s Deprecates absl::ConvertDateTime() and absl::FromDateTime(). PiperOrigin-RevId: 216424948 -- 088e11235124267517d7f137854fa5554679c24f by Eric Fiselier <ericwf@google.com>: Remove unneeded break statements in test. PiperOrigin-RevId: 216403321 GitOrigin-RevId: 906c47420646d510edd2479d5542c56f5fa31b65 Change-Id: Idb44420be623e369c66f5a9c92bdc9ab46d3ec92
This commit is contained in:
parent
445998d7ac
commit
f340f773ed
24 changed files with 2675 additions and 2592 deletions
|
|
@ -93,7 +93,6 @@ cc_library(
|
|||
srcs = ["internal/city.cc"],
|
||||
hdrs = [
|
||||
"internal/city.h",
|
||||
"internal/city_crc.h",
|
||||
],
|
||||
copts = ABSL_DEFAULT_COPTS,
|
||||
deps = [
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ list(APPEND HASH_PUBLIC_HEADERS
|
|||
|
||||
list(APPEND HASH_INTERNAL_HEADERS
|
||||
"internal/city.h"
|
||||
"internal/city_crc.h"
|
||||
"internal/hash.h"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -340,251 +340,5 @@ uint64_t CityHash64WithSeeds(const char *s, size_t len, uint64_t seed0,
|
|||
return HashLen16(CityHash64(s, len) - seed0, seed1);
|
||||
}
|
||||
|
||||
// A subroutine for CityHash128(). Returns a decent 128-bit hash for strings
|
||||
// of any length representable in signed long. Based on City and Murmur.
|
||||
static uint128 CityMurmur(const char *s, size_t len, uint128 seed) {
|
||||
uint64_t a = Uint128Low64(seed);
|
||||
uint64_t b = Uint128High64(seed);
|
||||
uint64_t c = 0;
|
||||
uint64_t d = 0;
|
||||
int64_t l = len - 16;
|
||||
if (l <= 0) { // len <= 16
|
||||
a = ShiftMix(a * k1) * k1;
|
||||
c = b * k1 + HashLen0to16(s, len);
|
||||
d = ShiftMix(a + (len >= 8 ? Fetch64(s) : c));
|
||||
} else { // len > 16
|
||||
c = HashLen16(Fetch64(s + len - 8) + k1, a);
|
||||
d = HashLen16(b + len, c + Fetch64(s + len - 16));
|
||||
a += d;
|
||||
do {
|
||||
a ^= ShiftMix(Fetch64(s) * k1) * k1;
|
||||
a *= k1;
|
||||
b ^= a;
|
||||
c ^= ShiftMix(Fetch64(s + 8) * k1) * k1;
|
||||
c *= k1;
|
||||
d ^= c;
|
||||
s += 16;
|
||||
l -= 16;
|
||||
} while (l > 0);
|
||||
}
|
||||
a = HashLen16(a, c);
|
||||
b = HashLen16(d, b);
|
||||
return uint128(a ^ b, HashLen16(b, a));
|
||||
}
|
||||
|
||||
uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed) {
|
||||
if (len < 128) {
|
||||
return CityMurmur(s, len, seed);
|
||||
}
|
||||
|
||||
// We expect len >= 128 to be the common case. Keep 56 bytes of state:
|
||||
// v, w, x, y, and z.
|
||||
std::pair<uint64_t, uint64_t> v, w;
|
||||
uint64_t x = Uint128Low64(seed);
|
||||
uint64_t y = Uint128High64(seed);
|
||||
uint64_t z = len * k1;
|
||||
v.first = Rotate(y ^ k1, 49) * k1 + Fetch64(s);
|
||||
v.second = Rotate(v.first, 42) * k1 + Fetch64(s + 8);
|
||||
w.first = Rotate(y + z, 35) * k1 + x;
|
||||
w.second = Rotate(x + Fetch64(s + 88), 53) * k1;
|
||||
|
||||
// This is the same inner loop as CityHash64(), manually unrolled.
|
||||
do {
|
||||
x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
|
||||
y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
|
||||
x ^= w.second;
|
||||
y += v.first + Fetch64(s + 40);
|
||||
z = Rotate(z + w.first, 33) * k1;
|
||||
v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
|
||||
w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
|
||||
std::swap(z, x);
|
||||
s += 64;
|
||||
x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
|
||||
y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
|
||||
x ^= w.second;
|
||||
y += v.first + Fetch64(s + 40);
|
||||
z = Rotate(z + w.first, 33) * k1;
|
||||
v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
|
||||
w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
|
||||
std::swap(z, x);
|
||||
s += 64;
|
||||
len -= 128;
|
||||
} while (ABSL_PREDICT_TRUE(len >= 128));
|
||||
x += Rotate(v.first + z, 49) * k0;
|
||||
y = y * k0 + Rotate(w.second, 37);
|
||||
z = z * k0 + Rotate(w.first, 27);
|
||||
w.first *= 9;
|
||||
v.first *= k0;
|
||||
// If 0 < len < 128, hash up to 4 chunks of 32 bytes each from the end of s.
|
||||
for (size_t tail_done = 0; tail_done < len;) {
|
||||
tail_done += 32;
|
||||
y = Rotate(x + y, 42) * k0 + v.second;
|
||||
w.first += Fetch64(s + len - tail_done + 16);
|
||||
x = x * k0 + w.first;
|
||||
z += w.second + Fetch64(s + len - tail_done);
|
||||
w.second += v.first;
|
||||
v = WeakHashLen32WithSeeds(s + len - tail_done, v.first + z, v.second);
|
||||
v.first *= k0;
|
||||
}
|
||||
// At this point our 56 bytes of state should contain more than
|
||||
// enough information for a strong 128-bit hash. We use two
|
||||
// different 56-byte-to-8-byte hashes to get a 16-byte final result.
|
||||
x = HashLen16(x, v.first);
|
||||
y = HashLen16(y + z, w.first);
|
||||
return uint128(HashLen16(x + v.second, w.second) + y,
|
||||
HashLen16(x + w.second, y + v.second));
|
||||
}
|
||||
|
||||
uint128 CityHash128(const char *s, size_t len) {
|
||||
return len >= 16
|
||||
? CityHash128WithSeed(s + 16, len - 16,
|
||||
uint128(Fetch64(s), Fetch64(s + 8) + k0))
|
||||
: CityHash128WithSeed(s, len, uint128(k0, k1));
|
||||
}
|
||||
} // namespace hash_internal
|
||||
} // namespace absl
|
||||
|
||||
#ifdef __SSE4_2__
|
||||
#include <nmmintrin.h>
|
||||
#include "absl/hash/internal/city_crc.h"
|
||||
|
||||
namespace absl {
|
||||
namespace hash_internal {
|
||||
|
||||
// Requires len >= 240.
|
||||
static void CityHashCrc256Long(const char *s, size_t len, uint32_t seed,
|
||||
uint64_t *result) {
|
||||
uint64_t a = Fetch64(s + 56) + k0;
|
||||
uint64_t b = Fetch64(s + 96) + k0;
|
||||
uint64_t c = result[0] = HashLen16(b, len);
|
||||
uint64_t d = result[1] = Fetch64(s + 120) * k0 + len;
|
||||
uint64_t e = Fetch64(s + 184) + seed;
|
||||
uint64_t f = 0;
|
||||
uint64_t g = 0;
|
||||
uint64_t h = c + d;
|
||||
uint64_t x = seed;
|
||||
uint64_t y = 0;
|
||||
uint64_t z = 0;
|
||||
|
||||
// 240 bytes of input per iter.
|
||||
size_t iters = len / 240;
|
||||
len -= iters * 240;
|
||||
do {
|
||||
#undef CHUNK
|
||||
#define CHUNK(r) \
|
||||
PERMUTE3(x, z, y); \
|
||||
b += Fetch64(s); \
|
||||
c += Fetch64(s + 8); \
|
||||
d += Fetch64(s + 16); \
|
||||
e += Fetch64(s + 24); \
|
||||
f += Fetch64(s + 32); \
|
||||
a += b; \
|
||||
h += f; \
|
||||
b += c; \
|
||||
f += d; \
|
||||
g += e; \
|
||||
e += z; \
|
||||
g += x; \
|
||||
z = _mm_crc32_u64(z, b + g); \
|
||||
y = _mm_crc32_u64(y, e + h); \
|
||||
x = _mm_crc32_u64(x, f + a); \
|
||||
e = Rotate(e, r); \
|
||||
c += e; \
|
||||
s += 40
|
||||
|
||||
CHUNK(0);
|
||||
PERMUTE3(a, h, c);
|
||||
CHUNK(33);
|
||||
PERMUTE3(a, h, f);
|
||||
CHUNK(0);
|
||||
PERMUTE3(b, h, f);
|
||||
CHUNK(42);
|
||||
PERMUTE3(b, h, d);
|
||||
CHUNK(0);
|
||||
PERMUTE3(b, h, e);
|
||||
CHUNK(33);
|
||||
PERMUTE3(a, h, e);
|
||||
} while (--iters > 0);
|
||||
|
||||
while (len >= 40) {
|
||||
CHUNK(29);
|
||||
e ^= Rotate(a, 20);
|
||||
h += Rotate(b, 30);
|
||||
g ^= Rotate(c, 40);
|
||||
f += Rotate(d, 34);
|
||||
PERMUTE3(c, h, g);
|
||||
len -= 40;
|
||||
}
|
||||
if (len > 0) {
|
||||
s = s + len - 40;
|
||||
CHUNK(33);
|
||||
e ^= Rotate(a, 43);
|
||||
h += Rotate(b, 42);
|
||||
g ^= Rotate(c, 41);
|
||||
f += Rotate(d, 40);
|
||||
}
|
||||
result[0] ^= h;
|
||||
result[1] ^= g;
|
||||
g += h;
|
||||
a = HashLen16(a, g + z);
|
||||
x += y << 32;
|
||||
b += x;
|
||||
c = HashLen16(c, z) + h;
|
||||
d = HashLen16(d, e + result[0]);
|
||||
g += e;
|
||||
h += HashLen16(x, f);
|
||||
e = HashLen16(a, d) + g;
|
||||
z = HashLen16(b, c) + a;
|
||||
y = HashLen16(g, h) + c;
|
||||
result[0] = e + z + y + x;
|
||||
a = ShiftMix((a + y) * k0) * k0 + b;
|
||||
result[1] += a + result[0];
|
||||
a = ShiftMix(a * k0) * k0 + c;
|
||||
result[2] = a + result[1];
|
||||
a = ShiftMix((a + e) * k0) * k0;
|
||||
result[3] = a + result[2];
|
||||
}
|
||||
|
||||
// Requires len < 240.
|
||||
static void CityHashCrc256Short(const char *s, size_t len, uint64_t *result) {
|
||||
char buf[240];
|
||||
memcpy(buf, s, len);
|
||||
memset(buf + len, 0, 240 - len);
|
||||
CityHashCrc256Long(buf, 240, ~static_cast<uint32_t>(len), result);
|
||||
}
|
||||
|
||||
void CityHashCrc256(const char *s, size_t len, uint64_t *result) {
|
||||
if (ABSL_PREDICT_TRUE(len >= 240)) {
|
||||
CityHashCrc256Long(s, len, 0, result);
|
||||
} else {
|
||||
CityHashCrc256Short(s, len, result);
|
||||
}
|
||||
}
|
||||
|
||||
uint128 CityHashCrc128WithSeed(const char *s, size_t len, uint128 seed) {
|
||||
if (len <= 900) {
|
||||
return CityHash128WithSeed(s, len, seed);
|
||||
} else {
|
||||
uint64_t result[4];
|
||||
CityHashCrc256(s, len, result);
|
||||
uint64_t u = Uint128High64(seed) + result[0];
|
||||
uint64_t v = Uint128Low64(seed) + result[1];
|
||||
return uint128(HashLen16(u, v + result[2]),
|
||||
HashLen16(Rotate(v, 32), u * k0 + result[3]));
|
||||
}
|
||||
}
|
||||
|
||||
uint128 CityHashCrc128(const char *s, size_t len) {
|
||||
if (len <= 900) {
|
||||
return CityHash128(s, len);
|
||||
} else {
|
||||
uint64_t result[4];
|
||||
CityHashCrc256(s, len, result);
|
||||
return uint128(result[2], result[3]);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace hash_internal
|
||||
} // namespace absl
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -23,15 +23,6 @@
|
|||
// is Murmur3. For 64-bit x86 code, CityHash64 is an excellent choice for hash
|
||||
// tables and most other hashing (excluding cryptography).
|
||||
//
|
||||
// For 64-bit x86 code, on long strings, the picture is more complicated.
|
||||
// On many recent Intel CPUs, such as Nehalem, Westmere, Sandy Bridge, etc.,
|
||||
// CityHashCrc128 appears to be faster than all competitors of comparable
|
||||
// quality. CityHash128 is also good but not quite as fast. We believe our
|
||||
// nearest competitor is Bob Jenkins' Spooky. We don't have great data for
|
||||
// other 64-bit CPUs, but for long strings we know that Spooky is slightly
|
||||
// faster than CityHash on some relatively recent AMD x86-64 CPUs, for example.
|
||||
// Note that CityHashCrc128 is declared in citycrc.h.
|
||||
//
|
||||
// For 32-bit x86 code, we don't know of anything faster than CityHash32 that
|
||||
// is of comparable quality. We believe our nearest competitor is Murmur3A.
|
||||
// (On 64-bit CPUs, it is typically faster to use the other CityHash variants.)
|
||||
|
|
@ -79,13 +70,6 @@ uint64_t CityHash64WithSeed(const char *s, size_t len, uint64_t seed);
|
|||
uint64_t CityHash64WithSeeds(const char *s, size_t len, uint64_t seed0,
|
||||
uint64_t seed1);
|
||||
|
||||
// Hash function for a byte array.
|
||||
uint128 CityHash128(const char *s, size_t len);
|
||||
|
||||
// Hash function for a byte array. For convenience, a 128-bit seed is also
|
||||
// hashed into the result.
|
||||
uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed);
|
||||
|
||||
// Hash function for a byte array. Most useful in 32-bit binaries.
|
||||
uint32_t CityHash32(const char *s, size_t len);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,41 +0,0 @@
|
|||
// Copyright 2018 The Abseil Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// This file declares the subset of the CityHash functions that require
|
||||
// _mm_crc32_u64(). See the CityHash README for details.
|
||||
//
|
||||
// Functions in the CityHash family are not suitable for cryptography.
|
||||
|
||||
#ifndef ABSL_HASH_INTERNAL_CITY_CRC_H_
|
||||
#define ABSL_HASH_INTERNAL_CITY_CRC_H_
|
||||
|
||||
#include "absl/hash/internal/city.h"
|
||||
|
||||
namespace absl {
|
||||
namespace hash_internal {
|
||||
|
||||
// Hash function for a byte array.
|
||||
uint128 CityHashCrc128(const char *s, size_t len);
|
||||
|
||||
// Hash function for a byte array. For convenience, a 128-bit seed is also
|
||||
// hashed into the result.
|
||||
uint128 CityHashCrc128WithSeed(const char *s, size_t len, uint128 seed);
|
||||
|
||||
// Hash function for a byte array. Sets result[0] ... result[3].
|
||||
void CityHashCrc256(const char *s, size_t len, uint64_t *result);
|
||||
|
||||
} // namespace hash_internal
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_HASH_INTERNAL_CITY_CRC_H_
|
||||
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue