1#ifndef HYPERTRIE_MARTINUS_ROBINHOOD_HASH_HPP
2#define HYPERTRIE_MARTINUS_ROBINHOOD_HASH_HPP
38#include <initializer_list>
41namespace dice::hash::martinus {
43 inline constexpr std::size_t m = 0xc6a4a7935bd1e995UL;
44 inline constexpr std::size_t seed = 0xe17a1465UL;
45 inline constexpr unsigned int r = 47;
49 inline T unaligned_load(
void const *ptr)
noexcept {
53 std::memcpy(&t, ptr,
sizeof(T));
58 inline T rotr(T x,
unsigned k) {
59 return (x >> k) | (x << (8U *
sizeof(T) - k));
62 inline std::size_t hash_bytes(
void const *ptr, std::size_t len)
noexcept {
65 static constexpr unsigned int r = 47;
67 auto const *
const data64 =
static_cast<uint64_t
const *
>(ptr);
68 uint64_t h = seed ^ (len * m);
70 size_t const n_blocks = len / 8;
71 for (std::size_t i = 0; i < n_blocks; ++i) {
72 auto k = unaligned_load<uint64_t>(data64 + i);
82 auto const *
const data8 =
reinterpret_cast<uint8_t
const *
>(data64 + n_blocks);
85 h ^=
static_cast<uint64_t
>(data8[6]) << 48U;
88 h ^=
static_cast<uint64_t
>(data8[5]) << 40U;
91 h ^=
static_cast<uint64_t
>(data8[4]) << 32U;
94 h ^=
static_cast<uint64_t
>(data8[3]) << 24U;
97 h ^=
static_cast<uint64_t
>(data8[2]) << 16U;
100 h ^=
static_cast<uint64_t
>(data8[1]) << 8U;
103 h ^=
static_cast<uint64_t
>(data8[0]);
113 return static_cast<size_t>(h);
116 inline std::size_t hash_combine(std::initializer_list<size_t> hashes) {
119 uint64_t h = seed ^ (hashes.size() * m);
121 for (
auto k : hashes) {
133 return static_cast<size_t>(h);
141 explicit HashState(uint64_t size) : h(seed ^ (size * m)) {}
143 void add(std::size_t hash)
noexcept {
152 [[nodiscard]] std::size_t digest()
const noexcept {
157 return static_cast<size_t>(hash);
161 inline std::size_t hash_int(uint64_t x)
noexcept {
169 auto h1 = x * 0xA24BAED4963EE407UL;
170 auto h2 = rotr(x, 32U) * 0x9FB21C651E98DF25UL;
171 auto h = rotr(h1 + h2, 32U);
172 return static_cast<size_t>(h);
Definition martinus_robinhood_hash.hpp:136