libcruft-util/hash/murmur/common.cpp

134 lines
4.6 KiB
C++

/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
*/
#include "common.hpp"
#include "../../debug/panic.hpp"
///////////////////////////////////////////////////////////////////////////////
namespace cruft::hash::murmur {
template <>
uint32_t
tail<uint32_t> (const uint8_t *restrict bytes, size_t len)
{
uint32_t h = 0;
switch (len % sizeof (uint32_t)) {
case 3: h += bytes[2] << 16; [[fallthrough]];
case 2: h += bytes[1] << 8; [[fallthrough]];
case 1: h += bytes[0];
break;
default:
unreachable ();
}
return h;
}
}
//-----------------------------------------------------------------------------
namespace cruft::hash::murmur {
template <>
uint64_t
tail<uint64_t> (const uint8_t *restrict bytes, size_t len)
{
uint64_t h = 0;
switch (len % sizeof (uint64_t)) {
case 7: h += uint64_t(bytes[6]) << 48; [[fallthrough]];
case 6: h += uint64_t(bytes[5]) << 40; [[fallthrough]];
case 5: h += uint64_t(bytes[4]) << 32; [[fallthrough]];
case 4: h += uint64_t(bytes[3]) << 24; [[fallthrough]];
case 3: h += uint64_t(bytes[2]) << 16; [[fallthrough]];
case 2: h += uint64_t(bytes[1]) << 8; [[fallthrough]];
case 1: h += uint64_t(bytes[0]);
break;
default:
unreachable ();
}
return h;
}
}
//-----------------------------------------------------------------------------
namespace cruft::hash::murmur {
template <>
std::array<uint32_t,4>
tail_array<uint32_t> (const uint8_t *restrict bytes, size_t len)
{
std::array<uint32_t,4> result {0,0,0,0};
switch (len % 16) {
case 15: result[3] |= bytes[14] << 16; [[fallthrough]];
case 14: result[3] |= bytes[13] << 8; [[fallthrough]];
case 13: result[3] |= bytes[12] << 0; [[fallthrough]];
case 12: result[2] |= bytes[11] << 24; [[fallthrough]];
case 11: result[2] |= bytes[10] << 16; [[fallthrough]];
case 10: result[2] |= bytes[ 9] << 8; [[fallthrough]];
case 9: result[2] |= bytes[ 8] << 0; [[fallthrough]];
case 8: result[1] |= bytes[ 7] << 24; [[fallthrough]];
case 7: result[1] |= bytes[ 6] << 16; [[fallthrough]];
case 6: result[1] |= bytes[ 5] << 8; [[fallthrough]];
case 5: result[1] |= bytes[ 4] << 0; [[fallthrough]];
case 4: result[0] |= bytes[ 3] << 24; [[fallthrough]];
case 3: result[0] |= bytes[ 2] << 16; [[fallthrough]];
case 2: result[0] |= bytes[ 1] << 8; [[fallthrough]];
case 1: result[0] |= bytes[ 0] << 0;
break;
default:
unreachable ();
}
return result;
}
}
//-----------------------------------------------------------------------------
namespace cruft::hash::murmur {
template <>
std::array<uint64_t,2>
tail_array<uint64_t> (const uint8_t *restrict bytes, size_t len)
{
std::array<uint64_t,2> result {0, 0};
switch(len & 15)
{
case 15: result[1] |= uint64_t{bytes[14]} << 48; [[fallthrough]];
case 14: result[1] |= uint64_t{bytes[13]} << 40; [[fallthrough]];
case 13: result[1] |= uint64_t{bytes[12]} << 32; [[fallthrough]];
case 12: result[1] |= uint64_t{bytes[11]} << 24; [[fallthrough]];
case 11: result[1] |= uint64_t{bytes[10]} << 16; [[fallthrough]];
case 10: result[1] |= uint64_t{bytes[ 9]} << 8; [[fallthrough]];
case 9: result[1] |= uint64_t{bytes[ 8]} << 0; [[fallthrough]];
case 8: result[0] |= uint64_t{bytes[ 7]} << 56; [[fallthrough]];
case 7: result[0] |= uint64_t{bytes[ 6]} << 48; [[fallthrough]];
case 6: result[0] |= uint64_t{bytes[ 5]} << 40; [[fallthrough]];
case 5: result[0] |= uint64_t{bytes[ 4]} << 32; [[fallthrough]];
case 4: result[0] |= uint64_t{bytes[ 3]} << 24; [[fallthrough]];
case 3: result[0] |= uint64_t{bytes[ 2]} << 16; [[fallthrough]];
case 2: result[0] |= uint64_t{bytes[ 1]} << 8; [[fallthrough]];
case 1: result[0] |= uint64_t{bytes[ 0]} << 0;
break;
default:
unreachable ();
};
return result;
}
}