Skip to content

Instantly share code, notes, and snippets.

@malkia
Forked from mattyclarkson/LICENSE
Created June 19, 2013 01:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save malkia/5811033 to your computer and use it in GitHub Desktop.
Save malkia/5811033 to your computer and use it in GitHub Desktop.
#include <type_traits>
#include <iostream>
#include <cassert>
#include <cstdint>
#include "murmur3_32_constexpr.hpp"
// Add compilers here
#define UNKNOWN -1
#define GCC 0
#define CLANG 1
// Set up the compiler version
#ifdef __GNUC__
# define CC GCC
# define MAJOR __GNUC_MAJOR__
# define MINOR __GNUC_MINOR__
# define REVISON __GNUC_PATCHLEVEL__
#else
# define CC UNKNOWN
# define MAJOR -1
# define MINOR -1
# define REVISON -1
#endif
// Detection function
#define COMPILER(cc, major, minor, revision) \
(cc == CC) && \
(major >= MAJOR) && \
(minor >= MINOR) && \
(revision >= REVISON)
int main() {
#if COMPILER(GCC, 4, 7, 2)
const uint32_t hash = std::integral_constant<uint32_t,
Murmur3_32("some_string_to_hash", 0xAED123FD)>::value;
#else
# error Untested compiler
#endif
std::cerr << hash << std::endl;
assert(hash == 4291478129);
}
constexpr size_t _StringLengthLoop(const char * const str, const size_t size)
noexcept {
return (str[size] == '\0') ? size : _StringLengthLoop(str, size + 1);
}
constexpr inline size_t _StringLength(const char * const str) noexcept {
return _StringLengthLoop(str, 0);
}
constexpr uint32_t _Murmur3Rotate_32(const uint32_t target,
const uint8_t rotation) noexcept {
return (target << rotation) | (target >> (32 - rotation));
}
constexpr uint32_t _Murmur3ShiftXor_32(const uint32_t hash, const size_t shift)
noexcept {
return hash ^ (hash >> shift);
}
constexpr uint32_t _Murmur3Last_32(const size_t len, const uint32_t hash)
noexcept {
return _Murmur3ShiftXor_32(0xc2b2ae35 * _Murmur3ShiftXor_32(
0x85ebca6b * _Murmur3ShiftXor_32(
hash ^ len, 16), 13), 16);
}
constexpr uint32_t _Murmur3Tail1_32(const char data, const size_t len,
const uint32_t hash, const uint32_t constant) noexcept {
return _Murmur3Last_32(len, hash ^ (0x1b873593 * _Murmur3Rotate_32(
0xcc9e2d51 * (constant ^ static_cast<uint8_t>(data)), 15)));
}
constexpr uint32_t _Murmur3Tail2_32(const char data[2], const size_t len,
const uint32_t hash, const uint32_t constant) noexcept {
return _Murmur3Tail1_32(data[0], len, hash,
constant ^ (static_cast<uint8_t>(data[1]) << 8));
}
constexpr uint32_t _Murmur3Tail3_32(const char data[3], const size_t len,
const uint32_t hash) noexcept {
return _Murmur3Tail2_32(data, len, hash,
0 ^ (static_cast<uint8_t>(data[2]) << 16));
}
constexpr uint32_t _Murmur3Rest_32(const char *const data,
const size_t len, const uint32_t hash) noexcept {
return ((len & 3) == 3) ? _Murmur3Tail3_32(&data[len - 3], len, hash) :
((len & 3) == 2) ? _Murmur3Tail2_32(&data[len - 2], len, hash, 0) :
((len & 3) == 1) ? _Murmur3Tail1_32(data[len - 1], len, hash, 0) :
_Murmur3Last_32(len, hash);
}
constexpr inline uint32_t _Murmur3Load_32(const char *const data,
const size_t i) noexcept {
return static_cast<uint32_t>(data[(i * sizeof(uint32_t)) + 3]) << 24 |
static_cast<uint32_t>(data[(i * sizeof(uint32_t)) + 2]) << 16 |
static_cast<uint32_t>(data[(i * sizeof(uint32_t)) + 1]) << 8 |
static_cast<uint32_t>(data[(i * sizeof(uint32_t)) + 0]) << 0;
}
constexpr inline uint32_t _Murmur3Update_32(const uint32_t hash,
const uint32_t update) noexcept {
return 0xe6546b64 + (5 * _Murmur3Rotate_32(hash ^ (
0x1b873593 * _Murmur3Rotate_32(0xcc9e2d51 * update, 15)), 13));
}
constexpr uint32_t _Murmur3Loop_32(const char *const data,
const size_t len, const uint32_t hash, const size_t i = 0) noexcept {
return (i < (len / 4)) ?
_Murmur3Loop_32(data, len,
_Murmur3Update_32(hash, _Murmur3Load_32(data, i)), i + 1) :
_Murmur3Rest_32(data, len, hash);
}
constexpr inline uint32_t Murmur3_32(const void *const key, const size_t length,
const uint32_t seed) noexcept {
return _Murmur3Loop_32(reinterpret_cast<const char *const>(key), length,
seed);
}
constexpr inline uint32_t Murmur3_32(const char *const str,
const uint32_t seed) noexcept {
return Murmur3_32(reinterpret_cast<const void *const>(str),
_StringLength(str), seed);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment