diff --git a/murmur3.h b/murmur3.h index 37b00069..e6e4e109 100644 --- a/murmur3.h +++ b/murmur3.h @@ -32,7 +32,6 @@ SOFTWARE. #include -#include "endian.h" #include "ihash.h" #include "binary.h" #include "error_handler.h" @@ -47,25 +46,26 @@ SOFTWARE. namespace etl { //*************************************************************************** - /// Calculates the murmur3_32 hash. + /// Calculates the murmur3 hash. /// See https://en.wikipedia.org/wiki/MurmurHash for more details. ///\tparam ENDIANNESS The endianness of the calculation for input types larger than uint8_t. Default = endian::little. - ///\ingroup murmur3_32 + ///\ingroup murmur3 //*************************************************************************** - template - class murmur3_32 : public etl::ihash + template + class murmur3 { public: - typedef uint32_t value_type; + STATIC_ASSERT((etl::is_same::value || etl::is_same::value), "Only 32 & 64 bit types supported"); + + typedef THash value_type; //************************************************************************* /// Default constructor. /// \param seed The seed value. Default = 0. //************************************************************************* - murmur3_32(value_type seed = 0) - : seed(seed), - ihash(etl::endian(ENDIANNESS)) + murmur3(value_type seed = 0) + : seed(seed) { reset(); } @@ -77,12 +77,25 @@ namespace etl /// \param seed The seed value. Default = 0. //************************************************************************* template - murmur3_32(TIterator begin, const TIterator end, value_type seed = 0) - : seed(seed), - ihash(etl::endian(ENDIANNESS)) + murmur3(TIterator begin, const TIterator end, value_type seed = 0) + : seed(seed) { + STATIC_ASSERT(sizeof(typename std::iterator_traits::value_type) == 1, "Incompatible type"); + reset(); - add(begin, end); + while (begin != end) + { + block |= (*begin++) << (block_fill_count * 8); + + if (++block_fill_count == FULL_BLOCK) + { + add_block(); + block_fill_count = 0; + block = 0; + } + + ++char_count; + } } //************************************************************************* @@ -105,17 +118,28 @@ namespace etl template void add(TIterator begin, const TIterator end) { - ihash::add(begin, end); - } + STATIC_ASSERT(sizeof(typename std::iterator_traits::value_type) == 1, "Incompatible type"); - //************************************************************************* - /// Adds a value. - /// \param value The value to add to the hash. - //************************************************************************* - template - void add(TValue value) - { - ihash::add(value); + if (is_finalised) + { + ETL_ERROR(hash_finalised()); + } + else + { + while (begin != end) + { + block |= (*begin++) << (block_fill_count * 8); + + if (++block_fill_count == FULL_BLOCK) + { + add_block(); + block_fill_count = 0; + block = 0; + } + + ++char_count; + } + } } //************************************************************************* @@ -162,15 +186,6 @@ namespace etl return value(); } - //************************************************************************* - /// Gets the generic digest value. - //************************************************************************* - generic_digest digest() - { - finalise(); - return ihash::get_digest(hash); - } - private: //************************************************************************* @@ -227,4 +242,4 @@ namespace etl }; } -#endif // MURMUR3_H +#endif diff --git a/test/murmurhash3.cpp b/test/murmurhash3.cpp index 0d91feaa..284774f5 100644 --- a/test/murmurhash3.cpp +++ b/test/murmurhash3.cpp @@ -91,8 +91,7 @@ FORCE_INLINE uint64_t fmix64(uint64_t k) //----------------------------------------------------------------------------- -void MurmurHash3_x86_32(const void * key, int len, - uint32_t seed, void * out) +void MurmurHash3_x86_32(const void * key, int len, uint32_t seed, void * out) { const uint8_t * data = (const uint8_t*)key; const int nblocks = len / 4; diff --git a/test/test_murmur3.cpp b/test/test_murmur3.cpp index 9deb361b..c2a76903 100644 --- a/test/test_murmur3.cpp +++ b/test/test_murmur3.cpp @@ -46,7 +46,7 @@ namespace { std::string data("123456789"); - uint32_t hash = etl::murmur3_32<>(data.begin(), data.end()); + uint32_t hash = etl::murmur3(data.begin(), data.end()); uint32_t compare; MurmurHash3_x86_32(data.c_str(), data.size(), 0, &compare); @@ -59,11 +59,11 @@ namespace { std::string data("123456789"); - etl::murmur3_32<> murmur3_32_calculator; + etl::murmur3 murmur3_32_calculator; for (size_t i = 0; i < data.size(); ++i) { - murmur3_32_calculator += data[i]; + murmur3_32_calculator.add(data[i]); } uint32_t hash = murmur3_32_calculator; @@ -79,7 +79,7 @@ namespace { std::string data("123456789"); - etl::murmur3_32<> murmur3_32_calculator; + etl::murmur3 murmur3_32_calculator; murmur3_32_calculator.add(data.begin(), data.end()); @@ -96,25 +96,19 @@ namespace { std::vector data1 = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; std::vector data2 = { 0x04030201, 0x08070605 }; - std::vector data3 = { 0x01020304, 0x05060708 }; - uint32_t hash1 = etl::murmur3_32(data1.begin(), data1.end()); - uint32_t hash2 = etl::murmur3_32(data2.begin(), data2.end()); - uint32_t hash3 = etl::murmur3_32(data3.begin(), data3.end()); + uint32_t hash1 = etl::murmur3(data1.begin(), data1.end()); + uint32_t hash2 = etl::murmur3((uint8_t*)&data2[0], (uint8_t*)&data2[0] + (data2.size() * sizeof(uint32_t))); + CHECK_EQUAL(hash1, hash2); - CHECK_EQUAL(hash1, hash3); uint32_t compare1; - MurmurHash3_x86_32(&data1[0], data1.size(), 0, &compare1); + MurmurHash3_x86_32(&*data1.begin(), data1.size(), 0, &compare1); CHECK_EQUAL(compare1, hash1); uint32_t compare2; - MurmurHash3_x86_32(&data2[0], data2.size() * sizeof(uint32_t), 0, &compare2); + MurmurHash3_x86_32((uint8_t*)&data2[0], data2.size() * sizeof(uint32_t), 0, &compare2); CHECK_EQUAL(compare2, hash2); - - uint32_t compare3; - MurmurHash3_x86_32(&data3[0], data3.size() * sizeof(uint32_t), 0, &compare3); - CHECK_EQUAL(compare2, hash3); } }; }