HashCombine.h 2.3 KB

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