diff --git a/CLAUDE.md b/CLAUDE.md new file mode 120000 index 00000000..01cf8311 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +README_BOTS.md \ No newline at end of file diff --git a/README_BOTS.md b/README_BOTS.md new file mode 100644 index 00000000..b3a49320 --- /dev/null +++ b/README_BOTS.md @@ -0,0 +1,29 @@ +# Useful Commands + +## Building +To build the project (for most code changes): + +``` +(mkdir -p build && cd build && cmake .. -DRUN_DOXYGEN=OFF -DBUILD_PYTHON_BINDINGS=OFF && make -j8) +``` + +If something looks weirdly wrong with the CMake configuration, you can `rm -Rf build` and try the build again. + +## Testing + +To run the tests after building: + +``` +./bin/test_libbdsg +``` + +The test code is in `bdsg/src/test_libbdsg.cpp`. It doesn't use a unit test framework, just a convention of test functions that check things with asserts. The tests should be ordered from low-level to high-level because we stop at the first failure. + +If you want to run just a single test, you need to comment out the calls to all the other test functions in the main function with `/* */` and rebuild. + +# Layout + +All the code is in `bdsg/src` and `bdsg/include/bdsg`. Dependencies (like the HandleGraph headers) are in `bdsg/deps`. + +The `*.classfragment` files in `bdsg/include/bdsg/internal` are used to assemble "proxy" objects that wrap and expose all the methods of a contained object which for technical reasons isn't actually allowed to inherit from a base class, in order to provide something that does actually inherit from that base class. Try not to fiddle with this system. + diff --git a/bdsg/cmake_bindings/bdsg/internal/mapped_structs_1.cpp b/bdsg/cmake_bindings/bdsg/internal/mapped_structs_1.cpp index 1435dda3..85e8dc63 100644 --- a/bdsg/cmake_bindings/bdsg/internal/mapped_structs_1.cpp +++ b/bdsg/cmake_bindings/bdsg/internal/mapped_structs_1.cpp @@ -57,8 +57,8 @@ void bind_bdsg_internal_mapped_structs_1(std::function< pybind11::module &(std:: cl.def("assign", (class bdsg::PackedDeque<> & (bdsg::PackedDeque::*)(const class bdsg::PackedDeque<> &)) &bdsg::PackedDeque<>::operator=, "C++: bdsg::PackedDeque<>::operator=(const class bdsg::PackedDeque<> &) --> class bdsg::PackedDeque<> &", pybind11::return_value_policy::automatic, pybind11::arg("other")); cl.def("set", (void (bdsg::PackedDeque::*)(const unsigned long &, const unsigned long &)) &bdsg::PackedDeque<>::set, "C++: bdsg::PackedDeque<>::set(const unsigned long &, const unsigned long &) --> void", pybind11::arg("i"), pybind11::arg("value")); cl.def("get", (unsigned long (bdsg::PackedDeque::*)(const unsigned long &) const) &bdsg::PackedDeque<>::get, "C++: bdsg::PackedDeque<>::get(const unsigned long &) const --> unsigned long", pybind11::arg("i")); - cl.def("append_front", (void (bdsg::PackedDeque::*)(const unsigned long &)) &bdsg::PackedDeque<>::append_front, "C++: bdsg::PackedDeque<>::append_front(const unsigned long &) --> void", pybind11::arg("value")); - cl.def("append_back", (void (bdsg::PackedDeque::*)(const unsigned long &)) &bdsg::PackedDeque<>::append_back, "C++: bdsg::PackedDeque<>::append_back(const unsigned long &) --> void", pybind11::arg("value")); + cl.def("push_front", (void (bdsg::PackedDeque::*)(const unsigned long &)) &bdsg::PackedDeque<>::push_front, "C++: bdsg::PackedDeque<>::push_front(const unsigned long &) --> void", pybind11::arg("value")); + cl.def("push_back", (void (bdsg::PackedDeque::*)(const unsigned long &)) &bdsg::PackedDeque<>::push_back, "C++: bdsg::PackedDeque<>::push_back(const unsigned long &) --> void", pybind11::arg("value")); cl.def("pop_front", (void (bdsg::PackedDeque::*)()) &bdsg::PackedDeque<>::pop_front, "C++: bdsg::PackedDeque<>::pop_front() --> void"); cl.def("pop_back", (void (bdsg::PackedDeque::*)()) &bdsg::PackedDeque<>::pop_back, "C++: bdsg::PackedDeque<>::pop_back() --> void"); cl.def("reserve", (void (bdsg::PackedDeque::*)(const unsigned long &)) &bdsg::PackedDeque<>::reserve, "C++: bdsg::PackedDeque<>::reserve(const unsigned long &) --> void", pybind11::arg("future_size")); diff --git a/bdsg/include/bdsg/internal/base_packed_graph.hpp b/bdsg/include/bdsg/internal/base_packed_graph.hpp index dd152ac4..5b11d4d7 100644 --- a/bdsg/include/bdsg/internal/base_packed_graph.hpp +++ b/bdsg/include/bdsg/internal/base_packed_graph.hpp @@ -1160,26 +1160,26 @@ size_t BasePackedGraph::new_node_record(nid_t node_id) { size_t next_g_iv_idx = graph_iv.size(); // no edges yet, null pointer for linked list - graph_iv.append(0); - graph_iv.append(0); + graph_iv.push_back(0); + graph_iv.push_back(0); // record the sequence interval - seq_start_iv.append(0); - seq_length_iv.append(0); + seq_start_iv.push_back(0); + seq_length_iv.push_back(0); // initialize an empty path membership list - path_membership_node_iv.append(0); + path_membership_node_iv.push_back(0); // expand the ID vector's dimensions so it can handle the full ID interval if (nid_to_graph_iv.empty()) { - nid_to_graph_iv.append_back(0); + nid_to_graph_iv.push_back(0); } else { for (int64_t i = node_id; i < min_id; i++) { - nid_to_graph_iv.append_front(0); + nid_to_graph_iv.push_front(0); } for (int64_t i = nid_to_graph_iv.size(); i <= node_id - min_id; i++) { - nid_to_graph_iv.append_back(0); + nid_to_graph_iv.push_back(0); } } @@ -1215,7 +1215,7 @@ handle_t BasePackedGraph::create_handle(const string& sequence, const n // encode the sequence interval for (size_t i = 0; i < sequence.size(); i++) { - seq_iv.append(encode_nucleotide(sequence[i])); + seq_iv.push_back(encode_nucleotide(sequence[i])); } return get_handle(id); @@ -1243,8 +1243,8 @@ void BasePackedGraph::create_edge(const handle_t& left, const handle_t& GRAPH_START_EDGES_OFFSET); // add a new linked list node pointing to the rest of the list - edge_lists_iv.append(encode_traversal(right)); - edge_lists_iv.append(graph_iv.get(g_iv_left)); + edge_lists_iv.push_back(encode_traversal(right)); + edge_lists_iv.push_back(graph_iv.get(g_iv_left)); // make this new node the head graph_iv.set(g_iv_left, edge_lists_iv.size() / EDGE_RECORD_SIZE); @@ -1255,8 +1255,8 @@ void BasePackedGraph::create_edge(const handle_t& left, const handle_t& } // add a new linked list node pointing to the rest of the list - edge_lists_iv.append(encode_traversal(flip(left))); - edge_lists_iv.append(graph_iv.get(g_iv_right)); + edge_lists_iv.push_back(encode_traversal(flip(left))); + edge_lists_iv.push_back(graph_iv.get(g_iv_right)); // make this new node the head graph_iv.set(g_iv_right, edge_lists_iv.size() / EDGE_RECORD_SIZE); } @@ -1570,14 +1570,14 @@ std::vector BasePackedGraph::divide_handle(const handle_t& ha seq_length_iv.set(graph_index_to_seq_len_index(g_iv_idx), off - last_offset); // create an edge forward onto the new node - edge_lists_iv.append(encode_traversal(get_handle(next_id))); - edge_lists_iv.append(0); + edge_lists_iv.push_back(encode_traversal(get_handle(next_id))); + edge_lists_iv.push_back(0); // add the edge onto the previous node graph_iv.set(g_iv_idx + GRAPH_END_EDGES_OFFSET, edge_lists_iv.size() / EDGE_RECORD_SIZE); // create an edge backward to the previous node - edge_lists_iv.append(encode_traversal(get_handle(prev_id, true))); - edge_lists_iv.append(0); + edge_lists_iv.push_back(encode_traversal(get_handle(prev_id, true))); + edge_lists_iv.push_back(0); // add the edge backwards to the current node graph_iv.set(new_g_iv_idx + GRAPH_START_EDGES_OFFSET, edge_lists_iv.size() / EDGE_RECORD_SIZE); @@ -1635,17 +1635,17 @@ std::vector BasePackedGraph::divide_handle(const handle_t& ha vector divided_trav_offsets{occ_idx}; for (size_t i = 1; i < return_val.size(); i++) { // the new traversals will have the same strandedness as the original occurrence - packed_path.steps_iv.append(encode_traversal(path_trav_rev ? flip(return_val[i]) : return_val[i])); - packed_path.links_iv.append(0); - packed_path.links_iv.append(0); + packed_path.steps_iv.push_back(encode_traversal(path_trav_rev ? flip(return_val[i]) : return_val[i])); + packed_path.links_iv.push_back(0); + packed_path.links_iv.push_back(0); divided_trav_offsets.push_back(packed_path.steps_iv.size() / STEP_RECORD_SIZE); // record the membership of this node in this path size_t node_member_idx = graph_index_to_node_member_index(graph_iv_index(return_val[i])); - path_membership_id_iv.append(get_membership_path(path_membership)); - path_membership_offset_iv.append(packed_path.steps_iv.size() / STEP_RECORD_SIZE); - path_membership_next_iv.append(path_membership_node_iv.get(node_member_idx)); + path_membership_id_iv.push_back(get_membership_path(path_membership)); + path_membership_offset_iv.push_back(packed_path.steps_iv.size() / STEP_RECORD_SIZE); + path_membership_next_iv.push_back(path_membership_node_iv.get(node_member_idx)); // make this new membership record the head of the linked list path_membership_node_iv.set(node_member_idx, path_membership_next_iv.size() / MEMBERSHIP_NEXT_RECORD_SIZE); @@ -1774,7 +1774,7 @@ handle_t BasePackedGraph::change_sequence(const handle_t& handle, const // the new sequence doesn't fit, add it at the end seq_start_iv.set(graph_index_to_seq_start_index(g_iv_index), seq_iv.size()); for (size_t i = 0; i < sequence.size(); ++i) { - seq_iv.append(encode_nucleotide(sequence[i])); + seq_iv.push_back(encode_nucleotide(sequence[i])); } deleted_bases += seq_len; } @@ -1876,9 +1876,9 @@ void BasePackedGraph::defragment_path(const int64_t& path_idx, bool for size_t prev = 0; while (copying_from != 0 && (first_iter || copying_from != path_head_iv.get(path_idx))) { // make a new record - new_steps_iv.append(get_step_trav(path, copying_from)); - new_links_iv.append(prev); - new_links_iv.append(0); + new_steps_iv.push_back(get_step_trav(path, copying_from)); + new_links_iv.push_back(prev); + new_links_iv.push_back(0); size_t here = new_steps_iv.size() / STEP_RECORD_SIZE; @@ -1915,7 +1915,7 @@ void BasePackedGraph::defragment_path(const int64_t& path_idx, bool for // records (even if the node occurs multiple times on this path), so we will use a bit deque // indexed by node_id - min_id to flag nodes as either translated or untranslated PackedDeque<> nid_translated; - nid_translated.append_back(0); + nid_translated.push_back(0); nid_t min_translated_id = get_id(decode_traversal(get_step_trav(path, path_head_iv.get(path_idx)))); first_iter = true; @@ -1929,13 +1929,13 @@ void BasePackedGraph::defragment_path(const int64_t& path_idx, bool for // expand the bounds of the deque as necessary to be able to index by ID if (step_node_id < min_translated_id) { for (nid_t i = step_node_id; i < min_translated_id; ++i) { - nid_translated.append_front(0); + nid_translated.push_front(0); } min_translated_id = step_node_id; } else if (step_node_id >= min_translated_id + nid_translated.size()) { for (nid_t i = min_translated_id + nid_translated.size(); i <= step_node_id; ++i) { - nid_translated.append_back(0); + nid_translated.push_back(0); } } @@ -2048,49 +2048,49 @@ void BasePackedGraph::eject_deleted_paths() { decltype(path_name_start_iv) new_path_name_start_iv; new_path_name_start_iv.reserve(paths.size()); for (size_t i = 0; i < paths.size(); ++i) { - new_path_name_start_iv.append(path_name_start_iv.get(i)); + new_path_name_start_iv.push_back(path_name_start_iv.get(i)); } path_name_start_iv = std::move(new_path_name_start_iv); PackedVector<> new_path_name_length_iv; new_path_name_length_iv.reserve(paths.size()); for (size_t i = 0; i < paths.size(); ++i) { - new_path_name_length_iv.append(path_name_length_iv.get(i)); + new_path_name_length_iv.push_back(path_name_length_iv.get(i)); } path_name_length_iv = std::move(new_path_name_length_iv); PackedVector<> new_path_is_deleted_iv; new_path_is_deleted_iv.reserve(paths.size()); for (size_t i = 0; i < paths.size(); ++i) { - new_path_is_deleted_iv.append(path_is_deleted_iv.get(i)); + new_path_is_deleted_iv.push_back(path_is_deleted_iv.get(i)); } path_is_deleted_iv = std::move(new_path_is_deleted_iv); PackedVector<> new_path_is_circular_iv; new_path_is_circular_iv.reserve(paths.size()); for (size_t i = 0; i < paths.size(); ++i) { - new_path_is_circular_iv.append(path_is_circular_iv.get(i)); + new_path_is_circular_iv.push_back(path_is_circular_iv.get(i)); } path_is_circular_iv = std::move(new_path_is_circular_iv); decltype(path_head_iv) new_path_head_iv; new_path_head_iv.reserve(paths.size()); for (size_t i = 0; i < paths.size(); ++i) { - new_path_head_iv.append(path_head_iv.get(i)); + new_path_head_iv.push_back(path_head_iv.get(i)); } path_head_iv = std::move(new_path_head_iv); decltype(path_tail_iv) new_path_tail_iv; new_path_tail_iv.reserve(paths.size()); for (size_t i = 0; i < paths.size(); ++i) { - new_path_tail_iv.append(path_tail_iv.get(i)); + new_path_tail_iv.push_back(path_tail_iv.get(i)); } path_tail_iv = std::move(new_path_tail_iv); PackedVector<> new_path_deleted_steps_iv; new_path_deleted_steps_iv.reserve(paths.size()); for (size_t i = 0; i < paths.size(); ++i) { - new_path_deleted_steps_iv.append(path_deleted_steps_iv.get(i)); + new_path_deleted_steps_iv.push_back(path_deleted_steps_iv.get(i)); } path_deleted_steps_iv = std::move(new_path_deleted_steps_iv); @@ -2140,7 +2140,7 @@ void BasePackedGraph::tighten() { new_nid_to_graph_iv.reserve(nid_to_graph_iv.size()); // transfer of the data for (size_t i = 0; i < nid_to_graph_iv.size(); i++) { - new_nid_to_graph_iv.append_back(nid_to_graph_iv.get(i)); + new_nid_to_graph_iv.push_back(nid_to_graph_iv.get(i)); } // replace the old one nid_to_graph_iv = std::move(new_nid_to_graph_iv); @@ -2161,7 +2161,7 @@ void BasePackedGraph::tighten() { seq_start_iv.set(i, new_seq_iv.size()); // transfer the actual sequence over for (size_t j = begin; j < end; j++) { - new_seq_iv.append(seq_iv.get(j)); + new_seq_iv.push_back(seq_iv.get(j)); } } // replace the old seq iv @@ -2211,11 +2211,11 @@ void BasePackedGraph::defragment(bool force) { if (raw_g_iv_idx) { size_t g_iv_idx = (raw_g_iv_idx - 1) * GRAPH_RECORD_SIZE; // this node still exists, create a new copy - new_graph_iv.append(graph_iv.get(g_iv_idx + GRAPH_START_EDGES_OFFSET)); - new_graph_iv.append(graph_iv.get(g_iv_idx + GRAPH_END_EDGES_OFFSET)); - new_seq_length_iv.append(seq_length_iv.get(graph_index_to_seq_len_index(g_iv_idx))); - new_seq_start_iv.append(seq_start_iv.get(graph_index_to_seq_start_index(g_iv_idx))); - new_path_membership_node_iv.append(path_membership_node_iv.get(graph_index_to_node_member_index(g_iv_idx))); + new_graph_iv.push_back(graph_iv.get(g_iv_idx + GRAPH_START_EDGES_OFFSET)); + new_graph_iv.push_back(graph_iv.get(g_iv_idx + GRAPH_END_EDGES_OFFSET)); + new_seq_length_iv.push_back(seq_length_iv.get(graph_index_to_seq_len_index(g_iv_idx))); + new_seq_start_iv.push_back(seq_start_iv.get(graph_index_to_seq_start_index(g_iv_idx))); + new_path_membership_node_iv.push_back(path_membership_node_iv.get(graph_index_to_node_member_index(g_iv_idx))); // update the pointer into graph_iv nid_to_graph_iv.set(i, new_graph_iv.size() / GRAPH_RECORD_SIZE); } @@ -2249,16 +2249,16 @@ void BasePackedGraph::defragment(bool force) { size_t edge_list_idx = graph_iv.get(g_iv_idx + edge_list_offset); if (edge_list_idx) { // add a new edge record - new_edge_lists_iv.append(get_edge_target(edge_list_idx)); - new_edge_lists_iv.append(0); + new_edge_lists_iv.push_back(get_edge_target(edge_list_idx)); + new_edge_lists_iv.push_back(0); // point the graph vector at this new edge list graph_iv.set(g_iv_idx + edge_list_offset, new_edge_lists_iv.size() / EDGE_RECORD_SIZE); edge_list_idx = get_next_edge_index(edge_list_idx); while (edge_list_idx) { // add a new edge record - new_edge_lists_iv.append(get_edge_target(edge_list_idx)); - new_edge_lists_iv.append(0); + new_edge_lists_iv.push_back(get_edge_target(edge_list_idx)); + new_edge_lists_iv.push_back(0); // point the previous link at this one new_edge_lists_iv.set(new_edge_lists_iv.size() - 2 * EDGE_RECORD_SIZE + EDGE_NEXT_OFFSET, new_edge_lists_iv.size() / EDGE_RECORD_SIZE); @@ -2298,9 +2298,9 @@ void BasePackedGraph::defragment(bool force) { uint64_t member_idx = path_membership_node_iv.get(graph_index_to_node_member_index(g_iv_idx)); if (member_idx) { // make a new membership record - new_path_membership_id_iv.append(get_membership_path(member_idx)); - new_path_membership_offset_iv.append(get_membership_step(member_idx)); - new_path_membership_next_iv.append(0); + new_path_membership_id_iv.push_back(get_membership_path(member_idx)); + new_path_membership_offset_iv.push_back(get_membership_step(member_idx)); + new_path_membership_next_iv.push_back(0); // point the membership vector here path_membership_node_iv.set(graph_index_to_node_member_index(g_iv_idx), @@ -2309,9 +2309,9 @@ void BasePackedGraph::defragment(bool force) { member_idx = get_next_membership(member_idx); while (member_idx) { // make a new membership record - new_path_membership_id_iv.append(get_membership_path(member_idx)); - new_path_membership_offset_iv.append(get_membership_step(member_idx)); - new_path_membership_next_iv.append(0); + new_path_membership_id_iv.push_back(get_membership_path(member_idx)); + new_path_membership_offset_iv.push_back(get_membership_step(member_idx)); + new_path_membership_next_iv.push_back(0); // point the previous link at this one new_path_membership_next_iv.set(new_path_membership_next_iv.size() - 2 * MEMBERSHIP_NEXT_RECORD_SIZE, new_path_membership_next_iv.size() / MEMBERSHIP_NEXT_RECORD_SIZE); @@ -2617,7 +2617,7 @@ PackedVector<> BasePackedGraph::encode_path_name(const string& path_nam template void BasePackedGraph::append_path_name(const string& path_name) { for (size_t i = 0; i < path_name.size(); ++i) { - path_names_iv.append(get_or_make_assignment(path_name.at(i))); + path_names_iv.push_back(get_or_make_assignment(path_name.at(i))); } } @@ -2748,13 +2748,13 @@ path_handle_t BasePackedGraph::create_path_handle(const string& name, b paths.emplace_back(); - path_name_start_iv.append(path_names_iv.size()); - path_name_length_iv.append(name.size()); - path_is_circular_iv.append(is_circular); - path_is_deleted_iv.append(false); - path_head_iv.append(0); - path_tail_iv.append(0); - path_deleted_steps_iv.append(0); + path_name_start_iv.push_back(path_names_iv.size()); + path_name_length_iv.push_back(name.size()); + path_is_circular_iv.push_back(is_circular); + path_is_deleted_iv.push_back(false); + path_head_iv.push_back(0); + path_tail_iv.push_back(0); + path_deleted_steps_iv.push_back(0); append_path_name(name); @@ -2767,9 +2767,9 @@ step_handle_t BasePackedGraph::append_step(const path_handle_t& path, c PackedPath& packed_path = paths.at(as_integer(path)); // create a new path record - packed_path.steps_iv.append(as_integer(to_append)); - packed_path.links_iv.append(path_tail_iv.get(as_integer(path))); - packed_path.links_iv.append(0); + packed_path.steps_iv.push_back(as_integer(to_append)); + packed_path.links_iv.push_back(path_tail_iv.get(as_integer(path))); + packed_path.links_iv.push_back(0); // the offset associated with the new record size_t step_offset = packed_path.steps_iv.size() / STEP_RECORD_SIZE; @@ -2793,9 +2793,9 @@ step_handle_t BasePackedGraph::append_step(const path_handle_t& path, c // record the membership of this node in this path size_t node_member_idx = graph_index_to_node_member_index(graph_iv_index(to_append)); - path_membership_id_iv.append(as_integer(path)); - path_membership_offset_iv.append(step_offset); - path_membership_next_iv.append(path_membership_node_iv.get(node_member_idx)); + path_membership_id_iv.push_back(as_integer(path)); + path_membership_offset_iv.push_back(step_offset); + path_membership_next_iv.push_back(path_membership_node_iv.get(node_member_idx)); // make this new membership record the head of the linked list path_membership_node_iv.set(node_member_idx, path_membership_next_iv.size() / MEMBERSHIP_NEXT_RECORD_SIZE); @@ -2813,9 +2813,9 @@ step_handle_t BasePackedGraph::prepend_step(const path_handle_t& path, PackedPath& packed_path = paths.at(as_integer(path)); // create a new path record - packed_path.steps_iv.append(as_integer(to_prepend)); - packed_path.links_iv.append(0); - packed_path.links_iv.append(path_head_iv.get(as_integer(path))); + packed_path.steps_iv.push_back(as_integer(to_prepend)); + packed_path.links_iv.push_back(0); + packed_path.links_iv.push_back(path_head_iv.get(as_integer(path))); // the offset associated with the new record size_t step_offset = packed_path.steps_iv.size() / STEP_RECORD_SIZE; @@ -2839,9 +2839,9 @@ step_handle_t BasePackedGraph::prepend_step(const path_handle_t& path, // record the membership of this node in this path size_t node_member_idx = graph_index_to_node_member_index(graph_iv_index(to_prepend)); - path_membership_id_iv.append(as_integer(path)); - path_membership_offset_iv.append(step_offset); - path_membership_next_iv.append(path_membership_node_iv.get(node_member_idx)); + path_membership_id_iv.push_back(as_integer(path)); + path_membership_offset_iv.push_back(step_offset); + path_membership_next_iv.push_back(path_membership_node_iv.get(node_member_idx)); // make this new membership record the head of the linked list path_membership_node_iv.set(node_member_idx, path_membership_next_iv.size() / MEMBERSHIP_NEXT_RECORD_SIZE); @@ -2938,9 +2938,9 @@ pair BasePackedGraph::rewrite_segment(con for (const handle_t& handle : new_segment) { // create a new step record - packed_path.steps_iv.append(encode_traversal(handle)); - packed_path.links_iv.append(0); - packed_path.links_iv.append(0); + packed_path.steps_iv.push_back(encode_traversal(handle)); + packed_path.links_iv.push_back(0); + packed_path.links_iv.push_back(0); uint64_t step_offset = packed_path.steps_iv.size() / STEP_RECORD_SIZE; @@ -2982,9 +2982,9 @@ pair BasePackedGraph::rewrite_segment(con // put a membership record for this occurrence at the front of the membership list size_t node_member_idx = graph_index_to_node_member_index(graph_iv_index(handle)); - path_membership_id_iv.append(as_integers(segment_end)[0]); - path_membership_offset_iv.append(step_offset); - path_membership_next_iv.append(path_membership_node_iv.get(node_member_idx)); + path_membership_id_iv.push_back(as_integers(segment_end)[0]); + path_membership_offset_iv.push_back(step_offset); + path_membership_next_iv.push_back(path_membership_node_iv.get(node_member_idx)); path_membership_node_iv.set(node_member_idx, path_membership_next_iv.size() / MEMBERSHIP_NEXT_RECORD_SIZE); if (first_iter) { @@ -3084,14 +3084,14 @@ void BasePackedGraph::reassign_node_ids(const std::function -inline void repack(IntVector& target, size_t new_width, size_t new_size); +inline void repack(IntVector& target, size_t new_width, size_t new_size); + + +/** + * A forward iterator for anything vector-like (PackedVector, PagedVector, + * etc.) that provides read-only access to elements and internally uses integer + * indexes. + * + * This iterator is invalidated if the backing object changes size or moves. + */ +template +class IndexingIterator { +public: + // Iterator traits for standard library compatibility + using iterator_category = std::random_access_iterator_tag; + using value_type = uint64_t; + using difference_type = typename std::make_signed::type; + using pointer = void; + using reference = uint64_t; + + // Standard iterator operations + IndexingIterator(const IndexingIterator& other) = default; + IndexingIterator& operator=(const IndexingIterator& other) = default; + ~IndexingIterator() = default; + + /// Pre-increment operator + IndexingIterator& operator++(); + + /// Post-increment operator + IndexingIterator operator++(int); + + /// Dereference operator - returns value at current position + uint64_t operator*() const; + + /// Equality comparison + bool operator==(const IndexingIterator& other) const; + + /// Inequality comparison + bool operator!=(const IndexingIterator& other) const; + + // Bidirectional methods + + /// Pre-decrement operator + IndexingIterator& operator--(); + + /// Post-decrement operator + IndexingIterator operator--(int); + + // Random-access methods + + /// Addition of offset in place + IndexingIterator& operator+=(difference_type offset); + + /// Addition of offset + IndexingIterator operator+(difference_type offset) const; + + /// Subtraction of offset in place + IndexingIterator& operator-=(difference_type offset); + + /// Subtraction of offset + IndexingIterator operator-(difference_type offset) const; + + /// Subtraction of two iterators + difference_type operator-(const IndexingIterator& other) const; + + /// Indexing into iterator. Even though we type this as reference, remember + /// that we don't actually implement writing to our "references" and just + /// use the value type. + /// Result is undefined if itrators are to different collecitons. + reference operator[](difference_type offset) const; + + // Comaprable iterator methods (TODO: Is there an STL concept name for this?) + + /// Determine if this iterator is strictly before another. + /// Result is undefined if iterators are to different collecitons. + bool operator<(const IndexingIterator& other) const; + + /// Determine if this iterator is before or at another. + /// Result is undefined if iterators are to different collecitons. + bool operator<=(const IndexingIterator& other) const; + + /// Determine if this iterator is strictly after another. + /// Result is undefined if iterators are to different collecitons. + bool operator>(const IndexingIterator& other) const; + + /// Determine if this iterator is at or after another. + /// Result is undefined if itrators are to different collecitons. + bool operator>=(const IndexingIterator& other) const; + +private: + // Private constructor - only associated class can create iterators + IndexingIterator(const VectorLike* vec, size_t idx); + + const VectorLike* vec_ptr = nullptr; + size_t index = 0; + + // We're not allowed to use "class" when befriending a template parameter. + // See + friend VectorLike; +}; /* * A dynamic integer vector that maintains integers in bit-compressed form. @@ -37,9 +136,13 @@ class PackedVector { private: using IntVector = typename IntVectorFor::type; public: + + /// Allow iteration with a general indexing iterator. + using iterator = IndexingIterator; + /// Constructor (starts empty) PackedVector(); - + // TODO: constructor templated on allocator types conflicts with all the // other 1-argument constructor overloads. @@ -90,10 +193,22 @@ class PackedVector { inline uint64_t get(const size_t& i) const; /// Add a value to the end - inline void append(const uint64_t& value); + inline void push_back(const uint64_t& value); + + /// Add a value to the end (deprecated in favor of STL-like push_back) + [[deprecated("Use push_back instead of append_back")]] + inline void append_back(const uint64_t& value) { + push_back(value); + } /// Remove the last value - inline void pop(); + inline void pop_back(); + + /// Remove the last value (deprecated in favor of STL-like pop_back) + [[deprecated("Use pop_back instead of pop")]] + inline void pop() { + pop_back(); + } /// Either shrink the vector or grow the vector to the new size. New /// entries created by growing are filled with 0. @@ -114,14 +229,20 @@ class PackedVector { /// Clears the backing vector. inline void clear(); + + /// Iterator to the first element + iterator begin() const; + + /// Iterator to the past-the-end element + iterator end() const; /// Reports the amount of memory consumed by this object in bytes. size_t memory_usage() const; - + /// Returns true if the contents are identical (but not necessarily storage /// parameters, such as pointer to data, capacity, bit width, etc.). inline bool operator==(const PackedVector& other) const; - + private: // We don't allocate ourselves, so we don't need to hold an allocator. @@ -152,23 +273,26 @@ class PagedVector { using PageHolder = typename VectorFor::template type; public: - - /// Construct (starts empty) + + /// Allow iteration with a general indexing iterator. + using iterator = IndexingIterator; + + /// Construct (starts empty) PagedVector(); - + /// Construct from contents in a stream PagedVector(istream& in); - + /// Move constructor PagedVector(PagedVector&& other) = default; /// Move assignment operator PagedVector& operator=(PagedVector&& other) = default; - + /// Copy constructor PagedVector(const PagedVector& other) = default; /// Copy assignment operator PagedVector& operator=(const PagedVector& other) = default; - + // Destructor ~PagedVector(); @@ -185,10 +309,22 @@ class PagedVector { inline uint64_t get(const size_t& i) const; /// Add a value to the end - inline void append(const uint64_t& value); + inline void push_back(const uint64_t& value); + + /// Add a value to the end (deprecated in favor of STL-like push_back) + [[deprecated("Use push_back instead of append_back")]] + inline void append_back(const uint64_t& value) { + push_back(value); + } /// Remove the last value - inline void pop(); + inline void pop_back(); + + /// Remove the last value (deprecated in favor of STL-like pop_back) + [[deprecated("Use pop_back instead of pop")]] + inline void pop() { + pop_back(); + } /// Either shrink the vector or grow the vector to the new size. New /// entries created by growing are filled with 0. @@ -209,21 +345,27 @@ class PagedVector { /// Clears the backing vector inline void clear(); + + /// Iterator to the first element + iterator begin() const; + + /// Iterator to the past-the-end element + iterator end() const; /// Returns the page width of the vector inline size_t page_width() const; - + /// Reports the amount of memory consumed by this object in bytes size_t memory_usage() const; - + private: - + inline uint64_t to_diff(const uint64_t& value, const uint64_t& page) const; inline uint64_t from_diff(const uint64_t& diff, const uint64_t& page) const; - + // The number of entries filled so far size_t filled = 0; - + // Evenly spaced entries from the vector Page anchors; // All entries in the vector expressed as a difference from the preceding page value @@ -244,9 +386,13 @@ class RobustPagedVector { using PackedVec = PackedVector; using PagedVec = PagedVector; public: + + /// Allow iteration with a general indexing iterator. + using iterator = IndexingIterator; + /// Construct (starts empty) RobustPagedVector(); - + /// Construct from contents in a stream RobustPagedVector(istream& in); @@ -276,10 +422,22 @@ class RobustPagedVector { inline uint64_t get(const size_t& i) const; /// Add a value to the end - inline void append(const uint64_t& value); + inline void push_back(const uint64_t& value); + + /// Add a value to the end (deprecated in favor of STL-like push_back) + [[deprecated("Use push_back instead of append_back")]] + inline void append_back(const uint64_t& value) { + push_back(value); + } /// Remove the last value - inline void pop(); + inline void pop_back(); + + /// Remove the last value (deprecated in favor of STL-like pop_back) + [[deprecated("Use pop_back instead of pop")]] + inline void pop() { + pop_back(); + } /// Either shrink the vector or grow the vector to the new size. New /// entries created by growing are filled with 0. @@ -300,13 +458,19 @@ class RobustPagedVector { /// Clears the backing vector inline void clear(); + + /// Iterator to the first element + iterator begin() const; + + /// Iterator to the past-the-end element + iterator end() const; /// Returns the page width of the vector inline size_t page_width() const; - + /// Reports the amount of memory consumed by this object in bytes size_t memory_usage() const; - + private: /// The first page_size entries go in this vector @@ -328,6 +492,10 @@ class PackedDeque { private: using PackedVec = PackedVector; public: + + /// Allow iteration with a general indexing iterator. + using iterator = IndexingIterator; + /// Construct empty PackedDeque(void); /// Construct from contents in a stream @@ -359,10 +527,22 @@ class PackedDeque { inline uint64_t get(const size_t& i) const; /// Add a value to the front - inline void append_front(const uint64_t& value); + inline void push_front(const uint64_t& value); + + /// Add a value to the front (deprecated in favor of STL-like push_front) + [[deprecated("Use push_front instead of append_front")]] + inline void append_front(const uint64_t& value) { + push_front(value); + } /// Add a value to the back - inline void append_back(const uint64_t& value); + inline void push_back(const uint64_t& value); + + /// Add a value to the back (deprecated in favor of STL-like push_back) + [[deprecated("Use push_back instead of append_back")]] + inline void append_back(const uint64_t& value) { + push_back(value); + } /// Remove the front value inline void pop_front(); @@ -382,10 +562,16 @@ class PackedDeque { /// Empty the contents inline void clear(); - + + /// Iterator to the first element + iterator begin() const; + + /// Iterator to the past-the-end element + iterator end() const; + /// Reports the amount of memory consumed by this object in bytes. size_t memory_usage() const; - + private: inline void contract(); @@ -559,7 +745,113 @@ inline void repack>(sdsl::int_vector<>& target, size_t new_wi target = std::move(tmp); } - +///////////////////// +/// IndexingIterator +///////////////////// + +template +IndexingIterator::IndexingIterator(const VectorLike* vec, size_t idx) + : vec_ptr(vec), index(idx) { + // Constructor +} + +template +IndexingIterator& IndexingIterator::operator++() { + ++index; + return *this; +} + +template +IndexingIterator IndexingIterator::operator++(int) { + IndexingIterator tmp = *this; + ++index; + return tmp; +} + +template +uint64_t IndexingIterator::operator*() const { + return vec_ptr->get(index); +} + +template +bool IndexingIterator::operator==(const IndexingIterator& other) const { + return vec_ptr == other.vec_ptr && index == other.index; +} + +template +bool IndexingIterator::operator!=(const IndexingIterator& other) const { + return !(*this == other); +} + +template +IndexingIterator& IndexingIterator::operator--() { + --index; + return *this; +} + +template +IndexingIterator IndexingIterator::operator--(int) { + IndexingIterator tmp = *this; + --index; + return tmp; +} + +template +IndexingIterator& IndexingIterator::operator+=(difference_type offset) { + index += offset; + return *this; +} + +template +IndexingIterator IndexingIterator::operator+(difference_type offset) const { + return IndexingIterator(vec_ptr, index + offset); +} + +template +IndexingIterator& IndexingIterator::operator-=(difference_type offset) { + index -= offset; + return *this; +} + +template +IndexingIterator IndexingIterator::operator-(difference_type offset) const { + return IndexingIterator(vec_ptr, index - offset); +} + +template +typename IndexingIterator::difference_type IndexingIterator::operator-(const IndexingIterator& other) const { + // TODO: I don't know a way to subtract two unsigned values and get the + // signed difference in a single operation as long as that difference + // itself fits the signed type. So we cast and hope. + return (difference_type) index - (difference_type) other.index; +} + +template +typename IndexingIterator::reference IndexingIterator::operator[](difference_type offset) const { + return *(*this + offset); +} + +template +bool IndexingIterator::operator<(const IndexingIterator& other) const { + return index < other.index; +} + +template +bool IndexingIterator::operator<=(const IndexingIterator& other) const { + return index <= other.index; +} + +template +bool IndexingIterator::operator>(const IndexingIterator& other) const { + return index > other.index; +} + +template +bool IndexingIterator::operator>=(const IndexingIterator& other) const { + return index >= other.index; +} + + ///////////////////// /// PackedVector ///////////////////// @@ -592,13 +884,13 @@ inline uint64_t PackedVector::get(const size_t& i) const { } template -inline void PackedVector::append(const uint64_t& value) { +inline void PackedVector::push_back(const uint64_t& value) { resize(filled + 1); set(filled - 1, value); } template -inline void PackedVector::pop() { +inline void PackedVector::pop_back() { resize(filled - 1); } @@ -650,6 +942,16 @@ inline void PackedVector::clear() { filled = 0; } +template +typename PackedVector::iterator PackedVector::begin() const { + return iterator(this, 0); +} + +template +typename PackedVector::iterator PackedVector::end() const { + return iterator(this, filled); +} + template inline bool PackedVector::operator==(const PackedVector& other) const { if (size() != other.size()) { @@ -782,7 +1084,7 @@ inline void PackedDeque::reserve(const size_t& future_size) { } template -inline void PackedDeque::append_front(const uint64_t& value) { +inline void PackedDeque::push_front(const uint64_t& value) { // expand capacity if necessary if (filled == vec.size()) { size_t new_capacity = size_t(factor * vec.size()) + 1; @@ -804,7 +1106,7 @@ inline void PackedDeque::append_front(const uint64_t& value) { } template -inline void PackedDeque::append_back(const uint64_t& value) { +inline void PackedDeque::push_back(const uint64_t& value) { // expand capacity if necessary if (filled == vec.size()) { size_t new_capacity = size_t(factor * vec.size()) + 1; @@ -872,7 +1174,17 @@ inline void PackedDeque::clear() { filled = 0; begin_idx = 0; } - + +template +typename PackedDeque::iterator PackedDeque::begin() const { + return iterator(this, 0); +} + +template +typename PackedDeque::iterator PackedDeque::end() const { + return iterator(this, filled); +} + ///////////////////// /// PagedVector ///////////////////// @@ -951,12 +1263,12 @@ inline uint64_t PagedVector::get(const size_t& i) const { } template -inline void PagedVector::append(const uint64_t& value) { +inline void PagedVector::push_back(const uint64_t& value) { if (filled == pages.size() * page_size) { // init a new page and a new anchor pages.emplace_back(); pages.back().resize(page_size); - anchors.append(0); + anchors.push_back(0); } // use the logic in set to choose anchor and diff @@ -965,12 +1277,12 @@ inline void PagedVector::append(const uint64_t& value) { } template -inline void PagedVector::pop() { +inline void PagedVector::pop_back() { filled--; while (filled + page_size <= pages.size() * page_size) { // the final page is unused now, remove it pages.pop_back(); // TODO: this won't resize since it's an STL vector - anchors.pop(); + anchors.pop_back(); } } @@ -1033,6 +1345,16 @@ inline void PagedVector::clear() { filled = 0; } +template +typename PagedVector::iterator PagedVector::begin() const { + return iterator(this, 0); +} + +template +typename PagedVector::iterator PagedVector::end() const { + return iterator(this, filled); +} + template inline size_t PagedVector::page_width() const { return page_size; @@ -1064,7 +1386,7 @@ inline uint64_t PagedVector::to_diff(const uint64_t& value, template inline uint64_t PagedVector::from_diff(const uint64_t& diff, const uint64_t& anchor) const { // convert backward from the transformation described in to_diff - + if (diff == 0) { return 0; } @@ -1133,22 +1455,22 @@ inline uint64_t RobustPagedVector::get(const size_t& i) cons } template -inline void RobustPagedVector::append(const uint64_t& value) { +inline void RobustPagedVector::push_back(const uint64_t& value) { if (first_page.size() < latter_pages.page_width()) { - first_page.append(value); + first_page.push_back(value); } else { - latter_pages.append(value); + latter_pages.push_back(value); } } template -inline void RobustPagedVector::pop() { +inline void RobustPagedVector::pop_back() { if (latter_pages.empty()) { - first_page.pop(); + first_page.pop_back(); } else { - latter_pages.pop(); + latter_pages.pop_back(); } } @@ -1197,6 +1519,16 @@ inline void RobustPagedVector::clear() { latter_pages.clear(); } +template +typename RobustPagedVector::iterator RobustPagedVector::begin() const { + return iterator(this, 0); +} + +template +typename RobustPagedVector::iterator RobustPagedVector::end() const { + return iterator(this, size()); +} + template inline size_t RobustPagedVector::page_width() const { return latter_pages.page_width(); diff --git a/bdsg/src/test_libbdsg.cpp b/bdsg/src/test_libbdsg.cpp index 0d94c9e3..94c936d0 100644 --- a/bdsg/src/test_libbdsg.cpp +++ b/bdsg/src/test_libbdsg.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include // BINDER_IGNORE because Binder can't find this @@ -2832,7 +2833,7 @@ void test_packed_vector() { case APPEND: for (size_t k = 0; k < appends_per_op; k++) { std_vec.push_back(next_val); - dyn_vec.append(next_val); + dyn_vec.push_back(next_val); next_val++; } @@ -2842,7 +2843,7 @@ void test_packed_vector() { if (!std_vec.empty()) { for (size_t k = 0; k < pops_per_op; k++) { std_vec.pop_back(); - dyn_vec.pop(); + dyn_vec.pop_back(); } } @@ -2874,6 +2875,355 @@ void test_packed_vector() { cerr << "PackedVector (" << typeid(PackedVectorImpl).name() << ") tests successful!" << endl; } +/** + * Generic iterator test function that works with any vector-like container + * (PackedVector, PagedVector, RobustPagedVector, PackedDeque). + * + * Tests ForwardIterator, BidirectionalIterator, RandomAccessIterator, and + * iterator order comparison, but not OutputIterator. + */ +template +void test_iterators() { + // ForwardIterator tests + + // Empty iteration + { + VectorLike vec; + assert(vec.begin() == vec.end()); + + size_t count = 0; + for (auto it = vec.begin(); it != vec.end(); ++it) { + count++; + } + assert(count == 0); + } + + // Single element + { + VectorLike vec; + vec.push_back(42); + + assert(vec.begin() != vec.end()); + + auto it = vec.begin(); + assert(*it == 42); + ++it; + assert(it == vec.end()); + } + + // Multiple elements - basic iteration + { + VectorLike vec; + vector expected = {10, 20, 30, 40, 50}; + + for (auto val : expected) { + vec.push_back(val); + } + + // Iterate and compare + size_t idx = 0; + for (auto it = vec.begin(); it != vec.end(); ++it) { + assert(idx < expected.size()); + assert(*it == expected[idx]); + idx++; + } + assert(idx == expected.size()); + } + + // Range-based for loop + { + VectorLike vec; + vector expected = {100, 200, 300, 400, 500, 600, 700, 800}; + + for (auto val : expected) { + vec.push_back(val); + } + + size_t idx = 0; + for (auto val : vec) { + assert(idx < expected.size()); + assert(val == expected[idx]); + idx++; + } + assert(idx == expected.size()); + } + + // Iterator equality and inequality + { + VectorLike vec; + vec.push_back(1); + vec.push_back(2); + vec.push_back(3); + + auto it1 = vec.begin(); + auto it2 = vec.begin(); + assert(it1 == it2); + + ++it2; + assert(it1 != it2); + + ++it1; + assert(it1 == it2); + } + + // std::distance compatibility + { + VectorLike vec; + for (size_t i = 0; i < 15; i++) { + vec.push_back(i); + } + + auto dist = std::distance(vec.begin(), vec.end()); + assert((size_t)dist == vec.size()); + assert((size_t)dist == 15); + } + + // std::find compatibility + { + VectorLike vec; + vec.push_back(10); + vec.push_back(20); + vec.push_back(30); + vec.push_back(40); + vec.push_back(50); + + auto it = std::find(vec.begin(), vec.end(), 30); + assert(it != vec.end()); + assert(*it == 30); + + auto it2 = std::find(vec.begin(), vec.end(), 999); + assert(it2 == vec.end()); + } + + // Const iterator + { + VectorLike vec; + vec.push_back(5); + vec.push_back(15); + vec.push_back(25); + + const VectorLike& const_vec = vec; + + size_t count = 0; + for (auto it = const_vec.begin(); it != const_vec.end(); ++it) { + count++; + } + assert(count == 3); + + auto it = const_vec.begin(); + assert(*it == 5); + ++it; + assert(*it == 15); + ++it; + assert(*it == 25); + } + + // Large container with various patterns + { + VectorLike vec; + random_device rd; + default_random_engine prng(rd()); + uniform_int_distribution val_distr(0, 10000); + + vector expected; + size_t num_elements = 200; + + for (size_t i = 0; i < num_elements; i++) { + uint64_t val = val_distr(prng); + expected.push_back(val); + vec.push_back(val); + } + + size_t idx = 0; + for (auto val : vec) { + assert(val == expected[idx]); + idx++; + } + assert(idx == expected.size()); + } + + // Iteration after modification + { + VectorLike vec; + vec.push_back(1); + vec.push_back(2); + vec.push_back(3); + + // First iteration + size_t count = 0; + for (auto it = vec.begin(); it != vec.end(); ++it) { + count++; + } + assert(count == 3); + + // Modify + vec.push_back(4); + vec.set(0, 100); + + // Second iteration + vector expected = {100, 2, 3, 4}; + size_t idx = 0; + for (auto val : vec) { + assert(val == expected[idx]); + idx++; + } + assert(idx == 4); + } + + // Iterator copy construction + { + VectorLike vec; + vec.push_back(10); + vec.push_back(20); + + auto it1 = vec.begin(); + auto it2(it1); // Copy constructor + + assert(it1 == it2); + assert(*it1 == *it2); + assert(*it1 == 10); + } + + // Iterator assignment + { + VectorLike vec; + vec.push_back(10); + vec.push_back(20); + vec.push_back(30); + + auto it1 = vec.begin(); + auto it2 = vec.begin(); + ++it2; + + assert(*it1 == 10); + assert(*it2 == 20); + + it1 = it2; // Assignment + assert(it1 == it2); + assert(*it1 == 20); + } + + // BidirectionalIterator tests. + { + VectorLike vec; + vec.push_back(10); + vec.push_back(20); + vec.push_back(30); + + auto it1 = vec.begin(); + auto it2 = it1; + ++it2; + auto also_decremented = --it2; + + assert(it2 == it1); + assert(also_decremented == it1); + + it2++; + auto not_decremented = it2--; + + assert(it2 == it1); + assert(not_decremented != it1); + assert(*not_decremented == 20); + + auto it3 = vec.end(); + it3--; + assert(it3 != vec.end()); + assert(*it3 == 30); + } + + // RandomAccessIterator tests + { + VectorLike vec; + vec.push_back(10); + vec.push_back(20); + vec.push_back(30); + + auto it1 = vec.begin(); + auto it2 = it1; + + it1 += 1; + assert(*it1 == 20); + + it1 += 2; + assert(it1 == vec.end()); + + it1 -= 1; + auto it3 = it2 + 2; + assert(it1 == it3); + assert(*it1 == 30); + assert(it2 == vec.begin()); + + auto it4 = it1 - 2; + assert(*it4 == 10); + + assert(*it1 == vec.begin()[2]); + assert(*it4 == vec.begin()[0]); + assert(it4[2] == *it1); + assert(it1[-2] == *it4); + + assert(it1 + -2 == it4); + assert(it4 - -2 == it1); + + it1 += -2; + assert(it1 == it4); + + it1 -= -1; + it4++; + assert(it1 == it4); + } + + // Iterator comparison tests + { + VectorLike vec; + vec.push_back(10); + vec.push_back(20); + vec.push_back(30); + + auto it1 = vec.begin(); + auto it2 = it1; + + assert(it1 >= it2); + assert(it1 <= it2); + assert(!(it1 < it2)); + assert(!(it1 > it2)); + it1++; + + assert(it1 >= it2); + assert(!(it1 <= it2)); + assert(!(it2 >= it1)); + assert(it2 <= it1); + assert(!(it1 < it2)); + assert(it1 > it2); + assert(it2 < it1); + assert(!(it2 > it1)); + } + + // Iterator distance tests + { + VectorLike vec; + vec.push_back(10); + vec.push_back(20); + vec.push_back(30); + + assert(vec.end() - vec.begin() == vec.size()); + + auto it1 = vec.begin(); + auto it2 = it1; + + it1 += 1; + it2 += 2; + + assert(it2 - it1 == 1); + assert(it1 - it2 == -1); + + it1--; + assert(it2 - it1 == 2); + assert(it1 - it2 == -2); + } + + cerr << "Iterator (" << typeid(typename VectorLike::iterator).name() << ") tests successful!" << endl; +} + template void test_paged_vector() { enum vec_op_t {SET = 0, GET = 1, APPEND = 2, POP = 3, SERIALIZE = 4}; @@ -2926,7 +3276,7 @@ void test_paged_vector() { case APPEND: for (size_t k = 0; k < appends_per_op; k++) { std_vec.push_back(next_val); - dyn_vec.append(next_val); + dyn_vec.push_back(next_val); next_val = val_distr(prng); } @@ -2936,7 +3286,7 @@ void test_paged_vector() { if (!std_vec.empty()) { for (size_t k = 0; k < pops_per_op; k++) { std_vec.pop_back(); - dyn_vec.pop(); + dyn_vec.pop_back(); } } @@ -3018,7 +3368,7 @@ void test_packed_deque() { case APPEND_LEFT: for (size_t k = 0; k < appends_per_op; k++) { std_deq.push_front(next_val); - suc_deq.append_front(next_val); + suc_deq.push_front(next_val); next_val++; } @@ -3035,7 +3385,7 @@ void test_packed_deque() { case APPEND_RIGHT: for (size_t k = 0; k < appends_per_op; k++) { std_deq.push_back(next_val); - suc_deq.append_back(next_val); + suc_deq.push_back(next_val); next_val++; } @@ -4700,6 +5050,9 @@ int main(void) { test_packed_vector>(); test_packed_vector>(); test_packed_vector>(); + test_iterators>(); + test_iterators>(); + test_iterators>(); test_paged_vector>(); test_paged_vector>(); test_paged_vector>(); @@ -4707,7 +5060,24 @@ int main(void) { test_paged_vector>(); test_paged_vector>(); test_paged_vector>(); + test_iterators>(); + test_iterators>(); + test_iterators>(); + test_iterators>(); + test_iterators>(); + test_iterators>(); + test_iterators>(); + test_iterators>(); + test_iterators>(); + test_iterators>(); + test_iterators>(); + test_iterators>(); + test_iterators>(); + test_iterators>(); test_packed_deque(); + test_iterators>(); + test_iterators>(); + test_iterators>(); test_packed_set(); test_mutable_path_handle_graphs(); test_deletable_handle_graphs();