From c965760ea1380d64ddd43a5206deffdbf52077b4 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Tue, 28 Jan 2014 23:33:25 +0000 Subject: [PATCH] Improved(?) hash function. Given the existing interface, it's quite tricky to use most popular hash functions without a change, so I'm using a modified version of FNV1a. The current function always starts with a seed of 0 (and will in user functions), so I'm adding the offset each time instead. I'm not sure if that will work as well. --- include/boost/functional/hash/hash.hpp | 41 +++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/include/boost/functional/hash/hash.hpp b/include/boost/functional/hash/hash.hpp index c7de2c5..9716e6c 100644 --- a/include/boost/functional/hash/hash.hpp +++ b/include/boost/functional/hash/hash.hpp @@ -192,6 +192,44 @@ namespace boost return seed; } + + template + struct hash_combine_impl + { + inline static void combine(std::size_t& seed, + std::size_t value) + { + seed ^= value + 0x9e3779b9 + (seed<<6) + (seed>>2); + } + }; + + template <> + struct hash_combine_impl<4> + { + template + inline static void combine(T& seed, std::size_t value) + { + const T offset = 2166136261UL; + const T prime = 16777619UL; + + seed ^= (value + offset); + seed *= prime; + } + }; + + template <> + struct hash_combine_impl<8> + { + template + inline static void combine(T& seed, std::size_t value) + { + const T offset = 14695981039346656037ULL; + const T prime = 1099511628211ULL; + + seed ^= (value + offset); + seed *= prime; + } + }; } template @@ -252,7 +290,8 @@ namespace boost inline void hash_combine(std::size_t& seed, T const& v) { boost::hash hasher; - seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2); + return boost::hash_detail::hash_combine_impl< + sizeof(std::size_t)>::combine(seed, hasher(v)); } #if defined(BOOST_MSVC)