BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslh_fibonaccibadhashwrapper.h
Go to the documentation of this file.
1/// @file bslh_fibonaccibadhashwrapper.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslh_fibonaccibadhashwrapper.h -*-C++-*-
8#ifndef INCLUDED_BSLH_FIBONACCIBADHASHWRAPPER
9#define INCLUDED_BSLH_FIBONACCIBADHASHWRAPPER
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslh_fibonaccibadhashwrapper bslh_fibonaccibadhashwrapper
15/// @brief Provide a wrapper to improve "bad" hash algorithms.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslh
19/// @{
20/// @addtogroup bslh_fibonaccibadhashwrapper
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslh_fibonaccibadhashwrapper-purpose"> Purpose</a>
25/// * <a href="#bslh_fibonaccibadhashwrapper-classes"> Classes </a>
26/// * <a href="#bslh_fibonaccibadhashwrapper-description"> Description </a>
27/// * <a href="#bslh_fibonaccibadhashwrapper-requirements-upon-wrapped-hash-function-object"> Requirements Upon Wrapped Hash Function Object </a>
28/// * <a href="#bslh_fibonaccibadhashwrapper-usage"> Usage </a>
29/// * <a href="#bslh_fibonaccibadhashwrapper-example-1-obtaining-most-significant-and-least-significant-bit-variation"> Example 1: Obtaining Most-Significant and Least-Significant Bit Variation </a>
30///
31/// # Purpose {#bslh_fibonaccibadhashwrapper-purpose}
32/// Provide a wrapper to improve "bad" hash algorithms.
33///
34/// # Classes {#bslh_fibonaccibadhashwrapper-classes}
35///
36/// - bslh::FibonacciBadHashWrapper: wrapper to improve "bad" hashes
37///
38/// # Description {#bslh_fibonaccibadhashwrapper-description}
39/// This component provides a functor type,
40/// `bslh::FibonacciBadHashWrapper`, that can be used to wrap a hash algorithm
41/// ameliorating the unwanted properties of a poor hash function.
42///
43/// For example, the identity function is often used to hash integer values (see
44/// `bsl::hash<int>`), and although the identity function has the property that
45/// two different input values are unlikely to result in the same hash value, it
46/// does not have many of the other desirable properties of a hash function
47/// (common input values are not evenly distributed over the range of hash
48/// values, a small change the input does not change the hash value extensively,
49/// and it is easy to determine the input from a hash value).
50///
51/// The `bslh::FibonacciBadHashWrapper` can be used on the output of a bad hash
52/// function (like the identity function) to address some (but not all) of those
53/// deficiencies. Specifically, the resulting hash value is more evenly
54/// distributed over the range, and a small change in the input will result in a
55/// larger change in the hash value.
56///
57/// ## Requirements Upon Wrapped Hash Function Object {#bslh_fibonaccibadhashwrapper-requirements-upon-wrapped-hash-function-object}
58///
59///
60/// The wrapped hash function object must be a function object, default
61/// constructible, copy constructible, and destructible. The result of
62/// `operator()` must be convertable to `size_t`. For an instance of a hash
63/// functor, `operator()` must provide the same result for each argument value
64/// for the lifetime of the functor. For the `bslh::FibonacciBadHashWrapper` to
65/// support the type `KEY` in its `operator()`, the wrapped hash function's
66/// `operator()` must be invokable with the type `KEY`.
67///
68/// ## Usage {#bslh_fibonaccibadhashwrapper-usage}
69///
70///
71/// This section illustrates intended usage of this component.
72///
73/// ### Example 1: Obtaining Most-Significant and Least-Significant Bit Variation {#bslh_fibonaccibadhashwrapper-example-1-obtaining-most-significant-and-least-significant-bit-variation}
74///
75///
76/// Suppose we are using a hash table that requires variation in the
77/// most-significant and least-significant bits to operate efficiently (e.g.,
78/// Abseil's flat hash map). The keys we will be using are small integer
79/// values, and we would like to use the identity function as the hash functor
80/// since it is efficient. A simple and efficient method to obtain a hash
81/// functor with the necessary qualities is to wrap the identity functor with
82/// `bslh::FibonaccaBadHashWrapper`.
83///
84/// First, we define our `IdentityHash` class.
85/// @code
86/// class IdentityHash {
87/// // This class provides a hash algorithm that provides the "identity"
88/// // mapping from key to hash.
89///
90/// public:
91/// size_t operator()(const int key) const
92/// // Return the specified 'key'.
93/// {
94/// return static_cast<size_t>(key);
95/// }
96/// };
97/// @endcode
98/// Then, we instantiate an instance of the identity functor and the wrapped
99/// functor.
100/// @code
101/// IdentityHash identity;
102/// bslh::FibonacciBadHashWrapper<IdentityHash> wrapped;
103/// @endcode
104/// Finally, we examine the range of values obtained from small integer values:
105/// @code
106/// if (8 == sizeof(size_t)) {
107/// ASSERT(18446744073709551614ull == identity(-2));
108/// ASSERT(18446744073709551615ull == identity(-1));
109/// ASSERT( 0 == identity( 0));
110/// ASSERT( 1 == identity( 1));
111/// ASSERT( 2 == identity( 2));
112///
113/// ASSERT(14092058508772706262ull == wrapped(-2));
114/// ASSERT( 7046029254386353131ull == wrapped(-1));
115/// ASSERT( 0 == wrapped( 0));
116/// ASSERT(11400714819323198485ull == wrapped( 1));
117/// ASSERT( 4354685564936845354ull == wrapped( 2));
118/// }
119/// else {
120/// ASSERT(4294967294u == identity(-2));
121/// ASSERT(4294967295u == identity(-1));
122/// ASSERT( 0 == identity( 0));
123/// ASSERT( 1 == identity( 1));
124/// ASSERT( 2 == identity( 2));
125///
126/// ASSERT( 23791574u == wrapped(-2));
127/// ASSERT(2159379435u == wrapped(-1));
128/// ASSERT( 0 == wrapped( 0));
129/// ASSERT(2135587861u == wrapped( 1));
130/// ASSERT(4271175722u == wrapped( 2));
131/// }
132/// @endcode
133/// @}
134/** @} */
135/** @} */
136
137/** @addtogroup bsl
138 * @{
139 */
140/** @addtogroup bslh
141 * @{
142 */
143/** @addtogroup bslh_fibonaccibadhashwrapper
144 * @{
145 */
146
147#include <bslscm_version.h>
148
149#include <bsls_types.h> // 'bsls::Types::Uint64'
150
151#include <stddef.h> // 'size_t'
152
153
154namespace bslh {
155
156 // =============================
157 // class FibonacciBadHashWrapper
158 // =============================
159
160/// This class provides a hash algorithm wrapper that improves the
161/// distribution of varying bits from the `HASH` applied to the `KEY`.
162///
163/// See @ref bslh_fibonaccibadhashwrapper
164template <class HASH>
166
167 // DATA
168 HASH d_hash; // hash functor
169
170 public:
171 // PUBLIC CLASS DATA
172
173 /// The value corresponds to:
174 /// @code
175 /// 2^64 / phi - 1
176 /// @endcode
177 /// where *phi* is the Golden Ratio and 1 is subtracted to avoid the
178 /// value being a multiple of 2 (that would throw away one bit of
179 /// information from the resultant hash value). See
180 /// https://en.wikipedia.org/wiki/Hash_function#Fibonacci_hashing.
182 = 11400714819323198485ull;
183
184 // CREATORS
185
186 /// Create a `FibonacciBadHashWrapper` having a default constructed
187 /// hash.
189
190 /// Create a `FibonacciBadHashWrapper` having the specified `hash`.
191 explicit FibonacciBadHashWrapper(const HASH& hash);
192
194 const FibonacciBadHashWrapper& original) = default;
195 // Create a 'FibonacciBadHashWrapper' object having the value of the
196 // specified 'original' object.
197
199 // Destroy this object.
200
201 // MANIPULATORS
203 const FibonacciBadHashWrapper& rhs) = default;
204 // Assign to this object the value of the specified 'rhs' object, and
205 // return a reference providing modifiable access to this object.
206
207 // ACCESSORS
208
209 /// Return the hash of the specified `key`, computed as the product
210 /// of the result of the hash function supplied at construction and
211 /// `k_FIBONACCI_HASH_MULTIPLIER`.
212 template <class KEY>
213 size_t operator()(const KEY& key) const;
214};
215
216// ============================================================================
217// INLINE DEFINITIONS
218// ============================================================================
219
220 // ------------------------------
221 // struct FibonacciBadHashWrapper
222 // ------------------------------
223
224// CREATORS
225template <class HASH>
226inline
231
232template <class HASH>
233inline
235: d_hash(hash)
236{
237}
238
239// ACCESSORS
240template <class HASH>
241template <class KEY>
242inline
244{
245 return static_cast<size_t>(d_hash(key) * k_FIBONACCI_HASH_MULTIPLIER);
246}
247
248} // close package namespace
249
250
251#endif
252
253// ----------------------------------------------------------------------------
254// Copyright 2020 Bloomberg Finance L.P.
255//
256// Licensed under the Apache License, Version 2.0 (the "License"); you may not
257// use this file except in compliance with the License. You may obtain a copy
258// of the License at
259//
260// http://www.apache.org/licenses/LICENSE-2.0
261//
262// Unless required by applicable law or agreed to in writing, software
263// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
264// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
265// License for the specific language governing permissions and limitations
266// under the License.
267// ----------------------------- END-OF-FILE ----------------------------------
268
269/** @} */
270/** @} */
271/** @} */
Definition bslh_fibonaccibadhashwrapper.h:165
static const bsls::Types::Uint64 k_FIBONACCI_HASH_MULTIPLIER
Definition bslh_fibonaccibadhashwrapper.h:182
size_t operator()(const KEY &key) const
Definition bslh_fibonaccibadhashwrapper.h:243
FibonacciBadHashWrapper(const FibonacciBadHashWrapper &original)=default
FibonacciBadHashWrapper()
Definition bslh_fibonaccibadhashwrapper.h:227
FibonacciBadHashWrapper & operator=(const FibonacciBadHashWrapper &rhs)=default
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bslh_defaulthashalgorithm.h:339
unsigned long long Uint64
Definition bsls_types.h:137