From e1c115c71ae7e02245d578c80f98408010e66bcd Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Fri, 1 Jul 2016 17:01:21 +1000 Subject: [PATCH] murmur2: make mixing constexpr and inline --- hash/murmur/murmur2.cpp | 61 ++------------------------------ hash/murmur/murmur2.hpp | 6 ++-- hash/murmur/murmur2.ipp | 78 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 60 deletions(-) create mode 100644 hash/murmur/murmur2.ipp diff --git a/hash/murmur/murmur2.cpp b/hash/murmur/murmur2.cpp index 2cc80061..79773fa3 100644 --- a/hash/murmur/murmur2.cpp +++ b/hash/murmur/murmur2.cpp @@ -21,61 +21,6 @@ #include "common.hpp" -/////////////////////////////////////////////////////////////////////////////// -template struct constants { }; - -template <> -struct constants { - static const uint32_t m = 0x5bd1e995; - static const int32_t r = 24; -}; - -template <> -struct constants { - static const uint64_t m = 0xc6a4a7935bd1e995; - static const int64_t r = 47; -}; - - -///////////////////////////////////////////////////////////////////// -uint32_t -util::hash::murmur2::mix (uint32_t h, uint32_t k) -{ - static const uint32_t m = constants::m; - static const uint32_t r = constants::r; - - k *= m; - k ^= k >> r; - k *= m; - - h *= m; - h ^= k; - - return h; -} - - -//----------------------------------------------------------------------------- -// 64 bit murmur2 mixing function. Note the last two lines are swapped -// compared with 32 bit murmur2_mix. It's not clear if this is deliberate -// in the canonical implementation, so we just leave it to help compatibility. -uint64_t -util::hash::murmur2::mix (uint64_t h, uint64_t k) -{ - static const uint64_t m = constants::m; - static const uint64_t r = constants::r; - - k *= m; - k ^= k >> r; - k *= m; - - h ^= k; - h *= m; - - return h; -} - - /////////////////////////////////////////////////////////////////////////////// uint32_t util::hash::murmur2::hash_32 (const void *restrict key, @@ -85,7 +30,7 @@ util::hash::murmur2::hash_32 (const void *restrict key, CHECK (key); // setup - static const auto m = constants::m; + constexpr auto m = detail::constants::m; uint32_t h = seed ^ uint32_t (len); // body @@ -116,8 +61,8 @@ util::hash::murmur2::hash_64 (const void *restrict key, uint64_t seed) { // setup - const auto m = constants::m; - const auto r = constants::r; + constexpr auto m = detail::constants::m; + constexpr auto r = detail::constants::r; uint64_t h = seed ^ (len * m); diff --git a/hash/murmur/murmur2.hpp b/hash/murmur/murmur2.hpp index 50973d8d..84fa4c3c 100644 --- a/hash/murmur/murmur2.hpp +++ b/hash/murmur/murmur2.hpp @@ -24,12 +24,14 @@ // variants is deliberately not provided. You can damn well align your data or // fix the algorithm. namespace util { namespace hash { namespace murmur2 { - uint32_t mix (uint32_t, uint32_t); - uint64_t mix (uint64_t, uint64_t); + constexpr uint32_t mix (uint32_t, uint32_t); + constexpr uint64_t mix (uint64_t, uint64_t); uint32_t hash_32 (const void *restrict data, size_t len, uint32_t seed); uint64_t hash_64 (const void *restrict data, size_t len, uint64_t seed); } } } +#include "./murmur2.ipp" + #endif diff --git a/hash/murmur/murmur2.ipp b/hash/murmur/murmur2.ipp new file mode 100644 index 00000000..5af8a497 --- /dev/null +++ b/hash/murmur/murmur2.ipp @@ -0,0 +1,78 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright 2016 Danny Robson + */ + +#if defined(__UTIL_HASH_MURMUR_MURMUR2_IPP) +#error +#endif + +#define __UTIL_HASH_MURMUR_MURMUR2_IPP + + +/////////////////////////////////////////////////////////////////////////////// +namespace util { namespace hash { namespace murmur2 { namespace detail { + template struct constants; + + template <> + struct constants { + static const uint32_t m = 0x5bd1e995; + static const int32_t r = 24; + }; + + template <> + struct constants { + static const uint64_t m = 0xc6a4a7935bd1e995; + static const int64_t r = 47; + }; +} } } } + + +///////////////////////////////////////////////////////////////////// +constexpr uint32_t +util::hash::murmur2::mix (uint32_t h, uint32_t k) +{ + constexpr uint32_t m = detail::constants::m; + constexpr uint32_t r = detail::constants::r; + + k *= m; + k ^= k >> r; + k *= m; + + h *= m; + h ^= k; + + return h; +} + + +//----------------------------------------------------------------------------- +// 64 bit murmur2 mixing function. Note the last two lines are swapped +// compared with 32 bit murmur2_mix. It's not clear if this is deliberate +// in the canonical implementation, so we just leave it to help compatibility. +constexpr uint64_t +util::hash::murmur2::mix (uint64_t h, uint64_t k) +{ + constexpr uint64_t m = detail::constants::m; + constexpr uint64_t r = detail::constants::r; + + k *= m; + k ^= k >> r; + k *= m; + + h ^= k; + h *= m; + + return h; +}