diff --git a/CMakeLists.txt b/CMakeLists.txt index 3428d64..1b31dba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.8) +cmake_minimum_required(VERSION 3.4) list (APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") @@ -24,7 +24,7 @@ target_sources(${PROJECT_NAME} INTERFACE ${PHMAP_HEADERS}) target_include_directories( ${PROJECT_NAME} INTERFACE - $ + $ $) install( @@ -44,9 +44,12 @@ option(PHMAP_BUILD_EXAMPLES "Whether or not to build the examples" OFF) if (PHMAP_BUILD_TESTS) if(MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj") + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") endif() include(cmake/DownloadGTest.cmake) + include_directories(${PROJECT_SOURCE_DIR}) check_target(gtest) check_target(gtest_main) diff --git a/parallel_hashmap/phmap.h b/parallel_hashmap/phmap.h index e542255..1c09a7b 100644 --- a/parallel_hashmap/phmap.h +++ b/parallel_hashmap/phmap.h @@ -577,6 +577,139 @@ void SetHashtablezSampleParameter(int32_t rate) {} void SetHashtablezMaxSamples(int32_t max) {} +namespace memory_internal { + +// Constructs T into uninitialized storage pointed by `ptr` using the args +// specified in the tuple. +// ---------------------------------------------------------------------------- +template +void ConstructFromTupleImpl(Alloc* alloc, T* ptr, Tuple&& t, + phmap::index_sequence) { + phmap::allocator_traits::construct( + *alloc, ptr, std::get(std::forward(t))...); +} + +template +struct WithConstructedImplF { + template + decltype(std::declval()(std::declval())) operator()( + Args&&... args) const { + return std::forward(f)(T(std::forward(args)...)); + } + F&& f; +}; + +template +decltype(std::declval()(std::declval())) WithConstructedImpl( + Tuple&& t, phmap::index_sequence, F&& f) { + return WithConstructedImplF{std::forward(f)}( + std::get(std::forward(t))...); +} + +template +auto TupleRefImpl(T&& t, phmap::index_sequence) + -> decltype(std::forward_as_tuple(std::get(std::forward(t))...)) { + return std::forward_as_tuple(std::get(std::forward(t))...); +} + +// Returns a tuple of references to the elements of the input tuple. T must be a +// tuple. +// ---------------------------------------------------------------------------- +template +auto TupleRef(T&& t) -> decltype( + TupleRefImpl(std::forward(t), + phmap::make_index_sequence< + std::tuple_size::type>::value>())) { + return TupleRefImpl( + std::forward(t), + phmap::make_index_sequence< + std::tuple_size::type>::value>()); +} + +template +decltype(std::declval()(std::declval(), std::piecewise_construct, + std::declval>(), std::declval())) +DecomposePairImpl(F&& f, std::pair, V> p) { + const auto& key = std::get<0>(p.first); + return std::forward(f)(key, std::piecewise_construct, std::move(p.first), + std::move(p.second)); +} + +} // namespace memory_internal + +// Helper functions for asan and msan. +// ---------------------------------------------------------------------------- +inline void SanitizerPoisonMemoryRegion(const void* m, size_t s) { +#ifdef ADDRESS_SANITIZER + ASAN_POISON_MEMORY_REGION(m, s); +#endif +#ifdef MEMORY_SANITIZER + __msan_poison(m, s); +#endif + (void)m; + (void)s; +} + +inline void SanitizerUnpoisonMemoryRegion(const void* m, size_t s) { +#ifdef ADDRESS_SANITIZER + ASAN_UNPOISON_MEMORY_REGION(m, s); +#endif +#ifdef MEMORY_SANITIZER + __msan_unpoison(m, s); +#endif + (void)m; + (void)s; +} + +template +inline void SanitizerPoisonObject(const T* object) { + SanitizerPoisonMemoryRegion(object, sizeof(T)); +} + +template +inline void SanitizerUnpoisonObject(const T* object) { + SanitizerUnpoisonMemoryRegion(object, sizeof(T)); +} + +// ---------------------------------------------------------------------------- +// Allocates at least n bytes aligned to the specified alignment. +// Alignment must be a power of 2. It must be positive. +// +// Note that many allocators don't honor alignment requirements above certain +// threshold (usually either alignof(std::max_align_t) or alignof(void*)). +// Allocate() doesn't apply alignment corrections. If the underlying allocator +// returns insufficiently alignment pointer, that's what you are going to get. +// ---------------------------------------------------------------------------- +template +void* Allocate(Alloc* alloc, size_t n) { + static_assert(Alignment > 0, ""); + assert(n && "n must be positive"); + struct alignas(Alignment) M {}; + using A = typename phmap::allocator_traits::template rebind_alloc; + using AT = typename phmap::allocator_traits::template rebind_traits; + A mem_alloc(*alloc); + void* p = AT::allocate(mem_alloc, (n + sizeof(M) - 1) / sizeof(M)); + assert(reinterpret_cast(p) % Alignment == 0 && + "allocator does not respect alignment"); + return p; +} + +// ---------------------------------------------------------------------------- +// The pointer must have been previously obtained by calling +// Allocate(alloc, n). +// ---------------------------------------------------------------------------- +template +void Deallocate(Alloc* alloc, void* p, size_t n) { + static_assert(Alignment > 0, ""); + assert(n && "n must be positive"); + struct alignas(Alignment) M {}; + using A = typename phmap::allocator_traits::template rebind_alloc; + using AT = typename phmap::allocator_traits::template rebind_traits; + A mem_alloc(*alloc); + AT::deallocate(mem_alloc, static_cast(p), + (n + sizeof(M) - 1) / sizeof(M)); +} + // ---------------------------------------------------------------------------- // R A W _ H A S H _ S E T // ---------------------------------------------------------------------------- @@ -3330,104 +3463,6 @@ private: } }; -// ---------------------------------------------------------------------------- -// Allocates at least n bytes aligned to the specified alignment. -// Alignment must be a power of 2. It must be positive. -// -// Note that many allocators don't honor alignment requirements above certain -// threshold (usually either alignof(std::max_align_t) or alignof(void*)). -// Allocate() doesn't apply alignment corrections. If the underlying allocator -// returns insufficiently alignment pointer, that's what you are going to get. -// ---------------------------------------------------------------------------- -template -void* Allocate(Alloc* alloc, size_t n) { - static_assert(Alignment > 0, ""); - assert(n && "n must be positive"); - struct alignas(Alignment) M {}; - using A = typename phmap::allocator_traits::template rebind_alloc; - using AT = typename phmap::allocator_traits::template rebind_traits; - A mem_alloc(*alloc); - void* p = AT::allocate(mem_alloc, (n + sizeof(M) - 1) / sizeof(M)); - assert(reinterpret_cast(p) % Alignment == 0 && - "allocator does not respect alignment"); - return p; -} - -// ---------------------------------------------------------------------------- -// The pointer must have been previously obtained by calling -// Allocate(alloc, n). -// ---------------------------------------------------------------------------- -template -void Deallocate(Alloc* alloc, void* p, size_t n) { - static_assert(Alignment > 0, ""); - assert(n && "n must be positive"); - struct alignas(Alignment) M {}; - using A = typename phmap::allocator_traits::template rebind_alloc; - using AT = typename phmap::allocator_traits::template rebind_traits; - A mem_alloc(*alloc); - AT::deallocate(mem_alloc, static_cast(p), - (n + sizeof(M) - 1) / sizeof(M)); -} - -namespace memory_internal { - -// Constructs T into uninitialized storage pointed by `ptr` using the args -// specified in the tuple. -// ---------------------------------------------------------------------------- -template -void ConstructFromTupleImpl(Alloc* alloc, T* ptr, Tuple&& t, - phmap::index_sequence) { - phmap::allocator_traits::construct( - *alloc, ptr, std::get(std::forward(t))...); -} - -template -struct WithConstructedImplF { - template - decltype(std::declval()(std::declval())) operator()( - Args&&... args) const { - return std::forward(f)(T(std::forward(args)...)); - } - F&& f; -}; - -template -decltype(std::declval()(std::declval())) WithConstructedImpl( - Tuple&& t, phmap::index_sequence, F&& f) { - return WithConstructedImplF{std::forward(f)}( - std::get(std::forward(t))...); -} - -template -auto TupleRefImpl(T&& t, phmap::index_sequence) - -> decltype(std::forward_as_tuple(std::get(std::forward(t))...)) { - return std::forward_as_tuple(std::get(std::forward(t))...); -} - -// Returns a tuple of references to the elements of the input tuple. T must be a -// tuple. -// ---------------------------------------------------------------------------- -template -auto TupleRef(T&& t) -> decltype( - TupleRefImpl(std::forward(t), - phmap::make_index_sequence< - std::tuple_size::type>::value>())) { - return TupleRefImpl( - std::forward(t), - phmap::make_index_sequence< - std::tuple_size::type>::value>()); -} - -template -decltype(std::declval()(std::declval(), std::piecewise_construct, - std::declval>(), std::declval())) -DecomposePairImpl(F&& f, std::pair, V> p) { - const auto& key = std::get<0>(p.first); - return std::forward(f)(key, std::piecewise_construct, std::move(p.first), - std::move(p.second)); -} - -} // namespace memory_internal // Constructs T into uninitialized storage pointed by `ptr` using the args // specified in the tuple. @@ -3512,39 +3547,6 @@ DecomposeValue(F&& f, Arg&& arg) { return std::forward(f)(key, std::forward(arg)); } -// Helper functions for asan and msan. -// ---------------------------------------------------------------------------- -inline void SanitizerPoisonMemoryRegion(const void* m, size_t s) { -#ifdef ADDRESS_SANITIZER - ASAN_POISON_MEMORY_REGION(m, s); -#endif -#ifdef MEMORY_SANITIZER - __msan_poison(m, s); -#endif - (void)m; - (void)s; -} - -inline void SanitizerUnpoisonMemoryRegion(const void* m, size_t s) { -#ifdef ADDRESS_SANITIZER - ASAN_UNPOISON_MEMORY_REGION(m, s); -#endif -#ifdef MEMORY_SANITIZER - __msan_unpoison(m, s); -#endif - (void)m; - (void)s; -} - -template -inline void SanitizerPoisonObject(const T* object) { - SanitizerPoisonMemoryRegion(object, sizeof(T)); -} - -template -inline void SanitizerUnpoisonObject(const T* object) { - SanitizerUnpoisonMemoryRegion(object, sizeof(T)); -} namespace memory_internal { diff --git a/parallel_hashmap/phmap_base.h b/parallel_hashmap/phmap_base.h index a3ecb1a..7d1526c 100644 --- a/parallel_hashmap/phmap_base.h +++ b/parallel_hashmap/phmap_base.h @@ -750,6 +750,91 @@ using identity_t = typename identity::type; #endif // __cpp_inline_variables +// ----------- throw_delegate + +namespace phmap { +namespace base_internal { + +namespace { +template +[[noreturn]] void Throw(const T& error) { +#ifdef PHMAP_HAVE_EXCEPTIONS + throw error; +#else + PHMAP_RAW_LOG(FATAL, "%s", error.what()); + std::abort(); +#endif +} +} // namespace + +void ThrowStdLogicError(const std::string& what_arg) { + Throw(std::logic_error(what_arg)); +} +void ThrowStdLogicError(const char* what_arg) { + Throw(std::logic_error(what_arg)); +} +void ThrowStdInvalidArgument(const std::string& what_arg) { + Throw(std::invalid_argument(what_arg)); +} +void ThrowStdInvalidArgument(const char* what_arg) { + Throw(std::invalid_argument(what_arg)); +} + +void ThrowStdDomainError(const std::string& what_arg) { + Throw(std::domain_error(what_arg)); +} +void ThrowStdDomainError(const char* what_arg) { + Throw(std::domain_error(what_arg)); +} + +void ThrowStdLengthError(const std::string& what_arg) { + Throw(std::length_error(what_arg)); +} +void ThrowStdLengthError(const char* what_arg) { + Throw(std::length_error(what_arg)); +} + +void ThrowStdOutOfRange(const std::string& what_arg) { + Throw(std::out_of_range(what_arg)); +} +void ThrowStdOutOfRange(const char* what_arg) { + Throw(std::out_of_range(what_arg)); +} + +void ThrowStdRuntimeError(const std::string& what_arg) { + Throw(std::runtime_error(what_arg)); +} +void ThrowStdRuntimeError(const char* what_arg) { + Throw(std::runtime_error(what_arg)); +} + +void ThrowStdRangeError(const std::string& what_arg) { + Throw(std::range_error(what_arg)); +} +void ThrowStdRangeError(const char* what_arg) { + Throw(std::range_error(what_arg)); +} + +void ThrowStdOverflowError(const std::string& what_arg) { + Throw(std::overflow_error(what_arg)); +} +void ThrowStdOverflowError(const char* what_arg) { + Throw(std::overflow_error(what_arg)); +} + +void ThrowStdUnderflowError(const std::string& what_arg) { + Throw(std::underflow_error(what_arg)); +} +void ThrowStdUnderflowError(const char* what_arg) { + Throw(std::underflow_error(what_arg)); +} + +void ThrowStdBadFunctionCall() { Throw(std::bad_function_call()); } + +void ThrowStdBadAlloc() { Throw(std::bad_alloc()); } + +} // namespace base_internal +} // namespace phmap // ----------- invoke.h @@ -2965,7 +3050,7 @@ using EnableIfMutable = template bool EqualImpl(Span a, Span b) { static_assert(std::is_const::value, ""); - return phmap::equal(a.begin(), a.end(), b.begin(), b.end()); + return std::equal(a.begin(), a.end(), b.begin(), b.end()); } template @@ -3735,25 +3820,6 @@ constexpr size_t Max(size_t a, size_t b, Ts... rest) { return adl_barrier::Max(b < a ? a : b, rest...); } -template -std::string TypeName() { - std::string out; - int status = 0; - char* demangled = nullptr; -#ifdef PHMAP_INTERNAL_HAS_CXA_DEMANGLE - demangled = abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, &status); -#endif - if (status == 0 && demangled != nullptr) { // Demangling succeeded. - phmap::StrAppend(&out, "<", demangled, ">"); - free(demangled); - } else { -#if defined(__GXX_RTTI) || defined(_CPPRTTI) - phmap::StrAppend(&out, "<", typeid(T).name(), ">"); -#endif - } - return out; -} - } // namespace adl_barrier template @@ -4075,42 +4141,6 @@ public: #endif } - // Human-readable description of the memory layout. Useful for debugging. - // Slow. - // - // // char[5], 3 bytes of padding, int[3], 4 bytes of padding, followed - // // by an unknown number of doubles. - // auto x = Layout::Partial(5, 3); - // assert(x.DebugString() == - // "@0(1)[5]; @8(4)[3]; @24(8)"); - // - // Each field is in the following format: @offset(sizeof)[size] ( - // may be missing depending on the target platform). For example, - // @8(4)[3] means that at offset 8 we have an array of ints, where each - // int is 4 bytes, and we have 3 of those ints. The size of the last field may - // be missing (as in the example above). Only fields with known offsets are - // described. Type names may differ across platforms: one compiler might - // produce "unsigned*" where another produces "unsigned int *". - // --------------------------------------------------------------------------- - std::string DebugString() const { - const auto offsets = Offsets(); - const size_t sizes[] = {SizeOf>()...}; - const std::string types[] = { - adl_barrier::TypeName>()...}; - std::string res = phmap::StrCat("@0", types[0], "(", sizes[0], ")"); - for (size_t i = 0; i != NumOffsets - 1; ++i) { - phmap::StrAppend(&res, "[", size_[i], "]; @", offsets[i + 1], types[i + 1], - "(", sizes[i + 1], ")"); - } - // NumSizes is a constant that may be zero. Some compilers cannot see that - // inside the if statement "size_[NumSizes - 1]" must be valid. - int last = static_cast(NumSizes) - 1; - if (NumTypes == NumSizes && last >= 0) { - phmap::StrAppend(&res, "[", size_[last], "]"); - } - return res; - } - private: // Arguments of `Layout::Partial()` or `Layout::Layout()`. size_t size_[NumSizes > 0 ? NumSizes : 1]; diff --git a/parallel_hashmap/phmap_config.h b/parallel_hashmap/phmap_config.h index 8312fdd..3208260 100644 --- a/parallel_hashmap/phmap_config.h +++ b/parallel_hashmap/phmap_config.h @@ -637,4 +637,184 @@ #include #endif + +// ---------------------------------------------------------------------- +// base/macros.h +// ---------------------------------------------------------------------- + +// PHMAP_ARRAYSIZE() +// +// Returns the number of elements in an array as a compile-time constant, which +// can be used in defining new arrays. If you use this macro on a pointer by +// mistake, you will get a compile-time error. +#define PHMAP_ARRAYSIZE(array) \ + (sizeof(::absl::macros_internal::ArraySizeHelper(array))) + +namespace absl { +namespace macros_internal { +// Note: this internal template function declaration is used by PHMAP_ARRAYSIZE. +// The function doesn't need a definition, as we only use its type. +template +auto ArraySizeHelper(const T (&array)[N]) -> char (&)[N]; +} // namespace macros_internal +} // namespace absl + +// kLinkerInitialized +// +// An enum used only as a constructor argument to indicate that a variable has +// static storage duration, and that the constructor should do nothing to its +// state. Use of this macro indicates to the reader that it is legal to +// declare a static instance of the class, provided the constructor is given +// the absl::base_internal::kLinkerInitialized argument. +// +// Normally, it is unsafe to declare a static variable that has a constructor or +// a destructor because invocation order is undefined. However, if the type can +// be zero-initialized (which the loader does for static variables) into a valid +// state and the type's destructor does not affect storage, then a constructor +// for static initialization can be declared. +// +// Example: +// // Declaration +// explicit MyClass(absl::base_internal:LinkerInitialized x) {} +// +// // Invocation +// static MyClass my_global(absl::base_internal::kLinkerInitialized); +namespace absl { +namespace base_internal { +enum LinkerInitialized { + kLinkerInitialized = 0, +}; +} // namespace base_internal +} // namespace absl + +// PHMAP_FALLTHROUGH_INTENDED +// +// Annotates implicit fall-through between switch labels, allowing a case to +// indicate intentional fallthrough and turn off warnings about any lack of a +// `break` statement. The PHMAP_FALLTHROUGH_INTENDED macro should be followed by +// a semicolon and can be used in most places where `break` can, provided that +// no statements exist between it and the next switch label. +// +// Example: +// +// switch (x) { +// case 40: +// case 41: +// if (truth_is_out_there) { +// ++x; +// PHMAP_FALLTHROUGH_INTENDED; // Use instead of/along with annotations +// // in comments +// } else { +// return x; +// } +// case 42: +// ... +// +// Notes: when compiled with clang in C++11 mode, the PHMAP_FALLTHROUGH_INTENDED +// macro is expanded to the [[clang::fallthrough]] attribute, which is analysed +// when performing switch labels fall-through diagnostic +// (`-Wimplicit-fallthrough`). See clang documentation on language extensions +// for details: +// http://clang.llvm.org/docs/AttributeReference.html#fallthrough-clang-fallthrough +// +// When used with unsupported compilers, the PHMAP_FALLTHROUGH_INTENDED macro +// has no effect on diagnostics. In any case this macro has no effect on runtime +// behavior and performance of code. +#ifdef PHMAP_FALLTHROUGH_INTENDED + #error "PHMAP_FALLTHROUGH_INTENDED should not be defined." +#endif + +// TODO(zhangxy): Use c++17 standard [[fallthrough]] macro, when supported. +#if defined(__clang__) && defined(__has_warning) + #if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough") + #define PHMAP_FALLTHROUGH_INTENDED [[clang::fallthrough]] + #endif +#elif defined(__GNUC__) && __GNUC__ >= 7 + #define PHMAP_FALLTHROUGH_INTENDED [[gnu::fallthrough]] +#endif + +#ifndef PHMAP_FALLTHROUGH_INTENDED + #define PHMAP_FALLTHROUGH_INTENDED \ + do { } while (0) +#endif + +// PHMAP_DEPRECATED() +// +// Marks a deprecated class, struct, enum, function, method and variable +// declarations. The macro argument is used as a custom diagnostic message (e.g. +// suggestion of a better alternative). +// +// Example: +// +// class PHMAP_DEPRECATED("Use Bar instead") Foo {...}; +// PHMAP_DEPRECATED("Use Baz instead") void Bar() {...} +// +// Every usage of a deprecated entity will trigger a warning when compiled with +// clang's `-Wdeprecated-declarations` option. This option is turned off by +// default, but the warnings will be reported by clang-tidy. +#if defined(__clang__) && __cplusplus >= 201103L + #define PHMAP_DEPRECATED(message) __attribute__((deprecated(message))) +#endif + +#ifndef PHMAP_DEPRECATED + #define PHMAP_DEPRECATED(message) +#endif + +// PHMAP_BAD_CALL_IF() +// +// Used on a function overload to trap bad calls: any call that matches the +// overload will cause a compile-time error. This macro uses a clang-specific +// "enable_if" attribute, as described at +// http://clang.llvm.org/docs/AttributeReference.html#enable-if +// +// Overloads which use this macro should be bracketed by +// `#ifdef PHMAP_BAD_CALL_IF`. +// +// Example: +// +// int isdigit(int c); +// #ifdef PHMAP_BAD_CALL_IF +// int isdigit(int c) +// PHMAP_BAD_CALL_IF(c <= -1 || c > 255, +// "'c' must have the value of an unsigned char or EOF"); +// #endif // PHMAP_BAD_CALL_IF + +#if defined(__clang__) + #if __has_attribute(enable_if) + #define PHMAP_BAD_CALL_IF(expr, msg) \ + __attribute__((enable_if(expr, "Bad call trap"), unavailable(msg))) + #endif +#endif + +// PHMAP_ASSERT() +// +// In C++11, `assert` can't be used portably within constexpr functions. +// PHMAP_ASSERT functions as a runtime assert but works in C++11 constexpr +// functions. Example: +// +// constexpr double Divide(double a, double b) { +// return PHMAP_ASSERT(b != 0), a / b; +// } +// +// This macro is inspired by +// https://akrzemi1.wordpress.com/2017/05/18/asserts-in-constexpr-functions/ +#if defined(NDEBUG) + #define PHMAP_ASSERT(expr) (false ? (void)(expr) : (void)0) +#else + #define PHMAP_ASSERT(expr) \ + (PHMAP_PREDICT_TRUE((expr)) ? (void)0 \ + : [] { assert(false && #expr); }()) // NOLINT +#endif + +#ifdef PHMAP_HAVE_EXCEPTIONS + #define PHMAP_INTERNAL_TRY try + #define PHMAP_INTERNAL_CATCH_ANY catch (...) + #define PHMAP_INTERNAL_RETHROW do { throw; } while (false) +#else // PHMAP_HAVE_EXCEPTIONS + #define PHMAP_INTERNAL_TRY if (true) + #define PHMAP_INTERNAL_CATCH_ANY else if (false) + #define PHMAP_INTERNAL_RETHROW do {} while (false) +#endif // PHMAP_HAVE_EXCEPTIONS + + #endif // phmap_config_h_guard_ diff --git a/parallel_hashmap/phmap_utils.h b/parallel_hashmap/phmap_utils.h index 7d45886..53527e6 100644 --- a/parallel_hashmap/phmap_utils.h +++ b/parallel_hashmap/phmap_utils.h @@ -56,7 +56,7 @@ struct Hash template struct Hash { - static size_t spp_log2 (size_t val) noexcept + static size_t phmap_log2 (size_t val) noexcept { size_t res = 0; while (val > 1) @@ -69,7 +69,7 @@ struct Hash inline size_t operator()(const T *__v) const noexcept { - static const size_t shift = 3; // spp_log2(1 + sizeof(T)); // T might be incomplete! + static const size_t shift = 3; // phmap_log2(1 + sizeof(T)); // T might be incomplete! const uintptr_t i = (const uintptr_t)__v; return static_cast(i >> shift); } @@ -79,7 +79,7 @@ struct Hash // fast and efficient for power of two table sizes where we always // consider the last bits. // --------------------------------------------------------------- -inline size_t spp_mix_32(uint32_t a) +inline size_t phmap_mix_32(uint32_t a) { a = a ^ (a >> 4); a = (a ^ 0xdeadbeef) + (a << 5); @@ -90,7 +90,7 @@ inline size_t spp_mix_32(uint32_t a) // More thorough scrambling as described in // https://gist.github.com/badboy/6267743 // ---------------------------------------- -inline size_t spp_mix_64(uint64_t a) +inline size_t phmap_mix_64(uint64_t a) { a = (~a) + (a << 21); // a = (a << 21) - a - 1; a = a ^ (a >> 24); @@ -103,108 +103,108 @@ inline size_t spp_mix_64(uint64_t a) } template -struct spp_unary_function +struct phmap_unary_function { typedef ArgumentType argument_type; typedef ResultType result_type; }; template <> -struct Hash : public spp_unary_function +struct Hash : public phmap_unary_function { inline size_t operator()(bool __v) const noexcept { return static_cast(__v); } }; template <> -struct Hash : public spp_unary_function +struct Hash : public phmap_unary_function { inline size_t operator()(char __v) const noexcept { return static_cast(__v); } }; template <> -struct Hash : public spp_unary_function +struct Hash : public phmap_unary_function { inline size_t operator()(signed char __v) const noexcept { return static_cast(__v); } }; template <> -struct Hash : public spp_unary_function +struct Hash : public phmap_unary_function { inline size_t operator()(unsigned char __v) const noexcept { return static_cast(__v); } }; template <> -struct Hash : public spp_unary_function +struct Hash : public phmap_unary_function { inline size_t operator()(wchar_t __v) const noexcept { return static_cast(__v); } }; template <> -struct Hash : public spp_unary_function +struct Hash : public phmap_unary_function { inline size_t operator()(int16_t __v) const noexcept - { return spp_mix_32(static_cast(__v)); } + { return phmap_mix_32(static_cast(__v)); } }; template <> -struct Hash : public spp_unary_function +struct Hash : public phmap_unary_function { inline size_t operator()(uint16_t __v) const noexcept - { return spp_mix_32(static_cast(__v)); } + { return phmap_mix_32(static_cast(__v)); } }; template <> -struct Hash : public spp_unary_function +struct Hash : public phmap_unary_function { inline size_t operator()(int32_t __v) const noexcept - { return spp_mix_32(static_cast(__v)); } + { return phmap_mix_32(static_cast(__v)); } }; template <> -struct Hash : public spp_unary_function +struct Hash : public phmap_unary_function { inline size_t operator()(uint32_t __v) const noexcept - { return spp_mix_32(static_cast(__v)); } + { return phmap_mix_32(static_cast(__v)); } }; template <> -struct Hash : public spp_unary_function +struct Hash : public phmap_unary_function { inline size_t operator()(int64_t __v) const noexcept - { return spp_mix_64(static_cast(__v)); } + { return phmap_mix_64(static_cast(__v)); } }; template <> -struct Hash : public spp_unary_function +struct Hash : public phmap_unary_function { inline size_t operator()(uint64_t __v) const noexcept - { return spp_mix_64(static_cast(__v)); } + { return phmap_mix_64(static_cast(__v)); } }; template <> -struct Hash : public spp_unary_function +struct Hash : public phmap_unary_function { inline size_t operator()(float __v) const noexcept { // -0.0 and 0.0 should return same hash uint32_t *as_int = reinterpret_cast(&__v); - return (__v == 0) ? static_cast(0) : spp_mix_32(*as_int); + return (__v == 0) ? static_cast(0) : phmap_mix_32(*as_int); } }; template <> -struct Hash : public spp_unary_function +struct Hash : public phmap_unary_function { inline size_t operator()(double __v) const noexcept { // -0.0 and 0.0 should return same hash uint64_t *as_int = reinterpret_cast(&__v); - return (__v == 0) ? static_cast(0) : spp_mix_64(*as_int); + return (__v == 0) ? static_cast(0) : phmap_mix_64(*as_int); } }; @@ -232,7 +232,7 @@ template struct Combiner template inline void hash_combine(std::size_t& seed, T const& v) { - spp_::Hash hasher; + phmap::Hash hasher; Combiner combiner; combiner(seed, hasher(v));