FE 0.16.1
Fast, Effecient FrontEnds
Loading...
Searching...
No Matches
hash.h
Go to the documentation of this file.
1#pragma once
2
3#include <concepts>
4#include <cstddef>
5#include <cstdint>
6
7#include <functional>
8#include <string>
9#include <string_view>
10
11#include <ankerl/unordered_dense.h>
12
13namespace fe {
14
15/// Folds @p v into @p seed like `ankerl::unordered_dense` hashes a tuple: one 128-bit multiply, halves xored.
16/// Each step avalanches, so a chain needs no finalizer and suits a hasher that declares `is_avalanching`.
17/// Seed a chain with `0`:
18/// ```
19/// size_t h = 0;
20/// for (auto elem : elems) h = fe::hash_combine(h, elem);
21/// ```
22/// @note These hashes are *not* stable:
23/// they differ between 32- and 64-bit builds and may change between fe releases.
24/// Never serialize them and never rely on the iteration order they induce.
25template<std::integral T>
26constexpr size_t hash_combine(size_t seed, T v) noexcept {
27 constexpr auto Secret = UINT64_C(0x9ddfea08eb382d69);
28 auto a = uint64_t(seed) + uint64_t(v);
29
30 if !consteval {
31 return size_t(ankerl::unordered_dense::detail::hash_impl::mix(a, Secret));
32 } else {
33 uint64_t ha = a >> 32, la = uint32_t(a);
34 uint64_t hb = Secret >> 32, lb = uint32_t(Secret);
35 uint64_t rh = ha * hb, rm0 = ha * lb, rm1 = hb * la, rl = la * lb;
36 uint64_t t = rl + (rm0 << 32);
37 uint64_t c = t < rl;
38 uint64_t lo = t + (rm1 << 32);
39 c += lo < t;
40 uint64_t hi = rh + (rm0 >> 32) + (rm1 >> 32) + c;
41 return size_t(lo ^ hi);
42 }
43}
44
45/// Hashes the characters of a string; transparent, so `std::string` keys may be looked up by `std::string_view`.
46struct StrHash {
47 using is_transparent = void;
48 using is_avalanching = void;
49
50 size_t operator()(std::string_view sv) const noexcept {
51 return ankerl::unordered_dense::hash<std::string_view>()(sv);
52 }
53};
54
55/// @name StrMap/StrSet
56/// Keyed by `std::string` but also looked up by `std::string_view` or `const char*` without building a `std::string`.
57///@{
58template<class V>
59using StrMap = ankerl::unordered_dense::map<std::string, V, StrHash, std::equal_to<>>;
60using StrSet = ankerl::unordered_dense::set<std::string, StrHash, std::equal_to<>>;
61///@}
62
63} // namespace fe
Definition algo.h:17
ankerl::unordered_dense::map< std::string, V, StrHash, std::equal_to<> > StrMap
Definition hash.h:59
ankerl::unordered_dense::set< std::string, StrHash, std::equal_to<> > StrSet
Definition hash.h:60
constexpr size_t hash_combine(size_t seed, T v) noexcept
Folds v into seed like ankerl::unordered_dense hashes a tuple: one 128-bit multiply,...
Definition hash.h:26
Hashes the characters of a string; transparent, so std::string keys may be looked up by std::string_v...
Definition hash.h:46
size_t operator()(std::string_view sv) const noexcept
Definition hash.h:50
void is_transparent
Definition hash.h:47
void is_avalanching
Definition hash.h:48