sparse_bin_mat/matrix/
non_trivial_elements.rs

1use super::SparseBinMat;
2
3/// An iterator over the coordinates of non trivial elements.
4///
5/// See the [`non_trivial_elements`](SparseBinMat::non_trivial_elements) method.
6#[derive(Debug, Clone)]
7pub struct NonTrivialElements<'a> {
8    matrix: &'a SparseBinMat,
9    row_index: usize,
10    column_index: usize,
11}
12
13impl<'a> NonTrivialElements<'a> {
14    pub(super) fn new(matrix: &'a SparseBinMat) -> Self {
15        Self {
16            matrix,
17            row_index: 0,
18            column_index: 0,
19        }
20    }
21
22    fn next_element(&mut self) -> Option<(usize, usize)> {
23        self.matrix
24            .row(self.row_index)
25            .and_then(|row| row.as_slice().get(self.column_index).cloned())
26            .map(|column| (self.row_index, column))
27    }
28
29    fn move_to_next_row(&mut self) {
30        self.row_index += 1;
31        self.column_index = 0;
32    }
33
34    fn move_to_next_column(&mut self) {
35        self.column_index += 1;
36    }
37
38    fn is_done(&self) -> bool {
39        self.row_index >= self.matrix.number_of_rows()
40    }
41}
42
43impl<'a> Iterator for NonTrivialElements<'a> {
44    type Item = (usize, usize);
45
46    fn next(&mut self) -> Option<Self::Item> {
47        if self.is_done() {
48            None
49        } else {
50            match self.next_element() {
51                Some(element) => {
52                    self.move_to_next_column();
53                    Some(element)
54                }
55                None => {
56                    self.move_to_next_row();
57                    self.next()
58                }
59            }
60        }
61    }
62}
63
64#[cfg(test)]
65mod test {
66    use super::*;
67
68    #[test]
69    fn non_trivial_elements_of_small_matrix() {
70        let matrix = SparseBinMat::new(3, vec![vec![1], vec![0, 2], vec![0, 1, 2]]);
71        let mut iter = NonTrivialElements::new(&matrix);
72
73        assert_eq!(iter.next(), Some((0, 1)));
74        assert_eq!(iter.next(), Some((1, 0)));
75        assert_eq!(iter.next(), Some((1, 2)));
76        assert_eq!(iter.next(), Some((2, 0)));
77        assert_eq!(iter.next(), Some((2, 1)));
78        assert_eq!(iter.next(), Some((2, 2)));
79        assert_eq!(iter.next(), None);
80    }
81}