-
-
Save malkia/5811033 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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