|
80 | 80 | };
|
81 | 81 | (l, Some(l))
|
82 | 82 | }
|
| 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 | + } |
83 | 109 | }
|
84 | 110 |
|
85 | 111 | impl<D> ExactSizeIterator for IndicesIter<D> where D: Dimension {}
|
@@ -283,6 +309,34 @@ mod tests {
|
283 | 309 | assert_eq!(len, 0);
|
284 | 310 | }
|
285 | 311 |
|
| 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 | + |
286 | 340 | #[test]
|
287 | 341 | fn test_indices_iter_f_size_hint() {
|
288 | 342 | let dim = (3, 4);
|
|
0 commit comments