Last active
December 24, 2021 07:15
-
-
Save michaeljclark/46c28f82afe0b858d2322a5965f0839c to your computer and use it in GitHub Desktop.
maj2_random is a simplified floating point hash function derived from SHA-2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* maj2_random | |
* | |
* maj2_random is a simplified floating point hash function derived from SHA-2, | |
* retaining its high quality entropy compression function modified to permute | |
* entropy from a vec2 (designed for UV coordinates) returning float values | |
* between 0.0 and 1.0. since maj2_random is a hash function it will return | |
* coherent noise. vector argument can be truncated prior to increase grain. | |
*/ | |
#define NROUNDS 2 | |
/* first 8 rounds of the SHA-256 k constant */ | |
uint sha256_k[8] = uint[] | |
( | |
0x428a2f98u, 0x71374491u, 0xb5c0fbcfu, 0xe9b5dba5u, | |
0x3956c25bu, 0x59f111f1u, 0x923f82a4u, 0xab1c5ed5u | |
); | |
uint ror(uint x, int d) { return (x >> d) | (x << (32-d)); } | |
uint sigma0(uint h1) { return ror(h1, 2) ^ ror(h1, 13) ^ ror(h1, 22); } | |
uint sigma1(uint h4) { return ror(h4, 6) ^ ror(h4, 11) ^ ror(h4, 25); } | |
uint ch(uint x, uint y, uint z) { return z ^ (x & (y ^ z)); } | |
uint maj(uint x, uint y, uint z) { return (x & y) ^ ((x ^ y) & z); } | |
uint gamma0(uint a) { return ror(a, 7) ^ ror(a, 18) ^ (a >> 3); } | |
uint gamma1(uint b) { return ror(b, 17) ^ ror(b, 19) ^ (b >> 10); } | |
vec2 unorm(uvec2 n) { return uvec2(n & uvec2((1u<<23)-1u)) / vec2((1u<<23)-1u); } | |
vec2 trunc(vec2 uv, float d) { return floor(uv / d) * d; } | |
vec2 maj2_random(vec2 uv) | |
{ | |
uint H[8] = uint[] ( 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u ); | |
uint W[2]; | |
uint T0,T1; | |
int i; | |
/* | |
* extract 48-bits of entropy from mantissas to create truncated | |
* two word initialization vector 'W' composed using the 48-bits | |
* of 'uv' entropy rotated and copied to keep the field equalized. | |
* exponent is ignored as the inputs are normalized 'uv' values. | |
*/ | |
vec2 s = sign(uv); /* note: we don't have frexp in early GLSL */ | |
uint x = uint(abs(uv.x) * float(1u<<23)) | (uint(s.x < 0) << 23); | |
uint y = uint(abs(uv.y) * float(1u<<23)) | (uint(s.y < 0) << 23); | |
W[0] = x | (y << 24); | |
W[1] = (y >> 8) | (x << 16); | |
for (i=0; i<NROUNDS; i++) { | |
W[i] = gamma1(W[(i-2)&1]) + W[(i-7)&1] + gamma0(W[(i-15)&1]) + W[(i-16)&1]; | |
} | |
/* we use N rounds instead of 64 and alternate 2 words of iv in W */ | |
for (i=0; i<NROUNDS; i++) { | |
T0 = W[i&1] + H[7] + sigma1(H[4]) + ch(H[4], H[5], H[6]) + sha256_k[i]; | |
T1 = maj(H[0], H[1], H[2]) + sigma0(H[0]); | |
H[7] = H[6]; | |
H[6] = H[5]; | |
H[5] = H[4]; | |
H[4] = H[3] + T0; | |
H[3] = H[2]; | |
H[2] = H[1]; | |
H[1] = H[0]; | |
H[0] = T0 + T1; | |
} | |
return unorm(uvec2(H[0] ^ H[1] ^ H[2] ^ H[3], | |
H[4] ^ H[5] ^ H[6] ^ H[7])); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment