1use super::submatrix::*;
2
3use std::ops::Range;
4
5#[stability::unstable(feature = "enable")]
6pub struct TransposableSubmatrix<'a, V: AsPointerToSlice<T>, T, const TRANSPOSED: bool> {
7    data: Submatrix<'a, V, T>
8}
9
10impl<'a, V: AsPointerToSlice<T>, T> From<Submatrix<'a, V, T>> for TransposableSubmatrix<'a, V, T, false> {
11
12    fn from(value: Submatrix<'a, V, T>) -> Self {
13        Self { data: value }
14    }
15}
16
17impl<'a, V: AsPointerToSlice<T>, T> TransposableSubmatrix<'a, V, T, false> {
18
19    #[stability::unstable(feature = "enable")]
20    pub fn transpose(self) -> TransposableSubmatrix<'a, V, T, true> {
21        TransposableSubmatrix { data: self.data }
22    }
23}
24
25impl<'a, V: AsPointerToSlice<T>, T> TransposableSubmatrix<'a, V, T, true> {
26
27    #[stability::unstable(feature = "enable")]
28    pub fn transpose(self) -> TransposableSubmatrix<'a, V, T, false> {
29        TransposableSubmatrix { data: self.data }
30    }
31}
32
33impl<'a, V: AsPointerToSlice<T>, T, const TRANSPOSED: bool> Copy for TransposableSubmatrix<'a, V, T, TRANSPOSED> {}
34
35impl<'a, V: AsPointerToSlice<T>, T, const TRANSPOSED: bool> Clone for TransposableSubmatrix<'a, V, T, TRANSPOSED> {
36
37    fn clone(&self) -> Self {
38        *self
39    }
40}
41
42impl<'a, V: AsPointerToSlice<T>, T, const TRANSPOSED: bool> TransposableSubmatrix<'a, V, T, TRANSPOSED> {
43    
44    #[stability::unstable(feature = "enable")]
45    pub fn into_base(self) -> Submatrix<'a, V, T> {
46        assert!(!TRANSPOSED);
47        self.data
48    }
49
50    #[stability::unstable(feature = "enable")]
51    pub fn into_base_transposed(self) -> Submatrix<'a, V, T> {
52        assert!(TRANSPOSED);
53        self.data
54    }
55
56    #[stability::unstable(feature = "enable")]
57    pub fn submatrix(self, rows: Range<usize>, cols: Range<usize>) -> Self {
58        if TRANSPOSED {
59            Self { data: self.data.submatrix(cols, rows) }
60        } else {
61            Self { data: self.data.submatrix(rows, cols) }
62        }
63    }
64
65    #[stability::unstable(feature = "enable")]
66    pub fn restrict_rows(self, rows: Range<usize>) -> Self {
67        if TRANSPOSED {
68            Self { data: self.data.restrict_cols(rows) }
69        } else {
70            Self { data: self.data.restrict_rows(rows) }
71        }
72    }
73
74    #[stability::unstable(feature = "enable")]
75    pub fn into_at(self, i: usize, j: usize) -> &'a T {
76        if TRANSPOSED {
77            self.data.into_at(j, i)
78        } else {
79            self.data.into_at(i, j)
80        }
81    }
82    
83    #[stability::unstable(feature = "enable")]
84    pub fn at<'b>(&'b self, i: usize, j: usize) -> &'b T {
85        if TRANSPOSED {
86            self.data.at(j, i)
87        } else {
88            self.data.at(i, j)
89        }
90    }
91
92    #[stability::unstable(feature = "enable")]
93    pub fn restrict_cols(self, cols: Range<usize>) -> Self {
94        if TRANSPOSED {
95            Self { data: self.data.restrict_rows(cols) }
96        } else {
97            Self { data: self.data.restrict_cols(cols) }
98        }
99    }
100
101    #[stability::unstable(feature = "enable")]
102    pub fn col_count(&self) -> usize {
103        if TRANSPOSED {
104            self.data.row_count()
105        } else {
106            self.data.col_count()
107        }
108    }
109
110    #[stability::unstable(feature = "enable")]
111    pub fn row_count(&self) -> usize {
112        if TRANSPOSED {
113            self.data.col_count()
114        } else {
115            self.data.row_count()
116        }
117    }
118}
119
120#[stability::unstable(feature = "enable")]
121pub struct TransposableSubmatrixMut<'a, V: AsPointerToSlice<T>, T, const TRANSPOSED: bool> {
122    data: SubmatrixMut<'a, V, T>
123}
124
125impl<'a, V: AsPointerToSlice<T>, T> TransposableSubmatrixMut<'a, V, T, false> {
126
127    #[stability::unstable(feature = "enable")]
128    pub fn transpose(self) -> TransposableSubmatrixMut<'a, V, T, true> {
129        TransposableSubmatrixMut { data: self.data }
130    }
131}
132
133impl<'a, V: AsPointerToSlice<T>, T> TransposableSubmatrixMut<'a, V, T, true> {
134
135    #[stability::unstable(feature = "enable")]
136    pub fn transpose(self) -> TransposableSubmatrixMut<'a, V, T, false> {
137        TransposableSubmatrixMut { data: self.data }
138    }
139}
140
141impl<'a, V: AsPointerToSlice<T>, T> From<SubmatrixMut<'a, V, T>> for TransposableSubmatrixMut<'a, V, T, false> {
142
143    fn from(value: SubmatrixMut<'a, V, T>) -> Self {
144        Self { data: value }
145    }
146}
147
148impl<'a, V: AsPointerToSlice<T>, T, const TRANSPOSED: bool> TransposableSubmatrixMut<'a, V, T, TRANSPOSED> {
149
150    #[stability::unstable(feature = "enable")]
151    pub fn into_base(self) -> SubmatrixMut<'a, V, T> {
152        assert!(!TRANSPOSED);
153        self.data
154    }
155
156    #[stability::unstable(feature = "enable")]
157    pub fn into_base_transposed(self) -> SubmatrixMut<'a, V, T> {
158        assert!(TRANSPOSED);
159        self.data
160    }
161
162    #[stability::unstable(feature = "enable")]
163    pub fn submatrix(self, rows: Range<usize>, cols: Range<usize>) -> Self {
164        if TRANSPOSED {
165            Self { data: self.data.submatrix(cols, rows) }
166        } else {
167            Self { data: self.data.submatrix(rows, cols) }
168        }
169    }
170
171    #[stability::unstable(feature = "enable")]
172    pub fn restrict_rows(self, rows: Range<usize>) -> Self {
173        if TRANSPOSED {
174            Self { data: self.data.restrict_cols(rows) }
175        } else {
176            Self { data: self.data.restrict_rows(rows) }
177        }
178    }
179
180    #[stability::unstable(feature = "enable")]
181    pub fn at<'b>(&'b self, i: usize, j: usize) -> &'b T {
182        if TRANSPOSED {
183            self.data.at(j, i)
184        } else {
185            self.data.at(i, j)
186        }
187    }
188
189    #[stability::unstable(feature = "enable")]
190    pub fn restrict_cols(self, cols: Range<usize>) -> Self {
191        if TRANSPOSED {
192            Self { data: self.data.restrict_rows(cols) }
193        } else {
194            Self { data: self.data.restrict_cols(cols) }
195        }
196    }
197
198    #[stability::unstable(feature = "enable")]
199    pub fn col_count(&self) -> usize {
200        if TRANSPOSED {
201            self.data.row_count()
202        } else {
203            self.data.col_count()
204        }
205    }
206
207    #[stability::unstable(feature = "enable")]
208    pub fn row_count(&self) -> usize {
209        if TRANSPOSED {
210            self.data.col_count()
211        } else {
212            self.data.row_count()
213        }
214    }
215
216    #[stability::unstable(feature = "enable")]
217    pub fn split_rows(self, fst_rows: Range<usize>, snd_rows: Range<usize>) -> (Self, Self) {
218        if TRANSPOSED {
219            let (fst, snd) = self.data.split_cols(fst_rows, snd_rows);
220            return (Self { data: fst }, Self { data: snd });
221        } else {
222            let (fst, snd) = self.data.split_rows(fst_rows, snd_rows);
223            return (Self { data: fst }, Self { data: snd });
224        }
225    }
226
227    #[stability::unstable(feature = "enable")]
228    pub fn split_cols(self, fst_cols: Range<usize>, snd_cols: Range<usize>) -> (Self, Self) {
229        if TRANSPOSED {
230            let (fst, snd) = self.data.split_rows(fst_cols, snd_cols);
231            return (Self { data: fst }, Self { data: snd });
232        } else {
233            let (fst, snd) = self.data.split_cols(fst_cols, snd_cols);
234            return (Self { data: fst }, Self { data: snd });
235        }
236    }
237
238    #[stability::unstable(feature = "enable")]
239    pub fn at_mut<'b>(&'b mut self, i: usize, j: usize) -> &'b mut T {
240        if TRANSPOSED {
241            self.data.at_mut(j, i)
242        } else {
243            self.data.at_mut(i, j)
244        }
245    }
246
247    #[stability::unstable(feature = "enable")]
248    pub fn into_at_mut(self, i: usize, j: usize) -> &'a mut T {
249        if TRANSPOSED {
250            self.data.into_at_mut(j, i)
251        } else {
252            self.data.into_at_mut(i, j)
253        }
254    }
255
256    #[stability::unstable(feature = "enable")]
257    pub fn reborrow<'b>(&'b mut self) -> TransposableSubmatrixMut<'b, V, T, TRANSPOSED> {
258        TransposableSubmatrixMut { data: self.data.reborrow() }
259    }
260
261    #[stability::unstable(feature = "enable")]
262    pub fn as_const<'b>(&'b self) -> TransposableSubmatrix<'b, V, T, TRANSPOSED> {
263        TransposableSubmatrix { data: self.data.as_const() }
264    }
265}