use crate::{Index, IndexMut, Matrix, Order, whilst};
impl<T, const R: usize, const C: usize, const LEN: usize> Matrix<T, R, C, LEN> {
pub const ROWS: usize = R;
pub const COLUMNS: usize = C;
pub const ELEMENTS: usize = LEN;
pub const fn new(data: [T; LEN]) -> Self {
Self::assert_valid_shape();
Self { data }
}
#[must_use]
pub const fn row_count(&self) -> usize {
R
}
#[must_use]
pub const fn column_count(&self) -> usize {
C
}
#[must_use]
pub const fn len(&self) -> usize {
LEN
}
#[must_use]
pub const fn is_empty(&self) -> bool {
LEN == 0
}
#[must_use]
pub const fn is_square(&self) -> bool {
R == C
}
#[must_use]
pub const fn get_index(row: usize, column: usize) -> Option<usize> {
Order::row_major_try_from_2d(column, row, C, R)
}
#[must_use]
pub const fn get(&self, row: usize, column: usize) -> Option<&T> {
match Self::get_index(row, column) {
Some(index) => Some(&self.data[index]),
None => None,
}
}
pub const fn get_mut(&mut self, row: usize, column: usize) -> Option<&mut T> {
match Self::get_index(row, column) {
Some(index) => Some(&mut self.data[index]),
None => None,
}
}
#[must_use]
pub const fn at_ref(&self, row: usize, column: usize) -> &T {
match self.get(row, column) {
Some(value) => value,
None => panic!("matrix index out of bounds"),
}
}
#[must_use]
pub const fn at_mut(&mut self, row: usize, column: usize) -> &mut T {
match self.get_mut(row, column) {
Some(value) => value,
None => panic!("matrix index out of bounds"),
}
}
const fn assert_valid_shape() {
match R.checked_mul(C) {
Some(expected_len) => assert!(LEN == expected_len, "matrix LEN must equal R * C"),
None => panic!("matrix dimensions overflow usize"),
}
}
}
impl<T: Copy, const R: usize, const C: usize, const LEN: usize> Matrix<T, R, C, LEN> {
#[must_use]
pub const fn at(&self, row: usize, column: usize) -> T {
*self.at_ref(row, column)
}
pub const fn splat(value: T) -> Self {
Self::new([value; LEN])
}
pub const fn transpose(&self) -> Matrix<T, C, R, LEN> {
let mut data = self.data;
whilst! { row in 0..R; {
whilst! { col in 0..C; {
let source = row * C + col;
let dest = col * R + row;
data[dest] = self.data[source];
}}
}}
Matrix::<T, C, R, LEN>::new(data)
}
}
impl<T, const R: usize, const C: usize, const LEN: usize> Index<(usize, usize)>
for Matrix<T, R, C, LEN>
{
type Output = T;
fn index(&self, index: (usize, usize)) -> &Self::Output {
self.at_ref(index.0, index.1)
}
}
impl<T, const R: usize, const C: usize, const LEN: usize> IndexMut<(usize, usize)>
for Matrix<T, R, C, LEN>
{
fn index_mut(&mut self, index: (usize, usize)) -> &mut Self::Output {
self.at_mut(index.0, index.1)
}
}