From 01d1f9d24bff59d3d7aaf8251627e57584242a8f Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sun, 9 Dec 2018 11:22:21 +0100 Subject: [PATCH] Simplify the construction of DVector. Fix #377. --- src/base/alias_slice.rs | 36 +++---- src/base/construction.rs | 202 +++++++++++++++++++++++---------------- src/base/mod.rs | 3 + tests/core/matrix.rs | 16 ++-- 4 files changed, 148 insertions(+), 109 deletions(-) diff --git a/src/base/alias_slice.rs b/src/base/alias_slice.rs index 1b368c8e..790e4e59 100644 --- a/src/base/alias_slice.rs +++ b/src/base/alias_slice.rs @@ -175,24 +175,24 @@ pub type MatrixSliceXx6<'a, N, RStride = U1, CStride = Dynamic> = MatrixSliceMN<'a, N, Dynamic, U6, RStride, CStride>; /// A column vector slice with `D` rows. -pub type VectorSliceN<'a, N, D, Stride = U1> = - Matrix>; +pub type VectorSliceN<'a, N, D, RStride = U1, CStride = D> = + Matrix>; /// A column vector slice dynamic numbers of rows and columns. -pub type DVectorSlice<'a, N, Stride = U1> = VectorSliceN<'a, N, Dynamic, Stride>; +pub type DVectorSlice<'a, N, RStride = U1, CStride = Dynamic> = VectorSliceN<'a, N, Dynamic, RStride, CStride>; /// A 1D column vector slice. -pub type VectorSlice1<'a, N, Stride = U1> = VectorSliceN<'a, N, U1, Stride>; +pub type VectorSlice1<'a, N, RStride = U1, CStride = U1> = VectorSliceN<'a, N, U1, RStride, CStride>; /// A 2D column vector slice. -pub type VectorSlice2<'a, N, Stride = U1> = VectorSliceN<'a, N, U2, Stride>; +pub type VectorSlice2<'a, N, RStride = U1, CStride = U2> = VectorSliceN<'a, N, U2, RStride, CStride>; /// A 3D column vector slice. -pub type VectorSlice3<'a, N, Stride = U1> = VectorSliceN<'a, N, U3, Stride>; +pub type VectorSlice3<'a, N, RStride = U1, CStride = U3> = VectorSliceN<'a, N, U3, RStride, CStride>; /// A 4D column vector slice. -pub type VectorSlice4<'a, N, Stride = U1> = VectorSliceN<'a, N, U4, Stride>; +pub type VectorSlice4<'a, N, RStride = U1, CStride = U4> = VectorSliceN<'a, N, U4, RStride, CStride>; /// A 5D column vector slice. -pub type VectorSlice5<'a, N, Stride = U1> = VectorSliceN<'a, N, U5, Stride>; +pub type VectorSlice5<'a, N, RStride = U1, CStride = U5> = VectorSliceN<'a, N, U5, RStride, CStride>; /// A 6D column vector slice. -pub type VectorSlice6<'a, N, Stride = U1> = VectorSliceN<'a, N, U6, Stride>; +pub type VectorSlice6<'a, N, RStride = U1, CStride = U6> = VectorSliceN<'a, N, U6, RStride, CStride>; /* * @@ -367,21 +367,21 @@ pub type MatrixSliceMutXx6<'a, N, RStride = U1, CStride = Dynamic> = MatrixSliceMutMN<'a, N, Dynamic, U6, RStride, CStride>; /// A mutable column vector slice with `D` rows. -pub type VectorSliceMutN<'a, N, D, Stride = U1> = - Matrix>; +pub type VectorSliceMutN<'a, N, D, RStride = U1, CStride = D> = + Matrix>; /// A mutable column vector slice dynamic numbers of rows and columns. -pub type DVectorSliceMut<'a, N, Stride = U1> = VectorSliceMutN<'a, N, Dynamic, Stride>; +pub type DVectorSliceMut<'a, N, RStride = U1, CStride = Dynamic> = VectorSliceMutN<'a, N, Dynamic, RStride, CStride>; /// A 1D mutable column vector slice. -pub type VectorSliceMut1<'a, N, Stride = U1> = VectorSliceMutN<'a, N, U1, Stride>; +pub type VectorSliceMut1<'a, N, RStride = U1, CStride = U1> = VectorSliceMutN<'a, N, U1, RStride, CStride>; /// A 2D mutable column vector slice. -pub type VectorSliceMut2<'a, N, Stride = U1> = VectorSliceMutN<'a, N, U2, Stride>; +pub type VectorSliceMut2<'a, N, RStride = U1, CStride = U2> = VectorSliceMutN<'a, N, U2, RStride, CStride>; /// A 3D mutable column vector slice. -pub type VectorSliceMut3<'a, N, Stride = U1> = VectorSliceMutN<'a, N, U3, Stride>; +pub type VectorSliceMut3<'a, N, RStride = U1, CStride = U3> = VectorSliceMutN<'a, N, U3, RStride, CStride>; /// A 4D mutable column vector slice. -pub type VectorSliceMut4<'a, N, Stride = U1> = VectorSliceMutN<'a, N, U4, Stride>; +pub type VectorSliceMut4<'a, N, RStride = U1, CStride = U4> = VectorSliceMutN<'a, N, U4, RStride, CStride>; /// A 5D mutable column vector slice. -pub type VectorSliceMut5<'a, N, Stride = U1> = VectorSliceMutN<'a, N, U5, Stride>; +pub type VectorSliceMut5<'a, N, RStride = U1, CStride = U5> = VectorSliceMutN<'a, N, U5, RStride, CStride>; /// A 6D mutable column vector slice. -pub type VectorSliceMut6<'a, N, Stride = U1> = VectorSliceMutN<'a, N, U6, Stride>; +pub type VectorSliceMut6<'a, N, RStride = U1, CStride = U6> = VectorSliceMutN<'a, N, U6, RStride, CStride>; diff --git a/src/base/construction.rs b/src/base/construction.rs index 8adc90c1..1a53f33b 100644 --- a/src/base/construction.rs +++ b/src/base/construction.rs @@ -444,63 +444,6 @@ macro_rules! impl_constructors( Self::from_iterator_generic($($gargs, )* iter) } - /// Creates a matrix with its elements filled with the components provided by a slice - /// in row-major order. - /// - /// The order of elements in the slice must follow the usual mathematic writing, i.e., - /// row-by-row. - /// - /// # Example - /// ``` - /// # use nalgebra::{Matrix2x3, Vector3, DVector, DMatrix}; - /// # use std::iter; - /// - /// let v = Vector3::from_row_slice(&[0, 1, 2]); - /// // The additional argument represents the vector dimension. - /// let dv = DVector::from_row_slice(3, &[0, 1, 2]); - /// let m = Matrix2x3::from_row_slice(&[0, 1, 2, 3, 4, 5]); - /// // The two additional arguments represent the matrix dimensions. - /// let dm = DMatrix::from_row_slice(2, 3, &[0, 1, 2, 3, 4, 5]); - /// - /// assert!(v.x == 0 && v.y == 1 && v.z == 2); - /// assert!(dv[0] == 0 && dv[1] == 1 && dv[2] == 2); - /// assert!(m.m11 == 0 && m.m12 == 1 && m.m13 == 2 && - /// m.m21 == 3 && m.m22 == 4 && m.m23 == 5); - /// assert!(dm[(0, 0)] == 0 && dm[(0, 1)] == 1 && dm[(0, 2)] == 2 && - /// dm[(1, 0)] == 3 && dm[(1, 1)] == 4 && dm[(1, 2)] == 5); - /// ``` - #[inline] - pub fn from_row_slice($($args: usize,)* slice: &[N]) -> Self { - Self::from_row_slice_generic($($gargs, )* slice) - } - - /// Creates a matrix with its elements filled with the components provided by a slice - /// in column-major order. - /// - /// # Example - /// ``` - /// # use nalgebra::{Matrix2x3, Vector3, DVector, DMatrix}; - /// # use std::iter; - /// - /// let v = Vector3::from_column_slice(&[0, 1, 2]); - /// // The additional argument represents the vector dimension. - /// let dv = DVector::from_column_slice(3, &[0, 1, 2]); - /// let m = Matrix2x3::from_column_slice(&[0, 1, 2, 3, 4, 5]); - /// // The two additional arguments represent the matrix dimensions. - /// let dm = DMatrix::from_column_slice(2, 3, &[0, 1, 2, 3, 4, 5]); - /// - /// assert!(v.x == 0 && v.y == 1 && v.z == 2); - /// assert!(dv[0] == 0 && dv[1] == 1 && dv[2] == 2); - /// assert!(m.m11 == 0 && m.m12 == 2 && m.m13 == 4 && - /// m.m21 == 1 && m.m22 == 3 && m.m23 == 5); - /// assert!(dm[(0, 0)] == 0 && dm[(0, 1)] == 2 && dm[(0, 2)] == 4 && - /// dm[(1, 0)] == 1 && dm[(1, 1)] == 3 && dm[(1, 2)] == 5); - /// ``` - #[inline] - pub fn from_column_slice($($args: usize,)* slice: &[N]) -> Self { - Self::from_column_slice_generic($($gargs, )* slice) - } - /// Creates a matrix or vector filled with the results of a function applied to each of its /// component coordinates. /// @@ -612,32 +555,6 @@ macro_rules! impl_constructors( ) -> Self { Self::from_distribution_generic($($gargs, )* distribution, rng) } - - /// Creates a matrix backed by a given `Vec`. - /// - /// The output matrix is filled column-by-column. - /// - /// # Example - /// ``` - /// # use nalgebra::{DMatrix, Matrix2x3}; - /// - /// let m = Matrix2x3::from_vec(vec![0, 1, 2, 3, 4, 5]); - /// - /// assert!(m.m11 == 0 && m.m12 == 2 && m.m13 == 4 && - /// m.m21 == 1 && m.m22 == 3 && m.m23 == 5); - /// - /// - /// // The two additional arguments represent the matrix dimensions. - /// let dm = DMatrix::from_vec(2, 3, vec![0, 1, 2, 3, 4, 5]); - /// - /// assert!(dm[(0, 0)] == 0 && dm[(0, 1)] == 2 && dm[(0, 2)] == 4 && - /// dm[(1, 0)] == 1 && dm[(1, 1)] == 3 && dm[(1, 2)] == 5); - /// ``` - #[inline] - #[cfg(feature = "std")] - pub fn from_vec($($args: usize,)* data: Vec) -> Self { - Self::from_vec_generic($($gargs, )* data) - } } impl MatrixMN @@ -676,6 +593,125 @@ impl_constructors!(Dynamic, Dynamic; Dynamic::new(nrows), Dynamic::new(ncols); nrows, ncols); +/* + * + * Constructors that don't necessarily require all dimensions + * to be specified whon one dimension is already known. + * + */ +macro_rules! impl_constructors_from_data( + ($data: ident; $($Dims: ty),*; $(=> $DimIdent: ident: $DimBound: ident),*; $($gargs: expr),*; $($args: ident),*) => { + impl MatrixMN + where DefaultAllocator: Allocator { + /// Creates a matrix with its elements filled with the components provided by a slice + /// in row-major order. + /// + /// The order of elements in the slice must follow the usual mathematic writing, i.e., + /// row-by-row. + /// + /// # Example + /// ``` + /// # use nalgebra::{Matrix2x3, Vector3, DVector, DMatrix}; + /// # use std::iter; + /// + /// let v = Vector3::from_row_slice(&[0, 1, 2]); + /// // The additional argument represents the vector dimension. + /// let dv = DVector::from_row_slice(3, &[0, 1, 2]); + /// let m = Matrix2x3::from_row_slice(&[0, 1, 2, 3, 4, 5]); + /// // The two additional arguments represent the matrix dimensions. + /// let dm = DMatrix::from_row_slice(2, 3, &[0, 1, 2, 3, 4, 5]); + /// + /// assert!(v.x == 0 && v.y == 1 && v.z == 2); + /// assert!(dv[0] == 0 && dv[1] == 1 && dv[2] == 2); + /// assert!(m.m11 == 0 && m.m12 == 1 && m.m13 == 2 && + /// m.m21 == 3 && m.m22 == 4 && m.m23 == 5); + /// assert!(dm[(0, 0)] == 0 && dm[(0, 1)] == 1 && dm[(0, 2)] == 2 && + /// dm[(1, 0)] == 3 && dm[(1, 1)] == 4 && dm[(1, 2)] == 5); + /// ``` + #[inline] + pub fn from_row_slice($($args: usize,)* $data: &[N]) -> Self { + Self::from_row_slice_generic($($gargs, )* $data) + } + + /// Creates a matrix with its elements filled with the components provided by a slice + /// in column-major order. + /// + /// # Example + /// ``` + /// # use nalgebra::{Matrix2x3, Vector3, DVector, DMatrix}; + /// # use std::iter; + /// + /// let v = Vector3::from_column_slice(&[0, 1, 2]); + /// // The additional argument represents the vector dimension. + /// let dv = DVector::from_column_slice(3, &[0, 1, 2]); + /// let m = Matrix2x3::from_column_slice(&[0, 1, 2, 3, 4, 5]); + /// // The two additional arguments represent the matrix dimensions. + /// let dm = DMatrix::from_column_slice(2, 3, &[0, 1, 2, 3, 4, 5]); + /// + /// assert!(v.x == 0 && v.y == 1 && v.z == 2); + /// assert!(dv[0] == 0 && dv[1] == 1 && dv[2] == 2); + /// assert!(m.m11 == 0 && m.m12 == 2 && m.m13 == 4 && + /// m.m21 == 1 && m.m22 == 3 && m.m23 == 5); + /// assert!(dm[(0, 0)] == 0 && dm[(0, 1)] == 2 && dm[(0, 2)] == 4 && + /// dm[(1, 0)] == 1 && dm[(1, 1)] == 3 && dm[(1, 2)] == 5); + /// ``` + #[inline] + pub fn from_column_slice($($args: usize,)* $data: &[N]) -> Self { + Self::from_column_slice_generic($($gargs, )* $data) + } + + /// Creates a matrix backed by a given `Vec`. + /// + /// The output matrix is filled column-by-column. + /// + /// # Example + /// ``` + /// # use nalgebra::{DMatrix, Matrix2x3}; + /// + /// let m = Matrix2x3::from_vec(vec![0, 1, 2, 3, 4, 5]); + /// + /// assert!(m.m11 == 0 && m.m12 == 2 && m.m13 == 4 && + /// m.m21 == 1 && m.m22 == 3 && m.m23 == 5); + /// + /// + /// // The two additional arguments represent the matrix dimensions. + /// let dm = DMatrix::from_vec(2, 3, vec![0, 1, 2, 3, 4, 5]); + /// + /// assert!(dm[(0, 0)] == 0 && dm[(0, 1)] == 2 && dm[(0, 2)] == 4 && + /// dm[(1, 0)] == 1 && dm[(1, 1)] == 3 && dm[(1, 2)] == 5); + /// ``` + #[inline] + #[cfg(feature = "std")] + pub fn from_vec($($args: usize,)* $data: Vec) -> Self { + Self::from_vec_generic($($gargs, )* $data) + } + } + } +); + +// FIXME: this is not very pretty. We could find a better call syntax. +impl_constructors_from_data!(data; R, C; // Arguments for Matrix + => R: DimName, => C: DimName; // Type parameters for impl + R::name(), C::name(); // Arguments for `_generic` constructors. + ); // Arguments for non-generic constructors. + +impl_constructors_from_data!(data; R, Dynamic; + => R: DimName; + R::name(), Dynamic::new(data.len() / R::dim()); + ); + +impl_constructors_from_data!(data; Dynamic, C; + => C: DimName; + Dynamic::new(data.len() / C::dim()), C::name(); + ); + +impl_constructors_from_data!(data; Dynamic, Dynamic; + ; + Dynamic::new(nrows), Dynamic::new(ncols); + nrows, ncols); + + + /* * * Zero, One, Rand traits. diff --git a/src/base/mod.rs b/src/base/mod.rs index e7240fb3..be54eb6c 100644 --- a/src/base/mod.rs +++ b/src/base/mod.rs @@ -29,6 +29,8 @@ mod properties; mod scalar; mod swizzle; mod unit; +mod statistics; +pub mod norm; #[doc(hidden)] pub mod helper; @@ -36,6 +38,7 @@ pub mod helper; pub use self::matrix::*; pub use self::scalar::*; pub use self::unit::*; +pub use self::norm::*; pub use self::default_allocator::*; pub use self::dimension::*; diff --git a/tests/core/matrix.rs b/tests/core/matrix.rs index e3fa2bdb..3b624c69 100644 --- a/tests/core/matrix.rs +++ b/tests/core/matrix.rs @@ -195,10 +195,10 @@ fn from_columns() { #[test] fn from_columns_dynamic() { let columns = &[ - DVector::from_row_slice(3, &[11, 21, 31]), - DVector::from_row_slice(3, &[12, 22, 32]), - DVector::from_row_slice(3, &[13, 23, 33]), - DVector::from_row_slice(3, &[14, 24, 34]), + 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]); @@ -233,8 +233,8 @@ fn from_not_enough_columns() { #[should_panic] fn from_rows_with_different_dimensions() { let columns = &[ - DVector::from_row_slice(3, &[11, 21, 31]), - DVector::from_row_slice(3, &[12, 22, 32, 33]), + DVector::from_row_slice(&[11, 21, 31]), + DVector::from_row_slice(&[12, 22, 32, 33]), ]; let _ = DMatrix::from_columns(columns); @@ -272,8 +272,8 @@ 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(3, &[1.0, 2.0, 3.0]); - let expected_b = DVector::from_row_slice(4, &[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);