MADNESS 0.10.1
worldhash.h
Go to the documentation of this file.
1/*
2 This file is part of MADNESS.
3
4 Copyright (C) 2007,2010 Oak Ridge National Laboratory
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20 For more information please contact:
21
22 Robert J. Harrison
23 Oak Ridge National Laboratory
24 One Bethel Valley Road
25 P.O. Box 2008, MS-6367
26
27 email: harrisonrj@ornl.gov
28 tel: 865-241-3937
29 fax: 865-572-0680
30*/
31
32#ifndef MADNESS_WORLD_WORLDHASH_H__INCLUDED
33#define MADNESS_WORLD_WORLDHASH_H__INCLUDED
34
35/*!
36 \file worldhash.h
37 \brief Defines hash functions for use in distributed containers
38 \addtogroup hashing
39 @{
40
41MADNESS uses hashing functions are modeled after Boost.Functional/Hash. It has
42many similar function calls including hash_value, hash_combine, and hash_range.
43In addition, it is also compatible with C++ TR1 hashing functors. The
44\c madness::Hash functor interface is identical to both boost::hash and
45\c std::hash , and any one of these may be used. By default, MADNESS hashing
46functions can hash all fundamental types including integral types, floating
47point types, pointer types, std::string, std::wstring, and std::array. Presently
48\c hashT is typedef to \c std::size_t .
49
50Since having a good hash is important, we are using Bob Jenkin's "lookup v3"
51hash from http://www.burtleburtle.net/bob/c/lookup3.c. The preferred interface
52for these function is with the \c madness::Hash<T> functor, but you can also use
53hash_value or the "lookup v3" interface directly.
54
55\b Note: Bob Jenkin's "lookup v3" hash returns a uint32_t hash value, which is
56cast to std::size_t. This is done for compatibility with std::hash.
57
58\b WARNING: While both std::hash and madness::Hash have the same interface, they
59will not generate the same hash values from the same key value.
60
61MADNESS hashing consists of one functor and three functions
62 \li \c madness::Hash is the hash functor and the primary interface for hashing
63 \li \c hash_value() is for hashing a single value and is the function used by the Hash functor
64 \li \c hash_range() is for hashing a group of values. You can use this function to hash
65 an iterator range, a C-style array, or a pointer.
66 \li \c hash_combine() hashs a given value and combines it with a seed. This is
67 useful for combining multiple elements into a single hash value.
68
69There are several options for creating and using hash functions for your custom
70types. The easiest method is to define a \c hash_value function for your key
71type in the same namespace. This function will automatically be used by MADNESS
72hashing containers. The hashing function should have the following form.
73\code
74namespace MyNamespace {
75
76 class Key {
77 // ...
78 };
79
80 madness::hashT hash_value(const Key& t) {
81 // ...
82 }
83
84} // namespace MyNamespace
85\endcode
86If your object is in the \c madness namespace, you may also use the intrusive
87method and define a hash member function for your key.
88\code
89namespace madness {
90 class Key {
91 public:
92
93 // ...
94
95 madness::hashT hash() const {
96 // ...
97 }
98 };
99}
100\endcode
101You can create a specialization of madness::Hash for your type directly.
102\code
103class Key {
104 // ...
105};
106
107namespace madness {
108
109 template <>
110 struct Hash<Key> {
111 hashT operator()(const Key& a) const {
112 // ...
113 }
114 };
115
116} // namespace madness
117\endcode
118If you use any of the above methods, MADNESS hash_combine and hash_range functions
119will be able to hash your custom types.
120
121In addition to these methods, you can use std::hash, boost::hash, or create your
122own custom hashing functor that has the same form as madness::hash. However, if
123you want to use a hashing functor other than madness::Hash, you will need to
124provide the appropriate template parameter to the hashing container.
125
126*/
127
129#include <stdint.h>
130#include <cstddef>
131#include <cstring>
132#include <iterator>
133#include <type_traits>
134
135// Bob Jenkin's "lookup v3" hash from http://www.burtleburtle.net/bob/c/lookup3.c.
136extern "C" {
137 uint32_t hashword(const uint32_t *k, size_t length, uint32_t initval);
138 uint32_t hashlittle(const void *key, size_t length, uint32_t initval);
139}
140
141namespace madness {
142
143 // Hash, hash_value, hash_combine, and hash_range a la Boost.
144
145 /// The hash value type
146 typedef std::size_t hashT;
147
148 /// Hash a single fundamental object
149
150 /// \tparam T The fundamental type
151 /// \param t The object to hash
152 /// \return The hashed value
153 /// \note Use heavily optimized hashword when sizeof(T) is multiple
154 /// of sizeof(uint32_t) and presumably correctly aligned.
155 template <class T>
156 inline typename std::enable_if<std::is_fundamental<T>::value &&
157 ((sizeof(T)%sizeof(uint32_t)) == 0),
159 hash_value(const T t) {
160 alignas(uint32_t) uint32_t buf[sizeof(T)/sizeof(uint32_t)];
161 std::memcpy(buf, &t, sizeof(T));
162 return hashword(buf,
163 std::integral_constant<std::size_t,sizeof(T)/sizeof(uint32_t)>::value, 0u);
164 }
165
166 /// Hash a single fundamental object
167
168 /// \tparam T The fundamental type
169 /// \param t The object to hash
170 /// \return The hashed value
171 template <class T>
172 inline typename std::enable_if<std::is_fundamental<T>::value &&
173 ((sizeof(T)%sizeof(uint32_t)) != 0),
175 hash_value(const T t) {
176 hashT result = 0ul;
177 result = hashlittle(reinterpret_cast<const void*>(&t), sizeof(T), 0u);
178 return result;
179 }
180
181 /// Hash a pointer address
182
183 /// \tparam T The pointer type
184 /// \param t The pointer to be hashed
185 /// \return The hashed value
186 template <typename T>
187 inline hashT hash_value(const T* t) {
188 const unsigned long n = reinterpret_cast<unsigned long>(t);
189 return hash_value(n);
190 }
191
192 /// Hash a class object
193
194 /// \tparam T The class type
195 /// \param t The object to hash
196 /// \return \c t.hash()
197 template <typename T, typename = std::enable_if_t<std::is_same_v<decltype(std::declval<const T&>().hash()),hashT>>>
198 inline auto
199 hash_value(const T& t) {
200 return t.hash();
201 }
202
203 /// Hash a std::basic_string
204
205 /// \tparam T The character type
206 /// \param t The string to hash
207 /// \return The hashed value of the string
208 template <typename T>
209 inline hashT hash_value(const std::basic_string<T>& t);
210
211 /// Hash a std::pair
212
213 /// \param t a pair to hash
214 /// \return The hashed value of \p t
215 template <typename T, typename R>
216 inline hashT hash_value(const std::pair<T,R>& t);
217
218 /// Hash functor
219
220 /// This hash functor calls hash_value for the given type, \c T . The
221 /// namespace for hash_value function is not specified so you are free to
222 /// implement your own version for your data type as follows:
223 /// \code
224 /// namespace MyNamespace {
225 /// class MyClass;
226 /// madness::hashT hash_value(const MyClass& t) {
227 /// // ...
228 /// }
229 /// } // namespace MyNamespace
230 /// \endcode
231 /// or you can specialize this functor directly.
232 /// \tparam T The object type to hash
233 template <typename T>
234 struct Hash {
235
236 /// Hashing function wrapper
237
238 /// \param t The object to be hashed
239 /// \return The hashed value
240 hashT operator()(const T& t) const {
241 return hash_value(t);
242 }
243 }; // struct Hash
244
245 namespace detail {
246 /// Internal use only
247 // We don't hash anything here. It is just used for combining a hashed
248 // value with a seed.
249 inline void combine_hash(hashT& seed, hashT hash) {
250 seed ^= hash + 0x9e3779b9 + (seed<<6) + (seed>>2);
251 }
252 }
253
254 /// Combine hash values
255
256 /// This function uses the standard hash function.
257 /// \tparam T The type to hash
258 /// \param[in,out] seed The initial hash seed value
259 /// \param[in] v The value to be hashed
260 template <class T>
261 inline void hash_combine(hashT& seed, const T& v) {
262 Hash<T> hasher;
263 detail::combine_hash(seed, hasher(v));
264 }
265
266 template <typename T, typename R>
267 inline hashT hash_value(const std::pair<T,R>& t) {
268 hashT result = hash_value(t.first);
269 hash_combine(result, hash_value(t.second));
270 return result;
271 }
272
273
274
275
276 /// \tparam It the iterator type
277 /// \param[in,out] seed The initial hash seed value
278 /// \param[in] first The first element of the iterator range to be hashed
279 /// \param[in] last The end of the iterator range to be hashed
280 template <class It>
281 inline void hash_range(hashT& seed, It first, It last) {
283 for(; first != last; ++first)
284 detail::combine_hash(seed, hasher(*first));
285 }
286
287 /// Combine the hash values of an iterator range
288
289 /// \tparam It the iterator type
290 /// \param[in] first The first element of the iterator range to be hashed
291 /// \param[in] last The end of the iterator range to be hashed
292 /// \return The hashed iterator range
293 template <class It>
294 inline hashT hash_range(It first, It last) {
295 hashT seed = 0;
296 hash_range(seed, first, last);
297
298 return seed;
299 }
300
301 /// Combine the hash values of a C-style array
302
303 /// \tparam T The type to be hashed
304 /// \tparam n The size of the C-style array
305 /// \param[in] t The array to be hashed
306 /// \return The hashed array value
307 template <class T, std::size_t n>
308 inline hashT hash_range(const T(&t)[n]) {
309 return hash_range(t, n);
310 }
311
312 /// Combine the hash values of a C-style array
313
314 /// \tparam T The type to be hashed
315 /// \tparam n The size of the C-style array
316 /// \param[in,out] seed The initial hash seed value
317 /// \param[in] t The array to be hashed
318 /// \note This function uses std::hash
319 template <class T, std::size_t n>
320 inline void hash_range(hashT& seed, const T(&t)[n]) {
321 hash_range(seed, t, n);
322 }
323
324 /// Combine the hash values of a pointer range
325
326 /// \tparam T The type to be hashed
327 /// \param[in,out] seed The initial hash seed value
328 /// \param[in] t A pointer to the beginning of the range to be hashed
329 /// \param[in] n The number of elements to hashed
330 /// \note May use heavily optimized hashword when n * sizeof(T) is multiple
331 /// of sizeof(uint32_t) and presumably correctly aligned.
332 template <class T>
333 inline typename std::enable_if<std::is_fundamental<T>::value >::type
334 hash_range(hashT& seed, const T* t, std::size_t n) {
335 const std::size_t bytes = n * sizeof(T);
336 if((bytes % sizeof(uint32_t)) == 0)
337 seed = hashword(reinterpret_cast<const uint32_t *>(t), bytes/sizeof(uint32_t), seed);
338 else
339 seed = hashlittle(static_cast<const void *>(t), bytes, seed);
340 }
341
342 /// Combine the hash values of a pointer range
343
344 /// \tparam T The type to be hashed
345 /// \param[in,out] seed The initial hash seed value
346 /// \param[in] t A pointer to the beginning of the range to be hashed
347 /// \param[in] n The number of elements to hashed
348 template <class T>
349 inline typename std::enable_if<!std::is_fundamental<T>::value >::type
350 hash_range(hashT& seed, const T* t, std::size_t n) {
351 hash_range(seed, t, t + n);
352 }
353
354 /// Combine the hash values of a pointer range
355
356 /// \tparam T The type to be hashed
357 /// \param t A pointer to the beginning of the range to be hashed
358 /// \param n The number of elements to hashed
359 /// \return The hashed pointer range value
360 template <class T>
361 inline hashT hash_range(const T* t, std::size_t n) {
362 hashT seed = 0ul;
363 hash_range(seed, t, n);
364 return seed;
365 }
366
367 template <typename T>
368 inline hashT hash_value(const std::basic_string<T>& t) {
369 return hash_range(t.c_str(), t.size());
370 }
371
372
373} // namespace madness
374
375///@}
376
377#endif // MADNESS_WORLD_WORLDHASH_H__INCLUDED
uint32_t hashword(const uint32_t *k, size_t length, uint32_t initval)
Definition lookup3.c:189
uint32_t hashlittle(const void *key, size_t length, uint32_t initval)
Definition lookup3.c:253
static const double v
Definition hatom_sf_dirac.cc:20
static double u(double r, double c)
Definition he.cc:20
static const double length
Definition hedft.cc:48
Macros and tools pertaining to the configuration of MADNESS.
Definition potentialmanager.cc:41
void combine_hash(hashT &seed, hashT hash)
Internal use only.
Definition worldhash.h:249
Namespace for all elements and tools of MADNESS.
Definition DFConvergence.h:9
void hash_range(hashT &seed, It first, It last)
Definition worldhash.h:281
void hash_combine(hashT &seed, const T &v)
Combine hash values.
Definition worldhash.h:261
std::size_t hashT
The hash value type.
Definition worldhash.h:146
std::string type(const PairType &n)
Definition PNOParameters.h:18
madness::hashT hash_value(const std::array< T, N > &a)
Hash std::array with madness hash.
Definition array_addons.h:78
static const long k
Definition rk.cc:44
Hash functor.
Definition worldhash.h:234
hashT operator()(const T &t) const
Hashing function wrapper.
Definition worldhash.h:240