Skip to content

Commit

Permalink
Export of internal Abseil changes.
Browse files Browse the repository at this point in the history
--
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
  • Loading branch information
Abseil Team authored and CJ-Johnson committed Oct 10, 2018
1 parent 445998d commit f340f77
Show file tree
Hide file tree
Showing 24 changed files with 2,657 additions and 2,574 deletions.
24 changes: 6 additions & 18 deletions absl/container/internal/raw_hash_set_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1029,7 +1029,6 @@ ExpectedStats XorSeedExpectedStats() {
{{0.95, 0.1}},
{{0.95, 0}, {0.99, 2}, {0.999, 4}, {0.9999, 10}}};
}
break;
case 16:
if (kRandomizesInserts) {
return {0.1,
Expand All @@ -1042,10 +1041,8 @@ ExpectedStats XorSeedExpectedStats() {
{{0.95, 0.05}},
{{0.95, 0}, {0.99, 1}, {0.999, 4}, {0.9999, 10}}};
}
break;
default:
ABSL_RAW_LOG(FATAL, "%s", "Unknown Group width");
}
ABSL_RAW_LOG(FATAL, "%s", "Unknown Group width");
return {};
}
TEST(Table, DISABLED_EnsureNonQuadraticTopNXorSeedByProbeSeqLength) {
Expand Down Expand Up @@ -1125,7 +1122,6 @@ ExpectedStats LinearTransformExpectedStats() {
{{0.95, 0.3}},
{{0.95, 0}, {0.99, 3}, {0.999, 15}, {0.9999, 25}}};
}
break;
case 16:
if (kRandomizesInserts) {
return {0.1,
Expand All @@ -1138,10 +1134,8 @@ ExpectedStats LinearTransformExpectedStats() {
{{0.95, 0.1}},
{{0.95, 0}, {0.99, 1}, {0.999, 6}, {0.9999, 10}}};
}
break;
default:
ABSL_RAW_LOG(FATAL, "%s", "Unknown Group width");
}
ABSL_RAW_LOG(FATAL, "%s", "Unknown Group width");
return {};
}
TEST(Table, DISABLED_EnsureNonQuadraticTopNLinearTransformByProbeSeqLength) {
Expand Down Expand Up @@ -1834,18 +1828,15 @@ std::vector<std::pair<double, double>> StringTablePefectRatios() {
} else {
return {{0.995, 0.01}, {0.97, 0.01}, {0.89, 0.02}};
}
break;
case 16:
if (kRandomizesInserts) {
return {{0.973, 0.01}, {0.965, 0.01}, {0.92, 0.02}};
} else {
return {{0.995, 0.005}, {0.99, 0.005}, {0.94, 0.01}};
}
break;
default:
// Ignore anything else.
return {};
}
ABSL_RAW_LOG(FATAL, "%s", "Unknown Group width");
return {};
}

// This is almost a change detector, but it allows us to know how we are
Expand Down Expand Up @@ -1884,18 +1875,15 @@ std::vector<std::pair<double, double>> IntTablePefectRatios() {
} else {
return {{0.99, 0.01}, {0.99, 0.01}, {0.95, 0.02}};
}
break;
case 16:
if (kRandomizesInserts) {
return {{0.98, 0.02}, {0.978, 0.02}, {0.96, 0.02}};
} else {
return {{0.998, 0.003}, {0.995, 0.01}, {0.975, 0.02}};
}
break;
default:
// Ignore anything else.
return {};
}
ABSL_RAW_LOG(FATAL, "%s", "Unknown Group width");
return {};
}

// This is almost a change detector, but it allows us to know how we are
Expand Down
1 change: 0 additions & 1 deletion absl/hash/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ cc_library(
srcs = ["internal/city.cc"],
hdrs = [
"internal/city.h",
"internal/city_crc.h",
],
copts = ABSL_DEFAULT_COPTS,
deps = [
Expand Down
1 change: 0 additions & 1 deletion absl/hash/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ list(APPEND HASH_PUBLIC_HEADERS

list(APPEND HASH_INTERNAL_HEADERS
"internal/city.h"
"internal/city_crc.h"
"internal/hash.h"
)

Expand Down
246 changes: 0 additions & 246 deletions absl/hash/internal/city.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
16 changes: 0 additions & 16 deletions absl/hash/internal/city.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.)
Expand Down Expand Up @@ -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);

Expand Down
Loading

0 comments on commit f340f77

Please sign in to comment.