diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2024-01-18 23:22:41 +0100 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2024-01-18 23:22:41 +0100 |
commit | 3264ef85e50add2db3c54291540bde7e8411cb70 (patch) | |
tree | 9c26f478c73dfcd83e5a49f4a8fb188d3b86be62 /compat | |
parent | 848f3a16b95be89a1d639ae9ee4ea64e77625e39 (diff) |
c
Diffstat (limited to 'compat')
-rw-r--r-- | compat/defs.hpp | 2 | ||||
-rw-r--r-- | compat/int-hash.cpp | 42 | ||||
-rw-r--r-- | compat/int-hash.hpp | 12 |
3 files changed, 47 insertions, 9 deletions
diff --git a/compat/defs.hpp b/compat/defs.hpp index d14832d0..fe72dda6 100644 --- a/compat/defs.hpp +++ b/compat/defs.hpp @@ -74,7 +74,7 @@ #define fm_UNROLL_2 _Pragma("GCC unroll 2") #define fm_UNROLL_4 _Pragma("GCC unroll 4") #define fm_UNROLL_8 _Pragma("GCC unroll 8") -#if __SIZEOF_POINTER__ >= 8 +#if __SIZEOF_POINTER__ > 4 #define fm_UNROLL _Pragma("GCC unroll 8") #else #define fm_UNROLL _Pragma("GCC unroll 4") diff --git a/compat/int-hash.cpp b/compat/int-hash.cpp index c6ca7d3d..3c85a436 100644 --- a/compat/int-hash.cpp +++ b/compat/int-hash.cpp @@ -6,11 +6,9 @@ namespace floormat { namespace { -template<size_t N> struct fnvhash_params; - -template<> struct fnvhash_params<32> { uint32_t a = 0x811c9dc5u, b = 0x01000193u; }; -template<> struct fnvhash_params<64> { uint64_t a = 0xcbf29ce484222325u, b = 0x100000001b3u; }; +using namespace floormat::Hash; +// todo implement in terms of fnvhash_buf() [[maybe_unused]] CORRADE_ALWAYS_INLINE size_t fnvhash_uint_32(uint32_t x) { @@ -91,3 +89,39 @@ size_t hash_int(uint64_t x) noexcept } } // 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; + } + return hash; +} + +} // namespace floormat::Hash diff --git a/compat/int-hash.hpp b/compat/int-hash.hpp index b3dd7616..752c3597 100644 --- a/compat/int-hash.hpp +++ b/compat/int-hash.hpp @@ -1,12 +1,16 @@ #pragma once -namespace floormat::impl_hash { +namespace floormat::Hash { -template<size_t N> size_t hash_buf(const void* buf, size_t size) noexcept = delete; +template<size_t N = sizeof nullptr * 4> struct fnvhash_params; +template<> struct fnvhash_params<32> { static constexpr uint32_t a = 0x811c9dc5u, b = 0x01000193u; }; +template<> struct fnvhash_params<64> { static constexpr uint64_t a = 0xcbf29ce484222325u, b = 0x100000001b3u; }; -} // namespace floormat::impl_hash +size_t fnvhash_buf(const void* __restrict buf, size_t size, size_t seed = fnvhash_params<>::a) noexcept; -namespace floormat { +} // namespace floormat::Hash + +namespace floormat { // todo uint64_t hash_64(const void* buf, size_t size) noexcept; uint32_t hash_32(const void* buf, size_t size) noexcept; |