Fix missing docs.

This commit is contained in:
Sébastien Crozet 2021-08-03 17:26:56 +02:00
parent d609a2f174
commit eedb860565
9 changed files with 59 additions and 49 deletions

View File

@ -4,7 +4,7 @@ documented here.
This project adheres to [Semantic Versioning](https://semver.org/). This project adheres to [Semantic Versioning](https://semver.org/).
## [0.29.0] ## [0.29.0] - WIP
### Modified ### Modified
- The closure given to `apply`, `zip_apply`, `zip_zip_apply` must now modify the - The closure given to `apply`, `zip_apply`, `zip_zip_apply` must now modify the
first argument inplace, instead of returning a new value. This makes these first argument inplace, instead of returning a new value. This makes these

View File

@ -22,7 +22,7 @@ use crate::base::dimension::{Const, ToTypenum};
use crate::base::storage::{IsContiguous, Owned, RawStorage, RawStorageMut, ReshapableStorage}; use crate::base::storage::{IsContiguous, Owned, RawStorage, RawStorageMut, ReshapableStorage};
use crate::base::Scalar; use crate::base::Scalar;
use crate::Storage; use crate::Storage;
use std::mem::{self, MaybeUninit}; use std::mem;
/* /*
* *
@ -35,12 +35,14 @@ use std::mem::{self, MaybeUninit};
pub struct ArrayStorage<T, const R: usize, const C: usize>(pub [[T; R]; C]); pub struct ArrayStorage<T, const R: usize, const C: usize>(pub [[T; R]; C]);
impl<T, const R: usize, const C: usize> ArrayStorage<T, R, C> { impl<T, const R: usize, const C: usize> ArrayStorage<T, R, C> {
/// Converts this array storage to a slice.
#[inline] #[inline]
pub fn as_slice(&self) -> &[T] { pub fn as_slice(&self) -> &[T] {
// SAFETY: this is OK because ArrayStorage is contiguous. // SAFETY: this is OK because ArrayStorage is contiguous.
unsafe { self.as_slice_unchecked() } unsafe { self.as_slice_unchecked() }
} }
/// Converts this array storage to a mutable slice.
#[inline] #[inline]
pub fn as_mut_slice(&mut self) -> &mut [T] { pub fn as_mut_slice(&mut self) -> &mut [T] {
// SAFETY: this is OK because ArrayStorage is contiguous. // SAFETY: this is OK because ArrayStorage is contiguous.
@ -237,14 +239,15 @@ where
where where
V: SeqAccess<'a>, V: SeqAccess<'a>,
{ {
let mut out: ArrayStorage<MaybeUninit<T>, R, C> = let mut out: ArrayStorage<core::mem::MaybeUninit<T>, R, C> =
DefaultAllocator::allocate_uninit(Const::<R>, Const::<C>); DefaultAllocator::allocate_uninit(Const::<R>, Const::<C>);
let mut curr = 0; let mut curr = 0;
while let Some(value) = visitor.next_element()? { while let Some(value) = visitor.next_element()? {
*out.as_mut_slice() *out.as_mut_slice()
.get_mut(curr) .get_mut(curr)
.ok_or_else(|| V::Error::invalid_length(curr, &self))? = MaybeUninit::new(value); .ok_or_else(|| V::Error::invalid_length(curr, &self))? =
core::mem::MaybeUninit::new(value);
curr += 1; curr += 1;
} }

View File

@ -73,19 +73,12 @@ fn array_axc<Status, T>(
} }
} }
/// Computes `self = a * x * c + b * self`. /// Computes `y = a * x * c + b * y`.
/// ///
/// If `b` is zero, `self` is never read from. /// If `b` is zero, `y` is never read from and may be uninitialized.
/// ///
/// # Examples: /// # Safety
/// /// This is UB if `Status == Uninit && b != 0`.
/// ```
/// # use nalgebra::Vector3;
/// let mut vec1 = Vector3::new(1.0, 2.0, 3.0);
/// let vec2 = Vector3::new(0.1, 0.2, 0.3);
/// vec1.axcpy(5.0, &vec2, 2.0, 5.0);
/// assert_eq!(vec1, Vector3::new(6.0, 12.0, 18.0));
/// ```
#[inline] #[inline]
#[allow(clippy::many_single_char_names)] #[allow(clippy::many_single_char_names)]
pub unsafe fn axcpy_uninit<Status, T, D1: Dim, D2: Dim, SA, SB>( pub unsafe fn axcpy_uninit<Status, T, D1: Dim, D2: Dim, SA, SB>(
@ -119,22 +112,13 @@ pub unsafe fn axcpy_uninit<Status, T, D1: Dim, D2: Dim, SA, SB>(
} }
} }
/// Computes `self = alpha * a * x + beta * self`, where `a` is a matrix, `x` a vector, and /// Computes `y = alpha * a * x + beta * y`, where `a` is a matrix, `x` a vector, and
/// `alpha, beta` two scalars. /// `alpha, beta` two scalars.
/// ///
/// If `beta` is zero, `self` is never read. /// If `beta` is zero, `y` is never read from and may be uninitialized.
/// ///
/// # Examples: /// # Safety
/// /// This is UB if `Status == Uninit && beta != 0`.
/// ```
/// # use nalgebra::{Matrix2, Vector2};
/// let mut vec1 = Vector2::new(1.0, 2.0);
/// let vec2 = Vector2::new(0.1, 0.2);
/// let mat = Matrix2::new(1.0, 2.0,
/// 3.0, 4.0);
/// vec1.gemv(10.0, &mat, &vec2, 5.0);
/// assert_eq!(vec1, Vector2::new(10.0, 21.0));
/// ```
#[inline] #[inline]
pub unsafe fn gemv_uninit<Status, T, D1: Dim, R2: Dim, C2: Dim, D3: Dim, SA, SB, SC>( pub unsafe fn gemv_uninit<Status, T, D1: Dim, R2: Dim, C2: Dim, D3: Dim, SA, SB, SC>(
status: Status, status: Status,
@ -193,27 +177,13 @@ pub unsafe fn gemv_uninit<Status, T, D1: Dim, R2: Dim, C2: Dim, D3: Dim, SA, SB,
} }
} }
/// Computes `self = alpha * a * b + beta * self`, where `a, b, self` are matrices. /// Computes `y = alpha * a * b + beta * y`, where `a, b, y` are matrices.
/// `alpha` and `beta` are scalar. /// `alpha` and `beta` are scalar.
/// ///
/// If `beta` is zero, `self` is never read. /// If `beta` is zero, `y` is never read from and may be uninitialized.
/// ///
/// # Examples: /// # Safety
/// /// This is UB if `Status == Uninit && beta != 0`.
/// ```
/// # #[macro_use] extern crate approx;
/// # use nalgebra::{Matrix2x3, Matrix3x4, Matrix2x4};
/// let mut mat1 = Matrix2x4::identity();
/// let mat2 = Matrix2x3::new(1.0, 2.0, 3.0,
/// 4.0, 5.0, 6.0);
/// let mat3 = Matrix3x4::new(0.1, 0.2, 0.3, 0.4,
/// 0.5, 0.6, 0.7, 0.8,
/// 0.9, 1.0, 1.1, 1.2);
/// let expected = mat2 * mat3 * 10.0 + mat1 * 5.0;
///
/// mat1.gemm(10.0, &mat2, &mat3, 5.0);
/// assert_relative_eq!(mat1, expected);
/// ```
#[inline] #[inline]
pub unsafe fn gemm_uninit< pub unsafe fn gemm_uninit<
Status, Status,

View File

@ -31,6 +31,7 @@ impl<T: Scalar, R: Dim, C: Dim> UninitMatrix<T, R, C>
where where
DefaultAllocator: Allocator<T, R, C>, DefaultAllocator: Allocator<T, R, C>,
{ {
/// Builds a matrix with uninitialized elements of type `MaybeUninit<T>`.
pub fn uninit(nrows: R, ncols: C) -> Self { pub fn uninit(nrows: R, ncols: C) -> Self {
// SAFETY: this is OK because the dimension automatically match the storage // SAFETY: this is OK because the dimension automatically match the storage
// because we are building an owned storage. // because we are building an owned storage.

View File

@ -451,6 +451,7 @@ impl<T, R: Dim, C: Dim, S: RawStorage<T, R, C>> Matrix<T, R, C, S> {
(nrows.value(), ncols.value()) (nrows.value(), ncols.value())
} }
/// The shape of this matrix wrapped into their representative types (`Const` or `Dynamic`).
#[inline] #[inline]
#[must_use] #[must_use]
pub fn shape_generic(&self) -> (R, C) { pub fn shape_generic(&self) -> (R, C) {

View File

@ -38,6 +38,7 @@ mod blas_uninit;
pub mod helper; pub mod helper;
mod interpolation; mod interpolation;
mod min_max; mod min_max;
/// Mechanisms for working with values that may not be initialized.
pub mod uninit; pub mod uninit;
pub use self::matrix::*; pub use self::matrix::*;

View File

@ -32,6 +32,9 @@ pub type CStride<T, R, C = U1> =
/// The trait shared by all matrix data storage. /// The trait shared by all matrix data storage.
/// ///
/// TODO: doc /// TODO: doc
/// In generic code, it is recommended use the `Storage` trait bound instead. The `RawStorage`
/// trait bound is generally used by code that needs to work with storages that contains
/// `MaybeUninit<T>` elements.
/// ///
/// Note that `Self` must always have a number of elements compatible with the matrix length (given /// Note that `Self` must always have a number of elements compatible with the matrix length (given
/// by `R` and `C` if they are known at compile-time). For example, implementors of this trait /// by `R` and `C` if they are known at compile-time). For example, implementors of this trait
@ -125,6 +128,7 @@ pub unsafe trait RawStorage<T, R: Dim, C: Dim = U1>: Sized {
unsafe fn as_slice_unchecked(&self) -> &[T]; unsafe fn as_slice_unchecked(&self) -> &[T];
} }
/// Trait shared by all matrix data storage that dont contain any uninitialized elements.
pub unsafe trait Storage<T, R: Dim, C: Dim = U1>: RawStorage<T, R, C> { pub unsafe trait Storage<T, R: Dim, C: Dim = U1>: RawStorage<T, R, C> {
/// Builds a matrix data storage that does not contain any reference. /// Builds a matrix data storage that does not contain any reference.
fn into_owned(self) -> Owned<T, R, C> fn into_owned(self) -> Owned<T, R, C>
@ -139,6 +143,10 @@ pub unsafe trait Storage<T, R: Dim, C: Dim = U1>: RawStorage<T, R, C> {
/// Trait implemented by matrix data storage that can provide a mutable access to its elements. /// Trait implemented by matrix data storage that can provide a mutable access to its elements.
/// ///
/// In generic code, it is recommended use the `StorageMut` trait bound instead. The
/// `RawStorageMut` trait bound is generally used by code that needs to work with storages that
/// contains `MaybeUninit<T>` elements.
///
/// Note that a mutable access does not mean that the matrix owns its data. For example, a mutable /// Note that a mutable access does not mean that the matrix owns its data. For example, a mutable
/// matrix slice can provide mutable access to its elements even if it does not own its data (it /// matrix slice can provide mutable access to its elements even if it does not own its data (it
/// contains only an internal reference to them). /// contains only an internal reference to them).
@ -217,6 +225,7 @@ pub unsafe trait RawStorageMut<T, R: Dim, C: Dim = U1>: RawStorage<T, R, C> {
unsafe fn as_mut_slice_unchecked(&mut self) -> &mut [T]; unsafe fn as_mut_slice_unchecked(&mut self) -> &mut [T];
} }
/// Trait shared by all mutable matrix data storage that dont contain any uninitialized elements.
pub unsafe trait StorageMut<T, R: Dim, C: Dim = U1>: pub unsafe trait StorageMut<T, R: Dim, C: Dim = U1>:
Storage<T, R, C> + RawStorageMut<T, R, C> Storage<T, R, C> + RawStorageMut<T, R, C>
{ {

View File

@ -1,19 +1,44 @@
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
// # Safety /// This trait is used to write code that may work on matrices that may or may not
// This trait must not be implemented outside of this crate. /// be initialized.
///
/// This trait is used to describe how a value must be accessed to initialize it or
/// to retrieve a reference or mutable reference. Typically, a function accepting
/// both initialized and uninitialized inputs should have a `Status: InitStatus<T>`
/// type parameter. Then the methods of the `Status` can be used to access the element.
///
/// # Safety
/// This trait must not be implemented outside of this crate.
pub unsafe trait InitStatus<T>: Copy { pub unsafe trait InitStatus<T>: Copy {
/// The type of the values with the initialization status described by `Self`.
type Value; type Value;
/// Initialize the given element.
fn init(out: &mut Self::Value, t: T); fn init(out: &mut Self::Value, t: T);
/// Retrieve a reference to the element, assuming that it is initialized.
///
/// # Safety
/// This is unsound if the referenced value isnt initialized.
unsafe fn assume_init_ref(t: &Self::Value) -> &T; unsafe fn assume_init_ref(t: &Self::Value) -> &T;
/// Retrieve a mutable reference to the element, assuming that it is initialized.
///
/// # Safety
/// This is unsound if the referenced value isnt initialized.
unsafe fn assume_init_mut(t: &mut Self::Value) -> &mut T; unsafe fn assume_init_mut(t: &mut Self::Value) -> &mut T;
} }
#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
/// A type implementing `InitStatus` indicating that the value is completely initialized.
pub struct Init; pub struct Init;
#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
/// A type implementing `InitStatus` indicating that the value is completely unitialized.
pub struct Uninit; pub struct Uninit;
#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
/// A type implementing `InitStatus` indicating that the value is initialized even if the value
/// has the type `MaybeUninit` (i.e. when `Status == Uninit`).
pub struct Initialized<Status>(pub Status); pub struct Initialized<Status>(pub Status);
unsafe impl<T> InitStatus<T> for Init { unsafe impl<T> InitStatus<T> for Init {

View File

@ -73,6 +73,7 @@ an optimized set of tools for computer graphics and physics. Those features incl
#![allow(unused_variables, unused_mut)] #![allow(unused_variables, unused_mut)]
#![deny( #![deny(
missing_docs,
nonstandard_style, nonstandard_style,
unused_parens, unused_parens,
unused_qualifications, unused_qualifications,
@ -82,7 +83,6 @@ an optimized set of tools for computer graphics and physics. Those features incl
future_incompatible, future_incompatible,
missing_copy_implementations missing_copy_implementations
)] )]
// #![deny(missing_docs)] // XXX: deny that
#![doc( #![doc(
html_favicon_url = "https://nalgebra.org/img/favicon.ico", html_favicon_url = "https://nalgebra.org/img/favicon.ico",
html_root_url = "https://docs.rs/nalgebra/0.25.0" html_root_url = "https://docs.rs/nalgebra/0.25.0"