/** * 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; }