Blender V4.5
hash.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#pragma once
6
7#include "util/math.h"
8#include "util/types.h"
9
11
12/* [0, uint_max] -> [0.0, 1.0) */
14{
15 /* NOTE: we divide by 4294967808 instead of 2^32 because the latter
16 * leads to a [0.0, 1.0] mapping instead of [0.0, 1.0) due to floating
17 * point rounding error. 4294967808 unfortunately leaves (precisely)
18 * one unused ULP between the max number this outputs and 1.0, but
19 * that's the best you can do with this construction. */
20 return (float)n * (1.0f / 4294967808.0f);
21}
22
23/* [0, uint_max] -> [0.0, 1.0] */
25{
26 return (float)n * (1.0f / (float)0xFFFFFFFFu);
27}
28
29/* ***** Jenkins Lookup3 Hash Functions ***** */
30
31/* Source: http://burtleburtle.net/bob/c/lookup3.c */
32
33#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k))))
34
35#define mix(a, b, c) \
36 { \
37 a -= c; \
38 a ^= rot(c, 4); \
39 c += b; \
40 b -= a; \
41 b ^= rot(a, 6); \
42 a += c; \
43 c -= b; \
44 c ^= rot(b, 8); \
45 b += a; \
46 a -= c; \
47 a ^= rot(c, 16); \
48 c += b; \
49 b -= a; \
50 b ^= rot(a, 19); \
51 a += c; \
52 c -= b; \
53 c ^= rot(b, 4); \
54 b += a; \
55 } \
56 ((void)0)
57
58#define final(a, b, c) \
59 { \
60 c ^= b; \
61 c -= rot(b, 14); \
62 a ^= c; \
63 a -= rot(c, 11); \
64 b ^= a; \
65 b -= rot(a, 25); \
66 c ^= b; \
67 c -= rot(b, 16); \
68 a ^= c; \
69 a -= rot(c, 4); \
70 b ^= a; \
71 b -= rot(a, 14); \
72 c ^= b; \
73 c -= rot(b, 24); \
74 } \
75 ((void)0)
76
78{
79 uint a;
80 uint b;
81 uint c;
82 a = b = c = 0xdeadbeef + (1 << 2) + 13;
83
84 a += kx;
85 final(a, b, c);
86
87 return c;
88}
89
91{
92 uint a;
93 uint b;
94 uint c;
95 a = b = c = 0xdeadbeef + (2 << 2) + 13;
96
97 b += ky;
98 a += kx;
99 final(a, b, c);
100
101 return c;
102}
103
104ccl_device_inline uint hash_uint3(const uint kx, const uint ky, const uint kz)
105{
106 uint a;
107 uint b;
108 uint c;
109 a = b = c = 0xdeadbeef + (3 << 2) + 13;
110
111 c += kz;
112 b += ky;
113 a += kx;
114 final(a, b, c);
115
116 return c;
117}
118
119ccl_device_inline uint hash_uint4(const uint kx, const uint ky, const uint kz, const uint kw)
120{
121 uint a;
122 uint b;
123 uint c;
124 a = b = c = 0xdeadbeef + (4 << 2) + 13;
125
126 a += kx;
127 b += ky;
128 c += kz;
129 mix(a, b, c);
130
131 a += kw;
132 final(a, b, c);
133
134 return c;
135}
136
137#undef rot
138#undef final
139#undef mix
140
141/* Hashing uint or uint[234] into a float in the range [0, 1]. */
142
144{
145 return uint_to_float_incl(hash_uint(kx));
146}
147
149{
150 return uint_to_float_incl(hash_uint2(kx, ky));
151}
152
153ccl_device_inline float hash_uint3_to_float(const uint kx, const uint ky, const uint kz)
154{
155 return uint_to_float_incl(hash_uint3(kx, ky, kz));
156}
157
159 const uint ky,
160 const uint kz,
161 const uint kw)
162{
163 return uint_to_float_incl(hash_uint4(kx, ky, kz, kw));
164}
165
166/* Hashing float or float[234] into a float in the range [0, 1]. */
167
169{
171}
172
177
182
188
189/* Hashing float[234] into float[234] of components in the range [0, 1]. */
190
195
202
204{
206 hash_float4_to_float(make_float4(k.w, k.x, k.y, k.z)),
207 hash_float4_to_float(make_float4(k.z, k.w, k.x, k.y)),
208 hash_float4_to_float(make_float4(k.y, k.z, k.w, k.x)));
209}
210
211/* Hashing float or float[234] into float3 of components in range [0, 1]. */
212
219
226
233
234/* Hashing float or float[234] into float2 of components in range [0, 1]. */
235
240
246
248{
249 return make_float2(hash_float4_to_float(make_float4(k.x, k.y, k.z, k.w)),
250 hash_float4_to_float(make_float4(k.z, k.x, k.w, k.y)));
251}
252
253/* SSE Versions Of Jenkins Lookup3 Hash Functions */
254
255#ifdef __KERNEL_SSE__
256# define rot(x, k) (((x) << (k)) | (srl(x, 32 - (k))))
257
258# define mix(a, b, c) \
259 { \
260 a -= c; \
261 a ^= rot(c, 4); \
262 c += b; \
263 b -= a; \
264 b ^= rot(a, 6); \
265 a += c; \
266 c -= b; \
267 c ^= rot(b, 8); \
268 b += a; \
269 a -= c; \
270 a ^= rot(c, 16); \
271 c += b; \
272 b -= a; \
273 b ^= rot(a, 19); \
274 a += c; \
275 c -= b; \
276 c ^= rot(b, 4); \
277 b += a; \
278 }
279
280# define final(a, b, c) \
281 { \
282 c ^= b; \
283 c -= rot(b, 14); \
284 a ^= c; \
285 a -= rot(c, 11); \
286 b ^= a; \
287 b -= rot(a, 25); \
288 c ^= b; \
289 c -= rot(b, 16); \
290 a ^= c; \
291 a -= rot(c, 4); \
292 b ^= a; \
293 b -= rot(a, 14); \
294 c ^= b; \
295 c -= rot(b, 24); \
296 }
297
298ccl_device_inline int4 hash_int4(const int4 kx)
299{
300 int4 a;
301 int4 b;
302 int4 c;
303 a = b = c = make_int4(0xdeadbeef + (1 << 2) + 13);
304
305 a += kx;
306 final(a, b, c);
307
308 return c;
309}
310
311ccl_device_inline int4 hash_int4_2(const int4 kx, const int4 ky)
312{
313 int4 a;
314 int4 b;
315 int4 c;
316 a = b = c = make_int4(0xdeadbeef + (2 << 2) + 13);
317
318 b += ky;
319 a += kx;
320 final(a, b, c);
321
322 return c;
323}
324
325ccl_device_inline int4 hash_int4_3(const int4 kx, const int4 ky, const int4 kz)
326{
327 int4 a;
328 int4 b;
329 int4 c;
330 a = b = c = make_int4(0xdeadbeef + (3 << 2) + 13);
331
332 c += kz;
333 b += ky;
334 a += kx;
335 final(a, b, c);
336
337 return c;
338}
339
340ccl_device_inline int4 hash_int4_4(const int4 kx, const int4 ky, const int4 kz, const int4 kw)
341{
342 int4 a;
343 int4 b;
344 int4 c;
345 a = b = c = make_int4(0xdeadbeef + (4 << 2) + 13);
346
347 a += kx;
348 b += ky;
349 c += kz;
350 mix(a, b, c);
351
352 a += kw;
353 final(a, b, c);
354
355 return c;
356}
357
358# if defined(__KERNEL_AVX2__)
359ccl_device_inline vint8 hash_int8(vint8 kx)
360{
361 vint8 a, b, c;
362 a = b = c = make_vint8(0xdeadbeef + (1 << 2) + 13);
363
364 a += kx;
365 final(a, b, c);
366
367 return c;
368}
369
370ccl_device_inline vint8 hash_int8_2(vint8 kx, vint8 ky)
371{
372 vint8 a, b, c;
373 a = b = c = make_vint8(0xdeadbeef + (2 << 2) + 13);
374
375 b += ky;
376 a += kx;
377 final(a, b, c);
378
379 return c;
380}
381
382ccl_device_inline vint8 hash_int8_3(vint8 kx, vint8 ky, vint8 kz)
383{
384 vint8 a, b, c;
385 a = b = c = make_vint8(0xdeadbeef + (3 << 2) + 13);
386
387 c += kz;
388 b += ky;
389 a += kx;
390 final(a, b, c);
391
392 return c;
393}
394
395ccl_device_inline vint8 hash_int8_4(vint8 kx, vint8 ky, vint8 kz, vint8 kw)
396{
397 vint8 a, b, c;
398 a = b = c = make_vint8(0xdeadbeef + (4 << 2) + 13);
399
400 a += kx;
401 b += ky;
402 c += kz;
403 mix(a, b, c);
404
405 a += kw;
406 final(a, b, c);
407
408 return c;
409}
410# endif
411
412# undef rot
413# undef final
414# undef mix
415
416#endif
417
418/* ***** Hash Prospector Hash Functions *****
419 *
420 * These are based on the high-quality 32-bit hash/mixing functions from
421 * https://github.com/skeeto/hash-prospector
422 */
423
425{
426 // The actual mixing function from Hash Prospector.
427 i ^= i >> 16;
428 i *= 0x21f0aaad;
429 i ^= i >> 15;
430 i *= 0xd35a2d97;
431 i ^= i >> 15;
432
433 // The xor is just to make input zero not map to output zero.
434 // The number is randomly selected and isn't special.
435 return i ^ 0xe6fe3beb;
436}
437
438/* Seedable version of hash_hp_uint() above. */
440{
441 // Manipulate the seed so it doesn't interact poorly with n when they
442 // are both e.g. incrementing. This isn't fool-proof, but is good
443 // enough for practical use.
444 seed ^= seed << 19;
445
446 return hash_hp_uint(i ^ seed);
447}
448
449/* Outputs [0.0, 1.0). */
454
455/* Outputs [0.0, 1.0). */
460
461/* ***** Modified Wang Hash Functions *****
462 *
463 * These are based on a bespoke modified version of the Wang hash, and
464 * can serve as a faster hash when quality isn't critical.
465 *
466 * The original Wang hash is documented here:
467 * https://www.burtleburtle.net/bob/hash/integer.html
468 */
469
471{
472 i = (i ^ 61) ^ seed;
473 i += i << 3;
474 i ^= i >> 4;
475 i *= 0x27d4eb2d;
476 return i;
477}
478
479/* Outputs [0.0, 1.0). */
484
485/* ***** Index Shuffling Hash Function *****
486 *
487 * This function takes an index, the length of the thing the index points
488 * into, and returns a shuffled index. For example, if you pass indices
489 * 0 through 19 to this function with a length parameter of 20, it will
490 * return the indices in a shuffled order with no repeats. Indices
491 * larger than the length parameter will simply repeat the same shuffled
492 * pattern over and over.
493 *
494 * This is useful for iterating over an array in random shuffled order
495 * without having to shuffle the array itself.
496 *
497 * Passing different seeds results in different random shuffles.
498 *
499 * This function runs in average O(1) time.
500 *
501 * See https://andrew-helmer.github.io/permute/ for details on how this
502 * works.
503 */
505{
506 i = i % length;
507 const uint mask = (1 << (32 - count_leading_zeros(length - 1))) - 1;
508
509 do {
510 i ^= seed;
511 i *= 0xe170893d;
512 i ^= seed >> 16;
513 i ^= (i & mask) >> 4;
514 i ^= seed >> 8;
515 i *= 0x0929eb3f;
516 i ^= seed >> 23;
517 i ^= (i & mask) >> 1;
518 i *= 1 | seed >> 27;
519 i *= 0x6935fa69;
520 i ^= (i & mask) >> 11;
521 i *= 0x74dcb303;
522 i ^= (i & mask) >> 2;
523 i *= 0x9e501cc3;
524 i ^= (i & mask) >> 2;
525 i *= 0xc860a3df;
526 i &= mask;
527 i ^= i >> 5;
528 } while (i >= length);
529
530 return i;
531}
532
539{
540 const uint qx = 1103515245U * ((x >> 1U) ^ (y));
541 const uint qy = 1103515245U * ((y >> 1U) ^ (x));
542 const uint n = 1103515245U * ((qx) ^ (qy >> 3U));
543
544 return n;
545}
546
547/* ********** */
548
549#ifndef __KERNEL_GPU__
550static inline uint hash_string(const char *str)
551{
552 uint i = 0;
553 uint c;
554
555 while ((c = *str++)) {
556 i = i * 37 + c;
557 }
558
559 return i;
560}
561#endif
562
unsigned int uint
static unsigned long seed
Definition btSoftBody.h:39
#define ccl_device_forceinline
#define ccl_device_inline
#define CCL_NAMESPACE_END
ccl_device_forceinline float4 make_float4(const float x, const float y, const float z, const float w)
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
ccl_device_forceinline float2 make_float2(const float x, const float y)
#define __float_as_uint(x)
ccl_device_forceinline int4 make_int4(const int x, const int y, const int z, const int w)
#define str(s)
VecBase< float, 4 > float4
float length(VecOp< float, D >) RET
ccl_device_inline uint hash_wang_seeded_uint(uint i, const uint seed)
Definition hash.h:470
static uint hash_string(const char *str)
Definition hash.h:550
ccl_device_inline float2 hash_float3_to_float2(const float3 k)
Definition hash.h:241
ccl_device_inline float3 hash_float_to_float3(const float k)
Definition hash.h:213
ccl_device_inline uint hash_uint4(const uint kx, const uint ky, const uint kz, const uint kw)
Definition hash.h:119
ccl_device_inline float hash_float_to_float(const float k)
Definition hash.h:168
ccl_device_inline float hash_float3_to_float(const float3 k)
Definition hash.h:178
ccl_device_inline float hash_uint_to_float(const uint kx)
Definition hash.h:143
ccl_device_inline float2 hash_float_to_float2(const float k)
Definition hash.h:236
ccl_device_inline float2 hash_float2_to_float2(const float2 k)
Definition hash.h:191
ccl_device_inline float hash_hp_seeded_float(const uint i, const uint seed)
Definition hash.h:456
ccl_device_inline uint hash_shuffle_uint(uint i, const uint length, const uint seed)
Definition hash.h:504
ccl_device_inline float3 hash_float2_to_float3(const float2 k)
Definition hash.h:220
ccl_device_inline float hash_wang_seeded_float(const uint i, const uint seed)
Definition hash.h:480
ccl_device_inline float hash_float2_to_float(const float2 k)
Definition hash.h:173
ccl_device_inline uint hash_uint2(const uint kx, const uint ky)
Definition hash.h:90
ccl_device_inline uint hash_uint(const uint kx)
Definition hash.h:77
ccl_device_inline float4 hash_float4_to_float4(const float4 k)
Definition hash.h:203
ccl_device_inline uint hash_iqnt2d(const uint x, const uint y)
Definition hash.h:538
ccl_device_forceinline float uint_to_float_incl(const uint n)
Definition hash.h:24
ccl_device_inline float hash_float4_to_float(const float4 k)
Definition hash.h:183
ccl_device_inline float hash_hp_float(const uint i)
Definition hash.h:450
ccl_device_inline float2 hash_float4_to_float2(const float4 k)
Definition hash.h:247
ccl_device_inline float3 hash_float4_to_float3(const float4 k)
Definition hash.h:227
ccl_device_inline uint hash_hp_uint(uint i)
Definition hash.h:424
ccl_device_inline uint hash_uint3(const uint kx, const uint ky, const uint kz)
Definition hash.h:104
ccl_device_inline float hash_uint4_to_float(const uint kx, const uint ky, const uint kz, const uint kw)
Definition hash.h:158
ccl_device_inline float hash_uint2_to_float(const uint kx, const uint ky)
Definition hash.h:148
ccl_device_inline uint hash_hp_seeded_uint(const uint i, uint seed)
Definition hash.h:439
ccl_device_inline float3 hash_float3_to_float3(const float3 k)
Definition hash.h:196
ccl_device_inline float hash_uint3_to_float(const uint kx, const uint ky, const uint kz)
Definition hash.h:153
CCL_NAMESPACE_BEGIN ccl_device_forceinline float uint_to_float_excl(const uint n)
Definition hash.h:13
#define mix(a, b, c)
Definition hash.h:35
ccl_device_inline uint count_leading_zeros(const uint x)
Definition math_base.h:692
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
float x
float y
float z
Definition sky_float3.h:27
float y
Definition sky_float3.h:27
float x
Definition sky_float3.h:27
i
Definition text_draw.cc:230
ccl_device_inline vint8 make_vint8(const vfloat8 f)