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