3#include <clingo/util/immutable_array.hh>
4#include <clingo/util/immutable_value.hh>
5#include <clingo/util/small_vector.hh>
16namespace CppClingo::Util {
22inline auto hash_mix(
size_t h) -> size_t;
25template <
class... T>
inline auto hash_combine(T... a) -> size_t;
28auto value_hash(std::type_info
const &x) -> size_t;
31template <
class T>
auto value_hash(T
const &x) -> size_t;
34template <
class T>
auto value_hash(T *x) -> size_t;
37template <
class T>
auto value_hash(std::optional<T>
const &x) -> size_t;
40template <
class T>
auto value_hash(std::reference_wrapper<T>
const &x) -> size_t;
43template <
class T,
class D>
auto value_hash(std::unique_ptr<T, D>
const &x) -> size_t;
46template <
class T>
auto value_hash(immutable_value<T>
const &x) -> size_t;
49template <
class T,
class U>
auto value_hash(std::pair<T, U>
const &x) -> size_t;
52template <
class... T>
auto value_hash(std::tuple<T...>
const &x) -> size_t;
55template <
class... T>
auto value_hash(std::variant<T...>
const &x) -> size_t;
58template <
class T,
size_t E>
auto value_hash(std::span<T, E>
const &x) -> size_t;
61template <
class T,
class A>
auto value_hash(std::vector<T, A>
const &x) -> size_t;
64template <
class T>
auto value_hash(Util::immutable_array<T>
const &x) -> size_t;
67template <
class T,
size_t N>
auto value_hash(Util::small_vector<T, N>
const &x) -> size_t;
73auto value_hash(std::string_view
const &x) -> size_t;
76auto value_hash(std::string
const &x) -> size_t;
82template <
class T,
class... Args>
auto value_hash_record(Args
const &...x) -> size_t;
96 template <
class T,
class U>
auto operator()(T
const &a, U
const &b)
const ->
bool {
return a == b; }
98 auto operator()(
char const *a,
char const *b)
const ->
bool {
return std::strcmp(a, b) == 0; }
100 template <
class T,
class U>
101 auto operator()(std::reference_wrapper<T>
const &a, std::reference_wrapper<U>
const &b)
const ->
bool {
105 template <
class T,
class U>
auto operator()(std::optional<T>
const &a, std::optional<U>
const &b)
const ->
bool {
106 return (!a && !b) || (a && b &&
operator()(*a, *b));
109 template <
class T,
class U>
auto operator()(T *a, U *b)
const ->
bool {
110 return a == b || (a !=
nullptr && b !=
nullptr &&
operator()(*a, *b));
113 template <
class T,
class D,
class U,
class E>
114 auto operator()(std::unique_ptr<T, D>
const &a, std::unique_ptr<U, E>
const &b)
const ->
bool {
118 template <
class T,
class U,
class V,
class W>
119 auto operator()(std::pair<T, U>
const &a, std::pair<V, W>
const &b)
const ->
bool {
123 template <
class... T,
class... U>
124 auto operator()(std::tuple<T...>
const &a, std::tuple<U...>
const &b)
const ->
bool {
125 static_assert(
sizeof...(T) ==
sizeof...(U));
126 return [&,
this]<
size_t... I>([[maybe_unused]] std::index_sequence<I...> seq) {
127 return (this->
operator()(std::get<I>(a), std::get<I>(b)) && ...);
128 }(std::index_sequence_for<T...>());
131 template <
class... T,
class... U>
132 auto operator()(std::variant<T...>
const &a, std::variant<U...>
const &b)
const ->
bool {
133 static_assert(
sizeof...(T) ==
sizeof...(U));
135 return i == b.index() && [&,
this]<
size_t... I>([[maybe_unused]] std::index_sequence<I...> seq) {
136 return ((i == I && this->
operator()(std::get<I>(a), std::get<I>(b))) || ...);
137 }(std::index_sequence_for<T...>());
140 template <
class T,
size_t E,
class U,
size_t F>
141 auto operator()(std::span<T, E>
const &a, std::span<U, F>
const &b)
const ->
bool {
142 return std::equal(a.begin(), a.end(), b.begin(), b.end(), *
this);
145 template <
class T,
class A,
class U,
class B>
146 auto operator()(std::vector<T, A>
const &a, std::vector<U, B>
const &b)
const ->
bool {
147 return std::equal(a.begin(), a.end(), b.begin(), b.end(), *
this);
173 template <
class T>
auto operator()(T
const *a, T
const *b)
const ->
bool {
174 return value_equal_to{}(std::span(a, size_), std::span(b, size_));
185inline auto hash_combine() ->
size_t {
189inline auto hash_combine(
size_t a) ->
size_t {
193inline auto hash_combine(
size_t seed,
size_t h) ->
size_t {
195 if constexpr (
sizeof(size_t) ==
sizeof(uint64_t)) {
196 seed *= 0x87c37b91114253d5;
197 seed = (seed >> 31) | (seed << 33);
198 seed *= 0x4cf5ad432745937f;
200 seed = (seed >> 27) | (seed << 37);
201 seed = seed * 5 + 0x52dce729;
204 seed = (seed >> 17) | (seed << 15);
207 seed = (seed >> 19) | (seed << 13);
208 seed = seed * 5 + 0xe6546b64;
214template <
class... T>
inline auto hash_combine(
size_t a,
size_t b, T... c) ->
size_t {
222 if constexpr (
sizeof(size_t) ==
sizeof(uint64_t)) {
224 h *= 0xff51afd7ed558ccd;
226 h *= 0xc4ceb9fe1a85ec53;
240 return Detail::hash_combine(a...);
247 auto small = []<std::size_t... n>(std::index_sequence<n...>,
auto const &x) {
252 return small(std::make_index_sequence<0>(), x);
254 return small(std::make_index_sequence<1>(), x);
256 return small(std::make_index_sequence<2>(), x);
258 return small(std::make_index_sequence<3>(), x);
260 return small(std::make_index_sequence<4>(), x);
262 return small(std::make_index_sequence<5>(), x);
264 return small(std::make_index_sequence<6>(), x);
266 return small(std::make_index_sequence<7>(), x);
268 return small(std::make_index_sequence<8>(), x);
270 return std::accumulate(
272 [](
auto const &seed,
auto const &x) { return Util::hash_combine(seed, Util::value_hash(x)); });
282 if constexpr (
requires { x.hash(); }) {
284 }
else if constexpr (std::is_arithmetic_v<T> || std::is_enum_v<T>) {
287 return std::hash<T>{}(x);
298template <
class T>
auto value_hash(std::optional<T>
const &x) ->
size_t {
305template <
class T>
auto value_hash(std::reference_wrapper<T>
const &x) ->
size_t {
309template <
class T,
class D>
auto value_hash(std::unique_ptr<T, D>
const &x) ->
size_t {
323template <
class T,
class U>
auto value_hash(std::pair<T, U>
const &x) ->
size_t {
327template <
class... T>
auto value_hash(std::tuple<T...>
const &x) ->
size_t {
328 return [&x]<
size_t... Indices>([[maybe_unused]] std::index_sequence<Indices...> indices) ->
size_t {
330 }(std::index_sequence_for<T...>{});
333template <
class... T>
auto value_hash(std::variant<T...>
const &x) ->
size_t {
337template <
class T,
size_t E>
auto value_hash(std::span<T, E>
const &x) ->
size_t {
341template <
class T,
class A>
auto value_hash(std::vector<T, A>
const &x) ->
size_t {
354 return std::hash<std::string_view>{}(x);
358 return std::hash<std::string_view>{}(x);
362 return std::hash<std::string_view>{}(x);
369static constexpr unsigned int default_neighborhood_size = 62;
Hasher for arrays of dynamic but fixed size.
Definition hash.hh:154
auto operator()(T const *sym) const -> size_t
Get the hash of the symbol array.
Definition hash.hh:159
array_hash(size_t size)
Initialize with the given size.
Definition hash.hh:157
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:243
auto value_hash(std::type_info const &x) -> size_t
Compute a hash for type_info.
Definition hash.hh:277
auto value_hash_record(Args const &...x) -> size_t
Compute and combine the hashes of the given arguments.
Definition hash.hh:365
auto hash_mix(size_t h) -> size_t
Perturb the given seed.
Definition hash.hh:220
auto hash_combine(T... a) -> size_t
Combine the given hashes.
Definition hash.hh:239
Comparison operator for arrays of dynamic but fixed size.
Definition hash.hh:168
array_equal_to(size_t size)
Initialize with the given size.
Definition hash.hh:171
auto operator()(T const *a, T const *b) const -> bool
Compare two symbols arrays.
Definition hash.hh:173
Helper class to compare pointers and some STL containers holding pointers by value.
Definition hash.hh:91
auto operator()(std::optional< T > const &a, std::optional< U > const &b) const -> bool
Compare optionals by value.
Definition hash.hh:105
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:114
void is_transparent
Mark the comparison operator as transparent.
Definition hash.hh:93
auto operator()(T const &a, U const &b) const -> bool
Basic comparison.
Definition hash.hh:96
auto operator()(std::reference_wrapper< T > const &a, std::reference_wrapper< U > const &b) const -> bool
Compare reference wrappers by value.
Definition hash.hh:101
auto operator()(std::span< T, E > const &a, std::span< U, F > const &b) const -> bool
Compare spans by value.
Definition hash.hh:141
auto operator()(std::vector< T, A > const &a, std::vector< U, B > const &b) const -> bool
Compare vectors by value.
Definition hash.hh:146
auto operator()(char const *a, char const *b) const -> bool
Compare c-strings by value.
Definition hash.hh:98
auto operator()(std::tuple< T... > const &a, std::tuple< U... > const &b) const -> bool
Compare tuples by value.
Definition hash.hh:124
auto operator()(std::pair< T, U > const &a, std::pair< V, W > const &b) const -> bool
Compare pairs by value.
Definition hash.hh:119
auto operator()(std::variant< T... > const &a, std::variant< U... > const &b) const -> bool
Compare variants by value.
Definition hash.hh:132
auto operator()(T *a, U *b) const -> bool
Compare pointers by value.
Definition hash.hh:109
Compute a hash using std::hash.
Definition hash.hh:85
auto operator()(T const &x) const -> size_t
Compute the hash of the given value.
Definition hash.hh:87