/**
* This program uses the MurmurHash 2A hash function as a PRNG by
* simulating the process of feeding it successively longer blocks of
* all zeros. Each 32-bit hash value doubles as the pseudo-random
* number which is written as binary on stdout in the byte order of
* the machine.
*
* The last time I ran this program and fed its output to dieharder,
* it had no failures.
*
* @file
* @brief MurmurHash 2A hash function as PRNG
*/
#include
#include
#include
#include
#define mmix(h,k) { k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; }
int
main(int argc,
char* argv[])
{
int rv = 0;
uint32_t k = 0; /* used in mmix() macro above */
uint32_t r = 24; /* used in mmix() macro above */
uint32_t t = 0;
uint32_t a = 0xaa87231f;
uint32_t b = 0;
uint32_t m = 0x5bd1e995;
uint32_t l = 0;
uint32_t block_size = 0;
for (block_size = 0 ; ; ++block_size) {
#if 0
/* Check for overflow. */
if (block_size == UINT32_MAX) {
fprintf(stderr, "*** Error: block_size overflow detected.\n");
rv = 1;
break;
}
#endif
/* This is equivalent to the main loop which works on 4 bytes
* at a time. */
if ((block_size >= 4) && (block_size % 4 == 0)) {
k = 0;
mmix(a, k);
}
/* Post-processing starts here. "data" is zero so all of the
* "switch()" in the reference implementation has no
* effect. */
b = a;
t = 0;
l = block_size;
mmix(b, t);
mmix(b, l);
b ^= b >> 13;
b *= m;
b ^= b >> 15;
/* Write the hash value to stdout as binary in the byte order
* of the machine. */
if (fwrite(&b, sizeof(b), 1, stdout) != 1) {
if (feof(stdout)) {
fprintf(stderr, "*** Error: fwrite: Unexpected EOF.\n");
} else {
fprintf(stderr, "*** Error: fwrite: %s\n", strerror(errno));
}
rv = 1;
break;
}
}
return rv;
}