#include "Murmur3.hpp"
#include <time.h>
#include <stdint.h>
#include "../common/compat.hpp"
namespace sprawl
{
namespace murmur3
{
namespace Murmur3Cpp
{
static size_t seed = size_t(time(nullptr));
}
#if SPRAWL_32_BIT
namespace Murmur3Cpp
{
static inline int32_t RotateLeft(const uint32_t x, const uint8_t r)
{
return ( x << r ) | ( x >> (32 - r) );
}
}
size_t Hash(const void* const data, const size_t size, const size_t seed)
{
const uint32_t c1 = 0xcc9e2d51;
const uint32_t c2 = 0x1b873593;
const uint8_t r1 = 15;
const uint8_t r2 = 13;
const uint32_t m = 5;
const uint32_t n = 0xe6546b64;
const uint8_t* buffer = (const uint8_t*) data;
const uint32_t remainder = size % sizeof(uint32_t);
const uint32_t numChunks = (size - remainder) / sizeof(uint32_t);
uint32_t outputHash = seed;
for(uint32_t i = 0; i < numChunks; ++i, buffer += sizeof(uint32_t))
{
uint32_t k = *((uint32_t*) buffer);
k *= c1;
k = Murmur3Cpp::RotateLeft(k, r1);
k *= c2;
outputHash ^= k;
outputHash = Murmur3Cpp::RotateLeft(outputHash, r2);
outputHash = (outputHash * m) + n;
}
if(remainder > 0)
{
uint32_t finalChunk = 0;
// Intentional fallthrough cases to calculate the final chunk value.
switch(remainder)
{
case 3: finalChunk |= uint32_t(*buffer); finalChunk <<= 8; ++buffer;
case 2: finalChunk |= uint32_t(*buffer); finalChunk <<= 8; ++buffer;
case 1: finalChunk |= uint32_t(*buffer); ++buffer;
}
finalChunk *= c1;
finalChunk = Murmur3Cpp::RotateLeft(finalChunk, r1);
finalChunk *= c2;
outputHash ^= finalChunk;
}
outputHash ^= uint32_t(size);
outputHash ^= (outputHash >> 16);
outputHash *= 0x85ebca6b;
outputHash ^= (outputHash >> 13);
outputHash *= 0xc2b2ae35;
outputHash ^= (outputHash >> 16);
return outputHash;
}
#else
namespace Murmur3Cpp
{
static inline int64_t RotateLeft(const uint64_t x, const uint8_t r)
{
return ( x << r ) | ( x >> (64 - r) );
}
}
size_t Hash(const void* const data, const size_t size, const size_t seed)
{
const uint64_t c1 = 0x87c37b91114253d5ULL;
const uint64_t c2 = 0x4cf5ad432745937fULL;
const uint8_t r1 = 15;
const uint8_t r2 = 13;
const uint64_t m = 5;
const uint64_t n = 0x52dce72938495ab5ULL;
const uint8_t* buffer = (const uint8_t*) data;
const uint64_t remainder = size % sizeof(uint64_t);
const uint64_t numChunks = (size - remainder) / sizeof(uint64_t);
uint64_t outputHash = seed;
for(uint64_t i = 0; i < numChunks; ++i, buffer += sizeof(uint64_t))
{
uint64_t k = *((uint64_t*) buffer);
k *= c1;
k = Murmur3Cpp::RotateLeft(k, r1);
k *= c2;
outputHash ^= k;
outputHash = Murmur3Cpp::RotateLeft(outputHash, r2);
outputHash = (outputHash * m) + n;
}
if(remainder > 0)
{
uint64_t finalChunk = 0;
// Intentional fallthrough cases to calculate the final chunk value.
switch(remainder)
{
case 7: finalChunk |= uint64_t(*buffer); finalChunk <<= 8; ++buffer;
case 6: finalChunk |= uint64_t(*buffer); finalChunk <<= 8; ++buffer;
case 5: finalChunk |= uint64_t(*buffer); finalChunk <<= 8; ++buffer;
case 4: finalChunk |= uint64_t(*buffer); finalChunk <<= 8; ++buffer;
case 3: finalChunk |= uint64_t(*buffer); finalChunk <<= 8; ++buffer;
case 2: finalChunk |= uint64_t(*buffer); finalChunk <<= 8; ++buffer;
case 1: finalChunk |= uint64_t(*buffer); ++buffer;
}
finalChunk *= c1;
finalChunk = Murmur3Cpp::RotateLeft(finalChunk, r1);
finalChunk *= c2;
outputHash ^= finalChunk;
}
outputHash ^= uint64_t(size);
outputHash ^= (outputHash >> 33);
outputHash *= 0xff51afd7ed558ccdULL;
outputHash ^= (outputHash >> 33);
outputHash *= 0xc4ceb9fe1a85ec53ULL;
outputHash ^= (outputHash >> 33);
return outputHash;
}
#endif
size_t Hash(const void* const data, const size_t size)
{
return Hash(data, size, Murmur3Cpp::seed);
}
size_t HashInt32(uint32_t data)
{
data ^= (data >> 16);
data *= 0x85ebca6b;
data ^= (data >> 13);
data *= 0xc2b2ae35;
data ^= (data >> 16);
return data;
}
size_t HashInt64(uint64_t data)
{
data ^= (data >> 33);
data *= 0xff51afd7ed558ccdULL;
data ^= (data >> 33);
data *= 0xc4ceb9fe1a85ec53ULL;
data ^= (data >> 33);
return data;
}
size_t HashPointer(intptr_t data)
{
#if SPRAWL_32_BIT
return HashInt32(data);
#else
return HashInt64(data);
#endif
}
}
}
| # | Change | User | Description | Committed | |
|---|---|---|---|---|---|
| #1 | 23398 | ququlala | "Forking branch Mainline of shadauxcat-libsprawl to ququlala-libsprawl." | ||
| //guest/ShadauxCat/Sprawl/Mainline/hash/Murmur3.cpp | |||||
| #3 | 19906 | ShadauxCat |
- Added tag, compile time string type - Since tag requires visual studio 2015, removed compatibility code for earlier versions of visual studio - Improved compiler detection - Added endianness detection - Added template if/else helper - Fixed bug with murmur3 64 bit - Added seed argument for murmur3 #review-19907 |
||
| #2 | 12508 | ShadauxCat |
-Added threading library. Currently only functional for Linux; Windows will fail to link. (I will fix this soon.) -Fixed missing move and copy constructors in List and ForwardList -Fixed broken move constructor in HashMap -Fixed missing const get() in HashMap -Fixed broken operator-> in ListIterator -Added sprawl::noncopyable -Added sketch headers for filesystem library -Made StringLiteral hashable, added special hashes for pointers and integers in murmur3 -Fixed compiler warning in async_network -Updated memory allocators to use new threading library for mutexes -Added accessibility to sprawl::StringLiteral to be able toa ccess its pointer and length and perform pointer comparisons #review-12504 |
||
| #1 | 11496 | ShadauxCat | Initial checkin: Current states for csbuild and libSprawl | ||