murmur3: streamline 128 bit hash round functions

clang was getting tripped up calculating the tail half-rounds for the
128 bit hashes, so we streamline the round functions so it copes a
little better. plus, this is better code anyway.
This commit is contained in:
Danny Robson 2015-09-21 15:32:23 +10:00
parent ec42319224
commit 2469450ea9

View File

@ -143,7 +143,7 @@ traits<uint64_t>::X[] = {
///////////////////////////////////////////////////////////////////////////////
template <typename T>
std::array<T,traits<T>::COMPONENTS>
T
half_round (std::array<T,traits<T>::COMPONENTS> h,
std::array<T,traits<T>::COMPONENTS> k,
size_t i)
@ -155,8 +155,8 @@ half_round (std::array<T,traits<T>::COMPONENTS> h,
k[i] *= CONSTANTS[i].c;
k[i] = rotatel (k[i], CONSTANTS[i].Ks);
k[i] *= CONSTANTS[i_].c;
h[i] ^= k[i];
return h;
return h[i] ^= k[i];
}
@ -164,18 +164,19 @@ half_round (std::array<T,traits<T>::COMPONENTS> h,
template <typename T>
std::array<T,traits<T>::COMPONENTS>
full_round (std::array<T,traits<T>::COMPONENTS> h,
std::array<T,traits<T>::COMPONENTS> k,
size_t i)
std::array<T,traits<T>::COMPONENTS> k)
{
auto COMPONENTS = traits<T>::COMPONENTS;
auto CONSTANTS = traits<T>::X;
h = half_round (h, k, i);
for (size_t i = 0; i < COMPONENTS; ++i) {
h[i] = half_round (h, k, i);
auto i_ = (i + 1) % COMPONENTS;
h[i] = rotatel (h[i], CONSTANTS[i].Hs);
h[i] += h[i_];
h[i] = h[i] * 5 + CONSTANTS[i].O;
auto i_ = (i + 1) % COMPONENTS;
h[i] = rotatel (h[i], CONSTANTS[i].Hs);
h[i] += h[i_];
h[i] = h[i] * 5 + CONSTANTS[i].O;
}
return h;
}
@ -202,8 +203,7 @@ hash_128 (const void *restrict key,
result_t k;
std::copy_n (cursor, traits<T>::COMPONENTS, k.begin ());
for (size_t i = 0; i < traits<T>::COMPONENTS; ++i)
h = full_round (h, k, i);
h = full_round (h, k);
}
// process the tail
@ -214,25 +214,21 @@ hash_128 (const void *restrict key,
v = 0 ^ v;
for (size_t i = 0; i < traits<T>::COMPONENTS; ++i)
h = half_round (h, k, i);
h[i] = half_round (h, k, i);
}
// finalise the hash
for (auto &v: h)
v ^= len;
for (size_t i = 1; i < traits<T>::COMPONENTS; ++i)
h[0] += h[i];
for (size_t i = 1; i < traits<T>::COMPONENTS; ++i)
h[i] += h[0];
for (size_t i = 1; i < traits<T>::COMPONENTS; ++i) h[0] += h[i];
for (size_t i = 1; i < traits<T>::COMPONENTS; ++i) h[i] += h[0];
for (auto &v: h)
v = util::hash::murmur3::mix (v);
for (size_t i = 1; i < traits<T>::COMPONENTS; ++i)
h[0] += h[i];
for (size_t i = 1; i < traits<T>::COMPONENTS; ++i)
h[i] += h[0];
for (size_t i = 1; i < traits<T>::COMPONENTS; ++i) h[0] += h[i];
for (size_t i = 1; i < traits<T>::COMPONENTS; ++i) h[i] += h[0];
return h;
}