orx_v/matrices/
matrix.rs

1use crate::{Dim, Equality, IdxLeqD1, IdxLeqD2, IntoIdx, D2};
2
3/// A matrix or a matrix view over a `D2` vector with rectangular cardinality,
4/// or over a flattened representation by a `D1` vector.
5///
6/// An owned matrix can be created by:
7/// * calling [`into_matrix`] method on a `D2`
8///   vector implementing `NVec<D2, _>`, or equivalently, `V2<_>`; or by:
9/// * calling [`v1_into_matrix`] method on a `D1`
10///   vector implementing `NVec<D1, _>`, or equivalently, `V1<_>`.
11///
12/// Alternatively, matrix views can be created by:
13/// * calling [`as_matrix`] or [`as_matrix_col_major`] methods on a `D2`
14///   vector; or by:
15/// * calling [`as_matrix`] or [`as_matrix_col_major`] methods on a `D1`
16///   vector.
17///
18/// [`into_matrix`]: crate::V2AsMatrix::into_matrix
19/// [`as_matrix`]: crate::V2AsMatrix::as_matrix
20/// [`as_matrix_col_major`]: crate::V2AsMatrix::as_matrix_col_major
21/// [`v1_into_matrix`]: crate::V1AsMatrix::v1_into_matrix
22/// [`as_matrix`]: crate::V1AsMatrix::as_matrix
23/// [`as_matrix_col_major`]: crate::V1AsMatrix::as_matrix_col_major
24///
25/// All above mentioned methods have their `_mut` versions to create a
26/// mutable matrix view.
27pub trait Matrix<T> {
28    /// Number of rows.
29    fn num_rows(&self) -> usize;
30
31    /// Number of columns.
32    fn num_cols(&self) -> usize;
33
34    /// Returns the element at the given `idx` of the matrix.
35    ///
36    /// # Panics
37    ///
38    /// Panics if the `idx` is not `in_bounds`.
39    fn at(&self, idx: impl IntoIdx<D2>) -> T;
40
41    /// Returns an iterator of all elements of the matrix.
42    /// The direction of iteration depends on whether the matrix is row-major
43    /// or column-major.
44    ///
45    /// Row-major matrices are created by:
46    /// * calling [`as_matrix`] on a `D2` vector, or
47    /// * calling [`as_matrix`] on a `D1` vector.
48    ///
49    /// Column-major matrices are created by:
50    /// * calling [`as_matrix_col_major`] on a `D2` vector, or
51    /// * calling [`as_matrix_col_major`] on a `D1` vector.
52    ///
53    /// [`as_matrix`]: crate::V2AsMatrix::as_matrix
54    /// [`as_matrix_col_major`]: crate::V2AsMatrix::as_matrix_col_major
55    /// [`as_matrix`]: crate::V1AsMatrix::as_matrix
56    /// [`as_matrix_col_major`]: crate::V1AsMatrix::as_matrix_col_major
57    ///
58    /// All above mentioned methods have their `_mut` versions to create a
59    /// mutable matrix view.
60    fn all(&self) -> impl Iterator<Item = T>;
61
62    // provided
63
64    /// Returns true if the given `idx` is in bounds of the matrix.
65    #[inline(always)]
66    fn in_bounds(&self, idx: impl Into<<D2 as Dim>::LeqIdx>) -> bool {
67        match idx.into() {
68            IdxLeqD2::IdxD0([]) => true,
69            IdxLeqD2::IdxD1([i]) => i < self.num_rows(),
70            IdxLeqD2::IdxD2([i, j]) => i < self.num_rows() && j < self.num_cols(),
71        }
72    }
73
74    /// Returns the element at the given `idx` if it is `in_bounds`;
75    /// returns None otherwise.
76    fn try_at(&self, idx: impl IntoIdx<D2>) -> Option<T> {
77        let [i, j] = idx.into_idx();
78        match i < self.num_rows() && j < self.num_cols() {
79            true => Some(self.at(idx)),
80            false => None,
81        }
82    }
83
84    /// Returns the equality result of comparing this matrix to the `other`.
85    fn equality(&self, other: &impl Matrix<T>) -> Equality<D2>
86    where
87        T: PartialEq,
88    {
89        if self.num_rows() != other.num_rows() {
90            Equality::UnequalCard(IdxLeqD1::IdxD0([]), self.num_rows(), other.num_rows())
91        } else if self.num_cols() != other.num_cols() {
92            Equality::UnequalCard(IdxLeqD1::IdxD1([0]), self.num_rows(), other.num_rows())
93        } else {
94            for i in 0..self.num_rows() {
95                for j in 0..self.num_cols() {
96                    if self.at([i, j]) != other.at([i, j]) {
97                        return Equality::UnequalValue([i, j]);
98                    }
99                }
100            }
101            Equality::Equal
102        }
103    }
104}
105
106// &V auto impl
107
108impl<T, M: Matrix<T>> Matrix<T> for &M {
109    fn num_rows(&self) -> usize {
110        <M as Matrix<T>>::num_rows(self)
111    }
112
113    fn num_cols(&self) -> usize {
114        <M as Matrix<T>>::num_cols(self)
115    }
116
117    fn at(&self, idx: impl IntoIdx<D2>) -> T {
118        <M as Matrix<T>>::at(self, idx)
119    }
120
121    fn all(&self) -> impl Iterator<Item = T> {
122        <M as Matrix<T>>::all(self)
123    }
124}
125
126// &mut V auto impl
127
128impl<T, M: Matrix<T>> Matrix<T> for &mut M {
129    fn num_rows(&self) -> usize {
130        <M as Matrix<T>>::num_rows(self)
131    }
132
133    fn num_cols(&self) -> usize {
134        <M as Matrix<T>>::num_cols(self)
135    }
136
137    fn at(&self, idx: impl IntoIdx<D2>) -> T {
138        <M as Matrix<T>>::at(self, idx)
139    }
140
141    fn all(&self) -> impl Iterator<Item = T> {
142        <M as Matrix<T>>::all(self)
143    }
144}