MySQL 9.1.0
Source Code Documentation
my_hash_combine.h
Go to the documentation of this file.
1/* Copyright (c) 2017, 2024, Oracle and/or its affiliates.
2
3The code in this file is copied from Boost 1.63.0
4boost/functional/hash/hash.hpp, which contains the following copyright notice:
5
6Copyright 2005-2014 Daniel James.
7Distributed under the Boost Software License, Version 1.0. (See accompanying
8file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9
10 Based on Peter Dimov's proposal
11 http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf
12 issue 6.18._
13
14 This also contains public domain code from MurmurHash. From the
15 MurmurHash header:
16
17MurmurHash3 was written by Austin Appleby, and is placed in the public
18domain. The author hereby disclaims copyright to this source code. */
19
20/** @file include/my_hash_combine.h
21A convenient way to combine two hash values.
22
23It was decided to copy (parts of) the boost::hash_combine() implementation
24instead of using it directly (by including <boost/functional/hash.hpp>)
25because of the following reasons, raised by Steinar and Tor:
26
27Pros:
28
29 - It solves a real problem (how to hash std::pair).
30 - Few dependencies (just type_traits and enable_if).
31 - Seems like a reasonable implementation.
32
33Cons:
34
35 - It's more Boost.
36 - Doesn't seem to be accepted into C++17, so it's something we'd have to
37 drag around for a long time without an easy migration path off it.
38 - It solves the problem in a suboptimal way; combining values after
39 hash-finalization is going to both hash worse and slower than before it.
40 The real way requires an interface change to how std::hash works
41 (exposing more internal hasher state). I know people have been working on
42 this, but evidently it didn't reach C++17 either.
43 - Uses boost::hash instead of std::hash. This is probably the biggest killer
44 for me.
45 - Can easily be implemented by ourselves by lifting the core parts of the
46 Boost implementation. (It's about 20 lines.)
47
48I could go either way, but my immediate thought is probably that we should
49copy the Boost implementation into some header, and then prefix it with a
50warning saying that you shouldn't use this if you need optimal performance or
51hash distribution.
52
53Steinar */
54
55#ifndef MY_HASH_COMBINE_INCLUDED
56#define MY_HASH_COMBINE_INCLUDED
57
58#if defined(_MSC_VER)
59#define MY_FUNCTIONAL_HASH_ROTL32(x, r) _rotl(x, r)
60#else
61#define MY_FUNCTIONAL_HASH_ROTL32(x, r) (x << r) | (x >> (32 - r))
62#endif /* _MSC_VER */
63
64#include <stdint.h>
65
66template <typename SizeT>
67inline void my_hash_combine(SizeT &seed, SizeT value) {
68 seed ^= value + 0x9e3779b9 + (seed << 6) + (seed >> 2);
69}
70
71inline void my_hash_combine(uint32_t &h1, uint32_t k1) {
72 const uint32_t c1 = 0xcc9e2d51;
73 const uint32_t c2 = 0x1b873593;
74
75 k1 *= c1;
76 k1 = MY_FUNCTIONAL_HASH_ROTL32(k1, 15);
77 k1 *= c2;
78
79 h1 ^= k1;
80 h1 = MY_FUNCTIONAL_HASH_ROTL32(h1, 13);
81 h1 = h1 * 5 + 0xe6546b64;
82}
83
84inline void my_hash_combine(uint64_t &h, uint64_t k) {
85 const uint64_t m = 0xc6a4a7935bd1e995ull;
86 const int r = 47;
87
88 k *= m;
89 k ^= k >> r;
90 k *= m;
91
92 h ^= k;
93 h *= m;
94
95 // Completely arbitrary number, to prevent 0's
96 // from hashing to 0.
97 h += 0xe6546b64;
98}
99
100#endif /* MY_HASH_COMBINE_INCLUDED */
#define MY_FUNCTIONAL_HASH_ROTL32(x, r)
Definition: my_hash_combine.h:61
void my_hash_combine(SizeT &seed, SizeT value)
Definition: my_hash_combine.h:67
const mysql_service_registry_t * r
Definition: pfs_example_plugin_employee.cc:86