3#include <clingo/util/immutable_array.hh>
4#include <clingo/util/immutable_value.hh>
5#include <clingo/util/small_vector.hh>
19namespace CppClingo::Util {
25inline auto hash_mix(
size_t h) -> size_t;
28template <
class... T>
inline auto hash_combine(T... a) -> size_t;
31auto value_hash(std::type_info
const &x) -> size_t;
34template <
class T>
auto value_hash(T
const &x) -> size_t;
37template <
class T>
auto value_hash(T *x) -> size_t;
40template <
class T>
auto value_hash(std::optional<T>
const &x) -> size_t;
43template <
class T>
auto value_hash(std::reference_wrapper<T>
const &x) -> size_t;
46template <
class T,
class D>
auto value_hash(std::unique_ptr<T, D>
const &x) -> size_t;
49template <
class T>
auto value_hash(immutable_value<T>
const &x) -> size_t;
52template <
class T,
class U>
auto value_hash(std::pair<T, U>
const &x) -> size_t;
55template <
class... T>
auto value_hash(std::tuple<T...>
const &x) -> size_t;
58template <
class... T>
auto value_hash(std::variant<T...>
const &x) -> size_t;
61template <
class T,
size_t E>
auto value_hash(std::span<T, E>
const &x) -> size_t;
64template <
class T,
class A>
auto value_hash(std::vector<T, A>
const &x) -> size_t;
67template <
class T>
auto value_hash(Util::immutable_array<T>
const &x) -> size_t;
70template <
class T,
size_t N>
auto value_hash(Util::small_vector<T, N>
const &x) -> size_t;
76auto value_hash(std::string_view
const &x) -> size_t;
79auto value_hash(std::string
const &x) -> size_t;
85template <
class T,
class... Args>
auto value_hash_record(Args
const &...x) -> size_t;
99 template <
class T,
class U>
auto operator()(T
const &a, U
const &b)
const ->
bool {
return a == b; }
101 auto operator()(
char const *a,
char const *b)
const ->
bool {
return std::strcmp(a, b) == 0; }
103 template <
class T,
class U>
104 auto operator()(std::reference_wrapper<T>
const &a, std::reference_wrapper<U>
const &b)
const ->
bool {
108 template <
class T,
class U>
auto operator()(std::optional<T>
const &a, std::optional<U>
const &b)
const ->
bool {
109 return (!a && !b) || (a && b &&
operator()(*a, *b));
112 template <
class T,
class U>
auto operator()(T *a, U *b)
const ->
bool {
113 return a == b || (a !=
nullptr && b !=
nullptr &&
operator()(*a, *b));
116 template <
class T,
class D,
class U,
class E>
117 auto operator()(std::unique_ptr<T, D>
const &a, std::unique_ptr<U, E>
const &b)
const ->
bool {
121 template <
class T,
class U,
class V,
class W>
122 auto operator()(std::pair<T, U>
const &a, std::pair<V, W>
const &b)
const ->
bool {
126 template <
class... T,
class... U>
127 auto operator()(std::tuple<T...>
const &a, std::tuple<U...>
const &b)
const ->
bool {
128 static_assert(
sizeof...(T) ==
sizeof...(U));
129 return [&,
this]<
size_t... I>([[maybe_unused]] std::index_sequence<I...> seq) {
130 return (this->
operator()(std::get<I>(a), std::get<I>(b)) && ...);
131 }(std::index_sequence_for<T...>());
134 template <
class... T,
class... U>
135 auto operator()(std::variant<T...>
const &a, std::variant<U...>
const &b)
const ->
bool {
136 static_assert(
sizeof...(T) ==
sizeof...(U));
138 return i == b.index() && [&,
this]<
size_t... I>([[maybe_unused]] std::index_sequence<I...> seq) {
139 return ((i == I && this->
operator()(std::get<I>(a), std::get<I>(b))) || ...);
140 }(std::index_sequence_for<T...>());
143 template <
class T,
size_t E,
class U,
size_t F>
144 auto operator()(std::span<T, E>
const &a, std::span<U, F>
const &b)
const ->
bool {
145 return std::equal(a.begin(), a.end(), b.begin(), b.end(), *
this);
148 template <
class T,
class A,
class U,
class B>
149 auto operator()(std::vector<T, A>
const &a, std::vector<U, B>
const &b)
const ->
bool {
150 return std::equal(a.begin(), a.end(), b.begin(), b.end(), *
this);
176 template <
class T>
auto operator()(T
const *a, T
const *b)
const ->
bool {
177 return value_equal_to{}(std::span(a, size_), std::span(b, size_));
188inline auto hash_combine() ->
size_t {
192inline auto hash_combine(
size_t a) ->
size_t {
196inline auto hash_combine(
size_t seed,
size_t h) ->
size_t {
198 if constexpr (
sizeof(size_t) ==
sizeof(uint64_t)) {
199 seed *= 0x87c37b91114253d5;
200 seed = (seed >> 31) | (seed << 33);
201 seed *= 0x4cf5ad432745937f;
203 seed = (seed >> 27) | (seed << 37);
204 seed = (seed * 5) + 0x52dce729;
207 seed = (seed >> 17) | (seed << 15);
210 seed = (seed >> 19) | (seed << 13);
211 seed = (seed * 5) + 0xe6546b64;
217template <
class... T>
inline auto hash_combine(
size_t a,
size_t b, T... c) ->
size_t {
225 if constexpr (
sizeof(size_t) ==
sizeof(uint64_t)) {
227 h *= 0xff51afd7ed558ccd;
229 h *= 0xc4ceb9fe1a85ec53;
243 return Detail::hash_combine(a...);
250 auto small = []<std::size_t... n>(std::index_sequence<n...>,
auto const &x) {
255 return small(std::make_index_sequence<0>(), x);
257 return small(std::make_index_sequence<1>(), x);
259 return small(std::make_index_sequence<2>(), x);
261 return small(std::make_index_sequence<3>(), x);
263 return small(std::make_index_sequence<4>(), x);
265 return small(std::make_index_sequence<5>(), x);
267 return small(std::make_index_sequence<6>(), x);
269 return small(std::make_index_sequence<7>(), x);
271 return small(std::make_index_sequence<8>(), x);
273 return std::accumulate(
275 [](
auto const &seed,
auto const &x) { return Util::hash_combine(seed, Util::value_hash(x)); });
285 if constexpr (
requires { x.hash(); }) {
287 }
else if constexpr (std::is_arithmetic_v<T> || std::is_enum_v<T>) {
290 return std::hash<T>{}(x);
301template <
class T>
auto value_hash(std::optional<T>
const &x) ->
size_t {
308template <
class T>
auto value_hash(std::reference_wrapper<T>
const &x) ->
size_t {
312template <
class T,
class D>
auto value_hash(std::unique_ptr<T, D>
const &x) ->
size_t {
326template <
class T,
class U>
auto value_hash(std::pair<T, U>
const &x) ->
size_t {
330template <
class... T>
auto value_hash(std::tuple<T...>
const &x) ->
size_t {
331 return [&x]<
size_t... Indices>([[maybe_unused]] std::index_sequence<Indices...> indices) ->
size_t {
333 }(std::index_sequence_for<T...>{});
336template <
class... T>
auto value_hash(std::variant<T...>
const &x) ->
size_t {
340template <
class T,
size_t E>
auto value_hash(std::span<T, E>
const &x) ->
size_t {
344template <
class T,
class A>
auto value_hash(std::vector<T, A>
const &x) ->
size_t {
357 return std::hash<std::string_view>{}(x);
361 return std::hash<std::string_view>{}(x);
365 return std::hash<std::string_view>{}(x);
372static constexpr unsigned int default_neighborhood_size = 62;
Hasher for arrays of dynamic but fixed size.
Definition hash.hh:157
auto operator()(T const *sym) const -> size_t
Get the hash of the symbol array.
Definition hash.hh:162
array_hash(size_t size)
Initialize with the given size.
Definition hash.hh:160
An immutable array with efficient copying.
Definition immutable_array.hh:18
An immutable value imlementation.
Definition immutable_value.hh:19
A vector that misuses the begin, end and capacity pointers to store elements.
Definition small_vector.hh:26
auto value_hash_range(T const &x) -> size_t
Compute the hash for a given range of elements.
Definition hash.hh:246
auto value_hash(std::type_info const &x) -> size_t
Compute a hash for type_info.
Definition hash.hh:280
auto value_hash_record(Args const &...x) -> size_t
Compute and combine the hashes of the given arguments.
Definition hash.hh:368
auto hash_mix(size_t h) -> size_t
Perturb the given seed.
Definition hash.hh:223
auto hash_combine(T... a) -> size_t
Combine the given hashes.
Definition hash.hh:242
Comparison operator for arrays of dynamic but fixed size.
Definition hash.hh:171
array_equal_to(size_t size)
Initialize with the given size.
Definition hash.hh:174
auto operator()(T const *a, T const *b) const -> bool
Compare two symbols arrays.
Definition hash.hh:176
Helper class to compare pointers and some STL containers holding pointers by value.
Definition hash.hh:94
auto operator()(std::optional< T > const &a, std::optional< U > const &b) const -> bool
Compare optionals by value.
Definition hash.hh:108
auto operator()(std::unique_ptr< T, D > const &a, std::unique_ptr< U, E > const &b) const -> bool
Compare unique pointers by value.
Definition hash.hh:117
void is_transparent
Mark the comparison operator as transparent.
Definition hash.hh:96
auto operator()(T const &a, U const &b) const -> bool
Basic comparison.
Definition hash.hh:99
auto operator()(std::reference_wrapper< T > const &a, std::reference_wrapper< U > const &b) const -> bool
Compare reference wrappers by value.
Definition hash.hh:104
auto operator()(std::span< T, E > const &a, std::span< U, F > const &b) const -> bool
Compare spans by value.
Definition hash.hh:144
auto operator()(std::vector< T, A > const &a, std::vector< U, B > const &b) const -> bool
Compare vectors by value.
Definition hash.hh:149
auto operator()(char const *a, char const *b) const -> bool
Compare c-strings by value.
Definition hash.hh:101
auto operator()(std::tuple< T... > const &a, std::tuple< U... > const &b) const -> bool
Compare tuples by value.
Definition hash.hh:127
auto operator()(std::pair< T, U > const &a, std::pair< V, W > const &b) const -> bool
Compare pairs by value.
Definition hash.hh:122
auto operator()(std::variant< T... > const &a, std::variant< U... > const &b) const -> bool
Compare variants by value.
Definition hash.hh:135
auto operator()(T *a, U *b) const -> bool
Compare pointers by value.
Definition hash.hh:112
Compute a hash using std::hash.
Definition hash.hh:88
auto operator()(T const &x) const -> size_t
Compute the hash of the given value.
Definition hash.hh:90