aboutsummaryrefslogtreecommitdiffstats
path: root/util/digest/city.cpp
diff options
context:
space:
mode:
authorAlexander Smirnov <alex@ydb.tech>2024-11-20 11:14:58 +0000
committerAlexander Smirnov <alex@ydb.tech>2024-11-20 11:14:58 +0000
commit31773f157bf8164364649b5f470f52dece0a4317 (patch)
tree33d0f7eef45303ab68cf08ab381ce5e5e36c5240 /util/digest/city.cpp
parent2c7938962d8689e175574fc1e817c05049f27905 (diff)
parenteff600952d5dfe17942f38f510a8ac2b203bb3a5 (diff)
downloadydb-31773f157bf8164364649b5f470f52dece0a4317.tar.gz
Merge branch 'rightlib' into mergelibs-241120-1113
Diffstat (limited to 'util/digest/city.cpp')
-rw-r--r--util/digest/city.cpp62
1 files changed, 62 insertions, 0 deletions
diff --git a/util/digest/city.cpp b/util/digest/city.cpp
index c0c7c1a2e9..0976169447 100644
--- a/util/digest/city.cpp
+++ b/util/digest/city.cpp
@@ -28,6 +28,7 @@
// compromising on hash quality.
#include "city.h"
+#include "city_streaming.h"
using uint8 = ui8;
using uint32 = ui32;
@@ -307,3 +308,64 @@ uint128 CityHash128(const char* s, size_t len) noexcept {
return CityHash128WithSeed(s, len, uint128(k0, k1));
}
}
+
+TStreamingCityHash64::TStreamingCityHash64(size_t len, const char *head64, const char *tail64) {
+ Y_ASSERT(len > 64);
+ x = UNALIGNED_LOAD64(head64);
+ y = UNALIGNED_LOAD64(tail64 + 48) ^ k1;
+ z = UNALIGNED_LOAD64(tail64 + 8) ^ k0;
+ v = WeakHashLen32WithSeeds(tail64, len, y);
+ w = WeakHashLen32WithSeeds(tail64 + 32, len * k1, k0);
+ z += ShiftMix(v.second) * k1;
+ x = Rotate(z + x, 39) * k1;
+ y = Rotate(y, 33) * k1;
+ Rest64_ = (len - 1) / 64;
+ UnalignBufSz_ = 0;
+}
+
+void TStreamingCityHash64::Process(const char *s, size_t avail) {
+ if (Y_UNLIKELY(!Rest64_)) return;
+ if (UnalignBufSz_) {
+ if (UnalignBufSz_ + avail < 64) {
+ memcpy(&UnalignBuf_[UnalignBufSz_], s, avail);
+ UnalignBufSz_ += avail;
+ return;
+ } else {
+ memcpy(&UnalignBuf_[UnalignBufSz_], s, 64 - UnalignBufSz_);
+ x = Rotate(x + y + v.first + UNALIGNED_LOAD64(UnalignBuf_ + 16), 37) * k1;
+ y = Rotate(y + v.second + UNALIGNED_LOAD64(UnalignBuf_ + 48), 42) * k1;
+ x ^= w.second;
+ y ^= v.first;
+ z = Rotate(z ^ w.first, 33);
+ v = WeakHashLen32WithSeeds(UnalignBuf_, v.second * k1, x + w.first);
+ w = WeakHashLen32WithSeeds(UnalignBuf_ + 32, z + w.second, y);
+ DoSwap(z, x);
+ s += 64 - UnalignBufSz_;
+ avail -= 64 - UnalignBufSz_;
+ Rest64_--;
+ UnalignBufSz_ = 0;
+ }
+ }
+ while(Rest64_ && avail >= 64) {
+ x = Rotate(x + y + v.first + UNALIGNED_LOAD64(s + 16), 37) * k1;
+ y = Rotate(y + v.second + UNALIGNED_LOAD64(s + 48), 42) * k1;
+ x ^= w.second;
+ y ^= v.first;
+ z = Rotate(z ^ w.first, 33);
+ v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
+ w = WeakHashLen32WithSeeds(s + 32, z + w.second, y);
+ DoSwap(z, x);
+ s += 64;
+ avail -= 64;
+ Rest64_--;
+ }
+ if (Rest64_ && avail) {
+ memcpy(UnalignBuf_, s, avail);
+ UnalignBufSz_ = avail;
+ }
+}
+
+uint64 TStreamingCityHash64::operator() () {
+ return HashLen16(HashLen16(v.first, w.first) + ShiftMix(y) * k1 + z,
+ HashLen16(v.second, w.second) + x);
+}