about summary refs log tree commit diff
diff options
context:
space:
mode:
authorShotaro Yamada <sinkuu@sinkuu.xyz>2018-12-08 20:09:44 +0900
committerShotaro Yamada <sinkuu@sinkuu.xyz>2018-12-09 00:01:09 +0900
commitfbe5aa57ed810733f2fd4047cf5e5c24aebd8b01 (patch)
tree4e73ad57e1fa2caade9ed56636661739150e3ede
parent15a2607863fded7570cacfc7825702dde5a4234c (diff)
downloadrust-fbe5aa57ed810733f2fd4047cf5e5c24aebd8b01.tar.gz
rust-fbe5aa57ed810733f2fd4047cf5e5c24aebd8b01.zip
Override Cycle::try_fold
 name                            old ns/iter  new ns/iter  diff ns/iter   diff %  speedup
 iter::bench_cycle_take_ref_sum  927,152      927,194                42    0.00%   x 1.00
 iter::bench_cycle_take_sum      938,129      603,492          -334,637  -35.67%   x 1.55
-rw-r--r--src/libcore/benches/iter.rs6
-rw-r--r--src/libcore/iter/mod.rs13
-rw-r--r--src/libcore/tests/iter.rs2
3 files changed, 21 insertions, 0 deletions
diff --git a/src/libcore/benches/iter.rs b/src/libcore/benches/iter.rs
index 6c597301ac2..b0aca658343 100644
--- a/src/libcore/benches/iter.rs
+++ b/src/libcore/benches/iter.rs
@@ -282,6 +282,12 @@ bench_sums! {
     (0i64..1000000).chain(1000000..).take_while(|&x| x < 1111111)
 }
 
+bench_sums! {
+    bench_cycle_take_sum,
+    bench_cycle_take_ref_sum,
+    (0i64..10000).cycle().take(1000000)
+}
+
 // Checks whether Skip<Zip<A,B>> is as fast as Zip<Skip<A>, Skip<B>>, from
 // https://users.rust-lang.org/t/performance-difference-between-iterator-zip-and-skip-order/15743
 #[bench]
diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs
index de7ab8843da..83d35324bc2 100644
--- a/src/libcore/iter/mod.rs
+++ b/src/libcore/iter/mod.rs
@@ -649,6 +649,19 @@ impl<I> Iterator for Cycle<I> where I: Clone + Iterator {
             _ => (usize::MAX, None)
         }
     }
+
+    #[inline]
+    fn try_fold<Acc, F, R>(&mut self, init: Acc, mut f: F) -> R where
+        Self: Sized, F: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
+    {
+        let mut accum = init;
+        while let Some(x) = self.iter.next() {
+            accum = f(accum, x)?;
+            accum = self.iter.try_fold(accum, &mut f)?;
+            self.iter = self.orig.clone();
+        }
+        Try::from_ok(accum)
+    }
 }
 
 #[stable(feature = "fused", since = "1.26.0")]
diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs
index 19be1a07c5b..4efa0136314 100644
--- a/src/libcore/tests/iter.rs
+++ b/src/libcore/tests/iter.rs
@@ -1001,6 +1001,8 @@ fn test_cycle() {
     let mut it = (0..).step_by(1).take(0).cycle();
     assert_eq!(it.size_hint(), (0, Some(0)));
     assert_eq!(it.next(), None);
+
+    assert_eq!(empty::<i32>().cycle().fold(0, |acc, x| acc + x), 0);
 }
 
 #[test]