2
0

HashCombine.h 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
  2. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  3. // SPDX-License-Identifier: MIT
  4. #pragma once
  5. JPH_NAMESPACE_BEGIN
  6. /// Implements the FNV-1a hash algorithm
  7. /// @see https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
  8. /// @param inData Data block of bytes
  9. /// @param inSize Number of bytes
  10. /// @param inSeed Seed of the hash (can be used to pass in the hash of a previous operation, otherwise leave default)
  11. /// @return Hash
  12. inline uint64 HashBytes(const void *inData, uint inSize, uint64 inSeed = 0xcbf29ce484222325UL)
  13. {
  14. uint64 hash = inSeed;
  15. for (const uint8 *data = reinterpret_cast<const uint8 *>(inData); data < reinterpret_cast<const uint8 *>(inData) + inSize; ++data)
  16. {
  17. hash = hash ^ uint64(*data);
  18. hash = hash * 0x100000001b3UL;
  19. }
  20. return hash;
  21. }
  22. /// A 64 bit hash function by Thomas Wang, Jan 1997
  23. /// See: http://web.archive.org/web/20071223173210/http://www.concentric.net/~Ttwang/tech/inthash.htm
  24. /// @param inValue Value to hash
  25. /// @return Hash
  26. inline uint64 Hash64(uint64 inValue)
  27. {
  28. uint64 hash = inValue;
  29. hash = (~hash) + (hash << 21); // hash = (hash << 21) - hash - 1;
  30. hash = hash ^ (hash >> 24);
  31. hash = (hash + (hash << 3)) + (hash << 8); // hash * 265
  32. hash = hash ^ (hash >> 14);
  33. hash = (hash + (hash << 2)) + (hash << 4); // hash * 21
  34. hash = hash ^ (hash >> 28);
  35. hash = hash + (hash << 31);
  36. return hash;
  37. }
  38. /// @brief Helper function that hashes a single value into ioSeed
  39. /// Taken from: https://stackoverflow.com/questions/2590677/how-do-i-combine-hash-values-in-c0x
  40. template <typename T>
  41. inline void HashCombineHelper(size_t &ioSeed, const T &inValue)
  42. {
  43. std::hash<T> hasher;
  44. ioSeed ^= hasher(inValue) + 0x9e3779b9 + (ioSeed << 6) + (ioSeed >> 2);
  45. }
  46. /// Hash combiner to use a custom struct in an unordered map or set
  47. ///
  48. /// Usage:
  49. ///
  50. /// struct SomeHashKey
  51. /// {
  52. /// std::string key1;
  53. /// std::string key2;
  54. /// bool key3;
  55. /// };
  56. ///
  57. /// JPH_MAKE_HASHABLE(SomeHashKey, t.key1, t.key2, t.key3)
  58. template <typename... Values>
  59. inline void HashCombine(std::size_t &ioSeed, Values... inValues)
  60. {
  61. // Hash all values together using a fold expression
  62. (HashCombineHelper(ioSeed, inValues), ...);
  63. }
  64. JPH_NAMESPACE_END
  65. JPH_SUPPRESS_WARNING_PUSH
  66. JPH_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic")
  67. #define JPH_MAKE_HASH_STRUCT(type, name, ...) \
  68. struct [[nodiscard]] name \
  69. { \
  70. std::size_t operator()(const type &t) const \
  71. { \
  72. std::size_t ret = 0; \
  73. ::JPH::HashCombine(ret, __VA_ARGS__); \
  74. return ret; \
  75. } \
  76. };
  77. #define JPH_MAKE_HASHABLE(type, ...) \
  78. JPH_SUPPRESS_WARNING_PUSH \
  79. JPH_SUPPRESS_WARNINGS \
  80. namespace std \
  81. { \
  82. template<> \
  83. JPH_MAKE_HASH_STRUCT(type, hash<type>, __VA_ARGS__) \
  84. } \
  85. JPH_SUPPRESS_WARNING_POP
  86. JPH_SUPPRESS_WARNING_POP