order_statistics_imp.hpp

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // Copyright (C) 2005 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
00007 // terms of the GNU General Public License as published by the
00008 // Free Software Foundation; either version 2, or (at your option)
00009 // any later version.
00010 
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 
00016 // You should have received a copy of the GNU General Public License along
00017 // with this library; see the file COPYING.  If not, write to the Free
00018 // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
00019 // USA.
00020 
00021 // As a special exception, you may use this file as part of a free software
00022 // library without restriction.  Specifically, if other files instantiate
00023 // templates or use macros or inline functions from this file, or you compile
00024 // this file and link it with other files to produce an executable, this
00025 // file does not by itself cause the resulting executable to be covered by
00026 // the GNU General Public License.  This exception does not however
00027 // invalidate any other reasons why the executable file might be covered by
00028 // the GNU General Public License.
00029 
00030 // Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL.
00031 
00032 // Permission to use, copy, modify, sell, and distribute this software
00033 // is hereby granted without fee, provided that the above copyright
00034 // notice appears in all copies, and that both that copyright notice and
00035 // this permission notice appear in supporting documentation. None of
00036 // the above authors, nor IBM Haifa Research Laboratories, make any
00037 // representation about the suitability of this software for any
00038 // purpose. It is provided "as is" without express or implied warranty.
00039 
00040 /*
00041  * @file order_statistics_imp.hpp
00042  * Contains forward declarations for order_statistics_key
00043  */
00044 
00045 #ifndef ORDER_STATISTICS_IMP_HPP
00046 #define ORDER_STATISTICS_IMP_HPP
00047 
00048 #define PB_ASSOC_CLASS_T_DEC \
00049     template<class Key, class Allocator>
00050 
00051 #define PB_ASSOC_CLASS_C_DEC \
00052     order_statistics_key< \
00053         Key, \
00054         Allocator>
00055 
00056 PB_ASSOC_CLASS_T_DEC
00057 inline
00058 PB_ASSOC_CLASS_C_DEC::
00059 order_statistics_key(const_key_reference r_key) :
00060   m_key(r_key),
00061   m_rank(1)
00062 { }
00063 
00064 PB_ASSOC_CLASS_T_DEC
00065 inline
00066 PB_ASSOC_CLASS_C_DEC::
00067 operator typename PB_ASSOC_CLASS_C_DEC::key_reference()
00068 {
00069   return (m_key);
00070 }
00071 
00072 PB_ASSOC_CLASS_T_DEC
00073 inline
00074 PB_ASSOC_CLASS_C_DEC::
00075 operator typename PB_ASSOC_CLASS_C_DEC::key_type() const
00076 {
00077   return (m_key);
00078 }
00079 
00080 #undef PB_ASSOC_CLASS_T_DEC
00081 
00082 #undef PB_ASSOC_CLASS_C_DEC
00083 
00084 #define PB_ASSOC_CLASS_T_DEC \
00085     template<class Cmp_Fn, class Allocator>
00086 
00087 #define PB_ASSOC_CLASS_C_DEC \
00088     order_statistics_key_cmp< \
00089         Cmp_Fn, \
00090         Allocator>
00091 
00092 PB_ASSOC_CLASS_T_DEC
00093 inline
00094 PB_ASSOC_CLASS_C_DEC::
00095 order_statistics_key_cmp()
00096 { }
00097 
00098 PB_ASSOC_CLASS_T_DEC
00099 inline
00100 PB_ASSOC_CLASS_C_DEC::
00101 order_statistics_key_cmp(const Cmp_Fn& r_cmp_fn) :
00102   Cmp_Fn(r_cmp_fn)
00103 { }
00104 
00105 PB_ASSOC_CLASS_T_DEC
00106 inline bool
00107 PB_ASSOC_CLASS_C_DEC::
00108 operator()(const_key_reference r_lhs_key, const_key_reference r_rhs_key) const
00109 {
00110   return Cmp_Fn::operator()((key_type)r_lhs_key, (key_type)r_rhs_key);
00111 }
00112 
00113 PB_ASSOC_CLASS_T_DEC
00114 inline typename PB_ASSOC_CLASS_C_DEC::cmp_fn& 
00115 PB_ASSOC_CLASS_C_DEC::
00116 get_cmp_fn()
00117 {
00118   return (*this);
00119 }
00120 
00121 PB_ASSOC_CLASS_T_DEC
00122 inline const typename PB_ASSOC_CLASS_C_DEC::cmp_fn& 
00123 PB_ASSOC_CLASS_C_DEC::
00124 get_cmp_fn() const
00125 {
00126   return (*this);
00127 }
00128 
00129 #undef PB_ASSOC_CLASS_T_DEC
00130 
00131 #undef PB_ASSOC_CLASS_C_DEC
00132 
00133 #define PB_ASSOC_CLASS_T_DEC \
00134     template<class Key, class Allocator>
00135 
00136 #define PB_ASSOC_CLASS_C_DEC \
00137     order_statistics_node_updator< \
00138         Key, \
00139         Allocator>
00140 
00141 PB_ASSOC_CLASS_T_DEC
00142 inline void
00143 PB_ASSOC_CLASS_C_DEC::
00144 operator()(const_key_pointer p_key, const_key_pointer p_l_child_key, const_key_pointer p_r_child_key)
00145 {
00146   /*
00147    * The left rank is 0 if there is no left child,
00148    *    or the rank of the left child, otherwise.
00149    */
00150   const size_type l_rank =(p_l_child_key == NULL)? 0 : p_l_child_key->m_rank;
00151 
00152   /*
00153    * The right rank is 0 if there is no right child,
00154    *    or the rank of the right child, otherwise.
00155    */
00156   const size_type r_rank =(p_r_child_key == NULL)? 0 : p_r_child_key->m_rank;
00157 
00158   /*
00159    * The rand of the entry is the sumb of the ranks of its
00160    *    children + 1 (for itself).
00161    */
00162   p_key->m_rank = 1 + l_rank + r_rank;
00163 }
00164 
00165 PB_ASSOC_CLASS_T_DEC
00166 inline void
00167 PB_ASSOC_CLASS_C_DEC::
00168 swap(PB_ASSOC_CLASS_C_DEC& /*r_other*/)
00169 { }
00170 
00171 #undef PB_ASSOC_CLASS_T_DEC
00172 
00173 #undef PB_ASSOC_CLASS_C_DEC
00174 
00175 #define PB_ASSOC_CLASS_T_DEC \
00176     template<class Cntnr>
00177 
00178 #define PB_ASSOC_CLASS_C_DEC \
00179     find_by_order< \
00180         Cntnr>
00181 
00182 PB_ASSOC_CLASS_T_DEC
00183 inline typename PB_ASSOC_CLASS_C_DEC::iterator
00184 PB_ASSOC_CLASS_C_DEC::
00185 operator()(Cntnr& r_c, size_type order) const
00186 {
00187   return find(r_c, order);
00188 }
00189 
00190 PB_ASSOC_CLASS_T_DEC
00191 inline typename PB_ASSOC_CLASS_C_DEC::const_iterator
00192 PB_ASSOC_CLASS_C_DEC::
00193 operator()(const Cntnr& r_c, size_type order) const
00194 {
00195   return find(r_c, order);
00196 }
00197 
00198 PB_ASSOC_CLASS_T_DEC
00199 inline typename PB_ASSOC_CLASS_C_DEC::const_iterator
00200 PB_ASSOC_CLASS_C_DEC::
00201 find(const Cntnr& r_c, size_type order)
00202 {
00203   if (order > r_c.size())
00204     return (r_c.end());
00205 
00206   /*
00207    * Start at the top of the tree.
00208    */
00209   typename Cntnr::const_node_iterator it = r_c.node_begin();
00210 
00211   /*
00212    * Loop up to a leaf.
00213    */
00214   while (it != r_c.node_end())
00215     {
00216       typename Cntnr::const_node_iterator l_it = it.l_child();
00217 
00218       /*
00219        * The order of the element, o, is the rank of the left
00220        *    child (for the entry itself).
00221        */
00222       const size_type o = (l_it == r_c.node_end())?
00223     0 :(*l_it)->m_rank;
00224 
00225       /*
00226        * If the current order, o, is the order requested,
00227        *    the key has been found.
00228        */
00229       if (order == o)
00230     return (*it);
00231       /*
00232        * If the current order, o, is larger than the order requested,
00233        *    we should move to the left subtree.
00234        */
00235       else if (order < o)
00236     it = l_it;
00237       /*
00238        * Otherwise adujst the requested order and move to the right subtree.
00239        */
00240       else
00241     {
00242       order -= o + 1;
00243 
00244       it = it.r_child();
00245     }
00246     }
00247 
00248   return (r_c.end());
00249 }
00250 
00251 PB_ASSOC_CLASS_T_DEC
00252 inline typename PB_ASSOC_CLASS_C_DEC::iterator
00253 PB_ASSOC_CLASS_C_DEC::
00254 find(Cntnr& r_c, size_type order)
00255 {
00256   if (order > r_c.size())
00257     return (r_c.end());
00258 
00259   /*
00260    * Start at the top of the tree.
00261    */
00262   typename Cntnr::node_iterator it = r_c.node_begin();
00263 
00264   /*
00265    * Loop up to a leaf.
00266    */
00267   while (it != r_c.node_end())
00268     {
00269       typename Cntnr::node_iterator l_it = it.l_child();
00270 
00271       /*
00272        * The order of the element, o, is the rank of the left
00273        *    child (for the entry itself).
00274        */
00275       const size_type o = (l_it == r_c.node_end())?
00276     0 :
00277     r_c.extract_key(*(*l_it)).m_rank;
00278 
00279       /*
00280        * If the current order, o, is the order requested,
00281        *    the key has been found.
00282        */
00283       if (order == o)
00284     return (*it);
00285       /*
00286        * If the current order, o, is larger than the order requested,
00287        *    we should move to the left subtree.
00288        */
00289       else if (order < o)
00290     it = l_it;
00291       /*
00292        * Otherwise adujst the requested order and move to the right subtree.
00293        */
00294       else
00295     {
00296       order -= o + 1;
00297 
00298       it = it.r_child();
00299     }
00300     }
00301 
00302   return (r_c.end());
00303 }
00304 
00305 #undef PB_ASSOC_CLASS_T_DEC
00306 
00307 #undef PB_ASSOC_CLASS_C_DEC
00308 
00309 #define PB_ASSOC_CLASS_T_DEC \
00310     template<class Cntnr>
00311 
00312 #define PB_ASSOC_CLASS_C_DEC \
00313     order_by_key< \
00314         Cntnr>
00315 
00316 PB_ASSOC_CLASS_T_DEC
00317 inline typename PB_ASSOC_CLASS_C_DEC::size_type
00318 PB_ASSOC_CLASS_C_DEC::
00319 operator()(const Cntnr& r_c, const underlying_key_type& r_key) const
00320 {
00321   /*
00322    * The logic here is similar to that in order_by_key.
00323    */
00324 
00325   typename Cntnr::const_node_iterator it = r_c.node_begin();
00326 
00327   size_type ord = 0;
00328 
00329   while (it != r_c.node_end())
00330     {
00331       typename Cntnr::const_node_iterator l_it = it.l_child();
00332 
00333       if (r_c.get_cmp_fn().get_cmp_fn()(
00334                     r_key,
00335                     r_c.extract_key(*(*it)).m_key))
00336     it = l_it;
00337       else if (r_c.get_cmp_fn().get_cmp_fn()(
00338                          r_c.extract_key(*(*it)).m_key,
00339                          r_key))
00340     {
00341 
00342       ord += (l_it == r_c.node_end())?
00343         1 :
00344         1 + r_c.extract_key(*(*l_it)).m_rank;
00345 
00346       it = it.r_child();
00347     }
00348       else
00349     {
00350       ord += (l_it == r_c.node_end())?
00351         0 :
00352         r_c.extract_key(*(*l_it)).m_rank;
00353 
00354       it = r_c.node_end();
00355     }
00356     }
00357 
00358   return (ord);
00359 }
00360 
00361 #undef PB_ASSOC_CLASS_T_DEC
00362 
00363 #undef PB_ASSOC_CLASS_C_DEC
00364 
00365 #define PB_ASSOC_CLASS_T_DEC \
00366     template<class Cntnr, class Allocator>
00367 
00368 #define PB_ASSOC_CLASS_C_DEC \
00369     order_statistics_key_verifier< \
00370         Cntnr, \
00371         Allocator>
00372 
00373 template<class Cntnr, class Allocator = std::allocator<char> >
00374 class order_statistics_key_verifier
00375 {
00376 public:
00377   typedef Cntnr map;
00378 
00379   typedef Allocator allocator;
00380 
00381   typedef typename allocator::size_type size_type;
00382 
00383   typedef
00384   typename allocator::template rebind<map>::other::const_reference
00385   const_map_reference;
00386 
00387 public:
00388   bool
00389   operator()(const Cntnr& r_c) const;
00390 
00391 private:
00392   typedef typename Cntnr::const_node_iterator const_node_iterator;
00393 
00394   typedef typename Cntnr::const_iterator cntnr_const_it;
00395 
00396   typedef std::pair<bool, size_type> stat;
00397 
00398 private:
00399   static stat
00400   verify_imp(const_node_iterator it, const_node_iterator end_it)
00401   {
00402     if (it == end_it)
00403       return (std::make_pair(true, 0));
00404 
00405     const stat l_ret =
00406       verify_imp(it.l_child(), end_it);
00407 
00408     const stat r_ret =
00409       verify_imp(it.r_child(), end_it);
00410 
00411     if (!l_ret.first || !r_ret.first)
00412       return (std::make_pair(false, 0));
00413 
00414     if ((*it)->m_rank != 1 + l_ret.second + r_ret.second)
00415       return (std::make_pair(false, 0));
00416 
00417     return (std::make_pair(true, (*it)->m_rank));
00418   }
00419 };
00420 
00421 PB_ASSOC_CLASS_T_DEC
00422 bool
00423 PB_ASSOC_CLASS_C_DEC::
00424 operator()(const Cntnr& r_c) const
00425 {
00426   const stat top_stat =
00427     verify_imp(r_c.node_begin(), r_c.node_end());
00428 
00429   return (top_stat.first);
00430 }
00431 
00432 #undef PB_ASSOC_CLASS_T_DEC
00433 
00434 #undef PB_ASSOC_CLASS_C_DEC
00435 
00436 #endif // #ifndef ORDER_STATISTICS_IMP_HPP

Generated on Tue Feb 2 16:56:20 2010 for GNU C++ STL by  doxygen 1.4.7