Skip to content

Commit f905b9c

Browse files
authored
Add reverse tree iteration. (#92)
* Move advance/advance_back bodies to the streaming_iterator trait implementations.
1 parent a1a033f commit f905b9c

File tree

1 file changed

+68
-18
lines changed

1 file changed

+68
-18
lines changed

src/trees.rs

Lines changed: 68 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -68,23 +68,6 @@ impl Tree {
6868
handle_tsk_return_value!(rv, tree)
6969
}
7070

71-
fn advance_details(&mut self) {
72-
let rv = if self.current_tree == 0 {
73-
unsafe { ll_bindings::tsk_tree_first(self.as_mut_ptr()) }
74-
} else {
75-
unsafe { ll_bindings::tsk_tree_next(self.as_mut_ptr()) }
76-
};
77-
if rv == 0 {
78-
self.advanced = false;
79-
self.current_tree += 1;
80-
} else if rv == 1 {
81-
self.advanced = true;
82-
self.current_tree += 1;
83-
} else if rv < 0 {
84-
panic_on_tskit_error!(rv);
85-
}
86-
}
87-
8871
pub fn parent_array(&self) -> crate::ffi::TskIdArray {
8972
crate::ffi::TskIdArray::new(self.inner.parent, self.inner.num_nodes)
9073
}
@@ -361,7 +344,20 @@ impl Tree {
361344
impl streaming_iterator::StreamingIterator for Tree {
362345
type Item = Tree;
363346
fn advance(&mut self) {
364-
self.advance_details();
347+
let rv = if self.current_tree == 0 {
348+
unsafe { ll_bindings::tsk_tree_first(self.as_mut_ptr()) }
349+
} else {
350+
unsafe { ll_bindings::tsk_tree_next(self.as_mut_ptr()) }
351+
};
352+
if rv == 0 {
353+
self.advanced = false;
354+
self.current_tree += 1;
355+
} else if rv == 1 {
356+
self.advanced = true;
357+
self.current_tree += 1;
358+
} else if rv < 0 {
359+
panic_on_tskit_error!(rv);
360+
}
365361
}
366362

367363
fn get(&self) -> Option<&Tree> {
@@ -372,6 +368,25 @@ impl streaming_iterator::StreamingIterator for Tree {
372368
}
373369
}
374370

371+
impl streaming_iterator::DoubleEndedStreamingIterator for Tree {
372+
fn advance_back(&mut self) {
373+
let rv = if self.current_tree == 0 {
374+
unsafe { ll_bindings::tsk_tree_last(self.as_mut_ptr()) }
375+
} else {
376+
unsafe { ll_bindings::tsk_tree_prev(self.as_mut_ptr()) }
377+
};
378+
if rv == 0 {
379+
self.advanced = false;
380+
self.current_tree -= 1;
381+
} else if rv == 1 {
382+
self.advanced = true;
383+
self.current_tree -= 1;
384+
} else if rv < 0 {
385+
panic_on_tskit_error!(rv);
386+
}
387+
}
388+
}
389+
375390
/// Specify the traversal order used by
376391
/// [`Tree::nodes`].
377392
pub enum NodeTraversalOrder {
@@ -718,6 +733,9 @@ impl TreeSequence {
718733
/// // You must include streaming_iterator as a dependency
719734
/// // and import this type.
720735
/// use streaming_iterator::StreamingIterator;
736+
/// // Import this to allow .next_back() for reverse
737+
/// // iteration over trees.
738+
/// use streaming_iterator::DoubleEndedStreamingIterator;
721739
///
722740
/// let mut tables = tskit::TableCollection::new(1000.).unwrap();
723741
/// tables.build_index();
@@ -880,6 +898,7 @@ pub(crate) mod test_trees {
880898
make_small_table_collection, make_small_table_collection_two_trees,
881899
treeseq_from_small_table_collection, treeseq_from_small_table_collection_two_trees,
882900
};
901+
use streaming_iterator::DoubleEndedStreamingIterator;
883902
use streaming_iterator::StreamingIterator;
884903

885904
#[test]
@@ -1053,4 +1072,35 @@ pub(crate) mod test_trees {
10531072
let dumped = ts.dump_tables().unwrap();
10541073
assert!(tables_copy.equals(&dumped, crate::TableEqualityOptions::default()));
10551074
}
1075+
1076+
#[test]
1077+
fn test_reverse_tree_iteration() {
1078+
let treeseq = treeseq_from_small_table_collection_two_trees();
1079+
let mut tree_iter = treeseq.tree_iterator(TreeFlags::default()).unwrap();
1080+
let mut starts_fwd = vec![];
1081+
let mut stops_fwd = vec![];
1082+
let mut starts_rev = vec![];
1083+
let mut stops_rev = vec![];
1084+
while let Some(tree) = tree_iter.next() {
1085+
let interval = tree.interval();
1086+
starts_fwd.push(interval.0);
1087+
stops_fwd.push(interval.1);
1088+
}
1089+
assert_eq!(stops_fwd.len(), 2);
1090+
assert_eq!(stops_fwd.len(), 2);
1091+
1092+
// NOTE: we do NOT need to create a new iterator.
1093+
while let Some(tree) = tree_iter.next_back() {
1094+
let interval = tree.interval();
1095+
starts_rev.push(interval.0);
1096+
stops_rev.push(interval.1);
1097+
}
1098+
assert_eq!(starts_fwd.len(), starts_rev.len());
1099+
assert_eq!(stops_fwd.len(), stops_rev.len());
1100+
1101+
starts_rev.reverse();
1102+
assert!(starts_fwd == starts_rev);
1103+
stops_rev.reverse();
1104+
assert!(stops_fwd == stops_rev);
1105+
}
10561106
}

0 commit comments

Comments
 (0)