Path: blob/master/thirdparty/jolt_physics/Jolt/Core/HashCombine.h
9906 views
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)1// SPDX-FileCopyrightText: 2021 Jorrit Rouwe2// SPDX-License-Identifier: MIT34#pragma once56JPH_NAMESPACE_BEGIN78/// Implements the FNV-1a hash algorithm9/// @see https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function10/// @param inData Data block of bytes11/// @param inSize Number of bytes12/// @param inSeed Seed of the hash (can be used to pass in the hash of a previous operation, otherwise leave default)13/// @return Hash14inline uint64 HashBytes(const void *inData, uint inSize, uint64 inSeed = 0xcbf29ce484222325UL)15{16uint64 hash = inSeed;17for (const uint8 *data = reinterpret_cast<const uint8 *>(inData); data < reinterpret_cast<const uint8 *>(inData) + inSize; ++data)18{19hash ^= uint64(*data);20hash *= 0x100000001b3UL;21}22return hash;23}2425/// Calculate the FNV-1a hash of inString.26/// @see https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function27constexpr uint64 HashString(const char *inString, uint64 inSeed = 0xcbf29ce484222325UL)28{29uint64 hash = inSeed;30for (const char *c = inString; *c != 0; ++c)31{32hash ^= uint64(*c);33hash *= 0x100000001b3UL;34}35return hash;36}3738/// A 64 bit hash function by Thomas Wang, Jan 199739/// See: http://web.archive.org/web/20071223173210/http://www.concentric.net/~Ttwang/tech/inthash.htm40/// @param inValue Value to hash41/// @return Hash42inline uint64 Hash64(uint64 inValue)43{44uint64 hash = inValue;45hash = (~hash) + (hash << 21); // hash = (hash << 21) - hash - 1;46hash = hash ^ (hash >> 24);47hash = (hash + (hash << 3)) + (hash << 8); // hash * 26548hash = hash ^ (hash >> 14);49hash = (hash + (hash << 2)) + (hash << 4); // hash * 2150hash = hash ^ (hash >> 28);51hash = hash + (hash << 31);52return hash;53}5455/// Fallback hash function that calls T::GetHash()56template <class T>57struct Hash58{59uint64 operator () (const T &inValue) const60{61return inValue.GetHash();62}63};6465/// A hash function for floats66template <>67struct Hash<float>68{69uint64 operator () (float inValue) const70{71float value = inValue == 0.0f? 0.0f : inValue; // Convert -0.0f to 0.0f72return HashBytes(&value, sizeof(value));73}74};7576/// A hash function for doubles77template <>78struct Hash<double>79{80uint64 operator () (double inValue) const81{82double value = inValue == 0.0? 0.0 : inValue; // Convert -0.0 to 0.083return HashBytes(&value, sizeof(value));84}85};8687/// A hash function for character pointers88template <>89struct Hash<const char *>90{91uint64 operator () (const char *inValue) const92{93return HashString(inValue);94}95};9697/// A hash function for std::string_view98template <>99struct Hash<std::string_view>100{101uint64 operator () (const std::string_view &inValue) const102{103return HashBytes(inValue.data(), uint(inValue.size()));104}105};106107/// A hash function for String108template <>109struct Hash<String>110{111uint64 operator () (const String &inValue) const112{113return HashBytes(inValue.data(), uint(inValue.size()));114}115};116117/// A fallback function for generic pointers118template <class T>119struct Hash<T *>120{121uint64 operator () (T *inValue) const122{123return HashBytes(&inValue, sizeof(inValue));124}125};126127/// Helper macro to define a hash function for trivial types128#define JPH_DEFINE_TRIVIAL_HASH(type) \129template <> \130struct Hash<type> \131{ \132uint64 operator () (const type &inValue) const \133{ \134return HashBytes(&inValue, sizeof(inValue)); \135} \136};137138/// Commonly used types139JPH_DEFINE_TRIVIAL_HASH(char)140JPH_DEFINE_TRIVIAL_HASH(int)141JPH_DEFINE_TRIVIAL_HASH(uint32)142JPH_DEFINE_TRIVIAL_HASH(uint64)143144/// Helper function that hashes a single value into ioSeed145/// Based on https://github.com/jonmaiga/mx3 by Jon Maiga146template <typename T>147inline void HashCombine(uint64 &ioSeed, const T &inValue)148{149constexpr uint64 c = 0xbea225f9eb34556dUL;150151uint64 h = ioSeed;152uint64 x = Hash<T> { } (inValue);153154// See: https://github.com/jonmaiga/mx3/blob/master/mx3.h155// mix_stream(h, x)156x *= c;157x ^= x >> 39;158h += x * c;159h *= c;160161// mix(h)162h ^= h >> 32;163h *= c;164h ^= h >> 29;165h *= c;166h ^= h >> 32;167h *= c;168h ^= h >> 29;169170ioSeed = h;171}172173/// Hash combiner to use a custom struct in an unordered map or set174///175/// Usage:176///177/// struct SomeHashKey178/// {179/// std::string key1;180/// std::string key2;181/// bool key3;182/// };183///184/// JPH_MAKE_HASHABLE(SomeHashKey, t.key1, t.key2, t.key3)185template <typename FirstValue, typename... Values>186inline uint64 HashCombineArgs(const FirstValue &inFirstValue, Values... inValues)187{188// Prime the seed by hashing the first value189uint64 seed = Hash<FirstValue> { } (inFirstValue);190191// Hash all remaining values together using a fold expression192(HashCombine(seed, inValues), ...);193194return seed;195}196197#define JPH_MAKE_HASH_STRUCT(type, name, ...) \198struct [[nodiscard]] name \199{ \200::JPH::uint64 operator()(const type &t) const \201{ \202return ::JPH::HashCombineArgs(__VA_ARGS__); \203} \204};205206#define JPH_MAKE_STD_HASH(type) \207JPH_SUPPRESS_WARNING_PUSH \208JPH_SUPPRESS_WARNINGS \209namespace std \210{ \211template<> \212struct [[nodiscard]] hash<type> \213{ \214size_t operator()(const type &t) const \215{ \216return size_t(::JPH::Hash<type>{ }(t)); \217} \218}; \219} \220JPH_SUPPRESS_WARNING_POP221222#define JPH_MAKE_HASHABLE(type, ...) \223JPH_SUPPRESS_WARNING_PUSH \224JPH_SUPPRESS_WARNINGS \225namespace JPH \226{ \227template<> \228JPH_MAKE_HASH_STRUCT(type, Hash<type>, __VA_ARGS__) \229} \230JPH_SUPPRESS_WARNING_POP \231JPH_MAKE_STD_HASH(type)232233JPH_NAMESPACE_END234235236