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.
llvm-svn: 145795
Cr-Mirrored-From: sso://chromium.googlesource.com/_direct/external/github.com/llvm/llvm-project
Cr-Mirrored-Commit: f3d14a65ca0bc0e4f7548eb643d5e55e59429b1e
diff --git a/include/memory b/include/memory
index bab71b4..e6cfa07 100644
--- a/include/memory
+++ b/include/memory
@@ -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));
}
};
diff --git a/include/string b/include/string
index 575b9e1..4457e4a 100644
--- a/include/string
+++ b/include/string
@@ -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>
diff --git a/include/thread b/include/thread
index 2e82846..23b1915 100644
--- a/include/thread
+++ b/include/thread
@@ -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_);
}
};