1*f8a1b7d9SAlexander Kabaev // TR1 functional -*- C++ -*- 2*f8a1b7d9SAlexander Kabaev 3*f8a1b7d9SAlexander Kabaev // Copyright (C) 2007 Free Software Foundation, Inc. 4*f8a1b7d9SAlexander Kabaev // 5*f8a1b7d9SAlexander Kabaev // This file is part of the GNU ISO C++ Library. This library is free 6*f8a1b7d9SAlexander Kabaev // software; you can redistribute it and/or modify it under the 7*f8a1b7d9SAlexander Kabaev // terms of the GNU General Public License as published by the 8*f8a1b7d9SAlexander Kabaev // Free Software Foundation; either version 2, or (at your option) 9*f8a1b7d9SAlexander Kabaev // any later version. 10*f8a1b7d9SAlexander Kabaev 11*f8a1b7d9SAlexander Kabaev // This library is distributed in the hope that it will be useful, 12*f8a1b7d9SAlexander Kabaev // but WITHOUT ANY WARRANTY; without even the implied warranty of 13*f8a1b7d9SAlexander Kabaev // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*f8a1b7d9SAlexander Kabaev // GNU General Public License for more details. 15*f8a1b7d9SAlexander Kabaev 16*f8a1b7d9SAlexander Kabaev // You should have received a copy of the GNU General Public License along 17*f8a1b7d9SAlexander Kabaev // with this library; see the file COPYING. If not, write to the Free 18*f8a1b7d9SAlexander Kabaev // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 19*f8a1b7d9SAlexander Kabaev // USA. 20*f8a1b7d9SAlexander Kabaev 21*f8a1b7d9SAlexander Kabaev // As a special exception, you may use this file as part of a free software 22*f8a1b7d9SAlexander Kabaev // library without restriction. Specifically, if other files instantiate 23*f8a1b7d9SAlexander Kabaev // templates or use macros or inline functions from this file, or you compile 24*f8a1b7d9SAlexander Kabaev // this file and link it with other files to produce an executable, this 25*f8a1b7d9SAlexander Kabaev // file does not by itself cause the resulting executable to be covered by 26*f8a1b7d9SAlexander Kabaev // the GNU General Public License. This exception does not however 27*f8a1b7d9SAlexander Kabaev // invalidate any other reasons why the executable file might be covered by 28*f8a1b7d9SAlexander Kabaev // the GNU General Public License. 29*f8a1b7d9SAlexander Kabaev 30*f8a1b7d9SAlexander Kabaev /** @file tr1/functional_hash.h 31*f8a1b7d9SAlexander Kabaev * This is an internal header file, included by other library headers. 32*f8a1b7d9SAlexander Kabaev * You should not attempt to use it directly. 33*f8a1b7d9SAlexander Kabaev */ 34*f8a1b7d9SAlexander Kabaev 35*f8a1b7d9SAlexander Kabaev #ifndef _TR1_FUNCTIONAL_HASH_H 36*f8a1b7d9SAlexander Kabaev #define _TR1_FUNCTIONAL_HASH_H 1 37*f8a1b7d9SAlexander Kabaev 38*f8a1b7d9SAlexander Kabaev #include <string> 39*f8a1b7d9SAlexander Kabaev #include <cmath> // for std::frexp 40*f8a1b7d9SAlexander Kabaev 41*f8a1b7d9SAlexander Kabaev namespace std 42*f8a1b7d9SAlexander Kabaev { 43*f8a1b7d9SAlexander Kabaev _GLIBCXX_BEGIN_NAMESPACE(tr1) 44*f8a1b7d9SAlexander Kabaev 45*f8a1b7d9SAlexander Kabaev // Definition of default hash function std::tr1::hash<>. The types for 46*f8a1b7d9SAlexander Kabaev // which std::tr1::hash<T> is defined is in clause 6.3.3. of the PDTR. 47*f8a1b7d9SAlexander Kabaev template<typename T> 48*f8a1b7d9SAlexander Kabaev struct hash; 49*f8a1b7d9SAlexander Kabaev 50*f8a1b7d9SAlexander Kabaev #define _TR1_hashtable_define_trivial_hash(_Tp) \ 51*f8a1b7d9SAlexander Kabaev template<> \ 52*f8a1b7d9SAlexander Kabaev struct hash<_Tp> \ 53*f8a1b7d9SAlexander Kabaev : public std::unary_function<_Tp, std::size_t> \ 54*f8a1b7d9SAlexander Kabaev { \ 55*f8a1b7d9SAlexander Kabaev std::size_t \ 56*f8a1b7d9SAlexander Kabaev operator()(_Tp __val) const \ 57*f8a1b7d9SAlexander Kabaev { return static_cast<std::size_t>(__val); } \ 58*f8a1b7d9SAlexander Kabaev } 59*f8a1b7d9SAlexander Kabaev 60*f8a1b7d9SAlexander Kabaev _TR1_hashtable_define_trivial_hash(bool); 61*f8a1b7d9SAlexander Kabaev _TR1_hashtable_define_trivial_hash(char); 62*f8a1b7d9SAlexander Kabaev _TR1_hashtable_define_trivial_hash(signed char); 63*f8a1b7d9SAlexander Kabaev _TR1_hashtable_define_trivial_hash(unsigned char); 64*f8a1b7d9SAlexander Kabaev _TR1_hashtable_define_trivial_hash(wchar_t); 65*f8a1b7d9SAlexander Kabaev _TR1_hashtable_define_trivial_hash(short); 66*f8a1b7d9SAlexander Kabaev _TR1_hashtable_define_trivial_hash(int); 67*f8a1b7d9SAlexander Kabaev _TR1_hashtable_define_trivial_hash(long); 68*f8a1b7d9SAlexander Kabaev _TR1_hashtable_define_trivial_hash(long long); 69*f8a1b7d9SAlexander Kabaev _TR1_hashtable_define_trivial_hash(unsigned short); 70*f8a1b7d9SAlexander Kabaev _TR1_hashtable_define_trivial_hash(unsigned int); 71*f8a1b7d9SAlexander Kabaev _TR1_hashtable_define_trivial_hash(unsigned long); 72*f8a1b7d9SAlexander Kabaev _TR1_hashtable_define_trivial_hash(unsigned long long); 73*f8a1b7d9SAlexander Kabaev 74*f8a1b7d9SAlexander Kabaev #undef _TR1_hashtable_define_trivial_hash 75*f8a1b7d9SAlexander Kabaev 76*f8a1b7d9SAlexander Kabaev template<typename _Tp> 77*f8a1b7d9SAlexander Kabaev struct hash<_Tp*> 78*f8a1b7d9SAlexander Kabaev : public std::unary_function<_Tp*, std::size_t> 79*f8a1b7d9SAlexander Kabaev { 80*f8a1b7d9SAlexander Kabaev std::size_t 81*f8a1b7d9SAlexander Kabaev operator()(_Tp* __p) const 82*f8a1b7d9SAlexander Kabaev { return reinterpret_cast<std::size_t>(__p); } 83*f8a1b7d9SAlexander Kabaev }; 84*f8a1b7d9SAlexander Kabaev 85*f8a1b7d9SAlexander Kabaev // Fowler / Noll / Vo (FNV) Hash (type FNV-1a) 86*f8a1b7d9SAlexander Kabaev // (used by the next specializations of std::tr1::hash<>) 87*f8a1b7d9SAlexander Kabaev 88*f8a1b7d9SAlexander Kabaev // Dummy generic implementation (for sizeof(size_t) != 4, 8). 89*f8a1b7d9SAlexander Kabaev template<std::size_t = sizeof(std::size_t)> 90*f8a1b7d9SAlexander Kabaev struct _Fnv_hash 91*f8a1b7d9SAlexander Kabaev { 92*f8a1b7d9SAlexander Kabaev static std::size_t 93*f8a1b7d9SAlexander Kabaev hash(const char* __first, std::size_t __length) 94*f8a1b7d9SAlexander Kabaev { 95*f8a1b7d9SAlexander Kabaev std::size_t __result = 0; 96*f8a1b7d9SAlexander Kabaev for (; __length > 0; --__length) 97*f8a1b7d9SAlexander Kabaev __result = (__result * 131) + *__first++; 98*f8a1b7d9SAlexander Kabaev return __result; 99*f8a1b7d9SAlexander Kabaev } 100*f8a1b7d9SAlexander Kabaev }; 101*f8a1b7d9SAlexander Kabaev 102*f8a1b7d9SAlexander Kabaev template<> 103*f8a1b7d9SAlexander Kabaev struct _Fnv_hash<4> 104*f8a1b7d9SAlexander Kabaev { 105*f8a1b7d9SAlexander Kabaev static std::size_t 106*f8a1b7d9SAlexander Kabaev hash(const char* __first, std::size_t __length) 107*f8a1b7d9SAlexander Kabaev { 108*f8a1b7d9SAlexander Kabaev std::size_t __result = static_cast<std::size_t>(2166136261UL); 109*f8a1b7d9SAlexander Kabaev for (; __length > 0; --__length) 110*f8a1b7d9SAlexander Kabaev { 111*f8a1b7d9SAlexander Kabaev __result ^= static_cast<std::size_t>(*__first++); 112*f8a1b7d9SAlexander Kabaev __result *= static_cast<std::size_t>(16777619UL); 113*f8a1b7d9SAlexander Kabaev } 114*f8a1b7d9SAlexander Kabaev return __result; 115*f8a1b7d9SAlexander Kabaev } 116*f8a1b7d9SAlexander Kabaev }; 117*f8a1b7d9SAlexander Kabaev 118*f8a1b7d9SAlexander Kabaev template<> 119*f8a1b7d9SAlexander Kabaev struct _Fnv_hash<8> 120*f8a1b7d9SAlexander Kabaev { 121*f8a1b7d9SAlexander Kabaev static std::size_t 122*f8a1b7d9SAlexander Kabaev hash(const char* __first, std::size_t __length) 123*f8a1b7d9SAlexander Kabaev { 124*f8a1b7d9SAlexander Kabaev std::size_t __result = 125*f8a1b7d9SAlexander Kabaev static_cast<std::size_t>(14695981039346656037ULL); 126*f8a1b7d9SAlexander Kabaev for (; __length > 0; --__length) 127*f8a1b7d9SAlexander Kabaev { 128*f8a1b7d9SAlexander Kabaev __result ^= static_cast<std::size_t>(*__first++); 129*f8a1b7d9SAlexander Kabaev __result *= static_cast<std::size_t>(1099511628211ULL); 130*f8a1b7d9SAlexander Kabaev } 131*f8a1b7d9SAlexander Kabaev return __result; 132*f8a1b7d9SAlexander Kabaev } 133*f8a1b7d9SAlexander Kabaev }; 134*f8a1b7d9SAlexander Kabaev 135*f8a1b7d9SAlexander Kabaev // XXX String and floating point hashes probably shouldn't be inline 136*f8a1b7d9SAlexander Kabaev // member functions, since are nontrivial. Once we have the framework 137*f8a1b7d9SAlexander Kabaev // for TR1 .cc files, these should go in one. 138*f8a1b7d9SAlexander Kabaev template<> 139*f8a1b7d9SAlexander Kabaev struct hash<std::string> 140*f8a1b7d9SAlexander Kabaev : public std::unary_function<std::string, std::size_t> 141*f8a1b7d9SAlexander Kabaev { 142*f8a1b7d9SAlexander Kabaev std::size_t 143*f8a1b7d9SAlexander Kabaev operator()(const std::string& __s) const 144*f8a1b7d9SAlexander Kabaev { return _Fnv_hash<>::hash(__s.data(), __s.length()); } 145*f8a1b7d9SAlexander Kabaev }; 146*f8a1b7d9SAlexander Kabaev 147*f8a1b7d9SAlexander Kabaev #ifdef _GLIBCXX_USE_WCHAR_T 148*f8a1b7d9SAlexander Kabaev template<> 149*f8a1b7d9SAlexander Kabaev struct hash<std::wstring> 150*f8a1b7d9SAlexander Kabaev : public std::unary_function<std::wstring, std::size_t> 151*f8a1b7d9SAlexander Kabaev { 152*f8a1b7d9SAlexander Kabaev std::size_t 153*f8a1b7d9SAlexander Kabaev operator()(const std::wstring& __s) const 154*f8a1b7d9SAlexander Kabaev { 155*f8a1b7d9SAlexander Kabaev return _Fnv_hash<>::hash(reinterpret_cast<const char*>(__s.data()), 156*f8a1b7d9SAlexander Kabaev __s.length() * sizeof(wchar_t)); 157*f8a1b7d9SAlexander Kabaev } 158*f8a1b7d9SAlexander Kabaev }; 159*f8a1b7d9SAlexander Kabaev #endif 160*f8a1b7d9SAlexander Kabaev 161*f8a1b7d9SAlexander Kabaev template<> 162*f8a1b7d9SAlexander Kabaev struct hash<float> 163*f8a1b7d9SAlexander Kabaev : public std::unary_function<float, std::size_t> 164*f8a1b7d9SAlexander Kabaev { 165*f8a1b7d9SAlexander Kabaev std::size_t 166*f8a1b7d9SAlexander Kabaev operator()(float __fval) const 167*f8a1b7d9SAlexander Kabaev { 168*f8a1b7d9SAlexander Kabaev std::size_t __result = 0; 169*f8a1b7d9SAlexander Kabaev 170*f8a1b7d9SAlexander Kabaev // 0 and -0 both hash to zero. 171*f8a1b7d9SAlexander Kabaev if (__fval != 0.0f) 172*f8a1b7d9SAlexander Kabaev __result = _Fnv_hash<>::hash(reinterpret_cast<const char*>(&__fval), 173*f8a1b7d9SAlexander Kabaev sizeof(__fval)); 174*f8a1b7d9SAlexander Kabaev return __result; 175*f8a1b7d9SAlexander Kabaev } 176*f8a1b7d9SAlexander Kabaev }; 177*f8a1b7d9SAlexander Kabaev 178*f8a1b7d9SAlexander Kabaev template<> 179*f8a1b7d9SAlexander Kabaev struct hash<double> 180*f8a1b7d9SAlexander Kabaev : public std::unary_function<double, std::size_t> 181*f8a1b7d9SAlexander Kabaev { 182*f8a1b7d9SAlexander Kabaev std::size_t 183*f8a1b7d9SAlexander Kabaev operator()(double __dval) const 184*f8a1b7d9SAlexander Kabaev { 185*f8a1b7d9SAlexander Kabaev std::size_t __result = 0; 186*f8a1b7d9SAlexander Kabaev 187*f8a1b7d9SAlexander Kabaev // 0 and -0 both hash to zero. 188*f8a1b7d9SAlexander Kabaev if (__dval != 0.0) 189*f8a1b7d9SAlexander Kabaev __result = _Fnv_hash<>::hash(reinterpret_cast<const char*>(&__dval), 190*f8a1b7d9SAlexander Kabaev sizeof(__dval)); 191*f8a1b7d9SAlexander Kabaev return __result; 192*f8a1b7d9SAlexander Kabaev } 193*f8a1b7d9SAlexander Kabaev }; 194*f8a1b7d9SAlexander Kabaev 195*f8a1b7d9SAlexander Kabaev // For long double, careful with random padding bits (e.g., on x86, 196*f8a1b7d9SAlexander Kabaev // 10 bytes -> 12 bytes) and resort to frexp. 197*f8a1b7d9SAlexander Kabaev template<> 198*f8a1b7d9SAlexander Kabaev struct hash<long double> 199*f8a1b7d9SAlexander Kabaev : public std::unary_function<long double, std::size_t> 200*f8a1b7d9SAlexander Kabaev { 201*f8a1b7d9SAlexander Kabaev std::size_t 202*f8a1b7d9SAlexander Kabaev operator()(long double __ldval) const 203*f8a1b7d9SAlexander Kabaev { 204*f8a1b7d9SAlexander Kabaev std::size_t __result = 0; 205*f8a1b7d9SAlexander Kabaev 206*f8a1b7d9SAlexander Kabaev int __exponent; 207*f8a1b7d9SAlexander Kabaev __ldval = std::frexp(__ldval, &__exponent); 208*f8a1b7d9SAlexander Kabaev __ldval = __ldval < 0.0l ? -(__ldval + 0.5l) : __ldval; 209*f8a1b7d9SAlexander Kabaev 210*f8a1b7d9SAlexander Kabaev const long double __mult = 211*f8a1b7d9SAlexander Kabaev std::numeric_limits<std::size_t>::max() + 1.0l; 212*f8a1b7d9SAlexander Kabaev __ldval *= __mult; 213*f8a1b7d9SAlexander Kabaev 214*f8a1b7d9SAlexander Kabaev // Try to use all the bits of the mantissa (really necessary only 215*f8a1b7d9SAlexander Kabaev // on 32-bit targets, at least for 80-bit floating point formats). 216*f8a1b7d9SAlexander Kabaev const std::size_t __hibits = (std::size_t)__ldval; 217*f8a1b7d9SAlexander Kabaev __ldval = (__ldval - (long double)__hibits) * __mult; 218*f8a1b7d9SAlexander Kabaev 219*f8a1b7d9SAlexander Kabaev const std::size_t __coeff = 220*f8a1b7d9SAlexander Kabaev (std::numeric_limits<std::size_t>::max() 221*f8a1b7d9SAlexander Kabaev / std::numeric_limits<long double>::max_exponent); 222*f8a1b7d9SAlexander Kabaev 223*f8a1b7d9SAlexander Kabaev __result = __hibits + (std::size_t)__ldval + __coeff * __exponent; 224*f8a1b7d9SAlexander Kabaev 225*f8a1b7d9SAlexander Kabaev return __result; 226*f8a1b7d9SAlexander Kabaev } 227*f8a1b7d9SAlexander Kabaev }; 228*f8a1b7d9SAlexander Kabaev 229*f8a1b7d9SAlexander Kabaev _GLIBCXX_END_NAMESPACE 230*f8a1b7d9SAlexander Kabaev } 231*f8a1b7d9SAlexander Kabaev 232*f8a1b7d9SAlexander Kabaev #endif 233