use gat_lending_iterator::LendingIterator;
use linnet::permutation::Permutation;
use std::fmt::Debug;
use crate::{
structure::{representation::LibraryRep, slot::IsAbstractSlot, TensorStructure},
tensors::data::{DenseTensor, GetTensorData, SparseTensor},
};
use super::{
core_iterators::CoreFlatFiberIterator,
fiber::{Fiber, FiberClass, FiberMut},
traits::ResetableIterator,
FiberIteratorItem, IteratesAlongFibers, IteratesAlongPermutedFibers,
};
#[derive(Debug)]
pub struct FiberIterator<
'a,
S: TensorStructure,
I: IteratesAlongFibers<<S::Slot as IsAbstractSlot>::R>,
> {
pub fiber: Fiber<'a, S>,
pub iter: I,
pub skipped: usize,
}
impl<S: TensorStructure, I: IteratesAlongFibers<<S::Slot as IsAbstractSlot>::R> + Clone> Clone
for FiberIterator<'_, S, I>
{
fn clone(&self) -> Self {
FiberIterator {
fiber: self.fiber.clone(),
iter: self.iter.clone(),
skipped: self.skipped,
}
}
}
impl<'a, S: TensorStructure, I: IteratesAlongFibers<<S::Slot as IsAbstractSlot>::R>>
FiberIterator<'a, S, I>
{
pub fn new(fiber: Fiber<'a, S>, conj: bool) -> Self {
FiberIterator {
iter: I::new(&fiber, conj),
fiber,
skipped: 0,
}
}
pub fn reset(&mut self) {
self.iter.reset();
self.skipped = 0;
}
pub fn shift(&mut self, shift: usize) {
self.reset();
self.iter.shift(shift);
}
}
impl<'a, S: TensorStructure, I: IteratesAlongPermutedFibers<<S::Slot as IsAbstractSlot>::R>>
FiberIterator<'a, S, I>
{
pub fn new_permuted(fiber: Fiber<'a, S>, permutation: Permutation, conj: bool) -> Self {
FiberIterator {
iter: I::new_permuted(&fiber, conj, permutation),
fiber,
skipped: 0,
}
}
}
impl<I: IteratesAlongFibers<LibraryRep>> Iterator
for FiberIterator<'_, crate::structure::OrderedStructure, I>
{
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
}
impl<
'a,
I: IteratesAlongFibers<<S::Slot as IsAbstractSlot>::R, Item = It>,
S: TensorStructure,
T,
It,
> Iterator for FiberIterator<'a, DenseTensor<T, S>, I>
where
It: FiberIteratorItem,
{
type Item = (&'a T, It::OtherData);
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|x| {
if let Some(t) = self.fiber.structure.get_ref_linear(x.flat_idx()) {
(t, x.other_data())
} else {
panic!(
"DenseTensor: Out of bounds {} {}",
x.flat_idx(),
self.fiber.structure.size().unwrap()
)
}
})
}
}
impl<
'a,
I: IteratesAlongFibers<<S::Slot as IsAbstractSlot>::R, Item = It>,
S: TensorStructure,
T,
It,
> Iterator for FiberIterator<'a, SparseTensor<T, S>, I>
where
It: FiberIteratorItem,
{
type Item = (&'a T, usize, It::OtherData);
fn next(&mut self) -> Option<Self::Item> {
if let Some(i) = self.iter.next() {
if let Some(t) = self.fiber.structure.get_ref_linear(i.flat_idx()) {
let skipped = self.skipped;
self.skipped = 0;
return Some((t, skipped, i.other_data()));
} else {
self.skipped += 1;
return self.next();
}
}
None
}
}
pub struct MutFiberIterator<
'a,
S: TensorStructure,
I: IteratesAlongFibers<<S::Slot as IsAbstractSlot>::R>,
> {
iter: I,
fiber: FiberMut<'a, S>,
skipped: usize,
}
impl<
I: IteratesAlongFibers<<S::Slot as IsAbstractSlot>::R, Item = It>,
S: TensorStructure,
T,
It,
> LendingIterator for MutFiberIterator<'_, SparseTensor<T, S>, I>
where
It: FiberIteratorItem,
{
type Item<'r>
= (&'r mut T, usize, It::OtherData)
where
Self: 'r;
fn next(&mut self) -> Option<Self::Item<'_>> {
let flat = self.iter.next()?;
if self.fiber.structure.is_empty_at_flat(flat.flat_idx()) {
let skipped = self.skipped;
self.skipped = 0;
Some((
self.fiber
.structure
.get_mut_linear(flat.flat_idx())
.unwrap(),
skipped,
flat.other_data(),
))
} else {
self.skipped += 1;
self.next()
}
}
}
impl<
I: IteratesAlongFibers<<S::Slot as IsAbstractSlot>::R, Item = It>,
S: TensorStructure,
T,
It,
> LendingIterator for MutFiberIterator<'_, DenseTensor<T, S>, I>
where
It: FiberIteratorItem,
{
type Item<'r>
= (&'r mut T, It::OtherData)
where
Self: 'r;
fn next(&mut self) -> Option<Self::Item<'_>> {
self.iter.next().map(|x| {
(
self.fiber.structure.get_mut_linear(x.flat_idx()).unwrap(),
x.other_data(),
)
})
}
}
impl<'a, S: TensorStructure, I: IteratesAlongFibers<<S::Slot as IsAbstractSlot>::R>>
MutFiberIterator<'a, S, I>
{
pub fn new(fiber: FiberMut<'a, S>, conj: bool) -> Self {
MutFiberIterator {
iter: I::new(&fiber, conj),
fiber,
skipped: 0,
}
}
pub fn reset(&mut self) {
self.iter.reset();
self.skipped = 0;
}
pub fn shift(&mut self, shift: usize) {
self.iter.shift(shift);
}
}
impl<'a, S: TensorStructure, I: IteratesAlongPermutedFibers<<S::Slot as IsAbstractSlot>::R>>
MutFiberIterator<'a, S, I>
{
pub fn new_permuted(fiber: FiberMut<'a, S>, permutation: Permutation, conj: bool) -> Self {
MutFiberIterator {
iter: I::new_permuted(&fiber, conj, permutation),
fiber,
skipped: 0,
}
}
}
pub struct FiberClassIterator<
'b,
S: TensorStructure,
I: IteratesAlongFibers<<S::Slot as IsAbstractSlot>::R> = CoreFlatFiberIterator,
> {
pub fiber_iter: FiberIterator<'b, S, I>,
pub class_iter: CoreFlatFiberIterator,
}
impl<'b, N: TensorStructure> FiberClassIterator<'b, N, CoreFlatFiberIterator> {
pub fn new(class: FiberClass<'b, N>) -> Self {
let (iter, iter_conj) = CoreFlatFiberIterator::new_paired_conjugates(&class);
let fiber = FiberIterator {
fiber: class.into(),
iter,
skipped: 0,
};
FiberClassIterator {
fiber_iter: fiber,
class_iter: iter_conj,
}
}
}
impl<N: TensorStructure, I: IteratesAlongFibers<<N::Slot as IsAbstractSlot>::R>>
FiberClassIterator<'_, N, I>
{
pub fn reset(&mut self) {
self.class_iter.reset();
self.fiber_iter.reset();
self.fiber_iter.shift(0);
}
}
impl<'b, N: TensorStructure, I: IteratesAlongPermutedFibers<<N::Slot as IsAbstractSlot>::R>>
FiberClassIterator<'b, N, I>
{
pub fn new_permuted(class: FiberClass<'b, N>, permutation: Permutation) -> Self {
let iter = CoreFlatFiberIterator::new(&class, false);
let fiber = FiberIterator::new_permuted(class.into(), permutation, false);
FiberClassIterator {
fiber_iter: fiber,
class_iter: iter,
}
}
}
impl<
'a,
S: TensorStructure + 'a,
I: IteratesAlongFibers<<S::Slot as IsAbstractSlot>::R> + Clone + Debug,
> Iterator for FiberClassIterator<'a, S, I>
{
type Item = FiberIterator<'a, S, I>;
fn next(&mut self) -> Option<Self::Item> {
let shift = self.class_iter.next()?;
self.fiber_iter.reset();
self.fiber_iter.shift(shift.into());
Some(self.fiber_iter.clone())
}
}
impl<'a, S: TensorStructure + 'a, I: IteratesAlongFibers<<S::Slot as IsAbstractSlot>::R>>
LendingIterator for FiberClassIterator<'a, S, I>
{
type Item<'r>
= &'r mut FiberIterator<'a, S, I>
where
Self: 'r;
fn next(&mut self) -> Option<Self::Item<'_>> {
let shift = self.class_iter.next()?;
self.fiber_iter.reset();
self.fiber_iter.shift(shift.into());
Some(&mut self.fiber_iter)
}
}
#[cfg(test)]
mod tests {
use crate::structure::{
representation::{Euclidean, RepName},
OrderedStructure, PermutedStructure,
};
use super::*;
#[test]
fn weaved_iterator() {
let strct: DenseTensor<u32, OrderedStructure<Euclidean>> = DenseTensor::zero(
PermutedStructure::from_iter([
Euclidean {}.new_slot(4, 1),
Euclidean {}.new_slot(4, 2),
Euclidean {}.new_slot(4, 3),
Euclidean {}.new_slot(4, 4),
])
.structure,
);
let fiber_spec = [true, false, true, false];
let self_fiber_class = Fiber::from(fiber_spec.as_slice(), &strct.structure); let (self_fiber_class_iter, mut _other_fiber_class_iter) =
CoreFlatFiberIterator::new_paired_conjugates(&self_fiber_class);
for i in self_fiber_class_iter {
println!("{}-> {:?}", i, strct.expanded_index(i))
}
}
}