use crate::{
interval::{traits::Interval, IntInterval},
set::traits::Intersect,
};
use num::{Integer, Num, ToPrimitive};
use std::{
collections::BTreeSet,
marker::{PhantomData, Sized},
};
pub trait CommonRefinementZip<B, X, P, V>
where
B: Copy + Num + Ord,
Self: Iterator<Item = X> + Sized,
P: Clone + Interval<B> + for<'b> Intersect<&'b P, Option<P>>, {
fn get_interval_value_extractor(
&self,
) -> Box<dyn Fn(<Self as Iterator>::Item) -> (P, V)>;
fn common_refinement_zip(
mut self,
mut other: Self,
) -> CommonRefinementZipped<B, Self, X, P, V> {
let extractor = self.get_interval_value_extractor();
let mut intervals = Vec::new();
let mut values = Vec::new();
match self.next() {
None => {
intervals.push(None);
values.push(None);
}
Some(x) => {
let (interval, value) = extractor(x);
intervals.push(Some(interval));
values.push(Some(value));
}
}
match other.next() {
None => {
intervals.push(None);
values.push(None);
}
Some(x) => {
let (interval, value) = extractor(x);
intervals.push(Some(interval));
values.push(Some(value));
}
}
CommonRefinementZipped {
iters: vec![self, other],
intervals,
values,
extractor,
phantom: PhantomData,
}
}
fn into_common_refinement_zipped(
mut self,
) -> CommonRefinementZipped<B, Self, X, P, V> {
let extractor = self.get_interval_value_extractor();
let mut intervals = Vec::new();
let mut values = Vec::new();
match self.next() {
None => {
intervals.push(None);
values.push(None);
}
Some(x) => {
let (interval, value) = extractor(x);
intervals.push(Some(interval));
values.push(Some(value));
}
}
CommonRefinementZipped {
iters: vec![self],
intervals,
values,
extractor,
phantom: PhantomData,
}
}
}
impl<'a, V, B: Integer + Copy + ToPrimitive>
CommonRefinementZip<B, (&'a IntInterval<B>, &'a V), IntInterval<B>, V>
for std::collections::btree_map::Iter<'a, IntInterval<B>, V>
where
B: 'a,
V: 'a + Clone,
{
fn get_interval_value_extractor(
&self,
) -> Box<dyn Fn(<Self as Iterator>::Item) -> (IntInterval<B>, V)> {
Box::new(|item| ((*item.0).clone(), (*item.1).clone()))
}
}
impl<'a, V, B: Integer + Copy + ToPrimitive>
CommonRefinementZip<B, (IntInterval<B>, V), IntInterval<B>, V>
for std::collections::btree_map::IntoIter<IntInterval<B>, V>
where
B: 'a,
{
fn get_interval_value_extractor(
&self,
) -> Box<dyn Fn(<Self as Iterator>::Item) -> (IntInterval<B>, V)> {
Box::new(|item| (item.0, item.1))
}
}
pub struct CommonRefinementZipped<B, I, X, P, V>
where
B: Copy + Num + Ord,
I: Iterator<Item = X> + Sized,
P: Clone + Interval<B> + for<'b> Intersect<&'b P, Option<P>>, {
iters: Vec<I>,
intervals: Vec<Option<P>>,
values: Vec<Option<V>>,
extractor: Box<dyn Fn(X) -> (P, V)>,
phantom: PhantomData<B>,
}
impl<B, I, X, P, V> Iterator for CommonRefinementZipped<B, I, X, P, V>
where
B: Copy + Num + Ord,
I: Iterator<Item = X> + Sized,
P: Clone + Interval<B> + for<'b> Intersect<&'b P, Option<P>>,
V: Clone,
{
type Item = (P, Vec<Option<V>>);
fn next(&mut self) -> Option<Self::Item> {
let starts: BTreeSet<B> = self
.intervals
.iter()
.filter_map(|i| i.clone().and_then(|i| Some(i.get_start())))
.collect();
let ends: BTreeSet<B> = self
.intervals
.iter()
.filter_map(|i| i.clone().and_then(|i| Some(i.get_end())))
.collect();
let mut starts_iter = starts.iter();
let min_start = match starts_iter.next() {
None => return None,
Some(&a) => a,
};
let second_min_start = starts_iter.next();
let min_end = *ends.iter().next().unwrap();
let min_refinement = match second_min_start {
Some(&second_min_start) => {
if second_min_start <= min_end {
P::from_boundaries(min_start, second_min_start - B::one())
} else {
P::from_boundaries(min_start, min_end)
}
}
None => P::from_boundaries(min_start, min_end),
};
let mut refinement_values = Vec::new();
for ((interval, iter), v) in self
.intervals
.iter_mut()
.zip(self.iters.iter_mut())
.zip(self.values.iter_mut())
{
match interval {
Some(i) => {
if i.has_non_empty_intersection_with(&min_refinement) {
refinement_values.push((*v).clone());
let remainder = P::from_boundaries(
min_refinement.get_end() + B::one(),
i.get_end(),
);
if remainder.is_empty() {
match iter.next() {
None => {
*interval = None;
*v = None;
}
Some(x) => {
let (new_interval, new_val) =
(self.extractor)(x);
*interval = Some(new_interval);
*v = Some(new_val);
}
}
} else {
*interval = Some(remainder);
}
} else {
refinement_values.push(None);
}
}
None => {
refinement_values.push(None);
}
}
}
Some((min_refinement, refinement_values))
}
}
impl<B, I, X, P, V> CommonRefinementZipped<B, I, X, P, V>
where
B: Copy + Num + Ord,
I: Iterator<Item = X> + Sized,
P: Clone + Interval<B> + for<'b> Intersect<&'b P, Option<P>>,
{
pub fn common_refinement_flat_zip(
mut self,
mut other: I,
) -> CommonRefinementZipped<B, I, X, P, V>
where
I: Iterator<Item = X> + Sized, {
match other.next() {
None => {
self.intervals.push(None);
self.values.push(None);
}
Some(x) => {
let (i, v) = (self.extractor)(x);
self.intervals.push(Some(i.clone()));
self.values.push(Some(v));
}
}
self.iters.push(other);
CommonRefinementZipped {
iters: self.iters,
intervals: self.intervals,
values: self.values,
extractor: self.extractor,
phantom: PhantomData,
}
}
}