Skip to content

Commit eb26e0d

Browse files
committed
add dedicated fold and rfold impls
add test for `fold` also add test for treemap
1 parent 3fa2e73 commit eb26e0d

File tree

4 files changed

+152
-0
lines changed

4 files changed

+152
-0
lines changed

src/bitmap/iter.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,30 @@ impl Iterator for Iter<'_> {
4646
(usize::MAX, None)
4747
}
4848
}
49+
50+
#[inline]
51+
fn fold<B, F>(self, init: B, f: F) -> B
52+
where
53+
Self: Sized,
54+
F: FnMut(B, Self::Item) -> B,
55+
{
56+
self.inner.fold(init, f)
57+
}
4958
}
5059

5160
impl DoubleEndedIterator for Iter<'_> {
5261
fn next_back(&mut self) -> Option<Self::Item> {
5362
self.size_hint = self.size_hint.saturating_sub(1);
5463
self.inner.next_back()
5564
}
65+
66+
#[inline]
67+
fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
68+
where
69+
Fold: FnMut(Acc, Self::Item) -> Acc,
70+
{
71+
self.inner.rfold(init, fold)
72+
}
5673
}
5774

5875
#[cfg(target_pointer_width = "64")]
@@ -77,13 +94,30 @@ impl Iterator for IntoIter {
7794
(usize::MAX, None)
7895
}
7996
}
97+
98+
#[inline]
99+
fn fold<B, F>(self, init: B, f: F) -> B
100+
where
101+
Self: Sized,
102+
F: FnMut(B, Self::Item) -> B,
103+
{
104+
self.inner.fold(init, f)
105+
}
80106
}
81107

82108
impl DoubleEndedIterator for IntoIter {
83109
fn next_back(&mut self) -> Option<Self::Item> {
84110
self.size_hint = self.size_hint.saturating_sub(1);
85111
self.inner.next_back()
86112
}
113+
114+
#[inline]
115+
fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
116+
where
117+
Fold: FnMut(Acc, Self::Item) -> Acc,
118+
{
119+
self.inner.rfold(init, fold)
120+
}
87121
}
88122

89123
#[cfg(target_pointer_width = "64")]

src/treemap/iter.rs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,40 @@ impl<'a> Iterator for To64Iter<'a> {
1616
fn next(&mut self) -> Option<u64> {
1717
self.inner.next().map(|n| util::join(self.hi, n))
1818
}
19+
20+
#[inline]
21+
fn fold<B, F>(self, init: B, f: F) -> B
22+
where
23+
Self: Sized,
24+
F: FnMut(B, Self::Item) -> B,
25+
{
26+
#[inline]
27+
fn f_with_hi<B>(mut f: impl FnMut(B, u64) -> B, hi: u32) -> impl FnMut(B, u32) -> B {
28+
move |b, lo| f(b, ((hi as u64) << 32) + (lo as u64))
29+
}
30+
31+
self.inner.fold(init, f_with_hi(f, self.hi))
32+
}
1933
}
2034

2135
impl DoubleEndedIterator for To64Iter<'_> {
2236
fn next_back(&mut self) -> Option<Self::Item> {
2337
self.inner.next_back().map(|n| util::join(self.hi, n))
2438
}
39+
40+
#[inline]
41+
fn rfold<B, F>(self, init: B, f: F) -> B
42+
where
43+
Self: Sized,
44+
F: FnMut(B, Self::Item) -> B,
45+
{
46+
#[inline]
47+
fn f_with_hi<B>(mut f: impl FnMut(B, u64) -> B, hi: u32) -> impl FnMut(B, u32) -> B {
48+
move |b, lo| f(b, ((hi as u64) << 32) + (lo as u64))
49+
}
50+
51+
self.inner.rfold(init, f_with_hi(f, self.hi))
52+
}
2553
}
2654

2755
fn to64iter<'a>(t: (&'a u32, &'a RoaringBitmap)) -> To64Iter<'a> {
@@ -38,12 +66,40 @@ impl Iterator for To64IntoIter {
3866
fn next(&mut self) -> Option<u64> {
3967
self.inner.next().map(|n| util::join(self.hi, n))
4068
}
69+
70+
#[inline]
71+
fn fold<B, F>(self, init: B, f: F) -> B
72+
where
73+
Self: Sized,
74+
F: FnMut(B, Self::Item) -> B,
75+
{
76+
#[inline]
77+
fn f_with_hi<B>(mut f: impl FnMut(B, u64) -> B, hi: u32) -> impl FnMut(B, u32) -> B {
78+
move |b, lo| f(b, ((hi as u64) << 32) + (lo as u64))
79+
}
80+
81+
self.inner.fold(init, f_with_hi(f, self.hi))
82+
}
4183
}
4284

4385
impl DoubleEndedIterator for To64IntoIter {
4486
fn next_back(&mut self) -> Option<Self::Item> {
4587
self.inner.next_back().map(|n| util::join(self.hi, n))
4688
}
89+
90+
#[inline]
91+
fn rfold<B, F>(self, init: B, f: F) -> B
92+
where
93+
Self: Sized,
94+
F: FnMut(B, Self::Item) -> B,
95+
{
96+
#[inline]
97+
fn f_with_hi<B>(mut f: impl FnMut(B, u64) -> B, hi: u32) -> impl FnMut(B, u32) -> B {
98+
move |b, lo| f(b, ((hi as u64) << 32) + (lo as u64))
99+
}
100+
101+
self.inner.rfold(init, f_with_hi(f, self.hi))
102+
}
47103
}
48104

49105
fn to64intoiter(t: (u32, RoaringBitmap)) -> To64IntoIter {
@@ -104,13 +160,30 @@ impl<'a> Iterator for Iter<'a> {
104160
(usize::MAX, None)
105161
}
106162
}
163+
164+
#[inline]
165+
fn fold<B, F>(self, init: B, f: F) -> B
166+
where
167+
Self: Sized,
168+
F: FnMut(B, Self::Item) -> B,
169+
{
170+
self.inner.fold(init, f)
171+
}
107172
}
108173

109174
impl DoubleEndedIterator for Iter<'_> {
110175
fn next_back(&mut self) -> Option<Self::Item> {
111176
self.size_hint = self.size_hint.saturating_sub(1);
112177
self.inner.next_back()
113178
}
179+
180+
#[inline]
181+
fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
182+
where
183+
Fold: FnMut(Acc, Self::Item) -> Acc,
184+
{
185+
self.inner.rfold(init, fold)
186+
}
114187
}
115188

116189
#[cfg(target_pointer_width = "64")]
@@ -135,13 +208,30 @@ impl Iterator for IntoIter {
135208
(usize::MAX, None)
136209
}
137210
}
211+
212+
#[inline]
213+
fn fold<B, F>(self, init: B, f: F) -> B
214+
where
215+
Self: Sized,
216+
F: FnMut(B, Self::Item) -> B,
217+
{
218+
self.inner.fold(init, f)
219+
}
138220
}
139221

140222
impl DoubleEndedIterator for IntoIter {
141223
fn next_back(&mut self) -> Option<Self::Item> {
142224
self.size_hint = self.size_hint.saturating_sub(1);
143225
self.inner.next_back()
144226
}
227+
228+
#[inline]
229+
fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
230+
where
231+
Fold: FnMut(Acc, Self::Item) -> Acc,
232+
{
233+
self.inner.rfold(init, fold)
234+
}
145235
}
146236

147237
#[cfg(target_pointer_width = "64")]

tests/iter.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,20 @@ proptest! {
6767
}
6868
}
6969

70+
proptest! {
71+
#[test]
72+
fn fold(values in btree_set(any::<u32>(), ..=10_000)) {
73+
let bitmap = RoaringBitmap::from_sorted_iter(values.iter().cloned()).unwrap();
74+
let mut val_iter = values.into_iter();
75+
// `Iterator::all` uses currently unimplementable `try_fold`, we test `fold`
76+
#[allow(clippy::unnecessary_fold)]
77+
let r = bitmap.into_iter().fold(true, |b, i| {
78+
b && i == val_iter.next().unwrap()
79+
});
80+
assert!(r)
81+
}
82+
}
83+
7084
#[test]
7185
fn rev_array() {
7286
let values = 0..100;

tests/treemap_iter.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,20 @@ proptest! {
7777
}
7878
}
7979

80+
proptest! {
81+
#[test]
82+
fn fold(values in btree_set(any::<u64>(), ..=10_000)) {
83+
let bitmap = RoaringTreemap::from_sorted_iter(values.iter().cloned()).unwrap();
84+
let mut val_iter = values.into_iter();
85+
// `Iterator::all` uses currently unimplementable `try_fold`, we test `fold`
86+
#[allow(clippy::unnecessary_fold)]
87+
let r = bitmap.into_iter().fold(true, |b, i| {
88+
b && i == val_iter.next().unwrap()
89+
});
90+
assert!(r)
91+
}
92+
}
93+
8094
#[test]
8195
fn rev() {
8296
let values = (1..3)

0 commit comments

Comments
 (0)