diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2024-06-08 08:23:17 +0200 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2024-06-08 10:39:37 +0200 |
commit | c26e4ed3d5c0fa532356365bddd275fba04ae2c3 (patch) | |
tree | c2a2e00ea9d57016b3f52e0b2c7f4351858c0ebb /compat/hash.cpp | |
parent | 39670daf26c4fbbfe9148dec30c9f0e075eff404 (diff) |
compat: rename hash's source file only
Diffstat (limited to 'compat/hash.cpp')
-rw-r--r-- | compat/hash.cpp | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/compat/hash.cpp b/compat/hash.cpp new file mode 100644 index 00000000..3cb3cc35 --- /dev/null +++ b/compat/hash.cpp @@ -0,0 +1,146 @@ +#include "compat/defs.hpp" +#include "hash.hpp" +#include <Corrade/Containers/StringView.h> +#include <bit> +#include <utility> + +namespace floormat { + +namespace { + +using namespace floormat::Hash; + +[[maybe_unused]] +CORRADE_ALWAYS_INLINE size_t fnvhash_uint_32(uint32_t x) +{ + constexpr auto params = fnvhash_params<sizeof(size_t)*8>{}; + constexpr auto a = params.a, b = params.b; + auto hash = a; + const auto* str = (const char*)&x; + + hash *= b; hash ^= (uint8_t)*str++; // 0 + hash *= b; hash ^= (uint8_t)*str++; // 1 + hash *= b; hash ^= (uint8_t)*str++; // 2 + hash *= b; hash ^= (uint8_t)*str++; // 3 + + return hash; +} + +CORRADE_ALWAYS_INLINE size_t fnvhash_uint_64(uint64_t x) +{ + constexpr auto params = fnvhash_params<sizeof(std::common_type_t<size_t>)*8>{}; + constexpr auto a = params.a, b = params.b; + auto hash = a; + const auto* str = (const char*)&x; + + hash *= b; hash ^= (uint8_t)*str++; // 0 + hash *= b; hash ^= (uint8_t)*str++; // 1 + hash *= b; hash ^= (uint8_t)*str++; // 2 + hash *= b; hash ^= (uint8_t)*str++; // 3 + hash *= b; hash ^= (uint8_t)*str++; // 4 + hash *= b; hash ^= (uint8_t)*str++; // 5 + hash *= b; hash ^= (uint8_t)*str++; // 6 + hash *= b; hash ^= (uint8_t)*str++; // 7 + + return hash; +} + +} // namespace + +uint32_t hash_32(const void* buf, size_t size) noexcept +{ + constexpr auto params = fnvhash_params<32>{}; + constexpr auto a = params.a, b = params.b; + auto hash = a; + const auto *str = (const char*)buf, *const end = str + size; + +fm_UNROLL_4 + for (; str != end; ++str) + { + hash *= b; + hash ^= (uint8_t)*str; + } + return hash; +} + +uint64_t hash_64(const void* buf, size_t size) noexcept +{ + constexpr auto params = fnvhash_params<sizeof(size_t)*8>{}; + constexpr auto a = params.a, b = params.b; + auto hash = a; + const auto *str = (const char*)buf, *const end = str + size; + +fm_UNROLL_8 + for (; str != end; ++str) + { + hash *= b; + hash ^= (uint8_t)*str; + } + return hash; +} + +size_t hash_buf(const void* buf, size_t size) noexcept +{ +#if 1 + if constexpr(sizeof nullptr > 4) + return hash_64(buf, size); + else +#endif + return hash_32(buf, size); +} + +size_t hash_int(uint32_t x) noexcept +{ +#if 1 + if constexpr(sizeof nullptr > 4) + return fnvhash_uint_64(x); + else +#endif + return fnvhash_uint_32(x); +} + +size_t hash_int(uint64_t x) noexcept +{ + return fnvhash_uint_64(x); +} + +size_t hash_string_view::operator()(StringView s) const noexcept { return Hash::fnvhash_buf(s.data(), s.size()); } + +} // namespace floormat + +namespace floormat::Hash { + +size_t fnvhash_buf(const void* __restrict buf, size_t size, size_t seed) noexcept +{ + constexpr size_t b{fnvhash_params<sizeof nullptr*8>::b}; + size_t full_rounds = size / 8, rest = size % 8; + size_t hash = seed; + const char* str = (const char*)buf; + + while (full_rounds--) + { + hash *= b; hash ^= (uint8_t)*str++; // 0 + hash *= b; hash ^= (uint8_t)*str++; // 1 + hash *= b; hash ^= (uint8_t)*str++; // 2 + hash *= b; hash ^= (uint8_t)*str++; // 3 + hash *= b; hash ^= (uint8_t)*str++; // 4 + hash *= b; hash ^= (uint8_t)*str++; // 5 + hash *= b; hash ^= (uint8_t)*str++; // 6 + hash *= b; hash ^= (uint8_t)*str++; // 7 + } + switch (rest) + { + case 7: hash *= b; hash ^= (uint8_t)*str++; [[fallthrough]]; + case 6: hash *= b; hash ^= (uint8_t)*str++; [[fallthrough]]; + case 5: hash *= b; hash ^= (uint8_t)*str++; [[fallthrough]]; + case 4: hash *= b; hash ^= (uint8_t)*str++; [[fallthrough]]; + case 3: hash *= b; hash ^= (uint8_t)*str++; [[fallthrough]]; + case 2: hash *= b; hash ^= (uint8_t)*str++; [[fallthrough]]; + case 1: hash *= b; hash ^= (uint8_t)*str++; [[fallthrough]]; + case 0: break; + default: std::unreachable(); + } + return hash; +} + +} // namespace floormat::Hash |