Skip to content

Commit ca3f987

Browse files
committed
FEAT: Implement iterator method rfold where possible
Iterators can implement rfold to improve the inner loop of funtionality such as `Iterator::sum`. Note that `rfold` is also reached through `.iter().rev().fold()` and and similar. Only 1D iterators are double ended, so the implementation is relatively simple.
1 parent cd6482e commit ca3f987

File tree

1 file changed

+45
-0
lines changed

1 file changed

+45
-0
lines changed

src/iterators/mod.rs

+45
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,23 @@ impl<A> DoubleEndedIterator for Baseiter<A, Ix1> {
148148

149149
unsafe { Some(self.ptr.offset(offset)) }
150150
}
151+
152+
fn rfold<Acc, G>(mut self, init: Acc, mut g: G) -> Acc
153+
where G: FnMut(Acc, *mut A) -> Acc,
154+
{
155+
let mut accum = init;
156+
if let Some(index) = self.index {
157+
let elem_index = index[0];
158+
unsafe {
159+
// self.dim[0] is the current length
160+
while self.dim[0] > elem_index {
161+
self.dim[0] -= 1;
162+
accum = g(accum, self.ptr.offset(Ix1::stride_offset(&self.dim, &self.strides)));
163+
}
164+
}
165+
}
166+
accum
167+
}
151168
}
152169

153170
clone_bounds!(
@@ -206,6 +223,14 @@ impl<'a, A> DoubleEndedIterator for ElementsBase<'a, A, Ix1> {
206223
fn next_back(&mut self) -> Option<&'a A> {
207224
self.inner.next_back().map(|p| unsafe { &*p })
208225
}
226+
227+
fn rfold<Acc, G>(self, init: Acc, mut g: G) -> Acc
228+
where G: FnMut(Acc, Self::Item) -> Acc,
229+
{
230+
unsafe {
231+
self.inner.rfold(init, move |acc, ptr| g(acc, &*ptr))
232+
}
233+
}
209234
}
210235

211236
impl<'a, A, D> ExactSizeIterator for ElementsBase<'a, A, D>
@@ -370,6 +395,12 @@ impl<'a, A> DoubleEndedIterator for Iter<'a, A, Ix1> {
370395
fn next_back(&mut self) -> Option<&'a A> {
371396
either_mut!(self.inner, iter => iter.next_back())
372397
}
398+
399+
fn rfold<Acc, G>(self, init: Acc, g: G) -> Acc
400+
where G: FnMut(Acc, Self::Item) -> Acc
401+
{
402+
either!(self.inner, iter => iter.rfold(init, g))
403+
}
373404
}
374405

375406
impl<'a, A, D> ExactSizeIterator for Iter<'a, A, D>
@@ -431,6 +462,12 @@ impl<'a, A> DoubleEndedIterator for IterMut<'a, A, Ix1> {
431462
fn next_back(&mut self) -> Option<&'a mut A> {
432463
either_mut!(self.inner, iter => iter.next_back())
433464
}
465+
466+
fn rfold<Acc, G>(self, init: Acc, g: G) -> Acc
467+
where G: FnMut(Acc, Self::Item) -> Acc
468+
{
469+
either!(self.inner, iter => iter.rfold(init, g))
470+
}
434471
}
435472

436473
impl<'a, A, D> ExactSizeIterator for IterMut<'a, A, D>
@@ -466,6 +503,14 @@ impl<'a, A> DoubleEndedIterator for ElementsBaseMut<'a, A, Ix1> {
466503
fn next_back(&mut self) -> Option<&'a mut A> {
467504
self.inner.next_back().map(|p| unsafe { &mut *p })
468505
}
506+
507+
fn rfold<Acc, G>(self, init: Acc, mut g: G) -> Acc
508+
where G: FnMut(Acc, Self::Item) -> Acc
509+
{
510+
unsafe {
511+
self.inner.rfold(init, move |acc, ptr| g(acc, &mut *ptr))
512+
}
513+
}
469514
}
470515

471516
impl<'a, A, D> ExactSizeIterator for ElementsBaseMut<'a, A, D>

0 commit comments

Comments
 (0)