Files
snipplib/include/snipplib/utils/snplib_hash.h
2026-09-18 09:48:11 +03:00

87 lines
2.4 KiB
C++

#pragma once
#include <iterator>
#include "../concepts/snplib_concepts.h"
namespace snplib
{
template <snplib_input_char_range_c R>
static constexpr size_t hash_FNV1a(const R& r)
{
static_assert(sizeof(size_t) == 8 || sizeof(size_t) == 4, "The ONLY 32 or 64-bit std::size_t are supported!!!");
size_t hash = 0, prime = 0;
if constexpr (sizeof(size_t) == 8) { // 64-bit
prime = 1099511628211UL;
hash = 14695981039346656037UL;
} else if constexpr (sizeof(size_t) == 4) { // 32-bit
prime = 16777619;
hash = 2166136261;
}
for (const char& ch : r) {
hash ^= ch;
hash *= prime;
}
return hash;
}
static constexpr size_t hash_FNV1a(std::forward_iterator auto begin, std::sentinel_for<decltype(begin)> auto end)
requires std::same_as<std::remove_cv_t<std::iter_value_t<decltype(begin)>>, char>
{
static_assert(sizeof(size_t) == 8 || sizeof(size_t) == 4, "The ONLY 32 or 64-bit std::size_t are supported!!!");
size_t hash = 0, prime = 0;
if constexpr (sizeof(size_t) == 8) { // 64-bit
prime = 1099511628211UL;
hash = 14695981039346656037UL;
} else if constexpr (sizeof(size_t) == 4) { // 32-bit
prime = 16777619;
hash = 2166136261;
}
for (auto it = begin; it != end; ++it) {
hash ^= *it;
hash *= prime;
}
return hash;
}
// Boost implementation of hash combining
template <snplib_hashable_c T, snplib_hashable_c... Ts>
static constexpr void snplib_hash_combine(std::size_t& seed, const T& v, Ts&&... vs)
{
static constexpr auto digits = std::numeric_limits<std::size_t>::digits;
static_assert(digits == 64 || digits == 32, "The ONLY 32 or 64-bit std::size_t are supported!!!");
if constexpr (digits == 64) {
std::size_t x = seed + 0x9e3779b9 + std::hash<T>()(v);
const std::size_t m = 0xe9846af9b1a615d;
x ^= x >> 32;
x *= m;
x ^= x >> 32;
x *= m;
x ^= x >> 28;
seed = x;
} else { // 32-bits
std::size_t x = seed + 0x9e3779b9 + std::hash<T>()(v);
const std::size_t m1 = 0x21f0aaad;
const std::size_t m2 = 0x735a2d97;
x ^= x >> 16;
x *= m1;
x ^= x >> 15;
x *= m2;
x ^= x >> 15;
seed = x;
}
if constexpr (sizeof...(Ts)) {
snplib_hash_combine(seed, std::forward<Ts>(vs)...);
}
}
} // namespace snplib