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