[cfe-commits] [libcxx] r145795 - in /libcxx/trunk: include/memory include/string include/thread test/utilities/function.objects/unord.hash/integral.pass.cpp

Howard Hinnant hhinnant at apple.com
Sun Dec 4 16:08:45 PST 2011


Author: hhinnant
Date: Sun Dec  4 18:08:45 2011
New Revision: 145795

URL: http://llvm.org/viewvc/llvm-project?rev=145795&view=rev
Log:
Starting using murmur2 when combining multiple size_t's into a single hash, and also for basic_string.  Also made hash<thread::id> ever so slighly more portable.  I had to tweak one test which is questionable (definitely not portable) anyway.

Modified:
    libcxx/trunk/include/memory
    libcxx/trunk/include/string
    libcxx/trunk/include/thread
    libcxx/trunk/test/utilities/function.objects/unord.hash/integral.pass.cpp

Modified: libcxx/trunk/include/memory
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/memory?rev=145795&r1=145794&r2=145795&view=diff
==============================================================================
--- libcxx/trunk/include/memory (original)
+++ libcxx/trunk/include/memory Sun Dec  4 18:08:45 2011
@@ -2719,6 +2719,95 @@
 
 template <class _Tp> struct hash;
 
+template <class _Size, size_t = sizeof(_Size)*__CHAR_BIT__>
+struct __murmur2;
+
+template <class _Size>
+struct __murmur2<_Size, 32>
+{
+    _Size operator()(const void* __key, _Size __len);
+};
+
+template <class _Size>
+_Size
+__murmur2<_Size, 32>::operator()(const void* __key, _Size __len)
+{
+    const _Size __m = 0x5bd1e995;
+    const _Size __r = 24;
+    _Size __h = __len;
+    const unsigned char* __data = static_cast<const unsigned char*>(__key);
+    for (; __len >= 4; __data += 4, __len -= 4)
+    {
+        _Size __k = *(const _Size*)__data;
+        __k *= __m;
+        __k ^= __k >> __r;
+        __k *= __m;
+        __h *= __m;
+        __h ^= __k;
+    }
+    switch (__len)
+    {
+    case 3:
+        __h ^= __data[2] << 16;
+    case 2:
+        __h ^= __data[1] << 8;
+    case 1:
+        __h ^= __data[0];
+        __h *= __m;
+    }
+    __h ^= __h >> 13;
+    __h *= __m;
+    __h ^= __h >> 15;
+    return __h;
+}
+
+template <class _Size>
+struct __murmur2<_Size, 64>
+{
+    _Size operator()(const void* __key, _Size __len);
+};
+
+template <class _Size>
+_Size
+__murmur2<_Size, 64>::operator()(const void* __key, _Size __len)
+{
+    const _Size __m = 0xc6a4a7935bd1e995ull;
+    const _Size __r = 47;
+    _Size __h = __len * __m;
+    const unsigned char* __data = static_cast<const unsigned char*>(__key);
+    for (; __len >= 8; __data += 8, __len -= 8)
+    {
+        _Size __k = *(const _Size*)__data;
+        __k *= __m;
+        __k ^= __k >> __r;
+        __k *= __m;
+        __h ^= __k;
+        __h *= __m;
+    }
+    switch (__len)
+    {
+    case 7:
+        __h ^= __data[6] << 48;
+    case 6:
+        __h ^= __data[5] << 40;
+    case 5:
+        __h ^= __data[4] << 32;
+    case 4:
+        __h ^= __data[3] << 24;
+    case 3:
+        __h ^= __data[2] << 16;
+    case 2:
+        __h ^= __data[1] << 8;
+    case 1:
+        __h ^= __data[0];
+        __h *= __m;
+    }
+    __h ^= __h >> __r;
+    __h *= __m;
+    __h ^= __h >> __r;
+    return __h;
+}
+
 template <class _Tp, size_t = sizeof(_Tp) / sizeof(size_t)>
 struct __scalar_hash;
 
@@ -2774,7 +2863,7 @@
             };
         } __u;
         __u.__t = __v;
-        return __u.__a ^ __u.__b;
+        return __murmur2<size_t>()(&__u, sizeof(__u));
     }
 };
 
@@ -2796,7 +2885,7 @@
             };
         } __u;
         __u.__t = __v;
-        return __u.__a ^ __u.__b ^ __u.__c;
+        return __murmur2<size_t>()(&__u, sizeof(__u));
     }
 };
 
@@ -2819,7 +2908,7 @@
             };
         } __u;
         __u.__t = __v;
-        return __u.__a ^ __u.__b ^ __u.__c ^ __u.__d;
+        return __murmur2<size_t>()(&__u, sizeof(__u));
     }
 };
 

Modified: libcxx/trunk/include/string
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/string?rev=145795&r1=145794&r2=145795&view=diff
==============================================================================
--- libcxx/trunk/include/string (original)
+++ libcxx/trunk/include/string Sun Dec  4 18:08:45 2011
@@ -3915,16 +3915,8 @@
 template<class _Ptr>
 size_t _LIBCPP_INLINE_VISIBILITY __do_string_hash(_Ptr __p, _Ptr __e)
 {
-    size_t __r = 0;
-    const size_t __sr = __CHAR_BIT__ * sizeof(size_t) - 8;
-    const size_t __m = size_t(0xF) << (__sr + 4);
-    for (; __p != __e; ++__p)
-    {
-        __r = (__r << 4) + *__p;
-        size_t __g = __r & __m;
-        __r ^= __g | (__g >> __sr);
-    }
-    return __r;
+    typedef typename iterator_traits<_Ptr>::value_type value_type;
+    return __murmur2<size_t>()(__p, (__e-__p)*sizeof(value_type));
 }
 
 template<class _CharT, class _Traits, class _Allocator>

Modified: libcxx/trunk/include/thread
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/thread?rev=145795&r1=145794&r2=145795&view=diff
==============================================================================
--- libcxx/trunk/include/thread (original)
+++ libcxx/trunk/include/thread Sun Dec  4 18:08:45 2011
@@ -183,6 +183,9 @@
 
 }  // this_thread
 
+class _LIBCPP_VISIBLE __thread_id;
+template<> struct _LIBCPP_VISIBLE hash<__thread_id>;
+
 class _LIBCPP_VISIBLE __thread_id
 {
     // FIXME: pthread_t is a pointer on Darwin but a long on Linux.
@@ -226,10 +229,9 @@
 
     friend __thread_id this_thread::get_id();
     friend class _LIBCPP_VISIBLE thread;
+    friend struct _LIBCPP_VISIBLE hash<__thread_id>;
 };
 
-template<class _Tp> struct hash;
-
 template<>
 struct _LIBCPP_VISIBLE hash<__thread_id>
     : public unary_function<__thread_id, size_t>
@@ -237,8 +239,7 @@
     _LIBCPP_INLINE_VISIBILITY
     size_t operator()(__thread_id __v) const
     {
-        const size_t* const __p = reinterpret_cast<const size_t*>(&__v);
-        return *__p;
+        return hash<pthread_t>()(__v.__id_);
     }
 };
 

Modified: libcxx/trunk/test/utilities/function.objects/unord.hash/integral.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/utilities/function.objects/unord.hash/integral.pass.cpp?rev=145795&r1=145794&r2=145795&view=diff
==============================================================================
--- libcxx/trunk/test/utilities/function.objects/unord.hash/integral.pass.cpp (original)
+++ libcxx/trunk/test/utilities/function.objects/unord.hash/integral.pass.cpp Sun Dec  4 18:08:45 2011
@@ -33,7 +33,8 @@
     for (int i = 0; i <= 5; ++i)
     {
         T t(i);
-        assert(h(t) == t);
+        if (sizeof(T) <= sizeof(std::size_t))
+            assert(h(t) == t);
     }
 }
 





More information about the cfe-commits mailing list