From cf2654bae716cbcc70a45adfcb46c211121565d7 Mon Sep 17 00:00:00 2001 From: Howard Hinnant Date: Sat, 3 Dec 2011 21:11:36 +0000 Subject: [PATCH] Version #next on the hash functions for scalars. This builds on Dave's work, extends it to T*, and changes the way double and long double are handled (no longer convert to float on 32 bit). I also picked up a minor bug with uninitialized bits on the upper end of size_t when sizeof(size_t) > sizeof(T), e.g. in hash. Most of the functionality has been put in one place: __scalar_hash in . Unfortunately I could not reuse __scalar_hash for hash on x86 because of the padding bits which need to be zeroed. I didn't want to add this zeroing step to the more general __scalar_hash when it isn't needed (in the absence of padding bits). I'm not ignoring the hash issue (possibly changing that to a better hash). I just haven't gotten there yet. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@145778 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/functional | 122 +++++++++++++++++---------------------------- include/memory | 110 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 149 insertions(+), 83 deletions(-) diff --git a/include/functional b/include/functional index 243f3984d..ee0424d07 100644 --- a/include/functional +++ b/include/functional @@ -1916,123 +1916,91 @@ struct _LIBCPP_VISIBLE hash template <> struct _LIBCPP_VISIBLE hash - : public unary_function + : public __scalar_hash { - _LIBCPP_INLINE_VISIBILITY - size_t operator()(long long __v) const _NOEXCEPT - { - if (sizeof(long long) == sizeof(size_t)) - return __v; - union - { - long long __l; - struct - { - size_t __a; - size_t __b; - } __s; - } __u; - __u.__l = __v; - return __u.__s.__a ^ __u.__s.__b; - } }; template <> struct _LIBCPP_VISIBLE hash - : public unary_function + : public __scalar_hash { - _LIBCPP_INLINE_VISIBILITY - size_t operator()(unsigned long long __v) const _NOEXCEPT - { - if (sizeof(unsigned long long) == sizeof(size_t)) - return __v; - union - { - unsigned long long __l; - struct - { - size_t __a; - size_t __b; - } __s; - } __u; - __u.__l = __v; - return __u.__s.__a ^ __u.__s.__b; - } }; template <> struct _LIBCPP_VISIBLE hash - : public unary_function + : public __scalar_hash { _LIBCPP_INLINE_VISIBILITY size_t operator()(float __v) const _NOEXCEPT { + // -0.0 and 0.0 should return same hash if (__v == 0) return 0; - union - { - size_t __d; - float __f; - } __u; - __u.__f = __v; - return __u.__d; + return __scalar_hash::operator()(__v); } }; template <> struct _LIBCPP_VISIBLE hash - : public unary_function + : public __scalar_hash { _LIBCPP_INLINE_VISIBILITY size_t operator()(double __v) const _NOEXCEPT { - if (__v == 0) - return 0; - if (sizeof(double) == sizeof(size_t)) - { - union - { - double __f; - size_t __d; - } __u; - __u.__f = __v; - return __u.__d; - } - union - { - float __f; - size_t __d; - } __u; - __u.__f = __v; - return __u.__d; + // -0.0 and 0.0 should return same hash + if (__v == 0) + return 0; + return __scalar_hash::operator()(__v); } }; template <> struct _LIBCPP_VISIBLE hash - : public unary_function + : public __scalar_hash { _LIBCPP_INLINE_VISIBILITY size_t operator()(long double __v) const _NOEXCEPT { + // -0.0 and 0.0 should return same hash if (__v == 0) return 0; - if (sizeof(double) == sizeof(size_t)) +#if defined(__i386__) + // Zero out padding bits + union { - union + long double __t; + struct { - double __f; + size_t __a; + size_t __b; + size_t __c; size_t __d; - } __u; - __u.__f = __v; - return __u.__d; - } - union { - float __f; - size_t __d; + }; } __u; - __u.__f = __v; - return __u.__d; + __u.__a = 0; + __u.__b = 0; + __u.__c = 0; + __u.__d = 0; + __u.__t = __v; + return __u.__a ^ __u.__b ^ __u.__c ^ __u.__d; +#elif defined(__x86_64__) + // Zero out padding bits + union + { + long double __t; + struct + { + size_t __a; + size_t __b; + }; + } __u; + __u.__a = 0; + __u.__b = 0; + __u.__t = __v; + return __u.__a ^ __u.__b; +#else + return __scalar_hash::operator()(__v); +#endif } }; diff --git a/include/memory b/include/memory index e8abdbeee..bab71b4da 100644 --- a/include/memory +++ b/include/memory @@ -2719,18 +2719,116 @@ operator>=(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {re template struct hash; -template -struct _LIBCPP_VISIBLE hash<_Tp*> - : public unary_function<_Tp*, size_t> +template +struct __scalar_hash; + +template +struct __scalar_hash<_Tp, 0> + : public unary_function<_Tp, size_t> { _LIBCPP_INLINE_VISIBILITY - size_t operator()(_Tp* __v) const _NOEXCEPT + size_t operator()(_Tp __v) const _NOEXCEPT { - const size_t* const __p = reinterpret_cast(&__v); - return *__p; + union + { + _Tp __t; + size_t __a; + } __u; + __u.__a = 0; + __u.__t = __v; + return __u.__a; } }; +template +struct __scalar_hash<_Tp, 1> + : public unary_function<_Tp, size_t> +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(_Tp __v) const _NOEXCEPT + { + union + { + _Tp __t; + size_t __a; + } __u; + __u.__t = __v; + return __u.__a; + } +}; + +template +struct __scalar_hash<_Tp, 2> + : public unary_function<_Tp, size_t> +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(_Tp __v) const _NOEXCEPT + { + union + { + _Tp __t; + struct + { + size_t __a; + size_t __b; + }; + } __u; + __u.__t = __v; + return __u.__a ^ __u.__b; + } +}; + +template +struct __scalar_hash<_Tp, 3> + : public unary_function<_Tp, size_t> +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(_Tp __v) const _NOEXCEPT + { + union + { + _Tp __t; + struct + { + size_t __a; + size_t __b; + size_t __c; + }; + } __u; + __u.__t = __v; + return __u.__a ^ __u.__b ^ __u.__c; + } +}; + +template +struct __scalar_hash<_Tp, 4> + : public unary_function<_Tp, size_t> +{ + _LIBCPP_INLINE_VISIBILITY + size_t operator()(_Tp __v) const _NOEXCEPT + { + union + { + _Tp __t; + struct + { + size_t __a; + size_t __b; + size_t __c; + size_t __d; + }; + } __u; + __u.__t = __v; + return __u.__a ^ __u.__b ^ __u.__c ^ __u.__d; + } +}; + +template +struct _LIBCPP_VISIBLE hash<_Tp*> + : public __scalar_hash<_Tp*> +{ +}; + template struct _LIBCPP_VISIBLE hash > {