|
1 | 1 | #if !defined (__XXHASH_HH)
|
2 | 2 | #define __XXHASH_HH
|
3 | 3 |
|
| 4 | +#if INTPTR_MAX == INT64_MAX |
| 5 | +#define XXH_NO_STREAM |
| 6 | +#define XXH_INLINE_ALL |
| 7 | +#define XXH_NAMESPACE xaInternal_ |
| 8 | +#include <xxHash/xxhash.h> |
| 9 | +#include <constexpr-xxh3.h> |
| 10 | +#endif |
| 11 | + |
| 12 | +#include <type_traits> |
| 13 | + |
4 | 14 | //
|
5 | 15 | // Based on original code at https://github.com/ekpyron/xxhashct
|
6 | 16 | //
|
@@ -135,116 +145,26 @@ namespace xamarin::android
|
135 | 145 | }
|
136 | 146 | };
|
137 | 147 |
|
| 148 | +#if INTPTR_MAX == INT64_MAX |
138 | 149 | class xxhash64 final
|
139 | 150 | {
|
140 |
| - static constexpr uint64_t PRIME1 = 11400714785074694791ULL; |
141 |
| - static constexpr uint64_t PRIME2 = 14029467366897019727ULL; |
142 |
| - static constexpr uint64_t PRIME3 = 1609587929392839161ULL; |
143 |
| - static constexpr uint64_t PRIME4 = 9650029242287828579ULL; |
144 |
| - static constexpr uint64_t PRIME5 = 2870177450012600261ULL; |
145 |
| - |
146 | 151 | public:
|
147 |
| - // We don't use any special seed in XA, the template parameter is just to keep the algorithm more easily |
148 |
| - // understood and to run compile-time algorithm correctness tests |
149 |
| - template<uint64_t Seed = 0> |
150 |
| - force_inline static constexpr uint64_t hash (const char *p, size_t len) noexcept |
151 |
| - { |
152 |
| - return finalize ((len >= 32 ? h32bytes<Seed> (p, len) : Seed + PRIME5) + len, p + (len & ~0x1FU), len & 0x1F); |
153 |
| - } |
154 |
| - |
155 |
| - template<size_t Size, uint64_t Seed = 0> |
156 |
| - force_inline static constexpr uint64_t hash (const char (&input)[Size]) noexcept |
157 |
| - { |
158 |
| - return hash<Seed> (input, Size - 1); |
159 |
| - } |
160 |
| - |
161 |
| - private: |
162 |
| - template<int Bits> |
163 |
| - force_inline static constexpr uint64_t rotl (uint64_t x) noexcept |
164 |
| - { |
165 |
| - return ((x << Bits) | (x >> (64 - Bits))); |
166 |
| - } |
167 |
| - |
168 |
| - template<int RShift> |
169 |
| - force_inline static constexpr uint64_t mix1 (const uint64_t h, const uint64_t prime) noexcept |
170 |
| - { |
171 |
| - return (h ^ (h >> RShift)) * prime; |
172 |
| - } |
173 |
| - |
174 |
| - force_inline static constexpr uint64_t mix2 (const uint64_t p, const uint64_t v = 0) noexcept |
175 |
| - { |
176 |
| - return rotl<31> (v + p * PRIME2) * PRIME1; |
177 |
| - } |
178 |
| - |
179 |
| - force_inline static constexpr uint64_t mix3 (const uint64_t h, const uint64_t v) noexcept |
180 |
| - { |
181 |
| - return (h ^ mix2 (v)) * PRIME1 + PRIME4; |
182 |
| - } |
183 |
| - |
184 |
| - // little-endian versions: all our target platforms are little-endian |
185 |
| - force_inline static constexpr uint32_t endian32 (const char *v) noexcept |
| 152 | + force_inline static constexpr XXH64_hash_t hash (const char *p, size_t len) noexcept |
186 | 153 | {
|
187 |
| - return |
188 |
| - static_cast<uint32_t>(static_cast<uint8_t>(v[0])) | |
189 |
| - (static_cast<uint32_t>(static_cast<uint8_t>(v[1])) << 8) | |
190 |
| - (static_cast<uint32_t>(static_cast<uint8_t>(v[2])) << 16) | |
191 |
| - (static_cast<uint32_t>(static_cast<uint8_t>(v[3])) << 24); |
| 154 | + return XXH3_64bits (static_cast<const void*>(p), len); |
192 | 155 | }
|
193 | 156 |
|
194 |
| - force_inline static constexpr uint64_t endian64 (const char *v) |
| 157 | + // The C XXH64_64bits function from xxhash.h is not `constexpr` or `consteval`, so we cannot call it here. |
| 158 | + // At the same time, at build time performance is not that important, so we call the "unoptmized" `consteval` |
| 159 | + // C++ implementation here |
| 160 | + template<size_t Size> |
| 161 | + force_inline static consteval XXH64_hash_t hash (const char (&input)[Size]) noexcept |
195 | 162 | {
|
196 |
| - return |
197 |
| - static_cast<uint64_t>(static_cast<uint8_t>(v[0])) | |
198 |
| - (static_cast<uint64_t>(static_cast<uint8_t>(v[1])) << 8) | |
199 |
| - (static_cast<uint64_t>(static_cast<uint8_t>(v[2])) << 16) | |
200 |
| - (static_cast<uint64_t>(static_cast<uint8_t>(v[3])) << 24) | |
201 |
| - (static_cast<uint64_t>(static_cast<uint8_t>(v[4])) << 32) | |
202 |
| - (static_cast<uint64_t>(static_cast<uint8_t>(v[5])) << 40) | |
203 |
| - (static_cast<uint64_t>(static_cast<uint8_t>(v[6])) << 48) | |
204 |
| - (static_cast<uint64_t>(static_cast<uint8_t>(v[7])) << 56); |
205 |
| - } |
206 |
| - |
207 |
| - force_inline static constexpr uint64_t fetch64 (const char *p, const uint64_t v = 0) noexcept |
208 |
| - { |
209 |
| - return mix2 (endian64 (p), v); |
210 |
| - } |
211 |
| - |
212 |
| - force_inline static constexpr uint64_t fetch32 (const char *p) noexcept |
213 |
| - { |
214 |
| - return static_cast<uint64_t>(endian32 (p)) * PRIME1; |
215 |
| - } |
216 |
| - |
217 |
| - force_inline static constexpr uint64_t fetch8 (const char *p) noexcept |
218 |
| - { |
219 |
| - return static_cast<uint8_t> (*p) * PRIME5; |
220 |
| - } |
221 |
| - |
222 |
| - force_inline static constexpr uint64_t finalize (const uint64_t h, const char *p, size_t len) noexcept |
223 |
| - { |
224 |
| - return |
225 |
| - (len >= 8) ? (finalize (rotl<27> (h ^ fetch64 (p)) * PRIME1 + PRIME4, p + 8, len - 8)) : |
226 |
| - ((len >= 4) ? (finalize (rotl<23> (h ^ fetch32 (p)) * PRIME2 + PRIME3, p + 4, len - 4)) : |
227 |
| - ((len > 0) ? (finalize (rotl<11> (h ^ fetch8 (p)) * PRIME1, p + 1, len - 1)) : |
228 |
| - (mix1<32> (mix1<29> (mix1<33> (h, PRIME2), PRIME3), 1)))); |
229 |
| - } |
230 |
| - |
231 |
| - force_inline static constexpr uint64_t h32bytes (const char *p, size_t len, const uint64_t v1,const uint64_t v2, const uint64_t v3, const uint64_t v4) noexcept |
232 |
| - { |
233 |
| - return (len >= 32) ? h32bytes (p + 32, len - 32, fetch64 (p, v1), fetch64 (p + 8, v2), fetch64 (p + 16, v3), fetch64 (p + 24, v4)) : |
234 |
| - mix3 (mix3 (mix3 (mix3 (rotl<1> (v1) + rotl<7> (v2) + rotl<12> (v3) + rotl<18> (v4), v1), v2), v3), v4); |
235 |
| - } |
236 |
| - |
237 |
| - // We don't use any special seed in XA, the template parameter is just to keep the algorithm more easily |
238 |
| - // understood |
239 |
| - template<uint64_t Seed = 0> |
240 |
| - force_inline static constexpr uint64_t h32bytes (const char *p, size_t len) noexcept |
241 |
| - { |
242 |
| - return h32bytes (p, len, Seed + PRIME1 + PRIME2, Seed + PRIME2, Seed, Seed - PRIME1); |
| 163 | + return constexpr_xxh3::XXH3_64bits_const (input); |
243 | 164 | }
|
244 | 165 | };
|
245 | 166 |
|
246 |
| -#if INTPTR_MAX == INT64_MAX |
247 |
| - using hash_t = uint64_t; |
| 167 | + using hash_t = XXH64_hash_t; |
248 | 168 | using xxhash = xxhash64;
|
249 | 169 | #else
|
250 | 170 | using hash_t = uint32_t;
|
|
0 commit comments