diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 7ab1fca13bb2b8d6f6f169a3e0f3109c925c8f7e..18bd7701919843fad3907ba3cc7e3c282b5f0217 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,11 @@ +2005-07-13 Paolo Carlini <pcarlini@suse.de> + + PR libstdc++/21193 (string & wstring) + * include/tr1/functional (hash<string>, hash<wstring>): + Reimplement using the FNV hash. + + * include/tr1/functional: Trivial formatting fixes. + 2005-07-11 Paolo Carlini <pcarlini@suse.de> * include/bits/ostream.tcc (basic_ostream<>::operator<<(long), diff --git a/libstdc++-v3/include/tr1/functional b/libstdc++-v3/include/tr1/functional index abe92e3bf237f70b7fb87598eced8171607114c9..6866357c864ded85fee946df2ac529ae736657cc 100644 --- a/libstdc++-v3/include/tr1/functional +++ b/libstdc++-v3/include/tr1/functional @@ -1090,15 +1090,19 @@ namespace tr1 #undef _GLIBCXX_JOIN2 #undef _GLIBCXX_JOIN -// Definition of default hash function std::tr1::hash<>. The types for -// which std::tr1::hash<T> is defined is in clause 6.3.3. of the PDTR. - - template <typename T> struct hash; - - #define tr1_hashtable_define_trivial_hash(T) \ - template <> struct hash<T> { \ - std::size_t operator()(T val) const { return static_cast<std::size_t>(val); } \ - } \ + // Definition of default hash function std::tr1::hash<>. The types for + // which std::tr1::hash<T> is defined is in clause 6.3.3. of the PDTR. + template<typename T> + struct hash; + +#define tr1_hashtable_define_trivial_hash(T) \ + template<> \ + struct hash<T> \ + { \ + std::size_t \ + operator()(T val) const \ + { return static_cast<std::size_t>(val); } \ + } tr1_hashtable_define_trivial_hash(bool); tr1_hashtable_define_trivial_hash(char); @@ -1116,44 +1120,85 @@ namespace tr1 tr1_hashtable_define_trivial_hash(double); tr1_hashtable_define_trivial_hash(long double); - #undef tr1_hashtable_define_trivial_hash +#undef tr1_hashtable_define_trivial_hash + + template<typename T> + struct hash<T*> + { + std::size_t + operator()(T* p) const + { return reinterpret_cast<std::size_t>(p); } + }; + + // Fowler / Noll / Vo (FNV) Hash (type FNV-1a) + // (used by the next specializations of std::tr1::hash<>) - template <typename T> - struct hash<T*> { - std::size_t operator()(T* p) const { - return reinterpret_cast<std::size_t>(p); + // Dummy generic implementation (for sizeof(size_t) != 4,8). + template<std::size_t = sizeof(std::size_t)> + struct Fnv_hash + { + static std::size_t + hash(const char* first, std::size_t length) + { + std::size_t result = 0; + for (; length > 0; --length) + result = (result * 131) + *first++; + return result; } }; - // ??? We can probably find a better hash function than this (i.e. one - // that vectorizes better and that produces a more uniform distribution). + template<> + struct Fnv_hash<4> + { + static std::size_t + hash(const char* first, std::size_t length) + { + std::size_t result = 2166136261UL; + for (; length > 0; --length) + { + result ^= (std::size_t)*first++; + result *= 16777619UL; + } + return result; + } + }; + + template<> + struct Fnv_hash<8> + { + static std::size_t + hash(const char* first, std::size_t length) + { + std::size_t result = 14695981039346656037ULL; + for (; length > 0; --length) + { + result ^= (std::size_t)*first++; + result *= 1099511628211ULL; + } + return result; + } + }; // XXX String hash probably shouldn't be an inline member function, // since it's nontrivial. Once we have the framework for TR1 .cc // files, this should go in one. - - template <> + template<> struct hash<std::string> { - std::size_t operator()(const std::string& s) const - { - std::size_t result = 0; - for (std::string::const_iterator i = s.begin(); i != s.end(); ++i) - result = (result * 131) + *i; - return result; - } + std::size_t + operator()(const std::string& s) const + { return Fnv_hash<>::hash(s.data(), s.length()); } }; #ifdef _GLIBCXX_USE_WCHAR_T - template <> + template<> struct hash<std::wstring> { - std::size_t operator()(const std::wstring& s) const + std::size_t + operator()(const std::wstring& s) const { - std::size_t result = 0; - for (std::wstring::const_iterator i = s.begin(); i != s.end(); ++i) - result = (result * 131) + *i; - return result; + return Fnv_hash<>::hash(reinterpret_cast<const char*>(s.data()), + s.length() * sizeof(wchar_t)); } }; #endif