Tue, 20 Feb 2024 12:33:16 -0500
Logarithmic logging base correction
/*! Iteration utilities. This includes * [Stateful][StatefulIterator] and [restartable][RestartableIterator] iterators. * Variants of [`Iterator::map`] and [`Iterator::filter_map`], etc., that work on functions instead of closures, forgoing exact closure type signature specification; see [`Mappable`]. */ use crate::types::Integer; use std::marker::PhantomData; /// Trait for iterators that can be queried the current state without advancing. pub trait StatefulIterator : Iterator { /// Return current value of iterator. If the iterator has not yet started, /// `None` should be returned. fn current(&self) -> Option<Self::Item>; } /// Iterators that can be restarted and queried the current state without /// advancing to next state. pub trait RestartableIterator : StatefulIterator { /// Restart the iterator. Return the first item. fn restart(&mut self) -> Option<Self::Item>; } /// A variant of `std::iter::Map` that works for methods instead of closures, /// so can be returned from functions without `dyn`. /// Use [`Mappable::mapF`] to create this iterator. pub struct MapF<I,J> where I : Iterator { iter : I, func : fn(I::Item) -> J, } impl<I,J> Iterator for MapF<I,J> where I : Iterator { type Item = J; fn next(&mut self) -> Option<J> { self.iter.next().map(|item| (self.func)(item)) } } /// A variant of [`MapF`] with extra data for the function stored as a reference. /// See also [`MapZ`] and use [`Mappable::mapX`] to create this iteartor. pub struct MapX<'a,I,T,J> where I : Iterator { iter : I, data : &'a T, func : fn(&'a T, I::Item) -> J, } impl<'a,I,T,J> Iterator for MapX<'a,I,T,J> where I : Iterator { type Item = J; fn next(&mut self) -> Option<J> { self.iter.next().map(|item| (self.func)(self.data, item)) } } /// A variant of [`MapF`] and [`MapX`] with extra data for the function stored in the struct. /// Use [`Mappable::mapZ`] to create this iterator. pub struct MapZ<I,T,J> where I : Iterator { iter : I, data : T, func : fn(&T, I::Item) -> J, } impl<'a,I,T,J> Iterator for MapZ<I,T,J> where I : Iterator { type Item = J; fn next(&mut self) -> Option<J> { self.iter.next().map(|item| (self.func)(&self.data, item)) } } /// A variant of `std::iter::FilterMap` that works for methods instead of closures, /// so can be returned from functions without `dyn`. pub struct FilterMapX<'a,I,T,J> where I : Iterator { iter : I, data : &'a T, func : fn(&'a T, I::Item) -> Option<J>, } impl<'a,I,T,J> Iterator for FilterMapX<'a,I,T,J> where I : Iterator { type Item = J; fn next(&mut self) -> Option<J> { while let Some(item) = self.iter.next() { let v = (self.func)(self.data, item); if v.is_some() { return v } } None } } /// Helper for [`Mappable::filter_zip`]. pub struct FilterZip<I, J> where I : Iterator, J : Iterator<Item=bool> { iter : I, filter : J, } impl<I,J> Iterator for FilterZip<I, J> where I : Iterator, J : Iterator<Item=bool> { type Item = I::Item; #[inline] fn next(&mut self) -> Option<I::Item> { while let (v@Some(..), Some(filt)) = (self.iter.next(), self.filter.next()) { if filt { return v } } None } } /// This trait implements several mapping methods on iterators. pub trait Mappable : Iterator + Sized { /// Apply `func` to the output of the iterator. #[allow(non_snake_case)] fn mapF<J>(self, func : fn(Self::Item) -> J) -> MapF<Self,J>; /// Apply `func` to the output of the iterator, passing also `d` to it. #[allow(non_snake_case)] fn mapX<'a,T,J>(self, d : &'a T, func : fn(&'a T, Self::Item) -> J) -> MapX<'a,Self,T,J>; /// Apply `func` to the output of the iterator, passing also `d` to it. #[allow(non_snake_case)] fn mapZ<T,J>(self, d : T, func : fn(&T, Self::Item) -> J) -> MapZ<Self,T,J>; /// Apply `func` to the output of the iterator, filtering based on the result. /// The data `d` is passed to `func`. #[allow(non_snake_case)] fn filter_mapX<'a,T,J>(self, d : &'a T, func : fn(&'a T, Self::Item) -> Option<J>) -> FilterMapX<'a,Self,T,J>; /// Filter `self` based on another iterator `iter` with `bool` items. fn filter_zip<J>(self, filter : J) -> FilterZip<Self, J> where J : Iterator<Item=bool>; } impl<I> Mappable for I where I : Iterator + Sized { #[inline] fn mapF<J>(self, func : fn(Self::Item) -> J) -> MapF<Self,J> { MapF{ iter : self, func : func } } #[inline] fn mapX<'a,T,J>(self, d : &'a T, func : fn(&'a T, Self::Item) -> J) -> MapX<'a,Self,T,J> { MapX{ iter : self, data : d, func : func } } #[inline] fn mapZ<T,J>(self, d : T, func : fn(&T, Self::Item) -> J) -> MapZ<Self,T,J> { MapZ{ iter : self, data : d, func : func } } #[inline] fn filter_mapX<'a,T,J>(self, d : &'a T, func : fn(&'a T, Self::Item) -> Option<J>) -> FilterMapX<'a,Self,T,J> { FilterMapX{ iter : self, data : d, func : func } } #[inline] fn filter_zip<J>(self, filter : J) -> FilterZip<Self, J> where J : Iterator<Item=bool> { FilterZip{ iter : self, filter : filter } } } /// A [`RestartableIterator`] over the range ยด[start, end)`. #[derive(Clone,Copy,Debug)] pub struct RangeIter<T> { start : T, end : T, value : Option<T>, } pub trait StepNext : Ord + Copy { fn step_next(&self) -> Self; fn dist_to(&self, other : &Self) -> usize; } impl<T : Integer + Into<usize>> StepNext for T { #[inline] fn step_next(&self) -> Self { *self + Self::ONE } #[inline] fn dist_to(&self, other : &Self) -> usize { if *other >= *self { (*other - *self).into() } else { 0 } } } impl<T : StepNext> RangeIter<T> { /// Create a new [`RangeIter`]. pub fn new(start : T, end : T) -> Self { RangeIter{ start : start.min(end), end : end, value : None } } } impl<T : StepNext> Iterator for RangeIter<T> { type Item = T; #[inline] fn next(&mut self) -> Option<Self::Item> { match self.value { None => { if self.start < self.end { self.value = Some(self.start); self.value } else { None } } Some(v) => { let vn = v.step_next(); if vn < self.end { self.value = Some(vn); self.value } else { None } } } } } impl<T : StepNext> ExactSizeIterator for RangeIter<T> { #[inline] fn len(&self) -> usize { self.start.dist_to(&self.end) } } impl<T : StepNext> StatefulIterator for RangeIter<T> { #[inline] fn current(&self) -> Option<Self::Item> { self.value } } impl<T : StepNext> RestartableIterator for RangeIter<T> { fn restart(&mut self) -> Option<Self::Item> { if self.start < self.end { self.value = Some(self.start); self.value } else { None } } } /// A restartable slice iterator. pub struct RestartableSliceIter<'a, T> { inner : RangeIter<*const T>, _phantom : PhantomData<&'a[T]> } impl<T> StepNext for *const T { #[inline] fn step_next(&self) -> Self { unsafe { self.add(1) } } #[inline] fn dist_to(&self, other : &Self) -> usize { unsafe { other.offset_from(*self).max(0) as usize } } } impl<'a, T : 'a> RestartableSliceIter<'a, T> { /// Converts `Some` pointer to `Some` reference fn map_result(result : Option<*const T>) -> Option<&'a T> { match result { None => { None } Some(ptr) => { Some(unsafe{ &*ptr }) } } } /// Creates a restartable iterator over `slice`. pub fn new(slice : &'a [T]) -> Self { let ptr_range = slice.as_ptr_range(); let inner = RangeIter::new(ptr_range.start, ptr_range.end); RestartableSliceIter{ inner : inner, _phantom : PhantomData } } } impl<'a, T : 'a> Iterator for RestartableSliceIter<'a, T> { type Item = &'a T; #[inline] fn next(&mut self) -> Option<&'a T> { Self::map_result(self.inner.next()) } } impl<'a, T : 'a> ExactSizeIterator for RestartableSliceIter<'a, T> { #[inline] fn len(&self) -> usize { self.inner.len() } } impl<'a, T : 'a> StatefulIterator for RestartableSliceIter<'a, T> { #[inline] fn current(&self) -> Option<Self::Item> { Self::map_result(self.inner.current()) } } impl<'a, T : 'a> RestartableIterator for RestartableSliceIter<'a, T> { fn restart(&mut self) -> Option<Self::Item> { Self::map_result(self.inner.current()) } } /// A restartable variant of [`std::iter::Cloned`]. pub struct RestartableCloned<I : Iterator> { inner : I, } impl<'a, T : Clone + 'a , I : Iterator<Item=&'a T>> RestartableCloned<I> { fn map_result(result : Option<I::Item>) -> Option<T> { match result { None => { None } Some(v) => { Some(v.clone()) } } } pub fn new(inner : I) -> Self { RestartableCloned{ inner : inner } } } impl<'a, T : Clone + 'a , I : Iterator<Item=&'a T>> Iterator for RestartableCloned<I> { type Item = T; fn next(&mut self) -> Option<Self::Item> { Self::map_result(self.inner.next()) } } impl<'a, T : Clone + 'a , I : ExactSizeIterator<Item=&'a T>> ExactSizeIterator for RestartableCloned<I> { fn len(&self) -> usize { self.inner.len() } } impl<'a, T : Clone + 'a , I : StatefulIterator<Item=&'a T>> StatefulIterator for RestartableCloned<I> { fn current(&self) -> Option<Self::Item> { Self::map_result(self.inner.current()) } } impl<'a, T : Clone + 'a , I : RestartableIterator<Item=&'a T>> RestartableIterator for RestartableCloned<I> { fn restart(&mut self) -> Option<Self::Item> { Self::map_result(self.inner.restart()) } }