Add documentation.

This commit is contained in:
Sébastien Crozet 2017-08-13 19:52:57 +02:00 committed by Sébastien Crozet
parent c258d13f98
commit b22eb91a16
6 changed files with 111 additions and 23 deletions

View File

@ -586,7 +586,7 @@ where N: Scalar + Zero + One,
#[inline] #[inline]
pub fn x() -> Self pub fn x() -> Self
where R::Value: Cmp<typenum::U0, Output = Greater> { where R::Value: Cmp<typenum::U0, Output = Greater> {
let mut res = Self::from_element(N::zero()); let mut res = Self::zeros();
unsafe { *res.vget_unchecked_mut(0) = N::one(); } unsafe { *res.vget_unchecked_mut(0) = N::one(); }
res res
@ -596,7 +596,7 @@ where N: Scalar + Zero + One,
#[inline] #[inline]
pub fn y() -> Self pub fn y() -> Self
where R::Value: Cmp<typenum::U1, Output = Greater> { where R::Value: Cmp<typenum::U1, Output = Greater> {
let mut res = Self::from_element(N::zero()); let mut res = Self::zeros();
unsafe { *res.vget_unchecked_mut(1) = N::one(); } unsafe { *res.vget_unchecked_mut(1) = N::one(); }
res res
@ -606,7 +606,7 @@ where N: Scalar + Zero + One,
#[inline] #[inline]
pub fn z() -> Self pub fn z() -> Self
where R::Value: Cmp<typenum::U2, Output = Greater> { where R::Value: Cmp<typenum::U2, Output = Greater> {
let mut res = Self::from_element(N::zero()); let mut res = Self::zeros();
unsafe { *res.vget_unchecked_mut(2) = N::one(); } unsafe { *res.vget_unchecked_mut(2) = N::one(); }
res res
@ -616,7 +616,7 @@ where N: Scalar + Zero + One,
#[inline] #[inline]
pub fn w() -> Self pub fn w() -> Self
where R::Value: Cmp<typenum::U3, Output = Greater> { where R::Value: Cmp<typenum::U3, Output = Greater> {
let mut res = Self::from_element(N::zero()); let mut res = Self::zeros();
unsafe { *res.vget_unchecked_mut(3) = N::one(); } unsafe { *res.vget_unchecked_mut(3) = N::one(); }
res res
@ -626,7 +626,7 @@ where N: Scalar + Zero + One,
#[inline] #[inline]
pub fn a() -> Self pub fn a() -> Self
where R::Value: Cmp<typenum::U4, Output = Greater> { where R::Value: Cmp<typenum::U4, Output = Greater> {
let mut res = Self::from_element(N::zero()); let mut res = Self::zeros();
unsafe { *res.vget_unchecked_mut(4) = N::one(); } unsafe { *res.vget_unchecked_mut(4) = N::one(); }
res res
@ -636,7 +636,7 @@ where N: Scalar + Zero + One,
#[inline] #[inline]
pub fn b() -> Self pub fn b() -> Self
where R::Value: Cmp<typenum::U5, Output = Greater> { where R::Value: Cmp<typenum::U5, Output = Greater> {
let mut res = Self::from_element(N::zero()); let mut res = Self::zeros();
unsafe { *res.vget_unchecked_mut(5) = N::one(); } unsafe { *res.vget_unchecked_mut(5) = N::one(); }
res res

View File

@ -438,21 +438,30 @@ impl<N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
* *
*/ */
/// Resizes this matrix so that it contains `new_nrows` rows and `new_ncols` columns.
///
/// The values are copied such that `self[(i, j)] == result[(i, j)]`. If the result has more
/// rows and/or columns than `self`, then the extra rows or columns are filled with `val`.
pub fn resize(self, new_nrows: usize, new_ncols: usize, val: N) -> DMatrix<N> pub fn resize(self, new_nrows: usize, new_ncols: usize, val: N) -> DMatrix<N>
where DefaultAllocator: Reallocator<N, R, C, Dynamic, Dynamic> { where DefaultAllocator: Reallocator<N, R, C, Dynamic, Dynamic> {
self.resize_generic(Dynamic::new(new_nrows), Dynamic::new(new_ncols), val) self.resize_generic(Dynamic::new(new_nrows), Dynamic::new(new_ncols), val)
} }
/// Resizes this matrix so that it contains `R2::value()` rows and `C2::value()` columns.
///
/// The values are copied such that `self[(i, j)] == result[(i, j)]`. If the result has more
/// rows and/or columns than `self`, then the extra rows or columns are filled with `val`.
pub fn fixed_resize<R2: DimName, C2: DimName>(self, val: N) -> MatrixMN<N, R2, C2> pub fn fixed_resize<R2: DimName, C2: DimName>(self, val: N) -> MatrixMN<N, R2, C2>
where DefaultAllocator: Reallocator<N, R, C, R2, C2> { where DefaultAllocator: Reallocator<N, R, C, R2, C2> {
self.resize_generic(R2::name(), C2::name(), val) self.resize_generic(R2::name(), C2::name(), val)
} }
/// Resizes `self` such that it has dimensions `new_nrows × now_ncols`. The values are copied /// Resizes `self` such that it has dimensions `new_nrows × now_ncols`.
/// such that `self[(i, j)] == result[(i, j)]`. If the result has more rows and/or columns than ///
/// `self`, then the extra rows or columns are filled with `val`. /// The values are copied such that `self[(i, j)] == result[(i, j)]`. If the result has more
/// rows and/or columns than `self`, then the extra rows or columns are filled with `val`.
#[inline] #[inline]
pub fn resize_generic<R2: Dim, C2: Dim>(self, new_nrows: R2, new_ncols: C2, val: N) -> MatrixMN<N, R2, C2> pub fn resize_generic<R2: Dim, C2: Dim>(self, new_nrows: R2, new_ncols: C2, val: N) -> MatrixMN<N, R2, C2>
where DefaultAllocator: Reallocator<N, R, C, R2, C2> { where DefaultAllocator: Reallocator<N, R, C, R2, C2> {

View File

@ -193,11 +193,12 @@ impl<N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
#[inline] #[inline]
fn assert_slice_index(&self, start: (usize, usize), shape: (usize, usize), steps: (usize, usize)) { fn assert_slice_index(&self, start: (usize, usize), shape: (usize, usize), steps: (usize, usize)) {
let my_shape = self.shape(); let my_shape = self.shape();
// NOTE: we previously did: (shape.0 - 1) * steps.0 // NOTE: we don't do any subtraction to avoid underflow for zero-sized matrices.
// which was wrong because underflow may occur for zero-sized matrices. //
// Istead, we moved the subtraction into an addition on the right hand side. // Terms that would have been negative are moved to the other side of the inequality
assert!(start.0 + shape.0 * steps.0 <= my_shape.0 + steps.0, "Matrix slicing out of bounds."); // instead.
assert!(start.1 + shape.1 * steps.1 <= my_shape.1 + steps.1, "Matrix slicing out of bounds."); assert!(start.0 + (steps.0 + 1) * shape.0 <= my_shape.0 + steps.0, "Matrix slicing out of bounds.");
assert!(start.1 + (steps.1 + 1) * shape.1 <= my_shape.1 + steps.1, "Matrix slicing out of bounds.");
} }
} }
@ -290,7 +291,7 @@ macro_rules! matrix_slice_impl(
-> $MatrixSlice<N, RSlice, C, S::RStride, S::CStride> { -> $MatrixSlice<N, RSlice, C, S::RStride, S::CStride> {
let my_shape = $me.data.shape(); let my_shape = $me.data.shape();
$me.assert_slice_index((row_start, 0), (nrows.value(), my_shape.1.value()), (1, 1)); $me.assert_slice_index((row_start, 0), (nrows.value(), my_shape.1.value()), (0, 0));
let shape = (nrows, my_shape.1); let shape = (nrows, my_shape.1);
@ -309,7 +310,7 @@ macro_rules! matrix_slice_impl(
let my_shape = $me.data.shape(); let my_shape = $me.data.shape();
let my_strides = $me.data.strides(); let my_strides = $me.data.strides();
$me.assert_slice_index((row_start, 0), (nrows.value(), my_shape.1.value()), (step, 1)); $me.assert_slice_index((row_start, 0), (nrows.value(), my_shape.1.value()), (step, 0));
let strides = (Dynamic::new((step + 1) * my_strides.0.value()), my_strides.1); let strides = (Dynamic::new((step + 1) * my_strides.0.value()), my_strides.1);
let shape = (nrows, my_shape.1); let shape = (nrows, my_shape.1);
@ -378,7 +379,7 @@ macro_rules! matrix_slice_impl(
-> $MatrixSlice<N, R, CSlice, S::RStride, S::CStride> { -> $MatrixSlice<N, R, CSlice, S::RStride, S::CStride> {
let my_shape = $me.data.shape(); let my_shape = $me.data.shape();
$me.assert_slice_index((0, first_col), (my_shape.0.value(), ncols.value()), (1, 1)); $me.assert_slice_index((0, first_col), (my_shape.0.value(), ncols.value()), (0, 0));
let shape = (my_shape.0, ncols); let shape = (my_shape.0, ncols);
unsafe { unsafe {
@ -397,7 +398,7 @@ macro_rules! matrix_slice_impl(
let my_shape = $me.data.shape(); let my_shape = $me.data.shape();
let my_strides = $me.data.strides(); let my_strides = $me.data.strides();
$me.assert_slice_index((0, first_col), (my_shape.0.value(), ncols.value()), (1, step)); $me.assert_slice_index((0, first_col), (my_shape.0.value(), ncols.value()), (0, step));
let strides = (my_strides.0, Dynamic::new((step + 1) * my_strides.1.value())); let strides = (my_strides.0, Dynamic::new((step + 1) * my_strides.1.value()));
let shape = (my_shape.0, ncols); let shape = (my_shape.0, ncols);
@ -419,7 +420,7 @@ macro_rules! matrix_slice_impl(
pub fn $slice($me: $Me, start: (usize, usize), shape: (usize, usize)) pub fn $slice($me: $Me, start: (usize, usize), shape: (usize, usize))
-> $MatrixSlice<N, Dynamic, Dynamic, S::RStride, S::CStride> { -> $MatrixSlice<N, Dynamic, Dynamic, S::RStride, S::CStride> {
$me.assert_slice_index(start, shape, (1, 1)); $me.assert_slice_index(start, shape, (0, 0));
let shape = (Dynamic::new(shape.0), Dynamic::new(shape.1)); let shape = (Dynamic::new(shape.0), Dynamic::new(shape.1));
unsafe { unsafe {
@ -449,7 +450,7 @@ macro_rules! matrix_slice_impl(
where RSlice: DimName, where RSlice: DimName,
CSlice: DimName { CSlice: DimName {
$me.assert_slice_index((irow, icol), (RSlice::dim(), CSlice::dim()), (1, 1)); $me.assert_slice_index((irow, icol), (RSlice::dim(), CSlice::dim()), (0, 0));
let shape = (RSlice::name(), CSlice::name()); let shape = (RSlice::name(), CSlice::name());
unsafe { unsafe {
@ -478,7 +479,7 @@ macro_rules! matrix_slice_impl(
where RSlice: Dim, where RSlice: Dim,
CSlice: Dim { CSlice: Dim {
$me.assert_slice_index(start, (shape.0.value(), shape.1.value()), (1, 1)); $me.assert_slice_index(start, (shape.0.value(), shape.1.value()), (0, 0));
unsafe { unsafe {
let data = $SliceStorage::new_unchecked($data, start, shape); let data = $SliceStorage::new_unchecked($data, start, shape);
@ -644,12 +645,23 @@ matrix_slice_impl!(
columns_range_pair_mut); columns_range_pair_mut);
/// A range with a size that may be known at compile-time.
///
/// This may be:
/// * A single `usize` index, e.g., `4`
/// * A left-open range `std::ops::RangeTo`, e.g., `.. 4`
/// * A right-open range `std::ops::RangeFrom`, e.g., `4 ..`
/// * A full range `std::ops::RangeFull`, e.g., `..`
pub trait SliceRange<D: Dim> { pub trait SliceRange<D: Dim> {
/// Type of the range size. May be a type-level integer.
type Size: Dim; type Size: Dim;
/// The start index of the range.
fn begin(&self, shape: D) -> usize; fn begin(&self, shape: D) -> usize;
// NOTE: this is the index immediatly after the last index. // NOTE: this is the index immediatly after the last index.
/// The index immediatly after the last index inside of the range.
fn end(&self, shape: D) -> usize; fn end(&self, shape: D) -> usize;
/// The number of elements of the range, i.e., `self.end - self.begin`.
fn size(&self, shape: D) -> Self::Size; fn size(&self, shape: D) -> Self::Size;
} }
@ -750,6 +762,8 @@ impl<D: Dim> SliceRange<D> for RangeFull {
impl<N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> { impl<N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
/// Slices a sub-matrix containing the rows indexed by the range `rows` and the columns indexed
/// by the range `cols`.
#[inline] #[inline]
pub fn slice_range<RowRange, ColRange>(&self, rows: RowRange, cols: ColRange) pub fn slice_range<RowRange, ColRange>(&self, rows: RowRange, cols: ColRange)
-> MatrixSlice<N, RowRange::Size, ColRange::Size, S::RStride, S::CStride> -> MatrixSlice<N, RowRange::Size, ColRange::Size, S::RStride, S::CStride>
@ -761,6 +775,7 @@ impl<N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
(rows.size(nrows), cols.size(ncols))) (rows.size(nrows), cols.size(ncols)))
} }
/// Slice containing all the rows indexed by the range `rows`.
#[inline] #[inline]
pub fn rows_range<RowRange: SliceRange<R>>(&self, rows: RowRange) pub fn rows_range<RowRange: SliceRange<R>>(&self, rows: RowRange)
-> MatrixSlice<N, RowRange::Size, C, S::RStride, S::CStride> { -> MatrixSlice<N, RowRange::Size, C, S::RStride, S::CStride> {
@ -768,6 +783,7 @@ impl<N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
self.slice_range(rows, ..) self.slice_range(rows, ..)
} }
/// Slice containing all the columns indexed by the range `rows`.
#[inline] #[inline]
pub fn columns_range<ColRange: SliceRange<C>>(&self, cols: ColRange) pub fn columns_range<ColRange: SliceRange<C>>(&self, cols: ColRange)
-> MatrixSlice<N, R, ColRange::Size, S::RStride, S::CStride> { -> MatrixSlice<N, R, ColRange::Size, S::RStride, S::CStride> {
@ -777,6 +793,8 @@ impl<N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
} }
impl<N: Scalar, R: Dim, C: Dim, S: StorageMut<N, R, C>> Matrix<N, R, C, S> { impl<N: Scalar, R: Dim, C: Dim, S: StorageMut<N, R, C>> Matrix<N, R, C, S> {
/// Slices a mutable sub-matrix containing the rows indexed by the range `rows` and the columns
/// indexed by the range `cols`.
pub fn slice_range_mut<RowRange, ColRange>(&mut self, rows: RowRange, cols: ColRange) pub fn slice_range_mut<RowRange, ColRange>(&mut self, rows: RowRange, cols: ColRange)
-> MatrixSliceMut<N, RowRange::Size, ColRange::Size, S::RStride, S::CStride> -> MatrixSliceMut<N, RowRange::Size, ColRange::Size, S::RStride, S::CStride>
where RowRange: SliceRange<R>, where RowRange: SliceRange<R>,
@ -787,6 +805,7 @@ impl<N: Scalar, R: Dim, C: Dim, S: StorageMut<N, R, C>> Matrix<N, R, C, S> {
(rows.size(nrows), cols.size(ncols))) (rows.size(nrows), cols.size(ncols)))
} }
/// Slice containing all the rows indexed by the range `rows`.
#[inline] #[inline]
pub fn rows_range_mut<RowRange: SliceRange<R>>(&mut self, rows: RowRange) pub fn rows_range_mut<RowRange: SliceRange<R>>(&mut self, rows: RowRange)
-> MatrixSliceMut<N, RowRange::Size, C, S::RStride, S::CStride> { -> MatrixSliceMut<N, RowRange::Size, C, S::RStride, S::CStride> {
@ -794,6 +813,7 @@ impl<N: Scalar, R: Dim, C: Dim, S: StorageMut<N, R, C>> Matrix<N, R, C, S> {
self.slice_range_mut(rows, ..) self.slice_range_mut(rows, ..)
} }
/// Slice containing all the columns indexed by the range `cols`.
#[inline] #[inline]
pub fn columns_range_mut<ColRange: SliceRange<C>>(&mut self, cols: ColRange) pub fn columns_range_mut<ColRange: SliceRange<C>>(&mut self, cols: ColRange)
-> MatrixSliceMut<N, R, ColRange::Size, S::RStride, S::CStride> { -> MatrixSliceMut<N, R, ColRange::Size, S::RStride, S::CStride> {

View File

@ -7,6 +7,9 @@ use std::any::Any;
/// This does not make any assumption on the algebraic properties of `Self`. /// This does not make any assumption on the algebraic properties of `Self`.
pub trait Scalar: Copy + PartialEq + Debug + Any { pub trait Scalar: Copy + PartialEq + Debug + Any {
#[inline] #[inline]
/// Tests if `Self` the the same as the type `T`
///
/// Typically used to test of `Self` is a f32 or a f64 with `N::is::<f32>()`.
fn is<T: Scalar>() -> bool { fn is<T: Scalar>() -> bool {
TypeId::of::<Self>() == TypeId::of::<T>() TypeId::of::<Self>() == TypeId::of::<T>()
} }

View File

@ -15,7 +15,7 @@ Simply add the following to your `Cargo.toml` file:
```.ignore ```.ignore
[dependencies] [dependencies]
nalgebra = "0.12" nalgebra = "0.13"
``` ```
@ -84,7 +84,7 @@ an optimized set of tools for computer graphics and physics. Those features incl
#![deny(non_upper_case_globals)] #![deny(non_upper_case_globals)]
#![deny(unused_qualifications)] #![deny(unused_qualifications)]
#![deny(unused_results)] #![deny(unused_results)]
//#![warn(missing_docs)] #![deny(missing_docs)]
#![doc(html_root_url = "http://nalgebra.org/rustdoc")] #![doc(html_root_url = "http://nalgebra.org/rustdoc")]
#[cfg(feature = "arbitrary")] #[cfg(feature = "arbitrary")]

View File

@ -189,3 +189,59 @@ fn columns_range_pair() {
32.0, 33.0, 34.0); 32.0, 33.0, 34.0);
assert!(l.eq(&expected_l) && r.eq(&expected_r)); assert!(l.eq(&expected_l) && r.eq(&expected_r));
} }
#[test]
#[should_panic]
fn row_out_of_bounds() {
let a = Matrix3x4::<f32>::zeros();
a.row(3);
}
#[test]
#[should_panic]
fn rows_out_of_bounds() {
let a = Matrix3x4::<f32>::zeros();
a.rows(1, 3);
}
#[test]
#[should_panic]
fn rows_with_step_out_of_bounds() {
let a = Matrix3x4::<f32>::zeros();
a.rows_with_step(1, 2, 1);
}
#[test]
#[should_panic]
fn column_out_of_bounds() {
let a = Matrix3x4::<f32>::zeros();
a.column(4);
}
#[test]
#[should_panic]
fn columns_out_of_bounds() {
let a = Matrix3x4::<f32>::zeros();
a.columns(2, 3);
}
#[test]
#[should_panic]
fn columns_with_step_out_of_bounds() {
let a = Matrix3x4::<f32>::zeros();
a.columns_with_step(2, 2, 1);
}
#[test]
#[should_panic]
fn slice_out_of_bounds() {
let a = Matrix3x4::<f32>::zeros();
a.slice((1, 2), (3, 1));
}
#[test]
#[should_panic]
fn slice_with_steps_out_of_bounds() {
let a = Matrix3x4::<f32>::zeros();
a.slice_with_steps((1, 2), (2, 2), (0, 1));
}