#[cfg(all(feature = "alloc", not(feature = "std")))] use alloc::vec::Vec; #[cfg(feature = "arbitrary")] use crate::base::storage::Owned; #[cfg(feature = "arbitrary")] use quickcheck::{Arbitrary, Gen}; use num::{Bounded, One, Zero}; #[cfg(feature = "rand-no-std")] use rand::{ distributions::{Distribution, Standard}, Rng, }; use std::iter; use std::mem; use typenum::{self, Cmp, Greater}; use simba::scalar::{ClosedAdd, ClosedMul}; use crate::base::allocator::Allocator; use crate::base::dimension::{Dim, DimName, Dynamic, ToTypenum}; use crate::base::storage::Storage; use crate::base::{ ArrayStorage, Const, DefaultAllocator, Matrix, OMatrix, OVector, Scalar, Unit, Vector, }; /// When "no_unsound_assume_init" is enabled, expands to `unimplemented!()` instead of `new_uninitialized_generic().assume_init()`. /// Intended as a placeholder, each callsite should be refactored to use uninitialized memory soundly #[macro_export] macro_rules! unimplemented_or_uninitialized_generic { ($nrows:expr, $ncols:expr) => {{ #[cfg(feature="no_unsound_assume_init")] { // Some of the call sites need the number of rows and columns from this to infer a type, so // uninitialized memory is used to infer the type, as `T: Zero` isn't available at all callsites. // This may technically still be UB even though the assume_init is dead code, but all callsites should be fixed before #556 is closed. let typeinference_helper = crate::base::Matrix::new_uninitialized_generic($nrows, $ncols); unimplemented!(); typeinference_helper.assume_init() } #[cfg(not(feature="no_unsound_assume_init"))] { crate::base::Matrix::new_uninitialized_generic($nrows, $ncols).assume_init() } }} } /// # 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 OMatrix where DefaultAllocator: Allocator, { /// Creates a new uninitialized matrix. If the matrix has a compile-time dimension, this panics /// if `nrows != R::to_usize()` or `ncols != C::to_usize()`. #[inline] pub unsafe fn new_uninitialized_generic(nrows: R, ncols: C) -> mem::MaybeUninit { Self::from_uninitialized_data(DefaultAllocator::allocate_uninitialized(nrows, ncols)) } /// Creates a matrix with all its elements set to `elem`. #[inline] pub fn from_element_generic(nrows: R, ncols: C, elem: T) -> Self { let len = nrows.value() * ncols.value(); Self::from_iterator_generic(nrows, ncols, iter::repeat(elem).take(len)) } /// Creates a matrix with all its elements set to `elem`. /// /// Same as `from_element_generic`. #[inline] pub fn repeat_generic(nrows: R, ncols: C, elem: T) -> Self { let len = nrows.value() * ncols.value(); Self::from_iterator_generic(nrows, ncols, iter::repeat(elem).take(len)) } /// Creates a matrix with all its elements set to 0. #[inline] pub fn zeros_generic(nrows: R, ncols: C) -> Self where T: Zero, { Self::from_element_generic(nrows, ncols, T::zero()) } /// Creates a matrix with all its elements filled by an iterator. #[inline] pub fn from_iterator_generic(nrows: R, ncols: C, iter: I) -> Self where I: IntoIterator, { Self::from_data(DefaultAllocator::allocate_from_iterator(nrows, ncols, 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. #[inline] pub fn from_row_slice_generic(nrows: R, ncols: C, slice: &[T]) -> Self { assert!( slice.len() == nrows.value() * ncols.value(), "Matrix init. error: the slice did not contain the right number of elements." ); let mut res = unsafe { crate::unimplemented_or_uninitialized_generic!(nrows, ncols) }; let mut iter = slice.iter(); for i in 0..nrows.value() { for j in 0..ncols.value() { unsafe { *res.get_unchecked_mut((i, j)) = iter.next().unwrap().inlined_clone() } } } res } /// Creates a matrix with its elements filled with the components provided by a slice. The /// components must have the same layout as the matrix data storage (i.e. column-major). #[inline] pub fn from_column_slice_generic(nrows: R, ncols: C, slice: &[T]) -> Self { Self::from_iterator_generic(nrows, ncols, slice.iter().cloned()) } /// Creates a matrix filled with the results of a function applied to each of its component /// coordinates. #[inline] pub fn from_fn_generic(nrows: R, ncols: C, mut f: F) -> Self where F: FnMut(usize, usize) -> T, { let mut res: Self = unsafe { crate::unimplemented_or_uninitialized_generic!(nrows, ncols) }; for j in 0..ncols.value() { for i in 0..nrows.value() { unsafe { *res.get_unchecked_mut((i, j)) = f(i, j) } } } res } /// Creates a new identity matrix. /// /// If the matrix is not square, the largest square submatrix starting at index `(0, 0)` is set /// to the identity matrix. All other entries are set to zero. #[inline] pub fn identity_generic(nrows: R, ncols: C) -> Self where T: Zero + One, { Self::from_diagonal_element_generic(nrows, ncols, T::one()) } /// Creates a new matrix with its diagonal filled with copies of `elt`. /// /// If the matrix is not square, the largest square submatrix starting at index `(0, 0)` is set /// to the identity matrix. All other entries are set to zero. #[inline] pub fn from_diagonal_element_generic(nrows: R, ncols: C, elt: T) -> Self where T: Zero + One, { let mut res = Self::zeros_generic(nrows, ncols); for i in 0..crate::min(nrows.value(), ncols.value()) { unsafe { *res.get_unchecked_mut((i, i)) = elt.inlined_clone() } } res } /// 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`. #[inline] pub fn from_partial_diagonal_generic(nrows: R, ncols: C, elts: &[T]) -> Self where T: Zero, { let mut res = Self::zeros_generic(nrows, ncols); assert!( elts.len() <= crate::min(nrows.value(), ncols.value()), "Too many diagonal elements provided." ); for (i, elt) in elts.iter().enumerate() { unsafe { *res.get_unchecked_mut((i, i)) = elt.inlined_clone() } } res } /// Builds a new matrix from its rows. /// /// Panics if not enough rows are provided (for statically-sized matrices), or if all rows do /// not have the same dimensions. /// /// # Example /// ``` /// # use nalgebra::{RowVector3, Matrix3}; /// # use std::iter; /// /// let m = Matrix3::from_rows(&[ RowVector3::new(1.0, 2.0, 3.0), RowVector3::new(4.0, 5.0, 6.0), RowVector3::new(7.0, 8.0, 9.0) ]); /// /// assert!(m.m11 == 1.0 && m.m12 == 2.0 && m.m13 == 3.0 && /// m.m21 == 4.0 && m.m22 == 5.0 && m.m23 == 6.0 && /// m.m31 == 7.0 && m.m32 == 8.0 && m.m33 == 9.0); /// ``` #[inline] pub fn from_rows(rows: &[Matrix, C, SB>]) -> Self where SB: Storage, C>, { assert!(!rows.is_empty(), "At least one row must be given."); let nrows = R::try_to_usize().unwrap_or_else(|| rows.len()); let ncols = rows[0].len(); assert!( rows.len() == nrows, "Invalid number of rows provided to build this matrix." ); if C::try_to_usize().is_none() { assert!( rows.iter().all(|r| r.len() == ncols), "The provided rows must all have the same dimension." ); } // TODO: optimize that. Self::from_fn_generic(R::from_usize(nrows), C::from_usize(ncols), |i, j| { rows[i][(0, j)].inlined_clone() }) } /// Builds a new matrix from its columns. /// /// Panics if not enough columns are provided (for statically-sized matrices), or if all /// columns do not have the same dimensions. /// /// # Example /// ``` /// # use nalgebra::{Vector3, Matrix3}; /// # use std::iter; /// /// let m = Matrix3::from_columns(&[ Vector3::new(1.0, 2.0, 3.0), Vector3::new(4.0, 5.0, 6.0), Vector3::new(7.0, 8.0, 9.0) ]); /// /// assert!(m.m11 == 1.0 && m.m12 == 4.0 && m.m13 == 7.0 && /// m.m21 == 2.0 && m.m22 == 5.0 && m.m23 == 8.0 && /// m.m31 == 3.0 && m.m32 == 6.0 && m.m33 == 9.0); /// ``` #[inline] pub fn from_columns(columns: &[Vector]) -> Self where SB: Storage, { assert!(!columns.is_empty(), "At least one column must be given."); let ncols = C::try_to_usize().unwrap_or_else(|| columns.len()); let nrows = columns[0].len(); assert!( columns.len() == ncols, "Invalid number of columns provided to build this matrix." ); if R::try_to_usize().is_none() { assert!( columns.iter().all(|r| r.len() == nrows), "The columns provided must all have the same dimension." ); } // TODO: optimize that. Self::from_fn_generic(R::from_usize(nrows), C::from_usize(ncols), |i, j| { columns[j][i].inlined_clone() }) } /// Creates a matrix filled with random values. #[inline] #[cfg(feature = "rand")] pub fn new_random_generic(nrows: R, ncols: C) -> Self where Standard: Distribution, { let mut rng = rand::thread_rng(); Self::from_fn_generic(nrows, ncols, |_, _| rng.gen()) } /// Creates a matrix filled with random values from the given distribution. #[inline] #[cfg(feature = "rand-no-std")] pub fn from_distribution_generic + ?Sized, G: Rng + ?Sized>( nrows: R, ncols: C, distribution: &Distr, rng: &mut G, ) -> Self { Self::from_fn_generic(nrows, ncols, |_, _| distribution.sample(rng)) } /// Creates a matrix backed by a given `Vec`. /// /// The output matrix is filled column-by-column. /// /// # Example /// ``` /// # use nalgebra::{Dynamic, DMatrix, Matrix, Const}; /// /// let vec = vec![0, 1, 2, 3, 4, 5]; /// let vec_ptr = vec.as_ptr(); /// /// let matrix = Matrix::from_vec_generic(Dynamic::new(vec.len()), Const::<1>, vec); /// let matrix_storage_ptr = matrix.data.as_vec().as_ptr(); /// /// // `matrix` is backed by exactly the same `Vec` as it was constructed from. /// assert_eq!(matrix_storage_ptr, vec_ptr); /// ``` #[inline] #[cfg(any(feature = "std", feature = "alloc"))] pub fn from_vec_generic(nrows: R, ncols: C, data: Vec) -> Self { Self::from_iterator_generic(nrows, ncols, data) } } impl OMatrix where T: Scalar, DefaultAllocator: Allocator, { /// Creates a square matrix with its diagonal set to `diag` and all other entries set to 0. /// /// # Example /// ``` /// # use nalgebra::{Vector3, DVector, Matrix3, DMatrix}; /// # use std::iter; /// /// 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(&[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 && /// m.m31 == 0.0 && m.m32 == 0.0 && m.m33 == 3.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)] == 3.0); /// ``` #[inline] pub fn from_diagonal>(diag: &Vector) -> Self where T: Zero, { let (dim, _) = diag.data.shape(); let mut res = Self::zeros_generic(dim, dim); for i in 0..diag.len() { unsafe { *res.get_unchecked_mut((i, i)) = diag.vget_unchecked(i).inlined_clone(); } } res } } /* * * Generate constructors with varying number of arguments, depending on the object type. * */ macro_rules! impl_constructors( ($($Dims: ty),*; $(=> $DimIdent: ident: $DimBound: ident),*; $($gargs: expr),*; $($args: ident),*) => { /// Creates a new uninitialized matrix or vector. #[inline] pub unsafe fn new_uninitialized($($args: usize),*) -> mem::MaybeUninit { 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: T) -> 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: T) -> 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::::zeros(); /// // The argument represents the vector dimension. /// let dv = DVector::::zeros(3); /// let m = Matrix2x3::::zeros(); /// // The two arguments represent the matrix dimensions. /// let dm = DMatrix::::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 T: 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($($args: usize,)* iter: I) -> Self where I: IntoIterator { 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($($args: usize,)* f: F) -> Self where F: FnMut(usize, usize) -> T { 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::::identity(); /// // The two additional arguments represent the matrix dimensions. /// let dm = DMatrix::::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 T: 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: T) -> Self where T: 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: &[T]) -> Self where T: Zero { Self::from_partial_diagonal_generic($($gargs, )* elts) } /// Creates a matrix or vector filled with random values from the given distribution. #[inline] #[cfg(feature = "rand-no-std")] pub fn from_distribution + ?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 = "rand")] pub fn new_random($($args: usize),*) -> Self where Standard: Distribution { Self::new_random_generic($($gargs),*) } } ); /// # Constructors of statically-sized vectors or statically-sized matrices impl OMatrix where DefaultAllocator: Allocator, { // TODO: this is not very pretty. We could find a better call syntax. impl_constructors!(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. } /// # Constructors of matrices with a dynamic number of columns impl OMatrix where DefaultAllocator: Allocator, { impl_constructors!(R, Dynamic; => R: DimName; R::name(), Dynamic::new(ncols); ncols); } /// # Constructors of dynamic vectors and matrices with a dynamic number of rows impl OMatrix where DefaultAllocator: Allocator, { impl_constructors!(Dynamic, C; => C: DimName; Dynamic::new(nrows), C::name(); nrows); } /// # Constructors of fully dynamic matrices impl OMatrix where DefaultAllocator: Allocator, { impl_constructors!(Dynamic, Dynamic; ; Dynamic::new(nrows), Dynamic::new(ncols); nrows, ncols); } /* * * Constructors that don't necessarily require all dimensions * to be specified when one dimension is already known. * */ macro_rules! impl_constructors_from_data( ($data: ident; $($Dims: ty),*; $(=> $DimIdent: ident: $DimBound: ident),*; $($gargs: expr),*; $($args: ident),*) => { impl OMatrix 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(&[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: &[T]) -> 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(&[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: &[T]) -> 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(any(feature = "std", feature = "alloc"))] pub fn from_vec($($args: usize,)* $data: Vec) -> Self { Self::from_vec_generic($($gargs, )* $data) } } } ); // TODO: 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. * */ impl Zero for OMatrix where T: Scalar + Zero + ClosedAdd, DefaultAllocator: Allocator, { #[inline] fn zero() -> Self { Self::from_element(T::zero()) } #[inline] fn is_zero(&self) -> bool { self.iter().all(|e| e.is_zero()) } } impl One for OMatrix where T: Scalar + Zero + One + ClosedMul + ClosedAdd, DefaultAllocator: Allocator, { #[inline] fn one() -> Self { Self::identity() } } impl Bounded for OMatrix where T: Scalar + Bounded, DefaultAllocator: Allocator, { #[inline] fn max_value() -> Self { Self::from_element(T::max_value()) } #[inline] fn min_value() -> Self { Self::from_element(T::min_value()) } } #[cfg(feature = "rand-no-std")] impl Distribution> for Standard where DefaultAllocator: Allocator, Standard: Distribution, { #[inline] fn sample<'a, G: Rng + ?Sized>(&self, rng: &'a mut G) -> OMatrix { let nrows = R::try_to_usize().unwrap_or_else(|| rng.gen_range(0..10)); let ncols = C::try_to_usize().unwrap_or_else(|| rng.gen_range(0..10)); OMatrix::from_fn_generic(R::from_usize(nrows), C::from_usize(ncols), |_, _| rng.gen()) } } #[cfg(feature = "arbitrary")] impl Arbitrary for OMatrix where R: Dim, C: Dim, T: Scalar + Arbitrary + Send, DefaultAllocator: Allocator, Owned: Clone + Send, { #[inline] fn arbitrary(g: &mut Gen) -> Self { let nrows = R::try_to_usize().unwrap_or(usize::arbitrary(g) % 10); let ncols = C::try_to_usize().unwrap_or(usize::arbitrary(g) % 10); Self::from_fn_generic(R::from_usize(nrows), C::from_usize(ncols), |_, _| { T::arbitrary(g) }) } } // TODO(specialization): faster impls possible for D≤4 (see rand_distr::{UnitCircle, UnitSphere}) #[cfg(feature = "rand")] impl Distribution>> for Standard where DefaultAllocator: Allocator, rand_distr::StandardNormal: Distribution, { /// Generate a uniformly distributed random unit vector. #[inline] fn sample<'a, G: Rng + ?Sized>(&self, rng: &'a mut G) -> Unit> { Unit::new_normalize(OVector::from_distribution_generic( D::name(), Const::<1>, &rand_distr::StandardNormal, rng, )) } } /* * * Constructors for small matrices and vectors. * */ macro_rules! transpose_array( [$($a: ident),*;] => { [$([$a]),*] }; [$($a: ident),*; $($b: ident),*;] => { [$([$a, $b]),*]; }; [$($a: ident),*; $($b: ident),*; $($c: ident),*;] => { [$([$a, $b, $c]),*]; }; [$($a: ident),*; $($b: ident),*; $($c: ident),*; $($d: ident),*;] => { [$([$a, $b, $c, $d]),*]; }; [$($a: ident),*; $($b: ident),*; $($c: ident),*; $($d: ident),*; $($e: ident),*;] => { [$([$a, $b, $c, $d, $e]),*]; }; [$($a: ident),*; $($b: ident),*; $($c: ident),*; $($d: ident),*; $($e: ident),*; $($f: ident),*;] => { [$([$a, $b, $c, $d, $e, $f]),*]; }; ); macro_rules! componentwise_constructors_impl( ($($R: expr, $C: expr, [$($($args: ident),*);*] $(;)*)*) => {$( impl Matrix, Const<$C>, ArrayStorage> { /// Initializes this matrix from its components. #[inline] pub const fn new($($($args: T),*),*) -> Self { unsafe { Self::from_data_statically_unchecked( ArrayStorage( transpose_array![ $( $($args),* ;)* ] ) ) } } } )*} ); componentwise_constructors_impl!( /* * Square matrices 1 .. 6. */ 2, 2, [m11, m12; m21, m22]; 3, 3, [m11, m12, m13; m21, m22, m23; m31, m32, m33]; 4, 4, [m11, m12, m13, m14; m21, m22, m23, m24; m31, m32, m33, m34; m41, m42, m43, m44]; 5, 5, [m11, m12, m13, m14, m15; m21, m22, m23, m24, m25; m31, m32, m33, m34, m35; m41, m42, m43, m44, m45; m51, m52, m53, m54, m55]; 6, 6, [m11, m12, m13, m14, m15, m16; m21, m22, m23, m24, m25, m26; m31, m32, m33, m34, m35, m36; m41, m42, m43, m44, m45, m46; m51, m52, m53, m54, m55, m56; m61, m62, m63, m64, m65, m66]; /* * Rectangular matrices with 2 rows. */ 2, 3, [m11, m12, m13; m21, m22, m23]; 2, 4, [m11, m12, m13, m14; m21, m22, m23, m24]; 2, 5, [m11, m12, m13, m14, m15; m21, m22, m23, m24, m25]; 2, 6, [m11, m12, m13, m14, m15, m16; m21, m22, m23, m24, m25, m26]; /* * Rectangular matrices with 3 rows. */ 3, 2, [m11, m12; m21, m22; m31, m32]; 3, 4, [m11, m12, m13, m14; m21, m22, m23, m24; m31, m32, m33, m34]; 3, 5, [m11, m12, m13, m14, m15; m21, m22, m23, m24, m25; m31, m32, m33, m34, m35]; 3, 6, [m11, m12, m13, m14, m15, m16; m21, m22, m23, m24, m25, m26; m31, m32, m33, m34, m35, m36]; /* * Rectangular matrices with 4 rows. */ 4, 2, [m11, m12; m21, m22; m31, m32; m41, m42]; 4, 3, [m11, m12, m13; m21, m22, m23; m31, m32, m33; m41, m42, m43]; 4, 5, [m11, m12, m13, m14, m15; m21, m22, m23, m24, m25; m31, m32, m33, m34, m35; m41, m42, m43, m44, m45]; 4, 6, [m11, m12, m13, m14, m15, m16; m21, m22, m23, m24, m25, m26; m31, m32, m33, m34, m35, m36; m41, m42, m43, m44, m45, m46]; /* * Rectangular matrices with 5 rows. */ 5, 2, [m11, m12; m21, m22; m31, m32; m41, m42; m51, m52]; 5, 3, [m11, m12, m13; m21, m22, m23; m31, m32, m33; m41, m42, m43; m51, m52, m53]; 5, 4, [m11, m12, m13, m14; m21, m22, m23, m24; m31, m32, m33, m34; m41, m42, m43, m44; m51, m52, m53, m54]; 5, 6, [m11, m12, m13, m14, m15, m16; m21, m22, m23, m24, m25, m26; m31, m32, m33, m34, m35, m36; m41, m42, m43, m44, m45, m46; m51, m52, m53, m54, m55, m56]; /* * Rectangular matrices with 6 rows. */ 6, 2, [m11, m12; m21, m22; m31, m32; m41, m42; m51, m52; m61, m62]; 6, 3, [m11, m12, m13; m21, m22, m23; m31, m32, m33; m41, m42, m43; m51, m52, m53; m61, m62, m63]; 6, 4, [m11, m12, m13, m14; m21, m22, m23, m24; m31, m32, m33, m34; m41, m42, m43, m44; m51, m52, m53, m54; m61, m62, m63, m64]; 6, 5, [m11, m12, m13, m14, m15; m21, m22, m23, m24, m25; m31, m32, m33, m34, m35; m41, m42, m43, m44, m45; m51, m52, m53, m54, m55; m61, m62, m63, m64, m65]; /* * Row vectors 1 .. 6. */ 1, 1, [x]; 1, 2, [x, y]; 1, 3, [x, y, z]; 1, 4, [x, y, z, w]; 1, 5, [x, y, z, w, a]; 1, 6, [x, y, z, w, a, b]; /* * Column vectors 1 .. 6. */ 2, 1, [x; y]; 3, 1, [x; y; z]; 4, 1, [x; y; z; w]; 5, 1, [x; y; z; w; a]; 6, 1, [x; y; z; w; a; b]; ); /* * * Axis constructors. * */ impl OVector where R: ToTypenum, T: Scalar + Zero + One, DefaultAllocator: Allocator, { /// The column vector with `val` as its i-th component. #[inline] pub fn ith(i: usize, val: T) -> Self { let mut res = Self::zeros(); res[i] = val; res } /// The column unit vector with `T::one()` as its i-th component. #[inline] pub fn ith_axis(i: usize) -> Unit { Unit::new_unchecked(Self::ith(i, T::one())) } /// The column vector with a 1 as its first component, and zero elsewhere. #[inline] pub fn x() -> Self where R::Typenum: Cmp, { let mut res = Self::zeros(); unsafe { *res.vget_unchecked_mut(0) = T::one(); } res } /// The column vector with a 1 as its second component, and zero elsewhere. #[inline] pub fn y() -> Self where R::Typenum: Cmp, { let mut res = Self::zeros(); unsafe { *res.vget_unchecked_mut(1) = T::one(); } res } /// The column vector with a 1 as its third component, and zero elsewhere. #[inline] pub fn z() -> Self where R::Typenum: Cmp, { let mut res = Self::zeros(); unsafe { *res.vget_unchecked_mut(2) = T::one(); } res } /// The column vector with a 1 as its fourth component, and zero elsewhere. #[inline] pub fn w() -> Self where R::Typenum: Cmp, { let mut res = Self::zeros(); unsafe { *res.vget_unchecked_mut(3) = T::one(); } res } /// The column vector with a 1 as its fifth component, and zero elsewhere. #[inline] pub fn a() -> Self where R::Typenum: Cmp, { let mut res = Self::zeros(); unsafe { *res.vget_unchecked_mut(4) = T::one(); } res } /// The column vector with a 1 as its sixth component, and zero elsewhere. #[inline] pub fn b() -> Self where R::Typenum: Cmp, { let mut res = Self::zeros(); unsafe { *res.vget_unchecked_mut(5) = T::one(); } res } /// The unit column vector with a 1 as its first component, and zero elsewhere. #[inline] pub fn x_axis() -> Unit where R::Typenum: Cmp, { Unit::new_unchecked(Self::x()) } /// The unit column vector with a 1 as its second component, and zero elsewhere. #[inline] pub fn y_axis() -> Unit where R::Typenum: Cmp, { Unit::new_unchecked(Self::y()) } /// The unit column vector with a 1 as its third component, and zero elsewhere. #[inline] pub fn z_axis() -> Unit where R::Typenum: Cmp, { Unit::new_unchecked(Self::z()) } /// The unit column vector with a 1 as its fourth component, and zero elsewhere. #[inline] pub fn w_axis() -> Unit where R::Typenum: Cmp, { Unit::new_unchecked(Self::w()) } /// The unit column vector with a 1 as its fifth component, and zero elsewhere. #[inline] pub fn a_axis() -> Unit where R::Typenum: Cmp, { Unit::new_unchecked(Self::a()) } /// The unit column vector with a 1 as its sixth component, and zero elsewhere. #[inline] pub fn b_axis() -> Unit where R::Typenum: Cmp, { Unit::new_unchecked(Self::b()) } }