diff --git a/hash/doc/Jamfile.v2 b/hash/doc/Jamfile.v2 index 8909a83..700ad8a 100644 --- a/hash/doc/Jamfile.v2 +++ b/hash/doc/Jamfile.v2 @@ -12,4 +12,15 @@ boostbook standalone : hash : chunk.section.depth=2 generate.section.toc.level=2 toc.section.depth=1 - toc.max.depth=1 ; + toc.max.depth=1 + + css + images + ; + +install css : [ glob $(BOOST_ROOT)/doc/src/*.css ] + : html ; +install images : [ glob $(BOOST_ROOT)/doc/src/images/*.png ] + : html/images ; +explicit css ; +explicit images ; diff --git a/hash/test/hash_float_test.hpp b/hash/test/hash_float_test.hpp index 2fda7b8..7e698b1 100644 --- a/hash/test/hash_float_test.hpp +++ b/hash/test/hash_float_test.hpp @@ -29,12 +29,12 @@ void float_tests(char const* name, T* = 0) std::cerr<<"\n" <<"Testing " BOOST_STRINGIZE(HASH_NAMESPACE) "::hash<"<\n" <<"\n" - <<"std::numeric_limits::digits = " - <::digits<<"\n" - <<"std::numeric_limits::digits = " - <::digits<<"\n" - <<"std::numeric_limits::digits = " - <::digits<<"\n" + <<"boost::hash_detail::limits::digits = " + <::digits<<"\n" + <<"boost::hash_detail::limits::digits = " + <::digits<<"\n" + <<"boost::hash_detail::limits::digits = " + <::digits<<"\n" <<"\n" ; @@ -55,11 +55,11 @@ void float_tests(char const* name, T* = 0) #if defined(__BORLANDC__) std::cerr<<"Not running infinity checks on Borland, as it causes it to crash.\n"; #else - if(std::numeric_limits::has_infinity) { + if(boost::hash_detail::limits::has_infinity) { T infinity = -log(zero); T infinity2 = (T) 1. / zero; T infinity3 = (T) -1. / minus_zero; - T infinity4 = std::numeric_limits::infinity(); + T infinity4 = boost::hash_detail::limits::infinity(); T minus_infinity = log(zero); T minus_infinity2 = (T) -1. / zero; @@ -89,26 +89,26 @@ void float_tests(char const* name, T* = 0) // This should really be 'has_denorm == denorm_present' but some // compilers don't have 'denorm_present'. See also a later use. - if(std::numeric_limits::has_denorm) { - if(x1(std::numeric_limits::denorm_min()) == x1(infinity)) { + if(boost::hash_detail::limits::has_denorm) { + if(x1(boost::hash_detail::limits::denorm_min()) == x1(infinity)) { std::cerr<<"x1(denorm_min) == x1(infinity) == "<::denorm_min()) == x1(minus_infinity)) { + if(x1(boost::hash_detail::limits::denorm_min()) == x1(minus_infinity)) { std::cerr<<"x1(denorm_min) == x1(-infinity) == "<::has_quiet_NaN) { - if(x1(std::numeric_limits::quiet_NaN()) == x1(infinity)) { + if(boost::hash_detail::limits::has_quiet_NaN) { + if(x1(boost::hash_detail::limits::quiet_NaN()) == x1(infinity)) { std::cerr<<"x1(quiet_NaN) == x1(infinity) == "<::quiet_NaN()) == x1(minus_infinity)) { + if(x1(boost::hash_detail::limits::quiet_NaN()) == x1(minus_infinity)) { std::cerr<<"x1(quiet_NaN) == x1(-infinity) == "<::max)(); + T max = (boost::hash_detail::limits::max)(); T half_max = max / 2; T quarter_max = max / 4; T three_quarter_max = max - quarter_max; @@ -142,50 +142,50 @@ void float_tests(char const* name, T* = 0) BOOST_TEST(x1(v2) == HASH_NAMESPACE::hash_value(v2)); #endif - BOOST_TEST(x1(std::numeric_limits::epsilon()) == - HASH_NAMESPACE::hash_value(std::numeric_limits::epsilon())); + BOOST_TEST(x1(boost::hash_detail::limits::epsilon()) == + HASH_NAMESPACE::hash_value(boost::hash_detail::limits::epsilon())); - BOOST_TEST(std::numeric_limits::epsilon() != (T) 0); - if(x1(std::numeric_limits::epsilon()) == x1((T) 0)) + BOOST_TEST(boost::hash_detail::limits::epsilon() != (T) 0); + if(x1(boost::hash_detail::limits::epsilon()) == x1((T) 0)) std::cerr<<"x1(epsilon) == x1(0) == "<::epsilon() != (T) 0); - if(x1(-std::numeric_limits::epsilon()) == x1((T) 0)) + BOOST_TEST(-boost::hash_detail::limits::epsilon() != (T) 0); + if(x1(-boost::hash_detail::limits::epsilon()) == x1((T) 0)) std::cerr<<"x1(-epsilon) == x1(0) == "<::epsilon() != (T) 1); - if(x1((T) 1 + std::numeric_limits::epsilon()) == x1((T) 1)) + BOOST_TEST((T) 1 + boost::hash_detail::limits::epsilon() != (T) 1); + if(x1((T) 1 + boost::hash_detail::limits::epsilon()) == x1((T) 1)) std::cerr<<"x1(1 + epsilon) == x1(1) == "<::epsilon() != (T) 1); - if(x1((T) 1 - std::numeric_limits::epsilon()) == x1((T) 1)) + BOOST_TEST((T) 1 - boost::hash_detail::limits::epsilon() != (T) 1); + if(x1((T) 1 - boost::hash_detail::limits::epsilon()) == x1((T) 1)) std::cerr<<"x1(1 - epsilon) == x1(1) == "<::epsilon() != (T) -1); - if(x1((T) -1 + std::numeric_limits::epsilon()) == x1((T) -1)) + BOOST_TEST((T) -1 + boost::hash_detail::limits::epsilon() != (T) -1); + if(x1((T) -1 + boost::hash_detail::limits::epsilon()) == x1((T) -1)) std::cerr<<"x1(-1 + epsilon) == x1(-1) == "<::epsilon() != (T) -1); - if(x1((T) -1 - std::numeric_limits::epsilon()) == x1((T) -1)) + BOOST_TEST((T) -1 - boost::hash_detail::limits::epsilon() != (T) -1); + if(x1((T) -1 - boost::hash_detail::limits::epsilon()) == x1((T) -1)) std::cerr<<"x1(-1 - epsilon) == x1(-1) == "<::has_denorm) { - if(x1(std::numeric_limits::denorm_min()) == x1(zero)) { + if(boost::hash_detail::limits::has_denorm) { + if(x1(boost::hash_detail::limits::denorm_min()) == x1(zero)) { std::cerr<<"x1(denorm_min) == x1(zero) == "<::denorm_min()) != - HASH_NAMESPACE::hash_value(std::numeric_limits::denorm_min())) + if(x1(boost::hash_detail::limits::denorm_min()) != + HASH_NAMESPACE::hash_value(boost::hash_detail::limits::denorm_min())) { - std::cerr<<"x1(std::numeric_limits::denorm_min()) = " - << x1(std::numeric_limits::denorm_min()) - << "\nhash_value(std::numeric_limits::denorm_min()) = " + std::cerr<<"x1(boost::hash_detail::limits::denorm_min()) = " + << x1(boost::hash_detail::limits::denorm_min()) + << "\nhash_value(boost::hash_detail::limits::denorm_min()) = " << HASH_NAMESPACE::hash_value( - std::numeric_limits::denorm_min()) + boost::hash_detail::limits::denorm_min()) << "\nx1(0) = "<::has_quiet_NaN) { - if(x1(std::numeric_limits::quiet_NaN()) == x1(1.0)) { + if(boost::hash_detail::limits::has_quiet_NaN) { + if(x1(boost::hash_detail::limits::quiet_NaN()) == x1(1.0)) { std::cerr<<"x1(quiet_NaN) == x1(1.0) == "<::quiet_NaN()) == - HASH_NAMESPACE::hash_value(std::numeric_limits::quiet_NaN())); + BOOST_TEST(x1(boost::hash_detail::limits::quiet_NaN()) == + HASH_NAMESPACE::hash_value(boost::hash_detail::limits::quiet_NaN())); } #endif } diff --git a/hash/test/hash_number_test.cpp b/hash/test/hash_number_test.cpp index 204f84b..54cbf85 100644 --- a/hash/test/hash_number_test.cpp +++ b/hash/test/hash_number_test.cpp @@ -31,7 +31,7 @@ template void numeric_test(T*) { - typedef std::numeric_limits limits; + typedef boost::hash_detail::limits limits; compile_time_tests((T*) 0); @@ -55,7 +55,7 @@ void numeric_test(T*) if (limits::is_integer) { - if(limits::is_signed || limits::digits <= std::numeric_limits::digits) + if(limits::is_signed || limits::digits <= boost::hash_detail::limits::digits) BOOST_TEST(HASH_NAMESPACE::hash_value(T(-5)) == (std::size_t)T(-5)); BOOST_TEST(HASH_NAMESPACE::hash_value(T(0)) == (std::size_t)T(0u)); BOOST_TEST(HASH_NAMESPACE::hash_value(T(10)) == (std::size_t)T(10u)); @@ -67,7 +67,7 @@ void numeric_test(T*) template void limits_test(T*) { - typedef std::numeric_limits limits; + typedef boost::hash_detail::limits limits; if(limits::is_specialized) { @@ -98,7 +98,7 @@ void limits_test(T*) template void poor_quality_tests(T*) { - typedef std::numeric_limits limits; + typedef boost::hash_detail::limits limits; HASH_NAMESPACE::hash x1; HASH_NAMESPACE::hash x2; diff --git a/include/boost/functional/detail/hash_float.hpp b/include/boost/functional/detail/hash_float.hpp index 92b2b66..6c75c02 100644 --- a/include/boost/functional/detail/hash_float.hpp +++ b/include/boost/functional/detail/hash_float.hpp @@ -54,10 +54,43 @@ #endif +// On OpenBSD, numeric_limits is not reliable for long doubles, but +// the macros defined in are. + +#if defined(__OpenBSD__) +#include +#endif + namespace boost { namespace hash_detail { + template + struct limits : std::numeric_limits {}; + +#if defined(__OpenBSD__) + template <> + struct limits + : std::numeric_limits + { + static long double epsilon() { + return LDBL_EPSILON; + } + + static long double (max)() { + return LDBL_MAX; + } + + static long double (min)() { + return LDBL_MIN; + } + + BOOST_STATIC_CONSTANT(int, digits = LDBL_MANT_DIG); + BOOST_STATIC_CONSTANT(int, max_exponent = LDBL_MAX_EXP); + BOOST_STATIC_CONSTANT(int, min_exponent = LDBL_MIN_EXP); + }; +#endif // __OpenBSD__ + inline void hash_float_combine(std::size_t& seed, std::size_t value) { seed ^= value + (seed<<6) + (seed>>2); @@ -102,29 +135,28 @@ namespace boost // sign with the exponent. if(v < 0) { v = -v; - exp += std::numeric_limits::max_exponent - - std::numeric_limits::min_exponent; + exp += limits::max_exponent - + limits::min_exponent; } // The result of frexp is always between 0.5 and 1, so its // top bit will always be 1. Subtract by 0.5 to remove that. v -= T(0.5); v = boost::hash_detail::call_ldexp(v, - std::numeric_limits::digits + 1); + limits::digits + 1); std::size_t seed = static_cast(v); v -= seed; // ceiling(digits(T) * log2(radix(T))/ digits(size_t)) - 1; std::size_t const length - = (std::numeric_limits::digits * - boost::static_log2::radix>::value - - 1) - / std::numeric_limits::digits; + = (limits::digits * + boost::static_log2::radix>::value - 1) + / limits::digits; for(std::size_t i = 0; i != length; ++i) { v = boost::hash_detail::call_ldexp(v, - std::numeric_limits::digits); + limits::digits); std::size_t part = static_cast(v); v -= part; hash_float_combine(seed, part); diff --git a/include/boost/functional/hash.hpp b/include/boost/functional/hash.hpp index 60b2608..508f49a 100644 --- a/include/boost/functional/hash.hpp +++ b/include/boost/functional/hash.hpp @@ -8,3 +8,4 @@ // issue 6.18. #include + diff --git a/include/boost/functional/hash/extensions.hpp b/include/boost/functional/hash/extensions.hpp new file mode 100644 index 0000000..3681e0e --- /dev/null +++ b/include/boost/functional/hash/extensions.hpp @@ -0,0 +1,182 @@ + +// Copyright 2005-2007 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. + +#if !defined(BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP) +#define BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +namespace boost +{ + +#if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) + namespace hash_detail + { + template + struct call_hash_impl + { + template + struct inner + { + static std::size_t call(T const& v) + { + using namespace boost; + return hash_value(v); + } + }; + }; + + template <> + struct call_hash_impl + { + template + struct inner + { +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) + static std::size_t call(Array const& v) +#else + static std::size_t call(Array& v) +#endif + { + const int size = sizeof(v) / sizeof(*v); + return boost::hash_range(v, v + size); + } + }; + }; + + template + struct call_hash + : public call_hash_impl::value> + ::BOOST_NESTED_TEMPLATE inner + { + }; + } +#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + + template struct hash + : std::unary_function + { +#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) + std::size_t operator()(T const& val) const + { + return hash_value(val); + } +#else + std::size_t operator()(T const& val) const + { + return hash_detail::call_hash::call(val); + } +#endif + }; + +#if BOOST_WORKAROUND(__DMC__, <= 0x848) + template struct hash + : std::unary_function + { + std::size_t operator()(const T* val) const + { + return boost::hash_range(val, val+n); + } + }; +#endif + +#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + // On compilers without partial specialization, boost::hash + // has already been declared to deal with pointers, so just + // need to supply the non-pointer version. + + namespace hash_detail + { + template + struct hash_impl; + +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) + + template <> + struct hash_impl + { + template + struct inner + : std::unary_function + { +#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) + std::size_t operator()(T const& val) const + { + return hash_value(val); + } +#else + std::size_t operator()(T const& val) const + { + return hash_detail::call_hash::call(val); + } +#endif + }; + }; + +#else // Visual C++ 6.5 + + // There's probably a more elegant way to Visual C++ 6.5 to work + // but I don't know what it is. + + template + struct hash_impl_msvc + { + template + struct inner + : public std::unary_function + { + std::size_t operator()(T const& val) const + { + return hash_detail::call_hash::call(val); + } + + std::size_t operator()(T& val) const + { + return hash_detail::call_hash::call(val); + } + }; + }; + + template <> + struct hash_impl_msvc + { + template + struct inner + : public std::unary_function + { + std::size_t operator()(T& val) const + { + return hash_detail::call_hash::call(val); + } + }; + }; + + template + struct hash_impl_msvc2 + : public hash_impl_msvc::value> + ::BOOST_NESTED_TEMPLATE inner {}; + + template <> + struct hash_impl + { + template + struct inner : public hash_impl_msvc2 {}; + }; + +#endif // Visual C++ 6.5 + } +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +} + +#endif diff --git a/include/boost/functional/hash/hash.hpp b/include/boost/functional/hash/hash.hpp index b11862c..45ab213 100644 --- a/include/boost/functional/hash/hash.hpp +++ b/include/boost/functional/hash/hash.hpp @@ -518,176 +518,12 @@ namespace boost } #endif // BOOST_FUNCTIONAL_HASH_HASH_HPP -//////////////////////////////////////////////////////////////////////////////// + +// Include this outside of the include guards in case the file is included +// twice - once with BOOST_HASH_NO_EXTENSIONS defined, and then with it +// undefined. #if !defined(BOOST_HASH_NO_EXTENSIONS) \ && !defined(BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP) -#define BOOST_FUNCTIONAL_HASH_EXTENSIONS_HPP - -namespace boost -{ - -#if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) - namespace hash_detail - { - template - struct call_hash_impl - { - template - struct inner - { - static std::size_t call(T const& v) - { - using namespace boost; - return hash_value(v); - } - }; - }; - - template <> - struct call_hash_impl - { - template - struct inner - { -#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) - static std::size_t call(Array const& v) -#else - static std::size_t call(Array& v) +#include #endif - { - const int size = sizeof(v) / sizeof(*v); - return boost::hash_range(v, v + size); - } - }; - }; - - template - struct call_hash - : public call_hash_impl::value> - ::BOOST_NESTED_TEMPLATE inner - { - }; - } -#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING - -#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) - - template struct hash - : std::unary_function - { -#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) - std::size_t operator()(T const& val) const - { - return hash_value(val); - } -#else - std::size_t operator()(T const& val) const - { - return hash_detail::call_hash::call(val); - } -#endif - }; - -#if BOOST_WORKAROUND(__DMC__, <= 0x848) - template struct hash - : std::unary_function - { - std::size_t operator()(const T* val) const - { - return boost::hash_range(val, val+n); - } - }; -#endif - -#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - - // On compilers without partial specialization, boost::hash - // has already been declared to deal with pointers, so just - // need to supply the non-pointer version. - - namespace hash_detail - { - template - struct hash_impl; - -#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) - - template <> - struct hash_impl - { - template - struct inner - : std::unary_function - { -#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING) - std::size_t operator()(T const& val) const - { - return hash_value(val); - } -#else - std::size_t operator()(T const& val) const - { - return hash_detail::call_hash::call(val); - } -#endif - }; - }; - -#else // Visual C++ 6.5 - - // There's probably a more elegant way to Visual C++ 6.5 to work - // but I don't know what it is. - - template - struct hash_impl_msvc - { - template - struct inner - : public std::unary_function - { - std::size_t operator()(T const& val) const - { - return hash_detail::call_hash::call(val); - } - - std::size_t operator()(T& val) const - { - return hash_detail::call_hash::call(val); - } - }; - }; - - template <> - struct hash_impl_msvc - { - template - struct inner - : public std::unary_function - { - std::size_t operator()(T& val) const - { - return hash_detail::call_hash::call(val); - } - }; - }; - - template - struct hash_impl_msvc2 - : public hash_impl_msvc::value> - ::BOOST_NESTED_TEMPLATE inner {}; - - template <> - struct hash_impl - { - template - struct inner : public hash_impl_msvc2 {}; - }; - -#endif // Visual C++ 6.5 - } -#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -} - -#endif -