PPL  0.12.1
CO_Tree.cc
Go to the documentation of this file.
00001 /* CO_Tree class implementation.
00002    Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it>
00003    Copyright (C) 2010-2012 BUGSENG srl (http://bugseng.com)
00004 
00005 This file is part of the Parma Polyhedra Library (PPL).
00006 
00007 The PPL is free software; you can redistribute it and/or modify it
00008 under the terms of the GNU General Public License as published by the
00009 Free Software Foundation; either version 3 of the License, or (at your
00010 option) any later version.
00011 
00012 The PPL is distributed in the hope that it will be useful, but WITHOUT
00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00015 for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with this program; if not, write to the Free Software Foundation,
00019 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
00020 
00021 For the most up-to-date information see the Parma Polyhedra Library
00022 site: http://bugseng.com/products/ppl/ . */
00023 
00024 #include "ppl-config.h"
00025 #include "CO_Tree.defs.hh"
00026 
00027 namespace PPL = Parma_Polyhedra_Library;
00028 
00029 PPL::dimension_type
00030 PPL::CO_Tree::external_memory_in_bytes() const {
00031   dimension_type memory_size = 0;
00032   if (reserved_size != 0) {
00033     // Add the size of data[]
00034     memory_size += (reserved_size + 1)*sizeof(data[0]);
00035     // Add the size of indexes[]
00036     memory_size += (reserved_size + 2)*sizeof(indexes[0]);
00037     for (const_iterator itr = begin(), itr_end = end(); itr != itr_end; ++itr)
00038       memory_size += PPL::external_memory_in_bytes(*itr);
00039   }
00040   return memory_size;
00041 }
00042 
00043 PPL::CO_Tree::iterator
00044 PPL::CO_Tree::insert(iterator itr, dimension_type key1) {
00045   PPL_ASSERT(key1 != unused_index);
00046 
00047   if (empty()) {
00048     insert_in_empty_tree(key1, Coefficient_zero());
00049     return iterator(*this);
00050   }
00051 
00052   if (itr == end())
00053     return insert(key1);
00054 
00055   iterator candidate1 = bisect_near(itr, key1);
00056 
00057   if (key1 == candidate1.index())
00058     return candidate1;
00059 
00060   dimension_type candidate2_index = dfs_index(candidate1);
00061 
00062   if (key1 < candidate1.index()) {
00063     --candidate2_index;
00064     while (indexes[candidate2_index] == unused_index)
00065       --candidate2_index;
00066   } else {
00067     ++candidate2_index;
00068     while (indexes[candidate2_index] == unused_index)
00069       ++candidate2_index;
00070   }
00071 
00072   tree_iterator candidate1_node(candidate1, *this);
00073 
00074   PPL_ASSERT(candidate2_index <= reserved_size + 1);
00075 
00076   if (candidate2_index == 0 || candidate2_index > reserved_size)
00077     // Use candidate1
00078     return iterator(insert_precise(key1, Coefficient_zero(),
00079                                    candidate1_node));
00080 
00081   tree_iterator candidate2_node(*this, candidate2_index);
00082 
00083   // Adjacent nodes in an in-order visit of a tree always have different
00084   // heights. This fact can be easily proven by induction on the tree's
00085   // height, using the definition of the in-order layout.
00086   PPL_ASSERT(candidate1_node.get_offset() != candidate2_node.get_offset());
00087 
00088   if (candidate1_node.get_offset() < candidate2_node.get_offset()) {
00089     PPL_ASSERT(candidate1_node.depth() > candidate2_node.depth());
00090     // candidate1_node is deeper in the tree than candidate2_node, so use
00091     // candidate1_node.
00092     return iterator(insert_precise(key1, Coefficient_zero(),
00093                                    candidate1_node));
00094   } else {
00095     PPL_ASSERT(candidate1_node.depth() < candidate2_node.depth());
00096     // candidate2_node is deeper in the tree than candidate1_node, so use
00097     // candidate2_node.
00098     return iterator(insert_precise(key1, Coefficient_zero(),
00099                                     candidate2_node));
00100   }
00101 }
00102 
00103 PPL::CO_Tree::iterator
00104 PPL::CO_Tree::insert(iterator itr, dimension_type key1,
00105                      data_type_const_reference data1) {
00106   PPL_ASSERT(key1 != unused_index);
00107 
00108   if (empty()) {
00109     insert_in_empty_tree(key1, data1);
00110     return iterator(*this);
00111   }
00112 
00113   if (itr == end())
00114     return insert(key1, data1);
00115 
00116   iterator candidate1 = bisect_near(itr, key1);
00117 
00118   if (key1 == candidate1.index()) {
00119     *candidate1 = data1;
00120     return candidate1;
00121   }
00122 
00123   dimension_type candidate2_index = dfs_index(candidate1);
00124 
00125   if (key1 < candidate1.index()) {
00126     --candidate2_index;
00127     while (indexes[candidate2_index] == unused_index)
00128       --candidate2_index;
00129   } else {
00130     ++candidate2_index;
00131     while (indexes[candidate2_index] == unused_index)
00132       ++candidate2_index;
00133   }
00134 
00135   tree_iterator candidate1_node(candidate1, *this);
00136 
00137   if (candidate2_index == 0 || candidate2_index > reserved_size)
00138     // Use candidate1
00139     return iterator(insert_precise(key1, data1, candidate1_node));
00140 
00141   tree_iterator candidate2_node(*this, candidate2_index);
00142 
00143   // Adjacent nodes in an in-order visit of a tree always have different
00144   // heights. This fact can be easily proven by induction on the tree's
00145   // height, using the definition of the in-order layout.
00146   PPL_ASSERT(candidate1_node.get_offset() != candidate2_node.get_offset());
00147 
00148   if (candidate1_node.get_offset() < candidate2_node.get_offset()) {
00149     PPL_ASSERT(candidate1_node.depth() > candidate2_node.depth());
00150     // candidate1_node is deeper in the tree than candidate2_node, so
00151     // use candidate1_node.
00152     return iterator(insert_precise(key1, data1, candidate1_node));
00153   } else {
00154     PPL_ASSERT(candidate1_node.depth() < candidate2_node.depth());
00155     // candidate2_node is deeper in the tree than candidate1_node, so
00156     // use candidate2_node.
00157     return iterator(insert_precise(key1, data1, candidate2_node));
00158   }
00159 }
00160 
00161 void
00162 PPL::CO_Tree::erase_element_and_shift_left(dimension_type key) {
00163   iterator itr = erase(key);
00164   if (itr == end())
00165     return;
00166   dimension_type i = dfs_index(itr);
00167   dimension_type* p = indexes + i;
00168   dimension_type* p_end = indexes + (reserved_size + 1);
00169   for ( ; p != p_end; ++p)
00170     if (*p != unused_index)
00171       --(*p);
00172   PPL_ASSERT(OK());
00173 }
00174 
00175 void
00176 PPL::CO_Tree::increase_keys_from(dimension_type key, dimension_type n) {
00177   if (empty())
00178     return;
00179   dimension_type* p = indexes + reserved_size;
00180   while (*p == unused_index)
00181     --p;
00182   while (p != indexes && *p >= key) {
00183     *p += n;
00184     --p;
00185     while (*p == unused_index)
00186       --p;
00187   }
00188   PPL_ASSERT(OK());
00189 }
00190 
00191 PPL::dimension_type
00192 PPL::CO_Tree::bisect_in(dimension_type first, dimension_type last,
00193                    dimension_type key) const {
00194   PPL_ASSERT(first != 0);
00195   PPL_ASSERT(last <= reserved_size);
00196   PPL_ASSERT(first <= last);
00197   PPL_ASSERT(indexes[first] != unused_index);
00198   PPL_ASSERT(indexes[last] != unused_index);
00199 
00200   while (first < last) {
00201     dimension_type half = (first + last) / 2;
00202     dimension_type new_half = half;
00203 
00204     while (indexes[new_half] == unused_index)
00205       ++new_half;
00206 
00207     if (indexes[new_half] == key)
00208       return new_half;
00209 
00210     if (indexes[new_half] > key) {
00211 
00212       while (indexes[half] == unused_index)
00213         --half;
00214 
00215       last = half;
00216 
00217     } else {
00218 
00219       ++new_half;
00220       while (indexes[new_half] == unused_index)
00221         ++new_half;
00222 
00223       first = new_half;
00224     }
00225   }
00226 
00227   // It is important that last is returned instead of first, because first
00228   // may have increased beyond last, even beyond the original value of last
00229   // at the beginning of this method.
00230   return last;
00231 }
00232 
00233 PPL::dimension_type
00234 PPL::CO_Tree::bisect_near(dimension_type hint, dimension_type key) const {
00235   PPL_ASSERT(hint != 0);
00236   PPL_ASSERT(hint <= reserved_size);
00237   PPL_ASSERT(indexes[hint] != unused_index);
00238 
00239   if (indexes[hint] == key)
00240     return hint;
00241 
00242   dimension_type new_hint;
00243   dimension_type offset = 1;
00244 
00245   if (indexes[hint] > key) {
00246     // The searched element is before `hint'.
00247 
00248     while (true) {
00249 
00250       if (hint <= offset) {
00251         // The searched element is in (0,hint).
00252         new_hint = hint;
00253         hint = 1;
00254         // The searched element is in [hint,new_hint).
00255         while (indexes[hint] == unused_index)
00256           ++hint;
00257         if (indexes[hint] >= key)
00258           return hint;
00259         // The searched element is in (hint,new_hint) and both indexes point
00260         // to valid elements.
00261         break;
00262       } else
00263         new_hint = hint - offset;
00264 
00265       PPL_ASSERT(new_hint > 0);
00266       PPL_ASSERT(new_hint <= reserved_size);
00267 
00268       // Find the element at `new_hint' (or the first after it).
00269       while (indexes[new_hint] == unused_index)
00270         ++new_hint;
00271 
00272       PPL_ASSERT(new_hint <= hint);
00273 
00274       if (indexes[new_hint] == key)
00275         return new_hint;
00276       else
00277         if (indexes[new_hint] < key) {
00278           // The searched element is in (new_hint,hint)
00279           using std::swap;
00280           swap(hint, new_hint);
00281           // The searched element is now in (hint,new_hint).
00282           break;
00283         }
00284 
00285       hint = new_hint;
00286       offset *= 2;
00287     }
00288 
00289   } else {
00290     // The searched element is after `hint'.
00291     while (true) {
00292 
00293       if (hint + offset > reserved_size) {
00294         // The searched element is in (hint,reserved_size+1).
00295         new_hint = reserved_size;
00296         // The searched element is in (hint,new_hint].
00297         while (indexes[new_hint] == unused_index)
00298           --new_hint;
00299         if (indexes[new_hint] <= key)
00300           return new_hint;
00301         // The searched element is in (hint,new_hint) and both indexes point
00302         // to valid elements.
00303         break;
00304       } else
00305         new_hint = hint + offset;
00306 
00307       PPL_ASSERT(new_hint > 0);
00308       PPL_ASSERT(new_hint <= reserved_size);
00309 
00310       // Find the element at `new_hint' (or the first after it).
00311       while (indexes[new_hint] == unused_index)
00312         --new_hint;
00313 
00314       PPL_ASSERT(hint <= new_hint);
00315 
00316       if (indexes[new_hint] == key)
00317         return new_hint;
00318       else
00319         if (indexes[new_hint] > key)
00320           // The searched element is in (hint,new_hint).
00321           break;
00322 
00323       hint = new_hint;
00324       offset *= 2;
00325     }
00326   }
00327   // The searched element is in (hint,new_hint).
00328   PPL_ASSERT(hint > 0);
00329   PPL_ASSERT(hint < new_hint);
00330   PPL_ASSERT(new_hint <= reserved_size);
00331   PPL_ASSERT(indexes[hint] != unused_index);
00332   PPL_ASSERT(indexes[new_hint] != unused_index);
00333 
00334   ++hint;
00335   while (indexes[hint] == unused_index)
00336     ++hint;
00337 
00338   if (hint == new_hint)
00339     return hint;
00340 
00341   --new_hint;
00342   while (indexes[new_hint] == unused_index)
00343     --new_hint;
00344 
00345   PPL_ASSERT(hint <= new_hint);
00346   PPL_ASSERT(indexes[hint] != unused_index);
00347   PPL_ASSERT(indexes[new_hint] != unused_index);
00348 
00349   return bisect_in(hint, new_hint, key);
00350 }
00351 
00352 PPL::CO_Tree::tree_iterator
00353 PPL::CO_Tree::insert_precise(dimension_type key1,
00354                              data_type_const_reference data1,
00355                              tree_iterator itr) {
00356   PPL_ASSERT(key1 != unused_index);
00357   PPL_ASSERT(!empty());
00358 
00359 #ifndef NDEBUG
00360   tree_iterator itr2(*this);
00361   itr2.go_down_searching_key(key1);
00362   PPL_ASSERT(itr == itr2);
00363 #endif
00364 
00365   if (itr.index() == key1) {
00366     *itr = data1;
00367     PPL_ASSERT(OK());
00368     return itr;
00369   }
00370 
00371   if (is_greater_than_ratio(size_ + 1, reserved_size, max_density_percent)) {
00372 
00373     rebuild_bigger_tree();
00374 
00375     // itr was invalidated by the rebuild operation
00376     itr.get_root();
00377     itr.go_down_searching_key(key1);
00378 
00379     PPL_ASSERT(itr.index() != key1);
00380   }
00381 
00382   PPL_ASSERT(!is_greater_than_ratio(size_ + 1, reserved_size,
00383                                     max_density_percent));
00384 
00385   size_++;
00386 
00387   if (!itr.is_leaf()) {
00388     if (key1 < itr.index())
00389       itr.get_left_child();
00390     else
00391       itr.get_right_child();
00392     PPL_ASSERT(itr.index() == unused_index);
00393 
00394     itr.index() = key1;
00395     new (&(*itr)) data_type(data1);
00396 
00397   } else {
00398 
00399     itr = rebalance(itr, key1, data1);
00400 
00401     itr.go_down_searching_key(key1);
00402 
00403     PPL_ASSERT(itr.index() == key1);
00404   }
00405   PPL_ASSERT(OK());
00406 
00407   return itr;
00408 }
00409 
00410 PPL::CO_Tree::iterator
00411 PPL::CO_Tree::erase(tree_iterator itr) {
00412   PPL_ASSERT(itr.index() != unused_index);
00413 
00414   PPL_ASSERT(size_ != 0);
00415 
00416   if (size_ == 1) {
00417     // Deleting the only element of this tree, now it is empty.
00418     clear();
00419     return end();
00420   }
00421 
00422   if (is_less_than_ratio(size_ - 1, reserved_size, min_density_percent)
00423       && !is_greater_than_ratio(size_ - 1, reserved_size/2,
00424                                 max_density_percent)) {
00425 
00426     const dimension_type key = itr.index();
00427 
00428     PPL_ASSERT(!is_greater_than_ratio(size_, reserved_size,
00429                                       max_density_percent));
00430 
00431     rebuild_smaller_tree();
00432     itr.get_root();
00433     itr.go_down_searching_key(key);
00434 
00435     PPL_ASSERT(itr.index() == key);
00436   }
00437 
00438 #ifndef NDEBUG
00439   if (size_ > 1)
00440     PPL_ASSERT(!is_less_than_ratio(size_ - 1, reserved_size,
00441                                    min_density_percent)
00442                || is_greater_than_ratio(size_ - 1, reserved_size/2,
00443                                         max_density_percent));
00444 #endif
00445 
00446   const dimension_type deleted_key = itr.index();
00447   tree_iterator deleted_node = itr;
00448   (*itr).~data_type();
00449   while (true) {
00450     dimension_type& current_key  = itr.index();
00451     data_type&      current_data = *itr;
00452     if (itr.is_leaf())
00453       break;
00454     itr.get_left_child();
00455     if (itr.index() != unused_index)
00456       // The left child has a value.
00457       itr.follow_right_children_with_value();
00458     else {
00459       // The left child has not a value, try the right child.
00460       itr.get_parent();
00461       itr.get_right_child();
00462       if (itr.index() != unused_index)
00463         // The right child has a value.
00464         itr.follow_left_children_with_value();
00465       else {
00466         // The right child has not a value, too.
00467         itr.get_parent();
00468         break;
00469       }
00470     }
00471     using std::swap;
00472     swap(current_key, itr.index());
00473     move_data_element(current_data, *itr);
00474   }
00475 
00476   PPL_ASSERT(itr.index() != unused_index);
00477   itr.index() = unused_index;
00478   --size_;
00479 
00480   PPL_ASSERT(OK());
00481 
00482   itr = rebalance(itr, 0, Coefficient_zero());
00483 
00484   if (itr.get_offset() < deleted_node.get_offset())
00485     // deleted_node is an ancestor of itr
00486     itr = deleted_node;
00487 
00488   itr.go_down_searching_key(deleted_key);
00489 
00490   iterator result(itr);
00491 
00492   if (result.index() < deleted_key)
00493     ++result;
00494 
00495   PPL_ASSERT(OK());
00496   PPL_ASSERT(result == end() || result.index() > deleted_key);
00497 #ifndef NDEBUG
00498   if (!empty()) {
00499     iterator last = end();
00500     --last;
00501     PPL_ASSERT((result == end()) == (last.index() < deleted_key));
00502   }
00503 #endif
00504 
00505   return result;
00506 }
00507 
00508 void
00509 PPL::CO_Tree::init(dimension_type reserved_size1) {
00510 
00511   if (reserved_size1 == 0) {
00512     indexes = NULL;
00513     data = NULL;
00514     size_ = 0;
00515     reserved_size = 0;
00516     max_depth = 0;
00517   } else {
00518     max_depth = integer_log2(reserved_size1) + 1;
00519 
00520     size_ = 0;
00521     reserved_size = (static_cast<dimension_type>(1) << max_depth) - 1;
00522     indexes = new dimension_type[reserved_size + 2];
00523     try {
00524       data = data_allocator.allocate(reserved_size + 1);
00525     } catch (...) {
00526       delete[] indexes;
00527       throw;
00528     }
00529     // Mark all pairs as unused.
00530     for (dimension_type i = 1; i <= reserved_size; ++i)
00531       indexes[i] = unused_index;
00532 
00533     // These are used as markers by iterators.
00534     indexes[0] = 0;
00535     indexes[reserved_size + 1] = 0;
00536   }
00537 
00538   refresh_cached_iterators();
00539 
00540   PPL_ASSERT(structure_OK());
00541 }
00542 
00543 void
00544 PPL::CO_Tree::destroy() {
00545 
00546   if (reserved_size != 0) {
00547     for (dimension_type i = 1; i <= reserved_size; ++i) {
00548       if (indexes[i] != unused_index)
00549         data[i].~data_type();
00550     }
00551 
00552     delete[] indexes;
00553     data_allocator.deallocate(data, reserved_size + 1);
00554   }
00555 }
00556 
00557 bool
00558 PPL::CO_Tree::structure_OK() const {
00559 
00560   if (size_ > reserved_size)
00561     return false;
00562 
00563   if (reserved_size == 0) {
00564     if (indexes != NULL)
00565       return false;
00566     if (data != NULL)
00567       return false;
00568     if (max_depth != 0)
00569       return false;
00570 
00571     return true;
00572   }
00573 
00574   if (reserved_size < 3)
00575     return false;
00576 
00577   if (reserved_size != (static_cast<dimension_type>(1) << max_depth) - 1)
00578     return false;
00579 
00580   if (data == NULL)
00581     return false;
00582 
00583   if (indexes == NULL)
00584     return false;
00585 
00586   if (max_depth == 0)
00587     return false;
00588 
00589   if (size_ == 0) {
00590 
00591     // This const_cast could be removed by adding a const_tree_iterator,
00592     // but it would add much code duplication without a real need.
00593     tree_iterator itr(*const_cast<CO_Tree*>(this));
00594     if (itr.index() != unused_index)
00595       return false;
00596 
00597   } else {
00598     // This const_cast could be removed by adding a const_tree_iterator,
00599     // but it would add much code duplication without a real need.
00600     tree_iterator itr(*const_cast<CO_Tree*>(this));
00601     dimension_type real_size = count_used_in_subtree(itr);
00602     if (real_size != size_)
00603       // There are \p real_size elements in the tree that are reachable by the
00604       // root, but size is \p size.
00605       return false;
00606   }
00607 
00608   if (size_ != 0) {
00609     const_iterator itr = begin();
00610     const_iterator itr_end = end();
00611 
00612     if (itr != itr_end) {
00613       dimension_type last_index = itr.index();
00614       for (++itr; itr != itr_end; ++itr) {
00615         if (last_index >= itr.index())
00616           // Found index \p itr->first after index \p last_index.
00617           return false;
00618         last_index = itr.index();
00619       }
00620     }
00621   }
00622 
00623   if (const_iterator(cached_end) != const_iterator(*this, reserved_size + 1))
00624     return false;
00625   if (cached_const_end != const_iterator(*this, reserved_size + 1))
00626     return false;
00627 
00628   return true;
00629 }
00630 
00631 bool
00632 PPL::CO_Tree::OK() const {
00633 
00634   if (!structure_OK())
00635     return false;
00636 
00637   {
00638     dimension_type real_size = 0;
00639 
00640     for (const_iterator itr = begin(), itr_end = end(); itr != itr_end; ++itr)
00641       ++real_size;
00642 
00643     if (real_size != size_)
00644       // There are \p real_size elements in the tree, but size is \p size.
00645       return false;
00646   }
00647 
00648   if (reserved_size > 0) {
00649     if (is_greater_than_ratio(size_, reserved_size, max_density_percent)
00650         && reserved_size != 3)
00651       // Found too high density.
00652       return false;
00653     if (is_less_than_ratio(size_, reserved_size, min_density_percent)
00654         && !is_greater_than_ratio(size_, reserved_size/2, max_density_percent))
00655       // Found too low density
00656       return false;
00657   }
00658 
00659   return true;
00660 }
00661 
00662 unsigned
00663 PPL::CO_Tree::integer_log2(dimension_type n) {
00664   PPL_ASSERT(n != 0);
00665   unsigned result = 0;
00666   while (n != 1) {
00667     n /= 2;
00668     ++result;
00669   }
00670   return result;
00671 }
00672 
00673 void
00674 PPL::CO_Tree::dump_subtree(tree_iterator itr) {
00675   if (!itr.is_leaf()) {
00676     itr.get_left_child();
00677     dump_subtree(itr);
00678     itr.get_parent();
00679   }
00680   std::cout << "At depth: " << itr.depth();
00681   if (itr.index() == unused_index)
00682     std::cout << " (no data)" << std::endl;
00683   else
00684     std::cout << " pair (" << itr.index() << "," << *itr << ")" << std::endl;
00685   if (!itr.is_leaf()) {
00686     itr.get_right_child();
00687     dump_subtree(itr);
00688     itr.get_parent();
00689   }
00690 }
00691 
00692 void
00693 PPL::CO_Tree::rebuild_bigger_tree() {
00694   if (reserved_size == 0) {
00695     init(3);
00696     PPL_ASSERT(structure_OK());
00697     return;
00698   }
00699 
00700   dimension_type new_reserved_size = reserved_size*2 + 1;
00701 
00702   dimension_type* new_indexes = new dimension_type[new_reserved_size + 2];
00703 
00704   data_type* new_data;
00705 
00706   try {
00707     new_data = data_allocator.allocate(new_reserved_size + 1);
00708   } catch (...) {
00709     delete[] new_indexes;
00710     throw;
00711   }
00712 
00713   new_indexes[1] = unused_index;
00714 
00715   for (dimension_type i = 1, j = 2; i <= reserved_size; ++i, ++j) {
00716     new_indexes[j] = indexes[i];
00717     if (indexes[i] != unused_index)
00718       move_data_element(new_data[j], data[i]);
00719     ++j;
00720     new_indexes[j] = unused_index;
00721   }
00722 
00723   // These are used as markers by iterators.
00724   new_indexes[0] = 0;
00725   new_indexes[new_reserved_size + 1] = 0;
00726 
00727   delete[] indexes;
00728   data_allocator.deallocate(data, reserved_size + 1);
00729 
00730   indexes = new_indexes;
00731   data = new_data;
00732   reserved_size = new_reserved_size;
00733   ++max_depth;
00734 
00735   refresh_cached_iterators();
00736 
00737   PPL_ASSERT(structure_OK());
00738 }
00739 
00740 PPL::CO_Tree::tree_iterator
00741 PPL::CO_Tree::rebalance(tree_iterator itr, dimension_type key,
00742                         data_type_const_reference value) {
00743   // Trees with reserved size 3 need not to be rebalanced.
00744   // This check is needed because they can't be shrunk, so they may violate
00745   // the density thresholds, and this would prevent the following while from
00746   // working correctly.
00747   if (reserved_size == 3) {
00748     PPL_ASSERT(OK());
00749     return tree_iterator(*this);
00750   }
00751   PPL_ASSERT(itr.index() == unused_index || itr.is_leaf());
00752   height_t itr_depth_minus_1 = itr.depth() - 1;
00753   height_t height = max_depth - itr_depth_minus_1;
00754   dimension_type subtree_size;
00755   dimension_type subtree_reserved_size = (static_cast<dimension_type>(1)
00756                                           << height) - 1;
00757   const bool deleting = itr.index() == unused_index;
00758   PPL_ASSERT(deleting || key != unused_index);
00759   if (deleting)
00760     subtree_size = 0;
00761   else
00762     // The existing element and the element with index key we want to add.
00763     subtree_size = 2;
00764 
00765   while (is_greater_than_ratio(subtree_size, subtree_reserved_size,
00766                                max_density_percent
00767                                + ((itr_depth_minus_1
00768                                    * (100 - max_density_percent))
00769                                   / (max_depth - 1)))
00770          || is_less_than_ratio(subtree_size, subtree_reserved_size,
00771                                min_density_percent
00772                                - ((itr_depth_minus_1
00773                                    * (min_density_percent
00774                                       - min_leaf_density_percent))
00775                                   / (max_depth - 1)))) {
00776     // The density in the tree is correct, so the while condition is always
00777     // false for the root.
00778     PPL_ASSERT(itr_depth_minus_1 != 0);
00779     bool is_right_brother = itr.is_right_child();
00780     itr.get_parent();
00781     if (is_right_brother)
00782       itr.get_left_child();
00783     else
00784       itr.get_right_child();
00785     subtree_size += count_used_in_subtree(itr);
00786     itr.get_parent();
00787     PPL_ASSERT(itr.index() != unused_index);
00788     ++subtree_size;
00789     subtree_reserved_size = 2*subtree_reserved_size + 1;
00790     --itr_depth_minus_1;
00791     PPL_ASSERT(itr.depth() - 1 == itr_depth_minus_1);
00792   }
00793 
00794   // Now the subtree rooted at itr has been chosen as the subtree to be
00795   // rebalanced.
00796 
00797   // Step 1: compact elements of this subtree in the rightmost end, from right
00798   //         to left.
00799   dimension_type last_index_in_subtree
00800     = itr.dfs_index() + itr.get_offset() - 1;
00801 
00802   dimension_type first_unused
00803     = compact_elements_in_the_rightmost_end(last_index_in_subtree,
00804                                             subtree_size, key, value,
00805                                             !deleting);
00806 
00807   // Step 2: redistribute the elements, from left to right.
00808   redistribute_elements_in_subtree(itr.dfs_index(), subtree_size,
00809                                    first_unused + 1, key, value,
00810                                    first_unused != last_index_in_subtree
00811                                                    - subtree_size);
00812 
00813   PPL_ASSERT(OK());
00814 
00815   return itr;
00816 }
00817 
00818 PPL::dimension_type
00819 PPL::CO_Tree
00820 ::compact_elements_in_the_rightmost_end(dimension_type last_in_subtree,
00821                                         dimension_type subtree_size,
00822                                         dimension_type key,
00823                                         data_type_const_reference value,
00824                                         bool add_element) {
00825 
00826   PPL_ASSERT(subtree_size != 0);
00827 
00828   PPL_ASSERT(subtree_size != 1 || !add_element);
00829 
00830   dimension_type* last_index_in_subtree = &(indexes[last_in_subtree]);
00831   data_type* last_data_in_subtree = &(data[last_in_subtree]);
00832 
00833   dimension_type* first_unused_index = last_index_in_subtree;
00834   data_type* first_unused_data = last_data_in_subtree;
00835 
00836   while (*last_index_in_subtree == unused_index) {
00837     --last_index_in_subtree;
00838     --last_data_in_subtree;
00839   }
00840 
00841   // From now on, last_index_in_subtree and last_data_in_subtree point to the
00842   // rightmost node with a value in the subtree. first_unused_index and
00843   // first_unused_data point to the rightmost unused node in the subtree.
00844 
00845   if (add_element)
00846     while (subtree_size != 0) {
00847       --subtree_size;
00848       if (last_index_in_subtree == indexes || key > *last_index_in_subtree) {
00849         if (last_index_in_subtree == indexes
00850             || last_index_in_subtree != first_unused_index) {
00851           PPL_ASSERT(first_unused_index != indexes);
00852           PPL_ASSERT(*first_unused_index == unused_index);
00853           *first_unused_index = key;
00854           new (first_unused_data) data_type(value);
00855           --first_unused_index;
00856           --first_unused_data;
00857         }
00858         break;
00859       } else {
00860         if (last_index_in_subtree != first_unused_index) {
00861           PPL_ASSERT(first_unused_index != indexes);
00862           PPL_ASSERT(last_index_in_subtree != indexes);
00863           PPL_ASSERT(*first_unused_index == unused_index);
00864           *first_unused_index = *last_index_in_subtree;
00865           *last_index_in_subtree = unused_index;
00866           move_data_element(*first_unused_data, *last_data_in_subtree);
00867         }
00868         --last_index_in_subtree;
00869         --last_data_in_subtree;
00870         while (*last_index_in_subtree == unused_index) {
00871           --last_index_in_subtree;
00872           --last_data_in_subtree;
00873         }
00874         --first_unused_index;
00875         --first_unused_data;
00876       }
00877     }
00878   while (subtree_size != 0) {
00879     if (last_index_in_subtree != first_unused_index) {
00880       PPL_ASSERT(first_unused_index != indexes);
00881       PPL_ASSERT(last_index_in_subtree != indexes);
00882       PPL_ASSERT(*first_unused_index == unused_index);
00883       *first_unused_index = *last_index_in_subtree;
00884       *last_index_in_subtree = unused_index;
00885       move_data_element(*first_unused_data, *last_data_in_subtree);
00886     }
00887     --last_index_in_subtree;
00888     --last_data_in_subtree;
00889     while (*last_index_in_subtree == unused_index) {
00890       --last_index_in_subtree;
00891       --last_data_in_subtree;
00892     }
00893     --first_unused_index;
00894     --first_unused_data;
00895     --subtree_size;
00896   }
00897 
00898   ptrdiff_t distance = first_unused_index - indexes;
00899   PPL_ASSERT(distance >= 0);
00900   return static_cast<dimension_type>(distance);
00901 }
00902 
00903 void
00904 PPL::CO_Tree::redistribute_elements_in_subtree(
00905     dimension_type root_index,
00906     dimension_type subtree_size,
00907     dimension_type last_used,
00908     dimension_type key,
00909     data_type_const_reference value,
00910     bool add_element) {
00911 
00912   // This is static and with static allocation, to improve performance.
00913   // sizeof_to_bits(sizeof(dimension_type)) is the maximum k such that
00914   // 2^k-1 is a dimension_type, so it is the maximum tree height.
00915   // For each node level, the stack may contain up to two element (one for the
00916   // subtree rooted at the right son of a node of that level, and one for the
00917   // node itself). An additional element can be at the top of the tree.
00918   static std::pair<dimension_type,dimension_type>
00919     stack[2U * sizeof_to_bits(sizeof(dimension_type)) + 1U];
00920 
00921   std::pair<dimension_type,dimension_type>* stack_first_empty = stack;
00922 
00923   // A pair (n, i) in the stack means to visit the subtree with root index i
00924   // and size n.
00925 
00926   PPL_ASSERT(subtree_size != 0);
00927 
00928   stack_first_empty->first  = subtree_size;
00929   stack_first_empty->second = root_index;
00930   ++stack_first_empty;
00931 
00932   while (stack_first_empty != stack) {
00933 
00934     --stack_first_empty;
00935 
00936     // Implement
00937     //
00938     // <CODE>
00939     //   top_n = stack.top().first;
00940     //   top_i = stack.top().second;
00941     // </CODE>
00942     const dimension_type top_n = stack_first_empty->first;
00943     const dimension_type top_i = stack_first_empty->second;
00944 
00945     PPL_ASSERT(top_n != 0);
00946     if (top_n == 1) {
00947       if (add_element
00948           && (last_used > reserved_size || indexes[last_used] > key)) {
00949         PPL_ASSERT(last_used != top_i);
00950         PPL_ASSERT(indexes[top_i] == unused_index);
00951         add_element = false;
00952         indexes[top_i] = key;
00953         new (&(data[top_i])) data_type(value);
00954       } else {
00955         if (last_used != top_i) {
00956           PPL_ASSERT(indexes[top_i] == unused_index);
00957           indexes[top_i] = indexes[last_used];
00958           indexes[last_used] = unused_index;
00959           move_data_element(data[top_i], data[last_used]);
00960         }
00961         ++last_used;
00962       }
00963     } else {
00964       PPL_ASSERT(stack_first_empty + 2
00965                  < stack + sizeof(stack)/sizeof(stack[0]));
00966 
00967       const dimension_type offset = (top_i & -top_i) / 2;
00968       const dimension_type half = (top_n + 1) / 2;
00969 
00970       PPL_ASSERT(half > 0);
00971 
00972       // Right subtree
00973       PPL_ASSERT(top_n - half > 0);
00974       stack_first_empty->first  = top_n - half;
00975       stack_first_empty->second = top_i + offset;
00976       ++stack_first_empty;
00977 
00978       // Root of the current subtree
00979       stack_first_empty->first   = 1;
00980       stack_first_empty->second  = top_i;
00981       ++stack_first_empty;
00982 
00983       // Left subtree
00984       if (half - 1 != 0) {
00985         stack_first_empty->first   = half - 1;
00986         stack_first_empty->second  = top_i - offset;
00987         ++stack_first_empty;
00988       }
00989     }
00990   }
00991 
00992   PPL_ASSERT(!add_element);
00993 }
00994 
00995 void
00996 PPL::CO_Tree::move_data_from(CO_Tree& tree) {
00997   PPL_ASSERT(size_ == 0);
00998   if (tree.size_ == 0)
00999     return;
01000 
01001   tree_iterator root(*this);
01002 
01003   dimension_type source_index = 1;
01004   while (tree.indexes[source_index] == unused_index)
01005     ++source_index;
01006 
01007   // This is static and with static allocation, to improve performance.
01008   // sizeof_to_bits(sizeof(dimension_type)) is the maximum k such that 2^k-1 is a
01009   // dimension_type, so it is the maximum tree height.
01010   // For each node level, the stack may contain up to 4 elements: two elements
01011   // with operation 0, one element with operation 2 and one element
01012   // with operation 3. An additional element with operation 1 can be at the
01013   // top of the tree.
01014   static std::pair<dimension_type, signed char>
01015     stack[5U * sizeof_to_bits(sizeof(dimension_type))];
01016 
01017   dimension_type stack_first_empty = 0;
01018 
01019   // A pair (n, operation) in the stack means:
01020   //
01021   // * Go to the parent, if operation is 0.
01022   // * Go to the left child, then visit the current tree (with size n), if
01023   //   operation is 1.
01024   // * Go to the right child, then visit the current tree (with size n), if
01025   //   operation is 2.
01026   // * Visit the current tree (with size n), if operation is 3.
01027 
01028   stack[0].first = tree.size_;
01029   stack[0].second = 3;
01030   ++stack_first_empty;
01031 
01032   while (stack_first_empty != 0) {
01033 
01034     // Implement
01035     //
01036     // <CODE>
01037     //   top_n         = stack.top().first;
01038     //   top_operation = stack.top().second;
01039     // </CODE>
01040     const dimension_type top_n = stack[stack_first_empty - 1].first;
01041     const signed char top_operation = stack[stack_first_empty - 1].second;
01042 
01043     switch (top_operation) {
01044 
01045     case 0:
01046       root.get_parent();
01047       --stack_first_empty;
01048       continue;
01049 
01050     case 1:
01051       root.get_left_child();
01052       break;
01053 
01054     case 2:
01055       root.get_right_child();
01056       break;
01057 
01058 #ifndef NDEBUG
01059     case 3:
01060       break;
01061 
01062     default:
01063       PPL_UNREACHABLE;
01064       break;
01065 #endif
01066     }
01067 
01068     // We now visit the current tree
01069 
01070     if (top_n == 0) {
01071       --stack_first_empty;
01072     } else {
01073       if (top_n == 1) {
01074         PPL_ASSERT(root.index() == unused_index);
01075         PPL_ASSERT(tree.indexes[source_index] != unused_index);
01076         root.index() = tree.indexes[source_index];
01077         tree.indexes[source_index] = unused_index;
01078         move_data_element(*root, tree.data[source_index]);
01079         PPL_ASSERT(source_index <= tree.reserved_size);
01080         ++source_index;
01081         while (tree.indexes[source_index] == unused_index)
01082           ++source_index;
01083         --stack_first_empty;
01084       } else {
01085         PPL_ASSERT(stack_first_empty + 3 < sizeof(stack)/sizeof(stack[0]));
01086 
01087         const dimension_type half = (top_n + 1) / 2;
01088         stack[stack_first_empty - 1].second = 0;
01089         stack[stack_first_empty    ] = std::make_pair(top_n - half, 2);
01090         stack[stack_first_empty + 1] = std::make_pair(1, 3);
01091         stack[stack_first_empty + 2].second = 0;
01092         stack[stack_first_empty + 3] = std::make_pair(half - 1, 1);
01093         stack_first_empty += 4;
01094       }
01095     }
01096   }
01097   size_ = tree.size_;
01098   tree.size_ = 0;
01099   PPL_ASSERT(tree.structure_OK());
01100   PPL_ASSERT(structure_OK());
01101 }
01102 
01103 void
01104 PPL::CO_Tree::copy_data_from(const CO_Tree& x) {
01105   PPL_ASSERT(size_ == 0);
01106   PPL_ASSERT(reserved_size == x.reserved_size);
01107   PPL_ASSERT(structure_OK());
01108 
01109   if (x.size_ == 0) {
01110     PPL_ASSERT(OK());
01111     return;
01112   }
01113 
01114   for (dimension_type i = x.reserved_size; i > 0; --i)
01115     if (x.indexes[i] != unused_index) {
01116       indexes[i] = x.indexes[i];
01117       new (&(data[i])) data_type(x.data[i]);
01118     } else {
01119       PPL_ASSERT(indexes[i] == unused_index);
01120     }
01121 
01122   size_ = x.size_;
01123   PPL_ASSERT(OK());
01124 }
01125 
01126 PPL::dimension_type
01127 PPL::CO_Tree::count_used_in_subtree(tree_iterator itr) {
01128   dimension_type n = 0;
01129 
01130   const dimension_type k = itr.get_offset();
01131   const dimension_type root_index = itr.dfs_index();
01132 
01133   // The complete subtree rooted at itr has 2*k - 1 nodes.
01134 
01135   PPL_ASSERT(root_index > (k - 1));
01136 
01137   dimension_type* current_index = &(itr.tree.indexes[root_index - (k - 1)]);
01138 
01139   for (dimension_type j = 2*k - 1; j > 0; --j, ++current_index)
01140     if (*current_index != unused_index)
01141       ++n;
01142 
01143   return n;
01144 }
01145 
01146 bool
01147 PPL::CO_Tree::const_iterator::OK() const {
01148 #if PPL_CO_TREE_EXTRA_DEBUG
01149   if (tree == 0) {
01150     if (current_index != 0)
01151       return false;
01152     if (current_data != 0)
01153       return false;
01154   } else
01155     if (tree->reserved_size == 0) {
01156       if (current_index != 1 + (dimension_type*)0
01157           || current_data != 1 + (data_type*)0)
01158         return false;
01159     } else {
01160       if (current_index <= &(tree->indexes[0]))
01161         return false;
01162       if (current_index > &(tree->indexes[tree->reserved_size + 1]))
01163         return false;
01164       if (current_data <= &(tree->data[0]))
01165         return false;
01166       if (current_data > &(tree->data[tree->reserved_size + 1]))
01167         return false;
01168       if (*current_index == unused_index)
01169         return false;
01170       if (current_index - tree->indexes != current_data - tree->data)
01171         return false;
01172     }
01173 #endif
01174   return true;
01175 }
01176 
01177 bool
01178 PPL::CO_Tree::iterator::OK() const {
01179 #if PPL_CO_TREE_EXTRA_DEBUG
01180   if (tree == 0) {
01181     if (current_index != 0)
01182       return false;
01183     if (current_data != 0)
01184       return false;
01185   } else
01186     if (tree->reserved_size == 0) {
01187       if (current_index != 1 + (dimension_type*)0
01188           || current_data != 1 + (data_type*)0)
01189         return false;
01190     } else {
01191       if (current_index <= &(tree->indexes[0]))
01192         return false;
01193       if (current_index > &(tree->indexes[tree->reserved_size + 1]))
01194         return false;
01195       if (current_data <= &(tree->data[0]))
01196         return false;
01197       if (current_data > &(tree->data[tree->reserved_size + 1]))
01198         return false;
01199       if (*current_index == unused_index)
01200         return false;
01201       if (current_index - tree->indexes != current_data - tree->data)
01202         return false;
01203     }
01204 #endif
01205   return true;
01206 }
01207 
01208 bool
01209 PPL::CO_Tree::tree_iterator::OK() const {
01210   if (i == 0 || i > tree.reserved_size)
01211     return false;
01212 
01213   // This assumes two's complement encoding.
01214   dimension_type correct_offset = i & -i;
01215 
01216   if (offset != correct_offset)
01217     return false;
01218 
01219   return true;
01220 }
01221 
01222 void
01223 PPL::CO_Tree::tree_iterator::go_down_searching_key(dimension_type key) {
01224   // *this points to a node, so the tree is not empty.
01225   PPL_ASSERT(!tree.empty());
01226   PPL_ASSERT(key != unused_index);
01227   PPL_ASSERT(index() != unused_index);
01228   while (!is_leaf()) {
01229     if (key == index())
01230       break;
01231     if (key < index()) {
01232       get_left_child();
01233       if (index() == unused_index) {
01234         get_parent();
01235         break;
01236       }
01237     } else {
01238       get_right_child();
01239       if (index() == unused_index) {
01240         get_parent();
01241         break;
01242       }
01243     }
01244   }
01245 }