use crate::utilities::heaps::heap::{ heapify, heapify_tail, sift_down };
use crate::utilities::order::{JudgePartialOrder, OrderOperatorAuto, OrderOperatorAutoReverse, OrderOperatorByLessThan};
macro_rules! debug_fmt_fields {
($tyname:ident, $($($field:ident).+),*) => {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
f.debug_struct(stringify!($tyname))
$(
.field(stringify!($($field).+), &self.$($field).+)
)*
.finish()
}
}
}
macro_rules! clone_fields {
($($field:ident),*) => {
fn clone(&self) -> Self {
Self {
$($field: self.$field.clone(),)*
}
}
}
}
#[inline]
fn hacked_size_hint_add_scalar(sh: (usize, Option<usize>), x: usize) -> (usize, Option<usize>)
{
let (mut low, mut hi) = sh;
low = low.saturating_add(x);
hi = hi.and_then(|elt| elt.checked_add(x));
(low, hi)
}
#[inline]
fn hacked_size_hint_add(a: (usize, Option<usize>), b: (usize, Option<usize>)) -> (usize, Option<usize>)
{
let min = a.0.checked_add(b.0).unwrap_or(usize::MAX);
let max = match (a.1, b.1) {
(Some(x), Some(y)) => x.checked_add(y),
_ => None,
};
(min, max)
}
use std::mem::replace;
use std::fmt;
use super::super::general::PeekUnqualified;
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct HeadTailHit<I>
where I: Iterator
{
pub head: I::Item,
pub tail: I,
}
impl<I> HeadTailHit<I>
where I: Iterator
{
pub fn new(mut it: I) -> Option<HeadTailHit<I>> {
let head = it.next();
head.map(|h| {
HeadTailHit {
head: h,
tail: it,
}
})
}
fn next(&mut self) -> Option<I::Item> {
if let Some(next) = self.tail.next() {
Some(replace(&mut self.head, next))
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
hacked_size_hint_add_scalar(self.tail.size_hint(), 1)
}
}
impl<I> Clone for HeadTailHit<I>
where I: Iterator + Clone,
I::Item: Clone
{
fn clone(&self) -> Self {
Self { head: self.head.clone(), tail: self.tail.clone() }
}
}
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct IteratorsMergedInSortedOrder<I, F>
where I: Iterator,
{
heap: Vec<HeadTailHit<I>>,
less_than: F,
}
impl <I,F>
Clone for IteratorsMergedInSortedOrder<I, F>
where I: Iterator + Clone,
I::Item: Clone, F: Clone,
{
fn clone(&self) -> Self {
IteratorsMergedInSortedOrder {
heap: self.heap.clone(),
less_than: self.less_than.clone(),
}
}
}
impl<I, F> fmt::Debug for IteratorsMergedInSortedOrder<I, F>
where
I: Iterator + fmt::Debug,
I::Item: fmt::Debug,
F: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("IteratorsMergedInSortedOrder")
.field("heap", &self.heap)
.field("less_than", &self.less_than)
.finish()
}
}
impl <I,F>
PartialEq for IteratorsMergedInSortedOrder<I, F>
where I: PartialEq + Iterator< Item: PartialEq >,
F: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
( self.heap == other.heap ) & ( self.less_than == other.less_than )
}
}
impl <I,F>
Eq for IteratorsMergedInSortedOrder<I, F>
where I: Eq + Iterator< Item: Eq >,
F: Eq,
{}
impl <I,F>
PartialOrd for IteratorsMergedInSortedOrder<I, F>
where I: PartialOrd + Iterator< Item: PartialOrd >,
F: PartialOrd,
{
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
match self.heap.partial_cmp(&other.heap) {
Some(core::cmp::Ordering::Equal) => {}
ord => return ord,
}
self.less_than.partial_cmp(&other.less_than)
}
}
impl <I,F>
Ord for IteratorsMergedInSortedOrder<I, F>
where I: Ord + Iterator< Item: Ord >,
F: Ord,
{
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
match self.heap.cmp(&other.heap) {
core::cmp::Ordering::Equal => {}
ord => return ord,
}
self.less_than.cmp(&other.less_than)
}
}
impl <I, F> IteratorsMergedInSortedOrder < I, F >
where
I: Iterator,
F: JudgePartialOrder< <I as IntoIterator>::Item >
{
pub fn new( less_than: F ) -> IteratorsMergedInSortedOrder< I, F >
{
IteratorsMergedInSortedOrder{ heap: Vec::new(), less_than }
}
pub fn is_empty( &self ) -> bool { self.heap.is_empty() }
pub fn len( &self ) -> usize { self.heap.len() }
pub fn clear( &mut self ) { self.heap.clear() }
pub fn bulk_insert< J >( &mut self, iterables_to_insert: J )
where
J: IntoIterator,
J::Item: IntoIterator< IntoIter = I >,
{
let tail_base = self.heap.len();
let iter = iterables_to_insert.into_iter();
self.heap.extend(iter.filter_map(|it| HeadTailHit::new(it.into_iter())));
let less_than = &mut self.less_than;
heapify_tail(&mut self.heap, |a, b| less_than.judge_lt( &a.head, &b.head),
& tail_base);
}
pub fn insert_one_iter< J >( &mut self, iterable: J )
where
J: IntoIterator< IntoIter = I >,
{
let iterables_to_insert = std::iter::once( iterable );
self.bulk_insert(iterables_to_insert);
}
}
impl<I, F> Iterator for IteratorsMergedInSortedOrder<I, F>
where I: Iterator,
F: JudgePartialOrder< I::Item>
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
if self.heap.is_empty() {
return None;
}
let result = if let Some(next) = self.heap[0].next() {
next
} else {
self.heap.swap_remove(0).head
};
let less_than = &mut self.less_than;
sift_down(&mut self.heap, 0, |a, b| less_than.judge_lt(&a.head, &b.head));
Some(result)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.heap.iter()
.map(|i| i.size_hint())
.reduce(hacked_size_hint_add)
.unwrap_or((0, Some(0)))
}
}
impl < I, F > PeekUnqualified for IteratorsMergedInSortedOrder< I, F >
where I: Iterator,
F: JudgePartialOrder< I::Item>,
{
fn peek_unqualified( &mut self ) -> Option< & <Self as Iterator>::Item > {
match self.heap.is_empty() {
true => { None },
false => { Some( & self.heap[0].head ) }
}
}
}
pub fn hit_merge_by_predicate<I, F>(iterable: I, less_than: F)
-> IteratorsMergedInSortedOrder<<I::Item as IntoIterator>::IntoIter, F>
where I: IntoIterator,
I::Item: IntoIterator,
F: JudgePartialOrder< <<I as IntoIterator>::Item as IntoIterator>::Item>,
{
let iter = iterable.into_iter();
let (lower, _) = iter.size_hint();
let mut heap: Vec<_> = Vec::with_capacity(lower);
heap.extend(iter.filter_map(|it| HeadTailHit::new(it.into_iter())));
heapify(&mut heap, |a, b| less_than.judge_lt(&a.head, &b.head));
IteratorsMergedInSortedOrder { heap, less_than }
}
pub fn hit_merge_by_fnmut<I, F>(iter: I, less_than: F)
-> IteratorsMergedInSortedOrder<<I::Item as IntoIterator>::IntoIter, OrderOperatorByLessThan< F, <I::Item as IntoIterator>::Item > >
where I: Sized + IntoIterator,
I::Item: IntoIterator,
F: Fn(&<I::Item as IntoIterator>::Item,
&<I::Item as IntoIterator>::Item) -> bool
{
let order_operator: OrderOperatorByLessThan<F, <I::Item as IntoIterator>::Item > = OrderOperatorByLessThan::new( less_than );
hit_merge_by_predicate(iter, order_operator )
}
pub fn hit_merge<I>(iterable: I)
-> IteratorsMergedInSortedOrder<<I::Item as IntoIterator>::IntoIter, OrderOperatorAuto>
where I: IntoIterator,
I::Item: IntoIterator,
<<I as IntoIterator>::Item as IntoIterator>::Item: PartialOrd
{
hit_merge_by_predicate(iterable, OrderOperatorAuto)
}
pub fn hit_merge_descend<I>(iterable: I)
-> IteratorsMergedInSortedOrder<<I::Item as IntoIterator>::IntoIter, OrderOperatorAutoReverse>
where I: IntoIterator,
I::Item: IntoIterator,
<<I as IntoIterator>::Item as IntoIterator>::Item: PartialOrd
{
hit_merge_by_predicate(iterable, OrderOperatorAutoReverse)
}
pub fn hit_bulk_insert< I, F >(
merged : &mut IteratorsMergedInSortedOrder<<I::Item as IntoIterator>::IntoIter, F>,
iterable: I,
)
where I: IntoIterator,
I::Item: IntoIterator,
F: JudgePartialOrder< <<I as IntoIterator>::Item as IntoIterator>::Item>
{
merged.bulk_insert( iterable )
}
pub trait HitMergeByPredicateTrait{
fn hit_merge_by_predicate< F >( self, less_than: F)
-> IteratorsMergedInSortedOrder<<Self::Item as IntoIterator>::IntoIter, F>
where Self: IntoIterator + Sized,
Self::Item: IntoIterator,
F: JudgePartialOrder< <<Self as IntoIterator>::Item as IntoIterator>::Item>
{
hit_merge_by_predicate( self, less_than )
}
}
impl < T >HitMergeByPredicateTrait for
T
where
T: IntoIterator + Sized,
T::Item: IntoIterator,
{}
#[cfg(test)]
mod tests {
use ordered_float::OrderedFloat;
use super::*;
use crate::{utilities::{iterators::general::PeekUnqualified, order::OrderOperatorAuto}, algebra::rings::types::field_prime_order::{PrimeOrderField}, algebra::vectors::operations::{VectorOperations}};
#[test]
fn test_heap_clone() {
let ordered_sequences = vec![ vec![1, -2], vec![0, -3] ];
let merged = hit_merge_by_fnmut( ordered_sequences, |a: &i64, b: &i64| &a.abs() < &b.abs() );
let _ = merged.clone();
}
#[test]
fn test_heap_functions() {
let ordered_sequences = vec![ vec![1, -2], vec![0, -3] ];
let mut merged = hit_merge_by_fnmut( ordered_sequences, |a: &i64, b: &i64| &a.abs() < &b.abs() );
while let Some( x ) = merged.peek_unqualified() {
assert_eq!( Some(*x), merged.next() )
}
let ordered_sequences: Vec<Vec<usize>> = vec![ vec![1, 2, 3], vec![] ];
let mut merged = hit_merge_by_fnmut( ordered_sequences, |a: &usize, b: &usize| &a < &b );
while let Some( x ) = merged.peek_unqualified() {
assert_eq!( Some(*x), merged.next() )
}
let ordered_sequences: Vec<Vec<i64>> = vec![ vec![], vec![] ];
let mut merged = hit_merge_by_fnmut( ordered_sequences, |a: &i64, b: &i64| &a.abs() < &b.abs() );
while let Some( x ) = merged.peek_unqualified() {
assert_eq!( Some(*x), merged.next() )
}
}
#[test]
fn test_heap_allocations() {
let nvertices = 800;
let ring_operator = PrimeOrderField::new(3);
let ordered_sequences: Vec< Vec< _ > > = vec![
(0..nvertices)
.map(
|x|
(
( OrderedFloat( x as f64 ), vec![x,x+1,x+2] ),
1usize
)
).collect()
; nvertices as usize ];
let input_1 = ordered_sequences.iter().map(|x| x.iter().cloned().peekable());
let _input_2 = ordered_sequences.iter().map(|x| x.iter().cloned().peekable());
let mut h = hit_merge_by_predicate( input_1, OrderOperatorAuto ).simplify( ring_operator );
for vec_num in 0 .. nvertices {
hit_bulk_insert( &mut h.unsimplified, vec![ ordered_sequences[ vec_num as usize ].iter().cloned().peekable() ] );
let _ = h.next();
}
let input_2 = ordered_sequences.iter().map(|x| x.iter().cloned().peekable());
hit_bulk_insert( &mut h.unsimplified, input_2 );
println!("henry");
}
}