M5Utility 0.0.2 git rev:5c1a751
Loading...
Searching...
No Matches
murmurhash3.hpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD
3 *
4 * SPDX-License-Identifier: MIT
5 */
13#ifndef M5_UTILITY_MURMURHASH3_HPP
14#define M5_UTILITY_MURMURHASH3_HPP
15
16#include <cstdint>
17#include <cstddef>
18#include <cstring>
19#include <type_traits>
20#include "./stl/endianness.hpp"
21
22namespace m5 {
23namespace utility {
28namespace mmh3 {
29
31constexpr uint32_t mul(const uint32_t v, const uint32_t vv)
32{
33 return v * vv;
34}
35
36constexpr uint32_t xor_value(const uint32_t v, const uint32_t x)
37{
38 return v ^ x;
39}
40
41constexpr uint32_t shift_right(const uint32_t v, const uint8_t s)
42{
43 return v >> s;
44}
45
46constexpr uint32_t xor_by_shift_right(const uint32_t v, const uint32_t s)
47{
48 return xor_value(v, shift_right(v, s));
49}
50
51constexpr uint32_t str2uint32_little(const char* str, const size_t getc = sizeof(uint32_t), uint32_t v = 0)
52{
53 return getc ? str2uint32_little(str, getc - 1, (v << 8) | str[getc - 1]) : v;
54}
55
56constexpr uint32_t str2uint32_big(const char* str, const size_t getc = sizeof(uint32_t), uint32_t v = 0)
57{
58 return getc ? str2uint32_big(str + 1, getc - 1, (v << 8) | *str) : v;
59}
60
61// Switch between little and big enfian.
62template <uint32_t Endian>
63constexpr typename std::enable_if<Endian, uint32_t>::type str2uint32(const char* str,
64 const size_t getc = sizeof(uint32_t),
65 uint32_t v = 0)
66{
67 return str2uint32_little(str, getc, v);
68}
69
70template <uint32_t Endian>
71constexpr typename std::enable_if<!Endian, uint32_t>::type str2uint32(const char* str,
72 const size_t getc = sizeof(uint32_t),
73 uint32_t v = 0)
74{
75 return str2uint32_big(str, getc, v);
76}
77
78constexpr uint32_t scramble_sub(const uint32_t k)
79{
80 return (k << 15) | (k >> 17);
81}
82
83constexpr uint32_t scramble(const uint32_t k, const uint32_t h)
84{
85 return h ^ mul(scramble_sub(mul(k, 0xcc9e2d51)), 0x1b873593);
86}
87
88constexpr uint32_t group_of_4_sub_3(const uint32_t h)
89{
90 return h * 5 + 0xe6546b64;
91}
92
93constexpr uint32_t group_of_4_sub_2(const uint32_t h)
94{
95 return (h << 13) | (h >> 19);
96}
97
98constexpr uint32_t group_of_4_sub_1(const uint32_t k, const uint32_t h)
99{
100 return group_of_4_sub_3(group_of_4_sub_2(scramble(k, h)));
101}
102
103constexpr uint32_t group_of_4(const char* str, const size_t len, const uint32_t h = 0)
104{
105 return len ? group_of_4(str + sizeof(uint32_t), len - 1, group_of_4_sub_1(str2uint32<m5::endian::little>(str), h))
106 : h;
107}
108
109constexpr uint32_t rest(const char* str, const size_t len, const uint32_t h = 0)
110{
111 return len ? scramble(str2uint32<m5::endian::little>(str, len), h) : h;
112}
113
114constexpr uint32_t finalize(uint32_t h, size_t len)
115{
116 return xor_by_shift_right(
117 mul(xor_by_shift_right(mul(xor_by_shift_right(xor_value(h, len), 16), 0x85ebca6b), 13), 0xc2b2ae35), 16);
118}
120
127constexpr uint32_t calculate(const char* str, const size_t len)
128{
129 return finalize(rest(str + ((len >> 2) * sizeof(uint32_t)), (len & 3), group_of_4(str, len >> 2)), len);
130}
131
140constexpr uint32_t operator"" _mmh3(const char* str, const size_t len)
141{
142 return calculate(str, len);
143};
144
150uint32_t calculate(const char* str);
151
152} // namespace mmh3
153} // namespace utility
154} // namespace m5
155#endif
Compile-time endian identification.
uint32_t calculate(const char *str)
Calculate MurmurHash3 from string.
Definition murmurhash3.cpp:16
Top level namespace of M5.
Definition bit_segment.hpp:17
For Murmurhash3.
For utilities.