summaryrefslogtreecommitdiffhomepage
path: root/compat/hash.cpp
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2024-06-08 08:23:17 +0200
committerStanislaw Halik <sthalik@misaki.pl>2024-06-08 10:39:37 +0200
commitc26e4ed3d5c0fa532356365bddd275fba04ae2c3 (patch)
treec2a2e00ea9d57016b3f52e0b2c7f4351858c0ebb /compat/hash.cpp
parent39670daf26c4fbbfe9148dec30c9f0e075eff404 (diff)
compat: rename hash's source file only
Diffstat (limited to 'compat/hash.cpp')
-rw-r--r--compat/hash.cpp146
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