hash_combine.hpp 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. // Copyright 2005-2014 Daniel James.
  2. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  3. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  4. //
  5. // Based on Peter Dimov's proposal
  6. // http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf
  7. // issue 6.18.
  8. //
  9. // This also contains public domain code from MurmurHash. From the
  10. // MurmurHash header:
  11. //
  12. // MurmurHash3 was written by Austin Appleby, and is placed in the public
  13. // domain. The author hereby disclaims copyright to this source code.
  14. //
  15. // Copyright 2021 Ion Gaztanaga
  16. // Refactored the original bho/container_hash/hash.hpp to avoid
  17. // any heavy std header dependencies to just combine two hash
  18. // values represented in a std::size_t type.
  19. #ifndef BHO_INTRUSIVE_DETAIL_HASH_COMBINE_HPP
  20. #define BHO_INTRUSIVE_DETAIL_HASH_COMBINE_HPP
  21. #ifndef BHO_CONFIG_HPP
  22. # include <asio2/bho/config.hpp>
  23. #endif
  24. #if defined(BHO_HAS_PRAGMA_ONCE)
  25. # pragma once
  26. #endif
  27. #include <asio2/bho/cstdint.hpp>
  28. #if defined(_MSC_VER)
  29. # include <stdlib.h>
  30. # define BHO_INTRUSIVE_HASH_ROTL32(x, r) _rotl(x,r)
  31. #else
  32. # define BHO_INTRUSIVE_HASH_ROTL32(x, r) (x << r) | (x >> (32 - r))
  33. #endif
  34. namespace bho {
  35. namespace intrusive {
  36. namespace detail {
  37. template <typename SizeT>
  38. inline void hash_combine_size_t(SizeT& seed, SizeT value)
  39. {
  40. seed ^= value + 0x9e3779b9 + (seed<<6) + (seed>>2);
  41. }
  42. inline void hash_combine_size_t(bho::uint32_t& h1, bho::uint32_t k1)
  43. {
  44. const uint32_t c1 = 0xcc9e2d51;
  45. const uint32_t c2 = 0x1b873593;
  46. k1 *= c1;
  47. k1 = BHO_INTRUSIVE_HASH_ROTL32(k1,15);
  48. k1 *= c2;
  49. h1 ^= k1;
  50. h1 = BHO_INTRUSIVE_HASH_ROTL32(h1,13);
  51. h1 = h1*5+0xe6546b64;
  52. }
  53. // Don't define 64-bit hash combine on platforms without 64 bit integers,
  54. // and also not for 32-bit gcc as it warns about the 64-bit constant.
  55. #if !defined(BHO_NO_INT64_T) && \
  56. !(defined(__GNUC__) && ULONG_MAX == 0xffffffff)
  57. inline void hash_combine_size_t(bho::uint64_t& h, bho::uint64_t k)
  58. {
  59. const bho::uint64_t m = UINT64_C(0xc6a4a7935bd1e995);
  60. const int r = 47;
  61. k *= m;
  62. k ^= k >> r;
  63. k *= m;
  64. h ^= k;
  65. h *= m;
  66. // Completely arbitrary number, to prevent 0's
  67. // from hashing to 0.
  68. h += 0xe6546b64;
  69. }
  70. #endif // BHO_NO_INT64_T
  71. } //namespace detail {
  72. } //namespace intrusive {
  73. } //namespace bho {
  74. #endif //BHO_INTRUSIVE_DETAIL_HASH_COMBINE_HPP