[cfe-commits] [libcxx] r145778 - in /libcxx/trunk/include: functional memory

Howard Hinnant hhinnant at apple.com
Sat Dec 3 13:11:36 PST 2011


Author: hhinnant
Date: Sat Dec  3 15:11:36 2011
New Revision: 145778

URL: http://llvm.org/viewvc/llvm-project?rev=145778&view=rev
Log:
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<float>.  Most of the functionality has been put in one place:  __scalar_hash in <memory>.  Unfortunately I could not reuse __scalar_hash for hash<long double> 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<string> issue (possibly changing that to a better hash).  I just haven't gotten there yet.

Modified:
    libcxx/trunk/include/functional
    libcxx/trunk/include/memory

Modified: libcxx/trunk/include/functional
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/functional?rev=145778&r1=145777&r2=145778&view=diff
==============================================================================
--- libcxx/trunk/include/functional (original)
+++ libcxx/trunk/include/functional Sat Dec  3 15:11:36 2011
@@ -1916,123 +1916,91 @@
 
 template <>
 struct _LIBCPP_VISIBLE hash<long long>
-    : public unary_function<long long, size_t>
+    : public __scalar_hash<long long>
 {
-    _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<unsigned long long>
-    : public unary_function<unsigned long long, size_t>
+    : public __scalar_hash<unsigned long long>
 {
-    _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<float>
-    : public unary_function<float, size_t>
+    : public __scalar_hash<float>
 {
     _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<float>::operator()(__v);
     }
 };
 
 template <>
 struct _LIBCPP_VISIBLE hash<double>
-    : public unary_function<double, size_t>
+    : public __scalar_hash<double>
 {
     _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<double>::operator()(__v);
     }
 };
 
 template <>
 struct _LIBCPP_VISIBLE hash<long double>
-    : public unary_function<long double, size_t>
+    : public __scalar_hash<long double>
 {
     _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.__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.__f = __v;
-        return __u.__d;
+        __u.__a = 0;
+        __u.__b = 0;
+        __u.__t = __v;
+        return __u.__a ^ __u.__b;
+#else
+        return __scalar_hash<long double>::operator()(__v);
+#endif
     }
 };
 

Modified: libcxx/trunk/include/memory
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/memory?rev=145778&r1=145777&r2=145778&view=diff
==============================================================================
--- libcxx/trunk/include/memory (original)
+++ libcxx/trunk/include/memory Sat Dec  3 15:11:36 2011
@@ -2719,18 +2719,116 @@
 
 template <class _Tp> struct hash;
 
-template<class _Tp>
-struct _LIBCPP_VISIBLE hash<_Tp*>
-    : public unary_function<_Tp*, size_t>
+template <class _Tp, size_t = sizeof(_Tp) / sizeof(size_t)>
+struct __scalar_hash;
+
+template <class _Tp>
+struct __scalar_hash<_Tp, 0>
+    : public unary_function<_Tp, size_t>
+{
+    _LIBCPP_INLINE_VISIBILITY
+    size_t operator()(_Tp __v) const _NOEXCEPT
+    {
+        union
+        {
+            _Tp    __t;
+            size_t __a;
+        } __u;
+        __u.__a = 0;
+        __u.__t = __v;
+        return __u.__a;
+    }
+};
+
+template <class _Tp>
+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 <class _Tp>
+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 <class _Tp>
+struct __scalar_hash<_Tp, 3>
+    : 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<const size_t*>(&__v);
-        return *__p;
+        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 <class _Tp>
+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<class _Tp>
+struct _LIBCPP_VISIBLE hash<_Tp*>
+    : public __scalar_hash<_Tp*>
+{
+};
+
 template <class _Tp, class _Dp>
 struct _LIBCPP_VISIBLE hash<unique_ptr<_Tp, _Dp> >
 {





More information about the cfe-commits mailing list