87 lines
2.4 KiB
C++
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
|