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.
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@145795 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
cf2654bae7
commit
40c13d31c5
@ -2719,6 +2719,95 @@ operator>=(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) {re
|
|||||||
|
|
||||||
template <class _Tp> struct hash;
|
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)>
|
template <class _Tp, size_t = sizeof(_Tp) / sizeof(size_t)>
|
||||||
struct __scalar_hash;
|
struct __scalar_hash;
|
||||||
|
|
||||||
@ -2774,7 +2863,7 @@ struct __scalar_hash<_Tp, 2>
|
|||||||
};
|
};
|
||||||
} __u;
|
} __u;
|
||||||
__u.__t = __v;
|
__u.__t = __v;
|
||||||
return __u.__a ^ __u.__b;
|
return __murmur2<size_t>()(&__u, sizeof(__u));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2796,7 +2885,7 @@ struct __scalar_hash<_Tp, 3>
|
|||||||
};
|
};
|
||||||
} __u;
|
} __u;
|
||||||
__u.__t = __v;
|
__u.__t = __v;
|
||||||
return __u.__a ^ __u.__b ^ __u.__c;
|
return __murmur2<size_t>()(&__u, sizeof(__u));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2819,7 +2908,7 @@ struct __scalar_hash<_Tp, 4>
|
|||||||
};
|
};
|
||||||
} __u;
|
} __u;
|
||||||
__u.__t = __v;
|
__u.__t = __v;
|
||||||
return __u.__a ^ __u.__b ^ __u.__c ^ __u.__d;
|
return __murmur2<size_t>()(&__u, sizeof(__u));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3915,16 +3915,8 @@ template<class _CharT, class _Traits, class _Allocator>
|
|||||||
template<class _Ptr>
|
template<class _Ptr>
|
||||||
size_t _LIBCPP_INLINE_VISIBILITY __do_string_hash(_Ptr __p, _Ptr __e)
|
size_t _LIBCPP_INLINE_VISIBILITY __do_string_hash(_Ptr __p, _Ptr __e)
|
||||||
{
|
{
|
||||||
size_t __r = 0;
|
typedef typename iterator_traits<_Ptr>::value_type value_type;
|
||||||
const size_t __sr = __CHAR_BIT__ * sizeof(size_t) - 8;
|
return __murmur2<size_t>()(__p, (__e-__p)*sizeof(value_type));
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class _CharT, class _Traits, class _Allocator>
|
template<class _CharT, class _Traits, class _Allocator>
|
||||||
|
@ -183,6 +183,9 @@ __thread_id get_id();
|
|||||||
|
|
||||||
} // this_thread
|
} // this_thread
|
||||||
|
|
||||||
|
class _LIBCPP_VISIBLE __thread_id;
|
||||||
|
template<> struct _LIBCPP_VISIBLE hash<__thread_id>;
|
||||||
|
|
||||||
class _LIBCPP_VISIBLE __thread_id
|
class _LIBCPP_VISIBLE __thread_id
|
||||||
{
|
{
|
||||||
// FIXME: pthread_t is a pointer on Darwin but a long on Linux.
|
// FIXME: pthread_t is a pointer on Darwin but a long on Linux.
|
||||||
@ -226,10 +229,9 @@ private:
|
|||||||
|
|
||||||
friend __thread_id this_thread::get_id();
|
friend __thread_id this_thread::get_id();
|
||||||
friend class _LIBCPP_VISIBLE thread;
|
friend class _LIBCPP_VISIBLE thread;
|
||||||
|
friend struct _LIBCPP_VISIBLE hash<__thread_id>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class _Tp> struct hash;
|
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct _LIBCPP_VISIBLE hash<__thread_id>
|
struct _LIBCPP_VISIBLE hash<__thread_id>
|
||||||
: public unary_function<__thread_id, size_t>
|
: public unary_function<__thread_id, size_t>
|
||||||
@ -237,8 +239,7 @@ struct _LIBCPP_VISIBLE hash<__thread_id>
|
|||||||
_LIBCPP_INLINE_VISIBILITY
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
size_t operator()(__thread_id __v) const
|
size_t operator()(__thread_id __v) const
|
||||||
{
|
{
|
||||||
const size_t* const __p = reinterpret_cast<const size_t*>(&__v);
|
return hash<pthread_t>()(__v.__id_);
|
||||||
return *__p;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -33,7 +33,8 @@ test()
|
|||||||
for (int i = 0; i <= 5; ++i)
|
for (int i = 0; i <= 5; ++i)
|
||||||
{
|
{
|
||||||
T t(i);
|
T t(i);
|
||||||
assert(h(t) == t);
|
if (sizeof(T) <= sizeof(std::size_t))
|
||||||
|
assert(h(t) == t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user