1#pragma once
2
3#include <functional>
4#include <stddef.h>
5
6namespace taichi::hashing {
7
8template <typename T>
9struct Hasher {
10 public:
11 size_t operator()(T const &val) const {
12 return std::hash<T>{}(val);
13 }
14};
15
16namespace {
17template <typename T>
18inline size_t hash_value(T const &value) {
19 return Hasher<T>{}(value);
20}
21
22template <typename T>
23inline void hash_combine(size_t &seed, T const &value) {
24 // Reference:
25 // https://www.boost.org/doc/libs/1_55_0/doc/html/hash/reference.html#boost.hash_combine
26 seed ^= hash_value(value) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
27}
28} // namespace
29
30template <typename T>
31struct Hasher<std::vector<T>> {
32 public:
33 size_t operator()(std::vector<T> const &vec) const {
34 size_t ret = 0;
35 for (const auto &i : vec) {
36 hash_combine(ret, i);
37 }
38 return ret;
39 }
40};
41
42template <typename T1, typename T2>
43struct Hasher<std::pair<T1, T2>> {
44 public:
45 size_t operator()(std::pair<T1, T2> const &val) const {
46 size_t ret = hash_value(val.first);
47 hash_combine(ret, val.second);
48 return ret;
49 }
50};
51
52namespace {
53template <int N, typename... Ts>
54struct TupleHasher {
55 size_t operator()(std::tuple<Ts...> const &val) {
56 size_t ret = TupleHasher<N - 1, Ts...>{}(val);
57 hash_combine(ret, std::get<N>(val));
58 return ret;
59 }
60};
61
62template <typename... Ts>
63struct TupleHasher<0, Ts...> {
64 size_t operator()(std::tuple<Ts...> const &val) {
65 return hash_value(std::get<0>(val));
66 }
67};
68} // namespace
69
70template <typename... Ts>
71struct Hasher<std::tuple<Ts...>> {
72 public:
73 size_t operator()(std::tuple<Ts...> const &val) const {
74 return TupleHasher<std::tuple_size_v<std::tuple<Ts...>> - 1, Ts...>{}(val);
75 };
76};
77
78} // namespace taichi::hashing
79