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}