#include "CityHash.hpp"
#include <time.h>
#include <stdint.h>
#include <string.h>
#include "../common/compat.hpp"
#ifndef __BIG_ENDIAN__
#define INORDER32(x) (x)
#define INORDER64(x) (x)
#else
#ifdef _WIN32
# include <stdlib.h>
# define bswap_32(x) _byteswap_ulong(x)
# define bswap_64(x) _byteswap_uint64(x)
#elif defined(__APPLE__)
# include <libkern/OSByteOrder.h>
# define bswap_32(x) OSSwapInt32(x)
# define bswap_64(x) OSSwapInt64(x)
#else
# include <byteswap.h>
#endif
#define INORDER32(x) (bswap_32(x))
#define INORDER64(x) (bswap_64(x))
#endif // __BIG_ENDIAN__
namespace sprawl
{
namespace cityhash
{
namespace CityHashStatic
{
struct uint128_t
{
uint64_t first;
uint64_t second;
uint128_t(uint64_t first_, uint64_t second_)
: first(first_)
, second(second_)
{
//
}
};
static const uint64_t k0 = 0xc3a5c85c97cb3127ULL;
static const uint64_t k1 = 0xb492b66fbe98f273ULL;
static const uint64_t k2 = 0x9ae16a3b2f90404fULL;
static const uint64_t k3 = 0xc949d7c7509e6557ULL;
static inline uint64_t LoadUnaligned_32(const char *p)
{
uint64_t result;
memcpy(&result, p, sizeof(result));
return result;
}
static inline uint64_t LoadUnaligned_64(const char *p)
{
uint32_t result;
memcpy(&result, p, sizeof(result));
return result;
}
static inline uint64_t Fetch64(const char *p)
{
return INORDER64(LoadUnaligned_64(p));
}
static inline uint32_t Fetch32(const char *p)
{
return INORDER32(LoadUnaligned_32(p));
}
static inline uint64_t Rotate(uint64_t val, int shift)
{
return shift == 0 ? val : ((val >> shift) | (val << (64 - shift)));
}
static inline uint64_t RotateByAtLeastOne(uint64_t val, int shift)
{
return (val >> shift) | (val << (64 - shift));
}
static inline uint64_t ShiftMix(uint64_t val)
{
return val ^ (val >> 47);
}
static inline uint64_t Hash128to64(uint128_t const& x)
{
const uint64_t kMul = 0x9ddfea08eb382d69ULL;
uint64_t a = (x.first ^ x.second) * kMul;
a ^= (a >> 47);
uint64_t b = (x.second ^ a) * kMul;
b ^= (b >> 47);
b *= kMul;
return b;
}
static inline uint64_t Hash16(uint64_t u, uint64_t v)
{
return Hash128to64(uint128_t(u, v));
}
static uint64_t Hash0to16(char const* const data, size_t length)
{
if(length > 8)
{
uint64_t a = Fetch64(data);
uint64_t b = Fetch64(data + length - 8);
return Hash16(a, RotateByAtLeastOne(b + length, length)) ^ b;
}
if(length >= 4)
{
uint64_t a = Fetch32(data);
return Hash16(length + (a << 3), Fetch32(data + length - 4));
}
if(length > 0)
{
uint8_t a = data[0];
uint8_t b = data[length >> 1];
uint8_t c = data[length - 1];
uint32_t y = static_cast<uint32_t>(a) + (static_cast<uint32_t>(b) << 8);
uint32_t z = length + (static_cast<uint32_t>(c) << 2);
return ShiftMix(y * k2 ^ z * k3) * k2;
}
return k2;
}
static uint64_t Hash17to32(char const* const data, size_t length)
{
uint64_t a = Fetch64(data) * k1;
uint64_t b = Fetch64(data + 8);
uint64_t c = Fetch64(data + length - 8) * k2;
uint64_t d = Fetch64(data + length - 16) * k0;
return Hash16(Rotate(a - b, 43) + Rotate(c, 30) + d, a + Rotate(b ^ k3, 20) - c + length);
}
static uint64_t Hash33to64(char const* const data, size_t length)
{
uint64_t z = Fetch64(data + 24);
uint64_t a = Fetch64(data) + (length + Fetch64(data + length - 16)) * k0;
uint64_t b = Rotate(a + z, 52);
uint64_t c = Rotate(a, 37);
a += Fetch64(data + 8);
c += Rotate(a, 7);
a += Fetch64(data + 16);
uint64_t vf = a + z;
uint64_t vs = b + Rotate(a, 31) + c;
a = Fetch64(data + 16) + Fetch64(data + length - 32);
z = Fetch64(data + length - 8);
b = Rotate(a + z, 52);
c = Rotate(a, 37);
a += Fetch64(data + length - 24);
c += Rotate(a, 7);
a += Fetch64(data + length - 16);
uint64_t wf = a + z;
uint64_t ws = b + Rotate(a, 31) + c;
uint64_t r = ShiftMix((vf + ws) * k2 + (wf + vs) * k0);
return ShiftMix(r * k0 + vs) * k2;
}
static inline uint128_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);
uint64_t c = a;
a += x;
a += y;
b += Rotate(a, 44);
return uint128_t(a + z, b + c);
}
static inline uint128_t WeakHashLen32WithSeeds(char const* const data, uint64_t a, uint64_t b)
{
return WeakHashLen32WithSeeds(
Fetch64(data),
Fetch64(data + 8),
Fetch64(data + 16),
Fetch64(data + 24),
a,
b
);
}
}
size_t Hash(void const* data, size_t length)
{
const char* data_ = static_cast<char const*>(data);
if(length <= 32)
{
if(length <= 16)
{
return CityHashStatic::Hash0to16(data_, length);
}
return CityHashStatic::Hash17to32(data_, length);
}
else if(length <= 64)
{
return CityHashStatic::Hash33to64(data_, length);
}
uint64_t x = CityHashStatic::Fetch64(data_ + length - 40);
uint64_t y = CityHashStatic::Fetch64(data_ + length - 16) + CityHashStatic::Fetch64(data_ + length - 56);
uint64_t z = CityHashStatic::Hash16(CityHashStatic::Fetch64(data_ + length - 48) + length, CityHashStatic::Fetch64(data_ + length - 24));
CityHashStatic::uint128_t v = CityHashStatic::WeakHashLen32WithSeeds(data_ + length - 64, length, z);
CityHashStatic::uint128_t w = CityHashStatic::WeakHashLen32WithSeeds(data_ + length - 32, y + CityHashStatic::k1, x);
x = x * CityHashStatic::k1 + CityHashStatic::Fetch64(data_);
length = (length - 1) & ~static_cast<size_t>(63);
do
{
x = CityHashStatic::Rotate(x + y + v.first + CityHashStatic::Fetch64(data_ + 8), 37) * CityHashStatic::k1;
y = CityHashStatic::Rotate(y + v.second + CityHashStatic::Fetch64(data_ + 48), 42) * CityHashStatic::k1;
x ^= w.second;
y += v.first + CityHashStatic::Fetch64(data_ + 40);
z = CityHashStatic::Rotate(z + w.first, 33) * CityHashStatic::k1;
v = CityHashStatic::WeakHashLen32WithSeeds(data_, v.second * CityHashStatic::k1, x + w.first);
w = CityHashStatic::WeakHashLen32WithSeeds(data_ + 32, z + w.second, y + CityHashStatic::Fetch64(data_ + 16));
uint64_t temp = z;
z = x;
x = temp;
data_ += 64;
length -= 64;
} while (length != 0);
return CityHashStatic::Hash16(CityHashStatic::Hash16(v.first, w.first) + CityHashStatic::ShiftMix(y) * CityHashStatic::k1 + z, CityHashStatic::Hash16(v.second, w.second) + x);
}
}
}
| # | Change | User | Description | Committed | |
|---|---|---|---|---|---|
| #3 | 19906 | ShadauxCat |
- Added tag, compile time string type - Since tag requires visual studio 2015, removed compatibility code for earlier versions of visual studio - Improved compiler detection - Added endianness detection - Added template if/else helper - Fixed bug with murmur3 64 bit - Added seed argument for murmur3 #review-19907 |
||
| #2 | 14783 | ShadauxCat |
Style corrections (placement of const) #review-14784 |
||
| #1 | 11496 | ShadauxCat | Initial checkin: Current states for csbuild and libSprawl |