diff options
| author | 2023-03-25 22:43:55 -0400 | |
|---|---|---|
| committer | 2023-03-25 23:52:25 -0400 | |
| commit | 9971cd1d55b0481a2af74a7694b6dcf686176c7c (patch) | |
| tree | 12cdacd7b5292d31a7b92f8744ac7960b93fb6a5 /src | |
| parent | CMakeLists: Require a minimum of boost 1.79.0 (diff) | |
| download | yuzu-9971cd1d55b0481a2af74a7694b6dcf686176c7c.tar.gz yuzu-9971cd1d55b0481a2af74a7694b6dcf686176c7c.tar.xz yuzu-9971cd1d55b0481a2af74a7694b6dcf686176c7c.zip | |
common: Port boost's hash_value implementation
Ports a small subset of boost's hash_value implementation (<= 1.80.0).
Diffstat (limited to 'src')
| -rw-r--r-- | src/common/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/common/container_hash.h | 91 |
2 files changed, 92 insertions, 0 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 90805babe..c1d2b24a1 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt | |||
| @@ -38,6 +38,7 @@ add_library(common STATIC | |||
| 38 | common_precompiled_headers.h | 38 | common_precompiled_headers.h |
| 39 | common_types.h | 39 | common_types.h |
| 40 | concepts.h | 40 | concepts.h |
| 41 | container_hash.h | ||
| 41 | demangle.cpp | 42 | demangle.cpp |
| 42 | demangle.h | 43 | demangle.h |
| 43 | div_ceil.h | 44 | div_ceil.h |
diff --git a/src/common/container_hash.h b/src/common/container_hash.h new file mode 100644 index 000000000..cfc5dfea8 --- /dev/null +++ b/src/common/container_hash.h | |||
| @@ -0,0 +1,91 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2005-2014 Daniel James | ||
| 2 | // SPDX-FileCopyrightText: 2016 Austin Appleby | ||
| 3 | // SPDX-License-Identifier: BSL-1.0 | ||
| 4 | |||
| 5 | #include <array> | ||
| 6 | #include <cstdint> | ||
| 7 | #include <limits> | ||
| 8 | #include <type_traits> | ||
| 9 | #include <vector> | ||
| 10 | |||
| 11 | namespace Common { | ||
| 12 | |||
| 13 | namespace detail { | ||
| 14 | |||
| 15 | template <typename T> | ||
| 16 | requires std::is_unsigned_v<T> | ||
| 17 | inline std::size_t HashValue(T val) { | ||
| 18 | const unsigned int size_t_bits = std::numeric_limits<std::size_t>::digits; | ||
| 19 | const unsigned int length = | ||
| 20 | (std::numeric_limits<T>::digits - 1) / static_cast<unsigned int>(size_t_bits); | ||
| 21 | |||
| 22 | std::size_t seed = 0; | ||
| 23 | |||
| 24 | for (unsigned int i = length * size_t_bits; i > 0; i -= size_t_bits) { | ||
| 25 | seed ^= static_cast<size_t>(val >> i) + (seed << 6) + (seed >> 2); | ||
| 26 | } | ||
| 27 | |||
| 28 | seed ^= static_cast<size_t>(val) + (seed << 6) + (seed >> 2); | ||
| 29 | |||
| 30 | return seed; | ||
| 31 | } | ||
| 32 | |||
| 33 | template <size_t Bits> | ||
| 34 | struct HashCombineImpl { | ||
| 35 | template <typename T> | ||
| 36 | static inline T fn(T seed, T value) { | ||
| 37 | seed ^= value + 0x9e3779b9 + (seed << 6) + (seed >> 2); | ||
| 38 | return seed; | ||
| 39 | } | ||
| 40 | }; | ||
| 41 | |||
| 42 | template <> | ||
| 43 | struct HashCombineImpl<64> { | ||
| 44 | static inline std::uint64_t fn(std::uint64_t h, std::uint64_t k) { | ||
| 45 | const std::uint64_t m = (std::uint64_t(0xc6a4a793) << 32) + 0x5bd1e995; | ||
| 46 | const int r = 47; | ||
| 47 | |||
| 48 | k *= m; | ||
| 49 | k ^= k >> r; | ||
| 50 | k *= m; | ||
| 51 | |||
| 52 | h ^= k; | ||
| 53 | h *= m; | ||
| 54 | |||
| 55 | // Completely arbitrary number, to prevent 0's | ||
| 56 | // from hashing to 0. | ||
| 57 | h += 0xe6546b64; | ||
| 58 | |||
| 59 | return h; | ||
| 60 | } | ||
| 61 | }; | ||
| 62 | |||
| 63 | } // namespace detail | ||
| 64 | |||
| 65 | template <typename T> | ||
| 66 | inline void HashCombine(std::size_t& seed, const T& v) { | ||
| 67 | seed = detail::HashCombineImpl<sizeof(std::size_t) * CHAR_BIT>::fn(seed, detail::HashValue(v)); | ||
| 68 | } | ||
| 69 | |||
| 70 | template <typename It> | ||
| 71 | inline std::size_t HashRange(It first, It last) { | ||
| 72 | std::size_t seed = 0; | ||
| 73 | |||
| 74 | for (; first != last; ++first) { | ||
| 75 | HashCombine<typename std::iterator_traits<It>::value_type>(seed, *first); | ||
| 76 | } | ||
| 77 | |||
| 78 | return seed; | ||
| 79 | } | ||
| 80 | |||
| 81 | template <typename T, size_t Size> | ||
| 82 | std::size_t HashValue(const std::array<T, Size>& v) { | ||
| 83 | return HashRange(v.cbegin(), v.cend()); | ||
| 84 | } | ||
| 85 | |||
| 86 | template <typename T, typename Allocator> | ||
| 87 | std::size_t HashValue(const std::vector<T, Allocator>& v) { | ||
| 88 | return HashRange(v.cbegin(), v.cend()); | ||
| 89 | } | ||
| 90 | |||
| 91 | } // namespace Common | ||