libstdc++
|
00001 // -*- C++ -*- 00002 00003 // Copyright (C) 2005, 2006, 2009, 2011 Free Software Foundation, Inc. 00004 // 00005 // This file is part of the GNU ISO C++ Library. This library is free 00006 // software; you can redistribute it and/or modify it under the terms 00007 // of the GNU General Public License as published by the Free Software 00008 // Foundation; either version 3, or (at your option) any later 00009 // version. 00010 00011 // This library is distributed in the hope that it will be useful, but 00012 // WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 // General Public License for more details. 00015 00016 // Under Section 7 of GPL version 3, you are granted additional 00017 // permissions described in the GCC Runtime Library Exception, version 00018 // 3.1, as published by the Free Software Foundation. 00019 00020 // You should have received a copy of the GNU General Public License and 00021 // a copy of the GCC Runtime Library Exception along with this program; 00022 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 00023 // <http://www.gnu.org/licenses/>. 00024 00025 // Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL. 00026 00027 // Permission to use, copy, modify, sell, and distribute this software 00028 // is hereby granted without fee, provided that the above copyright 00029 // notice appears in all copies, and that both that copyright notice 00030 // and this permission notice appear in supporting documentation. None 00031 // of the above authors, nor IBM Haifa Research Laboratories, make any 00032 // representation about the suitability of this software for any 00033 // purpose. It is provided "as is" without express or implied 00034 // warranty. 00035 00036 /** 00037 * @file ranged_hash_fn.hpp 00038 * Contains a unified ranged hash functor, allowing the hash tables 00039 * to deal with a single class for ranged hashing. 00040 */ 00041 00042 #ifndef PB_DS_RANGED_HASH_FN_HPP 00043 #define PB_DS_RANGED_HASH_FN_HPP 00044 00045 #include <utility> 00046 #include <debug/debug.h> 00047 00048 namespace __gnu_pbds 00049 { 00050 namespace detail 00051 { 00052 /// Primary template. 00053 template<typename Key, typename Hash_Fn, typename _Alloc, 00054 typename Comb_Hash_Fn, bool Store_Hash> 00055 class ranged_hash_fn; 00056 00057 #define PB_DS_CLASS_T_DEC \ 00058 template<typename Key, typename Hash_Fn, typename _Alloc, \ 00059 typename Comb_Hash_Fn> 00060 00061 #define PB_DS_CLASS_C_DEC \ 00062 ranged_hash_fn<Key, Hash_Fn, _Alloc, Comb_Hash_Fn, false> 00063 00064 /** 00065 * Specialization 1 00066 * The client supplies a hash function and a ranged hash function, 00067 * and requests that hash values not be stored. 00068 **/ 00069 template<typename Key, typename Hash_Fn, typename _Alloc, 00070 typename Comb_Hash_Fn> 00071 class ranged_hash_fn< Key, Hash_Fn, _Alloc, Comb_Hash_Fn, false> 00072 : public Hash_Fn, public Comb_Hash_Fn 00073 { 00074 protected: 00075 typedef typename _Alloc::size_type size_type; 00076 typedef Hash_Fn hash_fn_base; 00077 typedef Comb_Hash_Fn comb_hash_fn_base; 00078 typedef typename _Alloc::template rebind< Key>::other key_allocator; 00079 typedef typename key_allocator::const_reference key_const_reference; 00080 00081 ranged_hash_fn(size_type); 00082 00083 ranged_hash_fn(size_type, const Hash_Fn&); 00084 00085 ranged_hash_fn(size_type, const Hash_Fn&, const Comb_Hash_Fn&); 00086 00087 void 00088 swap(PB_DS_CLASS_C_DEC&); 00089 00090 void 00091 notify_resized(size_type); 00092 00093 inline size_type 00094 operator()(key_const_reference) const; 00095 }; 00096 00097 PB_DS_CLASS_T_DEC 00098 PB_DS_CLASS_C_DEC:: 00099 ranged_hash_fn(size_type size) 00100 { Comb_Hash_Fn::notify_resized(size); } 00101 00102 PB_DS_CLASS_T_DEC 00103 PB_DS_CLASS_C_DEC:: 00104 ranged_hash_fn(size_type size, const Hash_Fn& r_hash_fn) 00105 : Hash_Fn(r_hash_fn) 00106 { Comb_Hash_Fn::notify_resized(size); } 00107 00108 PB_DS_CLASS_T_DEC 00109 PB_DS_CLASS_C_DEC:: 00110 ranged_hash_fn(size_type size, const Hash_Fn& r_hash_fn, 00111 const Comb_Hash_Fn& r_comb_hash_fn) 00112 : Hash_Fn(r_hash_fn), Comb_Hash_Fn(r_comb_hash_fn) 00113 { comb_hash_fn_base::notify_resized(size); } 00114 00115 PB_DS_CLASS_T_DEC 00116 void 00117 PB_DS_CLASS_C_DEC:: 00118 swap(PB_DS_CLASS_C_DEC& other) 00119 { 00120 comb_hash_fn_base::swap(other); 00121 std::swap((Hash_Fn& )(*this), (Hash_Fn& )other); 00122 } 00123 00124 PB_DS_CLASS_T_DEC 00125 void 00126 PB_DS_CLASS_C_DEC:: 00127 notify_resized(size_type size) 00128 { comb_hash_fn_base::notify_resized(size); } 00129 00130 PB_DS_CLASS_T_DEC 00131 inline typename PB_DS_CLASS_C_DEC::size_type 00132 PB_DS_CLASS_C_DEC:: 00133 operator()(key_const_reference r_key) const 00134 { return (comb_hash_fn_base::operator()(hash_fn_base::operator()(r_key)));} 00135 00136 #undef PB_DS_CLASS_T_DEC 00137 #undef PB_DS_CLASS_C_DEC 00138 00139 #define PB_DS_CLASS_T_DEC \ 00140 template<typename Key, typename Hash_Fn, typename _Alloc, \ 00141 typename Comb_Hash_Fn> 00142 00143 #define PB_DS_CLASS_C_DEC \ 00144 ranged_hash_fn<Key,Hash_Fn, _Alloc, Comb_Hash_Fn, true> 00145 00146 /** 00147 * Specialization 2 00148 * The client supplies a hash function and a ranged hash function, 00149 * and requests that hash values be stored. 00150 **/ 00151 template<typename Key, typename Hash_Fn, typename _Alloc, 00152 typename Comb_Hash_Fn> 00153 class ranged_hash_fn<Key, Hash_Fn, _Alloc, Comb_Hash_Fn, true> 00154 : public Hash_Fn, public Comb_Hash_Fn 00155 { 00156 protected: 00157 typedef typename _Alloc::size_type size_type; 00158 typedef std::pair<size_type, size_type> comp_hash; 00159 typedef Hash_Fn hash_fn_base; 00160 typedef Comb_Hash_Fn comb_hash_fn_base; 00161 typedef typename _Alloc::template rebind<Key>::other key_allocator; 00162 typedef typename key_allocator::const_reference key_const_reference; 00163 00164 ranged_hash_fn(size_type); 00165 00166 ranged_hash_fn(size_type, const Hash_Fn&); 00167 00168 ranged_hash_fn(size_type, const Hash_Fn&, const Comb_Hash_Fn&); 00169 00170 void 00171 swap(PB_DS_CLASS_C_DEC&); 00172 00173 void 00174 notify_resized(size_type); 00175 00176 inline comp_hash 00177 operator()(key_const_reference) const; 00178 00179 inline comp_hash 00180 operator()(key_const_reference, size_type) const; 00181 }; 00182 00183 PB_DS_CLASS_T_DEC 00184 PB_DS_CLASS_C_DEC:: 00185 ranged_hash_fn(size_type size) 00186 { Comb_Hash_Fn::notify_resized(size); } 00187 00188 PB_DS_CLASS_T_DEC 00189 PB_DS_CLASS_C_DEC:: 00190 ranged_hash_fn(size_type size, const Hash_Fn& r_hash_fn) : 00191 Hash_Fn(r_hash_fn) 00192 { Comb_Hash_Fn::notify_resized(size); } 00193 00194 PB_DS_CLASS_T_DEC 00195 PB_DS_CLASS_C_DEC:: 00196 ranged_hash_fn(size_type size, const Hash_Fn& r_hash_fn, 00197 const Comb_Hash_Fn& r_comb_hash_fn) 00198 : Hash_Fn(r_hash_fn), Comb_Hash_Fn(r_comb_hash_fn) 00199 { comb_hash_fn_base::notify_resized(size); } 00200 00201 PB_DS_CLASS_T_DEC 00202 void 00203 PB_DS_CLASS_C_DEC:: 00204 swap(PB_DS_CLASS_C_DEC& other) 00205 { 00206 comb_hash_fn_base::swap(other); 00207 std::swap((Hash_Fn& )(*this), (Hash_Fn& )other); 00208 } 00209 00210 PB_DS_CLASS_T_DEC 00211 void 00212 PB_DS_CLASS_C_DEC:: 00213 notify_resized(size_type size) 00214 { comb_hash_fn_base::notify_resized(size); } 00215 00216 PB_DS_CLASS_T_DEC 00217 inline typename PB_DS_CLASS_C_DEC::comp_hash 00218 PB_DS_CLASS_C_DEC:: 00219 operator()(key_const_reference r_key) const 00220 { 00221 const size_type hash = hash_fn_base::operator()(r_key); 00222 return std::make_pair(comb_hash_fn_base::operator()(hash), hash); 00223 } 00224 00225 PB_DS_CLASS_T_DEC 00226 inline typename PB_DS_CLASS_C_DEC::comp_hash 00227 PB_DS_CLASS_C_DEC:: 00228 operator() 00229 #ifdef _GLIBCXX_DEBUG 00230 (key_const_reference r_key, size_type hash) const 00231 #else 00232 (key_const_reference /*r_key*/, size_type hash) const 00233 #endif 00234 { 00235 _GLIBCXX_DEBUG_ASSERT(hash == hash_fn_base::operator()(r_key)); 00236 return std::make_pair(comb_hash_fn_base::operator()(hash), hash); 00237 } 00238 00239 #undef PB_DS_CLASS_T_DEC 00240 #undef PB_DS_CLASS_C_DEC 00241 00242 #define PB_DS_CLASS_T_DEC \ 00243 template<typename Key, typename _Alloc, typename Comb_Hash_Fn> 00244 00245 #define PB_DS_CLASS_C_DEC \ 00246 ranged_hash_fn<Key, null_type, _Alloc, Comb_Hash_Fn, false> 00247 00248 /** 00249 * Specialization 3 00250 * The client does not supply a hash function (by specifying 00251 * null_type as the Hash_Fn parameter), and requests that hash 00252 * values not be stored. 00253 **/ 00254 template<typename Key, typename _Alloc, typename Comb_Hash_Fn> 00255 class ranged_hash_fn<Key, null_type, _Alloc, Comb_Hash_Fn, false> 00256 : public Comb_Hash_Fn 00257 { 00258 protected: 00259 typedef typename _Alloc::size_type size_type; 00260 typedef Comb_Hash_Fn comb_hash_fn_base; 00261 00262 ranged_hash_fn(size_type); 00263 00264 ranged_hash_fn(size_type, const Comb_Hash_Fn&); 00265 00266 ranged_hash_fn(size_type, const null_type&, const Comb_Hash_Fn&); 00267 00268 void 00269 swap(PB_DS_CLASS_C_DEC&); 00270 }; 00271 00272 PB_DS_CLASS_T_DEC 00273 PB_DS_CLASS_C_DEC:: 00274 ranged_hash_fn(size_type size) 00275 { Comb_Hash_Fn::notify_resized(size); } 00276 00277 PB_DS_CLASS_T_DEC 00278 PB_DS_CLASS_C_DEC:: 00279 ranged_hash_fn(size_type size, const Comb_Hash_Fn& r_comb_hash_fn) : 00280 Comb_Hash_Fn(r_comb_hash_fn) 00281 { } 00282 00283 PB_DS_CLASS_T_DEC 00284 PB_DS_CLASS_C_DEC:: 00285 ranged_hash_fn(size_type size, const null_type& r_null_type, 00286 const Comb_Hash_Fn& r_comb_hash_fn) 00287 : Comb_Hash_Fn(r_comb_hash_fn) 00288 { } 00289 00290 PB_DS_CLASS_T_DEC 00291 void 00292 PB_DS_CLASS_C_DEC:: 00293 swap(PB_DS_CLASS_C_DEC& other) 00294 { comb_hash_fn_base::swap(other); } 00295 00296 #undef PB_DS_CLASS_T_DEC 00297 #undef PB_DS_CLASS_C_DEC 00298 00299 #define PB_DS_CLASS_T_DEC \ 00300 template<typename Key, typename _Alloc, typename Comb_Hash_Fn> 00301 00302 #define PB_DS_CLASS_C_DEC \ 00303 ranged_hash_fn<Key, null_type, _Alloc, Comb_Hash_Fn, true> 00304 00305 /** 00306 * Specialization 4 00307 * The client does not supply a hash function (by specifying 00308 * null_type as the Hash_Fn parameter), and requests that hash 00309 * values be stored. 00310 **/ 00311 template<typename Key, typename _Alloc, typename Comb_Hash_Fn> 00312 class ranged_hash_fn<Key, null_type, _Alloc, Comb_Hash_Fn, true> 00313 : public Comb_Hash_Fn 00314 { 00315 protected: 00316 typedef typename _Alloc::size_type size_type; 00317 typedef Comb_Hash_Fn comb_hash_fn_base; 00318 00319 ranged_hash_fn(size_type); 00320 00321 ranged_hash_fn(size_type, const Comb_Hash_Fn&); 00322 00323 ranged_hash_fn(size_type, const null_type&, const Comb_Hash_Fn&); 00324 00325 void 00326 swap(PB_DS_CLASS_C_DEC&); 00327 }; 00328 00329 PB_DS_CLASS_T_DEC 00330 PB_DS_CLASS_C_DEC:: 00331 ranged_hash_fn(size_type size) 00332 { Comb_Hash_Fn::notify_resized(size); } 00333 00334 PB_DS_CLASS_T_DEC 00335 PB_DS_CLASS_C_DEC:: 00336 ranged_hash_fn(size_type size, const Comb_Hash_Fn& r_comb_hash_fn) 00337 : Comb_Hash_Fn(r_comb_hash_fn) 00338 { } 00339 00340 PB_DS_CLASS_T_DEC 00341 PB_DS_CLASS_C_DEC:: 00342 ranged_hash_fn(size_type size, const null_type& r_null_type, 00343 const Comb_Hash_Fn& r_comb_hash_fn) 00344 : Comb_Hash_Fn(r_comb_hash_fn) 00345 { } 00346 00347 PB_DS_CLASS_T_DEC 00348 void 00349 PB_DS_CLASS_C_DEC:: 00350 swap(PB_DS_CLASS_C_DEC& other) 00351 { comb_hash_fn_base::swap(other); } 00352 00353 #undef PB_DS_CLASS_T_DEC 00354 #undef PB_DS_CLASS_C_DEC 00355 00356 } // namespace detail 00357 } // namespace __gnu_pbds 00358 00359 #endif