Skip to content

Commit 91c421c

Browse files
committed
specialize Intersperse::fold
1 parent 70988ff commit 91c421c

File tree

3 files changed

+100
-0
lines changed

3 files changed

+100
-0
lines changed

benches/fold_specialization.rs

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#![feature(test)]
2+
3+
extern crate test;
4+
extern crate itertools;
5+
6+
use itertools::Itertools;
7+
8+
struct Unspecialized<I>(I);
9+
10+
impl<I> Iterator for Unspecialized<I>
11+
where I: Iterator
12+
{
13+
type Item = I::Item;
14+
15+
#[inline(always)]
16+
fn next(&mut self) -> Option<I::Item> {
17+
self.0.next()
18+
}
19+
20+
#[inline(always)]
21+
fn size_hint(&self) -> (usize, Option<usize>) {
22+
self.0.size_hint()
23+
}
24+
}
25+
26+
mod specialization {
27+
use super::*;
28+
29+
mod intersperse {
30+
use super::*;
31+
32+
#[bench]
33+
fn external(b: &mut test::Bencher)
34+
{
35+
let arr = [1; 1024];
36+
37+
b.iter(|| {
38+
let mut sum = 0;
39+
for &x in arr.into_iter().intersperse(&0) {
40+
sum += x;
41+
}
42+
sum
43+
})
44+
}
45+
46+
#[bench]
47+
fn internal_specialized(b: &mut test::Bencher)
48+
{
49+
let arr = [1; 1024];
50+
51+
b.iter(|| {
52+
arr.into_iter().intersperse(&0).fold(0, |acc, x| acc + x)
53+
})
54+
}
55+
56+
#[bench]
57+
fn internal_unspecialized(b: &mut test::Bencher)
58+
{
59+
let arr = [1; 1024];
60+
61+
b.iter(|| {
62+
Unspecialized(arr.into_iter().intersperse(&0)).fold(0, |acc, x| acc + x)
63+
})
64+
}
65+
}
66+
}

src/intersperse.rs

+19
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,23 @@ impl<I> Iterator for Intersperse<I>
5757
let sh = self.iter.size_hint();
5858
size_hint::add_scalar(size_hint::add(sh, sh), has_peek)
5959
}
60+
61+
fn fold<B, F>(mut self, init: B, mut f: F) -> B where
62+
Self: Sized, F: FnMut(B, Self::Item) -> B,
63+
{
64+
let mut accum = init;
65+
66+
if let Some(x) = self.peek.take() {
67+
accum = f(accum, x);
68+
}
69+
70+
let element = &self.element;
71+
72+
self.iter.fold(accum,
73+
|accum, x| {
74+
let accum = f(accum, element.clone());
75+
let accum = f(accum, x);
76+
accum
77+
})
78+
}
6079
}

tests/fold_specialization.rs

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
extern crate itertools;
2+
3+
use itertools::Itertools;
4+
5+
#[test]
6+
fn specialization_intersperse() {
7+
let mut iter = (1..2).intersperse(0);
8+
iter.clone().for_each(|x| assert_eq!(Some(x), iter.next()));
9+
10+
let mut iter = (1..3).intersperse(0);
11+
iter.clone().for_each(|x| assert_eq!(Some(x), iter.next()));
12+
13+
let mut iter = (1..4).intersperse(0);
14+
iter.clone().for_each(|x| assert_eq!(Some(x), iter.next()));
15+
}

0 commit comments

Comments
 (0)