Implement From<&Matrix> for MatrixSlice

This commit is contained in:
Andreas Longva 2019-11-04 17:53:21 +01:00 committed by Sébastien Crozet
parent 6f1e924e40
commit a05aa313da
2 changed files with 147 additions and 0 deletions

View File

@ -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<N1, N2, R1, C1, R2, C2> SubsetOf<MatrixMN<N2, R2, C2>> for MatrixMN<N1, R1, C1>
@ -424,3 +425,60 @@ where
matrix_slice.into_owned()
}
}
impl<'a, N, R, C, RSlice, CSlice, S> From<&'a Matrix<N, R, C, S>>
for MatrixSlice<'a, N, RSlice, CSlice, S::RStride, S::CStride>
where
N: Scalar,
R: Dim,
C: Dim,
RSlice: Dim,
CSlice: Dim,
S: Storage<N, R, C>,
ShapeConstraint: DimEq<R, RSlice> + DimEq<C, CSlice>
{
fn from(m: &'a Matrix<N, R, C, S>) -> 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<N, R, C, S>>
for MatrixSlice<'a, N, RSlice, CSlice, S::RStride, S::CStride>
where
N: Scalar,
R: Dim,
C: Dim,
RSlice: Dim,
CSlice: Dim,
S: Storage<N, R, C>,
ShapeConstraint: DimEq<R, RSlice> + DimEq<C, CSlice>
{
fn from(m: &'a mut Matrix<N, R, C, S>) -> 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<N, R, C, S>>
for MatrixSliceMut<'a, N, RSlice, CSlice, S::RStride, S::CStride>
where
N: Scalar,
R: Dim,
C: Dim,
RSlice: Dim,
CSlice: Dim,
S: StorageMut<N, R, C>,
ShapeConstraint: DimEq<R, RSlice> + DimEq<C, CSlice>
{
fn from(m: &'a mut Matrix<N, R, C, S>) -> 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))
}
}

View File

@ -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<f64>, v: Vector3<f64>, p: Point3<f64>) -> 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());
}
}