24 #include "ppl-config.h"
38 itr != itr_end; ++itr) {
45 PPL::CO_Tree::iterator
47 PPL_ASSERT(key1 != unused_index);
58 iterator candidate1 = bisect_near(itr, key1);
60 if (key1 == candidate1.
index()) {
66 if (key1 < candidate1.
index()) {
68 while (indexes[candidate2_index] == unused_index) {
74 while (indexes[candidate2_index] == unused_index) {
81 PPL_ASSERT(candidate2_index <= reserved_size + 1);
83 if (candidate2_index == 0 || candidate2_index > reserved_size) {
97 PPL_ASSERT(candidate1_node.
depth() > candidate2_node.
depth());
104 PPL_ASSERT(candidate1_node.
depth() < candidate2_node.
depth());
112 PPL::CO_Tree::iterator
115 PPL_ASSERT(key1 != unused_index);
118 insert_in_empty_tree(key1, data1);
123 return insert(key1, data1);
126 iterator candidate1 = bisect_near(itr, key1);
128 if (key1 == candidate1.
index()) {
135 if (key1 < candidate1.
index()) {
137 while (indexes[candidate2_index] == unused_index) {
144 while (indexes[candidate2_index] == unused_index) {
152 if (candidate2_index == 0 || candidate2_index > reserved_size) {
154 return iterator(insert_precise(key1, data1, candidate1_node));
165 PPL_ASSERT(candidate1_node.
depth() > candidate2_node.
depth());
168 return iterator(insert_precise(key1, data1, candidate1_node));
171 PPL_ASSERT(candidate1_node.
depth() < candidate2_node.
depth());
174 return iterator(insert_precise(key1, data1, candidate2_node));
186 const dimension_type*
const p_end = indexes + (reserved_size + 1);
187 for ( ; p != p_end; ++p) {
188 if (*p != unused_index) {
201 while (*p == unused_index) {
204 while (p != indexes && *p >= key) {
207 while (*p == unused_index) {
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);
223 while (first < last) {
227 while (indexes[new_half] == unused_index) {
231 if (indexes[new_half] == key) {
235 if (indexes[new_half] > key) {
237 while (indexes[half] == unused_index) {
247 while (indexes[new_half] == unused_index) {
263 PPL_ASSERT(hint != 0);
264 PPL_ASSERT(hint <= reserved_size);
265 PPL_ASSERT(indexes[hint] != unused_index);
267 if (indexes[hint] == key) {
274 if (indexes[hint] > key) {
279 if (hint <= offset) {
284 while (indexes[hint] == unused_index) {
288 if (indexes[hint] >= key) {
296 new_hint = hint - offset;
299 PPL_ASSERT(new_hint > 0);
300 PPL_ASSERT(new_hint <= reserved_size);
303 while (indexes[new_hint] == unused_index) {
307 PPL_ASSERT(new_hint <= hint);
309 if (indexes[new_hint] == key) {
313 if (indexes[new_hint] < key) {
316 swap(hint, new_hint);
330 if (hint + offset > reserved_size) {
332 new_hint = reserved_size;
334 while (indexes[new_hint] == unused_index) {
337 if (indexes[new_hint] <= key) {
345 new_hint = hint + offset;
348 PPL_ASSERT(new_hint > 0);
349 PPL_ASSERT(new_hint <= reserved_size);
352 while (indexes[new_hint] == unused_index) {
356 PPL_ASSERT(hint <= new_hint);
358 if (indexes[new_hint] == key) {
362 if (indexes[new_hint] > key) {
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);
379 while (indexes[hint] == unused_index) {
383 if (hint == new_hint) {
389 while (indexes[new_hint] == unused_index) {
393 PPL_ASSERT(hint <= new_hint);
394 PPL_ASSERT(indexes[hint] != unused_index);
395 PPL_ASSERT(indexes[new_hint] != unused_index);
397 return bisect_in(hint, new_hint, key);
400 PPL::CO_Tree::tree_iterator
404 PPL_ASSERT(key1 != unused_index);
405 PPL_ASSERT(!
empty());
411 PPL_ASSERT(itr == itr2);
414 if (itr.
index() == key1) {
422 const bool invalidating
423 = (data <= &data1) && (&data1 < data + (reserved_size + 1));
426 return insert_precise_aux(key1, data1, itr);
435 PPL_ASSERT(key2 != unused_index);
437 PPL_ASSERT(key2 != key1);
445 PPL_ASSERT(itr.
index() == key1);
449 swap(*itr, data1_copy);
455 PPL::CO_Tree::tree_iterator
459 PPL_ASSERT(key1 != unused_index);
460 PPL_ASSERT(!
empty());
462 PPL_ASSERT(itr.
index() != key1);
464 PPL_ASSERT(!(data <= &data1 && &data1 < data + (reserved_size + 1)));
466 if (is_greater_than_ratio(size_ + 1, reserved_size, max_density_percent)) {
467 rebuild_bigger_tree();
471 PPL_ASSERT(itr.
index() != key1);
474 PPL_ASSERT(!is_greater_than_ratio(size_ + 1, reserved_size,
475 max_density_percent));
480 if (key1 < itr.
index()) {
486 PPL_ASSERT(itr.
index() == unused_index);
493 itr = rebalance(itr, key1, data1);
495 PPL_ASSERT(itr.
index() == key1);
502 PPL::CO_Tree::iterator
504 PPL_ASSERT(itr.
index() != unused_index);
506 PPL_ASSERT(size_ != 0);
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)) {
520 PPL_ASSERT(!is_greater_than_ratio(size_, reserved_size,
521 max_density_percent));
523 rebuild_smaller_tree();
527 PPL_ASSERT(itr.
index() == key);
532 PPL_ASSERT(!is_less_than_ratio(size_ - 1, reserved_size,
534 || is_greater_than_ratio(size_ - 1, reserved_size/2,
535 max_density_percent));
549 if (itr.
index() != unused_index) {
557 if (itr.
index() != unused_index) {
569 move_data_element(current_data, *itr);
572 PPL_ASSERT(itr.
index() != unused_index);
573 itr.
index() = unused_index;
589 if (result.
index() < deleted_key) {
594 PPL_ASSERT(result == end() || result.
index() > deleted_key);
599 PPL_ASSERT((result == end()) == (last.
index() < deleted_key));
622 data = data_allocator.allocate(new_reserved_size + 1);
630 max_depth = new_max_depth;
631 reserved_size = new_reserved_size;
635 indexes[i] = unused_index;
640 indexes[reserved_size + 1] = 0;
643 refresh_cached_iterators();
645 PPL_ASSERT(structure_OK());
651 if (reserved_size != 0) {
653 if (indexes[i] != unused_index) {
654 data[i].~data_type();
659 data_allocator.deallocate(data, reserved_size + 1);
666 if (size_ > reserved_size) {
670 if (reserved_size == 0) {
671 if (indexes != NULL) {
677 if (max_depth != 0) {
684 if (reserved_size < 3) {
687 if (reserved_size != (static_cast<dimension_type>(1) << max_depth) - 1) {
695 if (indexes == NULL) {
699 if (max_depth == 0) {
708 if (itr.
index() != unused_index) {
718 if (real_size != size_) {
729 if (itr != itr_end) {
731 for (++itr; itr != itr_end; ++itr) {
732 if (last_index >= itr.
index()) {
736 last_index = itr.
index();
744 if (cached_const_end !=
const_iterator(*
this, reserved_size + 1)) {
754 if (!structure_OK()) {
760 for (
const_iterator itr = begin(), itr_end = end(); itr != itr_end; ++itr) {
764 if (real_size != size_) {
770 if (reserved_size > 0) {
771 if (is_greater_than_ratio(size_, reserved_size, max_density_percent)
772 && reserved_size != 3) {
776 if (is_less_than_ratio(size_, reserved_size, min_density_percent)
777 && !is_greater_than_ratio(size_, reserved_size/2, max_density_percent)) {
804 std::cout <<
"At depth: " << itr.
depth();
805 if (itr.
index() == unused_index) {
806 std::cout <<
" (no data)" << std::endl;
809 std::cout <<
" pair (" << itr.
index() <<
"," << *itr <<
")" << std::endl;
820 if (reserved_size == 0) {
822 PPL_ASSERT(structure_OK());
833 new_data = data_allocator.allocate(new_reserved_size + 1);
835 delete[] new_indexes;
839 new_indexes[1] = unused_index;
842 new_indexes[j] = indexes[i];
843 if (indexes[i] != unused_index) {
844 move_data_element(new_data[j], data[i]);
847 new_indexes[j] = unused_index;
852 new_indexes[new_reserved_size + 1] = 0;
855 data_allocator.deallocate(data, reserved_size + 1);
857 indexes = new_indexes;
859 reserved_size = new_reserved_size;
862 refresh_cached_iterators();
864 PPL_ASSERT(structure_OK());
867 PPL::CO_Tree::tree_iterator
874 if (reserved_size == 3) {
878 PPL_ASSERT(itr.
index() == unused_index || itr.
is_leaf());
880 const height_t height = max_depth - itr_depth_minus_1;
884 const bool deleting = itr.
index() == unused_index;
885 PPL_ASSERT(deleting || key != unused_index);
894 while (is_greater_than_ratio(subtree_size, subtree_reserved_size,
896 + ((itr_depth_minus_1
897 * (100 - max_density_percent))
899 || is_less_than_ratio(subtree_size, subtree_reserved_size,
901 - ((itr_depth_minus_1
902 * (min_density_percent
903 - min_leaf_density_percent))
904 / (max_depth - 1)))) {
907 PPL_ASSERT(itr_depth_minus_1 != 0);
910 if (is_right_brother) {
916 subtree_size += count_used_in_subtree(itr);
918 PPL_ASSERT(itr.
index() != unused_index);
920 subtree_reserved_size = 2*subtree_reserved_size + 1;
922 PPL_ASSERT(itr.
depth() - 1 == itr_depth_minus_1);
934 = compact_elements_in_the_rightmost_end(last_index_in_subtree,
935 subtree_size, key, value,
939 redistribute_elements_in_subtree(itr.
dfs_index(), subtree_size,
940 first_unused + 1, key,
value,
941 first_unused != last_index_in_subtree
957 PPL_ASSERT(subtree_size != 0);
959 PPL_ASSERT(subtree_size != 1 || !add_element);
961 dimension_type* last_index_in_subtree = &(indexes[last_in_subtree]);
962 data_type* last_data_in_subtree = &(data[last_in_subtree]);
965 data_type* first_unused_data = last_data_in_subtree;
967 while (*last_index_in_subtree == unused_index) {
968 --last_index_in_subtree;
969 --last_data_in_subtree;
977 while (subtree_size != 0) {
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);
986 *first_unused_index = key;
987 --first_unused_index;
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);
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;
1007 --first_unused_index;
1008 --first_unused_data;
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);
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;
1027 --first_unused_index;
1028 --first_unused_data;
1032 const std::ptrdiff_t distance = first_unused_index - indexes;
1033 PPL_ASSERT(distance >= 0);
1052 static std::pair<dimension_type,dimension_type>
1055 std::pair<dimension_type,dimension_type>* stack_first_empty = stack;
1060 PPL_ASSERT(subtree_size != 0);
1062 stack_first_empty->first = subtree_size;
1063 stack_first_empty->second = root_index;
1064 ++stack_first_empty;
1066 while (stack_first_empty != stack) {
1068 --stack_first_empty;
1079 PPL_ASSERT(top_n != 0);
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;
1088 indexes[top_i] = key;
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]);
1101 PPL_ASSERT(stack_first_empty + 2
1102 < stack +
sizeof(stack)/
sizeof(stack[0]));
1107 PPL_ASSERT(half > 0);
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;
1116 stack_first_empty->first = 1;
1117 stack_first_empty->second = top_i;
1118 ++stack_first_empty;
1121 if (half - 1 != 0) {
1122 stack_first_empty->first = half - 1;
1123 stack_first_empty->second = top_i - offset;
1124 ++stack_first_empty;
1129 PPL_ASSERT(!add_element);
1134 PPL_ASSERT(size_ == 0);
1135 if (tree.
size_ == 0) {
1142 while (tree.
indexes[source_index] == unused_index) {
1153 static std::pair<dimension_type, signed char>
1167 stack[0].first = tree.
size_;
1168 stack[0].second = 3;
1169 ++stack_first_empty;
1171 while (stack_first_empty != 0) {
1180 const signed char top_operation = stack[stack_first_empty - 1].second;
1182 switch (top_operation) {
1186 --stack_first_empty;
1210 --stack_first_empty;
1214 PPL_ASSERT(root.
index() == unused_index);
1215 PPL_ASSERT(tree.
indexes[source_index] != unused_index);
1217 tree.
indexes[source_index] = unused_index;
1218 move_data_element(*root, tree.
data[source_index]);
1221 while (tree.
indexes[source_index] == unused_index) {
1224 --stack_first_empty;
1227 PPL_ASSERT(stack_first_empty + 3 <
sizeof(stack)/
sizeof(stack[0]));
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;
1242 PPL_ASSERT(structure_OK());
1247 PPL_ASSERT(size_ == 0);
1249 PPL_ASSERT(structure_OK());
1259 if (x.
indexes[i] != unused_index) {
1264 PPL_ASSERT(indexes[i] == unused_index);
1275 if (indexes[j] != unused_index) {
1276 data[j].~data_type();
1282 data_allocator.deallocate(data, reserved_size + 1);
1302 PPL_ASSERT(root_index > (k - 1));
1308 if (*current_index != unused_index) {
1317 PPL::CO_Tree::const_iterator::OK()
const {
1318 #if PPL_CO_TREE_EXTRA_DEBUG
1320 if (current_index != 0) {
1323 if (current_data != 0) {
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)) {
1335 if (current_index <= &(tree->indexes[0])) {
1338 if (current_index > &(tree->indexes[tree->reserved_size + 1])) {
1341 if (current_data <= &(tree->data[0])) {
1344 if (current_data > &(tree->data[tree->reserved_size + 1])) {
1347 if (*current_index == unused_index) {
1350 if (current_index - tree->indexes != current_data - tree->data) {
1359 PPL::CO_Tree::iterator::OK()
const {
1360 #if PPL_CO_TREE_EXTRA_DEBUG
1362 if (current_index != 0) {
1365 if (current_data != 0) {
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)) {
1377 if (current_index <= &(tree->indexes[0])) {
1380 if (current_index > &(tree->indexes[tree->reserved_size + 1])) {
1383 if (current_data <= &(tree->data[0])) {
1386 if (current_data > &(tree->data[tree->reserved_size + 1])) {
1389 if (*current_index == unused_index) {
1392 if (current_index - tree->indexes != current_data - tree->data) {
1401 PPL::CO_Tree::tree_iterator::OK()
const {
1402 if (i == 0 || i > tree.reserved_size) {
1409 if (offset != correct_offset) {
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()) {
1426 if (key < index()) {
1428 if (index() == unused_index) {
1435 if (index() == unused_index) {
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.
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 .
size_t dimension_type
An unsigned integral type for representing space dimensions.
bool OK() const
Checks the internal invariants.
static void dump_subtree(tree_iterator itr)
Dumps the subtree rooted at itr to stdout, for debugging purposes.
static unsigned integer_log2(dimension_type n)
Returns the floor of the base-2 logarithm of n .
void destroy()
Deallocates the tree's dynamic arrays.
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.
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.
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)
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.
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.
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.
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.
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.
dimension_type size_
The number of values stored in the tree.
bool structure_OK() const
Checks the internal invariants, but not the densities.
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...
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.
dimension_type external_memory_in_bytes() const
Returns the size in bytes of the memory managed by *this.
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.
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.
void go_down_searching_key(dimension_type key)
Searches for an element with key key in the subtree rooted at *this.