| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- // SPDX-FileCopyrightText: 2005-2014 Daniel James
- // SPDX-FileCopyrightText: 2016 Austin Appleby
- // SPDX-License-Identifier: BSL-1.0
- #include <array>
- #include <climits>
- #include <cstdint>
- #include <limits>
- #include <type_traits>
- #include <vector>
- namespace Common {
- namespace detail {
- template <typename T>
- requires std::is_unsigned_v<T>
- inline std::size_t HashValue(T val) {
- const unsigned int size_t_bits = std::numeric_limits<std::size_t>::digits;
- const unsigned int length =
- (std::numeric_limits<T>::digits - 1) / static_cast<unsigned int>(size_t_bits);
- std::size_t seed = 0;
- for (unsigned int i = length * size_t_bits; i > 0; i -= size_t_bits) {
- seed ^= static_cast<size_t>(val >> i) + (seed << 6) + (seed >> 2);
- }
- seed ^= static_cast<size_t>(val) + (seed << 6) + (seed >> 2);
- return seed;
- }
- template <size_t Bits>
- struct HashCombineImpl {
- template <typename T>
- static inline T fn(T seed, T value) {
- seed ^= value + 0x9e3779b9 + (seed << 6) + (seed >> 2);
- return seed;
- }
- };
- template <>
- struct HashCombineImpl<64> {
- static inline std::uint64_t fn(std::uint64_t h, std::uint64_t k) {
- const std::uint64_t m = (std::uint64_t(0xc6a4a793) << 32) + 0x5bd1e995;
- const int r = 47;
- k *= m;
- k ^= k >> r;
- k *= m;
- h ^= k;
- h *= m;
- // Completely arbitrary number, to prevent 0's
- // from hashing to 0.
- h += 0xe6546b64;
- return h;
- }
- };
- } // namespace detail
- template <typename T>
- inline void HashCombine(std::size_t& seed, const T& v) {
- seed = detail::HashCombineImpl<sizeof(std::size_t) * CHAR_BIT>::fn(seed, detail::HashValue(v));
- }
- template <typename It>
- inline std::size_t HashRange(It first, It last) {
- std::size_t seed = 0;
- for (; first != last; ++first) {
- HashCombine<typename std::iterator_traits<It>::value_type>(seed, *first);
- }
- return seed;
- }
- template <typename T, size_t Size>
- std::size_t HashValue(const std::array<T, Size>& v) {
- return HashRange(v.cbegin(), v.cend());
- }
- template <typename T, typename Allocator>
- std::size_t HashValue(const std::vector<T, Allocator>& v) {
- return HashRange(v.cbegin(), v.cend());
- }
- } // namespace Common
|