From bb2a91bf47354bfce7378394bc0fa84c76ecfe4e Mon Sep 17 00:00:00 2001 From: Daniel James Date: Tue, 28 Jan 2014 23:33:25 +0000 Subject: [PATCH 1/8] 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) From 309d17f38722b7bd15b804e55d1d8d6c3cd8691a Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 23 Feb 2014 10:16:53 +0000 Subject: [PATCH 2/8] Another try at an improved hash function. This is based on the mix function from MurmurHash. It's not the full algorithm as it's always seeded with 0, and doesn't do a final mix. This should be okay as Boost.Hash doesn't claim to avalanche the bits. --- include/boost/functional/hash/hash.hpp | 86 ++++++++++++++++---------- 1 file changed, 53 insertions(+), 33 deletions(-) diff --git a/include/boost/functional/hash/hash.hpp b/include/boost/functional/hash/hash.hpp index 9716e6c..3e5ab5b 100644 --- a/include/boost/functional/hash/hash.hpp +++ b/include/boost/functional/hash/hash.hpp @@ -1,11 +1,17 @@ -// Copyright 2005-2009 Daniel James. +// Copyright 2005-2014 Daniel James. // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // Based on Peter Dimov's proposal // http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf // issue 6.18. +// +// This also contains public domain code from MurmurHash. From the +// MurmurHash header: + +// MurmurHash3 was written by Austin Appleby, and is placed in the public +// domain. The author hereby disclaims copyright to this source code. #if !defined(BOOST_FUNCTIONAL_HASH_HASH_HPP) #define BOOST_FUNCTIONAL_HASH_HASH_HPP @@ -18,6 +24,7 @@ #include #include #include +#include #if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) #include @@ -45,6 +52,12 @@ #define BOOST_HASH_CHAR_TRAITS char_traits #endif +#if defined(_MSC_VER) +# define BOOST_FUNCTIONAL_HASH_ROTL32(x, r) _rotl(x,r) +#else +# define BOOST_FUNCTIONAL_HASH_ROTL32(x, r) (x << r) | (x >> (32 - r)) +#endif + namespace boost { namespace hash_detail @@ -193,43 +206,50 @@ namespace boost return seed; } - template - struct hash_combine_impl + template + inline void hash_combine_impl(SizeT& seed, SizeT value) { - inline static void combine(std::size_t& seed, - std::size_t value) - { - seed ^= value + 0x9e3779b9 + (seed<<6) + (seed>>2); - } - }; + seed ^= value + 0x9e3779b9 + (seed<<6) + (seed>>2); + } - template <> - struct hash_combine_impl<4> + template + inline void hash_combine_impl(boost::uint32_t& h1, + boost::uint32_t k1) { - template - inline static void combine(T& seed, std::size_t value) - { - const T offset = 2166136261UL; - const T prime = 16777619UL; + const uint32_t c1 = 0xcc9e2d51; + const uint32_t c2 = 0x1b873593; - seed ^= (value + offset); - seed *= prime; - } - }; + k1 *= c1; + k1 = BOOST_FUNCTIONAL_HASH_ROTL32(k1,15); + k1 *= c2; - template <> - struct hash_combine_impl<8> + h1 ^= k1; + h1 = BOOST_FUNCTIONAL_HASH_ROTL32(h1,13); + h1 = h1*5+0xe6546b64; + } + + +// Don't define 64-bit hash combine on platforms with 64 bit integers, +// and also not for 32-bit gcc as it warns about the 64-bit constant. +#if !defined(BOOST_NO_INT64_T) && \ + !(defined(__GNUC__) && ULONG_MAX == 0xffffffff) + + template + inline void hash_combine_impl(boost::uint64_t& h, + boost::uint64_t k) { - template - inline static void combine(T& seed, std::size_t value) - { - const T offset = 14695981039346656037ULL; - const T prime = 1099511628211ULL; + const uint64_t m = UINT64_C(0xc6a4a7935bd1e995); + const int r = 47; - seed ^= (value + offset); - seed *= prime; - } - }; + k *= m; + k ^= k >> r; + k *= m; + + h ^= k; + h *= m; + } + +#endif // BOOST_NO_INT64_T } template @@ -290,8 +310,7 @@ namespace boost inline void hash_combine(std::size_t& seed, T const& v) { boost::hash hasher; - return boost::hash_detail::hash_combine_impl< - sizeof(std::size_t)>::combine(seed, hasher(v)); + return boost::hash_detail::hash_combine_impl(seed, hasher(v)); } #if defined(BOOST_MSVC) @@ -522,6 +541,7 @@ namespace boost } #undef BOOST_HASH_CHAR_TRAITS +#undef BOOST_FUNCTIONAL_HASH_ROTL32 #if defined(BOOST_MSVC) #pragma warning(pop) From 97cc6fbbc19cffbac2a8f3866f0cda890e6819bb Mon Sep 17 00:00:00 2001 From: Daniel James Date: Sun, 23 Feb 2014 14:29:48 +0000 Subject: [PATCH 3/8] Add metadata --- meta/libraries.xml | 61 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 meta/libraries.xml diff --git a/meta/libraries.xml b/meta/libraries.xml new file mode 100644 index 0000000..a79b7de --- /dev/null +++ b/meta/libraries.xml @@ -0,0 +1,61 @@ + + + + functional + 1.16.0 + Functional + Mark Rodgers + The Boost.Function library contains a family of + class templates that are function object + wrappers. + false + false + Function-objects + + + functional/hash + 1.33.0 + Functional/Hash + Daniel James + A TR1 hash function object that can be extended to + hash user defined types. + hash/ + false + true + Function-objects + + + functional/factory + 1.43.0 + Functional/Factory + Tobias Schwinger + Function object templates for dynamic and static object creation + factory/ + false + false + Function-objects + + + functional/forward + 1.43.0 + Functional/Forward + Tobias Schwinger + Adapters to allow generic function objects to accept arbitrary arguments + forward/ + false + false + Function-objects + + + functional/overloaded_function + 1.50.0 + Functional/Overloaded Function + Lorenzo Caminiti + Overload different functions into a single function + object. + overloaded_function/ + false + false + Function-objects + + From 6c3e20ac18537ce4835b6bdf245bb24670252a9e Mon Sep 17 00:00:00 2001 From: Daniel James Date: Mon, 24 Feb 2014 21:40:10 +0000 Subject: [PATCH 4/8] Json meta data. --- meta/libraries.json | 14 +++++++++++ meta/libraries.xml | 61 --------------------------------------------- 2 files changed, 14 insertions(+), 61 deletions(-) create mode 100644 meta/libraries.json delete mode 100644 meta/libraries.xml diff --git a/meta/libraries.json b/meta/libraries.json new file mode 100644 index 0000000..7796caf --- /dev/null +++ b/meta/libraries.json @@ -0,0 +1,14 @@ +[ + { + "key": "functional/hash", + "boost-version": "1.33.0", + "name": "Functional/Hash", + "authors": "Daniel James", + "description": "A TR1 hash function object that can be extended to hash user defined types.", + "std-proposal": false, + "std-tr1": true, + "category": [ + "Function-objects" + ] + } +] \ No newline at end of file diff --git a/meta/libraries.xml b/meta/libraries.xml deleted file mode 100644 index a79b7de..0000000 --- a/meta/libraries.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - functional - 1.16.0 - Functional - Mark Rodgers - The Boost.Function library contains a family of - class templates that are function object - wrappers. - false - false - Function-objects - - - functional/hash - 1.33.0 - Functional/Hash - Daniel James - A TR1 hash function object that can be extended to - hash user defined types. - hash/ - false - true - Function-objects - - - functional/factory - 1.43.0 - Functional/Factory - Tobias Schwinger - Function object templates for dynamic and static object creation - factory/ - false - false - Function-objects - - - functional/forward - 1.43.0 - Functional/Forward - Tobias Schwinger - Adapters to allow generic function objects to accept arbitrary arguments - forward/ - false - false - Function-objects - - - functional/overloaded_function - 1.50.0 - Functional/Overloaded Function - Lorenzo Caminiti - Overload different functions into a single function - object. - overloaded_function/ - false - false - Function-objects - - From aa3ab0790ad2255555ef66b6fa8932e3209476f9 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Mon, 24 Feb 2014 22:21:03 +0000 Subject: [PATCH 5/8] Add maintainers to metadata. --- meta/libraries.json | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/meta/libraries.json b/meta/libraries.json index 7796caf..0637a08 100644 --- a/meta/libraries.json +++ b/meta/libraries.json @@ -1,14 +1 @@ -[ - { - "key": "functional/hash", - "boost-version": "1.33.0", - "name": "Functional/Hash", - "authors": "Daniel James", - "description": "A TR1 hash function object that can be extended to hash user defined types.", - "std-proposal": false, - "std-tr1": true, - "category": [ - "Function-objects" - ] - } -] \ No newline at end of file +[] \ No newline at end of file From 35ef2502d57697998bc5a97a2b7e5a785f837eb0 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Mon, 24 Feb 2014 22:21:35 +0000 Subject: [PATCH 6/8] Typo --- meta/libraries.json | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/meta/libraries.json b/meta/libraries.json index 0637a08..107679f 100644 --- a/meta/libraries.json +++ b/meta/libraries.json @@ -1 +1,17 @@ -[] \ No newline at end of file +[ + { + "key": "functional/hash", + "boost-version": "1.33.0", + "name": "Functional/Hash", + "authors": "Daniel James", + "maintainers": [ + "Daniel James" + ], + "description": "A TR1 hash function object that can be extended to hash user defined types.", + "std-proposal": false, + "std-tr1": true, + "category": [ + "Function-objects" + ] + } +] \ No newline at end of file From 23f1db7729ad65c84818770f0f3947fc5a4eb88d Mon Sep 17 00:00:00 2001 From: Daniel James Date: Thu, 27 Feb 2014 22:29:01 +0000 Subject: [PATCH 7/8] Update maintainers from /libs/maintainers.txt --- meta/libraries.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/meta/libraries.json b/meta/libraries.json index 107679f..7de78d5 100644 --- a/meta/libraries.json +++ b/meta/libraries.json @@ -4,9 +4,7 @@ "boost-version": "1.33.0", "name": "Functional/Hash", "authors": "Daniel James", - "maintainers": [ - "Daniel James" - ], + "maintainers": "Daniel James ", "description": "A TR1 hash function object that can be extended to hash user defined types.", "std-proposal": false, "std-tr1": true, From d888097468230b8fbc85abb9d25d75609dab8bd0 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Thu, 27 Feb 2014 22:46:55 +0000 Subject: [PATCH 8/8] Regenerate libraries.json --- meta/libraries.json | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/meta/libraries.json b/meta/libraries.json index 7de78d5..d019f6e 100644 --- a/meta/libraries.json +++ b/meta/libraries.json @@ -3,8 +3,12 @@ "key": "functional/hash", "boost-version": "1.33.0", "name": "Functional/Hash", - "authors": "Daniel James", - "maintainers": "Daniel James ", + "authors": [ + "Daniel James" + ], + "maintainers": [ + "Daniel James " + ], "description": "A TR1 hash function object that can be extended to hash user defined types.", "std-proposal": false, "std-tr1": true,