X-Git-Url: http://git.tdb.fi/?p=libs%2Fcore.git;a=blobdiff_plain;f=source%2Fcore%2Fhash.h;fp=source%2Fcore%2Fhash.h;h=a7e8cb165722cf7aa38aac417d97c21d2abd5004;hp=85ee5dd74c046a4cdbc3b793cfd07d22dca2132f;hb=4ad05c650c55e3edccea887d15b26f41cdf60fb6;hpb=991fabc1956b73a4007859058fb44171000b452e diff --git a/source/core/hash.h b/source/core/hash.h index 85ee5dd..a7e8cb1 100644 --- a/source/core/hash.h +++ b/source/core/hash.h @@ -2,40 +2,105 @@ #define MSP_CORE_HASH_H_ #include +#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