2014-11-28 06:13:18 -05:00
|
|
|
#ifndef XOR_FAST_HASH_HPP
|
|
|
|
#define XOR_FAST_HASH_HPP
|
2012-05-25 05:41:52 -04:00
|
|
|
|
2016-01-21 09:56:08 -05:00
|
|
|
#include <boost/assert.hpp>
|
|
|
|
|
2012-05-25 05:41:52 -04:00
|
|
|
#include <algorithm>
|
2016-05-27 15:05:04 -04:00
|
|
|
#include <array>
|
2016-01-21 09:56:08 -05:00
|
|
|
#include <iterator>
|
|
|
|
#include <numeric>
|
|
|
|
#include <random>
|
2012-05-25 05:41:52 -04:00
|
|
|
#include <vector>
|
|
|
|
|
2016-01-21 10:11:33 -05:00
|
|
|
#include <cstdint>
|
|
|
|
|
2016-01-05 10:51:13 -05:00
|
|
|
namespace osrm
|
|
|
|
{
|
|
|
|
namespace util
|
|
|
|
{
|
|
|
|
|
2012-05-25 05:41:52 -04:00
|
|
|
/*
|
2014-05-07 12:39:16 -04:00
|
|
|
This is an implementation of Tabulation hashing, which has suprising properties like
|
|
|
|
universality.
|
2012-05-25 05:41:52 -04:00
|
|
|
The space requirement is 2*2^16 = 256 kb of memory, which fits into L2 cache.
|
|
|
|
Evaluation boils down to 10 or less assembly instruction on any recent X86 CPU:
|
|
|
|
|
|
|
|
1: movq table2(%rip), %rdx
|
|
|
|
2: movl %edi, %eax
|
|
|
|
3: movzwl %di, %edi
|
|
|
|
4: shrl $16, %eax
|
|
|
|
5: movzwl %ax, %eax
|
|
|
|
6: movzbl (%rdx,%rax), %eax
|
|
|
|
7: movq table1(%rip), %rdx
|
|
|
|
8: xorb (%rdx,%rdi), %al
|
|
|
|
9: movzbl %al, %eax
|
|
|
|
10: ret
|
|
|
|
|
|
|
|
*/
|
2016-01-21 13:17:02 -05:00
|
|
|
template <std::size_t MaxNumElements = (1u << 16u)> class XORFastHash
|
|
|
|
{
|
|
|
|
static_assert(MaxNumElements <= (1u << 16u), "only 65536 elements indexable with uint16_t");
|
|
|
|
|
|
|
|
std::array<std::uint16_t, MaxNumElements> table1;
|
|
|
|
std::array<std::uint16_t, MaxNumElements> table2;
|
2014-05-07 12:39:16 -04:00
|
|
|
|
|
|
|
public:
|
|
|
|
XORFastHash()
|
|
|
|
{
|
2016-01-21 09:56:08 -05:00
|
|
|
std::mt19937 generator; // impl. defined but deterministic default seed
|
|
|
|
|
|
|
|
std::iota(begin(table1), end(table1), 0u);
|
|
|
|
std::shuffle(begin(table1), end(table1), generator);
|
|
|
|
|
|
|
|
std::iota(begin(table2), end(table2), 0u);
|
|
|
|
std::shuffle(begin(table2), end(table2), generator);
|
2012-05-25 05:41:52 -04:00
|
|
|
}
|
2012-07-10 05:50:41 -04:00
|
|
|
|
2016-01-21 10:11:33 -05:00
|
|
|
inline std::uint16_t operator()(const std::uint32_t originalValue) const
|
2014-05-07 12:39:16 -04:00
|
|
|
{
|
2016-01-21 10:19:51 -05:00
|
|
|
std::uint16_t lsb = originalValue & 0xffffu;
|
|
|
|
std::uint16_t msb = originalValue >> 16u;
|
2016-01-21 09:56:08 -05:00
|
|
|
|
|
|
|
BOOST_ASSERT(lsb < table1.size());
|
|
|
|
BOOST_ASSERT(msb < table2.size());
|
|
|
|
|
2012-05-25 05:41:52 -04:00
|
|
|
return table1[lsb] ^ table2[msb];
|
|
|
|
}
|
|
|
|
};
|
2020-11-26 10:21:39 -05:00
|
|
|
} // namespace util
|
|
|
|
} // namespace osrm
|
2016-01-05 10:51:13 -05:00
|
|
|
|
2014-11-28 06:13:18 -05:00
|
|
|
#endif // XOR_FAST_HASH_HPP
|