Skip to content

Instantly share code, notes, and snippets.

@elw00d
Created October 4, 2019 12:09
Show Gist options
  • Save elw00d/3c07e5985ec6a097d68ae6e87ce5695b to your computer and use it in GitHub Desktop.
Save elw00d/3c07e5985ec6a097d68ae6e87ce5695b to your computer and use it in GitHub Desktop.
namespace
{
inline std::size_t
unaligned_load(const char* p)
{
std::size_t result;
__builtin_memcpy(&result, p, sizeof(result));
return result;
}
#if __SIZEOF_SIZE_T__ == 8
// Loads n bytes, where 1 <= n < 8.
inline std::size_t
load_bytes(const char* p, int n)
{
std::size_t result = 0;
--n;
do
result = (result << 8) + static_cast<unsigned char>(p[n]);
while (--n >= 0);
return result;
}
inline std::size_t
shift_mix(std::size_t v)
{ return v ^ (v >> 47);}
#endif
}
size_t
my_Hash_bytes(const void* ptr, size_t len, size_t seed)
{
static const size_t mul = (((size_t) 0xc6a4a793UL) << 32UL)
+ (size_t) 0x5bd1e995UL;
const char* const buf = static_cast<const char*>(ptr);
// Remove the bytes not divisible by the sizeof(size_t). This
// allows the main loop to process the data as 64-bit integers.
const int len_aligned = len & ~0x7;
const char* const end = buf + len_aligned;
size_t hash = seed ^ (len * mul);
for (const char* p = buf; p != end; p += 8)
{
const size_t data = shift_mix(unaligned_load(p) * mul) * mul;
hash ^= data;
hash *= mul;
}
if ((len & 0x7) != 0)
{
const size_t data = load_bytes(end, len & 0x7);
hash ^= data;
hash *= mul;
}
hash = shift_mix(hash) * mul;
hash = shift_mix(hash);
return hash;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment