Tue, 20 Feb 2024 12:33:16 -0500
Logarithmic logging base correction
5 | 1 | /*! |
2 | Iteration utilities. | |
3 | ||
4 | This includes | |
5 | * [Stateful][StatefulIterator] and [restartable][RestartableIterator] iterators. | |
6 | * Variants of [`Iterator::map`] and [`Iterator::filter_map`], etc., that work on functions | |
7 | instead of closures, forgoing exact closure type signature specification; see [`Mappable`]. | |
8 | ||
9 | */ | |
0 | 10 | |
11 | use crate::types::Integer; | |
12 | use std::marker::PhantomData; | |
13 | ||
14 | /// Trait for iterators that can be queried the current state without advancing. | |
15 | pub trait StatefulIterator : Iterator { | |
16 | /// Return current value of iterator. If the iterator has not yet started, | |
17 | /// `None` should be returned. | |
18 | fn current(&self) -> Option<Self::Item>; | |
19 | } | |
20 | ||
21 | /// Iterators that can be restarted and queried the current state without | |
22 | /// advancing to next state. | |
23 | pub trait RestartableIterator : StatefulIterator { | |
24 | /// Restart the iterator. Return the first item. | |
25 | fn restart(&mut self) -> Option<Self::Item>; | |
26 | } | |
27 | ||
28 | /// A variant of `std::iter::Map` that works for methods instead of closures, | |
29 | /// so can be returned from functions without `dyn`. | |
30 | /// Use [`Mappable::mapF`] to create this iterator. | |
31 | pub struct MapF<I,J> where I : Iterator { | |
32 | iter : I, | |
33 | func : fn(I::Item) -> J, | |
34 | } | |
35 | ||
36 | impl<I,J> Iterator for MapF<I,J> where I : Iterator { | |
37 | type Item = J; | |
38 | fn next(&mut self) -> Option<J> { | |
39 | self.iter.next().map(|item| (self.func)(item)) | |
40 | } | |
41 | } | |
42 | ||
43 | /// A variant of [`MapF`] with extra data for the function stored as a reference. | |
44 | /// See also [`MapZ`] and use [`Mappable::mapX`] to create this iteartor. | |
45 | pub struct MapX<'a,I,T,J> where I : Iterator { | |
46 | iter : I, | |
47 | data : &'a T, | |
48 | func : fn(&'a T, I::Item) -> J, | |
49 | } | |
50 | ||
51 | impl<'a,I,T,J> Iterator for MapX<'a,I,T,J> where I : Iterator { | |
52 | type Item = J; | |
53 | fn next(&mut self) -> Option<J> { | |
54 | self.iter.next().map(|item| (self.func)(self.data, item)) | |
55 | } | |
56 | } | |
57 | ||
58 | /// A variant of [`MapF`] and [`MapX`] with extra data for the function stored in the struct. | |
59 | /// Use [`Mappable::mapZ`] to create this iterator. | |
60 | pub struct MapZ<I,T,J> where I : Iterator { | |
61 | iter : I, | |
62 | data : T, | |
63 | func : fn(&T, I::Item) -> J, | |
64 | } | |
65 | ||
66 | impl<'a,I,T,J> Iterator for MapZ<I,T,J> where I : Iterator { | |
67 | type Item = J; | |
68 | fn next(&mut self) -> Option<J> { | |
69 | self.iter.next().map(|item| (self.func)(&self.data, item)) | |
70 | } | |
71 | } | |
72 | ||
73 | /// A variant of `std::iter::FilterMap` that works for methods instead of closures, | |
74 | /// so can be returned from functions without `dyn`. | |
75 | pub struct FilterMapX<'a,I,T,J> where I : Iterator { | |
76 | iter : I, | |
77 | data : &'a T, | |
78 | func : fn(&'a T, I::Item) -> Option<J>, | |
79 | } | |
80 | ||
81 | impl<'a,I,T,J> Iterator for FilterMapX<'a,I,T,J> where I : Iterator { | |
82 | type Item = J; | |
83 | fn next(&mut self) -> Option<J> { | |
84 | while let Some(item) = self.iter.next() { | |
85 | let v = (self.func)(self.data, item); | |
86 | if v.is_some() { | |
87 | return v | |
88 | } | |
89 | } | |
90 | None | |
91 | } | |
92 | } | |
93 | ||
94 | /// Helper for [`Mappable::filter_zip`]. | |
95 | pub struct FilterZip<I, J> | |
96 | where I : Iterator, | |
97 | J : Iterator<Item=bool> { | |
98 | iter : I, | |
99 | filter : J, | |
100 | } | |
101 | ||
102 | impl<I,J> Iterator for FilterZip<I, J> | |
103 | where I : Iterator, | |
104 | J : Iterator<Item=bool> { | |
105 | type Item = I::Item; | |
106 | #[inline] | |
107 | fn next(&mut self) -> Option<I::Item> { | |
108 | while let (v@Some(..), Some(filt)) = (self.iter.next(), self.filter.next()) { | |
109 | if filt { | |
110 | return v | |
111 | } | |
112 | } | |
113 | None | |
114 | } | |
115 | } | |
116 | ||
117 | /// This trait implements several mapping methods on iterators. | |
118 | pub trait Mappable : Iterator + Sized { | |
119 | /// Apply `func` to the output of the iterator. | |
120 | #[allow(non_snake_case)] | |
121 | fn mapF<J>(self, func : fn(Self::Item) -> J) -> MapF<Self,J>; | |
122 | /// Apply `func` to the output of the iterator, passing also `d` to it. | |
123 | #[allow(non_snake_case)] | |
124 | fn mapX<'a,T,J>(self, d : &'a T, func : fn(&'a T, Self::Item) -> J) -> MapX<'a,Self,T,J>; | |
125 | /// Apply `func` to the output of the iterator, passing also `d` to it. | |
126 | #[allow(non_snake_case)] | |
127 | fn mapZ<T,J>(self, d : T, func : fn(&T, Self::Item) -> J) -> MapZ<Self,T,J>; | |
128 | /// Apply `func` to the output of the iterator, filtering based on the result. | |
129 | /// The data `d` is passed to `func`. | |
130 | #[allow(non_snake_case)] | |
131 | fn filter_mapX<'a,T,J>(self, d : &'a T, func : fn(&'a T, Self::Item) -> Option<J>) -> FilterMapX<'a,Self,T,J>; | |
132 | ||
133 | /// Filter `self` based on another iterator `iter` with `bool` items. | |
134 | fn filter_zip<J>(self, filter : J) -> FilterZip<Self, J> where J : Iterator<Item=bool>; | |
135 | } | |
136 | ||
137 | impl<I> Mappable for I where I : Iterator + Sized { | |
138 | #[inline] | |
139 | fn mapF<J>(self, func : fn(Self::Item) -> J) -> MapF<Self,J> { | |
140 | MapF{ iter : self, func : func } | |
141 | } | |
142 | #[inline] | |
143 | fn mapX<'a,T,J>(self, d : &'a T, func : fn(&'a T, Self::Item) -> J) -> MapX<'a,Self,T,J> { | |
144 | MapX{ iter : self, data : d, func : func } | |
145 | } | |
146 | #[inline] | |
147 | fn mapZ<T,J>(self, d : T, func : fn(&T, Self::Item) -> J) -> MapZ<Self,T,J> { | |
148 | MapZ{ iter : self, data : d, func : func } | |
149 | } | |
150 | #[inline] | |
151 | fn filter_mapX<'a,T,J>(self, d : &'a T, func : fn(&'a T, Self::Item) -> Option<J>) | |
152 | -> FilterMapX<'a,Self,T,J> { | |
153 | FilterMapX{ iter : self, data : d, func : func } | |
154 | } | |
155 | ||
156 | #[inline] | |
157 | fn filter_zip<J>(self, filter : J) -> FilterZip<Self, J> | |
158 | where J : Iterator<Item=bool> { | |
159 | FilterZip{ iter : self, filter : filter } | |
160 | } | |
161 | } | |
162 | ||
163 | /// A [`RestartableIterator`] over the range ´[start, end)`. | |
164 | #[derive(Clone,Copy,Debug)] | |
165 | pub struct RangeIter<T> { | |
166 | start : T, | |
167 | end : T, | |
168 | value : Option<T>, | |
169 | } | |
170 | ||
171 | pub trait StepNext : Ord + Copy { | |
172 | fn step_next(&self) -> Self; | |
173 | fn dist_to(&self, other : &Self) -> usize; | |
174 | } | |
175 | ||
176 | impl<T : Integer + Into<usize>> StepNext for T { | |
177 | #[inline] | |
178 | fn step_next(&self) -> Self { *self + Self::ONE } | |
179 | ||
180 | #[inline] | |
181 | fn dist_to(&self, other : &Self) -> usize { | |
182 | if *other >= *self { | |
183 | (*other - *self).into() | |
184 | } else { | |
185 | 0 | |
186 | } | |
187 | } | |
188 | } | |
189 | ||
190 | impl<T : StepNext> RangeIter<T> { | |
191 | /// Create a new [`RangeIter`]. | |
192 | pub fn new(start : T, end : T) -> Self { | |
193 | RangeIter{ start : start.min(end), end : end, value : None } | |
194 | } | |
195 | } | |
196 | ||
197 | impl<T : StepNext> Iterator for RangeIter<T> { | |
198 | type Item = T; | |
199 | ||
200 | #[inline] | |
201 | fn next(&mut self) -> Option<Self::Item> { | |
202 | match self.value { | |
203 | None => { | |
204 | if self.start < self.end { | |
205 | self.value = Some(self.start); | |
206 | self.value | |
207 | } else { | |
208 | None | |
209 | } | |
210 | } | |
211 | Some(v) => { | |
212 | let vn = v.step_next(); | |
213 | if vn < self.end { | |
214 | self.value = Some(vn); | |
215 | self.value | |
216 | } else { | |
217 | None | |
218 | } | |
219 | } | |
220 | } | |
221 | } | |
222 | } | |
223 | ||
224 | impl<T : StepNext> ExactSizeIterator for RangeIter<T> { | |
225 | #[inline] | |
226 | fn len(&self) -> usize { self.start.dist_to(&self.end) } | |
227 | } | |
228 | ||
229 | impl<T : StepNext> StatefulIterator for RangeIter<T> { | |
230 | #[inline] | |
231 | fn current(&self) -> Option<Self::Item> { | |
232 | self.value | |
233 | } | |
234 | } | |
235 | ||
236 | impl<T : StepNext> RestartableIterator for RangeIter<T> { | |
237 | fn restart(&mut self) -> Option<Self::Item> { | |
238 | if self.start < self.end { | |
239 | self.value = Some(self.start); | |
240 | self.value | |
241 | } else { | |
242 | None | |
243 | } | |
244 | } | |
245 | } | |
246 | ||
5 | 247 | /// A restartable slice iterator. |
248 | pub struct RestartableSliceIter<'a, T> { | |
0 | 249 | inner : RangeIter<*const T>, |
250 | _phantom : PhantomData<&'a[T]> | |
251 | } | |
252 | ||
253 | impl<T> StepNext for *const T { | |
254 | #[inline] | |
255 | fn step_next(&self) -> Self { unsafe { self.add(1) } } | |
256 | ||
257 | #[inline] | |
258 | fn dist_to(&self, other : &Self) -> usize { | |
259 | unsafe { other.offset_from(*self).max(0) as usize } | |
260 | } | |
261 | } | |
262 | ||
5 | 263 | impl<'a, T : 'a> RestartableSliceIter<'a, T> { |
264 | /// Converts `Some` pointer to `Some` reference | |
0 | 265 | fn map_result(result : Option<*const T>) -> Option<&'a T> { |
266 | match result { | |
267 | None => { None } | |
268 | Some(ptr) => { Some(unsafe{ &*ptr }) } | |
269 | } | |
270 | } | |
271 | ||
5 | 272 | /// Creates a restartable iterator over `slice`. |
0 | 273 | pub fn new(slice : &'a [T]) -> Self { |
274 | let ptr_range = slice.as_ptr_range(); | |
275 | let inner = RangeIter::new(ptr_range.start, ptr_range.end); | |
5 | 276 | RestartableSliceIter{ inner : inner, _phantom : PhantomData } |
0 | 277 | } |
278 | } | |
279 | ||
5 | 280 | impl<'a, T : 'a> Iterator for RestartableSliceIter<'a, T> { |
0 | 281 | type Item = &'a T; |
282 | #[inline] | |
283 | fn next(&mut self) -> Option<&'a T> { | |
284 | Self::map_result(self.inner.next()) | |
285 | } | |
286 | } | |
287 | ||
5 | 288 | impl<'a, T : 'a> ExactSizeIterator for RestartableSliceIter<'a, T> { |
0 | 289 | #[inline] |
290 | fn len(&self) -> usize { self.inner.len() } | |
291 | } | |
292 | ||
5 | 293 | impl<'a, T : 'a> StatefulIterator for RestartableSliceIter<'a, T> { |
0 | 294 | #[inline] |
295 | fn current(&self) -> Option<Self::Item> { | |
296 | Self::map_result(self.inner.current()) | |
297 | } | |
298 | } | |
299 | ||
5 | 300 | impl<'a, T : 'a> RestartableIterator for RestartableSliceIter<'a, T> { |
0 | 301 | fn restart(&mut self) -> Option<Self::Item> { |
302 | Self::map_result(self.inner.current()) | |
303 | } | |
304 | } | |
305 | ||
5 | 306 | /// A restartable variant of [`std::iter::Cloned`]. |
0 | 307 | pub struct RestartableCloned<I : Iterator> { |
308 | inner : I, | |
309 | } | |
310 | ||
311 | impl<'a, T : Clone + 'a , I : Iterator<Item=&'a T>> RestartableCloned<I> { | |
312 | fn map_result(result : Option<I::Item>) -> Option<T> { | |
313 | match result { | |
314 | None => { None } | |
315 | Some(v) => { Some(v.clone()) } | |
316 | } | |
317 | } | |
318 | ||
319 | pub fn new(inner : I) -> Self { | |
320 | RestartableCloned{ inner : inner } | |
321 | } | |
322 | } | |
323 | ||
324 | impl<'a, T : Clone + 'a , I : Iterator<Item=&'a T>> Iterator | |
325 | for RestartableCloned<I> { | |
326 | type Item = T; | |
327 | fn next(&mut self) -> Option<Self::Item> { | |
328 | Self::map_result(self.inner.next()) | |
329 | } | |
330 | } | |
331 | ||
332 | impl<'a, T : Clone + 'a , I : ExactSizeIterator<Item=&'a T>> ExactSizeIterator | |
333 | for RestartableCloned<I> { | |
334 | fn len(&self) -> usize { | |
335 | self.inner.len() | |
336 | } | |
337 | } | |
338 | ||
339 | impl<'a, T : Clone + 'a , I : StatefulIterator<Item=&'a T>> StatefulIterator | |
340 | for RestartableCloned<I> { | |
341 | fn current(&self) -> Option<Self::Item> { | |
342 | Self::map_result(self.inner.current()) | |
343 | } | |
344 | } | |
345 | ||
346 | impl<'a, T : Clone + 'a , I : RestartableIterator<Item=&'a T>> RestartableIterator | |
347 | for RestartableCloned<I> { | |
348 | fn restart(&mut self) -> Option<Self::Item> { | |
349 | Self::map_result(self.inner.restart()) | |
350 | } | |
351 | } |