summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--compat/int-hash.cpp29
1 files changed, 24 insertions, 5 deletions
diff --git a/compat/int-hash.cpp b/compat/int-hash.cpp
index 5c009b4e..79b5dfad 100644
--- a/compat/int-hash.cpp
+++ b/compat/int-hash.cpp
@@ -35,15 +35,34 @@ fm_UNROLL_8
} // namespace
+#define fnvhash_64_ROUND() do { hash *= 0x01000193u; hash ^= (uint8_t)*str++; } while(false)
+
uint64_t fnvhash_64(const void* str_, size_t size)
{
- const auto *str = (const char*)str_, *end = str + size;
+ const auto *str = (const char*)str_;
uint32_t hash = 0x811c9dc5u;
-fm_UNROLL_4
- for (; str != end; ++str)
+ size_t full = size / 8;
+ for (size_t i = 0; i < full; i++)
{
- hash *= 0x01000193u;
- hash ^= (uint8_t)*str;
+ fnvhash_64_ROUND();
+ fnvhash_64_ROUND();
+ fnvhash_64_ROUND();
+ fnvhash_64_ROUND();
+ fnvhash_64_ROUND();
+ fnvhash_64_ROUND();
+ fnvhash_64_ROUND();
+ fnvhash_64_ROUND();
+ }
+ switch (size & 7u)
+ {
+ case 7: fnvhash_64_ROUND(); [[fallthrough]];
+ case 6: fnvhash_64_ROUND(); [[fallthrough]];
+ case 5: fnvhash_64_ROUND(); [[fallthrough]];
+ case 4: fnvhash_64_ROUND(); [[fallthrough]];
+ case 3: fnvhash_64_ROUND(); [[fallthrough]];
+ case 2: fnvhash_64_ROUND(); [[fallthrough]];
+ case 1: fnvhash_64_ROUND(); [[fallthrough]];
+ case 0: break;
}
return hash;
}