Home | History | Annotate | Download | only in binary_heap_
      1 // -*- C++ -*-
      2 
      3 // Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
      4 //
      5 // This file is part of the GNU ISO C++ Library.  This library is free
      6 // software; you can redistribute it and/or modify it under the terms
      7 // of the GNU General Public License as published by the Free Software
      8 // Foundation; either version 3, or (at your option) any later
      9 // version.
     10 
     11 // This library is distributed in the hope that it will be useful, but
     12 // WITHOUT ANY WARRANTY; without even the implied warranty of
     13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14 // General Public License for more details.
     15 
     16 // Under Section 7 of GPL version 3, you are granted additional
     17 // permissions described in the GCC Runtime Library Exception, version
     18 // 3.1, as published by the Free Software Foundation.
     19 
     20 // You should have received a copy of the GNU General Public License and
     21 // a copy of the GCC Runtime Library Exception along with this program;
     22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23 // <http://www.gnu.org/licenses/>.
     24 
     25 // Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL.
     26 
     27 // Permission to use, copy, modify, sell, and distribute this software
     28 // is hereby granted without fee, provided that the above copyright
     29 // notice appears in all copies, and that both that copyright notice
     30 // and this permission notice appear in supporting documentation. None
     31 // of the above authors, nor IBM Haifa Research Laboratories, make any
     32 // representation about the suitability of this software for any
     33 // purpose. It is provided "as is" without express or implied
     34 // warranty.
     35 
     36 /**
     37  * @file erase_fn_imps.hpp
     38  * Contains an implementation class for a binary_heap.
     39  */
     40 
     41 PB_DS_CLASS_T_DEC
     42 void
     43 PB_DS_CLASS_C_DEC::
     44 clear()
     45 {
     46   for (size_type i = 0; i < m_size; ++i)
     47     erase_at(m_a_entries, i, s_no_throw_copies_ind);
     48 
     49   __try
     50     {
     51       const size_type actual_size = resize_policy::get_new_size_for_arbitrary(0);
     52 
     53       entry_pointer a_entries = s_entry_allocator.allocate(actual_size);
     54 
     55       resize_policy::notify_arbitrary(actual_size);
     56 
     57       s_entry_allocator.deallocate(m_a_entries, m_actual_size);
     58 
     59       m_actual_size = actual_size;
     60 
     61       m_a_entries = a_entries;
     62     }
     63   __catch(...)
     64     { }
     65 
     66   m_size = 0;
     67 
     68   _GLIBCXX_DEBUG_ONLY(assert_valid();)
     69     }
     70 
     71 PB_DS_CLASS_T_DEC
     72 void
     73 PB_DS_CLASS_C_DEC::
     74 erase_at(entry_pointer a_entries, size_type i, false_type)
     75 {
     76   a_entries[i]->~value_type();
     77 
     78   s_value_allocator.deallocate(a_entries[i], 1);
     79 }
     80 
     81 PB_DS_CLASS_T_DEC
     82 void
     83 PB_DS_CLASS_C_DEC::
     84 erase_at(entry_pointer, size_type, true_type)
     85 { }
     86 
     87 PB_DS_CLASS_T_DEC
     88 inline void
     89 PB_DS_CLASS_C_DEC::
     90 pop()
     91 {
     92   _GLIBCXX_DEBUG_ONLY(assert_valid();)
     93     _GLIBCXX_DEBUG_ASSERT(!empty());
     94 
     95   erase_at(m_a_entries, 0, s_no_throw_copies_ind);
     96 
     97   std::pop_heap(m_a_entries, m_a_entries + m_size, static_cast<entry_cmp& >(*this));
     98 
     99   resize_for_erase_if_needed();
    100 
    101   _GLIBCXX_DEBUG_ASSERT(m_size > 0);
    102   --m_size;
    103 
    104   _GLIBCXX_DEBUG_ONLY(assert_valid();)
    105     }
    106 
    107 PB_DS_CLASS_T_DEC
    108 template<typename Pred>
    109 typename PB_DS_CLASS_C_DEC::size_type
    110 PB_DS_CLASS_C_DEC::
    111 erase_if(Pred pred)
    112 {
    113   _GLIBCXX_DEBUG_ONLY(assert_valid();)
    114 
    115     typedef
    116     typename entry_pred<
    117     value_type,
    118     Pred,
    119     simple_value,
    120     Allocator>::type
    121     pred_t;
    122 
    123   const size_type left = partition(pred_t(pred));
    124 
    125   _GLIBCXX_DEBUG_ASSERT(m_size >= left);
    126 
    127   const size_type ersd = m_size - left;
    128 
    129   for (size_type i = left; i < m_size; ++i)
    130     erase_at(m_a_entries, i, s_no_throw_copies_ind);
    131 
    132   __try
    133     {
    134       const size_type actual_size =
    135 	resize_policy::get_new_size_for_arbitrary(left);
    136 
    137       entry_pointer a_entries = s_entry_allocator.allocate(actual_size);
    138 
    139       std::copy(m_a_entries, m_a_entries + left, a_entries);
    140 
    141       s_entry_allocator.deallocate(m_a_entries, m_actual_size);
    142 
    143       m_actual_size = actual_size;
    144 
    145       resize_policy::notify_arbitrary(m_actual_size);
    146     }
    147   __catch(...)
    148     { };
    149 
    150   m_size = left;
    151 
    152   std::make_heap(m_a_entries, m_a_entries + m_size, static_cast<entry_cmp& >(*this));
    153 
    154   _GLIBCXX_DEBUG_ONLY(assert_valid();)
    155 
    156     return ersd;
    157 }
    158 
    159 PB_DS_CLASS_T_DEC
    160 inline void
    161 PB_DS_CLASS_C_DEC::
    162 erase(point_iterator it)
    163 {
    164   _GLIBCXX_DEBUG_ONLY(assert_valid();)
    165     _GLIBCXX_DEBUG_ASSERT(!empty());
    166 
    167   const size_type fix_pos = it.m_p_e - m_a_entries;
    168 
    169   std::swap(*it.m_p_e, m_a_entries[m_size - 1]);
    170 
    171   erase_at(m_a_entries, m_size - 1, s_no_throw_copies_ind);
    172 
    173   resize_for_erase_if_needed();
    174 
    175   _GLIBCXX_DEBUG_ASSERT(m_size > 0);
    176   --m_size;
    177 
    178   _GLIBCXX_DEBUG_ASSERT(fix_pos <= m_size);
    179 
    180   if (fix_pos != m_size)
    181     fix(m_a_entries + fix_pos);
    182 
    183   _GLIBCXX_DEBUG_ONLY(assert_valid();)
    184     }
    185 
    186 PB_DS_CLASS_T_DEC
    187 inline void
    188 PB_DS_CLASS_C_DEC::
    189 resize_for_erase_if_needed()
    190 {
    191   if (!resize_policy::resize_needed_for_shrink(m_size))
    192     return;
    193 
    194   __try
    195     {
    196       const size_type new_actual_size =
    197 	resize_policy::get_new_size_for_shrink();
    198 
    199       entry_pointer a_new_entries = s_entry_allocator.allocate(new_actual_size);
    200 
    201       resize_policy::notify_shrink_resize();
    202 
    203       _GLIBCXX_DEBUG_ASSERT(m_size > 0);
    204       std::copy(m_a_entries, m_a_entries + m_size - 1, a_new_entries);
    205 
    206       s_entry_allocator.deallocate(m_a_entries, m_actual_size);
    207 
    208       m_actual_size = new_actual_size;
    209 
    210       m_a_entries = a_new_entries;
    211     }
    212   __catch(...)
    213     { }
    214 }
    215 
    216 PB_DS_CLASS_T_DEC
    217 template<typename Pred>
    218 typename PB_DS_CLASS_C_DEC::size_type
    219 PB_DS_CLASS_C_DEC::
    220 partition(Pred pred)
    221 {
    222   size_type left = 0;
    223   size_type right = m_size - 1;
    224 
    225   while (right + 1 != left)
    226     {
    227       _GLIBCXX_DEBUG_ASSERT(left <= m_size);
    228 
    229       if (!pred(m_a_entries[left]))
    230 	++left;
    231       else if (pred(m_a_entries[right]))
    232 	--right;
    233       else
    234         {
    235 	  _GLIBCXX_DEBUG_ASSERT(left < right);
    236 
    237 	  std::swap(m_a_entries[left], m_a_entries[right]);
    238 
    239 	  ++left;
    240 	  --right;
    241         }
    242     }
    243 
    244   return left;
    245 }
    246 
    247