/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * limitations under the License. * * Copyright 2015 Danny Robson <danny@nerdcruft.net> */ #include "murmur2.hpp" #include "common.hpp" using cruft::hash::murmur2; /////////////////////////////////////////////////////////////////////////////// static uint32_t hash_32 (const void *restrict key, size_t len, uint32_t seed) { // setup constexpr auto m = cruft::hash::detail::murmur2::constants<uint32_t>::m; uint32_t h = seed ^ (len & 0xffffffff); // body auto cursor = reinterpret_cast<const uint32_t*> (key); auto last = cursor + len / sizeof (uint32_t); for (; cursor < last; ++cursor) h = cruft::hash::murmur2<uint32_t>::mix (h, *cursor); // tail if (len % sizeof (uint32_t)) { h ^= cruft::hash::murmur::tail<uint32_t> (reinterpret_cast<const uint8_t*> (cursor), len); h *= m; } // finalise h ^= h >> 13; h *= m; h ^= h >> 15; return h; } //----------------------------------------------------------------------------- static uint64_t hash_64 (const void *restrict key, size_t len, uint64_t seed) { // setup constexpr auto m = cruft::hash::detail::murmur2::constants<uint64_t>::m; constexpr auto r = cruft::hash::detail::murmur2::constants<uint64_t>::r; uint64_t h = seed ^ (len * m); // body auto cursor = reinterpret_cast<const uint64_t*> (key); auto last = cursor + len / sizeof (uint64_t); for (; cursor < last; ++cursor) h = cruft::hash::murmur2<uint64_t>::mix (h, *cursor); // tail if (len % sizeof (uint64_t)) { h ^= cruft::hash::murmur::tail<uint64_t> (reinterpret_cast<const uint8_t*> (cursor), len); h *= m; } // finalise h ^= h >> r; h *= m; h ^= h >> r; return h; } /////////////////////////////////////////////////////////////////////////////// template <typename DigestT> typename murmur2<DigestT>::digest_t murmur2<DigestT>::operator() (cruft::view<const uint8_t*> data) const noexcept { static_assert (std::is_same_v<DigestT,uint32_t> || std::is_same_v<DigestT,uint64_t>); if constexpr (std::is_same_v<DigestT,uint32_t>) { return hash_32 (data.data (), data.size (), m_seed); } if constexpr (std::is_same_v<DigestT,uint64_t>) { return hash_64 (data.data (), data.size (), m_seed); } unreachable (); } /////////////////////////////////////////////////////////////////////////////// template class cruft::hash::murmur2<uint32_t>; template class cruft::hash::murmur2<uint64_t>;