From 2033b7630ce100f05110ad68229afc49e5475eb9 Mon Sep 17 00:00:00 2001 From: Piet Hessenius Date: Tue, 29 Nov 2022 21:04:58 +0100 Subject: [PATCH] implement `DoubleEndedIterator` for 1d lanes This is especially useful when one wants to iterate over rows or columns of a 2d array in reverse. Co-authored-by: Ulrik Sverdrup --- src/iterators/mod.rs | 18 ++++++++++++++++++ tests/iterators.rs | 16 ++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/src/iterators/mod.rs b/src/iterators/mod.rs index 49c9c1887..35b2d725f 100644 --- a/src/iterators/mod.rs +++ b/src/iterators/mod.rs @@ -732,6 +732,15 @@ where } } +impl<'a, A> DoubleEndedIterator for LanesIter<'a, A, Ix1> +{ + fn next_back(&mut self) -> Option { + self.iter.next_back().map(|ptr| unsafe { + ArrayView::new_(ptr, Ix1(self.inner_len), Ix1(self.inner_stride as Ix)) + }) + } +} + // NOTE: LanesIterMut is a mutable iterator and must not expose aliasing // pointers. Due to this we use an empty slice for the raw data (it's unused // anyway). @@ -772,6 +781,15 @@ where } } +impl<'a, A> DoubleEndedIterator for LanesIterMut<'a, A, Ix1> +{ + fn next_back(&mut self) -> Option { + self.iter.next_back().map(|ptr| unsafe { + ArrayViewMut::new_(ptr, Ix1(self.inner_len), Ix1(self.inner_stride as Ix)) + }) + } +} + #[derive(Debug)] pub struct AxisIterCore { /// Index along the axis of the value of `.next()`, relative to the start diff --git a/tests/iterators.rs b/tests/iterators.rs index fd0716036..b2cd58ecf 100644 --- a/tests/iterators.rs +++ b/tests/iterators.rs @@ -39,6 +39,22 @@ fn double_ended() { assert_equal(aview1(&[1, 2, 3]).into_iter().rev(), [1, 2, 3].iter().rev()); } +#[test] +fn double_ended_rows() { + let a = ArcArray::from_iter(0..8).into_shape_clone((4, 2)).unwrap(); + let mut row_it = a.rows().into_iter(); + assert_equal(row_it.next_back().unwrap(), &[6, 7]); + assert_equal(row_it.next().unwrap(), &[0, 1]); + assert_equal(row_it.next_back().unwrap(), &[4, 5]); + assert_equal(row_it.next_back().unwrap(), &[2, 3]); + assert!(row_it.next().is_none()); + assert!(row_it.next_back().is_none()); + + for (row, check) in a.rows().into_iter().rev().zip(&[[6, 7], [4, 5], [2, 3], [0, 1]]) { + assert_equal(row, check); + } +} + #[test] fn iter_size_hint() { // Check that the size hint is correctly computed