From cc2a70664da7523f2f529272f6831ce6399a33e4 Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sun, 9 Dec 2018 11:21:15 +0100 Subject: [PATCH 01/14] Add statistics functions: sum, variance, mean. --- src/base/statistics.rs | 163 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 src/base/statistics.rs diff --git a/src/base/statistics.rs b/src/base/statistics.rs new file mode 100644 index 00000000..8f95e447 --- /dev/null +++ b/src/base/statistics.rs @@ -0,0 +1,163 @@ +use ::{Real, Dim, Matrix, VectorN, RowVectorN, DefaultAllocator, U1, VectorSliceN}; +use storage::Storage; +use allocator::Allocator; + +impl> Matrix { + #[inline] + pub fn compress_rows(&self, f: impl Fn(VectorSliceN) -> N) -> RowVectorN + where DefaultAllocator: Allocator { + + let ncols = self.data.shape().1; + let mut res = unsafe { RowVectorN::new_uninitialized_generic(U1, ncols) }; + + for i in 0..ncols.value() { + // FIXME: avoid bound checking of column. + unsafe { *res.get_unchecked_mut(0, i) = f(self.column(i)); } + } + + res + } + + #[inline] + pub fn compress_rows_tr(&self, f: impl Fn(VectorSliceN) -> N) -> VectorN + where DefaultAllocator: Allocator { + + let ncols = self.data.shape().1; + let mut res = unsafe { VectorN::new_uninitialized_generic(ncols, U1) }; + + for i in 0..ncols.value() { + // FIXME: avoid bound checking of column. + unsafe { *res.vget_unchecked_mut(i) = f(self.column(i)); } + } + + res + } + + #[inline] + pub fn compress_columns(&self, init: VectorN, f: impl Fn(&mut VectorN, VectorSliceN)) -> VectorN + where DefaultAllocator: Allocator { + let mut res = init; + + for i in 0..self.ncols() { + f(&mut res, self.column(i)) + } + + res + } +} + +impl> Matrix { + /* + * + * Sum computation. + * + */ + #[inline] + pub fn sum(&self) -> N { + self.iter().cloned().fold(N::zero(), |a, b| a + b) + } + + #[inline] + pub fn row_sum(&self) -> RowVectorN + where DefaultAllocator: Allocator { + self.compress_rows(|col| col.sum()) + } + + #[inline] + pub fn row_sum_tr(&self) -> VectorN + where DefaultAllocator: Allocator { + self.compress_rows_tr(|col| col.sum()) + } + + #[inline] + pub fn column_sum(&self) -> VectorN + where DefaultAllocator: Allocator { + let nrows = self.data.shape().0; + self.compress_columns(VectorN::zeros_generic(nrows, U1), |out, col| { + out.axpy(N::one(), &col, N::one()) + }) + } + + /* + * + * Variance computation. + * + */ + #[inline] + pub fn variance(&self) -> N { + if self.len() == 0 { + N::zero() + } else { + let val = self.iter().cloned().fold((N::zero(), N::zero()), |a, b| (a.0 + b * b, a.1 + b)); + let denom = N::one() / ::convert::<_, N>(self.len() as f64); + val.0 * denom - (val.1 * denom) * (val.1 * denom) + } + } + + #[inline] + pub fn row_variance(&self) -> RowVectorN + where DefaultAllocator: Allocator { + self.compress_rows(|col| col.variance()) + } + + #[inline] + pub fn row_variance_tr(&self) -> VectorN + where DefaultAllocator: Allocator { + self.compress_rows_tr(|col| col.variance()) + } + + #[inline] + pub fn column_variance(&self) -> VectorN + where DefaultAllocator: Allocator { + let (nrows, ncols) = self.data.shape(); + + let mut mean = self.column_mean(); + mean.apply(|e| -(e * e)); + + let denom = N::one() / ::convert::<_, N>(ncols.value() as f64); + self.compress_columns(mean, |out, col| { + for i in 0..nrows.value() { + unsafe { + let val = col.vget_unchecked(i); + *out.vget_unchecked_mut(i) += denom * *val * *val + } + } + }) + } + + /* + * + * Mean computation. + * + */ + #[inline] + pub fn mean(&self) -> N { + if self.len() == 0 { + N::zero() + } else { + self.sum() / ::convert(self.len() as f64) + } + } + + #[inline] + pub fn row_mean(&self) -> RowVectorN + where DefaultAllocator: Allocator { + self.compress_rows(|col| col.mean()) + } + + #[inline] + pub fn row_mean_tr(&self) -> VectorN + where DefaultAllocator: Allocator { + self.compress_rows_tr(|col| col.mean()) + } + + #[inline] + pub fn column_mean(&self) -> VectorN + where DefaultAllocator: Allocator { + let (nrows, ncols) = self.data.shape(); + let denom = N::one() / ::convert::<_, N>(ncols.value() as f64); + self.compress_columns(VectorN::zeros_generic(nrows, U1), |out, col| { + out.axpy(denom, &col, N::one()) + }) + } +} \ No newline at end of file From 660b868603c85b30eeb10c053b8ade173eb8d9f0 Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sun, 9 Dec 2018 11:21:24 +0100 Subject: [PATCH 02/14] Add more general norms and metrics. Fix #258. --- src/base/matrix.rs | 138 ++++++++++++------------------ src/base/norm.rs | 203 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 254 insertions(+), 87 deletions(-) create mode 100644 src/base/norm.rs diff --git a/src/base/matrix.rs b/src/base/matrix.rs index 57229153..d9c03b54 100644 --- a/src/base/matrix.rs +++ b/src/base/matrix.rs @@ -493,6 +493,57 @@ impl> Matrix { res } + /// Folds a function `f` on each entry of `self`. + #[inline] + pub fn fold(&self, init: Acc, mut f: impl FnMut(Acc, N) -> Acc) -> Acc { + let (nrows, ncols) = self.data.shape(); + + let mut res = init; + + for j in 0..ncols.value() { + for i in 0..nrows.value() { + unsafe { + let a = *self.data.get_unchecked(i, j); + res = f(res, a) + } + } + } + + res + } + + /// Folds a function `f` on each pairs of entries from `self` and `rhs`. + #[inline] + pub fn zip_fold(&self, rhs: &Matrix, init: Acc, mut f: impl FnMut(Acc, N, N2) -> Acc) -> Acc + where + N2: Scalar, + R2: Dim, + C2: Dim, + S2: Storage, + ShapeConstraint: SameNumberOfRows + SameNumberOfColumns + { + let (nrows, ncols) = self.data.shape(); + + let mut res = init; + + assert!( + (nrows.value(), ncols.value()) == rhs.shape(), + "Matrix simultaneous traversal error: dimension mismatch." + ); + + for j in 0..ncols.value() { + for i in 0..nrows.value() { + unsafe { + let a = *self.data.get_unchecked(i, j); + let b = *rhs.data.get_unchecked(i, j); + res = f(res, a, b) + } + } + } + + res + } + /// Transposes `self` and store the result into `out`. #[inline] pub fn transpose_to(&self, out: &mut Matrix) @@ -1251,67 +1302,6 @@ impl> Matrix { } } -impl> Matrix { - /// The squared L2 norm of this vector. - #[inline] - pub fn norm_squared(&self) -> N { - let mut res = N::zero(); - - for i in 0..self.ncols() { - let col = self.column(i); - res += col.dot(&col) - } - - res - } - - /// The L2 norm of this matrix. - #[inline] - pub fn norm(&self) -> N { - self.norm_squared().sqrt() - } - - /// A synonym for the norm of this matrix. - /// - /// Aka the length. - /// - /// This function is simply implemented as a call to `norm()` - #[inline] - pub fn magnitude(&self) -> N { - self.norm() - } - - /// A synonym for the squared norm of this matrix. - /// - /// Aka the squared length. - /// - /// This function is simply implemented as a call to `norm_squared()` - #[inline] - pub fn magnitude_squared(&self) -> N { - self.norm_squared() - } - - /// Returns a normalized version of this matrix. - #[inline] - pub fn normalize(&self) -> MatrixMN - where DefaultAllocator: Allocator { - self / self.norm() - } - - /// Returns a normalized version of this matrix unless its norm as smaller or equal to `eps`. - #[inline] - pub fn try_normalize(&self, min_norm: N) -> Option> - where DefaultAllocator: Allocator { - let n = self.norm(); - - if n <= min_norm { - None - } else { - Some(self / n) - } - } -} - impl> Vector { @@ -1386,32 +1376,6 @@ impl> Unit> { } } -impl> Matrix { - /// Normalizes this matrix in-place and returns its norm. - #[inline] - pub fn normalize_mut(&mut self) -> N { - let n = self.norm(); - *self /= n; - - n - } - - /// Normalizes this matrix in-place or does nothing if its norm is smaller or equal to `eps`. - /// - /// If the normalization succeeded, returns the old normal of this matrix. - #[inline] - pub fn try_normalize_mut(&mut self, min_norm: N) -> Option { - let n = self.norm(); - - if n <= min_norm { - None - } else { - *self /= n; - Some(n) - } - } -} - impl AbsDiffEq for Unit> where N: Scalar + AbsDiffEq, diff --git a/src/base/norm.rs b/src/base/norm.rs new file mode 100644 index 00000000..6e392bd5 --- /dev/null +++ b/src/base/norm.rs @@ -0,0 +1,203 @@ +use num::{Signed, Zero}; +use std::cmp::PartialOrd; + +use allocator::Allocator; +use ::{Real, Scalar}; +use storage::{Storage, StorageMut}; +use base::{DefaultAllocator, Matrix, Dim, MatrixMN}; +use constraint::{SameNumberOfRows, SameNumberOfColumns, ShapeConstraint}; + + +// FIXME: this should be be a trait on alga? +pub trait Norm { + fn norm(&self, m: &Matrix) -> N + where R: Dim, C: Dim, S: Storage; + fn metric_distance(&self, m1: &Matrix, m2: &Matrix) -> N + where R1: Dim, C1: Dim, S1: Storage, + R2: Dim, C2: Dim, S2: Storage, + ShapeConstraint: SameNumberOfRows + SameNumberOfColumns; +} + +/// Euclidean norm. +pub struct EuclideanNorm; +/// Lp norm. +pub struct LpNorm(pub i32); +/// L-infinite norm aka. Chebytchev norm aka. uniform norm aka. suppremum norm. +pub struct UniformNorm; + +impl Norm for EuclideanNorm { + #[inline] + fn norm(&self, m: &Matrix) -> N + where R: Dim, C: Dim, S: Storage { + m.norm_squared().sqrt() + } + + #[inline] + fn metric_distance(&self, m1: &Matrix, m2: &Matrix) -> N + where R1: Dim, C1: Dim, S1: Storage, + R2: Dim, C2: Dim, S2: Storage, + ShapeConstraint: SameNumberOfRows + SameNumberOfColumns { + m1.zip_fold(m2, N::zero(), |acc, a, b| { + let diff = a - b; + acc + diff * diff + }).sqrt() + } +} + +impl Norm for LpNorm { + #[inline] + fn norm(&self, m: &Matrix) -> N + where R: Dim, C: Dim, S: Storage { + m.fold(N::zero(), |a, b| { + a + b.abs().powi(self.0) + }).powf(::convert(1.0 / (self.0 as f64))) + } + + #[inline] + fn metric_distance(&self, m1: &Matrix, m2: &Matrix) -> N + where R1: Dim, C1: Dim, S1: Storage, + R2: Dim, C2: Dim, S2: Storage, + ShapeConstraint: SameNumberOfRows + SameNumberOfColumns { + m1.zip_fold(m2, N::zero(), |acc, a, b| { + let diff = a - b; + acc + diff.abs().powi(self.0) + }).powf(::convert(1.0 / (self.0 as f64))) + } +} + +impl Norm for UniformNorm { + #[inline] + fn norm(&self, m: &Matrix) -> N + where R: Dim, C: Dim, S: Storage { + m.amax() + } + + #[inline] + fn metric_distance(&self, m1: &Matrix, m2: &Matrix) -> N + where R1: Dim, C1: Dim, S1: Storage, + R2: Dim, C2: Dim, S2: Storage, + ShapeConstraint: SameNumberOfRows + SameNumberOfColumns { + m1.zip_fold(m2, N::zero(), |acc, a, b| { + let val = (a - b).abs(); + if val > acc { + val + } else { + acc + } + }) + } +} + + +impl> Matrix { + /// The squared L2 norm of this vector. + #[inline] + pub fn norm_squared(&self) -> N { + let mut res = N::zero(); + + for i in 0..self.ncols() { + let col = self.column(i); + res += col.dot(&col) + } + + res + } + + /// The L2 norm of this matrix. + #[inline] + pub fn norm(&self) -> N { + self.norm_squared().sqrt() + } + + /// Computes the metric distance between `self` and `rhs` using the Euclidean metric. + #[inline] + pub fn metric_distance(&self, rhs: &Matrix) -> N + where R2: Dim, C2: Dim, S2: Storage, + ShapeConstraint: SameNumberOfRows + SameNumberOfColumns { + self.apply_metric_distance(rhs, &EuclideanNorm) + } + + #[inline] + pub fn apply_norm(&self, norm: &impl Norm) -> N { + norm.norm(self) + } + + #[inline] + pub fn apply_metric_distance(&self, rhs: &Matrix, norm: &impl Norm) -> N + where R2: Dim, C2: Dim, S2: Storage, + ShapeConstraint: SameNumberOfRows + SameNumberOfColumns { + norm.metric_distance(self,rhs) + } + + /// The Lp norm of this matrix. + #[inline] + pub fn lp_norm(&self, p: i32) -> N { + self.apply_norm(&LpNorm(p)) + } + + /// A synonym for the norm of this matrix. + /// + /// Aka the length. + /// + /// This function is simply implemented as a call to `norm()` + #[inline] + pub fn magnitude(&self) -> N { + self.norm() + } + + /// A synonym for the squared norm of this matrix. + /// + /// Aka the squared length. + /// + /// This function is simply implemented as a call to `norm_squared()` + #[inline] + pub fn magnitude_squared(&self) -> N { + self.norm_squared() + } + + /// Returns a normalized version of this matrix. + #[inline] + pub fn normalize(&self) -> MatrixMN + where DefaultAllocator: Allocator { + self / self.norm() + } + + /// Returns a normalized version of this matrix unless its norm as smaller or equal to `eps`. + #[inline] + pub fn try_normalize(&self, min_norm: N) -> Option> + where DefaultAllocator: Allocator { + let n = self.norm(); + + if n <= min_norm { + None + } else { + Some(self / n) + } + } +} + +impl> Matrix { + /// Normalizes this matrix in-place and returns its norm. + #[inline] + pub fn normalize_mut(&mut self) -> N { + let n = self.norm(); + *self /= n; + + n + } + + /// Normalizes this matrix in-place or does nothing if its norm is smaller or equal to `eps`. + /// + /// If the normalization succeeded, returns the old normal of this matrix. + #[inline] + pub fn try_normalize_mut(&mut self, min_norm: N) -> Option { + let n = self.norm(); + + if n <= min_norm { + None + } else { + *self /= n; + Some(n) + } + } +} \ No newline at end of file From 01d1f9d24bff59d3d7aaf8251627e57584242a8f Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sun, 9 Dec 2018 11:22:21 +0100 Subject: [PATCH 03/14] 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); From bba1f48e810c4e2391ec82b88d7f948961ad5463 Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sun, 9 Dec 2018 12:22:10 +0100 Subject: [PATCH 04/14] Add select_rows and select_columns. --- src/base/construction.rs | 6 +++--- src/base/edition.rs | 45 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/src/base/construction.rs b/src/base/construction.rs index 1a53f33b..05bb4b16 100644 --- a/src/base/construction.rs +++ b/src/base/construction.rs @@ -296,7 +296,7 @@ where /// /// let m = Matrix3::from_diagonal(&Vector3::new(1.0, 2.0, 3.0)); /// // The two additional arguments represent the matrix dimensions. - /// let dm = DMatrix::from_diagonal(&DVector::from_row_slice(3, &[1.0, 2.0, 3.0])); + /// let dm = DMatrix::from_diagonal(&DVector::from_row_slice(&[1.0, 2.0, 3.0])); /// /// assert!(m.m11 == 1.0 && m.m12 == 0.0 && m.m13 == 0.0 && /// m.m21 == 0.0 && m.m22 == 2.0 && m.m23 == 0.0 && @@ -616,7 +616,7 @@ macro_rules! impl_constructors_from_data( /// /// 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 dv = DVector::from_row_slice(&[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]); @@ -643,7 +643,7 @@ macro_rules! impl_constructors_from_data( /// /// 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 dv = DVector::from_column_slice(&[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]); diff --git a/src/base/edition.rs b/src/base/edition.rs index d1493847..a9932374 100644 --- a/src/base/edition.rs +++ b/src/base/edition.rs @@ -1,6 +1,7 @@ use num::{One, Zero}; use std::cmp; use std::ptr; +use std::iter::ExactSizeIterator; use base::allocator::{Allocator, Reallocator}; use base::constraint::{DimEq, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint}; @@ -32,6 +33,46 @@ impl> Matrix { res } + + /// Creates a new matrix by extracting the given set of rows from `self`. + pub fn select_rows(&self, irows: impl ExactSizeIterator + Clone) -> MatrixMN + where DefaultAllocator: Allocator { + let ncols = self.data.shape().1; + let mut res = unsafe { MatrixMN::new_uninitialized_generic(Dynamic::new(irows.len()), ncols) }; + + // First, check that all the indices from irows are valid. + // This will allow us to use unchecked access in the inner loop. + for i in irows.clone() { + assert!(i < self.nrows(), "Row index out of bounds.") + } + + for j in 0..ncols.value() { + // FIXME: use unchecked column indexing + let mut res = res.column_mut(j); + let mut src = self.column(j); + + for (destination, source) in irows.clone().enumerate() { + unsafe { + *res.vget_unchecked_mut(destination) = *src.vget_unchecked(source) + } + } + } + + res + } + + /// Creates a new matrix by extracting the given set of columns from `self`. + pub fn select_columns(&self, icols: impl ExactSizeIterator) -> MatrixMN + where DefaultAllocator: Allocator { + let nrows = self.data.shape().0; + let mut res = unsafe { MatrixMN::new_uninitialized_generic(nrows, Dynamic::new(icols.len())) }; + + for (destination, source) in icols.enumerate() { + res.column_mut(destination).copy_from(&self.column(source)) + } + + res + } } impl> Matrix { @@ -764,9 +805,9 @@ where /// # Example /// ``` /// # use nalgebra::DVector; - /// let mut vector = DVector::from_vec(3, vec![0, 1, 2]); + /// let mut vector = DVector::from_vec(vec![0, 1, 2]); /// vector.extend(vec![3, 4, 5]); - /// assert!(vector.eq(&DVector::from_vec(6, vec![0, 1, 2, 3, 4, 5]))); + /// assert!(vector.eq(&DVector::from_vec(vec![0, 1, 2, 3, 4, 5]))); /// ``` fn extend>(&mut self, iter: I) { self.data.extend(iter); From 0d2c1be8da888bcec291478427ed278be347fcd6 Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sun, 9 Dec 2018 15:21:05 +0100 Subject: [PATCH 05/14] Add row and column iterators. --- src/base/iter.rs | 225 ++++++++++++++++++++++++++++++++++++++++++++- src/base/matrix.rs | 24 ++++- 2 files changed, 246 insertions(+), 3 deletions(-) diff --git a/src/base/iter.rs b/src/base/iter.rs index fe8fd4f6..2b5a12d4 100644 --- a/src/base/iter.rs +++ b/src/base/iter.rs @@ -3,9 +3,9 @@ use std::marker::PhantomData; use std::mem; -use base::dimension::Dim; +use base::dimension::{Dim, U1}; use base::storage::{Storage, StorageMut}; -use base::Scalar; +use base::{Scalar, Matrix, MatrixSlice, MatrixSliceMut, Dynamic}; macro_rules! iterator { (struct $Name:ident for $Storage:ident.$ptr: ident -> $Ptr:ty, $Ref:ty, $SRef: ty) => { @@ -96,3 +96,224 @@ macro_rules! iterator { iterator!(struct MatrixIter for Storage.ptr -> *const N, &'a N, &'a S); iterator!(struct MatrixIterMut for StorageMut.ptr_mut -> *mut N, &'a mut N, &'a mut S); + + +/* + * + * Row iterators. + * + */ +#[derive(Clone)] +pub struct RowIter<'a, N: Scalar, R: Dim, C: Dim, S: Storage> { + mat: &'a Matrix, + curr: usize +} + +impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + Storage> RowIter<'a, N, R, C, S> { + pub fn new(mat: &'a Matrix) -> Self { + RowIter { + mat, curr: 0 + } + } +} + + +impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + Storage> Iterator for RowIter<'a, N, R, C, S> { + type Item = MatrixSlice<'a, N, U1, C, S::RStride, S::CStride>; + + #[inline] + fn next(&mut self) -> Option { + if self.curr < self.mat.nrows() { + let res = self.mat.row(self.curr); + self.curr += 1; + Some(res) + } else { + None + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + (self.mat.nrows() - self.curr, Some(self.mat.nrows() - self.curr)) + } + + #[inline] + fn count(self) -> usize { + self.mat.nrows() - self.curr + } +} + +impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + Storage> ExactSizeIterator for RowIter<'a, N, R, C, S> { + #[inline] + fn len(&self) -> usize { + self.mat.nrows() - self.curr + } +} + + + +pub struct RowIterMut<'a, N: Scalar, R: Dim, C: Dim, S: StorageMut> { + mat: *mut Matrix, + curr: usize, + phantom: PhantomData<&'a Matrix> +} + +impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + StorageMut> RowIterMut<'a, N, R, C, S> { + pub fn new(mat: &'a mut Matrix) -> Self { + RowIterMut { + mat, + curr: 0, + phantom: PhantomData + } + } + + fn nrows(&self) -> usize { + unsafe { + (*self.mat).nrows() + } + } +} + + +impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + StorageMut> Iterator for RowIterMut<'a, N, R, C, S> { + type Item = MatrixSliceMut<'a, N, U1, C, S::RStride, S::CStride>; + + #[inline] + fn next(&mut self) -> Option { + if self.curr < self.nrows() { + let res = unsafe { (*self.mat).row_mut(self.curr) }; + self.curr += 1; + Some(res) + } else { + None + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + (self.nrows() - self.curr, Some(self.nrows() - self.curr)) + } + + #[inline] + fn count(self) -> usize { + self.nrows() - self.curr + } +} + +impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + StorageMut> ExactSizeIterator for RowIterMut<'a, N, R, C, S> { + #[inline] + fn len(&self) -> usize { + self.nrows() - self.curr + } +} + + +/* + * + * Column iterators. + * + */ +#[derive(Clone)] +pub struct ColumnIter<'a, N: Scalar, R: Dim, C: Dim, S: Storage> { + mat: &'a Matrix, + curr: usize +} + +impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + Storage> ColumnIter<'a, N, R, C, S> { + pub fn new(mat: &'a Matrix) -> Self { + ColumnIter { + mat, curr: 0 + } + } +} + + +impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + Storage> Iterator for ColumnIter<'a, N, R, C, S> { + type Item = MatrixSlice<'a, N, R, U1, S::RStride, S::CStride>; + + #[inline] + fn next(&mut self) -> Option { + if self.curr < self.mat.ncols() { + let res = self.mat.column(self.curr); + self.curr += 1; + Some(res) + } else { + None + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + (self.mat.ncols() - self.curr, Some(self.mat.ncols() - self.curr)) + } + + #[inline] + fn count(self) -> usize { + self.mat.ncols() - self.curr + } +} + +impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + Storage> ExactSizeIterator for ColumnIter<'a, N, R, C, S> { + #[inline] + fn len(&self) -> usize { + self.mat.ncols() - self.curr + } +} + + + +pub struct ColumnIterMut<'a, N: Scalar, R: Dim, C: Dim, S: StorageMut> { + mat: *mut Matrix, + curr: usize, + phantom: PhantomData<&'a Matrix> +} + +impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + StorageMut> ColumnIterMut<'a, N, R, C, S> { + pub fn new(mat: &'a mut Matrix) -> Self { + ColumnIterMut { + mat, + curr: 0, + phantom: PhantomData + } + } + + fn ncols(&self) -> usize { + unsafe { + (*self.mat).ncols() + } + } +} + + +impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + StorageMut> Iterator for ColumnIterMut<'a, N, R, C, S> { + type Item = MatrixSliceMut<'a, N, R, U1, S::RStride, S::CStride>; + + #[inline] + fn next(&mut self) -> Option { + if self.curr < self.ncols() { + let res = unsafe { (*self.mat).column_mut(self.curr) }; + self.curr += 1; + Some(res) + } else { + None + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + (self.ncols() - self.curr, Some(self.ncols() - self.curr)) + } + + #[inline] + fn count(self) -> usize { + self.ncols() - self.curr + } +} + +impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + StorageMut> ExactSizeIterator for ColumnIterMut<'a, N, R, C, S> { + #[inline] + fn len(&self) -> usize { + self.ncols() - self.curr + } +} + diff --git a/src/base/matrix.rs b/src/base/matrix.rs index d9c03b54..625438d5 100644 --- a/src/base/matrix.rs +++ b/src/base/matrix.rs @@ -22,7 +22,7 @@ use alga::general::{ClosedAdd, ClosedMul, ClosedSub, Real, Ring}; use base::allocator::{Allocator, SameShapeAllocator, SameShapeC, SameShapeR}; use base::constraint::{DimEq, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint}; use base::dimension::{Dim, DimAdd, DimSum, IsNotStaticOne, U1, U2, U3}; -use base::iter::{MatrixIter, MatrixIterMut}; +use base::iter::{MatrixIter, MatrixIterMut, RowIter, RowIterMut, ColumnIter, ColumnIterMut}; use base::storage::{ ContiguousStorage, ContiguousStorageMut, Owned, SameShapeStorage, Storage, StorageMut, }; @@ -247,6 +247,16 @@ impl> Matrix { MatrixIter::new(&self.data) } + #[inline] + pub fn row_iter(&self) -> RowIter { + RowIter::new(self) + } + + #[inline] + pub fn column_iter(&self) -> ColumnIter { + ColumnIter::new(self) + } + /// Computes the row and column coordinates of the i-th element of this matrix seen as a /// vector. #[inline] @@ -591,6 +601,18 @@ impl> Matrix { MatrixIterMut::new(&mut self.data) } + /// Mutably iterates through this matrix rows. + #[inline] + pub fn row_iter_mut(&mut self) -> RowIterMut { + RowIterMut::new(self) + } + + /// Mutably iterates through this matrix columns. + #[inline] + pub fn column_iter_mut(&mut self) -> ColumnIterMut { + ColumnIterMut::new(self) + } + /// Swaps two entries without bound-checking. #[inline] pub unsafe fn swap_unchecked(&mut self, row_cols1: (usize, usize), row_cols2: (usize, usize)) { From 904000ce27e5495b8efc52b737fe2c99ed6a3b22 Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sun, 9 Dec 2018 16:55:42 +0100 Subject: [PATCH 06/14] Add argmin and argmax. --- src/base/blas.rs | 80 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 55 insertions(+), 25 deletions(-) diff --git a/src/base/blas.rs b/src/base/blas.rs index 1379db19..b770aa0e 100644 --- a/src/base/blas.rs +++ b/src/base/blas.rs @@ -13,18 +13,18 @@ use base::dimension::{Dim, Dynamic, U1, U2, U3, U4}; use base::storage::{Storage, StorageMut}; use base::{DefaultAllocator, Matrix, Scalar, SquareMatrix, Vector}; -impl> Vector { - /// Computes the index of the vector component with the largest value. +impl> Vector { + /// Computes the index and value of the vector component with the largest value. /// /// # Examples: /// /// ``` /// # use nalgebra::Vector3; /// let vec = Vector3::new(11, -15, 13); - /// assert_eq!(vec.imax(), 2); + /// assert_eq!(vec.argmax(), (2, 13)); /// ``` #[inline] - pub fn imax(&self) -> usize { + pub fn argmax(&self) -> (usize, N) { assert!(!self.is_empty(), "The input vector must not be empty."); let mut the_max = unsafe { self.vget_unchecked(0) }; @@ -39,7 +39,21 @@ impl> Vector } } - the_i + (the_i, *the_max) + } + + /// Computes the index of the vector component with the largest value. + /// + /// # Examples: + /// + /// ``` + /// # use nalgebra::Vector3; + /// let vec = Vector3::new(11, -15, 13); + /// assert_eq!(vec.imax(), 2); + /// ``` + #[inline] + pub fn imax(&self) -> usize { + self.argmax().0 } /// Computes the index of the vector component with the largest absolute value. @@ -52,7 +66,8 @@ impl> Vector /// assert_eq!(vec.iamax(), 1); /// ``` #[inline] - pub fn iamax(&self) -> usize { + pub fn iamax(&self) -> usize + where N: Signed { assert!(!self.is_empty(), "The input vector must not be empty."); let mut the_max = unsafe { self.vget_unchecked(0).abs() }; @@ -70,6 +85,34 @@ impl> Vector the_i } + /// Computes the index and value of the vector component with the smallest value. + /// + /// # Examples: + /// + /// ``` + /// # use nalgebra::Vector3; + /// let vec = Vector3::new(11, -15, 13); + /// assert_eq!(vec.argmin(), (1, -15)); + /// ``` + #[inline] + pub fn argmin(&self) -> (usize, N) { + assert!(!self.is_empty(), "The input vector must not be empty."); + + let mut the_min = unsafe { self.vget_unchecked(0) }; + let mut the_i = 0; + + for i in 1..self.nrows() { + let val = unsafe { self.vget_unchecked(i) }; + + if val < the_min { + the_min = val; + the_i = i; + } + } + + (the_i, *the_min) + } + /// Computes the index of the vector component with the smallest value. /// /// # Examples: @@ -81,21 +124,7 @@ impl> Vector /// ``` #[inline] pub fn imin(&self) -> usize { - assert!(!self.is_empty(), "The input vector must not be empty."); - - let mut the_max = unsafe { self.vget_unchecked(0) }; - let mut the_i = 0; - - for i in 1..self.nrows() { - let val = unsafe { self.vget_unchecked(i) }; - - if val < the_max { - the_max = val; - the_i = i; - } - } - - the_i + self.argmin().0 } /// Computes the index of the vector component with the smallest absolute value. @@ -108,17 +137,18 @@ impl> Vector /// assert_eq!(vec.iamin(), 0); /// ``` #[inline] - pub fn iamin(&self) -> usize { + pub fn iamin(&self) -> usize + where N: Signed { assert!(!self.is_empty(), "The input vector must not be empty."); - let mut the_max = unsafe { self.vget_unchecked(0).abs() }; + let mut the_min = unsafe { self.vget_unchecked(0).abs() }; let mut the_i = 0; for i in 1..self.nrows() { let val = unsafe { self.vget_unchecked(i).abs() }; - if val < the_max { - the_max = val; + if val < the_min { + the_min = val; the_i = i; } } From d1391592a0764f001d6c586bd1e7717febf8254c Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sun, 9 Dec 2018 16:56:09 +0100 Subject: [PATCH 07/14] Add zip_apply and zip_zip_apply. --- src/base/matrix.rs | 68 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 2 deletions(-) diff --git a/src/base/matrix.rs b/src/base/matrix.rs index 625438d5..3d12c12b 100644 --- a/src/base/matrix.rs +++ b/src/base/matrix.rs @@ -706,8 +706,7 @@ impl> Matrix { /// Replaces each component of `self` by the result of a closure `f` applied on it. #[inline] - pub fn apply N>(&mut self, mut f: F) - where DefaultAllocator: Allocator { + pub fn apply N>(&mut self, mut f: F) { let (nrows, ncols) = self.shape(); for j in 0..ncols { @@ -719,6 +718,71 @@ impl> Matrix { } } } + + /// Replaces each component of `self` by the result of a closure `f` applied on its components + /// joined with the components from `rhs`. + #[inline] + pub fn zip_apply(&mut self, rhs: Matrix, mut f: impl FnMut(N, N2) -> N) + where N2: Scalar, + R2: Dim, + C2: Dim, + S2: Storage, + ShapeConstraint: SameNumberOfRows + SameNumberOfColumns { + let (nrows, ncols) = self.shape(); + + assert!( + (nrows, ncols) == rhs.shape(), + "Matrix simultaneous traversal error: dimension mismatch." + ); + + for j in 0..ncols { + for i in 0..nrows { + unsafe { + let e = self.data.get_unchecked_mut(i, j); + let rhs = rhs.get_unchecked(i, j); + *e = f(*e, *rhs) + } + } + } + } + + + /// Replaces each component of `self` by the result of a closure `f` applied on its components + /// joined with the components from `b` and `c`. + #[inline] + pub fn zip_zip_apply(&mut self, b: Matrix, c: Matrix, mut f: impl FnMut(N, N2, N3) -> N) + where N2: Scalar, + R2: Dim, + C2: Dim, + S2: Storage, + N3: Scalar, + R3: Dim, + C3: Dim, + S3: Storage, + ShapeConstraint: SameNumberOfRows + SameNumberOfColumns, + ShapeConstraint: SameNumberOfRows + SameNumberOfColumns { + let (nrows, ncols) = self.shape(); + + assert!( + (nrows, ncols) == b.shape(), + "Matrix simultaneous traversal error: dimension mismatch." + ); + assert!( + (nrows, ncols) == c.shape(), + "Matrix simultaneous traversal error: dimension mismatch." + ); + + for j in 0..ncols { + for i in 0..nrows { + unsafe { + let e = self.data.get_unchecked_mut(i, j); + let b = b.get_unchecked(i, j); + let c = c.get_unchecked(i, j); + *e = f(*e, *b, *c) + } + } + } + } } impl> Vector { From da8dc6c4bdb439f8dc18833e578c58abcb99b35c Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sun, 9 Dec 2018 16:56:27 +0100 Subject: [PATCH 08/14] Use IntoIterator for select_rows and select_columns argument. --- src/base/edition.rs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/base/edition.rs b/src/base/edition.rs index a9932374..84f0b571 100644 --- a/src/base/edition.rs +++ b/src/base/edition.rs @@ -35,15 +35,18 @@ impl> Matrix { } /// Creates a new matrix by extracting the given set of rows from `self`. - pub fn select_rows(&self, irows: impl ExactSizeIterator + Clone) -> MatrixMN - where DefaultAllocator: Allocator { + pub fn select_rows<'a, I>(&self, irows: I) -> MatrixMN + where I: IntoIterator, + I::IntoIter: ExactSizeIterator + Clone, + DefaultAllocator: Allocator { + let mut irows = irows.into_iter(); let ncols = self.data.shape().1; let mut res = unsafe { MatrixMN::new_uninitialized_generic(Dynamic::new(irows.len()), ncols) }; // First, check that all the indices from irows are valid. // This will allow us to use unchecked access in the inner loop. for i in irows.clone() { - assert!(i < self.nrows(), "Row index out of bounds.") + assert!(*i < self.nrows(), "Row index out of bounds.") } for j in 0..ncols.value() { @@ -53,7 +56,7 @@ impl> Matrix { for (destination, source) in irows.clone().enumerate() { unsafe { - *res.vget_unchecked_mut(destination) = *src.vget_unchecked(source) + *res.vget_unchecked_mut(destination) = *src.vget_unchecked(*source) } } } @@ -62,13 +65,16 @@ impl> Matrix { } /// Creates a new matrix by extracting the given set of columns from `self`. - pub fn select_columns(&self, icols: impl ExactSizeIterator) -> MatrixMN - where DefaultAllocator: Allocator { + pub fn select_columns<'a, I>(&self, icols: I) -> MatrixMN + where I: IntoIterator, + I::IntoIter: ExactSizeIterator, + DefaultAllocator: Allocator { + let mut icols = icols.into_iter(); let nrows = self.data.shape().0; let mut res = unsafe { MatrixMN::new_uninitialized_generic(nrows, Dynamic::new(icols.len())) }; for (destination, source) in icols.enumerate() { - res.column_mut(destination).copy_from(&self.column(source)) + res.column_mut(destination).copy_from(&self.column(*source)) } res From 414fe8afda4f07bfc6808741ca1c5a5a7579b7d7 Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sun, 9 Dec 2018 17:00:56 +0100 Subject: [PATCH 09/14] Pass references to zip_apply and zip_zip_apply. --- src/base/matrix.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/base/matrix.rs b/src/base/matrix.rs index 3d12c12b..61434bb9 100644 --- a/src/base/matrix.rs +++ b/src/base/matrix.rs @@ -722,7 +722,7 @@ impl> Matrix { /// Replaces each component of `self` by the result of a closure `f` applied on its components /// joined with the components from `rhs`. #[inline] - pub fn zip_apply(&mut self, rhs: Matrix, mut f: impl FnMut(N, N2) -> N) + pub fn zip_apply(&mut self, rhs: &Matrix, mut f: impl FnMut(N, N2) -> N) where N2: Scalar, R2: Dim, C2: Dim, @@ -750,7 +750,7 @@ impl> Matrix { /// Replaces each component of `self` by the result of a closure `f` applied on its components /// joined with the components from `b` and `c`. #[inline] - pub fn zip_zip_apply(&mut self, b: Matrix, c: Matrix, mut f: impl FnMut(N, N2, N3) -> N) + pub fn zip_zip_apply(&mut self, b: &Matrix, c: &Matrix, mut f: impl FnMut(N, N2, N3) -> N) where N2: Scalar, R2: Dim, C2: Dim, From dcae274d2e8a465266330be6369b722702665b52 Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sun, 3 Feb 2019 08:33:07 +0100 Subject: [PATCH 10/14] Fix rebase fallback + add missing docs. --- src/base/edition.rs | 4 ++-- src/base/iter.rs | 20 +++++++++++--------- src/base/matrix.rs | 8 +++++--- src/base/mod.rs | 2 +- src/base/norm.rs | 15 +++++++++++++-- src/base/statistics.rs | 21 ++++++++++++++++++++- tests/core/matrix.rs | 4 ++-- 7 files changed, 54 insertions(+), 20 deletions(-) diff --git a/src/base/edition.rs b/src/base/edition.rs index 84f0b571..424374b0 100644 --- a/src/base/edition.rs +++ b/src/base/edition.rs @@ -39,7 +39,7 @@ impl> Matrix { where I: IntoIterator, I::IntoIter: ExactSizeIterator + Clone, DefaultAllocator: Allocator { - let mut irows = irows.into_iter(); + let irows = irows.into_iter(); let ncols = self.data.shape().1; let mut res = unsafe { MatrixMN::new_uninitialized_generic(Dynamic::new(irows.len()), ncols) }; @@ -69,7 +69,7 @@ impl> Matrix { where I: IntoIterator, I::IntoIter: ExactSizeIterator, DefaultAllocator: Allocator { - let mut icols = icols.into_iter(); + let icols = icols.into_iter(); let nrows = self.data.shape().0; let mut res = unsafe { MatrixMN::new_uninitialized_generic(nrows, Dynamic::new(icols.len())) }; diff --git a/src/base/iter.rs b/src/base/iter.rs index 2b5a12d4..8a5f10ab 100644 --- a/src/base/iter.rs +++ b/src/base/iter.rs @@ -5,7 +5,7 @@ use std::mem; use base::dimension::{Dim, U1}; use base::storage::{Storage, StorageMut}; -use base::{Scalar, Matrix, MatrixSlice, MatrixSliceMut, Dynamic}; +use base::{Scalar, Matrix, MatrixSlice, MatrixSliceMut}; macro_rules! iterator { (struct $Name:ident for $Storage:ident.$ptr: ident -> $Ptr:ty, $Ref:ty, $SRef: ty) => { @@ -104,13 +104,14 @@ iterator!(struct MatrixIterMut for StorageMut.ptr_mut -> *mut N, &'a mut N, &'a * */ #[derive(Clone)] +/// An iterator through the rows of a matrix. pub struct RowIter<'a, N: Scalar, R: Dim, C: Dim, S: Storage> { mat: &'a Matrix, curr: usize } impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + Storage> RowIter<'a, N, R, C, S> { - pub fn new(mat: &'a Matrix) -> Self { + pub(crate) fn new(mat: &'a Matrix) -> Self { RowIter { mat, curr: 0 } @@ -151,15 +152,15 @@ impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + Storage> ExactSizeIterator } - +/// An iterator through the mutable rows of a matrix. pub struct RowIterMut<'a, N: Scalar, R: Dim, C: Dim, S: StorageMut> { mat: *mut Matrix, curr: usize, - phantom: PhantomData<&'a Matrix> + phantom: PhantomData<&'a mut Matrix> } impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + StorageMut> RowIterMut<'a, N, R, C, S> { - pub fn new(mat: &'a mut Matrix) -> Self { + pub(crate) fn new(mat: &'a mut Matrix) -> Self { RowIterMut { mat, curr: 0, @@ -214,13 +215,14 @@ impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + StorageMut> ExactSizeIterat * */ #[derive(Clone)] +/// An iterator through the columns of a matrix. pub struct ColumnIter<'a, N: Scalar, R: Dim, C: Dim, S: Storage> { mat: &'a Matrix, curr: usize } impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + Storage> ColumnIter<'a, N, R, C, S> { - pub fn new(mat: &'a Matrix) -> Self { + pub(crate) fn new(mat: &'a Matrix) -> Self { ColumnIter { mat, curr: 0 } @@ -261,15 +263,15 @@ impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + Storage> ExactSizeIterator } - +/// An iterator through the mutable columns of a matrix. pub struct ColumnIterMut<'a, N: Scalar, R: Dim, C: Dim, S: StorageMut> { mat: *mut Matrix, curr: usize, - phantom: PhantomData<&'a Matrix> + phantom: PhantomData<&'a mut Matrix> } impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + StorageMut> ColumnIterMut<'a, N, R, C, S> { - pub fn new(mat: &'a mut Matrix) -> Self { + pub(crate) fn new(mat: &'a mut Matrix) -> Self { ColumnIterMut { mat, curr: 0, diff --git a/src/base/matrix.rs b/src/base/matrix.rs index 61434bb9..89078943 100644 --- a/src/base/matrix.rs +++ b/src/base/matrix.rs @@ -247,11 +247,13 @@ impl> Matrix { MatrixIter::new(&self.data) } + /// Iterate through the rows of this matrix. #[inline] pub fn row_iter(&self) -> RowIter { RowIter::new(self) } + /// Iterate through the columns of this matrix. #[inline] pub fn column_iter(&self) -> ColumnIter { ColumnIter::new(self) @@ -739,7 +741,7 @@ impl> Matrix { for i in 0..nrows { unsafe { let e = self.data.get_unchecked_mut(i, j); - let rhs = rhs.get_unchecked(i, j); + let rhs = rhs.get_unchecked((i, j)); *e = f(*e, *rhs) } } @@ -776,8 +778,8 @@ impl> Matrix { for i in 0..nrows { unsafe { let e = self.data.get_unchecked_mut(i, j); - let b = b.get_unchecked(i, j); - let c = c.get_unchecked(i, j); + let b = b.get_unchecked((i, j)); + let c = c.get_unchecked((i, j)); *e = f(*e, *b, *c) } } diff --git a/src/base/mod.rs b/src/base/mod.rs index be54eb6c..0ec6311c 100644 --- a/src/base/mod.rs +++ b/src/base/mod.rs @@ -30,7 +30,7 @@ mod scalar; mod swizzle; mod unit; mod statistics; -pub mod norm; +mod norm; #[doc(hidden)] pub mod helper; diff --git a/src/base/norm.rs b/src/base/norm.rs index 6e392bd5..354f2ca3 100644 --- a/src/base/norm.rs +++ b/src/base/norm.rs @@ -1,4 +1,4 @@ -use num::{Signed, Zero}; +use num::Signed; use std::cmp::PartialOrd; use allocator::Allocator; @@ -9,9 +9,14 @@ use constraint::{SameNumberOfRows, SameNumberOfColumns, ShapeConstraint}; // FIXME: this should be be a trait on alga? +/// A trait for abstract matrix norms. +/// +/// This may be moved to the alga crate in the future. pub trait Norm { + /// Apply this norm to the given matrix. fn norm(&self, m: &Matrix) -> N where R: Dim, C: Dim, S: Storage; + /// Use the metric induced by this norm to compute the metric distance between the two given matrices. fn metric_distance(&self, m1: &Matrix, m2: &Matrix) -> N where R1: Dim, C1: Dim, S1: Storage, R2: Dim, C2: Dim, S2: Storage, @@ -104,12 +109,16 @@ impl> Matrix { } /// The L2 norm of this matrix. + /// + /// Use `.apply_norm` to apply a custom norm. #[inline] pub fn norm(&self) -> N { self.norm_squared().sqrt() } - /// Computes the metric distance between `self` and `rhs` using the Euclidean metric. + /// Compute the distance between `self` and `rhs` using the metric induced by the euclidean norm. + /// + /// Use `.apply_metric_distance` to apply a custom norm. #[inline] pub fn metric_distance(&self, rhs: &Matrix) -> N where R2: Dim, C2: Dim, S2: Storage, @@ -117,11 +126,13 @@ impl> Matrix { self.apply_metric_distance(rhs, &EuclideanNorm) } + /// Uses the given `norm` to compute the norm of `self`. #[inline] pub fn apply_norm(&self, norm: &impl Norm) -> N { norm.norm(self) } + /// Uses the metric induced by the given `norm` to compute the metric distance between `self` and `rhs`. #[inline] pub fn apply_metric_distance(&self, rhs: &Matrix, norm: &impl Norm) -> N where R2: Dim, C2: Dim, S2: Storage, diff --git a/src/base/statistics.rs b/src/base/statistics.rs index 8f95e447..106673c4 100644 --- a/src/base/statistics.rs +++ b/src/base/statistics.rs @@ -3,6 +3,8 @@ use storage::Storage; use allocator::Allocator; impl> Matrix { + /// Returns a row vector where each element is the result of the application of `f` on the + /// corresponding column of the original matrix. #[inline] pub fn compress_rows(&self, f: impl Fn(VectorSliceN) -> N) -> RowVectorN where DefaultAllocator: Allocator { @@ -12,12 +14,16 @@ impl> Matrix { for i in 0..ncols.value() { // FIXME: avoid bound checking of column. - unsafe { *res.get_unchecked_mut(0, i) = f(self.column(i)); } + unsafe { *res.get_unchecked_mut((0, i)) = f(self.column(i)); } } res } + /// Returns a column vector where each element is the result of the application of `f` on the + /// corresponding column of the original matrix. + /// + /// This is the same as `self.compress_rows(f).transpose()`. #[inline] pub fn compress_rows_tr(&self, f: impl Fn(VectorSliceN) -> N) -> VectorN where DefaultAllocator: Allocator { @@ -33,6 +39,7 @@ impl> Matrix { res } + /// Returns a column vector resulting from the folding of `f` on each column of this matrix. #[inline] pub fn compress_columns(&self, init: VectorN, f: impl Fn(&mut VectorN, VectorSliceN)) -> VectorN where DefaultAllocator: Allocator { @@ -52,23 +59,27 @@ impl> Matrix { * Sum computation. * */ + /// The sum of all the elements of this matrix. #[inline] pub fn sum(&self) -> N { self.iter().cloned().fold(N::zero(), |a, b| a + b) } + /// The sum of all the rows of this matrix. #[inline] pub fn row_sum(&self) -> RowVectorN where DefaultAllocator: Allocator { self.compress_rows(|col| col.sum()) } + /// The sum of all the rows of this matrix. The result is transposed and returned as a column vector. #[inline] pub fn row_sum_tr(&self) -> VectorN where DefaultAllocator: Allocator { self.compress_rows_tr(|col| col.sum()) } + /// The sum of all the columns of this matrix. #[inline] pub fn column_sum(&self) -> VectorN where DefaultAllocator: Allocator { @@ -83,6 +94,7 @@ impl> Matrix { * Variance computation. * */ + /// The variance of all the elements of this matrix. #[inline] pub fn variance(&self) -> N { if self.len() == 0 { @@ -94,18 +106,21 @@ impl> Matrix { } } + /// The variance of all the rows of this matrix. #[inline] pub fn row_variance(&self) -> RowVectorN where DefaultAllocator: Allocator { self.compress_rows(|col| col.variance()) } + /// The variance of all the rows of this matrix. The result is transposed and returned as a column vector. #[inline] pub fn row_variance_tr(&self) -> VectorN where DefaultAllocator: Allocator { self.compress_rows_tr(|col| col.variance()) } + /// The variance of all the columns of this matrix. #[inline] pub fn column_variance(&self) -> VectorN where DefaultAllocator: Allocator { @@ -130,6 +145,7 @@ impl> Matrix { * Mean computation. * */ + /// The mean of all the elements of this matrix. #[inline] pub fn mean(&self) -> N { if self.len() == 0 { @@ -139,18 +155,21 @@ impl> Matrix { } } + /// The mean of all the rows of this matrix. #[inline] pub fn row_mean(&self) -> RowVectorN where DefaultAllocator: Allocator { self.compress_rows(|col| col.mean()) } + /// The mean of all the rows of this matrix. The result is transposed and returned as a column vector. #[inline] pub fn row_mean_tr(&self) -> VectorN where DefaultAllocator: Allocator { self.compress_rows_tr(|col| col.mean()) } + /// The mean of all the columns of this matrix. #[inline] pub fn column_mean(&self) -> VectorN where DefaultAllocator: Allocator { diff --git a/tests/core/matrix.rs b/tests/core/matrix.rs index 3b624c69..9c6d468a 100644 --- a/tests/core/matrix.rs +++ b/tests/core/matrix.rs @@ -292,8 +292,8 @@ 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(3, &[1.0, 2.0, 3.0]); - let expected_b = DVector::from_row_slice(4, &[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); From 381fdb642c1a842e497226cf49519dc709954fdc Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sun, 3 Feb 2019 10:56:30 +0100 Subject: [PATCH 11/14] Remove useless extern crate in doc-tests. --- nalgebra-glm/src/gtc/integer.rs | 2 +- nalgebra-glm/src/gtc/packing.rs | 2 +- nalgebra-glm/tests/lib.rs | 2 +- src/base/blas.rs | 6 -- src/base/indexing.rs | 2 +- src/base/norm.rs | 2 +- src/base/statistics.rs | 121 +++++++++++++++++++++- src/geometry/isometry.rs | 4 - src/geometry/isometry_construction.rs | 5 - src/geometry/orthographic.rs | 21 ---- src/geometry/quaternion.rs | 19 ---- src/geometry/quaternion_construction.rs | 14 --- src/geometry/rotation.rs | 4 - src/geometry/rotation_specialization.rs | 24 ----- src/geometry/similarity_construction.rs | 7 -- src/geometry/transform.rs | 4 - src/geometry/unit_complex.rs | 7 -- src/geometry/unit_complex_construction.rs | 7 -- tests/core/edition.rs | 2 +- tests/linalg/full_piv_lu.rs | 2 +- 20 files changed, 127 insertions(+), 130 deletions(-) diff --git a/nalgebra-glm/src/gtc/integer.rs b/nalgebra-glm/src/gtc/integer.rs index a5f1cc8f..df65843f 100644 --- a/nalgebra-glm/src/gtc/integer.rs +++ b/nalgebra-glm/src/gtc/integer.rs @@ -15,4 +15,4 @@ //pub fn uround(x: &TVec) -> TVec // where DefaultAllocator: Alloc { // unimplemented!() -//} \ No newline at end of file +//} diff --git a/nalgebra-glm/src/gtc/packing.rs b/nalgebra-glm/src/gtc/packing.rs index 414afe72..b0261239 100644 --- a/nalgebra-glm/src/gtc/packing.rs +++ b/nalgebra-glm/src/gtc/packing.rs @@ -288,4 +288,4 @@ pub fn unpackUnorm4x16(p: u64) -> Vec4 { pub fn unpackUnorm4x4(p: u16) -> Vec4 { unimplemented!() -} \ No newline at end of file +} diff --git a/nalgebra-glm/tests/lib.rs b/nalgebra-glm/tests/lib.rs index 0e76300c..ce95c64f 100644 --- a/nalgebra-glm/tests/lib.rs +++ b/nalgebra-glm/tests/lib.rs @@ -52,4 +52,4 @@ pub fn perspective_glm_nalgebra_project_same() assert_eq!(na_mat, gl_mat); assert_eq!(na_pt, gl_pt); -} \ No newline at end of file +} diff --git a/src/base/blas.rs b/src/base/blas.rs index b770aa0e..c16496d4 100644 --- a/src/base/blas.rs +++ b/src/base/blas.rs @@ -657,7 +657,6 @@ where N: Scalar + Zero + ClosedAdd + ClosedMul /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Matrix2x3, Matrix3x4, Matrix2x4}; /// let mut mat1 = Matrix2x4::identity(); /// let mat2 = Matrix2x3::new(1.0, 2.0, 3.0, @@ -790,7 +789,6 @@ where N: Scalar + Zero + ClosedAdd + ClosedMul /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Matrix3x2, Matrix3x4, Matrix2x4}; /// let mut mat1 = Matrix2x4::identity(); /// let mat2 = Matrix3x2::new(1.0, 4.0, @@ -909,7 +907,6 @@ where N: Scalar + Zero + One + ClosedAdd + ClosedMul /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{DMatrix, DVector}; /// // Note that all those would also work with statically-sized matrices. /// // We use DMatrix/DVector since that's the only case where pre-allocating the @@ -964,7 +961,6 @@ where N: Scalar + Zero + One + ClosedAdd + ClosedMul /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Matrix2, Matrix3, Matrix2x3, Vector2}; /// let mut mat = Matrix2::identity(); /// let lhs = Matrix2x3::new(1.0, 2.0, 3.0, @@ -1001,7 +997,6 @@ where N: Scalar + Zero + One + ClosedAdd + ClosedMul /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{DMatrix, DVector}; /// // Note that all those would also work with statically-sized matrices. /// // We use DMatrix/DVector since that's the only case where pre-allocating the @@ -1056,7 +1051,6 @@ where N: Scalar + Zero + One + ClosedAdd + ClosedMul /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Matrix2, Matrix3x2, Matrix3}; /// let mut mat = Matrix2::identity(); /// let rhs = Matrix3x2::new(1.0, 2.0, diff --git a/src/base/indexing.rs b/src/base/indexing.rs index 304242c4..976eef87 100644 --- a/src/base/indexing.rs +++ b/src/base/indexing.rs @@ -711,4 +711,4 @@ impl_index_pairs!{ => DimDiff where C: DimSub], } -} \ No newline at end of file +} diff --git a/src/base/norm.rs b/src/base/norm.rs index 354f2ca3..94c16e7d 100644 --- a/src/base/norm.rs +++ b/src/base/norm.rs @@ -211,4 +211,4 @@ impl> Matrix { Some(n) } } -} \ No newline at end of file +} diff --git a/src/base/statistics.rs b/src/base/statistics.rs index 106673c4..31f46d03 100644 --- a/src/base/statistics.rs +++ b/src/base/statistics.rs @@ -60,12 +60,31 @@ impl> Matrix { * */ /// The sum of all the elements of this matrix. + /// + /// # Example + /// + /// ``` + /// # use nalgebra::Matrix2x3; + /// + /// let m = Matrix2x3::new(1.0, 2.0, 3.0, + /// 4.0, 5.0, 6.0); + /// assert_eq!(m.sum(), 21.0); + /// ``` #[inline] pub fn sum(&self) -> N { self.iter().cloned().fold(N::zero(), |a, b| a + b) } /// The sum of all the rows of this matrix. + /// # Example + /// + /// ``` + /// # use nalgebra::{Matrix2x3, RowVector3}; + /// + /// let m = Matrix2x3::new(1.0, 2.0, 3.0, + /// 4.0, 5.0, 6.0); + /// assert_eq!(m.row_sum(), RowVector3::new(5.0, 7.0, 9.0)); + /// ``` #[inline] pub fn row_sum(&self) -> RowVectorN where DefaultAllocator: Allocator { @@ -73,6 +92,16 @@ impl> Matrix { } /// The sum of all the rows of this matrix. The result is transposed and returned as a column vector. + /// + /// # Example + /// + /// ``` + /// # use nalgebra::{Matrix2x3, Vector3}; + /// + /// let m = Matrix2x3::new(1.0, 2.0, 3.0, + /// 4.0, 5.0, 6.0); + /// assert_eq!(m.row_sum_tr(), Vector3::new(5.0, 7.0, 9.0)); + /// ``` #[inline] pub fn row_sum_tr(&self) -> VectorN where DefaultAllocator: Allocator { @@ -80,6 +109,16 @@ impl> Matrix { } /// The sum of all the columns of this matrix. + /// + /// # Example + /// + /// ``` + /// # use nalgebra::{Matrix2x3, Vector2}; + /// + /// let m = Matrix2x3::new(1.0, 2.0, 3.0, + /// 4.0, 5.0, 6.0); + /// assert_eq!(m.column_sum(), Vector2::new(6.0, 15.0)); + /// ``` #[inline] pub fn column_sum(&self) -> VectorN where DefaultAllocator: Allocator { @@ -95,6 +134,16 @@ impl> Matrix { * */ /// The variance of all the elements of this matrix. + /// + /// # Example + /// + /// ``` + /// # use nalgebra::Matrix2x3; + /// + /// let m = Matrix2x3::new(1.0, 2.0, 3.0, + /// 4.0, 5.0, 6.0); + /// assert_eq!(m.variance(), 3.5); + /// ``` #[inline] pub fn variance(&self) -> N { if self.len() == 0 { @@ -107,6 +156,15 @@ impl> Matrix { } /// The variance of all the rows of this matrix. + /// # Example + /// + /// ``` + /// # use nalgebra::{Matrix2x3, RowVector3}; + /// + /// let m = Matrix2x3::new(1.0, 2.0, 3.0, + /// 4.0, 5.0, 6.0); + /// assert_eq!(m.row_variance(), RowVector3::new(4.5, 4.5, 4.5)); + /// ``` #[inline] pub fn row_variance(&self) -> RowVectorN where DefaultAllocator: Allocator { @@ -114,6 +172,16 @@ impl> Matrix { } /// The variance of all the rows of this matrix. The result is transposed and returned as a column vector. + /// + /// # Example + /// + /// ``` + /// # use nalgebra::{Matrix2x3, Vector3}; + /// + /// let m = Matrix2x3::new(1.0, 2.0, 3.0, + /// 4.0, 5.0, 6.0); + /// assert_eq!(m.row_variance_tr(), Vector3::new(4.5, 4.5, 4.5)); + /// ``` #[inline] pub fn row_variance_tr(&self) -> VectorN where DefaultAllocator: Allocator { @@ -121,6 +189,17 @@ impl> Matrix { } /// The variance of all the columns of this matrix. + /// + /// # Example + /// + /// ``` + /// # #[macro_use] extern crate approx; + /// # use nalgebra::{Matrix2x3, Vector2}; + /// + /// let m = Matrix2x3::new(1.0, 2.0, 3.0, + /// 4.0, 5.0, 6.0); + /// assert_relative_eq!(m.column_variance(), Vector2::new(2.0 / 3.0, 2.0 / 3.0), epsilon = 1.0e-8); + /// ``` #[inline] pub fn column_variance(&self) -> VectorN where DefaultAllocator: Allocator { @@ -146,6 +225,16 @@ impl> Matrix { * */ /// The mean of all the elements of this matrix. + /// + /// # Example + /// + /// ``` + /// # use nalgebra::Matrix2x3; + /// + /// let m = Matrix2x3::new(1.0, 2.0, 3.0, + /// 4.0, 5.0, 6.0); + /// assert_eq!(m.mean(), 3.5); + /// ``` #[inline] pub fn mean(&self) -> N { if self.len() == 0 { @@ -156,6 +245,16 @@ impl> Matrix { } /// The mean of all the rows of this matrix. + /// + /// # Example + /// + /// ``` + /// # use nalgebra::{Matrix2x3, RowVector3}; + /// + /// let m = Matrix2x3::new(1.0, 2.0, 3.0, + /// 4.0, 5.0, 6.0); + /// assert_eq!(m.row_mean(), RowVector3::new(2.5, 3.5, 4.5)); + /// ``` #[inline] pub fn row_mean(&self) -> RowVectorN where DefaultAllocator: Allocator { @@ -163,6 +262,16 @@ impl> Matrix { } /// The mean of all the rows of this matrix. The result is transposed and returned as a column vector. + /// + /// # Example + /// + /// ``` + /// # use nalgebra::{Matrix2x3, Vector3}; + /// + /// let m = Matrix2x3::new(1.0, 2.0, 3.0, + /// 4.0, 5.0, 6.0); + /// assert_eq!(m.row_mean_tr(), Vector3::new(2.5, 3.5, 4.5)); + /// ``` #[inline] pub fn row_mean_tr(&self) -> VectorN where DefaultAllocator: Allocator { @@ -170,6 +279,16 @@ impl> Matrix { } /// The mean of all the columns of this matrix. + /// + /// # Example + /// + /// ``` + /// # use nalgebra::{Matrix2x3, Vector2}; + /// + /// let m = Matrix2x3::new(1.0, 2.0, 3.0, + /// 4.0, 5.0, 6.0); + /// assert_eq!(m.column_mean(), Vector2::new(2.0, 5.0)); + /// ``` #[inline] pub fn column_mean(&self) -> VectorN where DefaultAllocator: Allocator { @@ -179,4 +298,4 @@ impl> Matrix { out.axpy(denom, &col, N::one()) }) } -} \ No newline at end of file +} diff --git a/src/geometry/isometry.rs b/src/geometry/isometry.rs index 7ad3d4d9..1814efb5 100644 --- a/src/geometry/isometry.rs +++ b/src/geometry/isometry.rs @@ -113,7 +113,6 @@ where DefaultAllocator: Allocator /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{Isometry3, Translation3, UnitQuaternion, Vector3, Point3}; /// let tra = Translation3::new(0.0, 0.0, 3.0); @@ -197,7 +196,6 @@ where DefaultAllocator: Allocator /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{Isometry2, Translation2, UnitComplex, Vector2}; /// let mut iso = Isometry2::new(Vector2::new(1.0, 2.0), f32::consts::PI / 6.0); @@ -220,7 +218,6 @@ where DefaultAllocator: Allocator /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{Isometry2, Translation2, UnitComplex, Vector2, Point2}; /// let mut iso = Isometry2::new(Vector2::new(1.0, 2.0), f32::consts::FRAC_PI_2); @@ -272,7 +269,6 @@ where DefaultAllocator: Allocator /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{Isometry2, Vector2, Matrix3}; /// let iso = Isometry2::new(Vector2::new(10.0, 20.0), f32::consts::FRAC_PI_6); diff --git a/src/geometry/isometry_construction.rs b/src/geometry/isometry_construction.rs index b22ed32a..77a1f7c8 100644 --- a/src/geometry/isometry_construction.rs +++ b/src/geometry/isometry_construction.rs @@ -49,7 +49,6 @@ where DefaultAllocator: Allocator /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{Isometry2, Point2, UnitComplex}; /// let rot = UnitComplex::new(f32::consts::PI); @@ -165,7 +164,6 @@ macro_rules! isometry_construction_impl( /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{Isometry3, IsometryMatrix3, Point3, Vector3}; /// let axisangle = Vector3::y() * f32::consts::FRAC_PI_2; @@ -206,7 +204,6 @@ macro_rules! isometry_construction_impl( /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{Isometry3, IsometryMatrix3, Point3, Vector3}; /// let eye = Point3::new(1.0, 2.0, 3.0); @@ -258,7 +255,6 @@ macro_rules! isometry_construction_impl( /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{Isometry3, IsometryMatrix3, Point3, Vector3}; /// let eye = Point3::new(1.0, 2.0, 3.0); @@ -302,7 +298,6 @@ macro_rules! isometry_construction_impl( /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{Isometry3, IsometryMatrix3, Point3, Vector3}; /// let eye = Point3::new(1.0, 2.0, 3.0); diff --git a/src/geometry/orthographic.rs b/src/geometry/orthographic.rs index 4a04c8a8..c6c5628b 100644 --- a/src/geometry/orthographic.rs +++ b/src/geometry/orthographic.rs @@ -69,7 +69,6 @@ impl Orthographic3 { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Orthographic3, Point3}; /// let proj = Orthographic3::new(1.0, 10.0, 2.0, 20.0, 0.1, 1000.0); /// // Check this projection actually transforms the view cuboid into the double-unit cube. @@ -170,7 +169,6 @@ impl Orthographic3 { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Orthographic3, Point3, Matrix4}; /// let proj = Orthographic3::new(1.0, 10.0, 2.0, 20.0, 0.1, 1000.0); /// let inv = proj.inverse(); @@ -271,7 +269,6 @@ impl Orthographic3 { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Orthographic3, Point3, Matrix4}; /// let proj = Orthographic3::new(1.0, 10.0, 2.0, 20.0, 0.1, 1000.0); /// let expected = Matrix4::new( @@ -299,7 +296,6 @@ impl Orthographic3 { /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::Orthographic3; /// let proj = Orthographic3::new(1.0, 10.0, 2.0, 20.0, 0.1, 1000.0); /// assert_relative_eq!(proj.left(), 1.0, epsilon = 1.0e-6); @@ -316,7 +312,6 @@ impl Orthographic3 { /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::Orthographic3; /// let proj = Orthographic3::new(1.0, 10.0, 2.0, 20.0, 0.1, 1000.0); /// assert_relative_eq!(proj.right(), 10.0, epsilon = 1.0e-6); @@ -333,7 +328,6 @@ impl Orthographic3 { /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::Orthographic3; /// let proj = Orthographic3::new(1.0, 10.0, 2.0, 20.0, 0.1, 1000.0); /// assert_relative_eq!(proj.bottom(), 2.0, epsilon = 1.0e-6); @@ -350,7 +344,6 @@ impl Orthographic3 { /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::Orthographic3; /// let proj = Orthographic3::new(1.0, 10.0, 2.0, 20.0, 0.1, 1000.0); /// assert_relative_eq!(proj.top(), 20.0, epsilon = 1.0e-6); @@ -367,7 +360,6 @@ impl Orthographic3 { /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::Orthographic3; /// let proj = Orthographic3::new(1.0, 10.0, 2.0, 20.0, 0.1, 1000.0); /// assert_relative_eq!(proj.znear(), 0.1, epsilon = 1.0e-6); @@ -384,7 +376,6 @@ impl Orthographic3 { /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::Orthographic3; /// let proj = Orthographic3::new(1.0, 10.0, 2.0, 20.0, 0.1, 1000.0); /// assert_relative_eq!(proj.zfar(), 1000.0, epsilon = 1.0e-6); @@ -403,7 +394,6 @@ impl Orthographic3 { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Orthographic3, Point3}; /// let proj = Orthographic3::new(1.0, 10.0, 2.0, 20.0, 0.1, 1000.0); /// @@ -439,7 +429,6 @@ impl Orthographic3 { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Orthographic3, Point3}; /// let proj = Orthographic3::new(1.0, 10.0, 2.0, 20.0, 0.1, 1000.0); /// @@ -478,7 +467,6 @@ impl Orthographic3 { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Orthographic3, Vector3}; /// let proj = Orthographic3::new(1.0, 10.0, 2.0, 20.0, 0.1, 1000.0); /// @@ -504,7 +492,6 @@ impl Orthographic3 { /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::Orthographic3; /// let mut proj = Orthographic3::new(1.0, 10.0, 2.0, 20.0, 0.1, 1000.0); /// proj.set_left(2.0); @@ -524,7 +511,6 @@ impl Orthographic3 { /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::Orthographic3; /// let mut proj = Orthographic3::new(1.0, 10.0, 2.0, 20.0, 0.1, 1000.0); /// proj.set_right(15.0); @@ -544,7 +530,6 @@ impl Orthographic3 { /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::Orthographic3; /// let mut proj = Orthographic3::new(1.0, 10.0, 2.0, 20.0, 0.1, 1000.0); /// proj.set_bottom(8.0); @@ -564,7 +549,6 @@ impl Orthographic3 { /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::Orthographic3; /// let mut proj = Orthographic3::new(1.0, 10.0, 2.0, 20.0, 0.1, 1000.0); /// proj.set_top(15.0); @@ -584,7 +568,6 @@ impl Orthographic3 { /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::Orthographic3; /// let mut proj = Orthographic3::new(1.0, 10.0, 2.0, 20.0, 0.1, 1000.0); /// proj.set_znear(8.0); @@ -604,7 +587,6 @@ impl Orthographic3 { /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::Orthographic3; /// let mut proj = Orthographic3::new(1.0, 10.0, 2.0, 20.0, 0.1, 1000.0); /// proj.set_zfar(15.0); @@ -624,7 +606,6 @@ impl Orthographic3 { /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::Orthographic3; /// let mut proj = Orthographic3::new(1.0, 10.0, 2.0, 20.0, 0.1, 1000.0); /// proj.set_left_and_right(7.0, 70.0); @@ -650,7 +631,6 @@ impl Orthographic3 { /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::Orthographic3; /// let mut proj = Orthographic3::new(1.0, 10.0, 2.0, 20.0, 0.1, 1000.0); /// proj.set_bottom_and_top(7.0, 70.0); @@ -676,7 +656,6 @@ impl Orthographic3 { /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::Orthographic3; /// let mut proj = Orthographic3::new(1.0, 10.0, 2.0, 20.0, 0.1, 1000.0); /// proj.set_znear_and_zfar(50.0, 5000.0); diff --git a/src/geometry/quaternion.rs b/src/geometry/quaternion.rs index 4b0ce6b3..96e4f19a 100644 --- a/src/geometry/quaternion.rs +++ b/src/geometry/quaternion.rs @@ -114,7 +114,6 @@ impl Quaternion { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::Quaternion; /// let q = Quaternion::new(1.0, 2.0, 3.0, 4.0); /// let q_normalized = q.normalize(); @@ -150,7 +149,6 @@ impl Quaternion { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::Quaternion; /// let q = Quaternion::new(1.0, 2.0, 3.0, 4.0); /// let inv_q = q.try_inverse(); @@ -240,7 +238,6 @@ impl Quaternion { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::Quaternion; /// let q = Quaternion::new(1.0, 2.0, 3.0, 4.0); /// assert_relative_eq!(q.norm(), 5.47722557, epsilon = 1.0e-6); @@ -258,7 +255,6 @@ impl Quaternion { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::Quaternion; /// let q = Quaternion::new(1.0, 2.0, 3.0, 4.0); /// assert_relative_eq!(q.magnitude(), 5.47722557, epsilon = 1.0e-6); @@ -345,7 +341,6 @@ impl Quaternion { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::Quaternion; /// let q = Quaternion::new(2.0, 5.0, 0.0, 0.0); /// assert_relative_eq!(q.ln(), Quaternion::new(1.683647, 1.190289, 0.0, 0.0), epsilon = 1.0e-6) @@ -364,7 +359,6 @@ impl Quaternion { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::Quaternion; /// let q = Quaternion::new(1.683647, 1.190289, 0.0, 0.0); /// assert_relative_eq!(q.exp(), Quaternion::new(2.0, 5.0, 0.0, 0.0), epsilon = 1.0e-5) @@ -380,7 +374,6 @@ impl Quaternion { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::Quaternion; /// let q = Quaternion::new(1.683647, 1.190289, 0.0, 0.0); /// assert_relative_eq!(q.exp_eps(1.0e-6), Quaternion::new(2.0, 5.0, 0.0, 0.0), epsilon = 1.0e-5); @@ -410,7 +403,6 @@ impl Quaternion { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::Quaternion; /// let q = Quaternion::new(1.0, 2.0, 3.0, 4.0); /// assert_relative_eq!(q.powf(1.5), Quaternion::new( -6.2576659, 4.1549037, 6.2323556, 8.3098075), epsilon = 1.0e-6); @@ -476,7 +468,6 @@ impl Quaternion { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::Quaternion; /// let mut q = Quaternion::new(1.0, 2.0, 3.0, 4.0); /// @@ -506,7 +497,6 @@ impl Quaternion { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::Quaternion; /// let mut q = Quaternion::new(1.0, 2.0, 3.0, 4.0); /// q.normalize_mut(); @@ -672,7 +662,6 @@ impl UnitQuaternion { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{UnitQuaternion, Vector3}; /// let rot1 = UnitQuaternion::from_axis_angle(&Vector3::y_axis(), 1.0); /// let rot2 = UnitQuaternion::from_axis_angle(&Vector3::x_axis(), 0.1); @@ -691,7 +680,6 @@ impl UnitQuaternion { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{UnitQuaternion, Vector3}; /// let rot1 = UnitQuaternion::from_axis_angle(&Vector3::y_axis(), 1.0); /// let rot2 = UnitQuaternion::from_axis_angle(&Vector3::x_axis(), 0.1); @@ -785,7 +773,6 @@ impl UnitQuaternion { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{UnitQuaternion, Vector3, Unit}; /// let axisangle = Vector3::new(0.1, 0.2, 0.3); /// let mut rot = UnitQuaternion::new(axisangle); @@ -828,7 +815,6 @@ impl UnitQuaternion { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{UnitQuaternion, Vector3, Unit}; /// let axisangle = Vector3::new(0.1, 0.2, 0.3); /// let rot = UnitQuaternion::new(axisangle); @@ -885,7 +871,6 @@ impl UnitQuaternion { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Vector3, UnitQuaternion}; /// let axisangle = Vector3::new(0.1, 0.2, 0.3); /// let q = UnitQuaternion::new(axisangle); @@ -908,7 +893,6 @@ impl UnitQuaternion { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{UnitQuaternion, Vector3, Unit}; /// let axis = Unit::new_normalize(Vector3::new(1.0, 2.0, 3.0)); /// let angle = 1.2; @@ -932,7 +916,6 @@ impl UnitQuaternion { /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{UnitQuaternion, Vector3, Matrix3}; /// let q = UnitQuaternion::from_axis_angle(&Vector3::z_axis(), f32::consts::FRAC_PI_6); @@ -990,7 +973,6 @@ impl UnitQuaternion { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::UnitQuaternion; /// let rot = UnitQuaternion::from_euler_angles(0.1, 0.2, 0.3); /// let euler = rot.euler_angles(); @@ -1009,7 +991,6 @@ impl UnitQuaternion { /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{UnitQuaternion, Vector3, Matrix4}; /// let rot = UnitQuaternion::from_axis_angle(&Vector3::z_axis(), f32::consts::FRAC_PI_6); diff --git a/src/geometry/quaternion_construction.rs b/src/geometry/quaternion_construction.rs index 82db8b47..257cb719 100644 --- a/src/geometry/quaternion_construction.rs +++ b/src/geometry/quaternion_construction.rs @@ -166,7 +166,6 @@ impl UnitQuaternion { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{UnitQuaternion, Point3, Vector3}; /// let axis = Vector3::y_axis(); @@ -208,7 +207,6 @@ impl UnitQuaternion { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::UnitQuaternion; /// let rot = UnitQuaternion::from_euler_angles(0.1, 0.2, 0.3); /// let euler = rot.euler_angles(); @@ -237,7 +235,6 @@ impl UnitQuaternion { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Rotation3, UnitQuaternion, Vector3}; /// let axis = Vector3::y_axis(); /// let angle = 0.1; @@ -302,7 +299,6 @@ impl UnitQuaternion { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Vector3, UnitQuaternion}; /// let a = Vector3::new(1.0, 2.0, 3.0); /// let b = Vector3::new(3.0, 1.0, 2.0); @@ -325,7 +321,6 @@ impl UnitQuaternion { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Vector3, UnitQuaternion}; /// let a = Vector3::new(1.0, 2.0, 3.0); /// let b = Vector3::new(3.0, 1.0, 2.0); @@ -361,7 +356,6 @@ impl UnitQuaternion { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Unit, Vector3, UnitQuaternion}; /// let a = Unit::new_normalize(Vector3::new(1.0, 2.0, 3.0)); /// let b = Unit::new_normalize(Vector3::new(3.0, 1.0, 2.0)); @@ -387,7 +381,6 @@ impl UnitQuaternion { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Unit, Vector3, UnitQuaternion}; /// let a = Unit::new_normalize(Vector3::new(1.0, 2.0, 3.0)); /// let b = Unit::new_normalize(Vector3::new(3.0, 1.0, 2.0)); @@ -446,7 +439,6 @@ impl UnitQuaternion { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{UnitQuaternion, Vector3}; /// let dir = Vector3::new(1.0, 2.0, 3.0); @@ -488,7 +480,6 @@ impl UnitQuaternion { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{UnitQuaternion, Vector3}; /// let dir = Vector3::new(1.0, 2.0, 3.0); @@ -520,7 +511,6 @@ impl UnitQuaternion { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{UnitQuaternion, Vector3}; /// let dir = Vector3::new(1.0, 2.0, 3.0); @@ -545,7 +535,6 @@ impl UnitQuaternion { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{UnitQuaternion, Point3, Vector3}; /// let axisangle = Vector3::y() * f32::consts::FRAC_PI_2; @@ -575,7 +564,6 @@ impl UnitQuaternion { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{UnitQuaternion, Point3, Vector3}; /// let axisangle = Vector3::y() * f32::consts::FRAC_PI_2; @@ -606,7 +594,6 @@ impl UnitQuaternion { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{UnitQuaternion, Point3, Vector3}; /// let axisangle = Vector3::y() * f32::consts::FRAC_PI_2; @@ -635,7 +622,6 @@ impl UnitQuaternion { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{UnitQuaternion, Point3, Vector3}; /// let axisangle = Vector3::y() * f32::consts::FRAC_PI_2; diff --git a/src/geometry/rotation.rs b/src/geometry/rotation.rs index 299ddb1e..6c50230e 100644 --- a/src/geometry/rotation.rs +++ b/src/geometry/rotation.rs @@ -257,7 +257,6 @@ where DefaultAllocator: Allocator /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Rotation2, Rotation3, Vector3}; /// let rot = Rotation3::new(Vector3::new(1.0, 2.0, 3.0)); /// let tr_rot = rot.transpose(); @@ -281,7 +280,6 @@ where DefaultAllocator: Allocator /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Rotation2, Rotation3, Vector3}; /// let rot = Rotation3::new(Vector3::new(1.0, 2.0, 3.0)); /// let inv = rot.inverse(); @@ -305,7 +303,6 @@ where DefaultAllocator: Allocator /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Rotation2, Rotation3, Vector3}; /// let rot = Rotation3::new(Vector3::new(1.0, 2.0, 3.0)); /// let mut tr_rot = Rotation3::new(Vector3::new(1.0, 2.0, 3.0)); @@ -333,7 +330,6 @@ where DefaultAllocator: Allocator /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Rotation2, Rotation3, Vector3}; /// let rot = Rotation3::new(Vector3::new(1.0, 2.0, 3.0)); /// let mut inv = Rotation3::new(Vector3::new(1.0, 2.0, 3.0)); diff --git a/src/geometry/rotation_specialization.rs b/src/geometry/rotation_specialization.rs index ffb495d1..35ae1ea2 100644 --- a/src/geometry/rotation_specialization.rs +++ b/src/geometry/rotation_specialization.rs @@ -27,7 +27,6 @@ impl Rotation2 { /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{Rotation2, Point2}; /// let rot = Rotation2::new(f32::consts::FRAC_PI_2); @@ -56,7 +55,6 @@ impl Rotation2 { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Vector2, Rotation2}; /// let a = Vector2::new(1.0, 2.0); /// let b = Vector2::new(2.0, 1.0); @@ -79,7 +77,6 @@ impl Rotation2 { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Vector2, Rotation2}; /// let a = Vector2::new(1.0, 2.0); /// let b = Vector2::new(2.0, 1.0); @@ -108,7 +105,6 @@ impl Rotation2 { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::Rotation2; /// let rot = Rotation2::new(1.78); /// assert_relative_eq!(rot.angle(), 1.78); @@ -123,7 +119,6 @@ impl Rotation2 { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::Rotation2; /// let rot1 = Rotation2::new(0.1); /// let rot2 = Rotation2::new(1.7); @@ -141,7 +136,6 @@ impl Rotation2 { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::Rotation2; /// let rot1 = Rotation2::new(0.1); /// let rot2 = Rotation2::new(1.7); @@ -161,7 +155,6 @@ impl Rotation2 { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::Rotation2; /// let rot = Rotation2::new(0.78); /// let pow = rot.powf(2.0); @@ -217,7 +210,6 @@ impl Rotation3 { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{Rotation3, Point3, Vector3}; /// let axisangle = Vector3::y() * f32::consts::FRAC_PI_2; @@ -245,7 +237,6 @@ impl Rotation3 { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{Rotation3, Point3, Vector3}; /// let axisangle = Vector3::y() * f32::consts::FRAC_PI_2; @@ -269,7 +260,6 @@ impl Rotation3 { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{Rotation3, Point3, Vector3}; /// let axis = Vector3::y_axis(); @@ -322,7 +312,6 @@ impl Rotation3 { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::Rotation3; /// let rot = Rotation3::from_euler_angles(0.1, 0.2, 0.3); /// let euler = rot.euler_angles(); @@ -363,7 +352,6 @@ impl Rotation3 { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::Rotation3; /// let rot = Rotation3::from_euler_angles(0.1, 0.2, 0.3); /// let euler = rot.euler_angles(); @@ -403,7 +391,6 @@ impl Rotation3 { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{Rotation3, Vector3}; /// let dir = Vector3::new(1.0, 2.0, 3.0); @@ -451,7 +438,6 @@ impl Rotation3 { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{Rotation3, Vector3}; /// let dir = Vector3::new(1.0, 2.0, 3.0); @@ -483,7 +469,6 @@ impl Rotation3 { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{Rotation3, Vector3}; /// let dir = Vector3::new(1.0, 2.0, 3.0); @@ -508,7 +493,6 @@ impl Rotation3 { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Vector3, Rotation3}; /// let a = Vector3::new(1.0, 2.0, 3.0); /// let b = Vector3::new(3.0, 1.0, 2.0); @@ -531,7 +515,6 @@ impl Rotation3 { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Vector3, Rotation3}; /// let a = Vector3::new(1.0, 2.0, 3.0); /// let b = Vector3::new(3.0, 1.0, 2.0); @@ -576,7 +559,6 @@ impl Rotation3 { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Unit, Rotation3, Vector3}; /// let axis = Unit::new_normalize(Vector3::new(1.0, 2.0, 3.0)); /// let rot = Rotation3::from_axis_angle(&axis, 1.78); @@ -594,7 +576,6 @@ impl Rotation3 { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Rotation3, Vector3, Unit}; /// let axis = Unit::new_normalize(Vector3::new(1.0, 2.0, 3.0)); /// let angle = 1.2; @@ -621,7 +602,6 @@ impl Rotation3 { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Rotation3, Vector3, Unit}; /// let axisangle = Vector3::new(0.1, 0.2, 0.3); /// let rot = Rotation3::new(axisangle); @@ -643,7 +623,6 @@ impl Rotation3 { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Rotation3, Vector3, Unit}; /// let axis = Unit::new_normalize(Vector3::new(1.0, 2.0, 3.0)); /// let angle = 1.2; @@ -670,7 +649,6 @@ impl Rotation3 { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Rotation3, Vector3}; /// let rot1 = Rotation3::from_axis_angle(&Vector3::y_axis(), 1.0); /// let rot2 = Rotation3::from_axis_angle(&Vector3::x_axis(), 0.1); @@ -688,7 +666,6 @@ impl Rotation3 { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Rotation3, Vector3}; /// let rot1 = Rotation3::from_axis_angle(&Vector3::y_axis(), 1.0); /// let rot2 = Rotation3::from_axis_angle(&Vector3::x_axis(), 0.1); @@ -706,7 +683,6 @@ impl Rotation3 { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Rotation3, Vector3, Unit}; /// let axis = Unit::new_normalize(Vector3::new(1.0, 2.0, 3.0)); /// let angle = 1.2; diff --git a/src/geometry/similarity_construction.rs b/src/geometry/similarity_construction.rs index 31a95996..47bb46c7 100644 --- a/src/geometry/similarity_construction.rs +++ b/src/geometry/similarity_construction.rs @@ -86,7 +86,6 @@ where /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{Similarity2, Point2, UnitComplex}; /// let rot = UnitComplex::new(f32::consts::FRAC_PI_2); @@ -135,7 +134,6 @@ impl Similarity> { /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{SimilarityMatrix2, Vector2, Point2}; /// let sim = SimilarityMatrix2::new(Vector2::new(1.0, 2.0), f32::consts::FRAC_PI_2, 3.0); @@ -159,7 +157,6 @@ impl Similarity> { /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{Similarity2, Vector2, Point2}; /// let sim = Similarity2::new(Vector2::new(1.0, 2.0), f32::consts::FRAC_PI_2, 3.0); @@ -187,7 +184,6 @@ macro_rules! similarity_construction_impl( /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{Similarity3, SimilarityMatrix3, Point3, Vector3}; /// let axisangle = Vector3::y() * f32::consts::FRAC_PI_2; @@ -227,7 +223,6 @@ macro_rules! similarity_construction_impl( /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{Similarity3, SimilarityMatrix3, Point3, Vector3}; /// let eye = Point3::new(1.0, 2.0, 3.0); @@ -278,7 +273,6 @@ macro_rules! similarity_construction_impl( /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{Similarity3, SimilarityMatrix3, Point3, Vector3}; /// let eye = Point3::new(1.0, 2.0, 3.0); @@ -317,7 +311,6 @@ macro_rules! similarity_construction_impl( /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{Similarity3, SimilarityMatrix3, Point3, Vector3}; /// let eye = Point3::new(1.0, 2.0, 3.0); diff --git a/src/geometry/transform.rs b/src/geometry/transform.rs index 08248a46..0d5d9c4a 100644 --- a/src/geometry/transform.rs +++ b/src/geometry/transform.rs @@ -350,7 +350,6 @@ where DefaultAllocator: Allocator, DimNameSum> /// # Examples /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Matrix3, Transform2}; /// /// let m = Matrix3::new(2.0, 2.0, -0.3, @@ -383,7 +382,6 @@ where DefaultAllocator: Allocator, DimNameSum> /// # Examples /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Matrix3, Projective2}; /// /// let m = Matrix3::new(2.0, 2.0, -0.3, @@ -407,7 +405,6 @@ where DefaultAllocator: Allocator, DimNameSum> /// # Examples /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Matrix3, Transform2}; /// /// let m = Matrix3::new(2.0, 2.0, -0.3, @@ -437,7 +434,6 @@ where DefaultAllocator: Allocator, DimNameSum> /// # Examples /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Matrix3, Projective2}; /// /// let m = Matrix3::new(2.0, 2.0, -0.3, diff --git a/src/geometry/unit_complex.rs b/src/geometry/unit_complex.rs index 62280056..f8d94dc8 100644 --- a/src/geometry/unit_complex.rs +++ b/src/geometry/unit_complex.rs @@ -85,7 +85,6 @@ impl UnitComplex { /// # Example /// ``` /// # extern crate num_complex; - /// # extern crate nalgebra; /// # use num_complex::Complex; /// # use nalgebra::UnitComplex; /// let angle = 1.78f32; @@ -117,7 +116,6 @@ impl UnitComplex { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::UnitComplex; /// let rot = UnitComplex::new(1.2); /// let inv = rot.inverse(); @@ -134,7 +132,6 @@ impl UnitComplex { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::UnitComplex; /// let rot1 = UnitComplex::new(0.1); /// let rot2 = UnitComplex::new(1.7); @@ -153,7 +150,6 @@ impl UnitComplex { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::UnitComplex; /// let rot1 = UnitComplex::new(0.1); /// let rot2 = UnitComplex::new(1.7); @@ -172,7 +168,6 @@ impl UnitComplex { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::UnitComplex; /// let angle = 1.7; /// let rot = UnitComplex::new(angle); @@ -192,7 +187,6 @@ impl UnitComplex { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::UnitComplex; /// let angle = 1.7; /// let mut rot = UnitComplex::new(angle); @@ -213,7 +207,6 @@ impl UnitComplex { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::UnitComplex; /// let rot = UnitComplex::new(0.78); /// let pow = rot.powf(2.0); diff --git a/src/geometry/unit_complex_construction.rs b/src/geometry/unit_complex_construction.rs index fa4a0451..c4c9cc0d 100644 --- a/src/geometry/unit_complex_construction.rs +++ b/src/geometry/unit_complex_construction.rs @@ -35,7 +35,6 @@ impl UnitComplex { /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{UnitComplex, Point2}; /// let rot = UnitComplex::new(f32::consts::FRAC_PI_2); @@ -56,7 +55,6 @@ impl UnitComplex { /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{UnitComplex, Point2}; /// let rot = UnitComplex::from_angle(f32::consts::FRAC_PI_2); @@ -78,7 +76,6 @@ impl UnitComplex { /// /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use std::f32; /// # use nalgebra::{UnitComplex, Vector2, Point2}; /// let angle = f32::consts::FRAC_PI_2; @@ -138,7 +135,6 @@ impl UnitComplex { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Vector2, UnitComplex}; /// let a = Vector2::new(1.0, 2.0); /// let b = Vector2::new(2.0, 1.0); @@ -161,7 +157,6 @@ impl UnitComplex { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Vector2, UnitComplex}; /// let a = Vector2::new(1.0, 2.0); /// let b = Vector2::new(2.0, 1.0); @@ -197,7 +192,6 @@ impl UnitComplex { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Unit, Vector2, UnitComplex}; /// let a = Unit::new_normalize(Vector2::new(1.0, 2.0)); /// let b = Unit::new_normalize(Vector2::new(2.0, 1.0)); @@ -223,7 +217,6 @@ impl UnitComplex { /// # Example /// ``` /// # #[macro_use] extern crate approx; - /// # extern crate nalgebra; /// # use nalgebra::{Unit, Vector2, UnitComplex}; /// let a = Unit::new_normalize(Vector2::new(1.0, 2.0)); /// let b = Unit::new_normalize(Vector2::new(2.0, 1.0)); diff --git a/tests/core/edition.rs b/tests/core/edition.rs index edaf2f08..37452a2d 100644 --- a/tests/core/edition.rs +++ b/tests/core/edition.rs @@ -565,4 +565,4 @@ fn resize_empty_matrix() { assert_eq!(m1, m5.resize(0, 0, 42)); assert_eq!(m1, m6.resize(0, 0, 42)); assert_eq!(m1, m7.resize(0, 0, 42)); -} \ No newline at end of file +} diff --git a/tests/linalg/full_piv_lu.rs b/tests/linalg/full_piv_lu.rs index 06d87156..5a0ad75b 100644 --- a/tests/linalg/full_piv_lu.rs +++ b/tests/linalg/full_piv_lu.rs @@ -459,4 +459,4 @@ fn resize() { assert_eq!(add_del, m.resize(5, 2, 42)); assert_eq!(del_add, m.resize(1, 8, 42)); } -*/ \ No newline at end of file +*/ From bafd74da7002321c0378b6753204933b04d386b8 Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sun, 3 Feb 2019 11:06:06 +0100 Subject: [PATCH 12/14] Fix doc-tests for variance. --- src/base/statistics.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/base/statistics.rs b/src/base/statistics.rs index 31f46d03..11cc9e1c 100644 --- a/src/base/statistics.rs +++ b/src/base/statistics.rs @@ -76,6 +76,9 @@ impl> Matrix { } /// The sum of all the rows of this matrix. + /// + /// Use `.row_variance_tr` if you need the result in a column vector instead. + /// /// # Example /// /// ``` @@ -138,11 +141,12 @@ impl> Matrix { /// # Example /// /// ``` + /// # #[macro_use] extern crate approx; /// # use nalgebra::Matrix2x3; /// /// let m = Matrix2x3::new(1.0, 2.0, 3.0, /// 4.0, 5.0, 6.0); - /// assert_eq!(m.variance(), 3.5); + /// assert_relative_eq!(m.variance(), 35.0 / 12.0, epsilon = 1.0e-8); /// ``` #[inline] pub fn variance(&self) -> N { @@ -156,6 +160,8 @@ impl> Matrix { } /// The variance of all the rows of this matrix. + /// + /// Use `.row_variance_tr` if you need the result in a column vector instead. /// # Example /// /// ``` @@ -163,7 +169,7 @@ impl> Matrix { /// /// let m = Matrix2x3::new(1.0, 2.0, 3.0, /// 4.0, 5.0, 6.0); - /// assert_eq!(m.row_variance(), RowVector3::new(4.5, 4.5, 4.5)); + /// assert_eq!(m.row_variance(), RowVector3::new(2.25, 2.25, 2.25)); /// ``` #[inline] pub fn row_variance(&self) -> RowVectorN @@ -180,7 +186,7 @@ impl> Matrix { /// /// let m = Matrix2x3::new(1.0, 2.0, 3.0, /// 4.0, 5.0, 6.0); - /// assert_eq!(m.row_variance_tr(), Vector3::new(4.5, 4.5, 4.5)); + /// assert_eq!(m.row_variance_tr(), Vector3::new(2.25, 2.25, 2.25)); /// ``` #[inline] pub fn row_variance_tr(&self) -> VectorN @@ -246,6 +252,8 @@ impl> Matrix { /// The mean of all the rows of this matrix. /// + /// Use `.row_mean_tr` if you need the result in a column vector instead. + /// /// # Example /// /// ``` From 48e9bbc06581b59afe4a1804b97f4ddd9bccf436 Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sun, 3 Feb 2019 11:17:09 +0100 Subject: [PATCH 13/14] Add tests for row and column iterators. --- src/base/matrix.rs | 47 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/base/matrix.rs b/src/base/matrix.rs index 89078943..2e344669 100644 --- a/src/base/matrix.rs +++ b/src/base/matrix.rs @@ -248,12 +248,31 @@ impl> Matrix { } /// Iterate through the rows of this matrix. + /// + /// # Example + /// ``` + /// # use nalgebra::Matrix2x3; + /// let mut a = Matrix2x3::new(1, 2, 3, + /// 4, 5, 6); + /// for (i, row) in a.row_iter().enumerate() { + /// assert_eq!(row, a.row(i)) + /// } + /// ``` #[inline] pub fn row_iter(&self) -> RowIter { RowIter::new(self) } /// Iterate through the columns of this matrix. + /// # Example + /// ``` + /// # use nalgebra::Matrix2x3; + /// let mut a = Matrix2x3::new(1, 2, 3, + /// 4, 5, 6); + /// for (i, column) in a.column_iter().enumerate() { + /// assert_eq!(column, a.column(i)) + /// } + /// ``` #[inline] pub fn column_iter(&self) -> ColumnIter { ColumnIter::new(self) @@ -604,12 +623,40 @@ impl> Matrix { } /// Mutably iterates through this matrix rows. + /// + /// # Example + /// ``` + /// # use nalgebra::Matrix2x3; + /// let mut a = Matrix2x3::new(1, 2, 3, + /// 4, 5, 6); + /// for (i, mut row) in a.row_iter_mut().enumerate() { + /// row *= (i + 1) * 10; + /// } + /// + /// let expected = Matrix2x3::new(10, 20, 30, + /// 80, 100, 120); + /// assert_eq!(a, expected); + /// ``` #[inline] pub fn row_iter_mut(&mut self) -> RowIterMut { RowIterMut::new(self) } /// Mutably iterates through this matrix columns. + /// + /// # Example + /// ``` + /// # use nalgebra::Matrix2x3; + /// let mut a = Matrix2x3::new(1, 2, 3, + /// 4, 5, 6); + /// for (i, mut col) in a.column_iter_mut().enumerate() { + /// col *= (i + 1) * 10; + /// } + /// + /// let expected = Matrix2x3::new(10, 40, 90, + /// 40, 100, 180); + /// assert_eq!(a, expected); + /// ``` #[inline] pub fn column_iter_mut(&mut self) -> ColumnIterMut { ColumnIterMut::new(self) From e225297147ddb7ba741691be9aa582b48df54749 Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sun, 3 Feb 2019 11:29:10 +0100 Subject: [PATCH 14/14] Add doc-tests for apply_norm and apply_metric_distance. --- src/base/norm.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/base/norm.rs b/src/base/norm.rs index 94c16e7d..68fb88a1 100644 --- a/src/base/norm.rs +++ b/src/base/norm.rs @@ -127,12 +127,36 @@ impl> Matrix { } /// Uses the given `norm` to compute the norm of `self`. + /// + /// # Example + /// + /// ``` + /// # use nalgebra::{Vector3, UniformNorm, LpNorm, EuclideanNorm}; + /// + /// let v = Vector3::new(1.0, 2.0, 3.0); + /// assert_eq!(v.apply_norm(&UniformNorm), 3.0); + /// assert_eq!(v.apply_norm(&LpNorm(1)), 6.0); + /// assert_eq!(v.apply_norm(&EuclideanNorm), v.norm()); + /// ``` #[inline] pub fn apply_norm(&self, norm: &impl Norm) -> N { norm.norm(self) } /// Uses the metric induced by the given `norm` to compute the metric distance between `self` and `rhs`. + /// + /// # Example + /// + /// ``` + /// # use nalgebra::{Vector3, UniformNorm, LpNorm, EuclideanNorm}; + /// + /// let v1 = Vector3::new(1.0, 2.0, 3.0); + /// let v2 = Vector3::new(10.0, 20.0, 30.0); + /// + /// assert_eq!(v1.apply_metric_distance(&v2, &UniformNorm), 27.0); + /// assert_eq!(v1.apply_metric_distance(&v2, &LpNorm(1)), 27.0 + 18.0 + 9.0); + /// assert_eq!(v1.apply_metric_distance(&v2, &EuclideanNorm), (v1 - v2).norm()); + /// ``` #[inline] pub fn apply_metric_distance(&self, rhs: &Matrix, norm: &impl Norm) -> N where R2: Dim, C2: Dim, S2: Storage,