Created
October 25, 2014 00:04
-
-
Save atavener/d748ecb788830ce4d8d0 to your computer and use it in GitHub Desktop.
Some hash functions to generate pseudo-random values per-coordinate, in C, with OCaml FFI.
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
/* Some hash functions to generate pseudo-random values per-coordinate. | |
* Useful for spatial synthesis, such as procedural textures. | |
*/ | |
/*** Bob Jenkins' mix and final ***/ | |
#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; \ | |
} | |
#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); \ | |
} | |
/* ------------------------------------ */ | |
/* A portion of Paul Hsieh's hash */ | |
/* use this to generate a PRN sequence without state */ | |
uint32_t HsiehHashNext( uint32_t hash ){ | |
hash ^= hash << 3; | |
hash += hash >> 5; | |
hash ^= hash << 4; | |
hash += hash >> 17; | |
hash ^= hash << 25; | |
hash += hash >> 6; | |
return hash; | |
} | |
/* ------------------------------------ */ | |
/*** OCaml FFI ***/ | |
#define Uint32_val(v) (*((uint32_t *) Data_custom_val(v))) | |
CAMLprim value ocaml_float_of_u32( value i ){ | |
return caml_copy_double((double)Uint32_val(i)); | |
} | |
/* it's fine if we return int32 type to OCaml... so it can understand it... | |
* since we'll be using a C-call for float_of_u32 anyway */ | |
CAMLprim value ocaml_init_rnd( value data, value i ){ | |
CAMLparam2( data, i ); | |
uint32_t *p = (uint32_t*)data; | |
uint32_t a = p[0]; | |
uint32_t b = p[1]; | |
uint32_t c = p[2]; | |
mix(a,b,c); | |
a+= p[3]; b+= p[4]; c+= p[5]; | |
mix(a,b,c); | |
a+= Long_val(i); | |
final(a,b,c); | |
CAMLreturn( caml_copy_int32(c) ); | |
} | |
CAMLprim value ocaml_next_rnd( value i ){ | |
return caml_copy_int32( HsiehHashNext( Uint32_val(i) ) ); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment