X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2FHash.h;h=109b24e40e5478b1a2954c6b108376a02d76c9b5;hb=46e3ed2921bd4e5de81fbc36fcb6a82d30d1499f;hp=1cbeda6a81e5723786760c0d77a52b208d0b8ca1;hpb=148cba11ab1b0d20f17485bd80fcc7e7214f5cca;p=folly.git diff --git a/folly/Hash.h b/folly/Hash.h index 1cbeda6a..109b24e4 100644 --- a/folly/Hash.h +++ b/folly/Hash.h @@ -1,5 +1,5 @@ /* - * Copyright 2012 Facebook, Inc. + * Copyright 2014 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,9 +21,10 @@ #include #include #include +#include -#include "folly/SpookyHashV1.h" -#include "folly/SpookyHashV2.h" +#include +#include /* * Various hashing functions. @@ -32,14 +33,11 @@ namespace folly { namespace hash { // This is a general-purpose way to create a single hash from multiple -// hashable objects. It relies on std::hash being available for all -// relevant types and combines those hashes in an order-dependent way -// to yield a new hash. +// hashable objects. hash_combine_generic takes a class Hasher implementing +// hash; hash_combine uses a default hasher StdHasher that uses std::hash. +// hash_combine_generic hashes each argument and combines those hashes in +// an order-dependent way to yield a new hash. -// Never used, but gcc demands it. -inline size_t hash_combine() { - return 0; -} // This is the Hash128to64 function from Google's cityhash (available // under the MIT License). We use it to reduce multiple 64 bit hashes @@ -55,16 +53,52 @@ inline size_t hash_128_to_64(const size_t upper, const size_t lower) { return b; } -template -size_t hash_combine(const T& t, const Ts&... ts) { - size_t seed = std::hash()(t); +// Never used, but gcc demands it. +template +inline size_t hash_combine_generic() { + return 0; +} + +template < + class Iter, + class Hash = std::hash::value_type>> +uint64_t hash_range(Iter begin, + Iter end, + uint64_t hash = 0, + Hash hasher = Hash()) { + for (; begin != end; ++begin) { + hash = hash_128_to_64(hash, hasher(*begin)); + } + return hash; +} + +template +size_t hash_combine_generic(const T& t, const Ts&... ts) { + size_t seed = Hasher::hash(t); if (sizeof...(ts) == 0) { return seed; } - size_t remainder = hash_combine(ts...); + size_t remainder = hash_combine_generic(ts...); return hash_128_to_64(seed, remainder); } +// Simply uses std::hash to hash. Note that std::hash is not guaranteed +// to be a very good hash function; provided std::hash doesn't collide on +// the individual inputs, you are fine, but that won't be true for, say, +// strings or pairs +class StdHasher { + public: + template + static size_t hash(const T& t) { + return std::hash()(t); + } +}; + +template +size_t hash_combine(const T& t, const Ts&... ts) { + return hash_combine_generic(t, ts...); +} + ////////////////////////////////////////////////////////////////////// /* @@ -169,7 +203,7 @@ inline uint32_t jenkins_rev_unmix32(uint32_t key) { * http://www.isthe.com/chongo/tech/comp/fnv/ */ -const uint32_t FNV_32_HASH_START = 216613626UL; +const uint32_t FNV_32_HASH_START = 2166136261UL; const uint64_t FNV_64_HASH_START = 14695981039346656037ULL; inline uint32_t fnv32(const char* s, @@ -197,7 +231,7 @@ inline uint32_t fnv32_buf(const void* buf, } inline uint32_t fnv32(const std::string& str, - uint64_t hash = FNV_32_HASH_START) { + uint32_t hash = FNV_32_HASH_START) { return fnv32_buf(str.data(), str.size(), hash); } @@ -328,6 +362,26 @@ template<> struct hasher { } }; +// recursion +template +struct TupleHasher { + size_t operator()(std::tuple const& key) const { + return hash::hash_combine( + TupleHasher()(key), + std::get(key)); + } +}; + +// base +template +struct TupleHasher<0, Ts...> { + size_t operator()(std::tuple const& key) const { + // we could do std::hash here directly, but hash_combine hides all the + // ugly templating implicitly + return hash::hash_combine(std::get<0>(key)); + } +}; + } // namespace folly // Custom hash functions. @@ -341,6 +395,18 @@ namespace std { return folly::hash::hash_combine(x.first, x.second); } }; + + // Hash function for tuples. Requires default hash functions for all types. + template + struct hash> { + size_t operator()(std::tuple const& key) const { + folly::TupleHasher< + std::tuple_size>::value - 1, // start index + Ts...> hasher; + + return hasher(key); + } + }; } // namespace std #endif