use mymatrix::Matrix;
use pyinrs::Fraction;
use rstest::{fixture, rstest};
struct Fixture {
mat_0x0: Matrix,
mat_1x1: Matrix,
mat_3x3: Matrix,
}
#[fixture]
fn setup() -> Fixture {
Fixture {
mat_0x0: Matrix::new(),
mat_1x1: Matrix::from([[2]]),
mat_3x3: Matrix::from([[1, 2, 3], [4, 5, 6], [7, 8, 9]]),
}
}
#[rstest]
fn basics(setup: Fixture) {
assert_eq!(setup.mat_0x0.row_size(), 0);
assert_eq!(setup.mat_0x0.col_size(), 0);
assert!(setup.mat_0x0.is_empty());
assert_eq!(setup.mat_1x1.row_size(), 1);
assert_eq!(setup.mat_1x1.col_size(), 1);
assert!(!setup.mat_1x1.is_empty());
assert_eq!(setup.mat_3x3.row_size(), 3);
assert_eq!(setup.mat_3x3.col_size(), 3);
assert!(!setup.mat_3x3.is_empty());
assert_eq!(Matrix::from([[1, 2, 3]]).row_size(), 1);
assert_eq!(Matrix::from([[1, 2, 3]]).col_size(), 3);
assert!(!Matrix::from([[1, 2, 3]]).is_empty());
}
#[rstest]
fn compare(setup: Fixture) {
assert!(setup.mat_3x3 == Matrix::from([[1, 2, 3], [4, 5, 6], [7, 8, 9]]));
assert!(setup.mat_3x3 != Matrix::from([[1, 2, 3], [4, 5, 6], [7, 8, 0]]));
}
#[rstest]
fn access(mut setup: Fixture) {
for r in 0..setup.mat_3x3.row_size() {
for c in 0..setup.mat_3x3.col_size() {
assert_eq!(setup.mat_3x3[r][c], ((r * 3 + c + 1) as i32).into());
}
}
setup.mat_3x3[0][0] = 0.into();
assert_eq!(setup.mat_3x3[0][0], 0.into());
}
#[rstest]
fn is_symmetric(setup: Fixture) {
assert!(setup.mat_0x0.is_symmetric());
assert!(setup.mat_1x1.is_symmetric());
assert!(!setup.mat_3x3.is_symmetric());
assert!(Matrix::identity(3).is_symmetric());
}
#[rstest]
fn is_upper(setup: Fixture) {
assert!(setup.mat_0x0.is_upper());
assert!(setup.mat_1x1.is_upper());
assert!(!setup.mat_3x3.is_upper());
assert!(Matrix::identity(3).is_upper());
}
#[rstest]
fn is_lower(setup: Fixture) {
assert!(setup.mat_0x0.is_lower());
assert!(setup.mat_1x1.is_lower());
assert!(!setup.mat_3x3.is_lower());
assert!(Matrix::identity(3).is_lower());
}
#[rstest]
fn is_diagonal(setup: Fixture) {
assert!(setup.mat_0x0.is_diagonal());
assert!(setup.mat_1x1.is_diagonal());
assert!(!setup.mat_3x3.is_diagonal());
assert!(Matrix::identity(3).is_diagonal());
}
#[rstest]
fn trace(setup: Fixture) {
assert_eq!(setup.mat_0x0.trace(), 0.into());
assert_eq!(setup.mat_1x1.trace(), 2.into());
assert_eq!(setup.mat_3x3.trace(), 15.into());
assert_eq!(Matrix::identity(3).trace(), 3.into());
}
#[rstest]
fn transpose(setup: Fixture) {
assert_eq!(setup.mat_0x0.transpose(), setup.mat_0x0);
assert_eq!(setup.mat_1x1.transpose(), setup.mat_1x1);
assert_eq!(setup.mat_3x3.transpose().transpose(), setup.mat_3x3);
assert_eq!(Matrix::zeros(2, 3).transpose(), Matrix::zeros(3, 2));
}
#[rstest]
fn row_echelon_form(setup: Fixture) {
assert_eq!(setup.mat_0x0.row_echelon_form(), Matrix::new());
assert_eq!(setup.mat_1x1.row_echelon_form(), Matrix::from([[2]]));
assert_eq!(setup.mat_3x3.row_echelon_form(), Matrix::from([[1, 2, 3], [0, -3, -6], [0, 0, 0]]));
assert_eq!(Matrix::ones(2, 2).row_echelon_form(), Matrix::from([[1, 1], [0, 0]]));
assert_eq!(Matrix::from([[1, 2, 3], [4, 5, 6]]).row_echelon_form(), Matrix::from([[1, 2, 3], [0, -3, -6]]));
assert_eq!(Matrix::from([[1, 2], [3, 4], [5, 6]]).row_echelon_form(), Matrix::from([[1, 2], [0, -2], [0, 0]]));
}
#[rstest]
fn row_canonical_form(setup: Fixture) {
assert_eq!(setup.mat_0x0.row_canonical_form(), Matrix::new());
assert_eq!(setup.mat_1x1.row_canonical_form(), Matrix::from([[1]]));
assert_eq!(setup.mat_3x3.row_canonical_form(), Matrix::from([[1, 0, -1], [0, 1, 2], [0, 0, 0]]));
assert_eq!(Matrix::ones(2, 2).row_canonical_form(), Matrix::from([[1, 1], [0, 0]]));
assert_eq!(Matrix::from([[1, 2, 3], [4, 5, 6]]).row_canonical_form(), Matrix::from([[1, 0, -1], [0, 1, 2]]));
assert_eq!(Matrix::from([[1, 2], [3, 4], [5, 6]]).row_canonical_form(), Matrix::from([[1, 0], [0, 1], [0, 0]]));
}
#[rstest]
fn det(setup: Fixture) {
assert_eq!(setup.mat_0x0.det(), 1.into());
assert_eq!(setup.mat_1x1.det(), 2.into());
assert_eq!(setup.mat_3x3.det(), 0.into());
assert_eq!(Matrix::from([[1, 2, 3], [4, 5, 6], [7, 8, 0]]).det(), 27.into());
}
#[rstest]
fn submatrix(setup: Fixture) {
assert_eq!(setup.mat_3x3.submatrix(0, 0), Matrix::from([[5, 6], [8, 9]]));
assert_eq!(setup.mat_3x3.submatrix(1, 1), Matrix::from([[1, 3], [7, 9]]));
assert_eq!(setup.mat_3x3.submatrix(0, 2), Matrix::from([[4, 5], [7, 8]]));
}
#[rstest]
fn minor(setup: Fixture) {
assert_eq!(Matrix::from([[1, 2], [3, 4]]).minor(), Matrix::from([[4, 3], [2, 1]]));
assert_eq!(setup.mat_3x3.minor(), Matrix::from([[-3, -6, -3], [-6, -12, -6], [-3, -6, -3]]));
}
#[rstest]
fn cofactor(setup: Fixture) {
assert_eq!(Matrix::from([[1, 2], [3, 4]]).cofactor(), Matrix::from([[4, -3], [-2, 1]]));
assert_eq!(setup.mat_3x3.cofactor(), Matrix::from([[-3, 6, -3], [6, -12, 6], [-3, 6, -3]]));
}
#[rstest]
fn adj(setup: Fixture) {
assert_eq!(setup.mat_0x0.adj(), Matrix::new());
assert_eq!(setup.mat_1x1.adj(), Matrix::from([[1]]));
assert_eq!(setup.mat_3x3.adj(), Matrix::from([[-3, 6, -3], [6, -12, 6], [-3, 6, -3]]));
assert_eq!(Matrix::from([[1, 2], [3, 4]]).adj(), Matrix::from([[4, -2], [-3, 1]]));
let m = &setup.mat_3x3;
assert_eq!(Matrix::identity(3).adj(), Matrix::identity(3)); assert_eq!(Matrix::zeros(3, 3).adj(), Matrix::zeros(3, 3)); assert_eq!(Matrix::zeros(1, 1).adj(), Matrix::identity(1)); assert_eq!((2 * m.clone()).adj(), 4 * m.adj()); assert_eq!(m.transpose().adj(), m.adj().transpose()); assert_eq!(m.adj().det(), m.det() * m.det()); assert_eq!(m * m.adj(), m.det() * Matrix::identity(3)); assert_eq!((m * m).adj(), m.adj() * m.adj()); assert_eq!(m.adj().adj(), m.det() * m.clone()); }
#[rstest]
fn inv(setup: Fixture) {
assert_eq!(setup.mat_0x0.inv(), Some(Matrix::new()));
assert_eq!(setup.mat_1x1.inv(), Some(Matrix::from([[Fraction::from((1, 2))]])));
assert_eq!(setup.mat_3x3.inv(), None);
assert_eq!(
Matrix::from([[1, 2, 3], [4, 5, 6], [7, 8, 0]]).inv(),
Some(Matrix::from([
[Fraction::from((-16, 9)), Fraction::from((8, 9)), Fraction::from((-1, 9))],
[Fraction::from((14, 9)), Fraction::from((-7, 9)), Fraction::from((2, 9))],
[Fraction::from((-1, 9)), Fraction::from((2, 9)), Fraction::from((-1, 9))],
]))
);
}
#[rstest]
fn rank(setup: Fixture) {
assert_eq!(setup.mat_0x0.rank(), 0);
assert_eq!(setup.mat_1x1.rank(), 1);
assert_eq!(setup.mat_3x3.rank(), 2);
assert_eq!(Matrix::ones(2, 2).rank(), 1);
assert_eq!(Matrix::from([[1, 2, 3], [4, 5, 6]]).rank(), 2);
assert_eq!(Matrix::from([[1, 2], [3, 4], [5, 6]]).rank(), 2);
assert_eq!(Matrix::from([[1, 2, 3], [4, 5, 6], [7, 8, 0]]).rank(), 3);
}
#[rstest]
fn lu_decomposition(setup: Fixture) {
assert_eq!(
Matrix::from([[2, 3, 1], [4, 7, 1], [6, 7, 3]]).lu_decomposition(),
(Matrix::from([[1, 0, 0], [2, 1, 0], [3, -2, 1]]), Matrix::from([[2, 3, 1], [0, 1, -1], [0, 0, -2]]))
);
assert_eq!(
setup.mat_3x3.lu_decomposition(),
(Matrix::from([[1, 0, 0], [4, 1, 0], [7, 2, 1]]), Matrix::from([[1, 2, 3], [0, -3, -6], [0, 0, 0]]))
);
}
#[rstest]
fn split() {
let matrix = Matrix::from([[1, 2], [3, 4], [5, 6]]);
assert_eq!(matrix.split_row(1).0, Matrix::from([[1, 2]]));
assert_eq!(matrix.split_row(1).1, Matrix::from([[3, 4], [5, 6]]));
assert_eq!(matrix.split_col(1).0, Matrix::from([[1], [3], [5]]));
assert_eq!(matrix.split_col(1).1, Matrix::from([[2], [4], [6]]));
}
#[rstest]
fn expand() {
assert_eq!(
Matrix::from([[1, 2], [3, 4]]).expand_row(Matrix::zeros(2, 2)),
&Matrix::from([[1, 2], [3, 4], [0, 0], [0, 0]])
);
assert_eq!(
Matrix::from([[1, 2, 3, 4, 5]]).expand_row(Matrix::from([[6, 7, 8, 9, 10]])),
&Matrix::from([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
);
assert_eq!(
Matrix::from([[1, 2], [3, 4]]).expand_col(Matrix::zeros(2, 2)),
&Matrix::from([[1, 2, 0, 0], [3, 4, 0, 0]])
);
assert_eq!(
Matrix::from([[1, 2, 3, 4, 5]]).expand_col(Matrix::from([[6, 7, 8, 9, 10]])),
&Matrix::from([[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]])
);
}
#[rstest]
fn elementary_row_operations(mut setup: Fixture) {
assert_eq!(setup.mat_3x3.e_row_swap(0, 1), &Matrix::from([[4, 5, 6], [1, 2, 3], [7, 8, 9]]));
assert_eq!(setup.mat_3x3.e_scalar_multiplication(1, 2.into()), &Matrix::from([[4, 5, 6], [2, 4, 6], [7, 8, 9]]));
assert_eq!(setup.mat_3x3.e_row_sum(0, 1, (-1).into()), &Matrix::from([[2, 1, 0], [2, 4, 6], [7, 8, 9]]));
}
#[rstest]
fn add() {
assert_eq!(Matrix::create(2, 3, 1.into()) + Matrix::create(2, 3, 2.into()), Matrix::create(2, 3, 3.into()));
assert_eq!(Matrix::from([[1, 2], [3, 4]]) + Matrix::from([[-1, -1], [-1, -1]]), Matrix::from([[0, 1], [2, 3]]));
}
#[rstest]
fn sub() {
assert_eq!(Matrix::create(2, 3, 1.into()) - Matrix::create(2, 3, 2.into()), Matrix::create(2, 3, (-1).into()));
assert_eq!(Matrix::from([[1, 2], [3, 4]]) - Matrix::from([[-1, -1], [-1, -1]]), Matrix::from([[2, 3], [4, 5]]));
}
#[rstest]
fn mul() {
assert_eq!(Matrix::create(2, 2, 1.into()) * Matrix::create(2, 2, 2.into()), Matrix::create(2, 2, 4.into()));
assert_eq!(Matrix::create(1, 3, 1.into()) * Matrix::create(3, 1, 1.into()), Matrix::create(1, 1, 3.into()));
assert_eq!(Matrix::create(2, 3, 1.into()) * Fraction::from(2), Matrix::create(2, 3, 2.into()));
assert_eq!(Matrix::from([[1, 2], [3, 4]]) * Fraction::from(3), Matrix::from([[3, 6], [9, 12]]));
}
#[rstest]
fn format(setup: Fixture) {
assert_eq!(format!("{}", setup.mat_0x0), "[\n]");
assert_eq!(format!("{}", setup.mat_1x1), "[\n2\n]");
assert_eq!(format!("{}", setup.mat_3x3), "[\n1 2 3\n4 5 6\n7 8 9\n]");
assert_eq!(
format!(
"{}",
Matrix::from([[Fraction::from((-11, 6)), Fraction::from((5, 6))], [Fraction::from((5, 3)), Fraction::from((-2, 3))]])
),
"[
-11/6 5/6
5/3 -2/3
]"
);
}