PPL  1.2
CO_Tree.cc
Go to the documentation of this file.
1 /* CO_Tree class implementation.
2  Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it>
3  Copyright (C) 2010-2016 BUGSENG srl (http://bugseng.com)
4 
5 This file is part of the Parma Polyhedra Library (PPL).
6 
7 The PPL is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 The PPL is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
20 
21 For the most up-to-date information see the Parma Polyhedra Library
22 site: http://bugseng.com/products/ppl/ . */
23 
24 #include "ppl-config.h"
25 #include "CO_Tree_defs.hh"
26 
27 namespace PPL = Parma_Polyhedra_Library;
28 
31  dimension_type memory_size = 0;
32  if (reserved_size != 0) {
33  // Add the size of data[]
34  memory_size += (reserved_size + 1)*sizeof(data[0]);
35  // Add the size of indexes[]
36  memory_size += (reserved_size + 2)*sizeof(indexes[0]);
37  for (const_iterator itr = begin(), itr_end = end();
38  itr != itr_end; ++itr) {
39  memory_size += PPL::external_memory_in_bytes(*itr);
40  }
41  }
42  return memory_size;
43 }
44 
45 PPL::CO_Tree::iterator
47  PPL_ASSERT(key1 != unused_index);
48 
49  if (empty()) {
50  insert_in_empty_tree(key1, Coefficient_zero());
51  return iterator(*this);
52  }
53 
54  if (itr == end()) {
55  return insert(key1);
56  }
57 
58  iterator candidate1 = bisect_near(itr, key1);
59 
60  if (key1 == candidate1.index()) {
61  return candidate1;
62  }
63 
64  dimension_type candidate2_index = dfs_index(candidate1);
65 
66  if (key1 < candidate1.index()) {
67  --candidate2_index;
68  while (indexes[candidate2_index] == unused_index) {
69  --candidate2_index;
70  }
71  }
72  else {
73  ++candidate2_index;
74  while (indexes[candidate2_index] == unused_index) {
75  ++candidate2_index;
76  }
77  }
78 
79  tree_iterator candidate1_node(candidate1, *this);
80 
81  PPL_ASSERT(candidate2_index <= reserved_size + 1);
82 
83  if (candidate2_index == 0 || candidate2_index > reserved_size) {
84  // Use candidate1
85  return iterator(insert_precise(key1, Coefficient_zero(),
86  candidate1_node));
87  }
88 
89  tree_iterator candidate2_node(*this, candidate2_index);
90 
91  // Adjacent nodes in an in-order visit of a tree always have different
92  // heights. This fact can be easily proven by induction on the tree's
93  // height, using the definition of the in-order layout.
94  PPL_ASSERT(candidate1_node.get_offset() != candidate2_node.get_offset());
95 
96  if (candidate1_node.get_offset() < candidate2_node.get_offset()) {
97  PPL_ASSERT(candidate1_node.depth() > candidate2_node.depth());
98  // candidate1_node is deeper in the tree than candidate2_node, so use
99  // candidate1_node.
100  return iterator(insert_precise(key1, Coefficient_zero(),
101  candidate1_node));
102  }
103  else {
104  PPL_ASSERT(candidate1_node.depth() < candidate2_node.depth());
105  // candidate2_node is deeper in the tree than candidate1_node, so use
106  // candidate2_node.
107  return iterator(insert_precise(key1, Coefficient_zero(),
108  candidate2_node));
109  }
110 }
111 
112 PPL::CO_Tree::iterator
115  PPL_ASSERT(key1 != unused_index);
116 
117  if (empty()) {
118  insert_in_empty_tree(key1, data1);
119  return iterator(*this);
120  }
121 
122  if (itr == end()) {
123  return insert(key1, data1);
124  }
125 
126  iterator candidate1 = bisect_near(itr, key1);
127 
128  if (key1 == candidate1.index()) {
129  *candidate1 = data1;
130  return candidate1;
131  }
132 
133  dimension_type candidate2_index = dfs_index(candidate1);
134 
135  if (key1 < candidate1.index()) {
136  --candidate2_index;
137  while (indexes[candidate2_index] == unused_index) {
138  --candidate2_index;
139  }
140 
141  }
142  else {
143  ++candidate2_index;
144  while (indexes[candidate2_index] == unused_index) {
145  ++candidate2_index;
146  }
147 
148  }
149 
150  tree_iterator candidate1_node(candidate1, *this);
151 
152  if (candidate2_index == 0 || candidate2_index > reserved_size) {
153  // Use candidate1
154  return iterator(insert_precise(key1, data1, candidate1_node));
155  }
156 
157  tree_iterator candidate2_node(*this, candidate2_index);
158 
159  // Adjacent nodes in an in-order visit of a tree always have different
160  // heights. This fact can be easily proven by induction on the tree's
161  // height, using the definition of the in-order layout.
162  PPL_ASSERT(candidate1_node.get_offset() != candidate2_node.get_offset());
163 
164  if (candidate1_node.get_offset() < candidate2_node.get_offset()) {
165  PPL_ASSERT(candidate1_node.depth() > candidate2_node.depth());
166  // candidate1_node is deeper in the tree than candidate2_node, so
167  // use candidate1_node.
168  return iterator(insert_precise(key1, data1, candidate1_node));
169  }
170  else {
171  PPL_ASSERT(candidate1_node.depth() < candidate2_node.depth());
172  // candidate2_node is deeper in the tree than candidate1_node, so
173  // use candidate2_node.
174  return iterator(insert_precise(key1, data1, candidate2_node));
175  }
176 }
177 
178 void
180  iterator itr = erase(key);
181  if (itr == end()) {
182  return;
183  }
184  const dimension_type i = dfs_index(itr);
185  dimension_type* p = indexes + i;
186  const dimension_type* const p_end = indexes + (reserved_size + 1);
187  for ( ; p != p_end; ++p) {
188  if (*p != unused_index) {
189  --(*p);
190  }
191  }
192  PPL_ASSERT(OK());
193 }
194 
195 void
197  if (empty()) {
198  return;
199  }
200  dimension_type* p = indexes + reserved_size;
201  while (*p == unused_index) {
202  --p;
203  }
204  while (p != indexes && *p >= key) {
205  *p += n;
206  --p;
207  while (*p == unused_index) {
208  --p;
209  }
210  }
211  PPL_ASSERT(OK());
212 }
213 
216  dimension_type key) const {
217  PPL_ASSERT(first != 0);
218  PPL_ASSERT(last <= reserved_size);
219  PPL_ASSERT(first <= last);
220  PPL_ASSERT(indexes[first] != unused_index);
221  PPL_ASSERT(indexes[last] != unused_index);
222 
223  while (first < last) {
224  dimension_type half = (first + last) / 2;
225  dimension_type new_half = half;
226 
227  while (indexes[new_half] == unused_index) {
228  ++new_half;
229  }
230 
231  if (indexes[new_half] == key) {
232  return new_half;
233  }
234 
235  if (indexes[new_half] > key) {
236 
237  while (indexes[half] == unused_index) {
238  --half;
239  }
240 
241  last = half;
242 
243  }
244  else {
245 
246  ++new_half;
247  while (indexes[new_half] == unused_index) {
248  ++new_half;
249  }
250 
251  first = new_half;
252  }
253  }
254 
255  // It is important that last is returned instead of first, because first
256  // may have increased beyond last, even beyond the original value of last
257  // at the beginning of this method.
258  return last;
259 }
260 
263  PPL_ASSERT(hint != 0);
264  PPL_ASSERT(hint <= reserved_size);
265  PPL_ASSERT(indexes[hint] != unused_index);
266 
267  if (indexes[hint] == key) {
268  return hint;
269  }
270 
271  dimension_type new_hint;
272  dimension_type offset = 1;
273 
274  if (indexes[hint] > key) {
275  // The searched element is before `hint'.
276 
277  while (true) {
278 
279  if (hint <= offset) {
280  // The searched element is in (0,hint).
281  new_hint = hint;
282  hint = 1;
283  // The searched element is in [hint,new_hint).
284  while (indexes[hint] == unused_index) {
285  ++hint;
286  }
287 
288  if (indexes[hint] >= key) {
289  return hint;
290  }
291  // The searched element is in (hint,new_hint) and both indexes point
292  // to valid elements.
293  break;
294  }
295  else {
296  new_hint = hint - offset;
297  }
298 
299  PPL_ASSERT(new_hint > 0);
300  PPL_ASSERT(new_hint <= reserved_size);
301 
302  // Find the element at `new_hint' (or the first after it).
303  while (indexes[new_hint] == unused_index) {
304  ++new_hint;
305  }
306 
307  PPL_ASSERT(new_hint <= hint);
308 
309  if (indexes[new_hint] == key) {
310  return new_hint;
311  }
312  else
313  if (indexes[new_hint] < key) {
314  // The searched element is in (new_hint,hint)
315  using std::swap;
316  swap(hint, new_hint);
317  // The searched element is now in (hint,new_hint).
318  break;
319  }
320 
321  hint = new_hint;
322  offset *= 2;
323  }
324 
325  }
326  else {
327  // The searched element is after `hint'.
328  while (true) {
329 
330  if (hint + offset > reserved_size) {
331  // The searched element is in (hint,reserved_size+1).
332  new_hint = reserved_size;
333  // The searched element is in (hint,new_hint].
334  while (indexes[new_hint] == unused_index) {
335  --new_hint;
336  }
337  if (indexes[new_hint] <= key) {
338  return new_hint;
339  }
340  // The searched element is in (hint,new_hint) and both indexes point
341  // to valid elements.
342  break;
343  }
344  else {
345  new_hint = hint + offset;
346  }
347 
348  PPL_ASSERT(new_hint > 0);
349  PPL_ASSERT(new_hint <= reserved_size);
350 
351  // Find the element at `new_hint' (or the first after it).
352  while (indexes[new_hint] == unused_index) {
353  --new_hint;
354  }
355 
356  PPL_ASSERT(hint <= new_hint);
357 
358  if (indexes[new_hint] == key) {
359  return new_hint;
360  }
361  else {
362  if (indexes[new_hint] > key) {
363  // The searched element is in (hint,new_hint).
364  break;
365  }
366  }
367  hint = new_hint;
368  offset *= 2;
369  }
370  }
371  // The searched element is in (hint,new_hint).
372  PPL_ASSERT(hint > 0);
373  PPL_ASSERT(hint < new_hint);
374  PPL_ASSERT(new_hint <= reserved_size);
375  PPL_ASSERT(indexes[hint] != unused_index);
376  PPL_ASSERT(indexes[new_hint] != unused_index);
377 
378  ++hint;
379  while (indexes[hint] == unused_index) {
380  ++hint;
381  }
382 
383  if (hint == new_hint) {
384  return hint;
385  }
386 
387  --new_hint;
388 
389  while (indexes[new_hint] == unused_index) {
390  --new_hint;
391  }
392 
393  PPL_ASSERT(hint <= new_hint);
394  PPL_ASSERT(indexes[hint] != unused_index);
395  PPL_ASSERT(indexes[new_hint] != unused_index);
396 
397  return bisect_in(hint, new_hint, key);
398 }
399 
400 PPL::CO_Tree::tree_iterator
403  tree_iterator itr) {
404  PPL_ASSERT(key1 != unused_index);
405  PPL_ASSERT(!empty());
406 
407 #ifndef NDEBUG
408  // Check that `itr' is a correct hint.
409  tree_iterator itr2(*this);
410  itr2.go_down_searching_key(key1);
411  PPL_ASSERT(itr == itr2);
412 #endif
413 
414  if (itr.index() == key1) {
415  // Replacement, rather than insertion.
416  *itr = data1;
417  PPL_ASSERT(OK());
418  return itr;
419  }
420 
421  // Proper insertion: check if it would invalidate `data1'.
422  const bool invalidating
423  = (data <= &data1) && (&data1 < data + (reserved_size + 1));
424 
425  if (!invalidating) {
426  return insert_precise_aux(key1, data1, itr);
427  }
428  // `data1' could be invalidated by the insert, because it is
429  // a coefficient of this row. Avoid the issue by copying it.
430  data_type data1_copy = data1;
431 
432 #ifndef NDEBUG
433  dimension_type i = &data1 - data;
434  dimension_type key2 = indexes[i];
435  PPL_ASSERT(key2 != unused_index);
436  // This is true since `key1' is not in the tree.
437  PPL_ASSERT(key2 != key1);
438 #endif
439 
440  // Insert a dummy coefficient.
441  // NOTE: this may invalidate `data1', because it may reallocate the tree
442  // and/or move coefficients during rebalancing.
443  itr = insert_precise_aux(key1, Coefficient_zero(), itr);
444 
445  PPL_ASSERT(itr.index() == key1);
446 
447  // Swap the correct coefficient in place.
448  using std::swap;
449  swap(*itr, data1_copy);
450 
451  PPL_ASSERT(OK());
452  return itr;
453 }
454 
455 PPL::CO_Tree::tree_iterator
458  tree_iterator itr) {
459  PPL_ASSERT(key1 != unused_index);
460  PPL_ASSERT(!empty());
461  // This is a proper insert.
462  PPL_ASSERT(itr.index() != key1);
463  // `data1' is not going to be invalidated.
464  PPL_ASSERT(!(data <= &data1 && &data1 < data + (reserved_size + 1)));
465 
466  if (is_greater_than_ratio(size_ + 1, reserved_size, max_density_percent)) {
467  rebuild_bigger_tree();
468  // `itr' was invalidated by the rebuild operation
469  itr.get_root();
470  itr.go_down_searching_key(key1);
471  PPL_ASSERT(itr.index() != key1);
472  }
473 
474  PPL_ASSERT(!is_greater_than_ratio(size_ + 1, reserved_size,
475  max_density_percent));
476 
477  ++size_;
478 
479  if (!itr.is_leaf()) {
480  if (key1 < itr.index()) {
481  itr.get_left_child();
482  }
483  else {
484  itr.get_right_child();
485  }
486  PPL_ASSERT(itr.index() == unused_index);
487 
488  new(&(*itr)) data_type(data1);
489  // Set the index only if the construction was successful.
490  itr.index() = key1;
491  }
492  else {
493  itr = rebalance(itr, key1, data1);
494  itr.go_down_searching_key(key1);
495  PPL_ASSERT(itr.index() == key1);
496  }
497  PPL_ASSERT(OK());
498 
499  return itr;
500 }
501 
502 PPL::CO_Tree::iterator
504  PPL_ASSERT(itr.index() != unused_index);
505 
506  PPL_ASSERT(size_ != 0);
507 
508  if (size_ == 1) {
509  // Deleting the only element of this tree, now it is empty.
510  clear();
511  return end();
512  }
513 
514  if (is_less_than_ratio(size_ - 1, reserved_size, min_density_percent)
515  && !is_greater_than_ratio(size_ - 1, reserved_size/2,
516  max_density_percent)) {
517 
518  const dimension_type key = itr.index();
519 
520  PPL_ASSERT(!is_greater_than_ratio(size_, reserved_size,
521  max_density_percent));
522 
523  rebuild_smaller_tree();
524  itr.get_root();
525  itr.go_down_searching_key(key);
526 
527  PPL_ASSERT(itr.index() == key);
528  }
529 
530 #ifndef NDEBUG
531  if (size_ > 1) {
532  PPL_ASSERT(!is_less_than_ratio(size_ - 1, reserved_size,
533  min_density_percent)
534  || is_greater_than_ratio(size_ - 1, reserved_size/2,
535  max_density_percent));
536  }
537 #endif
538 
539  const dimension_type deleted_key = itr.index();
540  tree_iterator deleted_node = itr;
541  (*itr).~data_type();
542  while (true) {
543  dimension_type& current_key = itr.index();
544  data_type& current_data = *itr;
545  if (itr.is_leaf()) {
546  break;
547  }
548  itr.get_left_child();
549  if (itr.index() != unused_index) {
550  // The left child has a value.
552  }
553  else {
554  // The left child has not a value, try the right child.
555  itr.get_parent();
556  itr.get_right_child();
557  if (itr.index() != unused_index) {
558  // The right child has a value.
560  }
561  else {
562  // The right child has not a value, too.
563  itr.get_parent();
564  break;
565  }
566  }
567  using std::swap;
568  swap(current_key, itr.index());
569  move_data_element(current_data, *itr);
570  }
571 
572  PPL_ASSERT(itr.index() != unused_index);
573  itr.index() = unused_index;
574  --size_;
575 
576  PPL_ASSERT(OK());
577 
578  itr = rebalance(itr, 0, Coefficient_zero());
579 
580  if (itr.get_offset() < deleted_node.get_offset()) {
581  // deleted_node is an ancestor of itr
582  itr = deleted_node;
583  }
584 
585  itr.go_down_searching_key(deleted_key);
586 
587  iterator result(itr);
588 
589  if (result.index() < deleted_key) {
590  ++result;
591  }
592 
593  PPL_ASSERT(OK());
594  PPL_ASSERT(result == end() || result.index() > deleted_key);
595 #ifndef NDEBUG
596  if (!empty()) {
597  iterator last = end();
598  --last;
599  PPL_ASSERT((result == end()) == (last.index() < deleted_key));
600  }
601 #endif
602 
603  return result;
604 }
605 
606 void
608  indexes = NULL;
609  data = NULL;
610  size_ = 0;
611  reserved_size = 0;
612  max_depth = 0;
613 
614  if (n > 0) {
615  const dimension_type max_d = integer_log2(n) + 1;
616  const height_t new_max_depth = static_cast<height_t>(max_d);
617  const dimension_type new_reserved_size
618  = (static_cast<dimension_type>(1) << new_max_depth) - 1;
619  // If this throws, *this will be the empty tree.
620  indexes = new dimension_type[new_reserved_size + 2];
621  try {
622  data = data_allocator.allocate(new_reserved_size + 1);
623  }
624  catch (...) {
625  delete[] indexes;
626  indexes = 0;
627  PPL_ASSERT(OK());
628  throw;
629  }
630  max_depth = new_max_depth;
631  reserved_size = new_reserved_size;
632 
633  // Mark all pairs as unused.
634  for (dimension_type i = 1; i <= reserved_size; ++i) {
635  indexes[i] = unused_index;
636  }
637 
638  // These are used as markers by iterators.
639  indexes[0] = 0;
640  indexes[reserved_size + 1] = 0;
641  }
642 
643  refresh_cached_iterators();
644 
645  PPL_ASSERT(structure_OK());
646 }
647 
648 void
650 
651  if (reserved_size != 0) {
652  for (dimension_type i = 1; i <= reserved_size; ++i) {
653  if (indexes[i] != unused_index) {
654  data[i].~data_type();
655  }
656  }
657 
658  delete[] indexes;
659  data_allocator.deallocate(data, reserved_size + 1);
660  }
661 }
662 
663 bool
665 
666  if (size_ > reserved_size) {
667  return false;
668  }
669 
670  if (reserved_size == 0) {
671  if (indexes != NULL) {
672  return false;
673  }
674  if (data != NULL) {
675  return false;
676  }
677  if (max_depth != 0) {
678  return false;
679  }
680 
681  return true;
682  }
683 
684  if (reserved_size < 3) {
685  return false;
686  }
687  if (reserved_size != (static_cast<dimension_type>(1) << max_depth) - 1) {
688  return false;
689  }
690 
691  if (data == NULL) {
692  return false;
693  }
694 
695  if (indexes == NULL) {
696  return false;
697  }
698 
699  if (max_depth == 0) {
700  return false;
701  }
702 
703  if (size_ == 0) {
704 
705  // This const_cast could be removed by adding a const_tree_iterator,
706  // but it would add much code duplication without a real need.
707  tree_iterator itr(*const_cast<CO_Tree*>(this));
708  if (itr.index() != unused_index) {
709  return false;
710  }
711 
712  }
713  else {
714  // This const_cast could be removed by adding a const_tree_iterator,
715  // but it would add much code duplication without a real need.
716  tree_iterator itr(*const_cast<CO_Tree*>(this));
717  const dimension_type real_size = count_used_in_subtree(itr);
718  if (real_size != size_) {
719  // There are \p real_size elements in the tree that are reachable by the
720  // root, but size is \p size.
721  return false;
722  }
723  }
724 
725  if (size_ != 0) {
726  const_iterator itr = begin();
727  const_iterator itr_end = end();
728 
729  if (itr != itr_end) {
730  dimension_type last_index = itr.index();
731  for (++itr; itr != itr_end; ++itr) {
732  if (last_index >= itr.index()) {
733  // Found index \p itr->first after index \p last_index.
734  return false;
735  }
736  last_index = itr.index();
737  }
738  }
739  }
740 
741  if (const_iterator(cached_end) != const_iterator(*this, reserved_size + 1)) {
742  return false;
743  }
744  if (cached_const_end != const_iterator(*this, reserved_size + 1)) {
745  return false;
746  }
747 
748  return true;
749 }
750 
751 bool
753 
754  if (!structure_OK()) {
755  return false;
756  }
757  {
758  dimension_type real_size = 0;
759 
760  for (const_iterator itr = begin(), itr_end = end(); itr != itr_end; ++itr) {
761  ++real_size;
762  }
763 
764  if (real_size != size_) {
765  // There are \p real_size elements in the tree, but size is \p size.
766  return false;
767  }
768  }
769 
770  if (reserved_size > 0) {
771  if (is_greater_than_ratio(size_, reserved_size, max_density_percent)
772  && reserved_size != 3) {
773  // Found too high density.
774  return false;
775  }
776  if (is_less_than_ratio(size_, reserved_size, min_density_percent)
777  && !is_greater_than_ratio(size_, reserved_size/2, max_density_percent)) {
778  // Found too low density
779  return false;
780  }
781  }
782 
783  return true;
784 }
785 
786 unsigned
788  PPL_ASSERT(n != 0);
789  unsigned result = 0;
790  while (n != 1) {
791  n /= 2;
792  ++result;
793  }
794  return result;
795 }
796 
797 void
799  if (!itr.is_leaf()) {
800  itr.get_left_child();
801  dump_subtree(itr);
802  itr.get_parent();
803  }
804  std::cout << "At depth: " << itr.depth();
805  if (itr.index() == unused_index) {
806  std::cout << " (no data)" << std::endl;
807  }
808  else {
809  std::cout << " pair (" << itr.index() << "," << *itr << ")" << std::endl;
810  }
811  if (!itr.is_leaf()) {
812  itr.get_right_child();
813  dump_subtree(itr);
814  itr.get_parent();
815  }
816 }
817 
818 void
820  if (reserved_size == 0) {
821  init(3);
822  PPL_ASSERT(structure_OK());
823  return;
824  }
825 
826  const dimension_type new_reserved_size = reserved_size*2 + 1;
827 
828  dimension_type* const new_indexes = new dimension_type[new_reserved_size + 2];
829 
830  data_type* new_data;
831 
832  try {
833  new_data = data_allocator.allocate(new_reserved_size + 1);
834  } catch (...) {
835  delete[] new_indexes;
836  throw;
837  }
838 
839  new_indexes[1] = unused_index;
840 
841  for (dimension_type i = 1, j = 2; i <= reserved_size; ++i, ++j) {
842  new_indexes[j] = indexes[i];
843  if (indexes[i] != unused_index) {
844  move_data_element(new_data[j], data[i]);
845  }
846  ++j;
847  new_indexes[j] = unused_index;
848  }
849 
850  // These are used as markers by iterators.
851  new_indexes[0] = 0;
852  new_indexes[new_reserved_size + 1] = 0;
853 
854  delete[] indexes;
855  data_allocator.deallocate(data, reserved_size + 1);
856 
857  indexes = new_indexes;
858  data = new_data;
859  reserved_size = new_reserved_size;
860  ++max_depth;
861 
862  refresh_cached_iterators();
863 
864  PPL_ASSERT(structure_OK());
865 }
866 
867 PPL::CO_Tree::tree_iterator
870  // Trees with reserved size 3 need not to be rebalanced.
871  // This check is needed because they can't be shrunk, so they may violate
872  // the density thresholds, and this would prevent the following while from
873  // working correctly.
874  if (reserved_size == 3) {
875  PPL_ASSERT(OK());
876  return tree_iterator(*this);
877  }
878  PPL_ASSERT(itr.index() == unused_index || itr.is_leaf());
879  height_t itr_depth_minus_1 = itr.depth() - 1;
880  const height_t height = max_depth - itr_depth_minus_1;
881  dimension_type subtree_size;
882  dimension_type subtree_reserved_size = (static_cast<dimension_type>(1)
883  << height) - 1;
884  const bool deleting = itr.index() == unused_index;
885  PPL_ASSERT(deleting || key != unused_index);
886  if (deleting) {
887  subtree_size = 0;
888  }
889  else {
890  // The existing element and the element with index key we want to add.
891  subtree_size = 2;
892  }
893 
894  while (is_greater_than_ratio(subtree_size, subtree_reserved_size,
895  max_density_percent
896  + ((itr_depth_minus_1
897  * (100 - max_density_percent))
898  / (max_depth - 1)))
899  || is_less_than_ratio(subtree_size, subtree_reserved_size,
900  min_density_percent
901  - ((itr_depth_minus_1
902  * (min_density_percent
903  - min_leaf_density_percent))
904  / (max_depth - 1)))) {
905  // The density in the tree is correct, so the while condition is always
906  // false for the root.
907  PPL_ASSERT(itr_depth_minus_1 != 0);
908  const bool is_right_brother = itr.is_right_child();
909  itr.get_parent();
910  if (is_right_brother) {
911  itr.get_left_child();
912  }
913  else {
914  itr.get_right_child();
915  }
916  subtree_size += count_used_in_subtree(itr);
917  itr.get_parent();
918  PPL_ASSERT(itr.index() != unused_index);
919  ++subtree_size;
920  subtree_reserved_size = 2*subtree_reserved_size + 1;
921  --itr_depth_minus_1;
922  PPL_ASSERT(itr.depth() - 1 == itr_depth_minus_1);
923  }
924 
925  // Now the subtree rooted at itr has been chosen as the subtree to be
926  // rebalanced.
927 
928  // Step 1: compact elements of this subtree in the rightmost end, from right
929  // to left.
930  const dimension_type last_index_in_subtree
931  = itr.dfs_index() + itr.get_offset() - 1;
932 
933  const dimension_type first_unused
934  = compact_elements_in_the_rightmost_end(last_index_in_subtree,
935  subtree_size, key, value,
936  !deleting);
937 
938  // Step 2: redistribute the elements, from left to right.
939  redistribute_elements_in_subtree(itr.dfs_index(), subtree_size,
940  first_unused + 1, key, value,
941  first_unused != last_index_in_subtree
942  - subtree_size);
943 
944  PPL_ASSERT(OK());
945 
946  return itr;
947 }
948 
952  dimension_type subtree_size,
953  dimension_type key,
955  bool add_element) {
956 
957  PPL_ASSERT(subtree_size != 0);
958 
959  PPL_ASSERT(subtree_size != 1 || !add_element);
960 
961  dimension_type* last_index_in_subtree = &(indexes[last_in_subtree]);
962  data_type* last_data_in_subtree = &(data[last_in_subtree]);
963 
964  dimension_type* first_unused_index = last_index_in_subtree;
965  data_type* first_unused_data = last_data_in_subtree;
966 
967  while (*last_index_in_subtree == unused_index) {
968  --last_index_in_subtree;
969  --last_data_in_subtree;
970  }
971 
972  // From now on, last_index_in_subtree and last_data_in_subtree point to the
973  // rightmost node with a value in the subtree. first_unused_index and
974  // first_unused_data point to the rightmost unused node in the subtree.
975 
976  if (add_element) {
977  while (subtree_size != 0) {
978  --subtree_size;
979  if (last_index_in_subtree == indexes || key > *last_index_in_subtree) {
980  if (last_index_in_subtree == indexes
981  || last_index_in_subtree != first_unused_index) {
982  PPL_ASSERT(first_unused_index != indexes);
983  PPL_ASSERT(*first_unused_index == unused_index);
984  new(first_unused_data) data_type(value);
985  // Set the index only if the construction was successful.
986  *first_unused_index = key;
987  --first_unused_index;
988  --first_unused_data;
989  }
990  break;
991  }
992  else {
993  if (last_index_in_subtree != first_unused_index) {
994  PPL_ASSERT(first_unused_index != indexes);
995  PPL_ASSERT(last_index_in_subtree != indexes);
996  PPL_ASSERT(*first_unused_index == unused_index);
997  *first_unused_index = *last_index_in_subtree;
998  *last_index_in_subtree = unused_index;
999  move_data_element(*first_unused_data, *last_data_in_subtree);
1000  }
1001  --last_index_in_subtree;
1002  --last_data_in_subtree;
1003  while (*last_index_in_subtree == unused_index) {
1004  --last_index_in_subtree;
1005  --last_data_in_subtree;
1006  }
1007  --first_unused_index;
1008  --first_unused_data;
1009  }
1010  }
1011  }
1012  while (subtree_size != 0) {
1013  if (last_index_in_subtree != first_unused_index) {
1014  PPL_ASSERT(first_unused_index != indexes);
1015  PPL_ASSERT(last_index_in_subtree != indexes);
1016  PPL_ASSERT(*first_unused_index == unused_index);
1017  *first_unused_index = *last_index_in_subtree;
1018  *last_index_in_subtree = unused_index;
1019  move_data_element(*first_unused_data, *last_data_in_subtree);
1020  }
1021  --last_index_in_subtree;
1022  --last_data_in_subtree;
1023  while (*last_index_in_subtree == unused_index) {
1024  --last_index_in_subtree;
1025  --last_data_in_subtree;
1026  }
1027  --first_unused_index;
1028  --first_unused_data;
1029  --subtree_size;
1030  }
1031 
1032  const std::ptrdiff_t distance = first_unused_index - indexes;
1033  PPL_ASSERT(distance >= 0);
1034  return static_cast<dimension_type>(distance);
1035 }
1036 
1037 void
1039  dimension_type root_index,
1040  dimension_type subtree_size,
1041  dimension_type last_used,
1042  dimension_type key,
1044  bool add_element) {
1045 
1046  // This is static and with static allocation, to improve performance.
1047  // sizeof_to_bits(sizeof(dimension_type)) is the maximum k such that
1048  // 2^k-1 is a dimension_type, so it is the maximum tree height.
1049  // For each node level, the stack may contain up to two element (one for the
1050  // subtree rooted at the right son of a node of that level, and one for the
1051  // node itself). An additional element can be at the top of the tree.
1052  static std::pair<dimension_type,dimension_type>
1053  stack[2U * sizeof_to_bits(sizeof(dimension_type)) + 1U];
1054 
1055  std::pair<dimension_type,dimension_type>* stack_first_empty = stack;
1056 
1057  // A pair (n, i) in the stack means to visit the subtree with root index i
1058  // and size n.
1059 
1060  PPL_ASSERT(subtree_size != 0);
1061 
1062  stack_first_empty->first = subtree_size;
1063  stack_first_empty->second = root_index;
1064  ++stack_first_empty;
1065 
1066  while (stack_first_empty != stack) {
1067 
1068  --stack_first_empty;
1069 
1070  // Implement
1071  //
1072  // <CODE>
1073  // top_n = stack.top().first;
1074  // top_i = stack.top().second;
1075  // </CODE>
1076  const dimension_type top_n = stack_first_empty->first;
1077  const dimension_type top_i = stack_first_empty->second;
1078 
1079  PPL_ASSERT(top_n != 0);
1080  if (top_n == 1) {
1081  if (add_element
1082  && (last_used > reserved_size || indexes[last_used] > key)) {
1083  PPL_ASSERT(last_used != top_i);
1084  PPL_ASSERT(indexes[top_i] == unused_index);
1085  add_element = false;
1086  new(&(data[top_i])) data_type(value);
1087  // Set the index only if the construction was successful.
1088  indexes[top_i] = key;
1089  }
1090  else {
1091  if (last_used != top_i) {
1092  PPL_ASSERT(indexes[top_i] == unused_index);
1093  indexes[top_i] = indexes[last_used];
1094  indexes[last_used] = unused_index;
1095  move_data_element(data[top_i], data[last_used]);
1096  }
1097  ++last_used;
1098  }
1099  }
1100  else {
1101  PPL_ASSERT(stack_first_empty + 2
1102  < stack + sizeof(stack)/sizeof(stack[0]));
1103 
1104  const dimension_type offset = (top_i & -top_i) / 2;
1105  const dimension_type half = (top_n + 1) / 2;
1106 
1107  PPL_ASSERT(half > 0);
1108 
1109  // Right subtree
1110  PPL_ASSERT(top_n - half > 0);
1111  stack_first_empty->first = top_n - half;
1112  stack_first_empty->second = top_i + offset;
1113  ++stack_first_empty;
1114 
1115  // Root of the current subtree
1116  stack_first_empty->first = 1;
1117  stack_first_empty->second = top_i;
1118  ++stack_first_empty;
1119 
1120  // Left subtree
1121  if (half - 1 != 0) {
1122  stack_first_empty->first = half - 1;
1123  stack_first_empty->second = top_i - offset;
1124  ++stack_first_empty;
1125  }
1126  }
1127  }
1128 
1129  PPL_ASSERT(!add_element);
1130 }
1131 
1132 void
1134  PPL_ASSERT(size_ == 0);
1135  if (tree.size_ == 0) {
1136  return;
1137  }
1138 
1139  tree_iterator root(*this);
1140 
1141  dimension_type source_index = 1;
1142  while (tree.indexes[source_index] == unused_index) {
1143  ++source_index;
1144  }
1145 
1146  // This is static and with static allocation, to improve performance.
1147  // sizeof_to_bits(sizeof(dimension_type)) is the maximum k such that 2^k-1 is a
1148  // dimension_type, so it is the maximum tree height.
1149  // For each node level, the stack may contain up to 4 elements: two elements
1150  // with operation 0, one element with operation 2 and one element
1151  // with operation 3. An additional element with operation 1 can be at the
1152  // top of the tree.
1153  static std::pair<dimension_type, signed char>
1154  stack[5U * sizeof_to_bits(sizeof(dimension_type))];
1155 
1156  dimension_type stack_first_empty = 0;
1157 
1158  // A pair (n, operation) in the stack means:
1159  //
1160  // * Go to the parent, if operation is 0.
1161  // * Go to the left child, then visit the current tree (with size n), if
1162  // operation is 1.
1163  // * Go to the right child, then visit the current tree (with size n), if
1164  // operation is 2.
1165  // * Visit the current tree (with size n), if operation is 3.
1166 
1167  stack[0].first = tree.size_;
1168  stack[0].second = 3;
1169  ++stack_first_empty;
1170 
1171  while (stack_first_empty != 0) {
1172 
1173  // Implement
1174  //
1175  // <CODE>
1176  // top_n = stack.top().first;
1177  // top_operation = stack.top().second;
1178  // </CODE>
1179  const dimension_type top_n = stack[stack_first_empty - 1].first;
1180  const signed char top_operation = stack[stack_first_empty - 1].second;
1181 
1182  switch (top_operation) {
1183 
1184  case 0:
1185  root.get_parent();
1186  --stack_first_empty;
1187  continue;
1188 
1189  case 1:
1190  root.get_left_child();
1191  break;
1192 
1193  case 2:
1194  root.get_right_child();
1195  break;
1196 
1197 #ifndef NDEBUG
1198  case 3:
1199  break;
1200 
1201  default:
1202  PPL_UNREACHABLE;
1203  break;
1204 #endif
1205  }
1206 
1207  // We now visit the current tree
1208 
1209  if (top_n == 0) {
1210  --stack_first_empty;
1211  }
1212  else {
1213  if (top_n == 1) {
1214  PPL_ASSERT(root.index() == unused_index);
1215  PPL_ASSERT(tree.indexes[source_index] != unused_index);
1216  root.index() = tree.indexes[source_index];
1217  tree.indexes[source_index] = unused_index;
1218  move_data_element(*root, tree.data[source_index]);
1219  PPL_ASSERT(source_index <= tree.reserved_size);
1220  ++source_index;
1221  while (tree.indexes[source_index] == unused_index) {
1222  ++source_index;
1223  }
1224  --stack_first_empty;
1225  }
1226  else {
1227  PPL_ASSERT(stack_first_empty + 3 < sizeof(stack)/sizeof(stack[0]));
1228 
1229  const dimension_type half = (top_n + 1) / 2;
1230  stack[stack_first_empty - 1].second = 0;
1231  stack[stack_first_empty ] = std::make_pair(top_n - half, 2);
1232  stack[stack_first_empty + 1] = std::make_pair(1, 3);
1233  stack[stack_first_empty + 2].second = 0;
1234  stack[stack_first_empty + 3] = std::make_pair(half - 1, 1);
1235  stack_first_empty += 4;
1236  }
1237  }
1238  }
1239  size_ = tree.size_;
1240  tree.size_ = 0;
1241  PPL_ASSERT(tree.structure_OK());
1242  PPL_ASSERT(structure_OK());
1243 }
1244 
1245 void
1247  PPL_ASSERT(size_ == 0);
1248  PPL_ASSERT(reserved_size == x.reserved_size);
1249  PPL_ASSERT(structure_OK());
1250 
1251  if (x.size_ == 0) {
1252  PPL_ASSERT(OK());
1253  return;
1254  }
1255 
1256  dimension_type i;
1257  try {
1258  for (i = x.reserved_size; i > 0; --i) {
1259  if (x.indexes[i] != unused_index) {
1260  indexes[i] = x.indexes[i];
1261  new(&(data[i])) data_type(x.data[i]);
1262  }
1263  else {
1264  PPL_ASSERT(indexes[i] == unused_index);
1265  }
1266  }
1267  } catch (...) {
1268  // The (used) data elements in (i,x.reserved_size] have been constructed
1269  // successfully.
1270  // The constructor of data[i] has thrown an exception, so data[i] has not
1271  // been constructed.
1272 
1273  // 1. Destroy the data elements that have been constructed successfully.
1274  for (dimension_type j = x.reserved_size; j > i; --j) {
1275  if (indexes[j] != unused_index) {
1276  data[j].~data_type();
1277  }
1278  }
1279 
1280  // 2. Deallocate index[] and data[]
1281  delete[] indexes;
1282  data_allocator.deallocate(data, reserved_size + 1);
1283 
1284  // 3. Set the tree to an empty tree and rethrow exception.
1285  init(0);
1286  throw;
1287  }
1288 
1289  size_ = x.size_;
1290  PPL_ASSERT(OK());
1291 }
1292 
1295  dimension_type n = 0;
1296 
1297  const dimension_type k = itr.get_offset();
1298  const dimension_type root_index = itr.dfs_index();
1299 
1300  // The complete subtree rooted at itr has 2*k - 1 nodes.
1301 
1302  PPL_ASSERT(root_index > (k - 1));
1303 
1304  const dimension_type* current_index
1305  = &(itr.tree.indexes[root_index - (k - 1)]);
1306 
1307  for (dimension_type j = 2*k - 1; j > 0; --j, ++current_index) {
1308  if (*current_index != unused_index) {
1309  ++n;
1310  }
1311  }
1312 
1313  return n;
1314 }
1315 
1316 bool
1317 PPL::CO_Tree::const_iterator::OK() const {
1318 #if PPL_CO_TREE_EXTRA_DEBUG
1319  if (tree == 0) {
1320  if (current_index != 0) {
1321  return false;
1322  }
1323  if (current_data != 0) {
1324  return false;
1325  }
1326  }
1327  else
1328  if (tree->reserved_size == 0) {
1329  if (current_index != 1 + static_cast<dimension_type*>(0)
1330  || current_data != 1 + static_cast<data_type*>(0)) {
1331  return false;
1332  }
1333  }
1334  else {
1335  if (current_index <= &(tree->indexes[0])) {
1336  return false;
1337  }
1338  if (current_index > &(tree->indexes[tree->reserved_size + 1])) {
1339  return false;
1340  }
1341  if (current_data <= &(tree->data[0])) {
1342  return false;
1343  }
1344  if (current_data > &(tree->data[tree->reserved_size + 1])) {
1345  return false;
1346  }
1347  if (*current_index == unused_index) {
1348  return false;
1349  }
1350  if (current_index - tree->indexes != current_data - tree->data) {
1351  return false;
1352  }
1353  }
1354 #endif
1355  return true;
1356 }
1357 
1358 bool
1359 PPL::CO_Tree::iterator::OK() const {
1360 #if PPL_CO_TREE_EXTRA_DEBUG
1361  if (tree == 0) {
1362  if (current_index != 0) {
1363  return false;
1364  }
1365  if (current_data != 0) {
1366  return false;
1367  }
1368  }
1369  else
1370  if (tree->reserved_size == 0) {
1371  if (current_index != 1 + static_cast<dimension_type*>(0)
1372  || current_data != 1 + static_cast<data_type*>(0)) {
1373  return false;
1374  }
1375  }
1376  else {
1377  if (current_index <= &(tree->indexes[0])) {
1378  return false;
1379  }
1380  if (current_index > &(tree->indexes[tree->reserved_size + 1])) {
1381  return false;
1382  }
1383  if (current_data <= &(tree->data[0])) {
1384  return false;
1385  }
1386  if (current_data > &(tree->data[tree->reserved_size + 1])) {
1387  return false;
1388  }
1389  if (*current_index == unused_index) {
1390  return false;
1391  }
1392  if (current_index - tree->indexes != current_data - tree->data) {
1393  return false;
1394  }
1395  }
1396 #endif
1397  return true;
1398 }
1399 
1400 bool
1401 PPL::CO_Tree::tree_iterator::OK() const {
1402  if (i == 0 || i > tree.reserved_size) {
1403  return false;
1404  }
1405 
1406  // This assumes two's complement encoding.
1407  const dimension_type correct_offset = i & -i;
1408 
1409  if (offset != correct_offset) {
1410  return false;
1411  }
1412 
1413  return true;
1414 }
1415 
1416 void
1417 PPL::CO_Tree::tree_iterator::go_down_searching_key(dimension_type key) {
1418  // *this points to a node, so the tree is not empty.
1419  PPL_ASSERT(!tree.empty());
1420  PPL_ASSERT(key != unused_index);
1421  PPL_ASSERT(index() != unused_index);
1422  while (!is_leaf()) {
1423  if (key == index()) {
1424  break;
1425  }
1426  if (key < index()) {
1427  get_left_child();
1428  if (index() == unused_index) {
1429  get_parent();
1430  break;
1431  }
1432  }
1433  else {
1434  get_right_child();
1435  if (index() == unused_index) {
1436  get_parent();
1437  break;
1438  }
1439  }
1440  }
1441 }
dimension_type index() const
Returns the index of the element pointed to by *this.
void increase_keys_from(dimension_type key, dimension_type n)
Adds n to all keys greater than or equal to key.
Definition: CO_Tree.cc:196
void swap(CO_Tree &x, CO_Tree &y)
Coefficient data_type
The type of the data elements associated with keys.
void init(dimension_type n)
Initializes a tree with reserved size at least n .
Definition: CO_Tree.cc:607
size_t dimension_type
An unsigned integral type for representing space dimensions.
bool OK() const
Checks the internal invariants.
Definition: CO_Tree.cc:752
static void dump_subtree(tree_iterator itr)
Dumps the subtree rooted at itr to stdout, for debugging purposes.
Definition: CO_Tree.cc:798
static unsigned integer_log2(dimension_type n)
Returns the floor of the base-2 logarithm of n .
Definition: CO_Tree.cc:787
void destroy()
Deallocates the tree's dynamic arrays.
Definition: CO_Tree.cc:649
dimension_type get_offset() const
Returns 2^h, with h the height of the current node in the tree, counting from 0.
dimension_type dfs_index() const
Returns the index of the current node in the DFS layout of the complete tree.
void get_parent()
Makes the iterator point to the parent of the current node.
iterator begin()
Returns an iterator that points at the first element.
data_type * data
The vector that contains the data of the keys in the tree.
bool is_right_child() const
Returns true if the pointed node has a parent and is its right child.
bool is_leaf() const
Returns true if the pointed node is a leaf of the complete tree.
An iterator on the tree elements, ordered by key.
dimension_type * indexes
The vector that contains the keys in the tree.
unsigned height_t
This is used for node heights and depths in the tree.
tree_iterator insert_precise_aux(dimension_type key, data_type_const_reference data, tree_iterator itr)
Helper for insert_precise.
Definition: CO_Tree.cc:456
const iterator & end()
Returns an iterator that points after the last element.
iterator bisect_in(iterator first, iterator last, dimension_type key)
Searches an element with key key in [first, last] using bisection.
void get_left_child()
Makes the iterator point to the left child of the current node.
tree_iterator rebalance(tree_iterator itr, dimension_type key, data_type_const_reference value)
Rebalances the tree.
Definition: CO_Tree.cc:868
iterator insert(dimension_type key)
Inserts an element in the tree.
dimension_type reserved_size
The number of nodes in the complete tree.
#define sizeof_to_bits(size)
Definition: compiler.hh:80
Enable_If< Is_Native< T >::value, memory_size_type >::type external_memory_in_bytes(const T &)
For native types, returns the size in bytes of the memory managed by the type of the (unused) paramet...
A cache-oblivious binary search tree of pairs.
void follow_left_children_with_value()
Follows left children with a value, until it arrives at a leaf or at a node with no value...
dimension_type compact_elements_in_the_rightmost_end(dimension_type last_in_subtree, dimension_type subtree_size, dimension_type key, data_type_const_reference value, bool add_element)
Moves all elements of a subtree to the rightmost end.
Definition: CO_Tree.cc:951
Coefficient value
Definition: PIP_Tree.cc:618
CO_Tree & tree
The tree containing the element pointed to by this iterator.
dimension_type & index()
Returns a reference to the index of the element pointed to by *this.
tree_iterator insert_precise(dimension_type key, data_type_const_reference data, tree_iterator itr)
Inserts an element in the tree.
Definition: CO_Tree.cc:401
Coefficient_traits::const_reference data_type_const_reference
Coefficient_traits::const_reference Coefficient_zero()
Returns a const reference to a Coefficient with value 0.
The entire library is confined to this namespace.
Definition: version.hh:61
A const iterator on the tree elements, ordered by key.
height_t depth() const
Returns the depth of the current node in the complete tree.
void rebuild_bigger_tree()
Increases the tree's reserved size.
Definition: CO_Tree.cc:819
void get_root()
Makes the iterator point to the root of tree.
static dimension_type count_used_in_subtree(tree_iterator itr)
Counts the number of used elements in the subtree rooted at itr.
Definition: CO_Tree.cc:1294
dimension_type size_
The number of values stored in the tree.
bool structure_OK() const
Checks the internal invariants, but not the densities.
Definition: CO_Tree.cc:664
void follow_right_children_with_value()
Follows right children with a value, until it arrives at a leaf or at a node with no value...
iterator erase(dimension_type key)
Erases the element with key key from the tree.
void erase_element_and_shift_left(dimension_type key)
Removes the element with key key (if it exists) and decrements by 1 all elements' keys that were grea...
Definition: CO_Tree.cc:179
iterator bisect_near(iterator hint, dimension_type key)
Searches an element with key key near hint.
dimension_type index() const
Returns the index of the element pointed to by *this.
void move_data_from(CO_Tree &tree)
Moves all data in the tree tree into *this.
Definition: CO_Tree.cc:1133
dimension_type external_memory_in_bytes() const
Returns the size in bytes of the memory managed by *this.
Definition: CO_Tree.cc:30
void redistribute_elements_in_subtree(dimension_type root_index, dimension_type subtree_size, dimension_type last_used, dimension_type key, data_type_const_reference value, bool add_element)
Redistributes the elements in the subtree rooted at root_index.
Definition: CO_Tree.cc:1038
void get_right_child()
Makes the iterator point to the right child of the current node.
void copy_data_from(const CO_Tree &tree)
Copies all data in the tree tree into *this.
Definition: CO_Tree.cc:1246
void go_down_searching_key(dimension_type key)
Searches for an element with key key in the subtree rooted at *this.
Definition: CO_Tree.cc:1417