#![allow(unused)]
use std::{cmp::Ordering, iter::Peekable, marker::PhantomData, ptr::NonNull};
use itertools::Chunk;
pub trait CopyFromIterExt<I> where I : Iterator, I::Item : Copy
{
fn copy_from_iter(&mut self, it : I) -> usize;
}
impl<I> CopyFromIterExt<I> for [I::Item]
where
I : Iterator,
I::Item : Copy
{
fn copy_from_iter(&mut self, it : I) -> usize {
self.iter_mut().zip(it).map(|(t,s)| *t = s).count()
}
}
impl<I> CopyFromIterExt<I> for Vec<I::Item>
where
I : Iterator,
I::Item : Copy
{
fn copy_from_iter(&mut self, it : I) -> usize {
self.as_mut_slice().copy_from_iter(it)
}
}
pub struct IndexIterator<const N : usize> {
shape : [usize; N],
cur : [usize; N],
done : bool
}
impl<const N : usize> Iterator for IndexIterator<N> {
type Item = [usize; N];
fn next(& mut self) -> Option<Self::Item> {
if self.done {
None
}
else {
let res = self.cur;
if 0 < self.shape.iter().zip(self.cur.iter_mut()).rev().fold(1, |v,(&d, i)| { *i += v; if *i < d { 0 } else { *i = 0; 1 } }) {
self.done = true;
}
Some(res)
}
}
}
impl<const N : usize> IndexIterator<N> {
pub fn new(shape : &[usize; N]) -> IndexIterator<N> {
IndexIterator{
shape : *shape,
cur : [0; N],
done : shape.iter().any(|&v| v == 0)
}
}
}
pub trait IndexIteratorExt<const N : usize> {
type R;
#[allow(dead_code)]
fn index_iterator(&self) -> Self::R;
}
impl<const N : usize> IndexIteratorExt<N> for [usize;N] {
type R = IndexIterator<N>;
fn index_iterator(&self) -> Self::R { IndexIterator::new(self) }
}
pub struct SparseIndexIterator<'a, const N : usize> {
stride : [usize; N],
sp : & 'a [usize],
i : usize
}
impl<'a, const N : usize> SparseIndexIterator<'a,N> {
pub fn new(shape : &[usize; N], sp : &'a [usize]) -> SparseIndexIterator<'a,N> {
let mut stride = [1usize; N];
_ = stride.iter_mut().zip(shape.iter()).rev().fold(1, |v,(st,&d)| { *st = v; v*d });
SparseIndexIterator{
stride,
sp,
i : 0
}
}
}
impl<'a, const N : usize> Iterator for SparseIndexIterator<'a,N> {
type Item = [usize; N];
fn next(& mut self) -> Option<Self::Item> {
if self.i < self.sp.len() {
let mut res = [0usize; N];
let v = unsafe{ *self.sp.get_unchecked(self.i) };
self.i += 1;
_ = res.iter_mut().zip(self.stride.iter()).fold(v,|v, (r,&s)| { *r = v / s; v % s });
Some(res)
}
else {
None
}
}
}
pub struct ChunksByIter<'a,'b1,'b2,T,I>
where
I:Iterator<Item = (&'b1 usize,&'b2 usize)>
{
data : &'a [T],
ptr : I
}
impl<'a,'b1,'b2,T,I> Iterator for ChunksByIter<'a,'b1,'b2,T,I>
where
I:Iterator<Item = (&'b1 usize,&'b2 usize)>
{
type Item = &'a[T];
fn next(& mut self) -> Option<Self::Item> {
if let Some((&p0,&p1)) = self.ptr.next() {
Some(unsafe{ self.data.get_unchecked(p0..p1)})
}
else {
None
}
}
}
pub trait ChunksByIterExt<T> {
fn chunks_ptr<'a,'b>(&'a self, ptr : &'b[usize]) -> ChunksByIter<'a,'b,'b,T,std::iter::Zip<std::slice::Iter<'b,usize>,std::slice::Iter<'b,usize>>>;
fn chunks_ptr2<'a,'b1,'b2>(&'a self, ptrb : &'b1[usize],ptre : &'b2[usize]) -> ChunksByIter<'a,'b1,'b2,T,std::iter::Zip<std::slice::Iter<'b1,usize>,std::slice::Iter<'b2,usize>>>;
}
impl<T> ChunksByIterExt<T> for [T] {
fn chunks_ptr<'a,'b>(& 'a self, ptr : &'b[usize]) -> ChunksByIter<'a,'b,'b,T,std::iter::Zip<std::slice::Iter<'b,usize>,std::slice::Iter<'b,usize>>> {
if let Some(&p) = ptr.last() { if p > self.len() { panic!("Invalid ptr for chunks_ptr iterator") } }
if ptr.iter().zip(ptr[1..].iter()).any(|(p0,p1)| p1 < p0) { panic!("Invalid ptr for chunks_ptr iterator") }
ChunksByIter{ data : self, ptr:ptr.iter().zip(ptr[1..].iter()) }
}
fn chunks_ptr2<'a,'b1,'b2>(& 'a self, ptrb : &'b1[usize], ptre : &'b2[usize]) -> ChunksByIter<'a,'b1,'b2,T,std::iter::Zip<std::slice::Iter<'b1,usize>,std::slice::Iter<'b2,usize>>> {
if let Some(&p) = ptre.last() { if p > self.len() { panic!("Invalid ptr for chunks_ptr iterator") } }
if ptrb.iter().zip(ptre.iter()).any(|(p0,p1)| p1 < p0) { panic!("Invalid ptrb/ptre for chunks_ptr iterator") }
ChunksByIter{ data : self, ptr:ptrb.iter().zip(ptre.iter()) }
}
}
pub struct ChunksByIterMut<'a,'b,'c,T:'a>
{
ptrb : & 'b [usize],
ptre : & 'c [usize],
ptr : NonNull<T>,
_marker : PhantomData<& 'a mut T>,
i : usize
}
impl<'a,'b,'c,T:'a> ChunksByIterMut<'a,'b,'c,T> {
fn new(data : &'a mut [T], ptrb : &'b[usize], ptre : &'c[usize]) -> Self {
let n = ptrb.len().min(ptre.len());
let ptrb = &ptrb[..n];
let ptre = &ptre[..n];
if let Some(&p) = ptrb.iter().max() { if p > data.len() { panic!("Ptrb element out of bounds for data: {} > {}",p,data.len()) } }
if let Some(&p) = ptre.iter().max() { if p > data.len() { panic!("Invalid ptre for chunks_ptr iterator") } }
if ptrb.iter().zip(ptre.iter()).any(|(&p0,&p1)| p0 > p1 ) {
panic!("Invalid ptrb/ptre construction");
}
ChunksByIterMut{
ptrb,
ptre,
ptr : NonNull::from(data).cast(),
_marker : PhantomData,
i : 0 }
}
}
impl<'a,'b,'c,T:'a> Iterator for ChunksByIterMut<'a,'b,'c,T> {
type Item = &'a mut [T];
fn next(& mut self) -> Option<Self::Item> {
if self.i < self.ptrb.len() && self.i < self.ptre.len() {
let (b,e) = unsafe {
(*self.ptrb.get_unchecked(self.i),
*self.ptre.get_unchecked(self.i))
};
self.i += 1;
unsafe {
Some(std::slice::from_raw_parts_mut(self.ptr.as_ptr().add(b).as_mut().unwrap(),e-b))
}
}
else {
None
}
}
}
pub trait ChunksByIterMutExt<T> {
fn chunks_ptr_mut<'a,'b,'c>(&'a mut self, ptrb : &'b[usize],ptre : &'c[usize]) -> ChunksByIterMut<'a,'b,'c,T> where T:'a;
}
impl<T> ChunksByIterMutExt<T> for [T] {
fn chunks_ptr_mut<'a,'b,'c>(& 'a mut self, ptrb : &'b[usize], ptre : & 'c[usize]) -> ChunksByIterMut<'a,'b,'c,T> where T:'a {
ChunksByIterMut::new(self,ptrb,ptre)
}
}
pub struct InnerJoinBy<I1,I2,F>
where
I1:Iterator,
I2:Iterator,
F:FnMut(&I1::Item,&I2::Item) -> std::cmp::Ordering
{
i1 : std::iter::Peekable<I1>,
i2 : std::iter::Peekable<I2>,
f : F
}
pub trait InnerJoinByExt<I2,F>
where
Self:Iterator+Sized,
I2:Iterator,
F:FnMut(&Self::Item,&I2::Item) -> std::cmp::Ordering
{
fn inner_join_by(self, f : F, other : I2) -> InnerJoinBy<Self,I2,F> {
InnerJoinBy{
i1 : self.peekable(),
i2 : other.peekable(),
f
}
}
}
impl<I1,I2,F> InnerJoinByExt<I2,F> for I1
where
I1:Iterator,
I2:Iterator,
F:FnMut(&I1::Item,&I2::Item) -> std::cmp::Ordering
{
}
impl<T1,T2,I1,I2,F> Iterator for InnerJoinBy<I1,I2,F>
where
T1:Copy,
T2:Copy,
I1:Iterator<Item=T1>,
I2:Iterator<Item=T2>,
F:FnMut(&I1::Item,&I2::Item) -> std::cmp::Ordering
{
type Item = (I1::Item,I2::Item);
fn next(&mut self) -> Option<Self::Item> {
while let (Some(a),Some(b)) = (self.i1.peek(),self.i2.peek()) {
match (self.f)(a,b) {
std::cmp::Ordering::Less => { _ = self.i1.next(); }
std::cmp::Ordering::Greater => { _ = self.i2.next(); }
std::cmp::Ordering::Equal => { break }
}
}
if let (Some(a),Some(b)) = (self.i1.next(),self.i2.next()) {
Some((a,b))
}
else {
None
}
}
}
pub struct OuterMergeBy<I1,I2,C>
where
I1 : Iterator,
I2 : Iterator,
C : FnMut(&I1::Item,&I2::Item) -> Ordering
{
i1 : Peekable<I1>,
i2 : Peekable<I2>,
c : C
}
pub trait OuterMergeByEx where Self : Iterator+Sized {
fn outer_merge_by<I2,C>(self, cmp : C, other : I2) -> OuterMergeBy<Self,I2,C>
where
I2 : Iterator,
C : FnMut(&Self::Item,&I2::Item) -> Ordering
{
OuterMergeBy{
i1 : self.peekable(),
i2 : other.peekable(),
c : cmp
}
}
}
impl<I1,I2,C> Iterator for OuterMergeBy<I1,I2,C>
where
I1 : Iterator,
I2 : Iterator,
C : FnMut(&I1::Item,&I2::Item) -> Ordering
{
type Item = (Option<I1::Item>,Option<I2::Item>);
fn next(&mut self) -> Option<Self::Item> {
match (self.i1.peek(),self.i2.peek()) {
(None,None) => None,
(Some(_),None) => { let r = self.i1.next(); Some((r,None)) },
(None,Some(_)) => { let r = self.i2.next(); Some((None,r)) },
(Some(a),Some(b)) => match (self.c)(a,b) {
Ordering::Less => { let r = self.i1.next(); Some((r,None)) },
Ordering::Greater => { let r = self.i2.next(); Some((None,r)) },
Ordering::Equal => {
let r1 = self.i1.next();
let r2 = self.i2.next();
Some((r1,r2))
}
}
}
}
}
pub struct Interleave<I1,I2>
where
I1 : Iterator,
I2 : Iterator<Item=I1::Item>
{
i1 : I1,
i2 : I2,
which : bool
}
pub trait InterleaveEx where Self : Iterator+Sized {
fn interleave<I2>(self, other : I2) -> Interleave<Self,I2> where I2 : Iterator<Item=Self::Item> {
Interleave{
i1 : self,
i2 : other,
which : false
}
}
}
impl<I1,I2> Iterator for Interleave<I1,I2> where I1:Iterator, I2:Iterator<Item=I1::Item> {
type Item = I1::Item;
fn next(&mut self) -> Option<Self::Item> {
if self.which {
self.which = ! self.which;
self.i2.next()
}
else {
self.which = ! self.which;
self.i1.next()
}
}
}
pub struct InterleaveN<'a,I> where I : Iterator {
ii : &'a mut [I],
which : usize
}
pub fn interleave<'a,I>(ii : &'a mut [I]) -> InterleaveN<'a,I> where I : Iterator {
InterleaveN{
ii,
which : 0
}
}
impl<'a, I> Iterator for InterleaveN<'a,I> where I : Iterator {
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
{
let i = self.which;
self.which = (self.which+1)%self.ii.len();
unsafe{self.ii.get_unchecked_mut(i)}.next()
}
}
}
pub struct ChunksByIter2<'a,'b,T>
{
data : &'a [T],
ptr : &'b [usize],
index : usize,
}
pub struct ChunksByIter3<'a,'b,T>
{
data : &'a[T],
len : &'b[usize],
index : usize,
}
impl<'a,'b,T> Iterator for ChunksByIter2<'a,'b,T>
{
type Item = &'a[T];
fn next(& mut self) -> Option<Self::Item> {
if self.index+1 < self.ptr.len() {
let i = self.index;
self.index += 1;
Some(unsafe{ self.data.get_unchecked(*self.ptr.get_unchecked(i)..*self.ptr.get_unchecked(i+1))})
}
else {
None
}
}
}
pub struct ChunkationIter<'a,'b,'c,T> {
c : &'c Chunkation<'a>,
data : &'b[T],
i : usize
}
impl<'a,'b,'c,T> Iterator for ChunkationIter<'a,'b,'c,T> {
type Item = &'b[T];
fn next(&mut self) -> Option<Self::Item> {
if self.i+1 < self.c.ptr.len() {
let i = self.i;
self.i += 1;
Some(unsafe{self.data.get_unchecked(*self.c.ptr.get_unchecked(i)..*self.c.ptr.get_unchecked(i+1))})
}
else {
None
}
}
}
pub struct Chunkation<'a> {
ptr : & 'a[usize],
max : usize
}
impl<'a> Chunkation<'a> {
pub fn new(ptr : &'a[usize]) -> Option<Self> {
if let Some(max) = ptr.last() {
if ptr.iter().zip(ptr[1..].iter()).any(|item| *item.0 > *item.1) { None }
else {
Some(Chunkation { ptr, max:*max })
}
}
else {
None
}
}
pub fn chunks<'b,'c,T>(&'a self, data : &'b [T]) -> Option<ChunkationIter<'a,'b,'c,T>> {
if self.max > data.len() { None }
else { Some(ChunkationIter{ c : self, data, i : 0 }) }
}
}
#[cfg(test)]
mod tests {
use super::*;
}