use mymatrix::Matrix; use pyinrs::Fraction; use rstest::{fixture, rstest}; struct Fixture { empty: Matrix, one: Matrix, some: Matrix, } #[fixture] fn setup() -> Fixture { Fixture { empty: Matrix::new(), one: Matrix::from([[1]]), some: Matrix::from([[1, 2, 3], [4, 5, 6]]), } } #[rstest] fn basics(setup: Fixture) { assert_eq!(setup.empty.row_size(), 0); assert_eq!(setup.empty.col_size(), 0); assert!(setup.empty.is_empty()); assert_eq!(setup.one.row_size(), 1); assert_eq!(setup.one.col_size(), 1); assert!(!setup.one.is_empty()); assert_eq!(setup.some.row_size(), 2); assert_eq!(setup.some.col_size(), 3); assert!(!setup.some.is_empty()); } #[rstest] fn compare(setup: Fixture) { assert!(setup.some == Matrix::from([[1, 2, 3], [4, 5, 6]])); assert!(setup.some != Matrix::from([[1, 2, 3], [4, 5, 0]])); } #[rstest] fn access(mut setup: Fixture) { for r in 0..setup.some.row_size() { for c in 0..setup.some.col_size() { assert_eq!(setup.some[r][c], (r as i32 * 3 + c as i32 + 1).into()); } } setup.some[0][0] = 0.into(); assert_eq!(setup.some[0][0], 0.into()); } #[rstest] fn is_symmetric(setup: Fixture) { assert_eq!(setup.empty.is_symmetric(), true); assert_eq!(setup.one.is_symmetric(), true); assert_eq!(setup.some.is_symmetric(), false); assert_eq!((&setup.some * &setup.some.transpose()).is_symmetric(), true); assert_eq!(Matrix::from([[1, 2, 3], [4, 5, 6], [7, 8, 0]]).is_symmetric(), false); } #[rstest] fn transpose() { assert_eq!(Matrix::create(2, 3, 1.into()).transpose(), Matrix::create(3, 2, 1.into())); assert_eq!(Matrix::create(1, 3, 3.into()).transpose(), Matrix::create(3, 1, 3.into())); } #[rstest] fn submatrix() { let m = Matrix::from([[1, 2, 3], [4, 5, 6], [7, 8, 9]]); assert_eq!(m.submatrix(0, 0), Matrix::from([[5, 6], [8, 9]])); assert_eq!(m.submatrix(1, 1), Matrix::from([[1, 3], [7, 9]])); assert_eq!(m.submatrix(0, 2), Matrix::from([[4, 5], [7, 8]])); } #[rstest] fn minor() { assert_eq!(Matrix::from([[1, 2], [3, 4]]).minor(), Matrix::from([[4, 3], [2, 1]])); assert_eq!( Matrix::from([[1, 2, 3], [4, 5, 6], [7, 8, 9]]).minor(), Matrix::from([[-3, -6, -3], [-6, -12, -6], [-3, -6, -3]]) ); } #[rstest] fn cofactor() { assert_eq!(Matrix::from([[1, 2], [3, 4]]).cofactor(), Matrix::from([[4, -3], [-2, 1]])); assert_eq!( Matrix::from([[1, 2, 3], [4, 5, 6], [7, 8, 9]]).cofactor(), Matrix::from([[-3, 6, -3], [6, -12, 6], [-3, 6, -3]]) ); } #[rstest] fn adj() { let m1 = Matrix::from([[1, 2], [3, 4]]); assert_eq!(m1.adj(), Matrix::from([[4, -2], [-3, 1]])); assert_eq!(m1.adj() * (Fraction::from(1) / m1.det().unwrap()), m1.inv().unwrap()); // inv(A) = (1/det(A)) * adj(A) let m2 = Matrix::from([[1, 2, 3], [4, 5, 6], [7, 8, 0]]); assert_eq!(m2.adj(), Matrix::from([[-48, 24, -3], [42, -21, 6], [-3, 6, -3]])); assert_eq!(m2.adj() * (Fraction::from(1) / m2.det().unwrap()), m2.inv().unwrap()); } #[rstest] fn det() { assert_eq!(Matrix::from([[1, 2, 3], [4, 5, 6], [7, 8, 9]]).det(), Some(0.into())); assert_eq!(Matrix::from([[1, 2, 3], [4, 5, 6], [7, 8, 0]]).det(), Some(27.into())); assert_eq!(Matrix::from([[1, 2, 3], [4, 5, 6]]).det(), None); assert_eq!(Matrix::new().det(), Some(1.into())); } #[rstest] fn inv() { assert_eq!( Matrix::from([[1, 2], [3, 4]]).inv(), Some(Matrix::from([ [Fraction::from(-2), Fraction::from(1)], [Fraction::from((3, 2)), Fraction::from((-1, 2))] ])) ); 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))], ])) ); assert_eq!(Matrix::from([[1, 2, 3], [4, 5, 6], [7, 8, 9]]).inv(), None); } #[rstest] fn rref() { assert_eq!(Matrix::ones(2, 2).rref(), Matrix::from([[1, 1], [0, 0]])); assert_eq!(Matrix::from([[1, 2, 3], [4, 5, 6]]).rref(), Matrix::from([[1, 0, -1], [0, 1, 2]])); assert_eq!(Matrix::from([[1, 2], [3, 4], [5, 6]]).rref(), Matrix::from([[1, 0], [0, 1], [0, 0]])); assert_eq!(Matrix::from([[1, 2], [3, 4], [5, 6], [7, 8]]).rref(), Matrix::from([[1, 0], [0, 1], [0, 0], [0, 0]])); assert_eq!(Matrix::from([[1, 2, 3, 4], [5, 6, 7, 8]]).rref(), Matrix::from([[1, 0, -1, -2], [0, 1, 2, 3]])); } #[rstest] fn rank() { 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, 9]]).rank(), 2); assert_eq!(Matrix::from([[1, 2, 3], [4, 5, 6], [7, 8, 0]]).rank(), 3); } #[rstest] fn lu_decomposition() { 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!( Matrix::from([[2, 3, 1], [4, 0, 1], [6, 7, 3]]).lu_decomposition(), ( Matrix::from([ [1.into(), 0.into(), 0.into()], [2.into(), 1.into(), 0.into()], [3.into(), Fraction::from((1, 3)), 1.into()] ]), Matrix::from([ [2.into(), 3.into(), 1.into()], [0.into(), (-6).into(), (-1).into()], [0.into(), 0.into(), Fraction::from((1, 3))] ]) ) ); } #[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() { let mut matrix = Matrix::from([[1, 2, 3], [4, 5, 6], [7, 8, 9]]); assert_eq!(matrix.e_row_swap(0, 1), &Matrix::from([[4, 5, 6], [1, 2, 3], [7, 8, 9]])); assert_eq!(matrix.e_scalar_multiplication(1, 2.into()), &Matrix::from([[4, 5, 6], [2, 4, 6], [7, 8, 9]])); assert_eq!(matrix.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.empty), "[\n]"); assert_eq!(format!("{}", setup.one), "[\n1\n]"); assert_eq!(format!("{}", setup.some), "[\n1 2 3\n4 5 6\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 ]" ); }