2#include <ossia/detail/config.hpp>
17OSSIA_INLINE
inline uint64_t hash_bytes(
const void* data, std::size_t size)
noexcept;
18OSSIA_INLINE
inline uint64_t hash_string(std::string_view sv)
noexcept;
20OSSIA_INLINE
inline uint64_t hash_trivial(
const T& v)
noexcept;
24 using is_transparent = std::true_type;
25 using is_avalanching = std::true_type;
26 std::size_t operator()(
const std::string& s)
const noexcept
28 return hash_string(std::string_view{s});
31 std::size_t operator()(std::string_view s)
const noexcept
33 return hash_string(s);
36 template <std::
size_t N>
37 std::size_t operator()(
const char (&s)[N])
const noexcept
39 return hash_string(std::string_view{s, N - 1});
46 using is_transparent = std::true_type;
49 OSSIA_INLINE OSSIA_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK std::size_t
50 operator()(
const T* val)
const noexcept
52 static const constexpr std::size_t shift = constexpr_log2(1 +
sizeof(T));
53 return (
size_t)(val) >> shift;
57 OSSIA_INLINE OSSIA_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK std::size_t
58 operator()(
const std::shared_ptr<T>& val)
const noexcept
60 static const constexpr std::size_t shift = constexpr_log2(1 +
sizeof(T));
61 return (
size_t)(val.get()) >> shift;
65template <std::
size_t ApproximateObjectSizeof>
66struct unknown_pointer_hash
68 using is_transparent = std::true_type;
71 OSSIA_INLINE OSSIA_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK std::size_t
72 operator()(
const T* val)
const noexcept
74 static const constexpr std::size_t shift
75 = constexpr_log2(1 + ApproximateObjectSizeof);
76 return (
size_t)(val) >> shift;
80 OSSIA_INLINE OSSIA_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK std::size_t
81 operator()(
const std::shared_ptr<T>& val)
const noexcept
83 static const constexpr std::size_t shift
84 = constexpr_log2(1 + ApproximateObjectSizeof);
85 return (
size_t)(val.get()) >> shift;
89template<
typename T>
struct is_shared_ptr : std::false_type {};
90template<
typename T>
struct is_shared_ptr<std::shared_ptr<T>> : std::true_type {};
92struct pointer_hash_rapid
94 using is_transparent = std::true_type;
95 using is_avalanching = std::true_type;
97 OSSIA_INLINE uint64_t operator()(
const T* val)
const noexcept
99 const uintptr_t p =
reinterpret_cast<uintptr_t
>(val);
100 return hash_trivial(p);
103 template <
typename T>
104 OSSIA_INLINE uint64_t operator()(
const std::shared_ptr<T>& val)
const noexcept
106 const uintptr_t p =
reinterpret_cast<uintptr_t
>(val.get());
107 return hash_trivial(p);
114concept has_std_hash =
requires(
const T& v) {
115 { std::hash<T>{}(v) } -> std::convertible_to<std::size_t>;
118concept has_std_hash_avalanching
119 = has_std_hash<T> &&
requires {
typename std::hash<T>::is_avalanching; };
124 OSSIA_INLINE std::size_t operator()(
const T& v)
const
125 noexcept(
noexcept(std::declval<std::hash<T>>()(std::declval<const T&>())))
128 detail_hash::has_std_hash<T>,
129 "ossia::hash<T>: T is not trivially copyable and has no "
130 "std::hash<T> specialization. Specialize ossia::hash<T> "
131 "(see string_hash / pointer_hash_rapid for reference) or "
132 "provide std::hash<T>.");
133 return std::hash<T>{}(v);
137requires std::is_trivially_copyable_v<T>
138 && (!std::is_pointer_v<T>)
139 && (!is_shared_ptr<T>::value)
142 using is_transparent = std::true_type;
143 using is_avalanching = std::true_type;
144 OSSIA_INLINE uint64_t operator()(
const T& v)
const noexcept
146 return hash_trivial(v);
151requires (!std::is_trivially_copyable_v<T>)
152 && (!std::is_pointer_v<T>)
153 && (!is_shared_ptr<T>::value)
154 && (!std::is_same_v<T, std::string>)
155 && (!std::is_same_v<T, std::string_view>)
156 && detail_hash::has_std_hash_avalanching<T>
159 using is_avalanching = std::true_type;
161 OSSIA_INLINE std::size_t operator()(
const T& v)
const
162 noexcept(
noexcept(std::declval<std::hash<T>>()(std::declval<const T&>())))
164 return std::hash<T>{}(v);
169requires std::is_pointer_v<T>
170struct hash<T> : pointer_hash_rapid { };
173requires is_shared_ptr<T>::value
174struct hash<T> : pointer_hash_rapid { };
177struct hash<std::string> : string_hash { };
179struct hash<std::string_view> : string_hash { };
183struct hash<const char*>;
191 using is_transparent = std::true_type;
192 bool operator()(
const std::string& s,
const std::string& s2)
const noexcept
196 bool operator()(std::string_view s,
const std::string& s2)
const noexcept
200 bool operator()(
const std::string& s, std::string_view s2)
const noexcept
204 bool operator()(std::string_view s, std::string_view s2)
const noexcept
209 template <std::
size_t N>
210 bool operator()(
const std::string& s,
const char (&s2)[N])
const noexcept
212 return operator()(s, std::string_view{s2, N-1});
215 template <std::
size_t N>
216 bool operator()(std::string_view s,
const char (&s2)[N])
const noexcept
218 return operator()(s, std::string_view{s2, N-1});
221 template <std::
size_t N>
222 bool operator()(
const char (&s)[N],
const std::string& s2)
const noexcept
224 return operator()(std::string_view{s, N-1}, s2);
227 template <std::
size_t N>
228 bool operator()(
const char (&s)[N], std::string_view s2)
const noexcept
230 return operator()(std::string_view{s, N-1}, s2);
237 using is_transparent = std::true_type;
238 template<
typename U,
typename V>
240 bool operator()(
const U* lhs,
const V* rhs)
const noexcept {
return lhs == rhs; }
242 template<
typename U,
typename V>
244 bool operator()(
const std::shared_ptr<U>& lhs,
const V* rhs)
const noexcept
246 return lhs.get() == rhs;
249 template<
typename U,
typename V>
251 bool operator()(
const U* lhs,
const std::shared_ptr<V>& rhs)
const noexcept
253 return lhs == rhs.get();
256 template<
typename U,
typename V>
259 operator()(
const std::shared_ptr<U>& lhs,
const std::shared_ptr<V>& rhs)
const noexcept
266struct equal_to : std::equal_to<T> { };
269struct equal_to<std::string> : string_equal { };
271struct equal_to<std::string_view> : string_equal { };
274requires std::is_pointer_v<T>
275struct equal_to<T> : pointer_equal { };
278requires is_shared_ptr<T>::value
279struct equal_to<T> : pointer_equal { };
281OSSIA_INLINE
inline uint64_t hash_bytes(
const void* data, std::size_t size)
noexcept
283 return rapidhashMicro(data, size);
286OSSIA_INLINE
inline uint64_t hash_trivial(
const T& v)
noexcept
288 static_assert(std::is_trivially_copyable_v<T>,
289 "hash_trivial requires trivially copyable T");
290 if constexpr(
sizeof(T) <= 48)
291 return rapidhashNano(&v,
sizeof(T));
292 else if constexpr(
sizeof(T) <= 80)
293 return rapidhashMicro(&v,
sizeof(T));
295 return rapidhash(&v,
sizeof(T));
297OSSIA_INLINE
inline uint64_t hash_string(std::string_view sv)
noexcept
299 return rapidhashMicro(sv.data(), sv.size());
303OSSIA_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
constexpr inline void
304hash_combine(std::size_t& seed,
const T& k)
noexcept
307 seed ^= hash<T>{}(k) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
311OSSIA_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
constexpr inline void
312hash_combine(std::size_t& seed,
const T* k)
noexcept
315 seed ^= egur_hash{}(k) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
318OSSIA_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
319constexpr inline void hash_combine(uint64_t& seed, uint8_t k)
noexcept
321 seed ^= k + 0x9e3779b9 + (seed << 6) + (seed >> 2);
324OSSIA_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
325constexpr inline void hash_combine(uint64_t& seed, int8_t k)
noexcept
327 seed ^= k + 0x9e3779b9 + (seed << 6) + (seed >> 2);
330OSSIA_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
331constexpr inline void hash_combine(uint64_t& seed, uint16_t k)
noexcept
333 seed ^= k + 0x9e3779b9 + (seed << 6) + (seed >> 2);
336OSSIA_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
337constexpr inline void hash_combine(uint64_t& seed, int16_t k)
noexcept
339 seed ^= k + 0x9e3779b9 + (seed << 6) + (seed >> 2);
342OSSIA_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
343constexpr inline void hash_combine(uint64_t& seed, uint32_t k)
noexcept
345 seed ^= k + 0x9e3779b9 + (seed << 6) + (seed >> 2);
348OSSIA_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
349constexpr inline void hash_combine(uint64_t& seed, int32_t k)
noexcept
351 seed ^= k + 0x9e3779b9 + (seed << 6) + (seed >> 2);
354OSSIA_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
355constexpr inline void hash_combine(uint64_t& seed, int64_t k)
noexcept
357 seed ^= k + 0x9e3779b9 + (seed << 6) + (seed >> 2);
360OSSIA_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
361constexpr inline void hash_combine(uint32_t& seed, uint8_t k)
noexcept
363 seed ^= k + 0x9e3779b9 + (seed << 6) + (seed >> 2);
366OSSIA_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
367constexpr inline void hash_combine(uint32_t& seed, int8_t k)
noexcept
369 seed ^= k + 0x9e3779b9 + (seed << 6) + (seed >> 2);
372OSSIA_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
373constexpr inline void hash_combine(uint32_t& seed, uint16_t k)
noexcept
375 seed ^= k + 0x9e3779b9 + (seed << 6) + (seed >> 2);
378OSSIA_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
379constexpr inline void hash_combine(uint32_t& seed, int16_t k)
noexcept
381 seed ^= k + 0x9e3779b9 + (seed << 6) + (seed >> 2);
384OSSIA_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
385constexpr inline void hash_combine(uint32_t& seed, int32_t k)
noexcept
387 seed ^= k + 0x9e3779b9 + (seed << 6) + (seed >> 2);
390OSSIA_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
391constexpr inline void hash_combine(uint32_t& seed, uint64_t k)
noexcept
393 seed ^= k + 0x9e3779b9 + (seed << 6) + (seed >> 2);
396OSSIA_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
397constexpr inline void hash_combine(uint32_t& seed, int64_t k)
noexcept
399 seed ^= k + 0x9e3779b9 + (seed << 6) + (seed >> 2);
402OSSIA_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
403constexpr inline void hash_combine(uint32_t& h1, uint32_t k1)
noexcept
405 constexpr auto rotl32
406 = [](uint32_t x, int8_t r)
noexcept {
return (x << r) | (x >> (32 - r)); };
408 constexpr uint32_t c1 = 0xcc9e2d51;
409 constexpr uint32_t c2 = 0x1b873593;
417 h1 = h1 * 5 + 0xe6546b64;
420OSSIA_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
421constexpr inline void hash_combine(uint64_t& h, uint64_t k)
noexcept
423 constexpr auto m = UINT64_C(0xc6a4a7935bd1e995);
424 constexpr int r = 47;