From 4ad05c650c55e3edccea887d15b26f41cdf60fb6 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Wed, 17 Nov 2021 14:13:06 +0200 Subject: [PATCH] Rewrite the hash functions to be more generic The number of bits is now taken as a template parameter and the hash size is determined automatically. --- source/core/hash.cpp | 49 -------------------- source/core/hash.h | 107 ++++++++++++++++++++++++++++++++++--------- 2 files changed, 86 insertions(+), 70 deletions(-) delete mode 100644 source/core/hash.cpp diff --git a/source/core/hash.cpp b/source/core/hash.cpp deleted file mode 100644 index aed9ed1..0000000 --- a/source/core/hash.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include -#include "hash.h" - -using namespace std; - -namespace Msp { - -/* -http://en.wikipedia.org/wiki/Fowler-Noll-Vo_hash_function -http://www.isthe.com/chongo/tech/comp/fnv/index.html -*/ - -uint32_t hash32(const void *data, unsigned size, unsigned bits) -{ - if(bits==0 || bits>32) - throw invalid_argument("hash32"); - - static const unsigned prime = 16777619; - static const unsigned offset = 2166136261U; - - unsigned result = offset; - for(unsigned i=0; i(data)+i))*prime; - - if(bits<32) - result = (result>>bits ^ result) & ((1<64) - throw invalid_argument("hash64"); - - static const uint64_t prime = 1099511628211ULL; - static const uint64_t offset = 14695981039346656037ULL; - - uint64_t result = offset; - for(unsigned i=0; i(data)+i))*prime; - - if(bits<64) - result = (result>>bits ^ result) & ((1ULL< +#include #include namespace Msp { -/** -Computes a 32-bit Fowler-Noll-Vo (FNV-1a) hash. The number of bits can be -limited to less than 32, in which case XOR-folding is used to reduce the hash -size. -*/ -std::uint32_t hash32(const void *, unsigned, unsigned = 32); +template8)+(N>16)+(N>32)+(N>64)> +struct HashTraits; + +template<> +struct HashTraits<64, 6> +{ + using HashType = uint64_t; + using ResultType = uint64_t; + static constexpr HashType prime = 1099511628211ULL; + static constexpr HashType offset = 14695981039346656037ULL; + static constexpr bool folded = false; +}; + +template<> +struct HashTraits<32, 5> +{ + using HashType = uint32_t; + using ResultType = uint32_t; + static constexpr HashType prime = 16777619; + static constexpr HashType offset = 2166136261U; + static constexpr bool folded = false; +}; + +template +struct HashTraits +{ + using HashType = uint64_t; + using ResultType = uint64_t; + static constexpr bool folded = true; +}; + +template +struct HashTraits +{ + using HashType = uint32_t; + using ResultType = uint32_t; + static constexpr bool folded = true; +}; + +template +struct HashTraits +{ + using HashType = uint32_t; + using ResultType = uint16_t; + static constexpr bool folded = true; +}; + +template +struct HashTraits +{ + using HashType = uint32_t; + using ResultType = uint8_t; + static constexpr bool folded = true; +}; + /** -Convenience function to compute a 32-bit hash of a string. +Manually folds a hash to a smaller size. */ -inline unsigned hash32(const std::string &s, unsigned b = 32) -{ return hash32(s.data(), s.size(), b); } +template +typename std::enable_if::digits, typename HashTraits::ResultType>::type hash_fold(T hash) +{ return (hash>>N ^ hash) & ((T(1)< +typename std::enable_if::digits, typename HashTraits::ResultType>::type hash_fold(T hash) +{ return hash; } /** -Computes a 64-bit Fowler-Noll-Vo (FNV-1a) hash. Note that even if bits is -limited to 32 or less, this does not produce the same result as hash32. +Computes an N-bit Fowler-Noll-Vo (FNV-1a) hash. If N is not a native hash +size, the next larger native hash is computed and XOR-folding is applied to +the result. + +http://en.wikipedia.org/wiki/Fowler-Noll-Vo_hash_function +http://www.isthe.com/chongo/tech/comp/fnv/index.html */ -std::uint64_t hash64(const void *, unsigned, unsigned = 64); +template +typename HashTraits::ResultType hash(const void *data, std::size_t size) +{ + constexpr unsigned hash_bits = std::numeric_limits::HashType>::digits; + constexpr typename HashTraits::HashType prime = HashTraits::prime; + typename HashTraits::HashType result = HashTraits::offset; + for(unsigned i=0; i(data)+i))*prime; + if(HashTraits::folded) + result = hash_fold(result); + return result; +} /** -Convenience function to compute a 64-bit hash of a string. +Convenience function to compute an N-bit hash of a string. */ -inline std::uint64_t hash64(const std::string &s, unsigned b = 64) -{ return hash64(s.data(), s.size(), b); } - -inline std::uint32_t fold32(std::uint64_t hash) -{ return hash^(hash>>32); } - -inline std::uint16_t fold16(std::uint64_t hash) -{ return hash^(hash>>16)^(hash>>32)^(hash>>48); } +template +typename HashTraits::ResultType hash(const std::string &str) +{ return hash(str.data(), str.size()); } } // namespace Msp -- 2.45.2