diff options
Diffstat (limited to 'compat/int-hash.cpp')
| -rw-r--r-- | compat/int-hash.cpp | 42 |
1 files changed, 38 insertions, 4 deletions
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 |
