matrixable/
iterators.rs

1//! This module contains structs for iterating over matrices.
2//!
3//! Some of these structs also implement [`Index`](::core::ops::Index) allowing you to use the `container[index]` notation.
4//!
5//! # Examples
6//! ```rust
7//! use matrixable::MatrixExt;
8//!
9//! let m = [
10//!     ['a', 'b', 'c'],
11//!     ['d', 'e', 'f'],
12//!     ['g', 'h', 'i']
13//! ];
14//!
15//! {
16//!     let row = m.row(0).unwrap();
17//!     assert_eq!('a', row[0]);
18//!     assert_eq!('b', row[1]);
19//!     assert_eq!('c', row[2]);
20//! }
21//! 
22//! {
23//!     let col = m.col(1).unwrap();
24//!     assert_eq!('b', col[0]);
25//!     assert_eq!('e', col[1]);
26//!     assert_eq!('h', col[2]);
27//! }
28//! 
29//! {
30//!     let diag = m.diag(2).unwrap();
31//!     assert_eq!('a', diag[0]);
32//!     assert_eq!('e', diag[1]);
33//!     assert_eq!('i', diag[2]); 
34//! }
35//! 
36//! let m = [['r', 'i', 'o']];
37//! let it = m.iter();
38//! 
39//! assert_eq!('r', it[0]);
40//! assert_eq!('i', it[1]);
41//! assert_eq!('o', it[2]); 
42//! ```
43//! <br/>
44//!
45//! It may happen you just need a unique element. In that case you will rather use [`.nth()`](::core::iter::Iterator::nth) 
46//! from the standard [`Iterator`] trait.
47//!
48//! ```rust
49//! use matrixable::MatrixMutExt;
50//!
51//! let mut m = [
52//!     ['a', 'b', 'c'],
53//!     ['d', 'e', 'f'],
54//!     ['g', 'h', 'i']
55//! ];
56//! 
57//! let h = m.row_mut(2).unwrap().nth(1).unwrap();
58//! // Or 
59//! //    = m.rows_mut().nth(2).unwrap().nth(1).unwrap();
60//! 
61//! assert_eq!(&mut 'h', h);
62//! 
63//! *h = 'z';
64//! 
65//! assert_eq!(Some(&mut 'z'), m.row_mut(2).unwrap().nth(1));
66//! ```
67
68use ::core::{
69    fmt::Debug,
70    iter::{ FusedIterator, FromIterator },
71    marker::PhantomData,
72    
73};
74
75
76use alloc::vec::Vec;
77use alloc::vec::IntoIter;
78use alloc::boxed::Box;
79
80use crate::{MatrixExt, MatrixMutExt};
81
82macro_rules! iter {
83    (
84        $(#[doc = $doc:expr] $name:ident { $($mut:ident)? } { $ptr:ident } $matrixTrait:ident $getfn:ident $($start:ident)?),* ;
85        $get_bounds:expr ;
86        $incrfn:item ;
87        $lenimpl:item ;
88        $nextbackimpl:item 
89    ) => {
90        $(
91            #[doc = $doc]
92            /// See its documentation for more.
93            #[derive(Hash, Debug, Copy, Clone)]
94            pub struct $name<'a, M: $matrixTrait + 'a> 
95            {
96                m: *$ptr M,
97                i: usize,
98                irev: usize,
99                _marker: PhantomData<&'a M>,
100            }
101        
102            impl<'a, M: $matrixTrait> $name<'a, M>
103            where M::Element: 'a 
104            {
105                pub(crate) fn new(m: &'a $($mut)? M $(, $start: usize)? ) -> Self {
106                    let get_start = $get_bounds;
107                    let (i, irev) = get_start(m $(, $start)?);
108                    Self { m, i, irev, _marker: PhantomData }
109                }
110                
111                #[inline(always)]
112                fn use_matrix(&$($mut)? self) -> &'a $($mut)? M {
113                    unsafe { (&$($mut)? *self.m) }
114                }         
115                
116                #[inline(always)]
117                fn matrix(&self) -> &'a M {
118                    unsafe { (&*self.m) }
119                } 
120                
121                #[inline(always)]
122                fn get_nth(&$($mut)? self, i: usize) -> Option<&'a $($mut)? M::Element> {
123                    self.use_matrix().$getfn(i)
124                }
125                
126                #[inline(always)]
127                $incrfn
128                
129            }
130            
131            impl<'a, M: $matrixTrait> Iterator for $name<'a, M> 
132            where M::Element: 'a 
133            {
134                type Item = &'a $($mut)? M::Element;
135                    fn next(&mut self) -> Option<Self::Item> {
136                    if self.i > self.irev {
137                        return None
138                    }
139                    let i = self.i;    
140                    self.i = self.increment(i);
141
142                    // SAFETY: Nothing else points to or will point to the contents of this iterator.
143                    self.get_nth(i)
144                }
145            }
146            
147            impl<'a, M: $matrixTrait> FusedIterator for $name<'a, M> {}
148
149            impl<'a, M: $matrixTrait> ExactSizeIterator for $name<'a, M> {
150                $lenimpl
151            }
152
153            impl<'a, M: $matrixTrait> DoubleEndedIterator for $name<'a, M> {
154                $nextbackimpl
155            }
156            
157            impl<'a, 'b, M, M2> PartialEq<$name<'b, M2>> for $name<'a, M>
158            where
159                M: $matrixTrait,
160                M2: $matrixTrait,
161                M::Element: PartialEq<M2::Element>
162            {
163                fn eq(&self, other: & $name<'b, M2>) -> bool {
164                    let len = self.len();
165                    if len != other.len() { 
166                        return false
167                    }
168                    for i in 0..len {
169                        if self[i] != other[i] {
170                            return false
171                        } 
172                    }
173                    true
174                }
175            }
176            
177            impl<'a, M: $matrixTrait> Eq for $name<'a, M> 
178            where
179                M::Element: PartialEq
180            {}
181            
182            
183            /// Allows creating 2D arrays from this iterator.
184            impl<'a, M: $matrixTrait, T, F> FromIterator<$name<'a, M>> for Box<[F]>
185            where
186                F: ::core::ops::Deref<Target = [T]>,
187                F: FromIterator<<$name<'a, M> as Iterator>::Item>,
188                M::Element: 'a
189            {
190                fn from_iter<IntoI>(iter: IntoI) -> Self
191                where
192                    IntoI: IntoIterator<Item = $name<'a, M>>
193                {
194                    iter.into_iter().map(|c| c.collect::<F>()).collect()
195                }
196            } 
197                        
198            impl<'a, M: $matrixTrait, T, F> FromIterator<$name<'a, M>> for Vec<F>
199            where
200                F: ::core::ops::Deref<Target = [T]>,
201                F: FromIterator<<$name<'a, M> as Iterator>::Item>,
202                M::Element: 'a
203            {
204                fn from_iter<IntoI>(iter: IntoI) -> Self
205                where
206                    IntoI: IntoIterator<Item = $name<'a, M>>
207                {
208                    iter.into_iter().map(|c| c.collect::<F>()).collect()
209                }
210            }
211           
212            impl<'a, M: $matrixTrait> ::core::ops::Index<usize> for $name<'a, M>
213            where 
214                M::Element: 'a
215            {
216                type Output = M::Element;
217                
218                /// # Panics
219                /// Panics if the index is out of bounds.
220                fn index(&self, idx: usize) -> &Self::Output {
221                    let mut i = self.i;
222                    for _ in 0..idx {
223                        i = self.increment(i);
224                    }
225                    self.matrix().get_nth(i).unwrap()
226                }
227            }
228            
229            $(
230                impl<'a, M: $matrixTrait> ::core::ops::IndexMut<usize> for $name<'a, M>
231                where 
232                    M::Element: 'a
233                {
234                    /// # Panics
235                    /// Panics if the index is out of bounds.
236                    fn index_mut(&$mut self, idx: usize) -> &mut Self::Output {
237                        let mut i = self.i;
238                        for _ in 0..idx {
239                            i = self.increment(i);
240                        }
241                        self.get_nth(i).unwrap()
242                    }
243                }
244            )?
245            
246            unsafe impl<'a, M: $matrixTrait> Send for $name<'a, M>
247            where M: Send, M::Element: Send {}
248            
249            unsafe impl<'a, M: $matrixTrait> Sync for $name<'a, M>
250            where M: Sync, M::Element: Sync {}
251        )*
252    }
253}
254
255iter!{
256    #[doc =
257    "An iterator over the elements of the matrix.\n\n\
258    This struct is created by the [`iter`](MatrixExt::iter) method on [`MatrixExt`]."]
259    Iter {/*no mut */} { const } MatrixExt get_nth,
260    #[doc = 
261    "An iterator over the elements of the matrix (mutable).\n\n\
262    This struct is created by the [`iter_mut`](MatrixMutExt::iter_mut) method on [`MatrixMutExt`]."]
263    IterMut { mut } { mut } MatrixMutExt get_nth_mut;
264    |m: &M| (0, m.size().saturating_sub(1)) ;
265    fn increment(&self, i: usize) -> usize {
266        i + 1
267    } ;
268    fn len(&self) -> usize { self.matrix().size()  } ;
269    fn next_back(&mut self) -> Option<Self::Item> {
270        if self.i > self.irev {
271            return None
272        }
273        let j = self.irev;
274        self.irev -= 1;
275        
276        // SAFETY: Nothing else points to or will point to the contents of this iterator.
277        self.get_nth(j)
278    }
279}
280
281iter!{
282    #[doc = 
283    "An iterator over a matrix row.\n\n\
284    This struct is created by the [`row`](MatrixExt::row) method on [`MatrixExt`]."]
285    Row {/*no mut */} { const } MatrixExt get_nth irow,
286    #[doc = 
287    "An iterator over a mutable matrix row.\n\n\
288    This struct is created by the [`row_mut`](MatrixMutExt::row_mut) method on [`MatrixMutExt`]."]
289    RowMut { mut } { mut } MatrixMutExt get_nth_mut irow;
290    |m: &M, row| {
291        let rlen = m.row_len();
292        let i = row * rlen;
293        (i, i + rlen - 1)
294    } ;
295    fn increment(&self, i: usize) -> usize {  
296        i + 1
297    } ;
298    fn len(&self) -> usize {  self.matrix().row_len()  } ;
299    fn next_back(&mut self) -> Option<Self::Item> {
300        if self.i > self.irev {
301            return None
302        }
303        let j = self.irev;
304        self.irev -= 1;
305        
306        // SAFETY: Nothing else points to or will point to the contents of this iterator.
307        self.get_nth(j)
308    }
309}
310
311macro_rules! dimensional_iterator {
312    (   $w:ident,
313        $ptr:ident,
314        { $($mut:ident)? },
315        $matrixTrait:ident,
316        $outElem:ty,
317        $callfn:ident,
318        $lenfn:ident
319    ) => {
320
321        #[derive(Debug)]
322        pub struct $w<'a, M>
323        where M: $matrixTrait,
324        M::Element: 'a {
325            n: usize,
326            m:  *$ptr M,
327            _marker: PhantomData<&'a M>
328        }
329
330        impl<'a, M> Iterator for $w<'a, M>
331        where
332            M: $matrixTrait,
333            M::Element: 'a
334        {
335            type Item = $outElem;
336
337            fn next(&mut self) -> Option<Self::Item> {
338                let next = unsafe { (&$($mut)? *self.m).$callfn(self.n) };
339
340                self.n += 1;
341
342                // SAFETY: Nothing else points to or will point to the contents of this iterator.
343                next
344            }
345        }
346
347        impl<'a, M> DoubleEndedIterator for $w<'a, M>
348        where M: $matrixTrait,
349        {
350            fn next_back(&mut self) -> Option<Self::Item> {
351                let next = unsafe {
352                    let m = (&$($mut)? *self.m);
353                    let end = m.$lenfn();
354                    m.$callfn(end - self.n - 1)
355                };
356
357                self.n += 1;
358
359                // SAFETY: Nothing else points to or will point to the contents of this iterator.
360                next
361            }
362
363            fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
364                let next = unsafe {
365                    let m = (&$($mut)? *self.m);
366                    let end = m.$lenfn();
367                    m.$callfn(end - self.n + n - 1)
368                };
369
370                self.n += 1;
371
372                // SAFETY: Nothing else points to or will point to the contents of this iterator.
373                next
374            }
375        }
376
377        impl<'a, M> FusedIterator for $w<'a, M>
378        where M: $matrixTrait
379        {  }
380
381        impl<'a, M> ExactSizeIterator for $w<'a, M>
382        where M: $matrixTrait {
383            fn len(&self) -> usize {
384                let m = unsafe { &$($mut)? *self.m };
385                 m.$lenfn()
386            }
387        }
388
389        impl<'a, 'b, M> From<&'b $($mut)? M> for $w<'a, M>
390        where
391            'b: 'a,
392            M: $matrixTrait
393        {
394            fn from(source: &'b $($mut)? M) -> Self {
395                Self {
396                    n: 0,
397                    m: source,
398                    _marker: PhantomData
399                }
400            }
401        }
402
403        // impl<'a, M> $w<'a, M>
404        // where
405        //     M: $matrixTrait,
406        // {
407        //     pub fn equals<'b, M2>(self, other: $w<'b, M2>) -> bool
408        //     where
409        //         M2: $matrixTrait,
410        //         M::Element: PartialEq<M2::Element>
411        //     {
412        //         if self.len() != other.len() {
413        //             return false
414        //         }
415        //         while let Some(row) = self.next() {
416        //             if let Some(other_row) = other.next() {
417        //                 for _ in 0..row.len() {
418        //                     if row.next(). != other_row.next() {
419        //                         return false
420        //                     }
421        //                 }
422        //             }
423        //             else {
424        //                 return false
425        //             }
426        //         }
427        //
428        //         true
429        //     }
430        // }
431
432        unsafe impl<'a, M: $matrixTrait> Send for $w<'a, M>
433        where M: Send, M::Element: Send {}
434
435        unsafe impl<'a, M: $matrixTrait> Sync for $w<'a, M>
436        where M: Sync, M::Element: Sync {}
437    };
438}
439
440iter!{
441    #[doc =
442    "An iterator over a matrix column.\n\n\
443    This struct is created by the [`col`](MatrixExt::col) method on [`MatrixExt`]."]
444    Column {/*no mut */} { const } MatrixExt get_nth icol,
445    #[doc =
446    "An iterator over a mutable matrix column.\n\n\
447    This struct is created by the [`col_mut`](MatrixMutExt::col_mut) method on [`MatrixMutExt`]."]
448    ColumnMut { mut } { mut} MatrixMutExt get_nth_mut icol;
449    |m: &M, col| {
450        let (rows, cols) = m.shape();
451        (col, (rows * cols) - cols.saturating_sub(col))
452    } ;
453    fn increment(&self, i: usize) -> usize {
454        i + self.matrix().row_len()
455    } ;
456    fn len(&self) -> usize { self.matrix().col_len()  } ;
457    fn next_back(&mut self) -> Option<Self::Item> {
458        if self.i > self.irev {
459            return None
460        }
461        let j = self.irev;
462        self.irev -= self.use_matrix().row_len();
463
464        // SAFETY: Nothing else points to or will point to the contents of this iterator.
465        self.get_nth(j)
466    }
467}
468
469iter!{
470    #[doc =
471    "An iterator over a matrix diagonal.\n\n\
472    This struct is created by the [`diag`](MatrixExt::diag) method on [`MatrixExt`]."]
473    Diag {/*no mut */} { const } MatrixExt get_nth n,
474    #[doc =
475    "An iterator over a mutable matrix diagonal.\n\n\
476    This struct is created by the [`diag_mut`](MatrixMutExt::diag_mut) method on [`MatrixMutExt`]."]
477    DiagMut { mut } { mut } MatrixMutExt get_nth_mut n;
478    |m: &M, mut n| {
479        let (rows, cols) = match m.shape() {
480            (_, 0) | (0, _) => return (0, 1),
481            (rows, cols) => (rows, cols)
482        } ;
483        let diag_len = m.diag_len(n);
484        let main_diag = rows - 1;
485        if n < main_diag {
486            n = main_diag - n;
487            (
488                n * cols,
489                n + cols * (diag_len + 1),
490            )
491        } else {
492            n = n - main_diag;
493            (
494                n,
495                n + cols * (diag_len + 1),
496            )
497        }
498    } ;
499    fn increment(&self, i: usize) -> usize {
500        let m = self.matrix();
501        let (mut i, mut j) = m.subscripts_from(i);
502        i += 1;
503        j += 1;
504
505        if m.check(i, j) {
506            m.index_from((i, j))
507        }
508        else {
509            // Stop a further call to `next` method by passing value that ends iteration
510            //(iteration goes until self.i > self.irev).
511            self.irev + 1
512        }
513    };
514    fn len(&self) -> usize {  self.matrix().diag_len(self.i) };
515    fn next_back(&mut self) -> Option<Self::Item> {
516        if self.i > self.irev {
517            return None
518        }
519        let j = self.irev;
520        self.irev -= self.use_matrix().row_len() + 1;
521
522        // SAFETY: Nothing else points to or will point to the contents of this iterator.
523        self.get_nth(j)
524    }
525}
526
527
528dimensional_iterator!{ 
529    Rows, const, { /* no mut */}, MatrixExt,
530    Row<'a, M>,
531    row, num_rows 
532}
533
534dimensional_iterator!{ 
535    RowsMut, mut, { mut }, MatrixMutExt,
536    RowMut<'a, M>,
537    row_mut, num_rows 
538}
539
540dimensional_iterator!{ 
541    Columns, const, {/* no mut */}, MatrixExt,
542    Column<'a, M>,
543    col, num_cols
544}
545
546dimensional_iterator!{ 
547    ColumnsMut, mut, { mut }, MatrixMutExt,
548    ColumnMut<'a, M>,
549    col_mut, num_cols 
550}
551
552dimensional_iterator!{ 
553    Diags, const, { /* no mut */ }, MatrixExt,
554    Diag<'a, M>,
555    diag, num_diags 
556}
557
558dimensional_iterator!{ 
559    DiagsMut, mut, { mut }, MatrixMutExt,
560    DiagMut<'a, M>,
561    diag_mut, num_diags 
562}
563
564
565/// An iterator that yields an element of the a matrix-like `struct` along
566/// with the subscripts of that element.
567pub struct Enumerator<I> {
568    iter: I,
569    jmp: usize,
570    i: usize,
571    j: usize,
572}
573impl<I> Enumerator<I> {
574    pub(crate) fn new(iter: I, jmp: usize) -> Self {
575        Self {
576            iter,
577            jmp,
578            i: 0,
579            j: 0,
580        }
581    }
582}
583impl<I> Iterator for Enumerator<I>
584where
585    I: Iterator,
586{
587    type Item = (usize, usize, <I as Iterator>::Item);
588    fn next(&mut self) -> Option<Self::Item> {
589        let next = (self.i, self.j, self.iter.next()?);
590
591        self.j += 1;
592
593        if self.j == self.jmp {
594            self.j = 0;
595            self.i += 1;
596        }
597        
598        Some(next)
599    }
600}
601impl<I> ExactSizeIterator for Enumerator<I>
602where
603    I: ExactSizeIterator
604{
605    fn len(&self) -> usize {  self.iter.len()  }
606}
607impl<I: FusedIterator> FusedIterator for Enumerator<I> {}
608
609
610#[derive(Default, Clone, Debug)]
611pub struct IntoAxes<T> {
612    axes: IntoIter<Vec<T>>,
613}
614impl<T> IntoAxes<T>
615{
616    pub fn from_as_rows<M: MatrixExt + IntoIterator>(src: M) -> Self
617    where <M as IntoIterator>::Item: IntoIterator<Item = T>
618    {
619        let mut v = Vec::with_capacity(src.num_rows());
620        for row in src {
621            v.push(row.into_iter().collect());
622        }
623
624        Self { axes: v.into_iter() }
625    }
626
627    pub fn from_as_cols<M: MatrixExt + IntoIterator>(src: M) -> Self
628    where <M as IntoIterator>::Item: IntoIterator<Item = T>
629    {
630        let (num_rows, num_cols) = src.shape();
631        let mut v = Vec::with_capacity(num_cols);
632        for _ in 0..num_cols {
633            v.push(Vec::with_capacity(num_rows));
634        }
635        for row in src {
636            for (i, elem) in row.into_iter().enumerate() {
637                v[i].push(elem)
638            }
639        }
640        Self { axes: v.into_iter() }
641    }
642
643    pub fn from_as_diags<M: MatrixExt + IntoIterator>(src: M) -> Self
644        where <M as IntoIterator>::Item: IntoIterator<Item = T>
645    {
646        if src.is_empty () {
647            return Self {
648                axes: Vec::new().into_iter()
649            }
650        }
651
652        //let (num_rows, num_cols) = (value.num_rows(), value.num_cols());
653        let num_diags = src.num_diags();
654        let i_main_diag = src.num_rows() - 1;
655
656        let mut v = Vec::with_capacity(num_diags);
657        for i in 0..num_diags {
658            v.push(Vec::with_capacity(src.diag_len(i)));
659        }
660
661        //let (mut i, mut j) = (rows - 1, 0);
662        let mut into_iter = src.into_iter();
663
664        let first_row = into_iter.next().expect("Not empty so first row must exist");
665
666        // upper diagonals start
667        for (i, elem) in first_row.into_iter().enumerate() {
668            v[i_main_diag + i].push(elem);
669        }
670
671        // now continue iteration till the bottom
672        for (i, row) in into_iter.enumerate() {
673            let mut row = row.into_iter();
674
675            // a new lower diagonal at each row
676            // first element of that diag is first element of row
677            v[i_main_diag - i - 1].push(row.next().expect("If new row then must contain at least one element"));
678
679            for (j, elem) in row.enumerate() {
680                v[i_main_diag + j].push(elem);
681            }
682        }
683        Self { axes: v.into_iter() }
684    }
685}
686
687impl<T> Iterator for IntoAxes<T> {
688    type Item = Vec<T>;
689    fn next(&mut self) -> Option<Self::Item> {
690        self.axes.next()
691    }
692}
693
694impl<T> DoubleEndedIterator for IntoAxes<T> {
695    fn next_back(&mut self) -> Option<Self::Item> {
696        self.axes.next_back()
697    }
698}
699
700impl<T> ExactSizeIterator for IntoAxes<T> {
701    fn len(&self) -> usize { self.axes.len() }
702}
703
704impl<T> FusedIterator for IntoAxes<T> {}