orx_v/matrices/matrix.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 140 141 142 143 144
use crate::{Dim, Equality, IdxLeqD1, IdxLeqD2, IntoIdx, D2};
/// A matrix or a matrix view over a `D2` vector with rectangular cardinality,
/// or over a flattened representation by a `D1` vector.
///
/// An owned matrix can be created by:
/// * calling [`into_matrix`] method on a `D2`
/// vector implementing `NVec<D2, _>`, or equivalently, `V2<_>`; or by:
/// * calling [`v1_into_matrix`] method on a `D1`
/// vector implementing `NVec<D1, _>`, or equivalently, `V1<_>`.
///
/// Alternatively, matrix views can be created by:
/// * calling [`as_matrix`] or [`as_matrix_col_major`] methods on a `D2`
/// vector; or by:
/// * calling [`as_matrix`] or [`as_matrix_col_major`] methods on a `D1`
/// vector.
///
/// [`into_matrix`]: crate::V2AsMatrix::into_matrix
/// [`as_matrix`]: crate::V2AsMatrix::as_matrix
/// [`as_matrix_col_major`]: crate::V2AsMatrix::as_matrix_col_major
/// [`v1_into_matrix`]: crate::V1AsMatrix::v1_into_matrix
/// [`as_matrix`]: crate::V1AsMatrix::as_matrix
/// [`as_matrix_col_major`]: crate::V1AsMatrix::as_matrix_col_major
///
/// All above mentioned methods have their `_mut` versions to create a
/// mutable matrix view.
pub trait Matrix<T> {
/// Number of rows.
fn num_rows(&self) -> usize;
/// Number of columns.
fn num_cols(&self) -> usize;
/// Returns the element at the given `idx` of the matrix.
///
/// # Panics
///
/// Panics if the `idx` is not `in_bounds`.
fn at(&self, idx: impl IntoIdx<D2>) -> T;
/// Returns an iterator of all elements of the matrix.
/// The direction of iteration depends on whether the matrix is row-major
/// or column-major.
///
/// Row-major matrices are created by:
/// * calling [`as_matrix`] on a `D2` vector, or
/// * calling [`as_matrix`] on a `D1` vector.
///
/// Column-major matrices are created by:
/// * calling [`as_matrix_col_major`] on a `D2` vector, or
/// * calling [`as_matrix_col_major`] on a `D1` vector.
///
/// [`as_matrix`]: crate::V2AsMatrix::as_matrix
/// [`as_matrix_col_major`]: crate::V2AsMatrix::as_matrix_col_major
/// [`as_matrix`]: crate::V1AsMatrix::as_matrix
/// [`as_matrix_col_major`]: crate::V1AsMatrix::as_matrix_col_major
///
/// All above mentioned methods have their `_mut` versions to create a
/// mutable matrix view.
fn all(&self) -> impl Iterator<Item = T>;
// provided
/// Returns true if the given `idx` is in bounds of the matrix.
#[inline(always)]
fn in_bounds(&self, idx: impl Into<<D2 as Dim>::LeqIdx>) -> bool {
match idx.into() {
IdxLeqD2::IdxD0([]) => true,
IdxLeqD2::IdxD1([i]) => i < self.num_rows(),
IdxLeqD2::IdxD2([i, j]) => i < self.num_rows() && j < self.num_cols(),
}
}
/// Returns the element at the given `idx` if it is `in_bounds`;
/// returns None otherwise.
fn try_at(&self, idx: impl IntoIdx<D2>) -> Option<T> {
let [i, j] = idx.into_idx();
match i < self.num_rows() && j < self.num_cols() {
true => Some(self.at(idx)),
false => None,
}
}
/// Returns the equality result of comparing this matrix to the `other`.
fn equality(&self, other: &impl Matrix<T>) -> Equality<D2>
where
T: PartialEq,
{
if self.num_rows() != other.num_rows() {
Equality::UnequalCard(IdxLeqD1::IdxD0([]), self.num_rows(), other.num_rows())
} else if self.num_cols() != other.num_cols() {
Equality::UnequalCard(IdxLeqD1::IdxD1([0]), self.num_rows(), other.num_rows())
} else {
for i in 0..self.num_rows() {
for j in 0..self.num_cols() {
if self.at([i, j]) != other.at([i, j]) {
return Equality::UnequalValue([i, j]);
}
}
}
Equality::Equal
}
}
}
// &V auto impl
impl<T, M: Matrix<T>> Matrix<T> for &M {
fn num_rows(&self) -> usize {
<M as Matrix<T>>::num_rows(self)
}
fn num_cols(&self) -> usize {
<M as Matrix<T>>::num_cols(self)
}
fn at(&self, idx: impl IntoIdx<D2>) -> T {
<M as Matrix<T>>::at(self, idx)
}
fn all(&self) -> impl Iterator<Item = T> {
<M as Matrix<T>>::all(self)
}
}
// &mut V auto impl
impl<T, M: Matrix<T>> Matrix<T> for &mut M {
fn num_rows(&self) -> usize {
<M as Matrix<T>>::num_rows(self)
}
fn num_cols(&self) -> usize {
<M as Matrix<T>>::num_cols(self)
}
fn at(&self, idx: impl IntoIdx<D2>) -> T {
<M as Matrix<T>>::at(self, idx)
}
fn all(&self) -> impl Iterator<Item = T> {
<M as Matrix<T>>::all(self)
}
}