Skip to content

Commit 1a07258

Browse files
authored
Merge pull request #733 from jturner314/impl-fold-for-indicesiter
Implement fold for IndicesIter
2 parents 78846da + 76b7eaf commit 1a07258

File tree

1 file changed

+54
-0
lines changed

1 file changed

+54
-0
lines changed

src/indexes.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,32 @@ where
8080
};
8181
(l, Some(l))
8282
}
83+
84+
fn fold<B, F>(self, init: B, mut f: F) -> B
85+
where
86+
F: FnMut(B, D::Pattern) -> B,
87+
{
88+
let IndicesIter { mut index, dim } = self;
89+
let ndim = dim.ndim();
90+
if ndim == 0 {
91+
return match index {
92+
Some(ix) => f(init, ix.into_pattern()),
93+
None => init,
94+
};
95+
}
96+
let inner_axis = ndim - 1;
97+
let inner_len = dim[inner_axis];
98+
let mut acc = init;
99+
while let Some(mut ix) = index {
100+
// unroll innermost axis
101+
for i in ix[inner_axis]..inner_len {
102+
ix[inner_axis] = i;
103+
acc = f(acc, ix.clone().into_pattern());
104+
}
105+
index = dim.next_for(ix);
106+
}
107+
acc
108+
}
83109
}
84110

85111
impl<D> ExactSizeIterator for IndicesIter<D> where D: Dimension {}
@@ -283,6 +309,34 @@ mod tests {
283309
assert_eq!(len, 0);
284310
}
285311

312+
#[test]
313+
fn test_indices_iter_c_fold() {
314+
macro_rules! run_test {
315+
($dim:expr) => {
316+
for num_consume in 0..3 {
317+
let mut it = indices($dim).into_iter();
318+
for _ in 0..num_consume {
319+
it.next();
320+
}
321+
let clone = it.clone();
322+
let len = it.len();
323+
let acc = clone.fold(0, |acc, ix| {
324+
assert_eq!(ix, it.next().unwrap());
325+
acc + 1
326+
});
327+
assert_eq!(acc, len);
328+
assert!(it.next().is_none());
329+
}
330+
};
331+
}
332+
run_test!(());
333+
run_test!((2,));
334+
run_test!((2, 3));
335+
run_test!((2, 0, 3));
336+
run_test!((2, 3, 4));
337+
run_test!((2, 3, 4, 2));
338+
}
339+
286340
#[test]
287341
fn test_indices_iter_f_size_hint() {
288342
let dim = (3, 4);

0 commit comments

Comments
 (0)