libstdc++
ranged_hash_fn.hpp
Go to the documentation of this file.
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