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