diff options
Diffstat (limited to 'intern/cycles/util/hash.h')
-rw-r--r-- | intern/cycles/util/hash.h | 389 |
1 files changed, 389 insertions, 0 deletions
diff --git a/intern/cycles/util/hash.h b/intern/cycles/util/hash.h new file mode 100644 index 00000000000..013a0f90a27 --- /dev/null +++ b/intern/cycles/util/hash.h @@ -0,0 +1,389 @@ +/* + * Copyright 2011-2013 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __UTIL_HASH_H__ +#define __UTIL_HASH_H__ + +#include "util/types.h" + +CCL_NAMESPACE_BEGIN + +/* ***** Jenkins Lookup3 Hash Functions ***** */ + +/* Source: http://burtleburtle.net/bob/c/lookup3.c */ + +#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k)))) + +#define mix(a, b, c) \ + { \ + a -= c; \ + a ^= rot(c, 4); \ + c += b; \ + b -= a; \ + b ^= rot(a, 6); \ + a += c; \ + c -= b; \ + c ^= rot(b, 8); \ + b += a; \ + a -= c; \ + a ^= rot(c, 16); \ + c += b; \ + b -= a; \ + b ^= rot(a, 19); \ + a += c; \ + c -= b; \ + c ^= rot(b, 4); \ + b += a; \ + } \ + ((void)0) + +#define final(a, b, c) \ + { \ + c ^= b; \ + c -= rot(b, 14); \ + a ^= c; \ + a -= rot(c, 11); \ + b ^= a; \ + b -= rot(a, 25); \ + c ^= b; \ + c -= rot(b, 16); \ + a ^= c; \ + a -= rot(c, 4); \ + b ^= a; \ + b -= rot(a, 14); \ + c ^= b; \ + c -= rot(b, 24); \ + } \ + ((void)0) + +ccl_device_inline uint hash_uint(uint kx) +{ + uint a, b, c; + a = b = c = 0xdeadbeef + (1 << 2) + 13; + + a += kx; + final(a, b, c); + + return c; +} + +ccl_device_inline uint hash_uint2(uint kx, uint ky) +{ + uint a, b, c; + a = b = c = 0xdeadbeef + (2 << 2) + 13; + + b += ky; + a += kx; + final(a, b, c); + + return c; +} + +ccl_device_inline uint hash_uint3(uint kx, uint ky, uint kz) +{ + uint a, b, c; + a = b = c = 0xdeadbeef + (3 << 2) + 13; + + c += kz; + b += ky; + a += kx; + final(a, b, c); + + return c; +} + +ccl_device_inline uint hash_uint4(uint kx, uint ky, uint kz, uint kw) +{ + uint a, b, c; + a = b = c = 0xdeadbeef + (4 << 2) + 13; + + a += kx; + b += ky; + c += kz; + mix(a, b, c); + + a += kw; + final(a, b, c); + + return c; +} + +#undef rot +#undef final +#undef mix + +/* Hashing uint or uint[234] into a float in the range [0, 1]. */ + +ccl_device_inline float hash_uint_to_float(uint kx) +{ + return (float)hash_uint(kx) / (float)0xFFFFFFFFu; +} + +ccl_device_inline float hash_uint2_to_float(uint kx, uint ky) +{ + return (float)hash_uint2(kx, ky) / (float)0xFFFFFFFFu; +} + +ccl_device_inline float hash_uint3_to_float(uint kx, uint ky, uint kz) +{ + return (float)hash_uint3(kx, ky, kz) / (float)0xFFFFFFFFu; +} + +ccl_device_inline float hash_uint4_to_float(uint kx, uint ky, uint kz, uint kw) +{ + return (float)hash_uint4(kx, ky, kz, kw) / (float)0xFFFFFFFFu; +} + +/* Hashing float or float[234] into a float in the range [0, 1]. */ + +ccl_device_inline float hash_float_to_float(float k) +{ + return hash_uint_to_float(__float_as_uint(k)); +} + +ccl_device_inline float hash_float2_to_float(float2 k) +{ + return hash_uint2_to_float(__float_as_uint(k.x), __float_as_uint(k.y)); +} + +ccl_device_inline float hash_float3_to_float(float3 k) +{ + return hash_uint3_to_float(__float_as_uint(k.x), __float_as_uint(k.y), __float_as_uint(k.z)); +} + +ccl_device_inline float hash_float4_to_float(float4 k) +{ + return hash_uint4_to_float( + __float_as_uint(k.x), __float_as_uint(k.y), __float_as_uint(k.z), __float_as_uint(k.w)); +} + +/* Hashing float[234] into float[234] of components in the range [0, 1]. */ + +ccl_device_inline float2 hash_float2_to_float2(float2 k) +{ + return make_float2(hash_float2_to_float(k), hash_float3_to_float(make_float3(k.x, k.y, 1.0))); +} + +ccl_device_inline float3 hash_float3_to_float3(float3 k) +{ + return make_float3(hash_float3_to_float(k), + hash_float4_to_float(make_float4(k.x, k.y, k.z, 1.0)), + hash_float4_to_float(make_float4(k.x, k.y, k.z, 2.0))); +} + +ccl_device_inline float4 hash_float4_to_float4(float4 k) +{ + return make_float4(hash_float4_to_float(k), + hash_float4_to_float(make_float4(k.w, k.x, k.y, k.z)), + hash_float4_to_float(make_float4(k.z, k.w, k.x, k.y)), + hash_float4_to_float(make_float4(k.y, k.z, k.w, k.x))); +} + +/* Hashing float or float[234] into float3 of components in range [0, 1]. */ + +ccl_device_inline float3 hash_float_to_float3(float k) +{ + return make_float3(hash_float_to_float(k), + hash_float2_to_float(make_float2(k, 1.0)), + hash_float2_to_float(make_float2(k, 2.0))); +} + +ccl_device_inline float3 hash_float2_to_float3(float2 k) +{ + return make_float3(hash_float2_to_float(k), + hash_float3_to_float(make_float3(k.x, k.y, 1.0)), + hash_float3_to_float(make_float3(k.x, k.y, 2.0))); +} + +ccl_device_inline float3 hash_float4_to_float3(float4 k) +{ + return make_float3(hash_float4_to_float(k), + hash_float4_to_float(make_float4(k.z, k.x, k.w, k.y)), + hash_float4_to_float(make_float4(k.w, k.z, k.y, k.x))); +} + +/* SSE Versions Of Jenkins Lookup3 Hash Functions */ + +#ifdef __KERNEL_SSE2__ +# define rot(x, k) (((x) << (k)) | (srl(x, 32 - (k)))) + +# define mix(a, b, c) \ + { \ + a -= c; \ + a ^= rot(c, 4); \ + c += b; \ + b -= a; \ + b ^= rot(a, 6); \ + a += c; \ + c -= b; \ + c ^= rot(b, 8); \ + b += a; \ + a -= c; \ + a ^= rot(c, 16); \ + c += b; \ + b -= a; \ + b ^= rot(a, 19); \ + a += c; \ + c -= b; \ + c ^= rot(b, 4); \ + b += a; \ + } + +# define final(a, b, c) \ + { \ + c ^= b; \ + c -= rot(b, 14); \ + a ^= c; \ + a -= rot(c, 11); \ + b ^= a; \ + b -= rot(a, 25); \ + c ^= b; \ + c -= rot(b, 16); \ + a ^= c; \ + a -= rot(c, 4); \ + b ^= a; \ + b -= rot(a, 14); \ + c ^= b; \ + c -= rot(b, 24); \ + } + +ccl_device_inline ssei hash_ssei(ssei kx) +{ + ssei a, b, c; + a = b = c = ssei(0xdeadbeef + (1 << 2) + 13); + + a += kx; + final(a, b, c); + + return c; +} + +ccl_device_inline ssei hash_ssei2(ssei kx, ssei ky) +{ + ssei a, b, c; + a = b = c = ssei(0xdeadbeef + (2 << 2) + 13); + + b += ky; + a += kx; + final(a, b, c); + + return c; +} + +ccl_device_inline ssei hash_ssei3(ssei kx, ssei ky, ssei kz) +{ + ssei a, b, c; + a = b = c = ssei(0xdeadbeef + (3 << 2) + 13); + + c += kz; + b += ky; + a += kx; + final(a, b, c); + + return c; +} + +ccl_device_inline ssei hash_ssei4(ssei kx, ssei ky, ssei kz, ssei kw) +{ + ssei a, b, c; + a = b = c = ssei(0xdeadbeef + (4 << 2) + 13); + + a += kx; + b += ky; + c += kz; + mix(a, b, c); + + a += kw; + final(a, b, c); + + return c; +} + +# if defined(__KERNEL_AVX__) +ccl_device_inline avxi hash_avxi(avxi kx) +{ + avxi a, b, c; + a = b = c = avxi(0xdeadbeef + (1 << 2) + 13); + + a += kx; + final(a, b, c); + + return c; +} + +ccl_device_inline avxi hash_avxi2(avxi kx, avxi ky) +{ + avxi a, b, c; + a = b = c = avxi(0xdeadbeef + (2 << 2) + 13); + + b += ky; + a += kx; + final(a, b, c); + + return c; +} + +ccl_device_inline avxi hash_avxi3(avxi kx, avxi ky, avxi kz) +{ + avxi a, b, c; + a = b = c = avxi(0xdeadbeef + (3 << 2) + 13); + + c += kz; + b += ky; + a += kx; + final(a, b, c); + + return c; +} + +ccl_device_inline avxi hash_avxi4(avxi kx, avxi ky, avxi kz, avxi kw) +{ + avxi a, b, c; + a = b = c = avxi(0xdeadbeef + (4 << 2) + 13); + + a += kx; + b += ky; + c += kz; + mix(a, b, c); + + a += kw; + final(a, b, c); + + return c; +} +# endif + +# undef rot +# undef final +# undef mix + +#endif + +#ifndef __KERNEL_GPU__ +static inline uint hash_string(const char *str) +{ + uint i = 0, c; + + while ((c = *str++)) + i = i * 37 + c; + + return i; +} +#endif + +CCL_NAMESPACE_END + +#endif /* __UTIL_HASH_H__ */ |