diff options
| author | Matt Austern <austern@google.com> | 2010-09-13 18:23:56 +0000 |
|---|---|---|
| committer | Paolo Carlini <paolo@gcc.gnu.org> | 2010-09-13 18:23:56 +0000 |
| commit | e7f72940d251473512d541c7b546100209caa60c (patch) | |
| tree | 3f3b9859209b496beacdf65286399d7462f58285 /libstdc++-v3/src | |
| parent | 2ea5ee06a9ab474d15c98f432cfdfeaf2503ff8f (diff) | |
| download | gcc-e7f72940d251473512d541c7b546100209caa60c.tar.gz gcc-e7f72940d251473512d541c7b546100209caa60c.tar.bz2 gcc-e7f72940d251473512d541c7b546100209caa60c.zip | |
hash_bytes.cc: New file...
2010-09-13 Matt Austern <austern@google.com>
* src/hash_bytes.cc: New file, exports _Hash_bytes (a Murmur hash),
and _Fnv_hash_bytes (based on a FNV algorithm).
* src/compatibility-c++0x.cc (hash<string>::operator(),
hash<const string&>::operator(), hash<wstring>::operator(),
hash<const wstring&>::operator(), hash<error_code>::operator()):
Adjust, use _Hash_bytes.
* include/std/system_error (hash<error_code>::operator()): Likewise.
* include/std/thread (hash<thread::id>operator()): Likewise.
* include/std/bitset (hash<bitset>operator()): Likewise.
* include/bits/basic_string.h (hash<string>::operator(),
hash<wstring>::operator(), hash<u16string>::operator(),
hash<u32string>::operator()): Adjust.
* include/bits/vector.tcc (hash<vector<bool>>::operator()): Adjust.
* include/bits/functional_hash.h (_Hash_bytes, _Fnv_hash_bytes):
Declare.
(struct _Hash_impl, struct _Fnv_hash_impl): Add, use _Hash_bytes
and _Fnv_hash_bytes, respectively.
(hash<float>::operator(), hash<double>::operator()): Adjust.
* config/abi/pre/gnu.ver: Add exports.
* src/Makefile.am: Add.
* src/Makefile.in: Regenerate.
From-SVN: r164253
Diffstat (limited to 'libstdc++-v3/src')
| -rw-r--r-- | libstdc++-v3/src/Makefile.am | 6 | ||||
| -rw-r--r-- | libstdc++-v3/src/Makefile.in | 29 | ||||
| -rw-r--r-- | libstdc++-v3/src/compatibility-c++0x.cc | 12 | ||||
| -rw-r--r-- | libstdc++-v3/src/hash_bytes.cc | 184 |
4 files changed, 214 insertions, 17 deletions
diff --git a/libstdc++-v3/src/Makefile.am b/libstdc++-v3/src/Makefile.am index 5499bd2f0ed..d5194c3366e 100644 --- a/libstdc++-v3/src/Makefile.am +++ b/libstdc++-v3/src/Makefile.am @@ -179,6 +179,7 @@ sources = \ hash_tr1.cc \ hashtable_c++0x.cc \ hashtable_tr1.cc \ + hash_bytes.cc \ ios.cc \ ios_failure.cc \ ios_init.cc \ @@ -309,6 +310,11 @@ hashtable_c++0x.lo: hashtable_c++0x.cc hashtable_c++0x.o: hashtable_c++0x.cc $(CXXCOMPILE) -std=gnu++0x -c $< +hash_bytes.lo: hash_bytes.cc + $(LTCXXCOMPILE) -std=gnu++0x -c $< +hash_bytes.o: hash_bytes.cc + $(CXXCOMPILE) -std=gnu++0x -c $< + limits.lo: limits.cc $(LTCXXCOMPILE) -std=gnu++0x -c $< limits.o: limits.cc diff --git a/libstdc++-v3/src/Makefile.in b/libstdc++-v3/src/Makefile.in index 75a97bd9901..92390975740 100644 --- a/libstdc++-v3/src/Makefile.in +++ b/libstdc++-v3/src/Makefile.in @@ -100,17 +100,18 @@ am__objects_5 = atomic.lo bitmap_allocator.lo pool_allocator.lo \ compatibility-c++0x.lo compatibility-debug_list.lo \ compatibility-list.lo complex_io.lo ctype.lo debug.lo \ functexcept.lo globals_io.lo hash_c++0x.lo hash_tr1.lo \ - hashtable_c++0x.lo hashtable_tr1.lo ios.lo ios_failure.lo \ - ios_init.lo ios_locale.lo limits.lo list.lo debug_list.lo \ - locale.lo locale_init.lo locale_facets.lo localename.lo \ - math_stubs_float.lo math_stubs_long_double.lo stdexcept.lo \ - strstream.lo system_error.lo tree.lo allocator-inst.lo \ - concept-inst.lo fstream-inst.lo ext-inst.lo ios-inst.lo \ - iostream-inst.lo istream-inst.lo istream.lo locale-inst.lo \ - misc-inst.lo ostream-inst.lo sstream-inst.lo streambuf-inst.lo \ - streambuf.lo string-inst.lo valarray-inst.lo wlocale-inst.lo \ - wstring-inst.lo mutex.lo condition_variable.lo chrono.lo \ - thread.lo future.lo $(am__objects_1) $(am__objects_4) + hashtable_c++0x.lo hashtable_tr1.lo hash_bytes.lo ios.lo \ + ios_failure.lo ios_init.lo ios_locale.lo limits.lo list.lo \ + debug_list.lo locale.lo locale_init.lo locale_facets.lo \ + localename.lo math_stubs_float.lo math_stubs_long_double.lo \ + stdexcept.lo strstream.lo system_error.lo tree.lo \ + allocator-inst.lo concept-inst.lo fstream-inst.lo ext-inst.lo \ + ios-inst.lo iostream-inst.lo istream-inst.lo istream.lo \ + locale-inst.lo misc-inst.lo ostream-inst.lo sstream-inst.lo \ + streambuf-inst.lo streambuf.lo string-inst.lo valarray-inst.lo \ + wlocale-inst.lo wstring-inst.lo mutex.lo condition_variable.lo \ + chrono.lo thread.lo future.lo $(am__objects_1) \ + $(am__objects_4) am_libstdc___la_OBJECTS = $(am__objects_5) libstdc___la_OBJECTS = $(am_libstdc___la_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) @@ -383,6 +384,7 @@ sources = \ hash_tr1.cc \ hashtable_c++0x.cc \ hashtable_tr1.cc \ + hash_bytes.cc \ ios.cc \ ios_failure.cc \ ios_init.cc \ @@ -885,6 +887,11 @@ hashtable_c++0x.lo: hashtable_c++0x.cc hashtable_c++0x.o: hashtable_c++0x.cc $(CXXCOMPILE) -std=gnu++0x -c $< +hash_bytes.lo: hash_bytes.cc + $(LTCXXCOMPILE) -std=gnu++0x -c $< +hash_bytes.o: hash_bytes.cc + $(CXXCOMPILE) -std=gnu++0x -c $< + limits.lo: limits.cc $(LTCXXCOMPILE) -std=gnu++0x -c $< limits.o: limits.cc diff --git a/libstdc++-v3/src/compatibility-c++0x.cc b/libstdc++-v3/src/compatibility-c++0x.cc index e86eb8d9dab..4941b17a3fd 100644 --- a/libstdc++-v3/src/compatibility-c++0x.cc +++ b/libstdc++-v3/src/compatibility-c++0x.cc @@ -54,23 +54,23 @@ namespace std template<> size_t hash<string>::operator()(string __s) const - { return _Fnv_hash::hash(__s.data(), __s.length()); } + { return _Hash_impl::hash(__s.data(), __s.length()); } template<> size_t hash<const string&>::operator()(const string& __s) const - { return _Fnv_hash::hash(__s.data(), __s.length()); } + { return _Hash_impl::hash(__s.data(), __s.length()); } #ifdef _GLIBCXX_USE_WCHAR_T template<> size_t hash<wstring>::operator()(wstring __s) const - { return _Fnv_hash::hash(__s.data(), __s.length() * sizeof(wchar_t)); } + { return _Hash_impl::hash(__s.data(), __s.length() * sizeof(wchar_t)); } template<> size_t hash<const wstring&>::operator()(const wstring& __s) const - { return _Fnv_hash::hash(__s.data(), __s.length() * sizeof(wchar_t)); } + { return _Hash_impl::hash(__s.data(), __s.length() * sizeof(wchar_t)); } #endif #endif @@ -78,7 +78,7 @@ namespace std size_t hash<error_code>::operator()(error_code __e) const { - const size_t __tmp = std::_Fnv_hash::hash(__e._M_value); - return std::_Fnv_hash::__hash_combine(__e._M_cat, __tmp); + const size_t __tmp = std::_Hash_impl::hash(__e._M_value); + return std::_Hash_impl::__hash_combine(__e._M_cat, __tmp); } } diff --git a/libstdc++-v3/src/hash_bytes.cc b/libstdc++-v3/src/hash_bytes.cc new file mode 100644 index 00000000000..5dfa1eec1d6 --- /dev/null +++ b/libstdc++-v3/src/hash_bytes.cc @@ -0,0 +1,184 @@ +// Definition of _Hash_bytes. -*- C++ -*- + +// Copyright (C) 2010 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +// This file defines Hash_bytes, a primitive used for defining hash +// functions. Based on public domain MurmurHashUnaligned2, by Austin +// Appleby. http://murmurhash.googlepages.com/ + +// This file also defines _Fnv_hash_bytes, another primitive with +// exactly the same interface but using a different hash algorithm, +// Fowler / Noll / Vo (FNV) Hash (type FNV-1a). The Murmur hash +// function apears to be better in both speed and hash quality, and +// FNV is provided primarily for backward compatibility. + +#include <cstring> +#include <bits/functional_hash.h> + +namespace +{ + inline std::size_t + unaligned_load(const char* p) + { + std::size_t result; + std::memcpy(&result, p, sizeof(result)); + return result; + } + + // Loads n bytes, where 1 <= n < 8. + inline std::size_t + load_bytes(const char* p, int n) + { + size_t result = 0; + --n; + do + result = (result << 8) + static_cast<unsigned char>(p[n]); + while (--n >= 0); + return result; + } + + inline std::size_t + shift_mix(std::size_t v) + { return v ^ (v >> 47);} +} + +namespace std +{ +#if __SIZEOF_SIZE_T__ == 4 + + // Implementation of Murmur hash for 32-bit size_t. + size_t + _Hash_bytes(const void* ptr, size_t len, size_t seed) + { + const size_t m = 0x5bd1e995; + size_t hash = seed ^ len; + const char* buf = static_cast<const char*>(ptr); + + // Mix 4 bytes at a time into the hash. + while(len >= 4) + { + size_t k = unaligned_load(buf); + k *= m; + k ^= k >> 24; + k *= m; + hash *= m; + hash ^= k; + buf += 4; + len -= 4; + } + + // Handle the last few bytes of the input array. + switch(len) + { + case 3: + hash ^= static_cast<unsigned char>(buf[2]) << 16; + case 2: + hash ^= static_cast<unsigned char>(buf[1]) << 8; + case 1: + hash ^= static_cast<unsigned char>(buf[0]); + hash *= m; + }; + + // Do a few final mixes of the hash. + hash ^= hash >> 13; + hash *= m; + hash ^= hash >> 15; + return hash; + } + + // Implementation of FNV hash for 32-bit size_t. + size_t + _Fnv_hash_bytes(const void* ptr, size_t len, size_t hash) + { + const char* cptr = static_cast<const char*>(ptr); + for (; len; --len) + { + hash ^= static_cast<size_t>(*cptr++); + hash *= static_cast<size_t>(16777619UL); + } + return hash; + } + +#elif __SIZEOF_SIZE_T__ == 8 + + // Implementation of Murmur hash for 64-bit size_t. + size_t + _Hash_bytes(const void* ptr, size_t len, size_t seed) + { + static const size_t mul = (0xc6a4a793UL << 32UL) + 0x5bd1e995UL; + const char* const buf = static_cast<const char*>(ptr); + + // Remove the bytes not divisible by the sizeof(size_t). This + // allows the main loop to process the data as 64-bit integers. + const int len_aligned = len & ~0x7; + const char* const end = buf + len_aligned; + size_t hash = seed ^ (len * mul); + for (const char* p = buf; p != end; p += 8) + { + const size_t data = shift_mix(unaligned_load(p) * mul) * mul; + hash ^= data; + hash *= mul; + } + if ((len & 0x7) != 0) + { + const size_t data = load_bytes(end, len & 0x7); + hash ^= data; + hash *= mul; + } + hash = shift_mix(hash) * mul; + hash = shift_mix(hash); + return hash; + } + + // Implementation of FNV hash for 64-bit size_t. + size_t + _Fnv_hash_bytes(const void* ptr, size_t len, size_t hash) + { + const char* cptr = static_cast<const char*>(ptr); + for (; len; --len) + { + hash ^= static_cast<size_t>(*cptr++); + hash *= static_cast<size_t>(1099511628211ULL); + } + return hash; + } + +#else + + // Dummy hash implementation for unusual sizeof(size_t). + size_t + _Hash_bytes(const void* ptr, size_t len, size_t seed) + { + size_t hash = seed; + const char* cptr = reinterpret_cast<const char*>(ptr); + for (; clength; --clength) + hash = (hash * 131) + *cptr++; + return hash; + } + + size_t + _Fnv_hash_bytes(const void* ptr, size_t len, size_t seed) + { return _Hash_bytes(ptr, len, seed); } + +#endif /* __SIZEOF_SIZE_T__ */ +} |
