range_set_blaze/
sym_diff_iter.rs1use crate::sym_diff_iter_map::UsizeExtensions;
2use crate::{
3 Integer, Merge, SortedDisjoint, SortedStarts, SymDiffKMerge, SymDiffMerge, merge::KMerge,
4};
5use alloc::collections::BinaryHeap;
6use core::{cmp::Reverse, iter::FusedIterator, ops::RangeInclusive};
7
8#[derive(Clone, Debug)]
14#[must_use = "iterators are lazy and do nothing unless consumed"]
15pub struct SymDiffIter<T, I>
16where
17 T: Integer,
18 I: SortedStarts<T>,
19{
20 iter: I,
21 start_or_min_value: T,
22 end_heap: BinaryHeap<Reverse<T>>,
23 next_again: Option<RangeInclusive<T>>,
24 gather: Option<RangeInclusive<T>>,
25}
26
27impl<T, I> FusedIterator for SymDiffIter<T, I>
28where
29 T: Integer,
30 I: SortedStarts<T>,
31{
32}
33
34impl<T, I> Iterator for SymDiffIter<T, I>
35where
36 T: Integer,
37 I: SortedStarts<T>,
38{
39 type Item = RangeInclusive<T>;
40
41 fn next(&mut self) -> Option<RangeInclusive<T>> {
42 loop {
43 let count = self.end_heap.len();
44 let Some(next_range) = self.next_again.take().or_else(|| self.iter.next()) else {
45 if count == 0 {
47 return self.gather.take();
48 }
49
50 let end = self
52 .end_heap
53 .pop()
54 .expect("Real Assert: the workspace is not empty")
55 .0;
56 self.remove_same_end(end);
57 let result = self.start_or_min_value..=end;
58 if !self.end_heap.is_empty() {
59 self.start_or_min_value = end.add_one(); }
61 if let Some(result) = self.process(count.is_odd(), result) {
62 return result;
63 }
64 continue;
65 };
66
67 let (next_start, next_end) = next_range.into_inner();
70 if count == 0 || self.start_or_min_value == next_start {
71 self.start_or_min_value = next_start;
72 self.end_heap.push(Reverse(next_end));
73 continue;
74 }
75
76 let end = self
78 .end_heap
79 .peek()
80 .expect("Real Assert: The workspace has a first chunk.")
81 .0;
82 if next_start <= end {
83 let result = self.start_or_min_value..=next_start.sub_one();
84 self.start_or_min_value = next_start;
85 self.end_heap.push(Reverse(next_end));
86 if let Some(result) = self.process(count.is_odd(), result) {
87 return result;
88 }
89 continue;
90 }
91
92 self.remove_same_end(end);
95 let result = self.start_or_min_value..=end;
96 if self.end_heap.is_empty() {
97 self.start_or_min_value = next_start;
98 self.end_heap.push(Reverse(next_end));
99 if let Some(result) = self.process(count.is_odd(), result) {
100 return result;
101 }
102 continue;
103 }
104
105 self.start_or_min_value = end.add_one();
108 self.next_again = Some(next_start..=next_end);
109 if let Some(result) = self.process(count.is_odd(), result) {
110 return result;
111 }
112 }
114 }
115}
116
117impl<T, I> SymDiffIter<T, I>
118where
119 T: Integer,
120 I: SortedStarts<T>,
121{
122 #[inline]
123 fn remove_same_end(&mut self, end: T) {
124 while let Some(end2) = self.end_heap.peek() {
125 if end2.0 == end {
126 self.end_heap.pop();
127 } else {
128 break;
129 }
130 }
131 }
132
133 #[inline]
134 #[allow(clippy::option_option)]
135 fn process(
136 &mut self,
137 keep: bool,
138 next: RangeInclusive<T>,
139 ) -> Option<Option<RangeInclusive<T>>> {
140 if !keep {
141 return None;
142 }
143 let Some(gather) = self.gather.take() else {
144 self.gather = Some(next);
145 return None;
146 };
147 let (next_start, next_end) = next.into_inner();
151 let (gather_start, gather_end) = gather.into_inner();
152
153 debug_assert!(gather_end < next_start); if gather_end.add_one() == next_start {
158 self.gather = Some(gather_start..=next_end);
159 return None;
160 }
161
162 self.gather = Some(next_start..=next_end);
164 Some(Some(gather_start..=gather_end))
165 }
166
167 #[inline]
168 pub(crate) fn new(iter: I) -> Self {
169 Self {
170 iter,
171 start_or_min_value: T::min_value(),
172 end_heap: BinaryHeap::with_capacity(10),
173 next_again: None,
174 gather: None,
175 }
176 }
177}
178
179impl<T, L, R> SymDiffMerge<T, L, R>
180where
181 T: Integer,
182 L: SortedDisjoint<T>,
183 R: SortedDisjoint<T>,
184{
185 #[inline]
186 pub(crate) fn new2(left: L, right: R) -> Self {
187 let iter = Merge::new(left, right);
188 Self::new(iter)
189 }
190}
191
192impl<T, J> SymDiffKMerge<T, J>
193where
194 T: Integer,
195 J: SortedDisjoint<T>,
196{
197 #[inline]
198 pub(crate) fn new_k<K>(k: K) -> Self
199 where
200 K: IntoIterator<Item = J>,
201 {
202 let iter = KMerge::new(k);
203 Self::new(iter)
204 }
205}