#pragma once #include #include #include namespace mln { namespace util { template void hash_combine(std::size_t& seed, const T& v) noexcept { seed ^= std::hash()(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); } template std::size_t hash(Args&&... args) noexcept { std::size_t seed = 0; ignore({(hash_combine(seed, args), 0)...}); return seed; } namespace detail { template using TIterVal = std::enable_if_t, typename TIter::value_type>; } // namespace detail template constexpr T factor() noexcept { // Default factor prime value from 64-bit FNV hash. if constexpr (sizeof(T) == 8) return 1099511628211; // for 32-bit hash return 16777619; } /// Generate a hash key from a collection of integer values which doesn't depend on their order. /// Adapted from https://stackoverflow.com/a/76993810/135138 template , TKey factor = factor()> TKey order_independent_hash(std::remove_const_t cur, const TIter end) noexcept { detail::TIterVal sum = 0, product = 1; for (; cur != end; ++cur) { const auto& value = *cur; sum += value; product *= (1 + value) * factor; } return sum ^ product; } } // namespace util } // namespace mln