jens@1: /* jens@1: * MurmurHash.c jens@1: * MYUtilities jens@1: * jens@1: * This file created by Jens Alfke on 3/17/08. jens@1: * Algorithm & source code by Austin Appleby, released to public domain. jens@1: * jens@1: * Downloaded 3/16/2008. jens@1: * Modified slightly by Jens Alfke (use standard uint32_t and size_t types; jens@1: * change 'm' and 'r' to #defines for better C compatibility.) jens@1: * jens@1: */ jens@1: jens@1: #include "MurmurHash.h" jens@1: jens@1: jens@1: //----------------------------------------------------------------------------- jens@1: // MurmurHash2, by Austin Appleby jens@1: jens@1: // Note - This code makes a few assumptions about how your machine behaves - jens@1: jens@1: // 1. We can read a 4-byte value from any address without crashing jens@1: // 2. sizeof(int) == 4 **Jens: I fixed this by changing 'unsigned int' to 'uint32_t'** jens@1: jens@1: // And it has a few limitations - jens@1: jens@1: // 1. It will not work incrementally. jens@1: // 2. It will not produce the same results on little-endian and big-endian jens@1: // machines. jens@1: jens@1: uint32_t MurmurHash2 ( const void * key, size_t len, uint32_t seed ) jens@1: { jens@1: // 'm' and 'r' are mixing constants generated offline. jens@1: // They're not really 'magic', they just happen to work well. jens@1: jens@1: #define m 0x5bd1e995 jens@1: #define r 24 jens@1: jens@1: // Initialize the hash to a 'random' value jens@1: jens@1: uint32_t h = seed ^ len; jens@1: jens@1: // Mix 4 bytes at a time into the hash jens@1: jens@1: const unsigned char * data = (const unsigned char *)key; jens@1: jens@1: while(len >= 4) jens@1: { jens@1: uint32_t k = *(uint32_t *)data; jens@1: jens@1: k *= m; jens@1: k ^= k >> r; jens@1: k *= m; jens@1: jens@1: h *= m; jens@1: h ^= k; jens@1: jens@1: data += 4; jens@1: len -= 4; jens@1: } jens@1: jens@1: // Handle the last few bytes of the input array jens@1: jens@1: switch(len) jens@1: { jens@1: case 3: h ^= data[2] << 16; jens@1: case 2: h ^= data[1] << 8; jens@1: case 1: h ^= data[0]; jens@1: h *= m; jens@1: }; jens@1: jens@1: // Do a few final mixes of the hash to ensure the last few jens@1: // bytes are well-incorporated. jens@1: jens@1: h ^= h >> 13; jens@1: h *= m; jens@1: h ^= h >> 15; jens@1: jens@1: return h; jens@1: }