FastLED 3.9.15
Loading...
Searching...
No Matches
hash.h
Go to the documentation of this file.
1#pragma once
2
3#include "fl/str.h"
4#include "fl/type_traits.h"
5#include "fl/int.h"
6#include "fl/stdint.h"
7#include "fl/force_inline.h"
8#include "fl/memfill.h"
9#include <string.h>
10#include "fl/compiler_control.h"
11
12namespace fl {
13
14template <typename T> struct vec2;
15
16
17
18//-----------------------------------------------------------------------------
19// MurmurHash3 x86 32-bit
20//-----------------------------------------------------------------------------
21// Based on the public‐domain implementation by Austin Appleby:
22// https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp
23static inline u32 MurmurHash3_x86_32(const void *key, fl::size len,
24 u32 seed = 0) {
25
27 FL_DISABLE_WARNING_IMPLICIT_FALLTHROUGH;
28
29 const fl::u8 *data = static_cast<const fl::u8 *>(key);
30 const int nblocks = int(len / 4);
31
32 u32 h1 = seed;
33 const u32 c1 = 0xcc9e2d51;
34 const u32 c2 = 0x1b873593;
35
36 // body
37 const u32 *blocks = reinterpret_cast<const u32 *>(data);
38 for (int i = 0; i < nblocks; ++i) {
39 u32 k1 = blocks[i];
40 k1 *= c1;
41 k1 = (k1 << 15) | (k1 >> 17);
42 k1 *= c2;
43
44 h1 ^= k1;
45 h1 = (h1 << 13) | (h1 >> 19);
46 h1 = h1 * 5 + 0xe6546b64;
47 }
48
49 // tail
50 const fl::u8 *tail = data + (nblocks * 4);
51 u32 k1 = 0;
52 switch (len & 3) {
53 case 3:
54 k1 ^= u32(tail[2]) << 16;
55 case 2:
56 k1 ^= u32(tail[1]) << 8;
57 case 1:
58 k1 ^= u32(tail[0]);
59 k1 *= c1;
60 k1 = (k1 << 15) | (k1 >> 17);
61 k1 *= c2;
62 h1 ^= k1;
63 }
64
65 // finalization
66 h1 ^= u32(len);
67 // fmix32
68 h1 ^= h1 >> 16;
69 h1 *= 0x85ebca6b;
70 h1 ^= h1 >> 13;
71 h1 *= 0xc2b2ae35;
72 h1 ^= h1 >> 16;
73
74 return h1;
75
77}
78
79//-----------------------------------------------------------------------------
80// Fast, cheap 32-bit integer hash (Thomas Wang)
81//-----------------------------------------------------------------------------
82static inline u32 fast_hash32(u32 x) noexcept {
83 x = (x ^ 61u) ^ (x >> 16);
84 x = x + (x << 3);
85 x = x ^ (x >> 4);
86 x = x * 0x27d4eb2dU;
87 x = x ^ (x >> 15);
88 return x;
89}
90
91// 3) Handy two-word hasher
92static inline u32 hash_pair(u32 a, u32 b,
93 u32 seed = 0) noexcept {
94 // mix in 'a', then mix in 'b'
95 u32 h = fast_hash32(seed ^ a);
96 return fast_hash32(h ^ b);
97}
98
99static inline u32 fast_hash64(u64 x) noexcept {
100 u32 x1 = static_cast<u32>(x & 0x00000000FFFFFFFF);
101 u32 x2 = static_cast<u32>(x >> 32);
102 return hash_pair(x1, x2);
103}
104
105//-----------------------------------------------------------------------------
106// Functor for hashing arbitrary byte‐ranges to a 32‐bit value
107//-----------------------------------------------------------------------------
108// https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp
109template <typename T> struct Hash {
110 static_assert(fl::is_pod<T>::value,
111 "fl::Hash<T> only supports POD types (integrals, floats, "
112 "etc.), you need to define your own hash.");
113 u32 operator()(const T &key) const noexcept {
114 return MurmurHash3_x86_32(&key, sizeof(T));
115 }
116};
117
118template <typename T> struct FastHash {
119 static_assert(fl::is_pod<T>::value,
120 "fl::FastHash<T> only supports POD types (integrals, floats, "
121 "etc.), you need to define your own hash.");
122 u32 operator()(const T &key) const noexcept {
123 return fast_hash32(key);
124 }
125};
126
127template <typename T> struct FastHash<vec2<T>> {
128 u32 operator()(const vec2<T> &key) const noexcept {
129 if (sizeof(T) == sizeof(fl::u8)) {
130 u32 x = static_cast<u32>(key.x) +
131 (static_cast<u32>(key.y) << 8);
132 return fast_hash32(x);
133 }
134 if (sizeof(T) == sizeof(u16)) {
135 u32 x = static_cast<u32>(key.x) +
136 (static_cast<u32>(key.y) << 16);
137 return fast_hash32(x);
138 }
139 if (sizeof(T) == sizeof(u32)) {
140 return hash_pair(key.x, key.y);
141 }
142 return MurmurHash3_x86_32(&key, sizeof(T));
143 }
144};
145
146template <typename T> struct Hash<T *> {
147 u32 operator()(T *key) const noexcept {
148 if (sizeof(T *) == sizeof(u32)) {
149 u32 key_u = reinterpret_cast<fl::uptr>(key);
150 return fast_hash32(key_u);
151 } else {
152 return MurmurHash3_x86_32(key, sizeof(T *));
153 }
154 }
155};
156
157template <typename T> struct Hash<vec2<T>> {
158 u32 operator()(const vec2<T> &key) const noexcept {
159#ifndef __clang__
160#pragma GCC diagnostic push
161#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
162#endif
163 T packed[2] = {key.x, key.y};
164 const void *p = &packed[0];
165 return MurmurHash3_x86_32(p, sizeof(packed));
166#ifndef __clang__
167#pragma GCC diagnostic pop
168#endif
169 }
170};
171
172template <typename T> struct Hash<fl::shared_ptr<T>> {
173 u32 operator()(const T &key) const noexcept {
174 auto hasher = Hash<T *>();
175 return hasher(key.get());
176 }
177};
178
179template <typename T> struct Hash<fl::WeakPtr<T>> {
180 u32 operator()(const fl::WeakPtr<T> &key) const noexcept {
181 fl::uptr val = key.ptr_value();
182 return MurmurHash3_x86_32(&val, sizeof(fl::uptr));
183 }
184};
185
186template<> struct Hash<float> {
187 u32 operator()(const float key) const noexcept {
188 u32 ikey = fl::bit_cast<u32>(key);
189 return fast_hash32(ikey);
190 }
191};
192
193template<> struct Hash<double> {
194 u32 operator()(const double& key) const noexcept {
195 return MurmurHash3_x86_32(&key, sizeof(double));
196 }
197};
198
199template<> struct Hash<i32> {
200 u32 operator()(const i32 key) const noexcept {
201 u32 ukey = static_cast<u32>(key);
202 return fast_hash32(ukey);
203 }
204};
205
206template<> struct Hash<bool> {
207 u32 operator()(const bool key) const noexcept {
208 return fast_hash32(key);
209 }
210};
211
212template<> struct Hash<fl::u8> {
213 u32 operator()(const fl::u8 &key) const noexcept {
214 return fast_hash32(key);
215 }
216};
217
218template<> struct Hash<u16> {
219 u32 operator()(const u16 &key) const noexcept {
220 return fast_hash32(key);
221 }
222};
223
224template<> struct Hash<u32> {
225 u32 operator()(const u32 &key) const noexcept {
226 return fast_hash32(key);
227 }
228};
229
230template<> struct Hash<i8> {
231 u32 operator()(const i8 &key) const noexcept {
232 u8 v = static_cast<u8>(key);
233 return fast_hash32(v);
234 }
235};
236
237template<> struct Hash<i16> {
238 u32 operator()(const i16 &key) const noexcept {
239 u16 ukey = static_cast<u16>(key);
240 return fast_hash32(ukey);
241 }
242};
243
244// FASTLED_DEFINE_FAST_HASH(fl::u8)
245// FASTLED_DEFINE_FAST_HASH(u16)
246// FASTLED_DEFINE_FAST_HASH(u32)
247// FASTLED_DEFINE_FAST_HASH(i8)
248// FASTLED_DEFINE_FAST_HASH(i16)
249// FASTLED_DEFINE_FAST_HASH(bool)
250
251// FASTLED_DEFINE_FAST_HASH(int)
252
253//-----------------------------------------------------------------------------
254// Convenience for std::string → u32
255//----------------------------------------------------------------------------
256template <> struct Hash<fl::string> {
257 u32 operator()(const fl::string &key) const noexcept {
258 return MurmurHash3_x86_32(key.data(), key.size());
259 }
260};
261
262
263
264} // namespace fl
int x
Definition simple.h:92
#define FL_DISABLE_WARNING_PUSH
#define FL_DISABLE_WARNING_POP
static u32 hash_pair(u32 a, u32 b, u32 seed=0) noexcept
Definition hash.h:92
unsigned char u8
Definition int.h:17
To bit_cast(const From &from) noexcept
Definition bit_cast.h:39
static u32 fast_hash64(u64 x) noexcept
Definition hash.h:99
static u32 MurmurHash3_x86_32(const void *key, fl::size len, u32 seed=0)
Definition hash.h:23
signed char i8
Definition int.h:16
static u32 fast_hash32(u32 x) noexcept
Definition hash.h:82
IMPORTANT!
Definition crgb.h:20
u32 operator()(const vec2< T > &key) const noexcept
Definition hash.h:128
u32 operator()(const T &key) const noexcept
Definition hash.h:122
u32 operator()(T *key) const noexcept
Definition hash.h:147
u32 operator()(const bool key) const noexcept
Definition hash.h:207
u32 operator()(const double &key) const noexcept
Definition hash.h:194
u32 operator()(const fl::WeakPtr< T > &key) const noexcept
Definition hash.h:180
u32 operator()(const T &key) const noexcept
Definition hash.h:173
u32 operator()(const fl::string &key) const noexcept
Definition hash.h:257
u32 operator()(const fl::u8 &key) const noexcept
Definition hash.h:213
u32 operator()(const float key) const noexcept
Definition hash.h:187
u32 operator()(const i16 &key) const noexcept
Definition hash.h:238
u32 operator()(const i32 key) const noexcept
Definition hash.h:200
u32 operator()(const i8 &key) const noexcept
Definition hash.h:231
u32 operator()(const u16 &key) const noexcept
Definition hash.h:219
u32 operator()(const u32 &key) const noexcept
Definition hash.h:225
u32 operator()(const vec2< T > &key) const noexcept
Definition hash.h:158
u32 operator()(const T &key) const noexcept
Definition hash.h:113
static constexpr bool value