use lager::{isclose::IsClose, Matrix};
#[test]
fn index_matrices() {
let mtx = Matrix::new([[1., 2., 3.], [4., 5., 6.], [7., 8., 9.]]);
assert_eq!(mtx[[0, 0]], 1.);
assert_eq!(mtx[[0, 2]], 3.);
assert_eq!(mtx[[2, 0]], 7.);
assert_eq!(mtx[[2, 2]], 9.);
}
#[test]
fn check_matrices_are_close() {
let mtx1 = Matrix::new([[4.4, 7.3, 2.5], [2.4, 6.4, 2.2], [9.5, 3.5, 4.6]]);
let mtx2 = Matrix::new([
[4.40004, 7.299998, 2.50002],
[2.39998, 6.400001, 2.19998],
[9.50006, 3.499997, 4.60004],
]);
assert!(mtx1.isclose(&mtx2));
}
#[test]
fn multiply_3x3_identity_matrices() {
let i3 = Matrix::new([[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]]);
let res = i3.mul(&i3);
assert!(res.isclose(&i3));
}
#[test]
fn multiply_2x2_matrices_elementwise() {
let mtx1 = Matrix::new([[1., 2.], [3., 4.]]);
let mtx2 = Matrix::new([[4., 6.], [7., 5.]]);
let res = mtx1 * mtx2;
assert!(res.isclose(&Matrix::new([[4., 12.], [21., 20.]])));
}
#[test]
fn multiply_3x3_matrices() {
let mtx1 = Matrix::new([[1., 2., 3.], [4., 5., 6.], [7., 8., 9.]]);
let mtx2 = Matrix::new([[1., 2., 1.], [2., 4., 6.], [7., 2., 5.]]);
let res = mtx1.mul(&mtx2);
let expected = Matrix::new([[26., 16., 28.], [56., 40., 64.], [86., 64., 100.]]);
assert!(res.isclose(&expected));
}
#[test]
fn multiply_matrices_different_shapes() {
let mtx1 = Matrix::new([[1., 2., 3.], [4., 5., 6.]]);
let mtx2 = Matrix::new([[10., 11.], [20., 21.], [30., 31.]]);
let res = mtx1.mul(&mtx2);
let expected = Matrix::new([[140., 146.], [320., 335.]]);
assert!(res.isclose(&expected));
}
#[test]
fn get_view_from_matrix() {
let mtx = Matrix::new([[1., 2., 3.], [4., 5., 6.]]);
let slice = mtx.view([0..2, 1..3]);
let slice_mtx: Matrix<f64, 2, 2> = slice.into();
let expected = Matrix::new([[2., 3.], [5., 6.]]);
assert!(slice_mtx.isclose(&expected));
}
#[test]
fn view_iterator_column() {
let mtx = Matrix::new([[1., 2., 3.], [4., 5., 6.], [7., 8., 9.]]);
let slice = mtx.view::<3, 1>([0..3, 1..2]);
let mut iter = slice.iter();
assert_eq!(Some(&2.), iter.next());
assert_eq!(Some(&5.), iter.next());
assert_eq!(Some(&8.), iter.next());
assert_eq!(None, iter.next());
}
#[test]
fn view_iterator_matrix() {
let mtx = Matrix::new([[1., 2., 3.], [4., 5., 6.], [7., 8., 9.]]);
let slice = mtx.view::<2, 2>([1..3, 0..2]);
let mut iter = slice.iter();
assert_eq!(Some(&4.), iter.next());
assert_eq!(Some(&5.), iter.next());
assert_eq!(Some(&7.), iter.next());
assert_eq!(Some(&8.), iter.next());
assert_eq!(None, iter.next());
}
#[test]
fn row_echelon() {
let mut mtx = Matrix::new([
[2., 4., 1., 1., 0., 0.],
[-1., 1., -1., 0., 1., 0.],
[1., 4., 0., 0., 0., 1.],
]);
mtx.into_row_echelon();
let expected = Matrix::new([
[2., 4., 1., 1., 0., 0.],
[0., 3., -0.5, 0.5, 1., 0.],
[0., 0., -1. / 6., -5. / 6., -2. / 3., 1.],
]);
assert!(mtx.isclose(&expected));
}
#[test]
fn reduced_row_echelon() {
let mut mtx = Matrix::new([
[2., 4., 1., 1., 0., 0.],
[-1., 1., -1., 0., 1., 0.],
[1., 4., 0., 0., 0., 1.],
]);
mtx.into_reduced_row_echelon();
let expected = Matrix::new([
[1., 0., 0., -4., -4., 5.],
[0., 1., 0., 1., 1., -1.],
[0., 0., 1., 5., 4., -6.],
]);
assert!(mtx.isclose(&expected));
}
#[test]
fn matrix_inverse() {
let mtx = Matrix::new([[2., 4., 1.], [-1., 1., -1.], [1., 4., 0.]]);
let result = mtx.inv();
let expected = Matrix::new([[-4., -4., 5.], [1., 1., -1.], [5., 4., -6.]]);
assert!(result.isclose(&expected));
}
#[test]
fn hstack() {
let mtx1: Matrix<f64, 3, 4> =
Matrix::new([[2., 4., 1., 7.], [-1., 1., -1., 2.], [1., 4., 0., 9.]]);
let mtx2: Matrix<f64, 3, 3> = Matrix::new([[-4., -4., 5.], [1., 1., -1.], [5., 4., -6.]]);
let result: Matrix<f64, 3, 7> = mtx1.hstack(mtx2);
let expected = Matrix::new([
[2., 4., 1., 7., -4., -4., 5.],
[-1., 1., -1., 2., 1., 1., -1.],
[1., 4., 0., 9., 5., 4., -6.],
]);
assert!(result.isclose(&expected));
}
#[test]
fn vstack() {
let mtx1: Matrix<f64, 3, 3> = Matrix::new([[2., 4., 1.], [-1., 1., -1.], [1., 4., 0.]]);
let mtx2: Matrix<f64, 4, 3> =
Matrix::new([[-4., -4., 5.], [1., 1., -1.], [5., 4., -6.], [7., 2., 9.]]);
let result: Matrix<f64, 7, 3> = mtx1.vstack(mtx2);
let expected = Matrix::new([
[2., 4., 1.],
[-1., 1., -1.],
[1., 4., 0.],
[-4., -4., 5.],
[1., 1., -1.],
[5., 4., -6.],
[7., 2., 9.],
]);
assert!(result.isclose(&expected));
}
#[test]
fn zeros() {
let result = Matrix::zeros();
let expected = Matrix::new([[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]]);
assert!(result.isclose(&expected));
}
#[test]
fn ones() {
let result = Matrix::ones();
let expected = Matrix::new([[1., 1., 1.], [1., 1., 1.], [1., 1., 1.]]);
assert!(result.isclose(&expected));
}
#[test]
fn identity_3x3() {
let result = Matrix::identity();
let expected = Matrix::new([[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]]);
assert!(result.isclose(&expected));
}
#[test]
fn lu_decomposition() {
let mtx = Matrix::new([[2., -1., -2.], [-4., 6., 3.], [-4., -2., 8.]]);
let result = mtx.lu();
assert!(result.l.is_lower_triangular());
assert!(result.u.is_upper_triangular());
assert_eq!(result.p.count(), 3);
assert!(3.0_f64.isclose(result.p.sum()));
assert!(mtx.isclose(&result.p.inv().mul(&result.l.mul(&result.u))));
}
#[test]
fn lu_decomposition_unknown_result() {
let mtx = Matrix::new([[10., -7., 0.], [-3., 2., 6.], [5., -1., 5.]]);
let result = mtx.lu();
assert!(result.l.is_lower_triangular());
assert!(result.u.is_upper_triangular());
assert_eq!(result.p.count(), 3);
assert!(3.0_f64.isclose(result.p.sum()));
assert!(mtx.isclose(&result.p.inv().mul(&result.l.mul(&result.u))));
}
#[test]
fn lu_decomposition_with_permuations() {
let mtx = Matrix::new([
[0., 2., 8., 6.],
[0., 0., 1., 2.],
[0., 1., 0., 1.],
[3., 7., 1., 0.],
]);
let result = mtx.lu();
assert!(result.l.is_lower_triangular());
assert!(result.u.is_upper_triangular());
assert_eq!(result.p.count(), 4);
assert!(4.0_f64.isclose(result.p.sum()));
assert!(mtx.isclose(&result.p.inv().mul(&result.l.mul(&result.u))));
}
#[test]
fn count_3x3() {
let mtx = Matrix::new([[2., 4., 1.], [0., 1., -1.], [1., 4., 0.]]);
assert_eq!(mtx.count(), 7);
}
#[test]
fn diag_3x3() {
let mtx = Matrix::new([[2., 4., 1.], [0., 1., -1.], [1., 4., 0.]]);
let result = mtx.diag();
let expected = Matrix::new([[2.], [1.], [0.]]);
assert!(expected.isclose(&result))
}
#[test]
fn determinant_3x3() {
let mtx: Matrix<f64, 3, 3> = Matrix::new([[2., 4., 1.], [-1., 1., -1.], [1., 4., 0.]]);
assert!((-1.0_f64).isclose(mtx.det()));
}
#[test]
fn determinant_4x4() {
let mtx: Matrix<f64, 4, 4> = Matrix::new([
[4., 3., 2., 1.],
[1., 10., 3., 4.],
[5., 3., 2., -4.],
[4., 8., 7., 9.],
]);
assert!(602.0_f64.isclose(mtx.det()));
}
#[test]
fn transpose() {
let mtx = Matrix::new([[1., 2., 3.], [4., 5., 6.], [7., 8., 9.], [10., 11., 12.]]);
let res = mtx.t();
let expected = Matrix::new([[1., 4., 7., 10.], [2., 5., 8., 11.], [3., 6., 9., 12.]]);
assert!(res.isclose(&expected));
}