use na::iter::MatrixIter; use num::{One, Zero}; use std::cmp::Ordering; use na::dimension::{U15, U8}; use na::{ self, Const, DMatrix, DVector, Matrix2, Matrix2x3, Matrix2x4, Matrix3, Matrix3x2, Matrix3x4, Matrix4, Matrix4x3, Matrix4x5, Matrix5, Matrix6, MatrixView2x3, MatrixViewMut2x3, OMatrix, RowVector3, RowVector4, RowVector5, Vector1, Vector2, Vector3, Vector4, Vector5, Vector6, }; #[test] fn iter() { let a = Matrix2x3::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0); let view: MatrixView2x3<_> = (&a).into(); fn test<'a, F: Fn() -> I, I: Iterator + DoubleEndedIterator>(it: F) { { let mut it = it(); assert_eq!(*it.next().unwrap(), 1.0); assert_eq!(*it.next().unwrap(), 4.0); assert_eq!(*it.next().unwrap(), 2.0); assert_eq!(*it.next().unwrap(), 5.0); assert_eq!(*it.next().unwrap(), 3.0); assert_eq!(*it.next().unwrap(), 6.0); assert!(it.next().is_none()); } { let mut it = it(); assert_eq!(*it.next().unwrap(), 1.0); assert_eq!(*it.next_back().unwrap(), 6.0); assert_eq!(*it.next_back().unwrap(), 3.0); assert_eq!(*it.next_back().unwrap(), 5.0); assert_eq!(*it.next().unwrap(), 4.0); assert_eq!(*it.next().unwrap(), 2.0); assert!(it.next().is_none()); } { let mut it = it().rev(); assert_eq!(*it.next().unwrap(), 6.0); assert_eq!(*it.next().unwrap(), 3.0); assert_eq!(*it.next().unwrap(), 5.0); assert_eq!(*it.next().unwrap(), 2.0); assert_eq!(*it.next().unwrap(), 4.0); assert_eq!(*it.next().unwrap(), 1.0); assert!(it.next().is_none()); } } test(|| a.iter()); test(|| view.into_iter()); let row = a.row(0); let row_test = |mut it: MatrixIter<_, _, _, _>| { assert_eq!(*it.next().unwrap(), 1.0); assert_eq!(*it.next().unwrap(), 2.0); assert_eq!(*it.next().unwrap(), 3.0); assert!(it.next().is_none()); }; row_test(row.iter()); row_test(row.into_iter()); let row = a.row(1); let row_test = |mut it: MatrixIter<_, _, _, _>| { assert_eq!(*it.next().unwrap(), 4.0); assert_eq!(*it.next().unwrap(), 5.0); assert_eq!(*it.next().unwrap(), 6.0); assert!(it.next().is_none()); }; row_test(row.iter()); row_test(row.into_iter()); let m22 = row.column(1); let m22_test = |mut it: MatrixIter<_, _, _, _>| { assert_eq!(*it.next().unwrap(), 5.0); assert!(it.next().is_none()); }; m22_test(m22.iter()); m22_test(m22.into_iter()); let col = a.column(0); let col_test = |mut it: MatrixIter<_, _, _, _>| { assert_eq!(*it.next().unwrap(), 1.0); assert_eq!(*it.next().unwrap(), 4.0); assert!(it.next().is_none()); }; col_test(col.iter()); col_test(col.into_iter()); let col = a.column(1); let col_test = |mut it: MatrixIter<_, _, _, _>| { assert_eq!(*it.next().unwrap(), 2.0); assert_eq!(*it.next().unwrap(), 5.0); assert!(it.next().is_none()); }; col_test(col.iter()); col_test(col.into_iter()); let col = a.column(2); let col_test = |mut it: MatrixIter<_, _, _, _>| { assert_eq!(*it.next().unwrap(), 3.0); assert_eq!(*it.next().unwrap(), 6.0); assert!(it.next().is_none()); }; col_test(col.iter()); col_test(col.into_iter()); } #[test] fn iter_mut() { let mut a = Matrix2x3::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0); for v in a.iter_mut() { *v *= 2.0; } assert_eq!(a, Matrix2x3::new(2.0, 4.0, 6.0, 8.0, 10.0, 12.0)); let view: MatrixViewMut2x3<_> = MatrixViewMut2x3::from(&mut a); for v in view.into_iter() { *v *= 2.0; } assert_eq!(a, Matrix2x3::new(4.0, 8.0, 12.0, 16.0, 20.0, 24.0)); } #[test] fn debug_output_corresponds_to_data_container() { let m = Matrix2::new(1.0, 2.0, 3.0, 4.0); let output_stable = "[[1, 3], [2, 4]]"; // Current output on the stable channel. let output_nightly = "[[1.0, 3.0], [2.0, 4.0]]"; // Current output on the nightly channel. let current_output = format!("{:?}", m); dbg!(output_stable); dbg!(output_nightly); dbg!(¤t_output); assert!(current_output == output_stable || current_output == output_nightly); } #[test] fn is_column_major() { let a = Matrix2x3::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0); let expected = &[1.0, 4.0, 2.0, 5.0, 3.0, 6.0]; assert_eq!(a.as_slice(), expected); let a = Matrix2x3::from_row_slice(&[1.0, 2.0, 3.0, 4.0, 5.0, 6.0]); assert_eq!(a.as_slice(), expected); let a = Matrix2x3::from_column_slice(&[1.0, 4.0, 2.0, 5.0, 3.0, 6.0]); assert_eq!(a.as_slice(), expected); } #[test] fn linear_index() { let a = Matrix2x3::new(1, 2, 3, 4, 5, 6); assert_eq!(a[0], 1); assert_eq!(a[1], 4); assert_eq!(a[2], 2); assert_eq!(a[3], 5); assert_eq!(a[4], 3); assert_eq!(a[5], 6); let b = Vector4::new(1, 2, 3, 4); assert_eq!(b[0], 1); assert_eq!(b[1], 2); assert_eq!(b[2], 3); assert_eq!(b[3], 4); let c = RowVector4::new(1, 2, 3, 4); assert_eq!(c[0], 1); assert_eq!(c[1], 2); assert_eq!(c[2], 3); assert_eq!(c[3], 4); } #[test] fn identity() { let id1 = Matrix3::::identity(); let id2 = Matrix3x4::new(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); let id2bis = Matrix3x4::identity(); let id3 = Matrix4x3::new(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0); let id3bis = Matrix4x3::identity(); let not_id1 = Matrix3::identity() * 2.0; let not_id2 = Matrix3x4::new(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0); let not_id3 = Matrix4x3::new(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0); assert_eq!(id2, id2bis); assert_eq!(id3, id3bis); assert!(id1.is_identity(0.0)); assert!(id2.is_identity(0.0)); assert!(id3.is_identity(0.0)); assert!(!not_id1.is_identity(0.0)); assert!(!not_id2.is_identity(0.0)); assert!(!not_id3.is_identity(0.0)); } #[test] fn coordinates() { let a = Matrix3x4::new(11, 12, 13, 14, 21, 22, 23, 24, 31, 32, 33, 34); assert_eq!(a.m11, 11); assert_eq!(a.m12, 12); assert_eq!(a.m13, 13); assert_eq!(a.m14, 14); assert_eq!(a.m21, 21); assert_eq!(a.m22, 22); assert_eq!(a.m23, 23); assert_eq!(a.m24, 24); assert_eq!(a.m31, 31); assert_eq!(a.m32, 32); assert_eq!(a.m33, 33); assert_eq!(a.m34, 34); } #[test] fn from_diagonal() { let diag = Vector3::new(1, 2, 3); let expected = Matrix3::new(1, 0, 0, 0, 2, 0, 0, 0, 3); let a = Matrix3::from_diagonal(&diag); assert_eq!(a, expected); } #[test] fn from_rows() { let rows = &[ RowVector4::new(11, 12, 13, 14), RowVector4::new(21, 22, 23, 24), RowVector4::new(31, 32, 33, 34), ]; let expected = Matrix3x4::new(11, 12, 13, 14, 21, 22, 23, 24, 31, 32, 33, 34); let a = Matrix3x4::from_rows(rows); assert_eq!(a, expected); } #[test] fn from_columns() { let columns = &[ Vector3::new(11, 21, 31), Vector3::new(12, 22, 32), Vector3::new(13, 23, 33), Vector3::new(14, 24, 34), ]; let expected = Matrix3x4::new(11, 12, 13, 14, 21, 22, 23, 24, 31, 32, 33, 34); let a = Matrix3x4::from_columns(columns); assert_eq!(a, expected); } #[test] fn from_columns_dynamic() { let columns = &[ DVector::from_row_slice(&[11, 21, 31]), DVector::from_row_slice(&[12, 22, 32]), DVector::from_row_slice(&[13, 23, 33]), DVector::from_row_slice(&[14, 24, 34]), ]; let expected = DMatrix::from_row_slice(3, 4, &[11, 12, 13, 14, 21, 22, 23, 24, 31, 32, 33, 34]); let a = DMatrix::from_columns(columns); assert_eq!(a, expected); } #[test] #[should_panic] fn from_too_many_rows() { let rows = &[ RowVector4::new(11, 12, 13, 14), RowVector4::new(21, 22, 23, 24), RowVector4::new(31, 32, 33, 34), RowVector4::new(31, 32, 33, 34), ]; let _ = Matrix3x4::from_rows(rows); } #[test] #[should_panic] fn from_not_enough_columns() { let columns = &[Vector3::new(11, 21, 31), Vector3::new(14, 24, 34)]; let _ = Matrix3x4::from_columns(columns); } #[test] #[should_panic] fn from_rows_with_different_dimensions() { let columns = &[ DVector::from_row_slice(&[11, 21, 31]), DVector::from_row_slice(&[12, 22, 32, 33]), ]; let _ = DMatrix::from_columns(columns); } #[test] fn copy_from_slice() { let mut a = Matrix3::zeros(); let data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]; let expected_a = Matrix3::new(1.0, 4.0, 7.0, 2.0, 5.0, 8.0, 3.0, 6.0, 9.0); a.copy_from_slice(&data); assert_eq!(a, expected_a); } #[should_panic] #[test] fn copy_from_slice_too_small() { let mut a = Matrix3::zeros(); let data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]; a.copy_from_slice(&data); } #[should_panic] #[test] fn copy_from_slice_too_large() { let mut a = Matrix3::zeros(); let data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]; a.copy_from_slice(&data); } #[test] fn to_homogeneous() { let a = Vector3::new(1.0, 2.0, 3.0); let expected_a = Vector4::new(1.0, 2.0, 3.0, 0.0); let b = DVector::from_row_slice(&[1.0, 2.0, 3.0]); let expected_b = DVector::from_row_slice(&[1.0, 2.0, 3.0, 0.0]); let c = Matrix2::new(1.0, 2.0, 3.0, 4.0); let expected_c = Matrix3::new(1.0, 2.0, 0.0, 3.0, 4.0, 0.0, 0.0, 0.0, 1.0); let d = DMatrix::from_row_slice(2, 2, &[1.0, 2.0, 3.0, 4.0]); let expected_d = DMatrix::from_row_slice(3, 3, &[1.0, 2.0, 0.0, 3.0, 4.0, 0.0, 0.0, 0.0, 1.0]); assert_eq!(a.to_homogeneous(), expected_a); assert_eq!(b.to_homogeneous(), expected_b); assert_eq!(c.to_homogeneous(), expected_c); assert_eq!(d.to_homogeneous(), expected_d); } #[test] fn push() { let a = Vector3::new(1.0, 2.0, 3.0); let expected_a = Vector4::new(1.0, 2.0, 3.0, 4.0); let b = DVector::from_row_slice(&[1.0, 2.0, 3.0]); let expected_b = DVector::from_row_slice(&[1.0, 2.0, 3.0, 4.0]); assert_eq!(a.push(4.0), expected_a); assert_eq!(b.push(4.0), expected_b); } #[test] fn simple_add() { let a = Matrix2x3::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0); let b = Matrix2x3::new(10.0, 20.0, 30.0, 40.0, 50.0, 60.0); let c = DMatrix::from_row_slice(2, 3, &[10.0, 20.0, 30.0, 40.0, 50.0, 60.0]); let expected = Matrix2x3::new(11.0, 22.0, 33.0, 44.0, 55.0, 66.0); assert_eq!(expected, &a + &b); assert_eq!(expected, &a + b); assert_eq!(expected, a + &b); assert_eq!(expected, a + b); // Sum of a static matrix with a dynamic one. assert_eq!(expected, &a + &c); assert_eq!(expected, a + &c); assert_eq!(expected, &c + &a); assert_eq!(expected, &c + a); } #[test] fn simple_sum() { type M = Matrix2x3; let a = M::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0); let b = M::new(10.0, 20.0, 30.0, 40.0, 50.0, 60.0); let c = M::new(100.0, 200.0, 300.0, 400.0, 500.0, 600.0); assert_eq!(M::zero(), Vec::::new().iter().sum()); assert_eq!(M::zero(), Vec::::new().into_iter().sum()); assert_eq!(a + b, vec![a, b].iter().sum()); assert_eq!(a + b, vec![a, b].into_iter().sum()); assert_eq!(a + b + c, vec![a, b, c].iter().sum()); assert_eq!(a + b + c, vec![a, b, c].into_iter().sum()); } #[test] fn simple_scalar_mul() { let a = Matrix2x3::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0); let expected = Matrix2x3::new(10.0, 20.0, 30.0, 40.0, 50.0, 60.0); assert_eq!(expected, a * 10.0); assert_eq!(expected, &a * 10.0); assert_eq!(expected, 10.0 * a); assert_eq!(expected, 10.0 * &a); } #[test] fn simple_mul() { let a = Matrix2x3::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0); let b = Matrix3x4::new( 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0, 110.0, 120.0, ); let expected = Matrix2x4::new(380.0, 440.0, 500.0, 560.0, 830.0, 980.0, 1130.0, 1280.0); assert_eq!(expected, &a * &b); assert_eq!(expected, a * &b); assert_eq!(expected, &a * b); assert_eq!(expected, a * b); } #[test] fn simple_product() { type M = Matrix3; let a = M::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0); let b = M::new(10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0); let c = M::new( 100.0, 200.0, 300.0, 400.0, 500.0, 600.0, 700.0, 800.0, 900.0, ); assert_eq!(M::one(), Vec::::new().iter().product()); assert_eq!(M::one(), Vec::::new().into_iter().product()); assert_eq!(a * b, vec![a, b].iter().product()); assert_eq!(a * b, vec![a, b].into_iter().product()); assert_eq!(a * b * c, vec![a, b, c].iter().product()); assert_eq!(a * b * c, vec![a, b, c].into_iter().product()); } #[test] fn cross_product_vector_and_row_vector() { let v1 = Vector3::new(1.0, 2.0, 3.0); let v2 = Vector3::new(1.0, 5.0, 7.0); let column_cross = v1.cross(&v2); assert_eq!(column_cross, Vector3::new(-1.0, -4.0, 3.0)); let v1 = RowVector3::new(1.0, 2.0, 3.0); let v2 = RowVector3::new(1.0, 5.0, 7.0); let row_cross = v1.cross(&v2); assert_eq!(row_cross, RowVector3::new(-1.0, -4.0, 3.0)); assert_eq!( Vector3::new(1.0, 1.0, 0.0) .cross(&Vector3::new(-0.5, 17.0, 0.0)) .transpose(), RowVector3::new(1.0, 1.0, 0.0).cross(&RowVector3::new(-0.5, 17.0, 0.0)) ); } #[test] fn simple_scalar_conversion() { let a = Matrix2x3::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0); let expected = Matrix2x3::new(1, 2, 3, 4, 5, 6); let a_u32: Matrix2x3 = na::try_convert(a).unwrap(); // f32 -> u32 let a_f32: Matrix2x3 = na::convert(a_u32); // u32 -> f32 assert_eq!(a, a_f32); assert_eq!(expected, a_u32); } #[test] fn apply() { let mut a = Matrix4::new( 1.1f32, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 8.8, 7.7, 6.6, 5.5, 4.4, 3.3, 2.2, ); let expected = Matrix4::new( 1.0, 2.0, 3.0, 4.0, 6.0, 7.0, 8.0, 9.0, 10.0, 9.0, 8.0, 7.0, 6.0, 4.0, 3.0, 2.0, ); a.apply(|e| *e = e.round()); assert_eq!(a, expected); } #[test] fn map() { let a = Matrix4::new( 1.1f64, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 8.8, 7.7, 6.6, 5.5, 4.4, 3.3, 2.2, ); let expected = Matrix4::new(1, 2, 3, 4, 6, 7, 8, 9, 10, 9, 8, 7, 6, 4, 3, 2); let computed = a.map(|e| e.round() as i64); assert_eq!(computed, expected); } #[test] fn map_with_location() { let a = Matrix4::new(1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4); let expected = Matrix4::new(1, 2, 3, 4, 3, 4, 5, 6, 5, 6, 7, 8, 7, 8, 9, 10); let computed = a.map_with_location(|i, j, e| e + i + j); assert_eq!(computed, expected); } #[test] fn zip_map() { let a = Matrix3::new(11i32, 12, 13, 21, 22, 23, 31, 32, 33); let b = Matrix3::new(11u32, 12, 13, 21, 22, 23, 31, 32, 33); let expected = Matrix3::new(22.0f32, 24.0, 26.0, 42.0, 44.0, 46.0, 62.0, 64.0, 66.0); let computed = a.zip_map(&b, |ea, eb| ea as f32 + eb as f32); assert_eq!(computed, expected); } #[test] #[should_panic] fn trace_panic() { let m = DMatrix::::new_random(2, 3); let _ = m.trace(); } #[test] fn trace() { let m = Matrix2::new(1.0, 20.0, 30.0, 4.0); assert_eq!(m.trace(), 5.0); } #[test] fn simple_transpose() { let a = Matrix2x3::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0); let expected = Matrix3x2::new(1.0, 4.0, 2.0, 5.0, 3.0, 6.0); assert_eq!(a.transpose(), expected); } #[test] fn simple_transpose_mut() { let mut a = Matrix3::new(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0); let expected = Matrix3::new(1.0, 4.0, 7.0, 2.0, 5.0, 8.0, 3.0, 6.0, 9.0); a.transpose_mut(); assert_eq!(a, expected); } #[test] fn vector_index_mut() { let mut v = Vector3::new(1, 2, 3); assert_eq!(v[0], 1); assert_eq!(v[1], 2); assert_eq!(v[2], 3); v[0] = 10; v[1] = 20; v[2] = 30; assert_eq!(v, Vector3::new(10, 20, 30)); } #[test] fn components_mut() { let mut m2 = Matrix2::from_element(1.0); let mut m3 = Matrix3::from_element(1.0); let mut m4 = Matrix4::from_element(1.0); let mut m5 = Matrix5::from_element(1.0); let mut m6 = Matrix6::from_element(1.0); m2.m11 = 0.0; m2.m12 = 0.0; m2.m21 = 0.0; m2.m22 = 0.0; m3.m11 = 0.0; m3.m12 = 0.0; m3.m13 = 0.0; m3.m21 = 0.0; m3.m22 = 0.0; m3.m23 = 0.0; m3.m31 = 0.0; m3.m32 = 0.0; m3.m33 = 0.0; m4.m11 = 0.0; m4.m12 = 0.0; m4.m13 = 0.0; m4.m14 = 0.0; m4.m21 = 0.0; m4.m22 = 0.0; m4.m23 = 0.0; m4.m24 = 0.0; m4.m31 = 0.0; m4.m32 = 0.0; m4.m33 = 0.0; m4.m34 = 0.0; m4.m41 = 0.0; m4.m42 = 0.0; m4.m43 = 0.0; m4.m44 = 0.0; m5.m11 = 0.0; m5.m12 = 0.0; m5.m13 = 0.0; m5.m14 = 0.0; m5.m15 = 0.0; m5.m21 = 0.0; m5.m22 = 0.0; m5.m23 = 0.0; m5.m24 = 0.0; m5.m25 = 0.0; m5.m31 = 0.0; m5.m32 = 0.0; m5.m33 = 0.0; m5.m34 = 0.0; m5.m35 = 0.0; m5.m41 = 0.0; m5.m42 = 0.0; m5.m43 = 0.0; m5.m44 = 0.0; m5.m45 = 0.0; m5.m51 = 0.0; m5.m52 = 0.0; m5.m53 = 0.0; m5.m54 = 0.0; m5.m55 = 0.0; m6.m11 = 0.0; m6.m12 = 0.0; m6.m13 = 0.0; m6.m14 = 0.0; m6.m15 = 0.0; m6.m16 = 0.0; m6.m21 = 0.0; m6.m22 = 0.0; m6.m23 = 0.0; m6.m24 = 0.0; m6.m25 = 0.0; m6.m26 = 0.0; m6.m31 = 0.0; m6.m32 = 0.0; m6.m33 = 0.0; m6.m34 = 0.0; m6.m35 = 0.0; m6.m36 = 0.0; m6.m41 = 0.0; m6.m42 = 0.0; m6.m43 = 0.0; m6.m44 = 0.0; m6.m45 = 0.0; m6.m46 = 0.0; m6.m51 = 0.0; m6.m52 = 0.0; m6.m53 = 0.0; m6.m54 = 0.0; m6.m55 = 0.0; m6.m56 = 0.0; m6.m61 = 0.0; m6.m62 = 0.0; m6.m63 = 0.0; m6.m64 = 0.0; m6.m65 = 0.0; m6.m66 = 0.0; assert!(m2.is_zero()); assert!(m3.is_zero()); assert!(m4.is_zero()); assert!(m5.is_zero()); assert!(m6.is_zero()); let mut v1 = Vector1::from_element(1.0); let mut v2 = Vector2::from_element(1.0); let mut v3 = Vector3::from_element(1.0); let mut v4 = Vector4::from_element(1.0); let mut v5 = Vector5::from_element(1.0); let mut v6 = Vector6::from_element(1.0); v1.x = 0.0; v2.x = 0.0; v2.y = 0.0; v3.x = 0.0; v3.y = 0.0; v3.z = 0.0; v4.x = 0.0; v4.y = 0.0; v4.z = 0.0; v4.w = 0.0; v5.x = 0.0; v5.y = 0.0; v5.z = 0.0; v5.w = 0.0; v5.a = 0.0; v6.x = 0.0; v6.y = 0.0; v6.z = 0.0; v6.w = 0.0; v6.a = 0.0; v6.b = 0.0; assert!(v1.is_zero()); assert!(v2.is_zero()); assert!(v3.is_zero()); assert!(v4.is_zero()); assert!(v5.is_zero()); assert!(v6.is_zero()); // Check that the components order is correct. m3.m11 = 11.0; m3.m12 = 12.0; m3.m13 = 13.0; m3.m21 = 21.0; m3.m22 = 22.0; m3.m23 = 23.0; m3.m31 = 31.0; m3.m32 = 32.0; m3.m33 = 33.0; let expected_m3 = Matrix3::new(11.0, 12.0, 13.0, 21.0, 22.0, 23.0, 31.0, 32.0, 33.0); assert_eq!(expected_m3, m3); } #[test] fn kronecker() { let a = Matrix2x3::new(11, 12, 13, 21, 22, 23); let b = Matrix4x5::new( 110, 120, 130, 140, 150, 210, 220, 230, 240, 250, 310, 320, 330, 340, 350, 410, 420, 430, 440, 450, ); let expected = OMatrix::<_, U8, U15>::from_row_slice(&[ 1210, 1320, 1430, 1540, 1650, 1320, 1440, 1560, 1680, 1800, 1430, 1560, 1690, 1820, 1950, 2310, 2420, 2530, 2640, 2750, 2520, 2640, 2760, 2880, 3000, 2730, 2860, 2990, 3120, 3250, 3410, 3520, 3630, 3740, 3850, 3720, 3840, 3960, 4080, 4200, 4030, 4160, 4290, 4420, 4550, 4510, 4620, 4730, 4840, 4950, 4920, 5040, 5160, 5280, 5400, 5330, 5460, 5590, 5720, 5850, 2310, 2520, 2730, 2940, 3150, 2420, 2640, 2860, 3080, 3300, 2530, 2760, 2990, 3220, 3450, 4410, 4620, 4830, 5040, 5250, 4620, 4840, 5060, 5280, 5500, 4830, 5060, 5290, 5520, 5750, 6510, 6720, 6930, 7140, 7350, 6820, 7040, 7260, 7480, 7700, 7130, 7360, 7590, 7820, 8050, 8610, 8820, 9030, 9240, 9450, 9020, 9240, 9460, 9680, 9900, 9430, 9660, 9890, 10120, 10350, ]); let computed = a.kronecker(&b); assert_eq!(computed, expected); let a = Vector2::new(1, 2); let b = Vector3::new(10, 20, 30); let expected = Vector6::new(10, 20, 30, 20, 40, 60); assert_eq!(a.kronecker(&b), expected); let a = Vector2::new(1, 2); let b = RowVector4::new(10, 20, 30, 40); let expected = Matrix2x4::new(10, 20, 30, 40, 20, 40, 60, 80); assert_eq!(a.kronecker(&b), expected); } #[test] fn set_row_column() { let a = Matrix4x5::new( 11, 12, 13, 14, 15, 21, 22, 23, 24, 25, 31, 32, 33, 34, 35, 41, 42, 43, 44, 45, ); let expected1 = Matrix4x5::new( 11, 12, 13, 14, 15, 42, 43, 44, 45, 46, 31, 32, 33, 34, 35, 41, 42, 43, 44, 45, ); let expected2 = Matrix4x5::new( 11, 12, 100, 14, 15, 42, 43, 101, 45, 46, 31, 32, 102, 34, 35, 41, 42, 103, 44, 45, ); let row = RowVector5::new(42, 43, 44, 45, 46); let col = Vector4::new(100, 101, 102, 103); let mut computed = a; computed.set_row(1, &row); assert_eq!(expected1, computed); computed.set_column(2, &col); assert_eq!(expected2, computed); } #[test] fn partial_clamp() { // NOTE: from #401. let n = Vector2::new(1.5, 0.0); let min = Vector2::new(-75.0, -0.0); let max = Vector2::new(75.0, 0.0); let inter = na::partial_clamp(&n, &min, &max); assert_eq!(*inter.unwrap(), n); } #[test] fn partial_cmp() { let a = Vector2::new(1.0, 6.0); let b = Vector2::new(1.0, 3.0); let c = Vector2::new(2.0, 7.0); let d = Vector2::new(0.0, 7.0); assert_eq!(a.partial_cmp(&a), Some(Ordering::Equal)); assert_eq!(a.partial_cmp(&b), Some(Ordering::Greater)); assert_eq!(a.partial_cmp(&c), Some(Ordering::Less)); assert_eq!(a.partial_cmp(&d), None); } #[test] fn swizzle() { let a = Vector2::new(1.0f32, 2.0); let b = Vector3::new(1.0f32, 2.0, 3.0); let c = Vector4::new(1.0f32, 2.0, 3.0, 4.0); assert_eq!(a.xy(), Vector2::new(1.0, 2.0)); assert_eq!(a.yx(), Vector2::new(2.0, 1.0)); assert_eq!(a.xx(), Vector2::new(1.0, 1.0)); assert_eq!(a.yy(), Vector2::new(2.0, 2.0)); assert_eq!(a.xxx(), Vector3::new(1.0, 1.0, 1.0)); assert_eq!(a.yyy(), Vector3::new(2.0, 2.0, 2.0)); assert_eq!(a.xyx(), Vector3::new(1.0, 2.0, 1.0)); assert_eq!(a.yxy(), Vector3::new(2.0, 1.0, 2.0)); assert_eq!(b.xy(), Vector2::new(1.0, 2.0)); assert_eq!(b.yx(), Vector2::new(2.0, 1.0)); assert_eq!(b.xx(), Vector2::new(1.0, 1.0)); assert_eq!(b.yy(), Vector2::new(2.0, 2.0)); assert_eq!(b.xz(), Vector2::new(1.0, 3.0)); assert_eq!(b.zx(), Vector2::new(3.0, 1.0)); assert_eq!(b.yz(), Vector2::new(2.0, 3.0)); assert_eq!(b.zy(), Vector2::new(3.0, 2.0)); assert_eq!(b.zz(), Vector2::new(3.0, 3.0)); assert_eq!(b.xyz(), Vector3::new(1.0, 2.0, 3.0)); assert_eq!(b.xxx(), Vector3::new(1.0, 1.0, 1.0)); assert_eq!(b.yyy(), Vector3::new(2.0, 2.0, 2.0)); assert_eq!(b.zzz(), Vector3::new(3.0, 3.0, 3.0)); assert_eq!(b.zxy(), Vector3::new(3.0, 1.0, 2.0)); assert_eq!(b.zxz(), Vector3::new(3.0, 1.0, 3.0)); assert_eq!(b.zyz(), Vector3::new(3.0, 2.0, 3.0)); assert_eq!(c.xy(), Vector2::new(1.0, 2.0)); assert_eq!(c.yx(), Vector2::new(2.0, 1.0)); assert_eq!(c.xx(), Vector2::new(1.0, 1.0)); assert_eq!(c.yy(), Vector2::new(2.0, 2.0)); assert_eq!(c.xz(), Vector2::new(1.0, 3.0)); assert_eq!(c.zx(), Vector2::new(3.0, 1.0)); assert_eq!(c.yz(), Vector2::new(2.0, 3.0)); assert_eq!(c.zy(), Vector2::new(3.0, 2.0)); assert_eq!(c.zz(), Vector2::new(3.0, 3.0)); assert_eq!(c.xyz(), Vector3::new(1.0, 2.0, 3.0)); assert_eq!(c.xxx(), Vector3::new(1.0, 1.0, 1.0)); assert_eq!(c.yyy(), Vector3::new(2.0, 2.0, 2.0)); assert_eq!(c.zzz(), Vector3::new(3.0, 3.0, 3.0)); assert_eq!(c.zxy(), Vector3::new(3.0, 1.0, 2.0)); assert_eq!(c.zxz(), Vector3::new(3.0, 1.0, 3.0)); assert_eq!(c.zyz(), Vector3::new(3.0, 2.0, 3.0)); } #[cfg(feature = "proptest-support")] mod transposition_tests { use super::*; use crate::proptest::{dmatrix, matrix, vector4, PROPTEST_F64}; use proptest::{prop_assert, prop_assert_eq, proptest}; proptest! { #[test] fn transpose_transpose_is_self(m in matrix(PROPTEST_F64, Const::<2>, Const::<3>)) { prop_assert_eq!(m.transpose().transpose(), m) } #[test] fn transpose_mut_transpose_mut_is_self(m in matrix(PROPTEST_F64, Const::<3>, Const::<3>)) { let mut mm = m; mm.transpose_mut(); mm.transpose_mut(); prop_assert_eq!(m, mm) } #[test] fn transpose_transpose_is_id_dyn(m in dmatrix()) { prop_assert_eq!(m.transpose().transpose(), m) } #[test] fn check_transpose_components_dyn(m in dmatrix()) { let tr = m.transpose(); let (nrows, ncols) = m.shape(); prop_assert!(nrows == tr.shape().1 && ncols == tr.shape().0); for i in 0 .. nrows { for j in 0 .. ncols { prop_assert_eq!(m[(i, j)], tr[(j, i)]); } } } #[test] fn tr_mul_is_transpose_then_mul(m in matrix(PROPTEST_F64, Const::<4>, Const::<6>), v in vector4()) { prop_assert!(relative_eq!(m.transpose() * v, m.tr_mul(&v), epsilon = 1.0e-7)) } } } #[cfg(feature = "proptest-support")] mod inversion_tests { use super::*; use crate::proptest::*; use na::Matrix1; use proptest::{prop_assert, proptest}; proptest! { #[test] fn self_mul_inv_is_id_dim1(m in matrix1()) { if let Some(im) = m.try_inverse() { let id = Matrix1::one(); prop_assert!(relative_eq!(im * m, id, epsilon = 1.0e-7)); prop_assert!(relative_eq!(m * im, id, epsilon = 1.0e-7)); } } #[test] fn self_mul_inv_is_id_dim2(m in matrix2()) { if let Some(im) = m.try_inverse() { let id = Matrix2::one(); prop_assert!(relative_eq!(im * m, id, epsilon = 1.0e-7)); prop_assert!(relative_eq!(m * im, id, epsilon = 1.0e-7)); } } #[test] fn self_mul_inv_is_id_dim3(m in matrix3()) { if let Some(im) = m.try_inverse() { let id = Matrix3::one(); prop_assert!(relative_eq!(im * m, id, epsilon = 1.0e-7)); prop_assert!(relative_eq!(m * im, id, epsilon = 1.0e-7)); } } #[test] fn self_mul_inv_is_id_dim4(m in matrix4()) { if let Some(im) = m.try_inverse() { let id = Matrix4::one(); prop_assert!(relative_eq!(im * m, id, epsilon = 1.0e-7)); prop_assert!(relative_eq!(m * im, id, epsilon = 1.0e-7)); } } #[test] fn self_mul_inv_is_id_dim6(m in matrix6()) { if let Some(im) = m.try_inverse() { let id = Matrix6::one(); prop_assert!(relative_eq!(im * m, id, epsilon = 1.0e-7)); prop_assert!(relative_eq!(m * im, id, epsilon = 1.0e-7)); } } } } #[cfg(feature = "proptest-support")] mod normalization_tests { use crate::proptest::*; use proptest::{prop_assert, proptest}; proptest! { #[test] fn normalized_vec_norm_is_one(v in vector3()) { if let Some(nv) = v.try_normalize(1.0e-10) { prop_assert!(relative_eq!(nv.norm(), 1.0, epsilon = 1.0e-7)); } } #[test] fn normalized_vec_norm_is_one_dyn(v in dvector()) { if let Some(nv) = v.try_normalize(1.0e-10) { prop_assert!(relative_eq!(nv.norm(), 1.0, epsilon = 1.0e-7)); } } } } #[cfg(all(feature = "proptest-support", feature = "alga"))] // TODO: move this to alga ? mod finite_dim_inner_space_tests { use super::*; use crate::proptest::*; use alga::linear::FiniteDimInnerSpace; use proptest::collection::vec; use proptest::{prop_assert, proptest}; use std::fmt::Display; macro_rules! finite_dim_inner_space_test( ($($Vector: ident, $vstrategy: ident, $orthonormal_subspace: ident, $orthonormalization: ident);* $(;)*) => {$( proptest! { #[test] fn $orthonormal_subspace(vs in vec($vstrategy(), 0..10)) { let mut given_basis = vs.clone(); let given_basis_dim = $Vector::orthonormalize(&mut given_basis[..]); let mut ortho_basis = Vec::new(); $Vector::orthonormal_subspace_basis( &given_basis[.. given_basis_dim], |e| { ortho_basis.push(*e); true } ); prop_assert!(is_subspace_basis(&ortho_basis[..])); for v in vs { for b in &ortho_basis { prop_assert!(relative_eq!(v.dot(b), 0.0, epsilon = 1.0e-7)); } } } #[test] fn $orthonormalization(vs in vec($vstrategy(), 0..10)) { let mut basis = vs.clone(); let subdim = $Vector::orthonormalize(&mut basis[..]); prop_assert!(is_subspace_basis(&basis[.. subdim])); for mut e in vs { for b in &basis[.. subdim] { e -= e.dot(b) * b } // Any element of `e` must be a linear combination of the basis elements. prop_assert!(relative_eq!(e.norm(), 0.0, epsilon = 1.0e-7)); } } } )*} ); finite_dim_inner_space_test!( Vector1, vector1, orthonormal_subspace_basis1, orthonormalize1; Vector2, vector2, orthonormal_subspace_basis2, orthonormalize2; Vector3, vector3, orthonormal_subspace_basis3, orthonormalize3; Vector4, vector4, orthonormal_subspace_basis4, orthonormalize4; Vector5, vector5, orthonormal_subspace_basis5, orthonormalize5; Vector6, vector6, orthonormal_subspace_basis6, orthonormalize6; ); /* * * Helper functions. * */ fn is_subspace_basis + Display>( vs: &[T], ) -> bool { for i in 0..vs.len() { // Basis elements must be normalized. if !relative_eq!(vs[i].norm(), 1.0, epsilon = 1.0e-7) { println!("Non-zero basis element norm: {}", vs[i].norm()); return false; } for j in 0..i { // Basis elements must be orthogonal. if !relative_eq!(vs[i].dot(&vs[j]), 0.0, epsilon = 1.0e-7) { println!( "Non-orthogonal basis elements: {} ยท {} = {}", vs[i], vs[j], vs[i].dot(&vs[j]) ); return false; } } } true } } #[test] fn partial_eq_shape_mismatch() { let a = Matrix2::new(1, 2, 3, 4); let b = Matrix2x3::new(1, 2, 3, 4, 5, 6); assert_ne!(a, b); assert_ne!(b, a); } #[test] fn partial_eq_different_types() { // Ensure comparability of several types of Matrices let dynamic_mat = DMatrix::from_row_slice(2, 4, &[1, 2, 3, 4, 5, 6, 7, 8]); let static_mat = Matrix2x4::new(1, 2, 3, 4, 5, 6, 7, 8); let mut typenum_static_mat = OMatrix::, Const<4>>::zeros(); let mut view = typenum_static_mat.view_mut((0, 0), (2, 4)); view += static_mat; let fview_of_dmat = dynamic_mat.fixed_view::<2, 2>(0, 0); let dview_of_dmat = dynamic_mat.view((0, 0), (2, 2)); let fview_of_smat = static_mat.fixed_view::<2, 2>(0, 0); let dview_of_smat = static_mat.view((0, 0), (2, 2)); assert_eq!(dynamic_mat, static_mat); assert_eq!(static_mat, dynamic_mat); assert_eq!(dynamic_mat, view); assert_eq!(view, dynamic_mat); assert_eq!(static_mat, view); assert_eq!(view, static_mat); assert_eq!(fview_of_dmat, dview_of_dmat); assert_eq!(dview_of_dmat, fview_of_dmat); assert_eq!(fview_of_dmat, fview_of_smat); assert_eq!(fview_of_smat, fview_of_dmat); assert_eq!(fview_of_dmat, dview_of_smat); assert_eq!(dview_of_smat, fview_of_dmat); assert_eq!(dview_of_dmat, fview_of_smat); assert_eq!(fview_of_smat, dview_of_dmat); assert_eq!(dview_of_dmat, dview_of_smat); assert_eq!(dview_of_smat, dview_of_dmat); assert_eq!(fview_of_smat, dview_of_smat); assert_eq!(dview_of_smat, fview_of_smat); assert_ne!(dynamic_mat, dview_of_smat); assert_ne!(dview_of_smat, dynamic_mat); // TODO - implement those comparisons // assert_ne!(static_mat, typenum_static_mat); //assert_ne!(typenum_static_mat, static_mat); } fn generic_omatrix_to_string( vector: &nalgebra::OVector, matrix: &nalgebra::OMatrix, ) -> (String, String) where D: nalgebra::Dim, nalgebra::DefaultAllocator: nalgebra::base::allocator::Allocator, nalgebra::DefaultAllocator: nalgebra::base::allocator::Allocator, { (vector.to_string(), matrix.to_string()) } #[test] fn omatrix_to_string() { let dvec: nalgebra::DVector = nalgebra::dvector![1.0, 2.0]; let dmatr: nalgebra::DMatrix = nalgebra::dmatrix![1.0, 2.0; 3.0, 4.0]; let svec: nalgebra::SVector = nalgebra::vector![1.0, 2.0]; let smatr: nalgebra::SMatrix = nalgebra::matrix![1.0, 2.0; 3.0, 4.0]; assert_eq!( generic_omatrix_to_string(&dvec, &dmatr), (dvec.to_string(), dmatr.to_string()) ); assert_eq!( generic_omatrix_to_string(&svec, &smatr), (svec.to_string(), smatr.to_string()) ); } #[test] fn column_iteration() { // dynamic matrix let dmat = nalgebra::dmatrix![ 13,14,15; 23,24,25; 33,34,35; ]; let mut col_iter = dmat.column_iter(); assert_eq!(col_iter.next(), Some(dmat.column(0))); assert_eq!(col_iter.next(), Some(dmat.column(1))); assert_eq!(col_iter.next(), Some(dmat.column(2))); assert_eq!(col_iter.next(), None); // statically sized matrix let smat: nalgebra::SMatrix = nalgebra::matrix![1.0, 2.0; 3.0, 4.0]; let mut col_iter = smat.column_iter(); assert_eq!(col_iter.next(), Some(smat.column(0))); assert_eq!(col_iter.next(), Some(smat.column(1))); assert_eq!(col_iter.next(), None); } #[test] fn column_iteration_mut() { let mut dmat = nalgebra::dmatrix![ 13,14,15; 23,24,25; 33,34,35; ]; let mut cloned = dmat.clone(); let mut col_iter = dmat.column_iter_mut(); assert_eq!(col_iter.next(), Some(cloned.column_mut(0))); assert_eq!(col_iter.next(), Some(cloned.column_mut(1))); assert_eq!(col_iter.next(), Some(cloned.column_mut(2))); assert_eq!(col_iter.next(), None); // statically sized matrix let mut smat: nalgebra::SMatrix = nalgebra::matrix![1.0, 2.0; 3.0, 4.0]; let mut cloned = smat.clone(); let mut col_iter = smat.column_iter_mut(); assert_eq!(col_iter.next(), Some(cloned.column_mut(0))); assert_eq!(col_iter.next(), Some(cloned.column_mut(1))); assert_eq!(col_iter.next(), None); } #[test] fn column_iteration_double_ended() { let dmat = nalgebra::dmatrix![ 13,14,15,16,17; 23,24,25,26,27; 33,34,35,36,37; ]; let mut col_iter = dmat.column_iter(); assert_eq!(col_iter.next(), Some(dmat.column(0))); assert_eq!(col_iter.next(), Some(dmat.column(1))); assert_eq!(col_iter.next_back(), Some(dmat.column(4))); assert_eq!(col_iter.next_back(), Some(dmat.column(3))); assert_eq!(col_iter.next(), Some(dmat.column(2))); assert_eq!(col_iter.next_back(), None); assert_eq!(col_iter.next(), None); } #[test] fn column_iterator_double_ended_mut() { let mut dmat = nalgebra::dmatrix![ 13,14,15,16,17; 23,24,25,26,27; 33,34,35,36,37; ]; let mut cloned = dmat.clone(); let mut col_iter_mut = dmat.column_iter_mut(); assert_eq!(col_iter_mut.next(), Some(cloned.column_mut(0))); assert_eq!(col_iter_mut.next(), Some(cloned.column_mut(1))); assert_eq!(col_iter_mut.next_back(), Some(cloned.column_mut(4))); assert_eq!(col_iter_mut.next_back(), Some(cloned.column_mut(3))); assert_eq!(col_iter_mut.next(), Some(cloned.column_mut(2))); assert_eq!(col_iter_mut.next_back(), None); assert_eq!(col_iter_mut.next(), None); } #[test] fn test_inversion_failure_leaves_matrix4_unchanged() { let mut mat = na::Matrix4::new( 1.0, 2.0, 3.0, 4.0, 2.0, 4.0, 6.0, 8.0, 3.0, 6.0, 9.0, 12.0, 4.0, 8.0, 12.0, 16.0, ); let expected = mat.clone(); assert!(!mat.try_inverse_mut()); assert_eq!(mat, expected); } #[test] #[cfg(feature = "rayon")] fn parallel_column_iteration() { use nalgebra::dmatrix; use rayon::prelude::*; let dmat: DMatrix = dmatrix![ 13.,14.; 23.,24.; 33.,34.; ]; let cloned = dmat.clone(); // test that correct columns are iterated over dmat.par_column_iter().enumerate().for_each(|(idx, col)| { assert_eq!(col, cloned.column(idx)); }); // test that a more complex expression produces the same // result as the serial equivalent let par_result: f64 = dmat.par_column_iter().map(|col| col.norm()).sum(); let ser_result: f64 = dmat.column_iter().map(|col| col.norm()).sum(); assert_eq!(par_result, ser_result); // repeat this test using mutable iterators let mut dmat = dmat; dmat.par_column_iter_mut() .enumerate() .for_each(|(idx, col)| { assert_eq!(col, cloned.column(idx)); }); let par_mut_result: f64 = dmat.par_column_iter_mut().map(|col| col.norm()).sum(); assert_eq!(par_mut_result, ser_result); } #[test] #[cfg(feature = "rayon")] fn column_iteration_mut_double_ended() { let dmat = nalgebra::dmatrix![ 13,14,15,16,17; 23,24,25,26,27; 33,34,35,36,37; ]; let cloned = dmat.clone(); let mut col_iter = dmat.column_iter(); assert_eq!(col_iter.next(), Some(cloned.column(0))); assert_eq!(col_iter.next(), Some(cloned.column(1))); assert_eq!(col_iter.next_back(), Some(cloned.column(4))); assert_eq!(col_iter.next_back(), Some(cloned.column(3))); assert_eq!(col_iter.next(), Some(cloned.column(2))); assert_eq!(col_iter.next_back(), None); assert_eq!(col_iter.next(), None); } #[test] #[cfg(feature = "rayon")] fn parallel_column_iteration_mut() { use rayon::prelude::*; let mut first = DMatrix::::zeros(400, 300); let mut second = DMatrix::::zeros(400, 300); first .column_iter_mut() .enumerate() .for_each(|(idx, mut col)| col[idx] = 1.); second .par_column_iter_mut() .enumerate() .for_each(|(idx, mut col)| col[idx] = 1.); assert_eq!(first, second); assert_eq!(second, DMatrix::identity(400, 300)); }