lib_tsalign/alignment_matrix/index/iterators/
mod.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
use super::AlignmentMatrixIndex;

pub struct AlignmentMatrixReferenceIterator {
    index: AlignmentMatrixIndex,
    limit: usize,
}

pub struct AlignmentMatrixQueryIterator {
    index: AlignmentMatrixIndex,
    limit: usize,
}

/// An iterator over the alignment matrix indices skipping row and column zero.
///
/// The iterator is query-major, i.e. it increments the reference position every iteration, and increments the query position only after reaching the limit of the reference.
pub struct AlignmentMatrixInnerIterator {
    index: AlignmentMatrixIndex,
    limit: AlignmentMatrixIndex,
}

impl AlignmentMatrixReferenceIterator {
    pub(in crate::alignment_matrix) fn new(query_index: usize, limit: usize) -> Self {
        Self {
            index: AlignmentMatrixIndex::new(0, query_index),
            limit,
        }
    }
}

impl AlignmentMatrixQueryIterator {
    pub(in crate::alignment_matrix) fn new(reference_index: usize, limit: usize) -> Self {
        Self {
            index: AlignmentMatrixIndex::new(reference_index, 0),
            limit,
        }
    }
}

impl AlignmentMatrixInnerIterator {
    pub(in crate::alignment_matrix) fn new(limit: AlignmentMatrixIndex) -> Self {
        debug_assert!(limit.reference_index > 0);
        debug_assert!(limit.query_index > 0);

        Self {
            index: if limit.reference_index > 1 && limit.query_index > 1 {
                AlignmentMatrixIndex::new(1, 1)
            } else {
                limit
            },
            limit,
        }
    }
}

impl Iterator for AlignmentMatrixReferenceIterator {
    type Item = AlignmentMatrixIndex;

    fn next(&mut self) -> Option<Self::Item> {
        if self.index.reference_index < self.limit {
            let result = self.index;
            self.index.reference_index += 1;
            Some(result)
        } else {
            None
        }
    }
}

impl Iterator for AlignmentMatrixQueryIterator {
    type Item = AlignmentMatrixIndex;

    fn next(&mut self) -> Option<Self::Item> {
        if self.index.query_index < self.limit {
            let result = self.index;
            self.index.query_index += 1;
            Some(result)
        } else {
            None
        }
    }
}

impl Iterator for AlignmentMatrixInnerIterator {
    type Item = AlignmentMatrixIndex;

    fn next(&mut self) -> Option<Self::Item> {
        if self.index.reference_index < self.limit.reference_index {
            let result = self.index;
            self.index.reference_index += 1;
            Some(result)
        } else if self.index.query_index < self.limit.query_index - 1 {
            self.index.reference_index = 1;
            self.index.query_index += 1;
            let result = self.index;
            self.index.reference_index += 1;
            Some(result)
        } else {
            None
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::alignment_matrix::index::{
        iterators::AlignmentMatrixInnerIterator, AlignmentMatrixIndex,
    };

    #[test]
    fn alignment_matrix_inner_iterator() {
        assert_eq!(
            AlignmentMatrixInnerIterator::new(AlignmentMatrixIndex::new(3, 3)).collect::<Vec<_>>(),
            vec![
                AlignmentMatrixIndex::new(1, 1),
                AlignmentMatrixIndex::new(2, 1),
                AlignmentMatrixIndex::new(1, 2),
                AlignmentMatrixIndex::new(2, 2)
            ],
        );
        assert_eq!(
            AlignmentMatrixInnerIterator::new(AlignmentMatrixIndex::new(1, 3)).collect::<Vec<_>>(),
            vec![],
        );
        assert_eq!(
            AlignmentMatrixInnerIterator::new(AlignmentMatrixIndex::new(3, 1)).collect::<Vec<_>>(),
            vec![],
        );
        assert_eq!(
            AlignmentMatrixInnerIterator::new(AlignmentMatrixIndex::new(1, 1)).collect::<Vec<_>>(),
            vec![],
        );
    }

    #[test]
    #[should_panic]
    fn alignment_matrix_inner_iterator_zero() {
        AlignmentMatrixInnerIterator::new(AlignmentMatrixIndex::new(0, 0));
    }
}