Fix rebase fallback + add missing docs.

This commit is contained in:
sebcrozet 2019-02-03 08:33:07 +01:00
parent 414fe8afda
commit dcae274d2e
7 changed files with 54 additions and 20 deletions

View File

@ -39,7 +39,7 @@ impl<N: Scalar + Zero, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
where I: IntoIterator<Item = &'a usize>, where I: IntoIterator<Item = &'a usize>,
I::IntoIter: ExactSizeIterator + Clone, I::IntoIter: ExactSizeIterator + Clone,
DefaultAllocator: Allocator<N, Dynamic, C> { DefaultAllocator: Allocator<N, Dynamic, C> {
let mut irows = irows.into_iter(); let irows = irows.into_iter();
let ncols = self.data.shape().1; let ncols = self.data.shape().1;
let mut res = unsafe { MatrixMN::new_uninitialized_generic(Dynamic::new(irows.len()), ncols) }; let mut res = unsafe { MatrixMN::new_uninitialized_generic(Dynamic::new(irows.len()), ncols) };
@ -69,7 +69,7 @@ impl<N: Scalar + Zero, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
where I: IntoIterator<Item = &'a usize>, where I: IntoIterator<Item = &'a usize>,
I::IntoIter: ExactSizeIterator, I::IntoIter: ExactSizeIterator,
DefaultAllocator: Allocator<N, R, Dynamic> { DefaultAllocator: Allocator<N, R, Dynamic> {
let mut icols = icols.into_iter(); let icols = icols.into_iter();
let nrows = self.data.shape().0; let nrows = self.data.shape().0;
let mut res = unsafe { MatrixMN::new_uninitialized_generic(nrows, Dynamic::new(icols.len())) }; let mut res = unsafe { MatrixMN::new_uninitialized_generic(nrows, Dynamic::new(icols.len())) };

View File

@ -5,7 +5,7 @@ use std::mem;
use base::dimension::{Dim, U1}; use base::dimension::{Dim, U1};
use base::storage::{Storage, StorageMut}; use base::storage::{Storage, StorageMut};
use base::{Scalar, Matrix, MatrixSlice, MatrixSliceMut, Dynamic}; use base::{Scalar, Matrix, MatrixSlice, MatrixSliceMut};
macro_rules! iterator { macro_rules! iterator {
(struct $Name:ident for $Storage:ident.$ptr: ident -> $Ptr:ty, $Ref:ty, $SRef: ty) => { (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)] #[derive(Clone)]
/// An iterator through the rows of a matrix.
pub struct RowIter<'a, N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> { pub struct RowIter<'a, N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> {
mat: &'a Matrix<N, R, C, S>, mat: &'a Matrix<N, R, C, S>,
curr: usize curr: usize
} }
impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + Storage<N, R, C>> RowIter<'a, N, R, C, S> { impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + Storage<N, R, C>> RowIter<'a, N, R, C, S> {
pub fn new(mat: &'a Matrix<N, R, C, S>) -> Self { pub(crate) fn new(mat: &'a Matrix<N, R, C, S>) -> Self {
RowIter { RowIter {
mat, curr: 0 mat, curr: 0
} }
@ -151,15 +152,15 @@ impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + Storage<N, R, C>> ExactSizeIterator
} }
/// An iterator through the mutable rows of a matrix.
pub struct RowIterMut<'a, N: Scalar, R: Dim, C: Dim, S: StorageMut<N, R, C>> { pub struct RowIterMut<'a, N: Scalar, R: Dim, C: Dim, S: StorageMut<N, R, C>> {
mat: *mut Matrix<N, R, C, S>, mat: *mut Matrix<N, R, C, S>,
curr: usize, curr: usize,
phantom: PhantomData<&'a Matrix<N, R, C, S>> phantom: PhantomData<&'a mut Matrix<N, R, C, S>>
} }
impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + StorageMut<N, R, C>> RowIterMut<'a, N, R, C, S> { impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + StorageMut<N, R, C>> RowIterMut<'a, N, R, C, S> {
pub fn new(mat: &'a mut Matrix<N, R, C, S>) -> Self { pub(crate) fn new(mat: &'a mut Matrix<N, R, C, S>) -> Self {
RowIterMut { RowIterMut {
mat, mat,
curr: 0, curr: 0,
@ -214,13 +215,14 @@ impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + StorageMut<N, R, C>> ExactSizeIterat
* *
*/ */
#[derive(Clone)] #[derive(Clone)]
/// An iterator through the columns of a matrix.
pub struct ColumnIter<'a, N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> { pub struct ColumnIter<'a, N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> {
mat: &'a Matrix<N, R, C, S>, mat: &'a Matrix<N, R, C, S>,
curr: usize curr: usize
} }
impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + Storage<N, R, C>> ColumnIter<'a, N, R, C, S> { impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + Storage<N, R, C>> ColumnIter<'a, N, R, C, S> {
pub fn new(mat: &'a Matrix<N, R, C, S>) -> Self { pub(crate) fn new(mat: &'a Matrix<N, R, C, S>) -> Self {
ColumnIter { ColumnIter {
mat, curr: 0 mat, curr: 0
} }
@ -261,15 +263,15 @@ impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + Storage<N, R, C>> ExactSizeIterator
} }
/// An iterator through the mutable columns of a matrix.
pub struct ColumnIterMut<'a, N: Scalar, R: Dim, C: Dim, S: StorageMut<N, R, C>> { pub struct ColumnIterMut<'a, N: Scalar, R: Dim, C: Dim, S: StorageMut<N, R, C>> {
mat: *mut Matrix<N, R, C, S>, mat: *mut Matrix<N, R, C, S>,
curr: usize, curr: usize,
phantom: PhantomData<&'a Matrix<N, R, C, S>> phantom: PhantomData<&'a mut Matrix<N, R, C, S>>
} }
impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + StorageMut<N, R, C>> ColumnIterMut<'a, N, R, C, S> { impl<'a, N: Scalar, R: Dim, C: Dim, S: 'a + StorageMut<N, R, C>> ColumnIterMut<'a, N, R, C, S> {
pub fn new(mat: &'a mut Matrix<N, R, C, S>) -> Self { pub(crate) fn new(mat: &'a mut Matrix<N, R, C, S>) -> Self {
ColumnIterMut { ColumnIterMut {
mat, mat,
curr: 0, curr: 0,

View File

@ -247,11 +247,13 @@ impl<N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
MatrixIter::new(&self.data) MatrixIter::new(&self.data)
} }
/// Iterate through the rows of this matrix.
#[inline] #[inline]
pub fn row_iter(&self) -> RowIter<N, R, C, S> { pub fn row_iter(&self) -> RowIter<N, R, C, S> {
RowIter::new(self) RowIter::new(self)
} }
/// Iterate through the columns of this matrix.
#[inline] #[inline]
pub fn column_iter(&self) -> ColumnIter<N, R, C, S> { pub fn column_iter(&self) -> ColumnIter<N, R, C, S> {
ColumnIter::new(self) ColumnIter::new(self)
@ -739,7 +741,7 @@ impl<N: Scalar, R: Dim, C: Dim, S: StorageMut<N, R, C>> Matrix<N, R, C, S> {
for i in 0..nrows { for i in 0..nrows {
unsafe { unsafe {
let e = self.data.get_unchecked_mut(i, j); 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) *e = f(*e, *rhs)
} }
} }
@ -776,8 +778,8 @@ impl<N: Scalar, R: Dim, C: Dim, S: StorageMut<N, R, C>> Matrix<N, R, C, S> {
for i in 0..nrows { for i in 0..nrows {
unsafe { unsafe {
let e = self.data.get_unchecked_mut(i, j); let e = self.data.get_unchecked_mut(i, j);
let b = b.get_unchecked(i, j); let b = b.get_unchecked((i, j));
let c = c.get_unchecked(i, j); let c = c.get_unchecked((i, j));
*e = f(*e, *b, *c) *e = f(*e, *b, *c)
} }
} }

View File

@ -30,7 +30,7 @@ mod scalar;
mod swizzle; mod swizzle;
mod unit; mod unit;
mod statistics; mod statistics;
pub mod norm; mod norm;
#[doc(hidden)] #[doc(hidden)]
pub mod helper; pub mod helper;

View File

@ -1,4 +1,4 @@
use num::{Signed, Zero}; use num::Signed;
use std::cmp::PartialOrd; use std::cmp::PartialOrd;
use allocator::Allocator; use allocator::Allocator;
@ -9,9 +9,14 @@ use constraint::{SameNumberOfRows, SameNumberOfColumns, ShapeConstraint};
// FIXME: this should be be a trait on alga? // 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<N: Scalar> { pub trait Norm<N: Scalar> {
/// Apply this norm to the given matrix.
fn norm<R, C, S>(&self, m: &Matrix<N, R, C, S>) -> N fn norm<R, C, S>(&self, m: &Matrix<N, R, C, S>) -> N
where R: Dim, C: Dim, S: Storage<N, R, C>; where R: Dim, C: Dim, S: Storage<N, R, C>;
/// Use the metric induced by this norm to compute the metric distance between the two given matrices.
fn metric_distance<R1, C1, S1, R2, C2, S2>(&self, m1: &Matrix<N, R1, C1, S1>, m2: &Matrix<N, R2, C2, S2>) -> N fn metric_distance<R1, C1, S1, R2, C2, S2>(&self, m1: &Matrix<N, R1, C1, S1>, m2: &Matrix<N, R2, C2, S2>) -> N
where R1: Dim, C1: Dim, S1: Storage<N, R1, C1>, where R1: Dim, C1: Dim, S1: Storage<N, R1, C1>,
R2: Dim, C2: Dim, S2: Storage<N, R2, C2>, R2: Dim, C2: Dim, S2: Storage<N, R2, C2>,
@ -104,12 +109,16 @@ impl<N: Real, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
} }
/// The L2 norm of this matrix. /// The L2 norm of this matrix.
///
/// Use `.apply_norm` to apply a custom norm.
#[inline] #[inline]
pub fn norm(&self) -> N { pub fn norm(&self) -> N {
self.norm_squared().sqrt() 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] #[inline]
pub fn metric_distance<R2, C2, S2>(&self, rhs: &Matrix<N, R2, C2, S2>) -> N pub fn metric_distance<R2, C2, S2>(&self, rhs: &Matrix<N, R2, C2, S2>) -> N
where R2: Dim, C2: Dim, S2: Storage<N, R2, C2>, where R2: Dim, C2: Dim, S2: Storage<N, R2, C2>,
@ -117,11 +126,13 @@ impl<N: Real, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
self.apply_metric_distance(rhs, &EuclideanNorm) self.apply_metric_distance(rhs, &EuclideanNorm)
} }
/// Uses the given `norm` to compute the norm of `self`.
#[inline] #[inline]
pub fn apply_norm(&self, norm: &impl Norm<N>) -> N { pub fn apply_norm(&self, norm: &impl Norm<N>) -> N {
norm.norm(self) norm.norm(self)
} }
/// Uses the metric induced by the given `norm` to compute the metric distance between `self` and `rhs`.
#[inline] #[inline]
pub fn apply_metric_distance<R2, C2, S2>(&self, rhs: &Matrix<N, R2, C2, S2>, norm: &impl Norm<N>) -> N pub fn apply_metric_distance<R2, C2, S2>(&self, rhs: &Matrix<N, R2, C2, S2>, norm: &impl Norm<N>) -> N
where R2: Dim, C2: Dim, S2: Storage<N, R2, C2>, where R2: Dim, C2: Dim, S2: Storage<N, R2, C2>,

View File

@ -3,6 +3,8 @@ use storage::Storage;
use allocator::Allocator; use allocator::Allocator;
impl<N: Real, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> { impl<N: Real, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
/// Returns a row vector where each element is the result of the application of `f` on the
/// corresponding column of the original matrix.
#[inline] #[inline]
pub fn compress_rows(&self, f: impl Fn(VectorSliceN<N, R, S::RStride, S::CStride>) -> N) -> RowVectorN<N, C> pub fn compress_rows(&self, f: impl Fn(VectorSliceN<N, R, S::RStride, S::CStride>) -> N) -> RowVectorN<N, C>
where DefaultAllocator: Allocator<N, U1, C> { where DefaultAllocator: Allocator<N, U1, C> {
@ -12,12 +14,16 @@ impl<N: Real, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
for i in 0..ncols.value() { for i in 0..ncols.value() {
// FIXME: avoid bound checking of column. // 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 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] #[inline]
pub fn compress_rows_tr(&self, f: impl Fn(VectorSliceN<N, R, S::RStride, S::CStride>) -> N) -> VectorN<N, C> pub fn compress_rows_tr(&self, f: impl Fn(VectorSliceN<N, R, S::RStride, S::CStride>) -> N) -> VectorN<N, C>
where DefaultAllocator: Allocator<N, C> { where DefaultAllocator: Allocator<N, C> {
@ -33,6 +39,7 @@ impl<N: Real, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
res res
} }
/// Returns a column vector resulting from the folding of `f` on each column of this matrix.
#[inline] #[inline]
pub fn compress_columns(&self, init: VectorN<N, R>, f: impl Fn(&mut VectorN<N, R>, VectorSliceN<N, R, S::RStride, S::CStride>)) -> VectorN<N, R> pub fn compress_columns(&self, init: VectorN<N, R>, f: impl Fn(&mut VectorN<N, R>, VectorSliceN<N, R, S::RStride, S::CStride>)) -> VectorN<N, R>
where DefaultAllocator: Allocator<N, R> { where DefaultAllocator: Allocator<N, R> {
@ -52,23 +59,27 @@ impl<N: Real, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
* Sum computation. * Sum computation.
* *
*/ */
/// The sum of all the elements of this matrix.
#[inline] #[inline]
pub fn sum(&self) -> N { pub fn sum(&self) -> N {
self.iter().cloned().fold(N::zero(), |a, b| a + b) self.iter().cloned().fold(N::zero(), |a, b| a + b)
} }
/// The sum of all the rows of this matrix.
#[inline] #[inline]
pub fn row_sum(&self) -> RowVectorN<N, C> pub fn row_sum(&self) -> RowVectorN<N, C>
where DefaultAllocator: Allocator<N, U1, C> { where DefaultAllocator: Allocator<N, U1, C> {
self.compress_rows(|col| col.sum()) 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] #[inline]
pub fn row_sum_tr(&self) -> VectorN<N, C> pub fn row_sum_tr(&self) -> VectorN<N, C>
where DefaultAllocator: Allocator<N, C> { where DefaultAllocator: Allocator<N, C> {
self.compress_rows_tr(|col| col.sum()) self.compress_rows_tr(|col| col.sum())
} }
/// The sum of all the columns of this matrix.
#[inline] #[inline]
pub fn column_sum(&self) -> VectorN<N, R> pub fn column_sum(&self) -> VectorN<N, R>
where DefaultAllocator: Allocator<N, R> { where DefaultAllocator: Allocator<N, R> {
@ -83,6 +94,7 @@ impl<N: Real, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
* Variance computation. * Variance computation.
* *
*/ */
/// The variance of all the elements of this matrix.
#[inline] #[inline]
pub fn variance(&self) -> N { pub fn variance(&self) -> N {
if self.len() == 0 { if self.len() == 0 {
@ -94,18 +106,21 @@ impl<N: Real, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
} }
} }
/// The variance of all the rows of this matrix.
#[inline] #[inline]
pub fn row_variance(&self) -> RowVectorN<N, C> pub fn row_variance(&self) -> RowVectorN<N, C>
where DefaultAllocator: Allocator<N, U1, C> { where DefaultAllocator: Allocator<N, U1, C> {
self.compress_rows(|col| col.variance()) 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] #[inline]
pub fn row_variance_tr(&self) -> VectorN<N, C> pub fn row_variance_tr(&self) -> VectorN<N, C>
where DefaultAllocator: Allocator<N, C> { where DefaultAllocator: Allocator<N, C> {
self.compress_rows_tr(|col| col.variance()) self.compress_rows_tr(|col| col.variance())
} }
/// The variance of all the columns of this matrix.
#[inline] #[inline]
pub fn column_variance(&self) -> VectorN<N, R> pub fn column_variance(&self) -> VectorN<N, R>
where DefaultAllocator: Allocator<N, R> { where DefaultAllocator: Allocator<N, R> {
@ -130,6 +145,7 @@ impl<N: Real, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
* Mean computation. * Mean computation.
* *
*/ */
/// The mean of all the elements of this matrix.
#[inline] #[inline]
pub fn mean(&self) -> N { pub fn mean(&self) -> N {
if self.len() == 0 { if self.len() == 0 {
@ -139,18 +155,21 @@ impl<N: Real, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
} }
} }
/// The mean of all the rows of this matrix.
#[inline] #[inline]
pub fn row_mean(&self) -> RowVectorN<N, C> pub fn row_mean(&self) -> RowVectorN<N, C>
where DefaultAllocator: Allocator<N, U1, C> { where DefaultAllocator: Allocator<N, U1, C> {
self.compress_rows(|col| col.mean()) 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] #[inline]
pub fn row_mean_tr(&self) -> VectorN<N, C> pub fn row_mean_tr(&self) -> VectorN<N, C>
where DefaultAllocator: Allocator<N, C> { where DefaultAllocator: Allocator<N, C> {
self.compress_rows_tr(|col| col.mean()) self.compress_rows_tr(|col| col.mean())
} }
/// The mean of all the columns of this matrix.
#[inline] #[inline]
pub fn column_mean(&self) -> VectorN<N, R> pub fn column_mean(&self) -> VectorN<N, R>
where DefaultAllocator: Allocator<N, R> { where DefaultAllocator: Allocator<N, R> {

View File

@ -292,8 +292,8 @@ fn push() {
let a = Vector3::new(1.0, 2.0, 3.0); let a = Vector3::new(1.0, 2.0, 3.0);
let expected_a = Vector4::new(1.0, 2.0, 3.0, 4.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 b = DVector::from_row_slice(&[1.0, 2.0, 3.0]);
let expected_b = DVector::from_row_slice(4, &[1.0, 2.0, 3.0, 4.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!(a.push(4.0), expected_a);
assert_eq!(b.push(4.0), expected_b); assert_eq!(b.push(4.0), expected_b);