mirror of
https://github.com/abseil/abseil-cpp.git
synced 2026-06-04 12:07:05 +08:00
Cleanup duplicated bit-rotation code
PiperOrigin-RevId: 857286087 Change-Id: Ie79f5b9e7ca8417f6311750c0de469ca6de4a8f9
This commit is contained in:
committed by
Copybara-Service
parent
ae164c5888
commit
569ff20318
@@ -43,13 +43,13 @@ absl_cc_library(
|
||||
${ABSL_DEFAULT_COPTS}
|
||||
DEPS
|
||||
absl::crc_cpu_detect
|
||||
absl::bits
|
||||
absl::config
|
||||
absl::core_headers
|
||||
absl::endian
|
||||
absl::memory
|
||||
absl::prefetch
|
||||
absl::raw_logging_internal
|
||||
absl::memory
|
||||
absl::bits
|
||||
)
|
||||
|
||||
absl_cc_library(
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include "absl/base/internal/raw_logging.h"
|
||||
#include "absl/base/prefetch.h"
|
||||
#include "absl/crc/internal/crc_internal.h"
|
||||
#include "absl/numeric/bits.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
@@ -410,16 +411,13 @@ void CRC32::Scramble(uint32_t* crc) const {
|
||||
// Rotate by near half the word size plus 1. See the scramble comment in
|
||||
// crc_internal.h for an explanation.
|
||||
constexpr int scramble_rotate = (32 / 2) + 1;
|
||||
*crc = RotateRight<uint32_t>(static_cast<unsigned int>(*crc + kScrambleLo),
|
||||
32, scramble_rotate) &
|
||||
MaskOfLength<uint32_t>(32);
|
||||
*crc = absl::rotr(static_cast<uint32_t>(*crc + kScrambleLo), scramble_rotate);
|
||||
}
|
||||
|
||||
void CRC32::Unscramble(uint32_t* crc) const {
|
||||
constexpr int scramble_rotate = (32 / 2) + 1;
|
||||
uint64_t rotated = RotateRight<uint32_t>(static_cast<unsigned int>(*crc), 32,
|
||||
32 - scramble_rotate);
|
||||
*crc = (rotated - kScrambleLo) & MaskOfLength<uint32_t>(32);
|
||||
uint64_t rotated = absl::rotl(*crc, scramble_rotate);
|
||||
*crc = static_cast<uint32_t>(rotated - kScrambleLo);
|
||||
}
|
||||
|
||||
// Constructor and destructor for base class CRC.
|
||||
|
||||
@@ -137,22 +137,6 @@ class CRC32 : public CRCImpl {
|
||||
|
||||
// Helpers
|
||||
|
||||
// Return a bit mask containing len 1-bits.
|
||||
// Requires 0 < len <= sizeof(T)
|
||||
template <typename T>
|
||||
T MaskOfLength(int len) {
|
||||
// shift 2 by len-1 rather than 1 by len because shifts of wordsize
|
||||
// are undefined.
|
||||
return (T(2) << (len - 1)) - 1;
|
||||
}
|
||||
|
||||
// Rotate low-order "width" bits of "in" right by "r" bits,
|
||||
// setting other bits in word to arbitrary values.
|
||||
template <typename T>
|
||||
T RotateRight(T in, int width, int r) {
|
||||
return (in << (width - r)) | ((in >> r) & MaskOfLength<T>(width - r));
|
||||
}
|
||||
|
||||
// RoundUp<N>(p) returns the lowest address >= p aligned to an N-byte
|
||||
// boundary. Requires that N is a power of 2.
|
||||
template <int alignment>
|
||||
|
||||
@@ -174,6 +174,7 @@ cc_library(
|
||||
"//absl/base:config",
|
||||
"//absl/base:core_headers",
|
||||
"//absl/base:endian",
|
||||
"//absl/numeric:bits",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -137,6 +137,7 @@ absl_cc_library(
|
||||
DEPS
|
||||
absl::config
|
||||
absl::core_headers
|
||||
absl::bits
|
||||
absl::endian
|
||||
)
|
||||
|
||||
|
||||
@@ -21,13 +21,13 @@
|
||||
|
||||
#include "absl/hash/internal/city.h"
|
||||
|
||||
#include <string.h> // for memcpy and memset
|
||||
#include <algorithm>
|
||||
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/internal/endian.h"
|
||||
#include "absl/base/internal/unaligned_access.h"
|
||||
#include "absl/base/optimization.h"
|
||||
#include "absl/numeric/bits.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
@@ -68,11 +68,6 @@ static uint32_t fmix(uint32_t h) {
|
||||
return h;
|
||||
}
|
||||
|
||||
static uint32_t Rotate32(uint32_t val, int shift) {
|
||||
// Avoid shifting by 32: doing so yields an undefined result.
|
||||
return shift == 0 ? val : ((val >> shift) | (val << (32 - shift)));
|
||||
}
|
||||
|
||||
#undef PERMUTE3
|
||||
#define PERMUTE3(a, b, c) \
|
||||
do { \
|
||||
@@ -83,10 +78,10 @@ static uint32_t Rotate32(uint32_t val, int shift) {
|
||||
static uint32_t Mur(uint32_t a, uint32_t h) {
|
||||
// Helper from Murmur3 for combining two 32-bit values.
|
||||
a *= c1;
|
||||
a = Rotate32(a, 17);
|
||||
a = absl::rotr(a, 17);
|
||||
a *= c2;
|
||||
h ^= a;
|
||||
h = Rotate32(h, 19);
|
||||
h = absl::rotr(h, 19);
|
||||
return h * 5 + 0xe6546b64;
|
||||
}
|
||||
|
||||
@@ -131,44 +126,44 @@ uint32_t CityHash32(const char *s, size_t len) {
|
||||
// len > 24
|
||||
uint32_t h = static_cast<uint32_t>(len), g = c1 * h, f = g;
|
||||
|
||||
uint32_t a0 = Rotate32(Fetch32(s + len - 4) * c1, 17) * c2;
|
||||
uint32_t a1 = Rotate32(Fetch32(s + len - 8) * c1, 17) * c2;
|
||||
uint32_t a2 = Rotate32(Fetch32(s + len - 16) * c1, 17) * c2;
|
||||
uint32_t a3 = Rotate32(Fetch32(s + len - 12) * c1, 17) * c2;
|
||||
uint32_t a4 = Rotate32(Fetch32(s + len - 20) * c1, 17) * c2;
|
||||
uint32_t a0 = absl::rotr(Fetch32(s + len - 4) * c1, 17) * c2;
|
||||
uint32_t a1 = absl::rotr(Fetch32(s + len - 8) * c1, 17) * c2;
|
||||
uint32_t a2 = absl::rotr(Fetch32(s + len - 16) * c1, 17) * c2;
|
||||
uint32_t a3 = absl::rotr(Fetch32(s + len - 12) * c1, 17) * c2;
|
||||
uint32_t a4 = absl::rotr(Fetch32(s + len - 20) * c1, 17) * c2;
|
||||
h ^= a0;
|
||||
h = Rotate32(h, 19);
|
||||
h = absl::rotr(h, 19);
|
||||
h = h * 5 + 0xe6546b64;
|
||||
h ^= a2;
|
||||
h = Rotate32(h, 19);
|
||||
h = absl::rotr(h, 19);
|
||||
h = h * 5 + 0xe6546b64;
|
||||
g ^= a1;
|
||||
g = Rotate32(g, 19);
|
||||
g = absl::rotr(g, 19);
|
||||
g = g * 5 + 0xe6546b64;
|
||||
g ^= a3;
|
||||
g = Rotate32(g, 19);
|
||||
g = absl::rotr(g, 19);
|
||||
g = g * 5 + 0xe6546b64;
|
||||
f += a4;
|
||||
f = Rotate32(f, 19);
|
||||
f = absl::rotr(f, 19);
|
||||
f = f * 5 + 0xe6546b64;
|
||||
size_t iters = (len - 1) / 20;
|
||||
do {
|
||||
uint32_t b0 = Rotate32(Fetch32(s) * c1, 17) * c2;
|
||||
uint32_t b0 = absl::rotr(Fetch32(s) * c1, 17) * c2;
|
||||
uint32_t b1 = Fetch32(s + 4);
|
||||
uint32_t b2 = Rotate32(Fetch32(s + 8) * c1, 17) * c2;
|
||||
uint32_t b3 = Rotate32(Fetch32(s + 12) * c1, 17) * c2;
|
||||
uint32_t b2 = absl::rotr(Fetch32(s + 8) * c1, 17) * c2;
|
||||
uint32_t b3 = absl::rotr(Fetch32(s + 12) * c1, 17) * c2;
|
||||
uint32_t b4 = Fetch32(s + 16);
|
||||
h ^= b0;
|
||||
h = Rotate32(h, 18);
|
||||
h = absl::rotr(h, 18);
|
||||
h = h * 5 + 0xe6546b64;
|
||||
f += b1;
|
||||
f = Rotate32(f, 19);
|
||||
f = absl::rotr(f, 19);
|
||||
f = f * c1;
|
||||
g += b2;
|
||||
g = Rotate32(g, 18);
|
||||
g = absl::rotr(g, 18);
|
||||
g = g * 5 + 0xe6546b64;
|
||||
h ^= b3 + b1;
|
||||
h = Rotate32(h, 19);
|
||||
h = absl::rotr(h, 19);
|
||||
h = h * 5 + 0xe6546b64;
|
||||
g ^= b4;
|
||||
g = absl::gbswap_32(g) * 5;
|
||||
@@ -178,26 +173,19 @@ uint32_t CityHash32(const char *s, size_t len) {
|
||||
PERMUTE3(f, h, g);
|
||||
s += 20;
|
||||
} while (--iters != 0);
|
||||
g = Rotate32(g, 11) * c1;
|
||||
g = Rotate32(g, 17) * c1;
|
||||
f = Rotate32(f, 11) * c1;
|
||||
f = Rotate32(f, 17) * c1;
|
||||
h = Rotate32(h + g, 19);
|
||||
g = absl::rotr(g, 11) * c1;
|
||||
g = absl::rotr(g, 17) * c1;
|
||||
f = absl::rotr(f, 11) * c1;
|
||||
f = absl::rotr(f, 17) * c1;
|
||||
h = absl::rotr(h + g, 19);
|
||||
h = h * 5 + 0xe6546b64;
|
||||
h = Rotate32(h, 17) * c1;
|
||||
h = Rotate32(h + f, 19);
|
||||
h = absl::rotr(h, 17) * c1;
|
||||
h = absl::rotr(h + f, 19);
|
||||
h = h * 5 + 0xe6546b64;
|
||||
h = Rotate32(h, 17) * c1;
|
||||
h = absl::rotr(h, 17) * c1;
|
||||
return h;
|
||||
}
|
||||
|
||||
// Bitwise right rotate. Normally this will compile to a single
|
||||
// instruction, especially if the shift is a manifest constant.
|
||||
static uint64_t Rotate(uint64_t val, int shift) {
|
||||
// Avoid shifting by 64: doing so yields an undefined result.
|
||||
return shift == 0 ? val : ((val >> shift) | (val << (64 - shift)));
|
||||
}
|
||||
|
||||
static uint64_t ShiftMix(uint64_t val) { return val ^ (val >> 47); }
|
||||
|
||||
static uint64_t HashLen16(uint64_t u, uint64_t v, uint64_t mul) {
|
||||
@@ -220,8 +208,8 @@ static uint64_t HashLen0to16(const char *s, size_t len) {
|
||||
uint64_t mul = k2 + len * 2;
|
||||
uint64_t a = Fetch64(s) + k2;
|
||||
uint64_t b = Fetch64(s + len - 8);
|
||||
uint64_t c = Rotate(b, 37) * mul + a;
|
||||
uint64_t d = (Rotate(a, 25) + b) * mul;
|
||||
uint64_t c = absl::rotr(b, 37) * mul + a;
|
||||
uint64_t d = (absl::rotr(a, 25) + b) * mul;
|
||||
return HashLen16(c, d, mul);
|
||||
}
|
||||
if (len >= 4) {
|
||||
@@ -248,8 +236,8 @@ static uint64_t HashLen17to32(const char *s, size_t len) {
|
||||
uint64_t b = Fetch64(s + 8);
|
||||
uint64_t c = Fetch64(s + len - 8) * mul;
|
||||
uint64_t d = Fetch64(s + len - 16) * k2;
|
||||
return HashLen16(Rotate(a + b, 43) + Rotate(c, 30) + d,
|
||||
a + Rotate(b + k2, 18) + c, mul);
|
||||
return HashLen16(absl::rotr(a + b, 43) + absl::rotr(c, 30) + d,
|
||||
a + absl::rotr(b + k2, 18) + c, mul);
|
||||
}
|
||||
|
||||
// Return a 16-byte hash for 48 bytes. Quick and dirty.
|
||||
@@ -257,11 +245,11 @@ static uint64_t HashLen17to32(const char *s, size_t len) {
|
||||
static std::pair<uint64_t, uint64_t> WeakHashLen32WithSeeds(
|
||||
uint64_t w, uint64_t x, uint64_t y, uint64_t z, uint64_t a, uint64_t b) {
|
||||
a += w;
|
||||
b = Rotate(b + a + z, 21);
|
||||
b = absl::rotr(b + a + z, 21);
|
||||
uint64_t c = a;
|
||||
a += x;
|
||||
a += y;
|
||||
b += Rotate(a, 44);
|
||||
b += absl::rotr(a, 44);
|
||||
return std::make_pair(a + z, b + c);
|
||||
}
|
||||
|
||||
@@ -284,10 +272,10 @@ static uint64_t HashLen33to64(const char *s, size_t len) {
|
||||
uint64_t f = Fetch64(s + 24) * 9;
|
||||
uint64_t g = Fetch64(s + len - 8);
|
||||
uint64_t h = Fetch64(s + len - 16) * mul;
|
||||
uint64_t u = Rotate(a + g, 43) + (Rotate(b, 30) + c) * 9;
|
||||
uint64_t u = absl::rotr(a + g, 43) + (absl::rotr(b, 30) + c) * 9;
|
||||
uint64_t v = ((a + g) ^ d) + f + 1;
|
||||
uint64_t w = absl::gbswap_64((u + v) * mul) + h;
|
||||
uint64_t x = Rotate(e + f, 42) + c;
|
||||
uint64_t x = absl::rotr(e + f, 42) + c;
|
||||
uint64_t y = (absl::gbswap_64((v + w) * mul) + g) * mul;
|
||||
uint64_t z = e + f + c;
|
||||
a = absl::gbswap_64((x + z) * mul + y) + b;
|
||||
@@ -320,11 +308,11 @@ uint64_t CityHash64(const char *s, size_t len) {
|
||||
// Decrease len to the nearest multiple of 64, and operate on 64-byte chunks.
|
||||
len = (len - 1) & ~static_cast<size_t>(63);
|
||||
do {
|
||||
x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
|
||||
y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
|
||||
x = absl::rotr(x + y + v.first + Fetch64(s + 8), 37) * k1;
|
||||
y = absl::rotr(y + v.second + Fetch64(s + 48), 42) * k1;
|
||||
x ^= w.second;
|
||||
y += v.first + Fetch64(s + 40);
|
||||
z = Rotate(z + w.first, 33) * k1;
|
||||
z = absl::rotr(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);
|
||||
|
||||
Reference in New Issue
Block a user