-
Notifications
You must be signed in to change notification settings - Fork 89
/
Copy pathh3.hpp
71 lines (61 loc) · 1.81 KB
/
h3.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#ifndef BF_H3_HPP
#define BF_H3_HPP
#include <limits>
#include <random>
namespace bf {
/// An implementation of the H3 hash function family.
template <typename T, int N>
class h3
{
static size_t const bits_per_byte =
std::numeric_limits<unsigned char>::digits;
public:
constexpr static size_t byte_range =
std::numeric_limits<unsigned char>::max() + 1;
h3(T seed = 0)
{
T bits[N * bits_per_byte];
std::minstd_rand0 prng(seed);
for (size_t bit = 0; bit < N * bits_per_byte; ++bit)
{
bits[bit] = 0;
for (size_t i = 0; i < sizeof(T)/2; i++)
bits[bit] = (bits[bit] << 16) | (prng() & 0xFFFF);
}
for (size_t byte = 0; byte < N; ++byte)
for (size_t val = 0; val < byte_range; ++val)
{
bytes_[byte][val] = 0;
for (size_t bit = 0; bit < bits_per_byte; ++bit)
if (val & (1 << bit))
bytes_[byte][val] ^= bits[byte * bits_per_byte + bit];
}
}
T operator()(void const* data, size_t size, size_t offset = 0) const
{
auto *p = static_cast<unsigned char const*>(data);
T result = 0;
// Duff's Device.
auto n = (size + 7) / 8;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
switch (size % 8)
{
case 0: do { result ^= bytes_[offset++][*p++];
case 7: result ^= bytes_[offset++][*p++];
case 6: result ^= bytes_[offset++][*p++];
case 5: result ^= bytes_[offset++][*p++];
case 4: result ^= bytes_[offset++][*p++];
case 3: result ^= bytes_[offset++][*p++];
case 2: result ^= bytes_[offset++][*p++];
case 1: result ^= bytes_[offset++][*p++];
} while ( --n > 0 );
}
#pragma GCC diagnostic pop
return result;
}
private:
T bytes_[N][byte_range];
};
} // namespace bf
#endif