-
Notifications
You must be signed in to change notification settings - Fork 0
/
murmur32.h
102 lines (87 loc) · 2 KB
/
murmur32.h
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#pragma once
/*
* By Paul Dreik 2019,2020
* https://www.pauldreik.se/
* License: Boost 1.0
* SPDX-License-Identifier: BSL-1.0
*/
#include <cstdint>
#include "ManyU32.h"
class Murmur32 {
public:
explicit Murmur32(int nbits) {
m_nbits=nbits;
m_shift=nbits-nbits/2;
m_mask=1;
while(__builtin_popcount(m_mask)<nbits) {
m_mask<<=1;
m_mask |=1;
}
}
template<typename URBG>
void seed(URBG&& rng) {
for(auto& e: m_keys) {
e=rng() & m_mask;
}
}
std::uint32_t encrypt(std::uint32_t x) const {
assert( (x & ~mask)==0 && "high bits are set");
x ^= m_keys[0];
x ^= (x>>m_shift);
//x &= m_mask;
x *= 0xcc9e2d51;
x &= m_mask;
x ^= (x>>m_shift);
//x &= m_mask;
x *= 0x1b873593;
x &= m_mask;
x ^= (x>>m_shift);
//x &= m_mask;
return x;
}
private:
int m_nbits;
int m_shift;
std::uint32_t m_mask;
std::array<std::uint32_t,3> m_keys;
};
class SimdMurmur32 {
public:
explicit SimdMurmur32(int nbits) : m_mask{0U} {
m_nbits=nbits;
m_shift=nbits-nbits/2;
std::uint32_t mask=1;
while(__builtin_popcount(mask)<nbits) {
mask<<=1;
mask |=1;
}
m_mask=ManyU32{mask};
}
template<typename URBG>
void seed(URBG&& rng) {
auto mask=m_mask.get<0>();
for(auto& e: m_keys) {
e=rng() & mask;
}
m_mask=ManyU32{mask};
}
ManyU32 encrypt(ManyU32 x) const {
x ^= ManyU32{m_keys[0]};
x ^= (x>>m_shift);
//x &= m_mask;
x *= ManyU32{0xcc9e2d51};
x &= m_mask;
x ^= (x>>m_shift);
//x &= m_mask;
x *= ManyU32{0x1b873593};
x &= m_mask;
x ^= (x>>m_shift);
//x &= m_mask;
return x;
}
private:
int m_nbits;
int m_shift;
ManyU32 m_mask;
std::array<std::uint32_t,3> m_keys;
};