From 9a4cf0b69fd0d320f26ce8f0afe99831fa4993c4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Crozet=20S=C3=A9bastien?= <developer@crozet.re>
Date: Fri, 13 Nov 2020 18:34:47 +0100
Subject: [PATCH] Reorganize matrix construction macros.

---
 src/base/construction.rs | 518 ++++++++++++++++++++-------------------
 src/base/matrix.rs       |  67 +++--
 2 files changed, 316 insertions(+), 269 deletions(-)

diff --git a/src/base/construction.rs b/src/base/construction.rs
index aa4cf956..4718309b 100644
--- a/src/base/construction.rs
+++ b/src/base/construction.rs
@@ -22,11 +22,12 @@ use crate::base::dimension::{Dim, DimName, Dynamic, U1, U2, U3, U4, U5, U6};
 use crate::base::storage::Storage;
 use crate::base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, Scalar, Unit, Vector, VectorN};
 
-/*
- *
- * Generic constructors.
- *
- */
+/// # Generic constructors
+/// This set of matrix and vector construction functions are all generic
+/// with-regard to the matrix dimensions. They all expect to be given
+/// the dimension as inputs.
+///
+/// These functions should only be used when working on dimension-generic code.
 impl<N: Scalar, R: Dim, C: Dim> MatrixMN<N, R, C>
 where
     DefaultAllocator: Allocator<N, R, C>,
@@ -350,275 +351,290 @@ where
  */
 macro_rules! impl_constructors(
     ($($Dims: ty),*; $(=> $DimIdent: ident: $DimBound: ident),*; $($gargs: expr),*; $($args: ident),*) => {
-        impl<N: Scalar, $($DimIdent: $DimBound, )*> MatrixMN<N $(, $Dims)*>
-            where DefaultAllocator: Allocator<N $(, $Dims)*> {
-
-            /// Creates a new uninitialized matrix or vector.
-            #[inline]
-            pub unsafe fn new_uninitialized($($args: usize),*) -> Self {
-                Self::new_uninitialized_generic($($gargs),*)
-            }
-
-            /// Creates a matrix or vector with all its elements set to `elem`.
-            ///
-            /// # Example
-            /// ```
-            /// # use nalgebra::{Matrix2x3, Vector3, DVector, DMatrix};
-            ///
-            /// let v = Vector3::from_element(2.0);
-            /// // The additional argument represents the vector dimension.
-            /// let dv = DVector::from_element(3, 2.0);
-            /// let m = Matrix2x3::from_element(2.0);
-            /// // The two additional arguments represent the matrix dimensions.
-            /// let dm = DMatrix::from_element(2, 3, 2.0);
-            ///
-            /// assert!(v.x == 2.0 && v.y == 2.0 && v.z == 2.0);
-            /// assert!(dv[0] == 2.0 && dv[1] == 2.0 && dv[2] == 2.0);
-            /// assert!(m.m11 == 2.0 && m.m12 == 2.0 && m.m13 == 2.0 &&
-            ///         m.m21 == 2.0 && m.m22 == 2.0 && m.m23 == 2.0);
-            /// assert!(dm[(0, 0)] == 2.0 && dm[(0, 1)] == 2.0 && dm[(0, 2)] == 2.0 &&
-            ///         dm[(1, 0)] == 2.0 && dm[(1, 1)] == 2.0 && dm[(1, 2)] == 2.0);
-            /// ```
-            #[inline]
-            pub fn from_element($($args: usize,)* elem: N) -> Self {
-                Self::from_element_generic($($gargs, )* elem)
-            }
-
-            /// Creates a matrix or vector with all its elements set to `elem`.
-            ///
-            /// Same as `.from_element`.
-            ///
-            /// # Example
-            /// ```
-            /// # use nalgebra::{Matrix2x3, Vector3, DVector, DMatrix};
-            ///
-            /// let v = Vector3::repeat(2.0);
-            /// // The additional argument represents the vector dimension.
-            /// let dv = DVector::repeat(3, 2.0);
-            /// let m = Matrix2x3::repeat(2.0);
-            /// // The two additional arguments represent the matrix dimensions.
-            /// let dm = DMatrix::repeat(2, 3, 2.0);
-            ///
-            /// assert!(v.x == 2.0 && v.y == 2.0 && v.z == 2.0);
-            /// assert!(dv[0] == 2.0 && dv[1] == 2.0 && dv[2] == 2.0);
-            /// assert!(m.m11 == 2.0 && m.m12 == 2.0 && m.m13 == 2.0 &&
-            ///         m.m21 == 2.0 && m.m22 == 2.0 && m.m23 == 2.0);
-            /// assert!(dm[(0, 0)] == 2.0 && dm[(0, 1)] == 2.0 && dm[(0, 2)] == 2.0 &&
-            ///         dm[(1, 0)] == 2.0 && dm[(1, 1)] == 2.0 && dm[(1, 2)] == 2.0);
-            /// ```
-            #[inline]
-            pub fn repeat($($args: usize,)* elem: N) -> Self {
-                Self::repeat_generic($($gargs, )* elem)
-            }
-
-            /// Creates a matrix or vector with all its elements set to `0`.
-            ///
-            /// # Example
-            /// ```
-            /// # use nalgebra::{Matrix2x3, Vector3, DVector, DMatrix};
-            ///
-            /// let v = Vector3::<f32>::zeros();
-            /// // The argument represents the vector dimension.
-            /// let dv = DVector::<f32>::zeros(3);
-            /// let m = Matrix2x3::<f32>::zeros();
-            /// // The two arguments represent the matrix dimensions.
-            /// let dm = DMatrix::<f32>::zeros(2, 3);
-            ///
-            /// assert!(v.x == 0.0 && v.y == 0.0 && v.z == 0.0);
-            /// assert!(dv[0] == 0.0 && dv[1] == 0.0 && dv[2] == 0.0);
-            /// assert!(m.m11 == 0.0 && m.m12 == 0.0 && m.m13 == 0.0 &&
-            ///         m.m21 == 0.0 && m.m22 == 0.0 && m.m23 == 0.0);
-            /// assert!(dm[(0, 0)] == 0.0 && dm[(0, 1)] == 0.0 && dm[(0, 2)] == 0.0 &&
-            ///         dm[(1, 0)] == 0.0 && dm[(1, 1)] == 0.0 && dm[(1, 2)] == 0.0);
-            /// ```
-            #[inline]
-            pub fn zeros($($args: usize),*) -> Self
-                where N: Zero {
-                Self::zeros_generic($($gargs),*)
-            }
-
-            /// Creates a matrix or vector with all its elements filled by an iterator.
-            ///
-            /// The output matrix is filled column-by-column.
-            ///
-            /// # Example
-            /// ```
-            /// # use nalgebra::{Matrix2x3, Vector3, DVector, DMatrix};
-            /// # use std::iter;
-            ///
-            /// let v = Vector3::from_iterator((0..3).into_iter());
-            /// // The additional argument represents the vector dimension.
-            /// let dv = DVector::from_iterator(3, (0..3).into_iter());
-            /// let m = Matrix2x3::from_iterator((0..6).into_iter());
-            /// // The two additional arguments represent the matrix dimensions.
-            /// let dm = DMatrix::from_iterator(2, 3, (0..6).into_iter());
-            ///
-            /// 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_iterator<I>($($args: usize,)* iter: I) -> Self
-                where I: IntoIterator<Item = N> {
-                Self::from_iterator_generic($($gargs, )* iter)
-            }
-
-            /// Creates a matrix or vector filled with the results of a function applied to each of its
-            /// component coordinates.
-            ///
-            /// # Example
-            /// ```
-            /// # use nalgebra::{Matrix2x3, Vector3, DVector, DMatrix};
-            /// # use std::iter;
-            ///
-            /// let v = Vector3::from_fn(|i, _| i);
-            /// // The additional argument represents the vector dimension.
-            /// let dv = DVector::from_fn(3, |i, _| i);
-            /// let m = Matrix2x3::from_fn(|i, j| i * 3 + j);
-            /// // The two additional arguments represent the matrix dimensions.
-            /// let dm = DMatrix::from_fn(2, 3, |i, j| i * 3 + j);
-            ///
-            /// 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_fn<F>($($args: usize,)* f: F) -> Self
-                where F: FnMut(usize, usize) -> N {
-                Self::from_fn_generic($($gargs, )* f)
-            }
-
-            /// Creates an identity matrix. If the matrix is not square, the largest square
-            /// submatrix (starting at the first row and column) is set to the identity while all
-            /// other entries are set to zero.
-            ///
-            /// # Example
-            /// ```
-            /// # use nalgebra::{Matrix2x3, DMatrix};
-            /// # use std::iter;
-            ///
-            /// let m = Matrix2x3::<f32>::identity();
-            /// // The two additional arguments represent the matrix dimensions.
-            /// let dm = DMatrix::<f32>::identity(2, 3);
-            ///
-            /// assert!(m.m11 == 1.0 && m.m12 == 0.0 && m.m13 == 0.0 &&
-            ///         m.m21 == 0.0 && m.m22 == 1.0 && m.m23 == 0.0);
-            /// assert!(dm[(0, 0)] == 1.0 && dm[(0, 1)] == 0.0 && dm[(0, 2)] == 0.0 &&
-            ///         dm[(1, 0)] == 0.0 && dm[(1, 1)] == 1.0 && dm[(1, 2)] == 0.0);
-            /// ```
-            #[inline]
-            pub fn identity($($args: usize,)*) -> Self
-                where N: Zero + One {
-                Self::identity_generic($($gargs),* )
-            }
-
-            /// Creates a matrix filled with its diagonal filled with `elt` and all other
-            /// components set to zero.
-            ///
-            /// # Example
-            /// ```
-            /// # use nalgebra::{Matrix2x3, DMatrix};
-            /// # use std::iter;
-            ///
-            /// let m = Matrix2x3::from_diagonal_element(5.0);
-            /// // The two additional arguments represent the matrix dimensions.
-            /// let dm = DMatrix::from_diagonal_element(2, 3, 5.0);
-            ///
-            /// assert!(m.m11 == 5.0 && m.m12 == 0.0 && m.m13 == 0.0 &&
-            ///         m.m21 == 0.0 && m.m22 == 5.0 && m.m23 == 0.0);
-            /// assert!(dm[(0, 0)] == 5.0 && dm[(0, 1)] == 0.0 && dm[(0, 2)] == 0.0 &&
-            ///         dm[(1, 0)] == 0.0 && dm[(1, 1)] == 5.0 && dm[(1, 2)] == 0.0);
-            /// ```
-            #[inline]
-            pub fn from_diagonal_element($($args: usize,)* elt: N) -> Self
-                where N: Zero + One {
-                Self::from_diagonal_element_generic($($gargs, )* elt)
-            }
-
-            /// Creates a new matrix that may be rectangular. The first `elts.len()` diagonal
-            /// elements are filled with the content of `elts`. Others are set to 0.
-            ///
-            /// Panics if `elts.len()` is larger than the minimum among `nrows` and `ncols`.
-            ///
-            /// # Example
-            /// ```
-            /// # use nalgebra::{Matrix3, DMatrix};
-            /// # use std::iter;
-            ///
-            /// let m = Matrix3::from_partial_diagonal(&[1.0, 2.0]);
-            /// // The two additional arguments represent the matrix dimensions.
-            /// let dm = DMatrix::from_partial_diagonal(3, 3, &[1.0, 2.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 &&
-            ///         m.m31 == 0.0 && m.m32 == 0.0 && m.m33 == 0.0);
-            /// assert!(dm[(0, 0)] == 1.0 && dm[(0, 1)] == 0.0 && dm[(0, 2)] == 0.0 &&
-            ///         dm[(1, 0)] == 0.0 && dm[(1, 1)] == 2.0 && dm[(1, 2)] == 0.0 &&
-            ///         dm[(2, 0)] == 0.0 && dm[(2, 1)] == 0.0 && dm[(2, 2)] == 0.0);
-            /// ```
-            #[inline]
-            pub fn from_partial_diagonal($($args: usize,)* elts: &[N]) -> Self
-                where N: Zero {
-                Self::from_partial_diagonal_generic($($gargs, )* elts)
-            }
-
-            /// Creates a matrix or vector filled with random values from the given distribution.
-            #[inline]
-            pub fn from_distribution<Distr: Distribution<N> + ?Sized, G: Rng + ?Sized>(
-                $($args: usize,)*
-                distribution: &Distr,
-                rng: &mut G,
-            ) -> Self {
-                Self::from_distribution_generic($($gargs, )* distribution, rng)
-            }
+        /// Creates a new uninitialized matrix or vector.
+        #[inline]
+        pub unsafe fn new_uninitialized($($args: usize),*) -> Self {
+            Self::new_uninitialized_generic($($gargs),*)
         }
 
-        impl<N: Scalar, $($DimIdent: $DimBound, )*> MatrixMN<N $(, $Dims)*>
-            where
-            DefaultAllocator: Allocator<N $(, $Dims)*>,
-            Standard: Distribution<N> {
+        /// Creates a matrix or vector with all its elements set to `elem`.
+        ///
+        /// # Example
+        /// ```
+        /// # use nalgebra::{Matrix2x3, Vector3, DVector, DMatrix};
+        ///
+        /// let v = Vector3::from_element(2.0);
+        /// // The additional argument represents the vector dimension.
+        /// let dv = DVector::from_element(3, 2.0);
+        /// let m = Matrix2x3::from_element(2.0);
+        /// // The two additional arguments represent the matrix dimensions.
+        /// let dm = DMatrix::from_element(2, 3, 2.0);
+        ///
+        /// assert!(v.x == 2.0 && v.y == 2.0 && v.z == 2.0);
+        /// assert!(dv[0] == 2.0 && dv[1] == 2.0 && dv[2] == 2.0);
+        /// assert!(m.m11 == 2.0 && m.m12 == 2.0 && m.m13 == 2.0 &&
+        ///         m.m21 == 2.0 && m.m22 == 2.0 && m.m23 == 2.0);
+        /// assert!(dm[(0, 0)] == 2.0 && dm[(0, 1)] == 2.0 && dm[(0, 2)] == 2.0 &&
+        ///         dm[(1, 0)] == 2.0 && dm[(1, 1)] == 2.0 && dm[(1, 2)] == 2.0);
+        /// ```
+        #[inline]
+        pub fn from_element($($args: usize,)* elem: N) -> Self {
+            Self::from_element_generic($($gargs, )* elem)
+        }
 
-            /// Creates a matrix filled with random values.
-            #[inline]
-            #[cfg(feature = "std")]
-            pub fn new_random($($args: usize),*) -> Self {
-                Self::new_random_generic($($gargs),*)
-            }
+        /// Creates a matrix or vector with all its elements set to `elem`.
+        ///
+        /// Same as `.from_element`.
+        ///
+        /// # Example
+        /// ```
+        /// # use nalgebra::{Matrix2x3, Vector3, DVector, DMatrix};
+        ///
+        /// let v = Vector3::repeat(2.0);
+        /// // The additional argument represents the vector dimension.
+        /// let dv = DVector::repeat(3, 2.0);
+        /// let m = Matrix2x3::repeat(2.0);
+        /// // The two additional arguments represent the matrix dimensions.
+        /// let dm = DMatrix::repeat(2, 3, 2.0);
+        ///
+        /// assert!(v.x == 2.0 && v.y == 2.0 && v.z == 2.0);
+        /// assert!(dv[0] == 2.0 && dv[1] == 2.0 && dv[2] == 2.0);
+        /// assert!(m.m11 == 2.0 && m.m12 == 2.0 && m.m13 == 2.0 &&
+        ///         m.m21 == 2.0 && m.m22 == 2.0 && m.m23 == 2.0);
+        /// assert!(dm[(0, 0)] == 2.0 && dm[(0, 1)] == 2.0 && dm[(0, 2)] == 2.0 &&
+        ///         dm[(1, 0)] == 2.0 && dm[(1, 1)] == 2.0 && dm[(1, 2)] == 2.0);
+        /// ```
+        #[inline]
+        pub fn repeat($($args: usize,)* elem: N) -> Self {
+            Self::repeat_generic($($gargs, )* elem)
+        }
+
+        /// Creates a matrix or vector with all its elements set to `0`.
+        ///
+        /// # Example
+        /// ```
+        /// # use nalgebra::{Matrix2x3, Vector3, DVector, DMatrix};
+        ///
+        /// let v = Vector3::<f32>::zeros();
+        /// // The argument represents the vector dimension.
+        /// let dv = DVector::<f32>::zeros(3);
+        /// let m = Matrix2x3::<f32>::zeros();
+        /// // The two arguments represent the matrix dimensions.
+        /// let dm = DMatrix::<f32>::zeros(2, 3);
+        ///
+        /// assert!(v.x == 0.0 && v.y == 0.0 && v.z == 0.0);
+        /// assert!(dv[0] == 0.0 && dv[1] == 0.0 && dv[2] == 0.0);
+        /// assert!(m.m11 == 0.0 && m.m12 == 0.0 && m.m13 == 0.0 &&
+        ///         m.m21 == 0.0 && m.m22 == 0.0 && m.m23 == 0.0);
+        /// assert!(dm[(0, 0)] == 0.0 && dm[(0, 1)] == 0.0 && dm[(0, 2)] == 0.0 &&
+        ///         dm[(1, 0)] == 0.0 && dm[(1, 1)] == 0.0 && dm[(1, 2)] == 0.0);
+        /// ```
+        #[inline]
+        pub fn zeros($($args: usize),*) -> Self
+            where N: Zero {
+            Self::zeros_generic($($gargs),*)
+        }
+
+        /// Creates a matrix or vector with all its elements filled by an iterator.
+        ///
+        /// The output matrix is filled column-by-column.
+        ///
+        /// # Example
+        /// ```
+        /// # use nalgebra::{Matrix2x3, Vector3, DVector, DMatrix};
+        /// # use std::iter;
+        ///
+        /// let v = Vector3::from_iterator((0..3).into_iter());
+        /// // The additional argument represents the vector dimension.
+        /// let dv = DVector::from_iterator(3, (0..3).into_iter());
+        /// let m = Matrix2x3::from_iterator((0..6).into_iter());
+        /// // The two additional arguments represent the matrix dimensions.
+        /// let dm = DMatrix::from_iterator(2, 3, (0..6).into_iter());
+        ///
+        /// 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_iterator<I>($($args: usize,)* iter: I) -> Self
+            where I: IntoIterator<Item = N> {
+            Self::from_iterator_generic($($gargs, )* iter)
+        }
+
+        /// Creates a matrix or vector filled with the results of a function applied to each of its
+        /// component coordinates.
+        ///
+        /// # Example
+        /// ```
+        /// # use nalgebra::{Matrix2x3, Vector3, DVector, DMatrix};
+        /// # use std::iter;
+        ///
+        /// let v = Vector3::from_fn(|i, _| i);
+        /// // The additional argument represents the vector dimension.
+        /// let dv = DVector::from_fn(3, |i, _| i);
+        /// let m = Matrix2x3::from_fn(|i, j| i * 3 + j);
+        /// // The two additional arguments represent the matrix dimensions.
+        /// let dm = DMatrix::from_fn(2, 3, |i, j| i * 3 + j);
+        ///
+        /// 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_fn<F>($($args: usize,)* f: F) -> Self
+            where F: FnMut(usize, usize) -> N {
+            Self::from_fn_generic($($gargs, )* f)
+        }
+
+        /// Creates an identity matrix. If the matrix is not square, the largest square
+        /// submatrix (starting at the first row and column) is set to the identity while all
+        /// other entries are set to zero.
+        ///
+        /// # Example
+        /// ```
+        /// # use nalgebra::{Matrix2x3, DMatrix};
+        /// # use std::iter;
+        ///
+        /// let m = Matrix2x3::<f32>::identity();
+        /// // The two additional arguments represent the matrix dimensions.
+        /// let dm = DMatrix::<f32>::identity(2, 3);
+        ///
+        /// assert!(m.m11 == 1.0 && m.m12 == 0.0 && m.m13 == 0.0 &&
+        ///         m.m21 == 0.0 && m.m22 == 1.0 && m.m23 == 0.0);
+        /// assert!(dm[(0, 0)] == 1.0 && dm[(0, 1)] == 0.0 && dm[(0, 2)] == 0.0 &&
+        ///         dm[(1, 0)] == 0.0 && dm[(1, 1)] == 1.0 && dm[(1, 2)] == 0.0);
+        /// ```
+        #[inline]
+        pub fn identity($($args: usize,)*) -> Self
+            where N: Zero + One {
+            Self::identity_generic($($gargs),* )
+        }
+
+        /// Creates a matrix filled with its diagonal filled with `elt` and all other
+        /// components set to zero.
+        ///
+        /// # Example
+        /// ```
+        /// # use nalgebra::{Matrix2x3, DMatrix};
+        /// # use std::iter;
+        ///
+        /// let m = Matrix2x3::from_diagonal_element(5.0);
+        /// // The two additional arguments represent the matrix dimensions.
+        /// let dm = DMatrix::from_diagonal_element(2, 3, 5.0);
+        ///
+        /// assert!(m.m11 == 5.0 && m.m12 == 0.0 && m.m13 == 0.0 &&
+        ///         m.m21 == 0.0 && m.m22 == 5.0 && m.m23 == 0.0);
+        /// assert!(dm[(0, 0)] == 5.0 && dm[(0, 1)] == 0.0 && dm[(0, 2)] == 0.0 &&
+        ///         dm[(1, 0)] == 0.0 && dm[(1, 1)] == 5.0 && dm[(1, 2)] == 0.0);
+        /// ```
+        #[inline]
+        pub fn from_diagonal_element($($args: usize,)* elt: N) -> Self
+            where N: Zero + One {
+            Self::from_diagonal_element_generic($($gargs, )* elt)
+        }
+
+        /// Creates a new matrix that may be rectangular. The first `elts.len()` diagonal
+        /// elements are filled with the content of `elts`. Others are set to 0.
+        ///
+        /// Panics if `elts.len()` is larger than the minimum among `nrows` and `ncols`.
+        ///
+        /// # Example
+        /// ```
+        /// # use nalgebra::{Matrix3, DMatrix};
+        /// # use std::iter;
+        ///
+        /// let m = Matrix3::from_partial_diagonal(&[1.0, 2.0]);
+        /// // The two additional arguments represent the matrix dimensions.
+        /// let dm = DMatrix::from_partial_diagonal(3, 3, &[1.0, 2.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 &&
+        ///         m.m31 == 0.0 && m.m32 == 0.0 && m.m33 == 0.0);
+        /// assert!(dm[(0, 0)] == 1.0 && dm[(0, 1)] == 0.0 && dm[(0, 2)] == 0.0 &&
+        ///         dm[(1, 0)] == 0.0 && dm[(1, 1)] == 2.0 && dm[(1, 2)] == 0.0 &&
+        ///         dm[(2, 0)] == 0.0 && dm[(2, 1)] == 0.0 && dm[(2, 2)] == 0.0);
+        /// ```
+        #[inline]
+        pub fn from_partial_diagonal($($args: usize,)* elts: &[N]) -> Self
+            where N: Zero {
+            Self::from_partial_diagonal_generic($($gargs, )* elts)
+        }
+
+        /// Creates a matrix or vector filled with random values from the given distribution.
+        #[inline]
+        pub fn from_distribution<Distr: Distribution<N> + ?Sized, G: Rng + ?Sized>(
+            $($args: usize,)*
+            distribution: &Distr,
+            rng: &mut G,
+        ) -> Self {
+            Self::from_distribution_generic($($gargs, )* distribution, rng)
+        }
+
+        /// Creates a matrix filled with random values.
+        #[inline]
+        #[cfg(feature = "std")]
+        pub fn new_random($($args: usize),*) -> Self
+            where Standard: Distribution<N> {
+            Self::new_random_generic($($gargs),*)
         }
     }
 );
 
-// FIXME: this is not very pretty. We could find a better call syntax.
-impl_constructors!(R, C;                         // Arguments for Matrix<N, ..., S>
-=> R: DimName, => C: DimName; // Type parameters for impl<N, ..., S>
-R::name(), C::name();         // Arguments for `_generic` constructors.
-); // Arguments for non-generic constructors.
+/// # Constructors of statically-sized vectors or statically-sized matrices
+impl<N: Scalar, R: DimName, C: DimName> MatrixMN<N, R, C>
+where
+    DefaultAllocator: Allocator<N, R, C>,
+{
+    // FIXME: this is not very pretty. We could find a better call syntax.
+    impl_constructors!(R, C;                         // Arguments for Matrix<N, ..., S>
+    => R: DimName, => C: DimName; // Type parameters for impl<N, ..., S>
+    R::name(), C::name();         // Arguments for `_generic` constructors.
+    ); // Arguments for non-generic constructors.
+}
 
-impl_constructors!(R, Dynamic;
+/// # Constructors of matrices with a dynamic number of columns
+impl<N: Scalar, R: DimName> MatrixMN<N, R, Dynamic>
+where
+    DefaultAllocator: Allocator<N, R, Dynamic>,
+{
+    impl_constructors!(R, Dynamic;
                    => R: DimName;
                    R::name(), Dynamic::new(ncols);
                    ncols);
+}
 
-impl_constructors!(Dynamic, C;
+/// # Constructors of dynamic vectors and matrices with a dynamic number of rows
+impl<N: Scalar, C: DimName> MatrixMN<N, Dynamic, C>
+where
+    DefaultAllocator: Allocator<N, Dynamic, C>,
+{
+    impl_constructors!(Dynamic, C;
                    => C: DimName;
                    Dynamic::new(nrows), C::name();
                    nrows);
+}
 
-impl_constructors!(Dynamic, Dynamic;
+/// # Constructors of fully dynamic matrices
+impl<N: Scalar> MatrixMN<N, Dynamic, Dynamic>
+where
+    DefaultAllocator: Allocator<N, Dynamic, Dynamic>,
+{
+    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.
+ * to be specified when one dimension is already known.
  *
  */
 macro_rules! impl_constructors_from_data(
diff --git a/src/base/matrix.rs b/src/base/matrix.rs
index 2ba91826..b510d9af 100644
--- a/src/base/matrix.rs
+++ b/src/base/matrix.rs
@@ -54,7 +54,34 @@ pub type MatrixCross<N, R1, C1, R2, C2> =
 
 /// The most generic column-major matrix (and vector) type.
 ///
-/// It combines four type parameters:
+/// # Methods summary
+/// Because `Matrix` is the most generic types that groups all matrix and vectors of **nalgebra**
+/// this documentation page contains every single matrix/vector-related method. In order to make
+/// browsing this page simpler, the next subsections contain direct links to groups of methods
+/// related to a specific topic.
+///
+/// #### Vector and matrix construction
+/// - [Constructors of statically-sized vectors or statically-sized matrices](#constructors-of-statically-sized-vectors-or-statically-sized-matrices)
+///   (`Vector3`, `Matrix3x6`, etc.)
+/// - [Constructors of fully dynamic matrices](#constructors-of-fully-dynamic-matrices) (`DMatrix`)
+/// - [Constructors of dynamic vectors and matrices with a dynamic number of rows](#constructors-of-dynamic-vectors-and-matrices-with-a-dynamic-number-of-rows)
+///   (`DVector`, `MatrixXx3`, etc.)
+/// - [Constructors of matrices with a dynamic number of columns](#constructors-of-matrices-with-a-dynamic-number-of-columns)
+///   (`Matrix2xX`, etc.)
+/// - [Generic constructors](#generic-constructors)
+///   (For code generic wrt. the vectors or matrices dimensions.)
+/// #### Matrix decomposition
+/// - [Rectangular matrix decomposition](#rectangular-matrix-decomposition) (Applicable to square matrices too)
+/// - [Square matrix decomposition](#square-matrix-decomposition)
+///
+/// #### Vector and matrix slicing
+/// - [Slicing based on index and length](#slicing-based-on-index-and-length)
+/// - [Mutable slicing based on index and length](#mutable-slicing-based-on-index-and-length)
+/// - [Slicing based on ranges](#slicing-based-on-ranges)
+/// - [Mutable slicing based on ranges](#mutable-slicing-based-on-ranges)
+///
+/// # Type parameters
+/// The generic `Matrix` type has four type parameters:
 /// - `N`: for the matrix components scalar type.
 /// - `R`: for the matrix number of rows.
 /// - `C`: for the matrix number of columns.
@@ -75,26 +102,30 @@ pub type MatrixCross<N, R1, C1, R2, C2> =
 /// Note that mixing `Dynamic` with type-level unsigned integers is allowed. Actually, a
 /// dynamically-sized column vector should be represented as a `Matrix<N, Dynamic, U1, S>` (given
 /// some concrete types for `N` and a compatible data storage type `S`).
-///
-/// # Documentation by feature
-/// Because `Matrix` is the most generic types that groups all matrix and vectors of **nalgebra**
-/// this documentation page contains every single matrix/vector-related method. In order to make
-/// browsing this page simpler, the next subsections contain direct links to groups of methods
-/// related to a specific topic.
-///
-/// #### Matrix decomposition
-/// - [Rectangular matrix decomposition](#rectangular-matrix-decomposition).
-/// - [Square matrix decomposition](#square-matrix-decomposition).
-///
-/// #### Matrix slicing
-/// - [Slicing](#slicing)
-/// - [Mutable slicing](#mutable-slicing)
-/// - [Range-based slicing](#range-based-slicing), [mutable range-based slicing](#mutable-range-based-slicing).
 #[repr(C)]
 #[derive(Clone, Copy)]
 pub struct Matrix<N: Scalar, R: Dim, C: Dim, S> {
-    /// The data storage that contains all the matrix components and informations about its number
-    /// of rows and column (if needed).
+    /// The data storage that contains all the matrix components. Disappointed?
+    ///
+    /// Well, if you came here to see how you can access the matrix components,
+    /// you may be in luck: you can access the individual components of all vectors with compile-time
+    /// dimensions <= 6 using field notation like this:
+    /// `vec.x`, `vec.y`, `vec.z`, `vec.w`, `vec.a`, `vec.b`. Reference and assignation work too:
+    /// ```.ignore
+    /// let mut v = Vector3::new(1.0, 2.0, 3.0);
+    /// vec.x = 10.0;
+    /// my_function(&vec.z);
+    /// println!("{}", vec.y + 30.0);
+    /// ```
+    /// Similarly, for matrices with compile-time dimensions <= 6, you can use field notation
+    /// like this: `mat.m11`, `mat.m42`, etc. The first digit identifies the row to address
+    /// and the second digit identifies the column to address. So `mat.m13` identifies the component
+    /// at the first row and third column (note that the count of rows and columns start at 1 instead
+    /// of 0 here. This is so we match the mathematical notation).
+    ///
+    /// For all matrices and vectors, independently from their size, individual components can
+    /// be accessed and modified using indexing: `vec[20]`, `mat[(20, 19)]`. Here the indexing
+    /// starts at 0 as you would expect.
     pub data: S,
 
     _phantoms: PhantomData<(N, R, C)>,