ferrix/
matrix_transpose_view.rs

1use crate::matrix::Matrix;
2use crate::matrix_transpose_view_mut::MatrixTransposeViewMut;
3use crate::matrix_view::MatrixView;
4use crate::matrix_view_mut::MatrixViewMut;
5use std::fmt;
6use std::ops::Index;
7
8/// A static transposed view of matrix.
9#[derive(Debug)]
10pub struct MatrixTransposeView<
11    'a,
12    T,
13    const R: usize,
14    const C: usize,
15    const VR: usize,
16    const VC: usize,
17> {
18    data: &'a Matrix<T, R, C>,
19    start: (usize, usize), // In terms of the transposed matrix
20}
21
22impl<'a, T, const R: usize, const C: usize, const VR: usize, const VC: usize>
23    MatrixTransposeView<'a, T, R, C, VR, VC>
24{
25    pub(super) fn new(data: &'a Matrix<T, R, C>, start: (usize, usize)) -> Self {
26        if start.0 + VR > C || start.1 + VC > R {
27            panic!("View size out of bounds");
28        }
29        Self { data, start }
30    }
31}
32
33impl<'a, T, const R: usize, const C: usize, const VR: usize, const VC: usize>
34    MatrixTransposeView<'a, T, R, C, VR, VC>
35{
36    /// Returns the shape of the [`MatrixTransposeView`].
37    ///
38    /// The shape is always equal to `(VR, VC)`.
39    ///
40    /// # Examples
41    ///
42    /// ```
43    /// use ferrix::Matrix;
44    ///
45    /// let mat = Matrix::from([[1, 2, 3], [4, 5, 6]]);
46    /// let transposed = mat.t();
47    /// assert_eq!(transposed.shape(), (3, 2));
48    /// ```
49    #[inline]
50    pub fn shape(&self) -> (usize, usize) {
51        (VR, VC)
52    }
53
54    /// Returns the total number of elements in the [`MatrixTransposeView`].
55    ///
56    /// The total number of elements is always equal to `VR * VC`.
57    ///
58    /// # Examples
59    ///
60    /// ```
61    /// use ferrix::Matrix;
62    ///
63    /// let mat = Matrix::from([[1, 2, 3], [4, 5, 6]]);
64    /// let transposed = mat.t();
65    /// assert_eq!(transposed.capacity(), 6);
66    /// ```
67    #[inline]
68    pub fn capacity(&self) -> usize {
69        VR * VC
70    }
71
72    /// Returns the number of rows in the [`MatrixTransposeView`].
73    ///
74    /// The number of rows is always equal to `VR`.
75    ///
76    /// # Examples
77    ///
78    /// ```
79    /// use ferrix::Matrix;
80    ///
81    /// let mat = Matrix::from([[1, 2, 3], [4, 5, 6]]);
82    /// let transposed = mat.t();
83    /// assert_eq!(transposed.rows(), 3);
84    /// ```
85    #[inline]
86    pub fn rows(&self) -> usize {
87        VR
88    }
89
90    /// Returns the number of columns in the [`MatrixTransposeView`].
91    ///
92    /// The number of columns is always equal to `VC`.
93    ///
94    /// # Examples
95    ///
96    /// ```
97    /// use ferrix::Matrix;
98    ///
99    /// let mat = Matrix::from([[1, 2, 3], [4, 5, 6]]);
100    /// let transposed = mat.t();
101    /// assert_eq!(transposed.cols(), 2);
102    /// ```
103    #[inline]
104    pub fn cols(&self) -> usize {
105        VC
106    }
107
108    /// Returns a transposed view of the [`MatrixTransposeView`].
109    ///
110    /// This method returns a [`MatrixView`], which is a read-only view of the [`MatrixTransposeView`] transposed.
111    ///
112    /// # Examples
113    ///
114    /// ```
115    /// use ferrix::Matrix;
116    ///
117    /// let mat = Matrix::from([[1, 2, 3], [4, 5, 6], [7, 8, 9]]);
118    /// let transposed = mat.t();
119    /// let original = transposed.t();
120    /// assert_eq!(original, mat);
121    /// ```
122    pub fn t(&self) -> MatrixView<T, R, C, VC, VR> {
123        MatrixView::new(self.data, (self.start.1, self.start.0))
124    }
125}
126
127//////////////////////////////////////
128//  Equality Trait Implementations  //
129//////////////////////////////////////
130
131// MatrixTransposeView == Matrix
132impl<'a, T: PartialEq, const R: usize, const C: usize, const VR: usize, const VC: usize>
133    PartialEq<Matrix<T, VR, VC>> for MatrixTransposeView<'a, T, R, C, VR, VC>
134{
135    fn eq(&self, other: &Matrix<T, VR, VC>) -> bool {
136        (0..VR).all(|i| (0..VC).all(|j| self[(i, j)] == other[(i, j)]))
137    }
138}
139
140// MatrixTransposeView == MatrixView
141impl<
142        'a,
143        T: PartialEq,
144        const A: usize,
145        const B: usize,
146        const R: usize,
147        const C: usize,
148        const VR: usize,
149        const VC: usize,
150    > PartialEq<MatrixView<'a, T, A, B, VR, VC>> for MatrixTransposeView<'a, T, R, C, VR, VC>
151{
152    fn eq(&self, other: &MatrixView<'a, T, A, B, VR, VC>) -> bool {
153        (0..VR).all(|i| (0..VC).all(|j| self[(i, j)] == other[(i, j)]))
154    }
155}
156
157// MatrixTransposeView == MatrixViewMut
158impl<
159        'a,
160        T: PartialEq,
161        const A: usize,
162        const B: usize,
163        const R: usize,
164        const C: usize,
165        const VR: usize,
166        const VC: usize,
167    > PartialEq<MatrixViewMut<'a, T, A, B, VR, VC>> for MatrixTransposeView<'a, T, R, C, VR, VC>
168{
169    fn eq(&self, other: &MatrixViewMut<'a, T, A, B, VR, VC>) -> bool {
170        (0..VR).all(|i| (0..VC).all(|j| self[(i, j)] == other[(i, j)]))
171    }
172}
173
174// MatrixTransposeView == MatrixTransposeView
175impl<
176        'a,
177        T: PartialEq,
178        const A: usize,
179        const B: usize,
180        const R: usize,
181        const C: usize,
182        const VR: usize,
183        const VC: usize,
184    > PartialEq<MatrixTransposeView<'a, T, A, B, VR, VC>>
185    for MatrixTransposeView<'a, T, R, C, VR, VC>
186{
187    fn eq(&self, other: &MatrixTransposeView<'a, T, A, B, VR, VC>) -> bool {
188        (0..VR).all(|i| (0..VC).all(|j| self[(i, j)] == other[(i, j)]))
189    }
190}
191
192// MatrixTransposeView == MatrixTransposeViewMut
193impl<
194        'a,
195        T: PartialEq,
196        const A: usize,
197        const B: usize,
198        const R: usize,
199        const C: usize,
200        const VR: usize,
201        const VC: usize,
202    > PartialEq<MatrixTransposeViewMut<'a, T, A, B, VR, VC>>
203    for MatrixTransposeView<'a, T, R, C, VR, VC>
204{
205    fn eq(&self, other: &MatrixTransposeViewMut<'a, T, A, B, VR, VC>) -> bool {
206        (0..VR).all(|i| (0..VC).all(|j| self[(i, j)] == other[(i, j)]))
207    }
208}
209
210impl<'a, T: Eq, const R: usize, const C: usize, const VR: usize, const VC: usize> Eq
211    for MatrixTransposeView<'a, T, R, C, VR, VC>
212{
213}
214
215/////////////////////////////////////
216//  Display Trait Implementations  //
217/////////////////////////////////////
218
219impl<T: fmt::Display, const R: usize, const C: usize, const VR: usize, const VC: usize> fmt::Display
220    for MatrixTransposeView<'_, T, R, C, VR, VC>
221{
222    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
223        if f.alternate() {
224            write!(f, "MatrixTransposeView(")?;
225        }
226
227        write!(f, "[")?;
228        for i in 0..VR {
229            if i > 0 {
230                write!(f, " ")?;
231                if f.alternate() {
232                    write!(f, "                    ")?;
233                }
234            }
235            write!(f, "[")?;
236            for j in 0..VC {
237                write!(f, "{}", self[(i, j)])?;
238                if j < VC - 1 {
239                    write!(f, ", ")?;
240                }
241            }
242            write!(f, "]")?;
243            if i < VR - 1 {
244                writeln!(f)?;
245            }
246        }
247        write!(f, "]")?;
248
249        if f.alternate() {
250            write!(f, ", dtype={})", std::any::type_name::<T>())?;
251        }
252
253        Ok(())
254    }
255}
256
257///////////////////////////////////
258//  Index Trait Implementations  //
259///////////////////////////////////
260
261impl<'a, T, const R: usize, const C: usize, const VR: usize, const VC: usize>
262    MatrixTransposeView<'a, T, R, C, VR, VC>
263{
264    #[inline]
265    fn flip(&self, index: (usize, usize)) -> (usize, usize) {
266        (index.1, index.0)
267    }
268
269    #[inline]
270    fn offset(&self, index: (usize, usize)) -> (usize, usize) {
271        (index.0 + self.start.0, index.1 + self.start.1)
272    }
273
274    #[inline]
275    fn validate_index(&self, index: (usize, usize)) -> bool {
276        index.0 < VR && index.1 < VC
277    }
278}
279
280impl<T, const R: usize, const C: usize, const VR: usize, const VC: usize> Index<usize>
281    for MatrixTransposeView<'_, T, R, C, VR, VC>
282{
283    type Output = T;
284    fn index(&self, index: usize) -> &Self::Output {
285        if index >= R * C {
286            panic!("Index out of bounds");
287        }
288
289        let row_idx = index / VC;
290        let col_idx = index % VC;
291        &self.data[self.flip(self.offset((row_idx, col_idx)))]
292    }
293}
294
295impl<T, const R: usize, const C: usize, const VR: usize, const VC: usize> Index<(usize, usize)>
296    for MatrixTransposeView<'_, T, R, C, VR, VC>
297{
298    type Output = T;
299    fn index(&self, index: (usize, usize)) -> &Self::Output {
300        if !self.validate_index(index) {
301            panic!("Index out of bounds");
302        }
303        &self.data[self.flip(self.offset(index))]
304    }
305}