diff --git a/src/base/conversion.rs b/src/base/conversion.rs index 4c5bb017..36ac43c1 100644 --- a/src/base/conversion.rs +++ b/src/base/conversion.rs @@ -21,6 +21,7 @@ use crate::base::storage::{ContiguousStorage, ContiguousStorageMut, Storage, Sto #[cfg(any(feature = "std", feature = "alloc"))] use crate::base::VecStorage; use crate::base::{DefaultAllocator, Matrix, ArrayStorage, MatrixMN, MatrixSlice, MatrixSliceMut, Scalar}; +use crate::constraint::DimEq; // FIXME: too bad this won't work allo slice conversions. impl SubsetOf> for MatrixMN @@ -424,3 +425,60 @@ where matrix_slice.into_owned() } } + +impl<'a, N, R, C, RSlice, CSlice, S> From<&'a Matrix> +for MatrixSlice<'a, N, RSlice, CSlice, S::RStride, S::CStride> + where + N: Scalar, + R: Dim, + C: Dim, + RSlice: Dim, + CSlice: Dim, + S: Storage, + ShapeConstraint: DimEq + DimEq +{ + fn from(m: &'a Matrix) -> Self { + let (row, col) = m.data.shape(); + let row_slice = RSlice::from_usize(row.value()); + let col_slice = CSlice::from_usize(col.value()); + m.generic_slice((0, 0), (row_slice, col_slice)) + } +} + +impl<'a, N, R, C, RSlice, CSlice, S> From<&'a mut Matrix> +for MatrixSlice<'a, N, RSlice, CSlice, S::RStride, S::CStride> + where + N: Scalar, + R: Dim, + C: Dim, + RSlice: Dim, + CSlice: Dim, + S: Storage, + ShapeConstraint: DimEq + DimEq +{ + fn from(m: &'a mut Matrix) -> Self { + let (row, col) = m.data.shape(); + let row_slice = RSlice::from_usize(row.value()); + let col_slice = CSlice::from_usize(col.value()); + m.generic_slice((0, 0), (row_slice, col_slice)) + } +} + +impl<'a, N, R, C, RSlice, CSlice, S> From<&'a mut Matrix> +for MatrixSliceMut<'a, N, RSlice, CSlice, S::RStride, S::CStride> + where + N: Scalar, + R: Dim, + C: Dim, + RSlice: Dim, + CSlice: Dim, + S: StorageMut, + ShapeConstraint: DimEq + DimEq +{ + fn from(m: &'a mut Matrix) -> Self { + let (row, col) = m.data.shape(); + let row_slice = RSlice::from_usize(row.value()); + let col_slice = CSlice::from_usize(col.value()); + m.generic_slice_mut((0, 0), (row_slice, col_slice)) + } +} \ No newline at end of file diff --git a/tests/core/conversion.rs b/tests/core/conversion.rs index f8be8588..20954a25 100644 --- a/tests/core/conversion.rs +++ b/tests/core/conversion.rs @@ -8,6 +8,8 @@ use na::{ RowVector4, RowVector5, RowVector6, Similarity3, Transform3, Translation3, UnitQuaternion, Vector1, Vector2, Vector3, Vector4, Vector5, Vector6, }; +use na::{U3, U4}; +use na::{DMatrix, MatrixSlice, MatrixSliceMut, DMatrixSlice, DMatrixSliceMut}; quickcheck!{ fn translation_conversion(t: Translation3, v: Vector3, p: Point3) -> bool { @@ -250,3 +252,90 @@ array_matrix_conversion!( array_matrix_conversion_6_5, Matrix6x5, (6, 5); array_matrix_conversion_6_6, Matrix6, (6, 6); ); + +#[test] +fn matrix_slice_from_matrix_ref() { + let a = Matrix3x4::new(11.0, 12.0, 13.0, 14.0, + 21.0, 22.0, 23.0, 24.0, + 31.0, 32.0, 33.0, 34.0); + + // TODO: What's a more idiomatic/better way to convert a static matrix to a dynamic one? + let d = DMatrix::from(a.get((0..a.nrows(), 0..a.ncols())).unwrap()); + + // Note: these have to be macros, and not functions, because the input type is different + // across the different tests. Moreover, the output type depends on the stride of the input, + // which is different for static and dynamic matrices. + macro_rules! dynamic_slice { ($mref:expr) => { DMatrixSlice::from($mref) } } + macro_rules! dynamic_slice_mut { ($mref:expr) => { DMatrixSliceMut::from($mref) } } + macro_rules! fixed_slice { ($mref:expr) => { MatrixSlice::<_, U3, U4, _, _>::from($mref)} }; + macro_rules! fixed_slice_mut { + ($mref:expr) => { MatrixSliceMut::<_, U3, U4, _, _>::from($mref) } + }; + + // TODO: The `into_owned()` is a result of `PartialEq` not being implemented for different + // Self and RHS. See issue #674. Once this is implemented, we can remove `into_owned` + // from the below tests. + + // Construct slices from reference to a + { + assert_eq!(a, fixed_slice!(&a).into_owned()); + assert_eq!(d, dynamic_slice!(&a).into_owned()); + } + + // Construct slices from mutable reference to a + { + let mut a_clone = a.clone(); + assert_eq!(a, fixed_slice!(&mut a_clone).into_owned()); + assert_eq!(d, dynamic_slice!(&mut a_clone).into_owned()); + } + + // Construct mutable slices from mutable reference to a + { + let mut a_clone = a.clone(); + assert_eq!(a, fixed_slice_mut!(&mut a_clone).into_owned()); + assert_eq!(d, dynamic_slice_mut!(&mut a_clone).into_owned()); + } + + // Construct slices from reference to d + { + assert_eq!(a, fixed_slice!(&d).into_owned()); + assert_eq!(d, dynamic_slice!(&d).into_owned()); + } + + // Construct slices from mutable reference to d + { + let mut d_clone = a.clone(); + assert_eq!(a, fixed_slice!(&mut d_clone).into_owned()); + assert_eq!(d, dynamic_slice!(&mut d_clone).into_owned()); + } + + // Construct mutable slices from mutable reference to d + { + let mut d_clone = d.clone(); + assert_eq!(a, fixed_slice_mut!(&mut d_clone).into_owned()); + assert_eq!(d, dynamic_slice_mut!(&mut d_clone).into_owned()); + } + + // Construct slices from a slice of a + { + let mut a_slice = fixed_slice!(&a); + assert_eq!(a, fixed_slice!(&a_slice).into_owned()); + assert_eq!(a, fixed_slice!(&mut a_slice).into_owned()); + assert_eq!(d, dynamic_slice!(&a_slice).into_owned()); + assert_eq!(d, dynamic_slice!(&mut a_slice).into_owned()); + } + + // Construct slices from a slice mut of a + { + // Need a clone of a here, so that we can both have a mutable borrow and compare equality + let mut a_clone = a.clone(); + let mut a_slice = fixed_slice_mut!(&mut a_clone); + + assert_eq!(a, fixed_slice!(&a_slice).into_owned()); + assert_eq!(a, fixed_slice!(&mut a_slice).into_owned()); + assert_eq!(d, dynamic_slice!(&a_slice).into_owned()); + assert_eq!(d, dynamic_slice!(&mut a_slice).into_owned()); + assert_eq!(a, fixed_slice_mut!(&mut a_slice).into_owned()); + assert_eq!(d, dynamic_slice_mut!(&mut a_slice).into_owned()); + } +}