BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslalg_hashutil.h
Go to the documentation of this file.
1/// @file bslalg_hashutil.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslalg_hashutil.h -*-C++-*-
8#ifndef INCLUDED_BSLALG_HASHUTIL
9#define INCLUDED_BSLALG_HASHUTIL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslalg_hashutil bslalg_hashutil
15/// @brief Provide a utility of hash functions.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslalg
19/// @{
20/// @addtogroup bslalg_hashutil
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslalg_hashutil-purpose"> Purpose</a>
25/// * <a href="#bslalg_hashutil-classes"> Classes </a>
26/// * <a href="#bslalg_hashutil-description"> Description </a>
27/// * <a href="#bslalg_hashutil-usage"> Usage </a>
28/// * <a href="#bslalg_hashutil-example-1-dumping-out-hash-values"> Example 1: Dumping Out Hash Values </a>
29///
30/// # Purpose {#bslalg_hashutil-purpose}
31/// Provide a utility of hash functions.
32///
33/// # Classes {#bslalg_hashutil-classes}
34///
35/// - bslalg::HashUtil: utility for hash functions
36///
37/// # Description {#bslalg_hashutil-description}
38/// This component provides a namespace class, `HashUtil`, for
39/// hash functions. At the current time it has one hash function,
40/// `HashUtil::computeHash`, which will hash most fundamental types, and
41/// pointers, rapidly. Note that when a pointer is passed, only the bits in the
42/// pointer itself are hashed, the memory the pointer refers to is not examined.
43///
44/// ## Usage {#bslalg_hashutil-usage}
45///
46///
47/// This section illustrates intended usage of this component.
48///
49/// ### Example 1: Dumping Out Hash Values {#bslalg_hashutil-example-1-dumping-out-hash-values}
50///
51///
52/// Suppose we want to analyze our hash function by seeing how it distributes
53/// integers across buckets. We will declare 64 buckets, and distribute hits
54/// among the bucket by indexing them with the low order 6 bits of the hash.
55/// Then we will display the distribution of hits in each bucket, to see if
56/// the hash function is distributing them evenly.
57/// @code
58/// int buckets[64];
59/// @endcode
60/// First, we hash on the values of i in the range `[ 0, 1 << 15 )`:
61/// @code
62/// {
63/// memset(buckets, 0, sizeof(buckets));
64/// for (int i = 0; i < (1 << 15); ++i) {
65/// std::size_t hash = bslalg::HashUtil::computeHash(i);
66///
67/// ++buckets[hash & 63];
68/// }
69/// if (verbose) printf("Straight hash:\n");
70/// int col = 0;
71/// for (int i = 0; i < 64; ++i) {
72/// if (verbose) printf("%s%5d", (0 == col ? " " : ", "),
73/// buckets[i]);
74/// ++col;
75/// if (8 == col) {
76/// col = 0;
77/// if (verbose) printf("\n");
78/// }
79/// }
80/// }
81/// @endcode
82/// Then, we will hash on the values of `4 * i` for i in the range
83/// `[ 0, 1 << 15 )`. This is interesting because pointers will often be 4-byte
84/// aligned and have the 2 low-order bits always zero, so this will be a
85/// simulation of that:
86/// @code
87/// {
88/// memset(buckets, 0, sizeof(buckets));
89/// for (int i = 0; i < (1 << 15); ++i) {
90/// std::size_t hash = bslalg::HashUtil::computeHash(4 * i);
91///
92/// ++buckets[hash & 63];
93/// }
94/// if (verbose) printf("\nStraight * 4 hash:\n");
95/// int col = 0;
96/// for (int i = 0; i < 64; ++i) {
97/// if (verbose) printf("%s%5d", (0 == col ? " " : ", "),
98/// buckets[i]);
99/// ++col;
100/// if (8 == col) {
101/// col = 0;
102/// if (verbose) printf("\n");
103/// }
104/// }
105/// }
106/// @endcode
107/// Next, we will xor the bottom 30 bits of the hash into the bottom 6 bits, so
108/// we'll be observing more of the whole word:
109/// @code
110/// {
111/// memset(buckets, 0, sizeof(buckets));
112/// for (int i = 0; i < (1 << 15); ++i) {
113/// std::size_t hash = bslalg::HashUtil::computeHash(i);
114/// hash = hash ^ (hash >> 6) ^ (hash >> 12) ^ (hash >> 18) ^
115/// (hash >> 24);
116///
117/// ++buckets[hash & 63];
118/// }
119/// if (verbose) printf("\nFolded hash:\n");
120/// int col = 0;
121/// for (int i = 0; i < 64; ++i) {
122/// if (verbose) printf("%s%5d", (0 == col ? " " : ", "),
123/// buckets[i]);
124/// ++col;
125/// if (8 == col) {
126/// col = 0;
127/// if (verbose) printf("\n");
128/// }
129/// }
130/// }
131/// @endcode
132/// Now, bear in mind that an identity hash will perform very optimally on the
133/// first and third tests we did. This time we will take the difference between
134/// the current hash and the previous one, a test for which the identity
135/// function would perform abominably:
136/// @code
137/// {
138/// memset(buckets, 0, sizeof(buckets));
139/// std::size_t prev = 0;
140/// for (int i = 0; i < (1 << 15); ++i) {
141/// std::size_t hash = bslalg::HashUtil::computeHash(i);
142///
143/// ++buckets[(hash - prev) & 63];
144/// prev = hash;
145/// }
146/// if (verbose) printf("\nDiff hash:\n");
147/// int col = 0;
148/// for (int i = 0; i < 64; ++i) {
149/// if (verbose) printf("%s%5d", (0 == col ? " " : ", "),
150/// buckets[i]);
151/// ++col;
152/// if (8 == col) {
153/// col = 0;
154/// if (verbose) printf("\n");
155/// }
156/// }
157/// }
158/// @endcode
159/// Finally, take the difference between the previous hash and the current one,
160/// only this time, instead of subtracting, take a bitwise xor:
161/// @code
162/// {
163/// memset(buckets, 0, sizeof(buckets));
164/// std::size_t prev = 0;
165/// for (int i = 0; i < (1 << 15); ++i) {
166/// std::size_t hash = bslalg::HashUtil::computeHash(i);
167///
168/// ++buckets[(hash ^ prev) & 63];
169/// prev = hash;
170/// }
171/// if (verbose) printf("\nXor diff hash:\n");
172/// int col = 0;
173/// for (int i = 0; i < 64; ++i) {
174/// if (verbose) printf("%s%5d", (0 == col ? " " : ", "),
175/// buckets[i]);
176/// ++col;
177/// if (8 == col) {
178/// col = 0;
179/// if (verbose) printf("\n");
180/// }
181/// }
182/// }
183/// @endcode
184/// The output produced by this usage example follows:
185/// @code
186/// Straight hash:
187/// 508, 501, 511, 502, 522, 524, 515, 500
188/// 501, 519, 523, 520, 495, 514, 540, 497
189/// 500, 523, 525, 518, 491, 515, 527, 509
190/// 513, 500, 511, 520, 487, 515, 505, 520
191/// 519, 516, 505, 534, 507, 514, 522, 517
192/// 538, 514, 510, 510, 531, 491, 513, 506
193/// 515, 497, 504, 496, 541, 508, 501, 523
194/// 501, 523, 485, 492, 517, 510, 503, 534
195///
196/// Straight * 4 hash:
197/// 513, 512, 493, 517, 514, 472, 501, 527
198/// 528, 504, 527, 507, 516, 494, 534, 514
199/// 517, 500, 513, 533, 507, 499, 511, 540
200/// 492, 518, 530, 522, 503, 522, 505, 494
201/// 520, 492, 490, 508, 538, 560, 522, 487
202/// 521, 516, 493, 491, 532, 504, 497, 530
203/// 495, 534, 537, 504, 487, 525, 533, 497
204/// 510, 499, 511, 506, 523, 512, 498, 517
205///
206/// Folded hash:
207/// 537, 493, 517, 544, 501, 508, 535, 528
208/// 502, 530, 536, 541, 500, 475, 540, 510
209/// 521, 513, 501, 525, 497, 511, 521, 513
210/// 522, 523, 479, 479, 508, 490, 507, 523
211/// 577, 490, 520, 514, 493, 465, 468, 511
212/// 518, 544, 503, 484, 550, 514, 517, 500
213/// 510, 501, 542, 528, 517, 456, 513, 530
214/// 518, 484, 510, 506, 522, 477, 563, 493
215///
216/// Diff hash:
217/// 329, 329, 526, 660, 755, 726, 466, 398
218/// 235, 410, 424, 713, 695, 714, 535, 314
219/// 342, 274, 598, 662, 711, 772, 498, 463
220/// 268, 360, 399, 655, 672, 694, 584, 311
221/// 404, 282, 601, 678, 660, 661, 418, 377
222/// 245, 425, 462, 762, 682, 627, 588, 295
223/// 369, 331, 529, 712, 659, 688, 418, 357
224/// 238, 387, 467, 687, 730, 695, 540, 302
225///
226/// Xor diff hash:
227/// 329, 142, 535, 475, 781, 800, 567, 510
228/// 258, 258, 378, 549, 664, 906, 477, 496
229/// 298, 118, 554, 467, 765, 883, 576, 418
230/// 233, 226, 375, 608, 633, 903, 422, 388
231/// 404, 133, 648, 412, 658, 896, 521, 459
232/// 258, 256, 383, 601, 699, 836, 511, 599
233/// 413, 169, 660, 450, 658, 826, 524, 560
234/// 237, 255, 383, 573, 706, 834, 539, 715
235/// @endcode
236/// @}
237/** @} */
238/** @} */
239
240/** @addtogroup bsl
241 * @{
242 */
243/** @addtogroup bslalg
244 * @{
245 */
246/** @addtogroup bslalg_hashutil
247 * @{
248 */
249
250#include <bslscm_version.h>
251
252#include <bsls_types.h>
253
254#ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
255#include <bsls_nativestd.h>
256#endif // BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
257
258
259
260namespace bslalg {
261 // ===============
262 // struct HashUtil
263 // ===============
264
265/// This `struct` provides a namespace for hash functions.
266struct HashUtil {
267
268 // CLASS METHODS
269
270 /// Return a `size_t` hash value corresponding to the specified `key`.
271 /// Note that the return value is seemingly random (i.e., the hash is
272 /// good) but identical on all platforms (irrespective of endianness).
273 ///
274 /// NOTE: We reserve the right to change these hash functions to return
275 /// different values. The current implementation only returns a 32 bit
276 /// value -- when `std::size_t` is 64 bits, the high-order 32
277 /// bits of the return value are all zero. This is not a feature, it is
278 /// a bug that we will fix in a later release.
279 static std::size_t computeHash(char key);
280 static std::size_t computeHash(signed char key);
281 static std::size_t computeHash(unsigned char key);
282 static std::size_t computeHash(short key);
283 static std::size_t computeHash(unsigned short key);
284 static std::size_t computeHash(int key);
285 static std::size_t computeHash(unsigned int key);
286 static std::size_t computeHash(long key);
287 static std::size_t computeHash(unsigned long key);
288 static std::size_t computeHash(long long key);
289 static std::size_t computeHash(unsigned long long key);
290 static std::size_t computeHash(float key);
291 static std::size_t computeHash(double key);
292 static std::size_t computeHash(const void *key);
293};
294
295// ============================================================================
296// INLINE FUNCTION DEFINITIONS
297// ============================================================================
298
299} // close package namespace
300
301
302#endif
303
304// ----------------------------------------------------------------------------
305// Copyright 2013 Bloomberg Finance L.P.
306//
307// Licensed under the Apache License, Version 2.0 (the "License");
308// you may not use this file except in compliance with the License.
309// You may obtain a copy of the License at
310//
311// http://www.apache.org/licenses/LICENSE-2.0
312//
313// Unless required by applicable law or agreed to in writing, software
314// distributed under the License is distributed on an "AS IS" BASIS,
315// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
316// See the License for the specific language governing permissions and
317// limitations under the License.
318// ----------------------------- END-OF-FILE ----------------------------------
319
320/** @} */
321/** @} */
322/** @} */
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bdlc_flathashmap.h:1805
This struct provides a namespace for hash functions.
Definition bslalg_hashutil.h:266
static std::size_t computeHash(unsigned long key)
static std::size_t computeHash(short key)
static std::size_t computeHash(float key)
static std::size_t computeHash(unsigned int key)
static std::size_t computeHash(unsigned short key)
static std::size_t computeHash(const void *key)
static std::size_t computeHash(int key)
static std::size_t computeHash(long long key)
static std::size_t computeHash(long key)
static std::size_t computeHash(signed char key)
static std::size_t computeHash(unsigned long long key)
static std::size_t computeHash(double key)
static std::size_t computeHash(char key)
static std::size_t computeHash(unsigned char key)