hash_combine.hpp 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  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 boost/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 BOOST_INTRUSIVE_DETAIL_HASH_COMBINE_HPP
  20. #define BOOST_INTRUSIVE_DETAIL_HASH_COMBINE_HPP
  21. #ifndef BOOST_CONFIG_HPP
  22. # include <boost/config.hpp>
  23. #endif
  24. #if defined(BOOST_HAS_PRAGMA_ONCE)
  25. # pragma once
  26. #endif
  27. #include <boost/cstdint.hpp>
  28. #if defined(_MSC_VER)
  29. # include <stdlib.h>
  30. # define BOOST_INTRUSIVE_HASH_ROTL32(x, r) _rotl(x,r)
  31. #else
  32. # define BOOST_INTRUSIVE_HASH_ROTL32(x, r) (x << r) | (x >> (32 - r))
  33. #endif
  34. namespace boost {
  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(boost::uint32_t& h1,
  43. boost::uint32_t k1)
  44. {
  45. const uint32_t c1 = 0xcc9e2d51;
  46. const uint32_t c2 = 0x1b873593;
  47. k1 *= c1;
  48. k1 = BOOST_INTRUSIVE_HASH_ROTL32(k1,15);
  49. k1 *= c2;
  50. h1 ^= k1;
  51. h1 = BOOST_INTRUSIVE_HASH_ROTL32(h1,13);
  52. h1 = h1*5+0xe6546b64;
  53. }
  54. // Don't define 64-bit hash combine on platforms without 64 bit integers,
  55. // and also not for 32-bit gcc as it warns about the 64-bit constant.
  56. #if !defined(BOOST_NO_INT64_T) && \
  57. !(defined(__GNUC__) && ULONG_MAX == 0xffffffff)
  58. inline void hash_combine_size_t(boost::uint64_t& h,
  59. boost::uint64_t k)
  60. {
  61. const boost::uint64_t m = UINT64_C(0xc6a4a7935bd1e995);
  62. const int r = 47;
  63. k *= m;
  64. k ^= k >> r;
  65. k *= m;
  66. h ^= k;
  67. h *= m;
  68. // Completely arbitrary number, to prevent 0's
  69. // from hashing to 0.
  70. h += 0xe6546b64;
  71. }
  72. #endif // BOOST_NO_INT64_T
  73. } //namespace detail {
  74. } //namespace intrusive {
  75. } //namespace boost {
  76. #endif //BOOST_INTRUSIVE_DETAIL_HASH_COMBINE_HPP