use crate::algorithm::matrix::{self as algorithm, DimensionMismatch};
use crate::scalar::Scalar;
use crate::storage::Storage;
use crate::vector::StaticVector;
#[derive(Debug, PartialEq)]
pub struct StaticMatrix<T, const R: usize, const C: usize> {
data: [[T; C]; R],
}
impl<T, const R: usize, const C: usize> Storage for StaticMatrix<T, R, C> {
type Item = T;
fn len(&self) -> usize {
R * C
}
fn get(&self, index: usize) -> Option<&T> {
self.data.as_flattened().get(index)
}
}
impl<T: Scalar, const R: usize, const C: usize> StaticMatrix<T, R, C> {
pub fn new(data: [[T; C]; R]) -> Self {
Self { data }
}
pub fn add(&self, other: &Self) -> Self {
let mut data = [[T::zero(); C]; R];
match algorithm::add(self, R, C, other, R, C, data.as_flattened_mut()) {
Ok(()) | Err(DimensionMismatch) => {}
}
Self::new(data)
}
pub fn sub(&self, other: &Self) -> Self {
let mut data = [[T::zero(); C]; R];
match algorithm::sub(self, R, C, other, R, C, data.as_flattened_mut()) {
Ok(()) | Err(DimensionMismatch) => {}
}
Self::new(data)
}
pub fn mul_scalar(&self, factor: T) -> Self {
let mut data = [[T::zero(); C]; R];
match algorithm::mul_scalar(self, R, C, factor, data.as_flattened_mut()) {
Ok(()) | Err(DimensionMismatch) => {}
}
Self::new(data)
}
pub fn mul_vector(&self, v: &StaticVector<T, C>) -> StaticVector<T, R> {
let mut out = [T::zero(); R];
match algorithm::mul_vector(self, R, C, v, &mut out) {
Ok(()) | Err(DimensionMismatch) => {}
}
StaticVector::new(out)
}
pub fn mul_matrix<const C2: usize>(
&self,
other: &StaticMatrix<T, C, C2>,
) -> StaticMatrix<T, R, C2> {
let mut data = [[T::zero(); C2]; R];
match algorithm::mul_matrix(self, R, C, other, C, C2, data.as_flattened_mut()) {
Ok(()) | Err(DimensionMismatch) => {}
}
StaticMatrix::new(data)
}
pub fn transpose(&self) -> StaticMatrix<T, C, R> {
let mut data = [[T::zero(); R]; C];
match algorithm::transpose(self, R, C, data.as_flattened_mut()) {
Ok(()) | Err(DimensionMismatch) => {}
}
StaticMatrix::new(data)
}
}
#[cfg(test)]
mod tests {
use super::StaticMatrix;
use crate::vector::StaticVector;
#[test]
fn constructs_from_rows() {
let m = StaticMatrix::new([[1.0, 2.0], [3.0, 4.0]]);
assert_eq!(m, StaticMatrix::new([[1.0, 2.0], [3.0, 4.0]]));
}
#[test]
fn add_is_wired_to_the_algorithm_layer() {
let a = StaticMatrix::new([[1.0, 2.0], [3.0, 4.0]]);
let b = StaticMatrix::new([[5.0, 6.0], [7.0, 8.0]]);
assert_eq!(a.add(&b), StaticMatrix::new([[6.0, 8.0], [10.0, 12.0]]));
}
#[test]
fn sub_is_wired_to_the_algorithm_layer() {
let a = StaticMatrix::new([[5.0, 6.0], [7.0, 8.0]]);
let b = StaticMatrix::new([[1.0, 2.0], [3.0, 4.0]]);
assert_eq!(a.sub(&b), StaticMatrix::new([[4.0, 4.0], [4.0, 4.0]]));
}
#[test]
fn mul_scalar_is_wired_to_the_algorithm_layer() {
let m = StaticMatrix::new([[1.0, 2.0], [3.0, 4.0]]);
assert_eq!(
m.mul_scalar(2.0),
StaticMatrix::new([[2.0, 4.0], [6.0, 8.0]])
);
}
#[test]
fn mul_vector_is_wired_to_the_algorithm_layer() {
let m = StaticMatrix::new([[1.0, 2.0], [3.0, 4.0]]);
let v = StaticVector::new([1.0, 1.0]);
assert_eq!(m.mul_vector(&v), StaticVector::new([3.0, 7.0]));
}
#[test]
fn mul_matrix_is_wired_to_the_algorithm_layer() {
let a = StaticMatrix::new([[1.0, 2.0], [3.0, 4.0]]);
let b = StaticMatrix::new([[5.0, 6.0], [7.0, 8.0]]);
assert_eq!(
a.mul_matrix(&b),
StaticMatrix::new([[19.0, 22.0], [43.0, 50.0]])
);
}
#[test]
fn transpose_is_wired_to_the_algorithm_layer() {
let m = StaticMatrix::new([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]);
assert_eq!(
m.transpose(),
StaticMatrix::new([[1.0, 4.0], [2.0, 5.0], [3.0, 6.0]])
);
}
}