nalgebra/base/construction.rs
1#[cfg(all(feature = "alloc", not(feature = "std")))]
2use alloc::vec::Vec;
3
4#[cfg(feature = "arbitrary")]
5use crate::base::storage::Owned;
6#[cfg(feature = "arbitrary")]
7use quickcheck::{Arbitrary, Gen};
8
9use num::{Bounded, One, Zero};
10#[cfg(feature = "rand-no-std")]
11use rand::{
12 distributions::{Distribution, Standard},
13 Rng,
14};
15
16use std::iter;
17use typenum::{self, Cmp, Greater};
18
19use simba::scalar::{ClosedAdd, ClosedMul};
20
21use crate::base::allocator::Allocator;
22use crate::base::dimension::{Dim, DimName, Dynamic, ToTypenum};
23use crate::base::storage::RawStorage;
24use crate::base::{
25 ArrayStorage, Const, DefaultAllocator, Matrix, OMatrix, OVector, Scalar, Unit, Vector,
26};
27use crate::UninitMatrix;
28use std::mem::MaybeUninit;
29
30impl<T: Scalar, R: Dim, C: Dim> UninitMatrix<T, R, C>
31where
32 DefaultAllocator: Allocator<T, R, C>,
33{
34 /// Builds a matrix with uninitialized elements of type `MaybeUninit<T>`.
35 #[inline(always)]
36 pub fn uninit(nrows: R, ncols: C) -> Self {
37 // SAFETY: this is OK because the dimension automatically match the storage
38 // because we are building an owned storage.
39 unsafe {
40 Self::from_data_statically_unchecked(DefaultAllocator::allocate_uninit(nrows, ncols))
41 }
42 }
43}
44
45/// # Generic constructors
46/// This set of matrix and vector construction functions are all generic
47/// with-regard to the matrix dimensions. They all expect to be given
48/// the dimension as inputs.
49///
50/// These functions should only be used when working on dimension-generic code.
51impl<T: Scalar, R: Dim, C: Dim> OMatrix<T, R, C>
52where
53 DefaultAllocator: Allocator<T, R, C>,
54{
55 /// Creates a matrix with all its elements set to `elem`.
56 #[inline]
57 pub fn from_element_generic(nrows: R, ncols: C, elem: T) -> Self {
58 let len = nrows.value() * ncols.value();
59 Self::from_iterator_generic(nrows, ncols, iter::repeat(elem).take(len))
60 }
61
62 /// Creates a matrix with all its elements set to `elem`.
63 ///
64 /// Same as `from_element_generic`.
65 #[inline]
66 pub fn repeat_generic(nrows: R, ncols: C, elem: T) -> Self {
67 let len = nrows.value() * ncols.value();
68 Self::from_iterator_generic(nrows, ncols, iter::repeat(elem).take(len))
69 }
70
71 /// Creates a matrix with all its elements set to 0.
72 #[inline]
73 pub fn zeros_generic(nrows: R, ncols: C) -> Self
74 where
75 T: Zero,
76 {
77 Self::from_element_generic(nrows, ncols, T::zero())
78 }
79
80 /// Creates a matrix with all its elements filled by an iterator.
81 #[inline]
82 pub fn from_iterator_generic<I>(nrows: R, ncols: C, iter: I) -> Self
83 where
84 I: IntoIterator<Item = T>,
85 {
86 Self::from_data(DefaultAllocator::allocate_from_iterator(nrows, ncols, iter))
87 }
88
89 /// Creates a matrix with its elements filled with the components provided by a slice in
90 /// row-major order.
91 ///
92 /// The order of elements in the slice must follow the usual mathematic writing, i.e.,
93 /// row-by-row.
94 #[inline]
95 pub fn from_row_slice_generic(nrows: R, ncols: C, slice: &[T]) -> Self {
96 assert!(
97 slice.len() == nrows.value() * ncols.value(),
98 "Matrix init. error: the slice did not contain the right number of elements."
99 );
100
101 let mut res = Matrix::uninit(nrows, ncols);
102 let mut iter = slice.iter();
103
104 unsafe {
105 for i in 0..nrows.value() {
106 for j in 0..ncols.value() {
107 *res.get_unchecked_mut((i, j)) = MaybeUninit::new(iter.next().unwrap().clone())
108 }
109 }
110
111 // SAFETY: the result has been fully initialized above.
112 res.assume_init()
113 }
114 }
115
116 /// Creates a matrix with its elements filled with the components provided by a slice. The
117 /// components must have the same layout as the matrix data storage (i.e. column-major).
118 #[inline]
119 pub fn from_column_slice_generic(nrows: R, ncols: C, slice: &[T]) -> Self {
120 Self::from_iterator_generic(nrows, ncols, slice.iter().cloned())
121 }
122
123 /// Creates a matrix filled with the results of a function applied to each of its component
124 /// coordinates.
125 #[inline]
126 pub fn from_fn_generic<F>(nrows: R, ncols: C, mut f: F) -> Self
127 where
128 F: FnMut(usize, usize) -> T,
129 {
130 let mut res = Matrix::uninit(nrows, ncols);
131
132 unsafe {
133 for j in 0..ncols.value() {
134 for i in 0..nrows.value() {
135 *res.get_unchecked_mut((i, j)) = MaybeUninit::new(f(i, j));
136 }
137 }
138
139 // SAFETY: the result has been fully initialized above.
140 res.assume_init()
141 }
142 }
143
144 /// Creates a new identity matrix.
145 ///
146 /// If the matrix is not square, the largest square submatrix starting at index `(0, 0)` is set
147 /// to the identity matrix. All other entries are set to zero.
148 #[inline]
149 pub fn identity_generic(nrows: R, ncols: C) -> Self
150 where
151 T: Zero + One,
152 {
153 Self::from_diagonal_element_generic(nrows, ncols, T::one())
154 }
155
156 /// Creates a new matrix with its diagonal filled with copies of `elt`.
157 ///
158 /// If the matrix is not square, the largest square submatrix starting at index `(0, 0)` is set
159 /// to the identity matrix. All other entries are set to zero.
160 #[inline]
161 pub fn from_diagonal_element_generic(nrows: R, ncols: C, elt: T) -> Self
162 where
163 T: Zero + One,
164 {
165 let mut res = Self::zeros_generic(nrows, ncols);
166
167 for i in 0..crate::min(nrows.value(), ncols.value()) {
168 unsafe { *res.get_unchecked_mut((i, i)) = elt.clone() }
169 }
170
171 res
172 }
173
174 /// Creates a new matrix that may be rectangular. The first `elts.len()` diagonal elements are
175 /// filled with the content of `elts`. Others are set to 0.
176 ///
177 /// Panics if `elts.len()` is larger than the minimum among `nrows` and `ncols`.
178 #[inline]
179 pub fn from_partial_diagonal_generic(nrows: R, ncols: C, elts: &[T]) -> Self
180 where
181 T: Zero,
182 {
183 let mut res = Self::zeros_generic(nrows, ncols);
184 assert!(
185 elts.len() <= crate::min(nrows.value(), ncols.value()),
186 "Too many diagonal elements provided."
187 );
188
189 for (i, elt) in elts.iter().enumerate() {
190 unsafe { *res.get_unchecked_mut((i, i)) = elt.clone() }
191 }
192
193 res
194 }
195
196 /// Builds a new matrix from its rows.
197 ///
198 /// Panics if not enough rows are provided (for statically-sized matrices), or if all rows do
199 /// not have the same dimensions.
200 ///
201 /// # Example
202 /// ```
203 /// # use nalgebra::{RowVector3, Matrix3};
204 /// # use std::iter;
205 ///
206 /// 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) ]);
207 ///
208 /// assert!(m.m11 == 1.0 && m.m12 == 2.0 && m.m13 == 3.0 &&
209 /// m.m21 == 4.0 && m.m22 == 5.0 && m.m23 == 6.0 &&
210 /// m.m31 == 7.0 && m.m32 == 8.0 && m.m33 == 9.0);
211 /// ```
212 #[inline]
213 pub fn from_rows<SB>(rows: &[Matrix<T, Const<1>, C, SB>]) -> Self
214 where
215 SB: RawStorage<T, Const<1>, C>,
216 {
217 assert!(!rows.is_empty(), "At least one row must be given.");
218 let nrows = R::try_to_usize().unwrap_or_else(|| rows.len());
219 let ncols = rows[0].len();
220 assert!(
221 rows.len() == nrows,
222 "Invalid number of rows provided to build this matrix."
223 );
224
225 if C::try_to_usize().is_none() {
226 assert!(
227 rows.iter().all(|r| r.len() == ncols),
228 "The provided rows must all have the same dimension."
229 );
230 }
231
232 // TODO: optimize that.
233 Self::from_fn_generic(R::from_usize(nrows), C::from_usize(ncols), |i, j| {
234 rows[i][(0, j)].clone()
235 })
236 }
237
238 /// Builds a new matrix from its columns.
239 ///
240 /// Panics if not enough columns are provided (for statically-sized matrices), or if all
241 /// columns do not have the same dimensions.
242 ///
243 /// # Example
244 /// ```
245 /// # use nalgebra::{Vector3, Matrix3};
246 /// # use std::iter;
247 ///
248 /// 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) ]);
249 ///
250 /// assert!(m.m11 == 1.0 && m.m12 == 4.0 && m.m13 == 7.0 &&
251 /// m.m21 == 2.0 && m.m22 == 5.0 && m.m23 == 8.0 &&
252 /// m.m31 == 3.0 && m.m32 == 6.0 && m.m33 == 9.0);
253 /// ```
254 #[inline]
255 pub fn from_columns<SB>(columns: &[Vector<T, R, SB>]) -> Self
256 where
257 SB: RawStorage<T, R>,
258 {
259 assert!(!columns.is_empty(), "At least one column must be given.");
260 let ncols = C::try_to_usize().unwrap_or_else(|| columns.len());
261 let nrows = columns[0].len();
262 assert!(
263 columns.len() == ncols,
264 "Invalid number of columns provided to build this matrix."
265 );
266
267 if R::try_to_usize().is_none() {
268 assert!(
269 columns.iter().all(|r| r.len() == nrows),
270 "The columns provided must all have the same dimension."
271 );
272 }
273
274 // TODO: optimize that.
275 Self::from_fn_generic(R::from_usize(nrows), C::from_usize(ncols), |i, j| {
276 columns[j][i].clone()
277 })
278 }
279
280 /// Creates a matrix filled with random values.
281 #[inline]
282 #[cfg(feature = "rand")]
283 pub fn new_random_generic(nrows: R, ncols: C) -> Self
284 where
285 Standard: Distribution<T>,
286 {
287 let mut rng = rand::thread_rng();
288 Self::from_fn_generic(nrows, ncols, |_, _| rng.gen())
289 }
290
291 /// Creates a matrix filled with random values from the given distribution.
292 #[inline]
293 #[cfg(feature = "rand-no-std")]
294 pub fn from_distribution_generic<Distr: Distribution<T> + ?Sized, G: Rng + ?Sized>(
295 nrows: R,
296 ncols: C,
297 distribution: &Distr,
298 rng: &mut G,
299 ) -> Self {
300 Self::from_fn_generic(nrows, ncols, |_, _| distribution.sample(rng))
301 }
302
303 /// Creates a matrix backed by a given `Vec`.
304 ///
305 /// The output matrix is filled column-by-column.
306 ///
307 /// # Example
308 /// ```
309 /// # use nalgebra::{Dynamic, DMatrix, Matrix, Const};
310 ///
311 /// let vec = vec![0, 1, 2, 3, 4, 5];
312 /// let vec_ptr = vec.as_ptr();
313 ///
314 /// let matrix = Matrix::from_vec_generic(Dynamic::new(vec.len()), Const::<1>, vec);
315 /// let matrix_storage_ptr = matrix.data.as_vec().as_ptr();
316 ///
317 /// // `matrix` is backed by exactly the same `Vec` as it was constructed from.
318 /// assert_eq!(matrix_storage_ptr, vec_ptr);
319 /// ```
320 #[inline]
321 #[cfg(any(feature = "std", feature = "alloc"))]
322 pub fn from_vec_generic(nrows: R, ncols: C, data: Vec<T>) -> Self {
323 Self::from_iterator_generic(nrows, ncols, data)
324 }
325}
326
327impl<T, D: Dim> OMatrix<T, D, D>
328where
329 T: Scalar,
330 DefaultAllocator: Allocator<T, D, D>,
331{
332 /// Creates a square matrix with its diagonal set to `diag` and all other entries set to 0.
333 ///
334 /// # Example
335 /// ```
336 /// # use nalgebra::{Vector3, DVector, Matrix3, DMatrix};
337 /// # use std::iter;
338 ///
339 /// let m = Matrix3::from_diagonal(&Vector3::new(1.0, 2.0, 3.0));
340 /// // The two additional arguments represent the matrix dimensions.
341 /// let dm = DMatrix::from_diagonal(&DVector::from_row_slice(&[1.0, 2.0, 3.0]));
342 ///
343 /// assert!(m.m11 == 1.0 && m.m12 == 0.0 && m.m13 == 0.0 &&
344 /// m.m21 == 0.0 && m.m22 == 2.0 && m.m23 == 0.0 &&
345 /// m.m31 == 0.0 && m.m32 == 0.0 && m.m33 == 3.0);
346 /// assert!(dm[(0, 0)] == 1.0 && dm[(0, 1)] == 0.0 && dm[(0, 2)] == 0.0 &&
347 /// dm[(1, 0)] == 0.0 && dm[(1, 1)] == 2.0 && dm[(1, 2)] == 0.0 &&
348 /// dm[(2, 0)] == 0.0 && dm[(2, 1)] == 0.0 && dm[(2, 2)] == 3.0);
349 /// ```
350 #[inline]
351 pub fn from_diagonal<SB: RawStorage<T, D>>(diag: &Vector<T, D, SB>) -> Self
352 where
353 T: Zero,
354 {
355 let (dim, _) = diag.shape_generic();
356 let mut res = Self::zeros_generic(dim, dim);
357
358 for i in 0..diag.len() {
359 unsafe {
360 *res.get_unchecked_mut((i, i)) = diag.vget_unchecked(i).clone();
361 }
362 }
363
364 res
365 }
366}
367
368/*
369 *
370 * Generate constructors with varying number of arguments, depending on the object type.
371 *
372 */
373macro_rules! impl_constructors(
374 ($($Dims: ty),*; $(=> $DimIdent: ident: $DimBound: ident),*; $($gargs: expr),*; $($args: ident),*) => {
375 /// Creates a matrix or vector with all its elements set to `elem`.
376 ///
377 /// # Example
378 /// ```
379 /// # use nalgebra::{Matrix2x3, Vector3, DVector, DMatrix};
380 ///
381 /// let v = Vector3::from_element(2.0);
382 /// // The additional argument represents the vector dimension.
383 /// let dv = DVector::from_element(3, 2.0);
384 /// let m = Matrix2x3::from_element(2.0);
385 /// // The two additional arguments represent the matrix dimensions.
386 /// let dm = DMatrix::from_element(2, 3, 2.0);
387 ///
388 /// assert!(v.x == 2.0 && v.y == 2.0 && v.z == 2.0);
389 /// assert!(dv[0] == 2.0 && dv[1] == 2.0 && dv[2] == 2.0);
390 /// assert!(m.m11 == 2.0 && m.m12 == 2.0 && m.m13 == 2.0 &&
391 /// m.m21 == 2.0 && m.m22 == 2.0 && m.m23 == 2.0);
392 /// assert!(dm[(0, 0)] == 2.0 && dm[(0, 1)] == 2.0 && dm[(0, 2)] == 2.0 &&
393 /// dm[(1, 0)] == 2.0 && dm[(1, 1)] == 2.0 && dm[(1, 2)] == 2.0);
394 /// ```
395 #[inline]
396 pub fn from_element($($args: usize,)* elem: T) -> Self {
397 Self::from_element_generic($($gargs, )* elem)
398 }
399
400 /// Creates a matrix or vector with all its elements set to `elem`.
401 ///
402 /// Same as `.from_element`.
403 ///
404 /// # Example
405 /// ```
406 /// # use nalgebra::{Matrix2x3, Vector3, DVector, DMatrix};
407 ///
408 /// let v = Vector3::repeat(2.0);
409 /// // The additional argument represents the vector dimension.
410 /// let dv = DVector::repeat(3, 2.0);
411 /// let m = Matrix2x3::repeat(2.0);
412 /// // The two additional arguments represent the matrix dimensions.
413 /// let dm = DMatrix::repeat(2, 3, 2.0);
414 ///
415 /// assert!(v.x == 2.0 && v.y == 2.0 && v.z == 2.0);
416 /// assert!(dv[0] == 2.0 && dv[1] == 2.0 && dv[2] == 2.0);
417 /// assert!(m.m11 == 2.0 && m.m12 == 2.0 && m.m13 == 2.0 &&
418 /// m.m21 == 2.0 && m.m22 == 2.0 && m.m23 == 2.0);
419 /// assert!(dm[(0, 0)] == 2.0 && dm[(0, 1)] == 2.0 && dm[(0, 2)] == 2.0 &&
420 /// dm[(1, 0)] == 2.0 && dm[(1, 1)] == 2.0 && dm[(1, 2)] == 2.0);
421 /// ```
422 #[inline]
423 pub fn repeat($($args: usize,)* elem: T) -> Self {
424 Self::repeat_generic($($gargs, )* elem)
425 }
426
427 /// Creates a matrix or vector with all its elements set to `0`.
428 ///
429 /// # Example
430 /// ```
431 /// # use nalgebra::{Matrix2x3, Vector3, DVector, DMatrix};
432 ///
433 /// let v = Vector3::<f32>::zeros();
434 /// // The argument represents the vector dimension.
435 /// let dv = DVector::<f32>::zeros(3);
436 /// let m = Matrix2x3::<f32>::zeros();
437 /// // The two arguments represent the matrix dimensions.
438 /// let dm = DMatrix::<f32>::zeros(2, 3);
439 ///
440 /// assert!(v.x == 0.0 && v.y == 0.0 && v.z == 0.0);
441 /// assert!(dv[0] == 0.0 && dv[1] == 0.0 && dv[2] == 0.0);
442 /// assert!(m.m11 == 0.0 && m.m12 == 0.0 && m.m13 == 0.0 &&
443 /// m.m21 == 0.0 && m.m22 == 0.0 && m.m23 == 0.0);
444 /// assert!(dm[(0, 0)] == 0.0 && dm[(0, 1)] == 0.0 && dm[(0, 2)] == 0.0 &&
445 /// dm[(1, 0)] == 0.0 && dm[(1, 1)] == 0.0 && dm[(1, 2)] == 0.0);
446 /// ```
447 #[inline]
448 pub fn zeros($($args: usize),*) -> Self
449 where T: Zero {
450 Self::zeros_generic($($gargs),*)
451 }
452
453 /// Creates a matrix or vector with all its elements filled by an iterator.
454 ///
455 /// The output matrix is filled column-by-column.
456 ///
457 /// # Example
458 /// ```
459 /// # use nalgebra::{Matrix2x3, Vector3, DVector, DMatrix};
460 /// # use std::iter;
461 ///
462 /// let v = Vector3::from_iterator((0..3).into_iter());
463 /// // The additional argument represents the vector dimension.
464 /// let dv = DVector::from_iterator(3, (0..3).into_iter());
465 /// let m = Matrix2x3::from_iterator((0..6).into_iter());
466 /// // The two additional arguments represent the matrix dimensions.
467 /// let dm = DMatrix::from_iterator(2, 3, (0..6).into_iter());
468 ///
469 /// assert!(v.x == 0 && v.y == 1 && v.z == 2);
470 /// assert!(dv[0] == 0 && dv[1] == 1 && dv[2] == 2);
471 /// assert!(m.m11 == 0 && m.m12 == 2 && m.m13 == 4 &&
472 /// m.m21 == 1 && m.m22 == 3 && m.m23 == 5);
473 /// assert!(dm[(0, 0)] == 0 && dm[(0, 1)] == 2 && dm[(0, 2)] == 4 &&
474 /// dm[(1, 0)] == 1 && dm[(1, 1)] == 3 && dm[(1, 2)] == 5);
475 /// ```
476 #[inline]
477 pub fn from_iterator<I>($($args: usize,)* iter: I) -> Self
478 where I: IntoIterator<Item = T> {
479 Self::from_iterator_generic($($gargs, )* iter)
480 }
481
482 /// Creates a matrix or vector filled with the results of a function applied to each of its
483 /// component coordinates.
484 ///
485 /// # Example
486 /// ```
487 /// # use nalgebra::{Matrix2x3, Vector3, DVector, DMatrix};
488 /// # use std::iter;
489 ///
490 /// let v = Vector3::from_fn(|i, _| i);
491 /// // The additional argument represents the vector dimension.
492 /// let dv = DVector::from_fn(3, |i, _| i);
493 /// let m = Matrix2x3::from_fn(|i, j| i * 3 + j);
494 /// // The two additional arguments represent the matrix dimensions.
495 /// let dm = DMatrix::from_fn(2, 3, |i, j| i * 3 + j);
496 ///
497 /// assert!(v.x == 0 && v.y == 1 && v.z == 2);
498 /// assert!(dv[0] == 0 && dv[1] == 1 && dv[2] == 2);
499 /// assert!(m.m11 == 0 && m.m12 == 1 && m.m13 == 2 &&
500 /// m.m21 == 3 && m.m22 == 4 && m.m23 == 5);
501 /// assert!(dm[(0, 0)] == 0 && dm[(0, 1)] == 1 && dm[(0, 2)] == 2 &&
502 /// dm[(1, 0)] == 3 && dm[(1, 1)] == 4 && dm[(1, 2)] == 5);
503 /// ```
504 #[inline]
505 pub fn from_fn<F>($($args: usize,)* f: F) -> Self
506 where F: FnMut(usize, usize) -> T {
507 Self::from_fn_generic($($gargs, )* f)
508 }
509
510 /// Creates an identity matrix. If the matrix is not square, the largest square
511 /// submatrix (starting at the first row and column) is set to the identity while all
512 /// other entries are set to zero.
513 ///
514 /// # Example
515 /// ```
516 /// # use nalgebra::{Matrix2x3, DMatrix};
517 /// # use std::iter;
518 ///
519 /// let m = Matrix2x3::<f32>::identity();
520 /// // The two additional arguments represent the matrix dimensions.
521 /// let dm = DMatrix::<f32>::identity(2, 3);
522 ///
523 /// assert!(m.m11 == 1.0 && m.m12 == 0.0 && m.m13 == 0.0 &&
524 /// m.m21 == 0.0 && m.m22 == 1.0 && m.m23 == 0.0);
525 /// assert!(dm[(0, 0)] == 1.0 && dm[(0, 1)] == 0.0 && dm[(0, 2)] == 0.0 &&
526 /// dm[(1, 0)] == 0.0 && dm[(1, 1)] == 1.0 && dm[(1, 2)] == 0.0);
527 /// ```
528 #[inline]
529 pub fn identity($($args: usize,)*) -> Self
530 where T: Zero + One {
531 Self::identity_generic($($gargs),* )
532 }
533
534 /// Creates a matrix filled with its diagonal filled with `elt` and all other
535 /// components set to zero.
536 ///
537 /// # Example
538 /// ```
539 /// # use nalgebra::{Matrix2x3, DMatrix};
540 /// # use std::iter;
541 ///
542 /// let m = Matrix2x3::from_diagonal_element(5.0);
543 /// // The two additional arguments represent the matrix dimensions.
544 /// let dm = DMatrix::from_diagonal_element(2, 3, 5.0);
545 ///
546 /// assert!(m.m11 == 5.0 && m.m12 == 0.0 && m.m13 == 0.0 &&
547 /// m.m21 == 0.0 && m.m22 == 5.0 && m.m23 == 0.0);
548 /// assert!(dm[(0, 0)] == 5.0 && dm[(0, 1)] == 0.0 && dm[(0, 2)] == 0.0 &&
549 /// dm[(1, 0)] == 0.0 && dm[(1, 1)] == 5.0 && dm[(1, 2)] == 0.0);
550 /// ```
551 #[inline]
552 pub fn from_diagonal_element($($args: usize,)* elt: T) -> Self
553 where T: Zero + One {
554 Self::from_diagonal_element_generic($($gargs, )* elt)
555 }
556
557 /// Creates a new matrix that may be rectangular. The first `elts.len()` diagonal
558 /// elements are filled with the content of `elts`. Others are set to 0.
559 ///
560 /// Panics if `elts.len()` is larger than the minimum among `nrows` and `ncols`.
561 ///
562 /// # Example
563 /// ```
564 /// # use nalgebra::{Matrix3, DMatrix};
565 /// # use std::iter;
566 ///
567 /// let m = Matrix3::from_partial_diagonal(&[1.0, 2.0]);
568 /// // The two additional arguments represent the matrix dimensions.
569 /// let dm = DMatrix::from_partial_diagonal(3, 3, &[1.0, 2.0]);
570 ///
571 /// assert!(m.m11 == 1.0 && m.m12 == 0.0 && m.m13 == 0.0 &&
572 /// m.m21 == 0.0 && m.m22 == 2.0 && m.m23 == 0.0 &&
573 /// m.m31 == 0.0 && m.m32 == 0.0 && m.m33 == 0.0);
574 /// assert!(dm[(0, 0)] == 1.0 && dm[(0, 1)] == 0.0 && dm[(0, 2)] == 0.0 &&
575 /// dm[(1, 0)] == 0.0 && dm[(1, 1)] == 2.0 && dm[(1, 2)] == 0.0 &&
576 /// dm[(2, 0)] == 0.0 && dm[(2, 1)] == 0.0 && dm[(2, 2)] == 0.0);
577 /// ```
578 #[inline]
579 pub fn from_partial_diagonal($($args: usize,)* elts: &[T]) -> Self
580 where T: Zero {
581 Self::from_partial_diagonal_generic($($gargs, )* elts)
582 }
583
584 /// Creates a matrix or vector filled with random values from the given distribution.
585 #[inline]
586 #[cfg(feature = "rand-no-std")]
587 pub fn from_distribution<Distr: Distribution<T> + ?Sized, G: Rng + ?Sized>(
588 $($args: usize,)*
589 distribution: &Distr,
590 rng: &mut G,
591 ) -> Self {
592 Self::from_distribution_generic($($gargs, )* distribution, rng)
593 }
594
595 /// Creates a matrix filled with random values.
596 #[inline]
597 #[cfg(feature = "rand")]
598 pub fn new_random($($args: usize),*) -> Self
599 where Standard: Distribution<T> {
600 Self::new_random_generic($($gargs),*)
601 }
602 }
603);
604
605/// # Constructors of statically-sized vectors or statically-sized matrices
606impl<T: Scalar, R: DimName, C: DimName> OMatrix<T, R, C>
607where
608 DefaultAllocator: Allocator<T, R, C>,
609{
610 // TODO: this is not very pretty. We could find a better call syntax.
611 impl_constructors!(R, C; // Arguments for Matrix<T, ..., S>
612 => R: DimName, => C: DimName; // Type parameters for impl<T, ..., S>
613 R::name(), C::name(); // Arguments for `_generic` constructors.
614 ); // Arguments for non-generic constructors.
615}
616
617/// # Constructors of matrices with a dynamic number of columns
618impl<T: Scalar, R: DimName> OMatrix<T, R, Dynamic>
619where
620 DefaultAllocator: Allocator<T, R, Dynamic>,
621{
622 impl_constructors!(R, Dynamic;
623 => R: DimName;
624 R::name(), Dynamic::new(ncols);
625 ncols);
626}
627
628/// # Constructors of dynamic vectors and matrices with a dynamic number of rows
629impl<T: Scalar, C: DimName> OMatrix<T, Dynamic, C>
630where
631 DefaultAllocator: Allocator<T, Dynamic, C>,
632{
633 impl_constructors!(Dynamic, C;
634 => C: DimName;
635 Dynamic::new(nrows), C::name();
636 nrows);
637}
638
639/// # Constructors of fully dynamic matrices
640impl<T: Scalar> OMatrix<T, Dynamic, Dynamic>
641where
642 DefaultAllocator: Allocator<T, Dynamic, Dynamic>,
643{
644 impl_constructors!(Dynamic, Dynamic;
645 ;
646 Dynamic::new(nrows), Dynamic::new(ncols);
647 nrows, ncols);
648}
649
650/*
651 *
652 * Constructors that don't necessarily require all dimensions
653 * to be specified when one dimension is already known.
654 *
655 */
656macro_rules! impl_constructors_from_data(
657 ($data: ident; $($Dims: ty),*; $(=> $DimIdent: ident: $DimBound: ident),*; $($gargs: expr),*; $($args: ident),*) => {
658 impl<T: Scalar, $($DimIdent: $DimBound, )*> OMatrix<T $(, $Dims)*>
659 where DefaultAllocator: Allocator<T $(, $Dims)*> {
660 /// Creates a matrix with its elements filled with the components provided by a slice
661 /// in row-major order.
662 ///
663 /// The order of elements in the slice must follow the usual mathematic writing, i.e.,
664 /// row-by-row.
665 ///
666 /// # Example
667 /// ```
668 /// # use nalgebra::{Matrix2x3, Vector3, DVector, DMatrix};
669 /// # use std::iter;
670 ///
671 /// let v = Vector3::from_row_slice(&[0, 1, 2]);
672 /// // The additional argument represents the vector dimension.
673 /// let dv = DVector::from_row_slice(&[0, 1, 2]);
674 /// let m = Matrix2x3::from_row_slice(&[0, 1, 2, 3, 4, 5]);
675 /// // The two additional arguments represent the matrix dimensions.
676 /// let dm = DMatrix::from_row_slice(2, 3, &[0, 1, 2, 3, 4, 5]);
677 ///
678 /// assert!(v.x == 0 && v.y == 1 && v.z == 2);
679 /// assert!(dv[0] == 0 && dv[1] == 1 && dv[2] == 2);
680 /// assert!(m.m11 == 0 && m.m12 == 1 && m.m13 == 2 &&
681 /// m.m21 == 3 && m.m22 == 4 && m.m23 == 5);
682 /// assert!(dm[(0, 0)] == 0 && dm[(0, 1)] == 1 && dm[(0, 2)] == 2 &&
683 /// dm[(1, 0)] == 3 && dm[(1, 1)] == 4 && dm[(1, 2)] == 5);
684 /// ```
685 #[inline]
686 pub fn from_row_slice($($args: usize,)* $data: &[T]) -> Self {
687 Self::from_row_slice_generic($($gargs, )* $data)
688 }
689
690 /// Creates a matrix with its elements filled with the components provided by a slice
691 /// in column-major order.
692 ///
693 /// # Example
694 /// ```
695 /// # use nalgebra::{Matrix2x3, Vector3, DVector, DMatrix};
696 /// # use std::iter;
697 ///
698 /// let v = Vector3::from_column_slice(&[0, 1, 2]);
699 /// // The additional argument represents the vector dimension.
700 /// let dv = DVector::from_column_slice(&[0, 1, 2]);
701 /// let m = Matrix2x3::from_column_slice(&[0, 1, 2, 3, 4, 5]);
702 /// // The two additional arguments represent the matrix dimensions.
703 /// let dm = DMatrix::from_column_slice(2, 3, &[0, 1, 2, 3, 4, 5]);
704 ///
705 /// assert!(v.x == 0 && v.y == 1 && v.z == 2);
706 /// assert!(dv[0] == 0 && dv[1] == 1 && dv[2] == 2);
707 /// assert!(m.m11 == 0 && m.m12 == 2 && m.m13 == 4 &&
708 /// m.m21 == 1 && m.m22 == 3 && m.m23 == 5);
709 /// assert!(dm[(0, 0)] == 0 && dm[(0, 1)] == 2 && dm[(0, 2)] == 4 &&
710 /// dm[(1, 0)] == 1 && dm[(1, 1)] == 3 && dm[(1, 2)] == 5);
711 /// ```
712 #[inline]
713 pub fn from_column_slice($($args: usize,)* $data: &[T]) -> Self {
714 Self::from_column_slice_generic($($gargs, )* $data)
715 }
716
717 /// Creates a matrix backed by a given `Vec`.
718 ///
719 /// The output matrix is filled column-by-column.
720 ///
721 /// # Example
722 /// ```
723 /// # use nalgebra::{DMatrix, Matrix2x3};
724 ///
725 /// let m = Matrix2x3::from_vec(vec![0, 1, 2, 3, 4, 5]);
726 ///
727 /// assert!(m.m11 == 0 && m.m12 == 2 && m.m13 == 4 &&
728 /// m.m21 == 1 && m.m22 == 3 && m.m23 == 5);
729 ///
730 ///
731 /// // The two additional arguments represent the matrix dimensions.
732 /// let dm = DMatrix::from_vec(2, 3, vec![0, 1, 2, 3, 4, 5]);
733 ///
734 /// assert!(dm[(0, 0)] == 0 && dm[(0, 1)] == 2 && dm[(0, 2)] == 4 &&
735 /// dm[(1, 0)] == 1 && dm[(1, 1)] == 3 && dm[(1, 2)] == 5);
736 /// ```
737 #[inline]
738 #[cfg(any(feature = "std", feature = "alloc"))]
739 pub fn from_vec($($args: usize,)* $data: Vec<T>) -> Self {
740 Self::from_vec_generic($($gargs, )* $data)
741 }
742 }
743 }
744);
745
746// TODO: this is not very pretty. We could find a better call syntax.
747impl_constructors_from_data!(data; R, C; // Arguments for Matrix<T, ..., S>
748=> R: DimName, => C: DimName; // Type parameters for impl<T, ..., S>
749R::name(), C::name(); // Arguments for `_generic` constructors.
750); // Arguments for non-generic constructors.
751
752impl_constructors_from_data!(data; R, Dynamic;
753=> R: DimName;
754R::name(), Dynamic::new(data.len() / R::dim());
755);
756
757impl_constructors_from_data!(data; Dynamic, C;
758=> C: DimName;
759Dynamic::new(data.len() / C::dim()), C::name();
760);
761
762impl_constructors_from_data!(data; Dynamic, Dynamic;
763 ;
764 Dynamic::new(nrows), Dynamic::new(ncols);
765 nrows, ncols);
766
767/*
768 *
769 * Zero, One, Rand traits.
770 *
771 */
772impl<T, R: DimName, C: DimName> Zero for OMatrix<T, R, C>
773where
774 T: Scalar + Zero + ClosedAdd,
775 DefaultAllocator: Allocator<T, R, C>,
776{
777 #[inline]
778 fn zero() -> Self {
779 Self::from_element(T::zero())
780 }
781
782 #[inline]
783 fn is_zero(&self) -> bool {
784 self.iter().all(|e| e.is_zero())
785 }
786}
787
788impl<T, D: DimName> One for OMatrix<T, D, D>
789where
790 T: Scalar + Zero + One + ClosedMul + ClosedAdd,
791 DefaultAllocator: Allocator<T, D, D>,
792{
793 #[inline]
794 fn one() -> Self {
795 Self::identity()
796 }
797}
798
799impl<T, R: DimName, C: DimName> Bounded for OMatrix<T, R, C>
800where
801 T: Scalar + Bounded,
802 DefaultAllocator: Allocator<T, R, C>,
803{
804 #[inline]
805 fn max_value() -> Self {
806 Self::from_element(T::max_value())
807 }
808
809 #[inline]
810 fn min_value() -> Self {
811 Self::from_element(T::min_value())
812 }
813}
814
815#[cfg(feature = "rand-no-std")]
816impl<T: Scalar, R: Dim, C: Dim> Distribution<OMatrix<T, R, C>> for Standard
817where
818 DefaultAllocator: Allocator<T, R, C>,
819 Standard: Distribution<T>,
820{
821 #[inline]
822 fn sample<G: Rng + ?Sized>(&self, rng: &mut G) -> OMatrix<T, R, C> {
823 let nrows = R::try_to_usize().unwrap_or_else(|| rng.gen_range(0..10));
824 let ncols = C::try_to_usize().unwrap_or_else(|| rng.gen_range(0..10));
825
826 OMatrix::from_fn_generic(R::from_usize(nrows), C::from_usize(ncols), |_, _| rng.gen())
827 }
828}
829
830#[cfg(feature = "arbitrary")]
831impl<T, R, C> Arbitrary for OMatrix<T, R, C>
832where
833 R: Dim,
834 C: Dim,
835 T: Scalar + Arbitrary + Send,
836 DefaultAllocator: Allocator<T, R, C>,
837 Owned<T, R, C>: Clone + Send,
838{
839 #[inline]
840 fn arbitrary(g: &mut Gen) -> Self {
841 let nrows = R::try_to_usize().unwrap_or(usize::arbitrary(g) % 10);
842 let ncols = C::try_to_usize().unwrap_or(usize::arbitrary(g) % 10);
843
844 Self::from_fn_generic(R::from_usize(nrows), C::from_usize(ncols), |_, _| {
845 T::arbitrary(g)
846 })
847 }
848}
849
850// TODO(specialization): faster impls possible for D≤4 (see rand_distr::{UnitCircle, UnitSphere})
851#[cfg(feature = "rand")]
852impl<T: crate::RealField, D: DimName> Distribution<Unit<OVector<T, D>>> for Standard
853where
854 DefaultAllocator: Allocator<T, D>,
855 rand_distr::StandardNormal: Distribution<T>,
856{
857 /// Generate a uniformly distributed random unit vector.
858 #[inline]
859 fn sample<G: Rng + ?Sized>(&self, rng: &mut G) -> Unit<OVector<T, D>> {
860 Unit::new_normalize(OVector::from_distribution_generic(
861 D::name(),
862 Const::<1>,
863 &rand_distr::StandardNormal,
864 rng,
865 ))
866 }
867}
868
869/*
870 *
871 * Constructors for small matrices and vectors.
872 *
873 */
874
875macro_rules! transpose_array(
876 [$($a: ident),*;] => {
877 [$([$a]),*]
878 };
879 [$($a: ident),*; $($b: ident),*;] => {
880 [$([$a, $b]),*]
881 };
882 [$($a: ident),*; $($b: ident),*; $($c: ident),*;] => {
883 [$([$a, $b, $c]),*]
884 };
885 [$($a: ident),*; $($b: ident),*; $($c: ident),*; $($d: ident),*;] => {
886 [$([$a, $b, $c, $d]),*]
887 };
888 [$($a: ident),*; $($b: ident),*; $($c: ident),*; $($d: ident),*; $($e: ident),*;] => {
889 [$([$a, $b, $c, $d, $e]),*]
890 };
891 [$($a: ident),*; $($b: ident),*; $($c: ident),*; $($d: ident),*; $($e: ident),*; $($f: ident),*;] => {
892 [$([$a, $b, $c, $d, $e, $f]),*]
893 };
894);
895
896macro_rules! componentwise_constructors_impl(
897 ($($R: expr, $C: expr, [$($($args: ident),*);*] $(;)*)*) => {$(
898 impl<T> Matrix<T, Const<$R>, Const<$C>, ArrayStorage<T, $R, $C>> {
899 /// Initializes this matrix from its components.
900 #[inline]
901 #[allow(clippy::too_many_arguments)]
902 pub const fn new($($($args: T),*),*) -> Self {
903 unsafe {
904 Self::from_data_statically_unchecked(
905 ArrayStorage(
906 transpose_array![
907 $(
908 $($args),*
909 ;)*
910 ]
911 )
912 )
913 }
914 }
915 }
916 )*}
917);
918
919componentwise_constructors_impl!(
920 /*
921 * Square matrices 1 .. 6.
922 */
923 2, 2, [m11, m12;
924 m21, m22];
925 3, 3, [m11, m12, m13;
926 m21, m22, m23;
927 m31, m32, m33];
928 4, 4, [m11, m12, m13, m14;
929 m21, m22, m23, m24;
930 m31, m32, m33, m34;
931 m41, m42, m43, m44];
932 5, 5, [m11, m12, m13, m14, m15;
933 m21, m22, m23, m24, m25;
934 m31, m32, m33, m34, m35;
935 m41, m42, m43, m44, m45;
936 m51, m52, m53, m54, m55];
937 6, 6, [m11, m12, m13, m14, m15, m16;
938 m21, m22, m23, m24, m25, m26;
939 m31, m32, m33, m34, m35, m36;
940 m41, m42, m43, m44, m45, m46;
941 m51, m52, m53, m54, m55, m56;
942 m61, m62, m63, m64, m65, m66];
943
944 /*
945 * Rectangular matrices with 2 rows.
946 */
947 2, 3, [m11, m12, m13;
948 m21, m22, m23];
949 2, 4, [m11, m12, m13, m14;
950 m21, m22, m23, m24];
951 2, 5, [m11, m12, m13, m14, m15;
952 m21, m22, m23, m24, m25];
953 2, 6, [m11, m12, m13, m14, m15, m16;
954 m21, m22, m23, m24, m25, m26];
955
956 /*
957 * Rectangular matrices with 3 rows.
958 */
959 3, 2, [m11, m12;
960 m21, m22;
961 m31, m32];
962 3, 4, [m11, m12, m13, m14;
963 m21, m22, m23, m24;
964 m31, m32, m33, m34];
965 3, 5, [m11, m12, m13, m14, m15;
966 m21, m22, m23, m24, m25;
967 m31, m32, m33, m34, m35];
968 3, 6, [m11, m12, m13, m14, m15, m16;
969 m21, m22, m23, m24, m25, m26;
970 m31, m32, m33, m34, m35, m36];
971
972 /*
973 * Rectangular matrices with 4 rows.
974 */
975 4, 2, [m11, m12;
976 m21, m22;
977 m31, m32;
978 m41, m42];
979 4, 3, [m11, m12, m13;
980 m21, m22, m23;
981 m31, m32, m33;
982 m41, m42, m43];
983 4, 5, [m11, m12, m13, m14, m15;
984 m21, m22, m23, m24, m25;
985 m31, m32, m33, m34, m35;
986 m41, m42, m43, m44, m45];
987 4, 6, [m11, m12, m13, m14, m15, m16;
988 m21, m22, m23, m24, m25, m26;
989 m31, m32, m33, m34, m35, m36;
990 m41, m42, m43, m44, m45, m46];
991
992 /*
993 * Rectangular matrices with 5 rows.
994 */
995 5, 2, [m11, m12;
996 m21, m22;
997 m31, m32;
998 m41, m42;
999 m51, m52];
1000 5, 3, [m11, m12, m13;
1001 m21, m22, m23;
1002 m31, m32, m33;
1003 m41, m42, m43;
1004 m51, m52, m53];
1005 5, 4, [m11, m12, m13, m14;
1006 m21, m22, m23, m24;
1007 m31, m32, m33, m34;
1008 m41, m42, m43, m44;
1009 m51, m52, m53, m54];
1010 5, 6, [m11, m12, m13, m14, m15, m16;
1011 m21, m22, m23, m24, m25, m26;
1012 m31, m32, m33, m34, m35, m36;
1013 m41, m42, m43, m44, m45, m46;
1014 m51, m52, m53, m54, m55, m56];
1015
1016 /*
1017 * Rectangular matrices with 6 rows.
1018 */
1019 6, 2, [m11, m12;
1020 m21, m22;
1021 m31, m32;
1022 m41, m42;
1023 m51, m52;
1024 m61, m62];
1025 6, 3, [m11, m12, m13;
1026 m21, m22, m23;
1027 m31, m32, m33;
1028 m41, m42, m43;
1029 m51, m52, m53;
1030 m61, m62, m63];
1031 6, 4, [m11, m12, m13, m14;
1032 m21, m22, m23, m24;
1033 m31, m32, m33, m34;
1034 m41, m42, m43, m44;
1035 m51, m52, m53, m54;
1036 m61, m62, m63, m64];
1037 6, 5, [m11, m12, m13, m14, m15;
1038 m21, m22, m23, m24, m25;
1039 m31, m32, m33, m34, m35;
1040 m41, m42, m43, m44, m45;
1041 m51, m52, m53, m54, m55;
1042 m61, m62, m63, m64, m65];
1043
1044 /*
1045 * Row vectors 1 .. 6.
1046 */
1047 1, 1, [x];
1048 1, 2, [x, y];
1049 1, 3, [x, y, z];
1050 1, 4, [x, y, z, w];
1051 1, 5, [x, y, z, w, a];
1052 1, 6, [x, y, z, w, a, b];
1053
1054 /*
1055 * Column vectors 1 .. 6.
1056 */
1057 2, 1, [x; y];
1058 3, 1, [x; y; z];
1059 4, 1, [x; y; z; w];
1060 5, 1, [x; y; z; w; a];
1061 6, 1, [x; y; z; w; a; b];
1062);
1063
1064/*
1065 *
1066 * Axis constructors.
1067 *
1068 */
1069impl<T, R: DimName> OVector<T, R>
1070where
1071 R: ToTypenum,
1072 T: Scalar + Zero + One,
1073 DefaultAllocator: Allocator<T, R>,
1074{
1075 /// The column vector with `val` as its i-th component.
1076 #[inline]
1077 pub fn ith(i: usize, val: T) -> Self {
1078 let mut res = Self::zeros();
1079 res[i] = val;
1080 res
1081 }
1082
1083 /// The column unit vector with `T::one()` as its i-th component.
1084 #[inline]
1085 pub fn ith_axis(i: usize) -> Unit<Self> {
1086 Unit::new_unchecked(Self::ith(i, T::one()))
1087 }
1088
1089 /// The column vector with a 1 as its first component, and zero elsewhere.
1090 #[inline]
1091 pub fn x() -> Self
1092 where
1093 R::Typenum: Cmp<typenum::U0, Output = Greater>,
1094 {
1095 let mut res = Self::zeros();
1096 unsafe {
1097 *res.vget_unchecked_mut(0) = T::one();
1098 }
1099
1100 res
1101 }
1102
1103 /// The column vector with a 1 as its second component, and zero elsewhere.
1104 #[inline]
1105 pub fn y() -> Self
1106 where
1107 R::Typenum: Cmp<typenum::U1, Output = Greater>,
1108 {
1109 let mut res = Self::zeros();
1110 unsafe {
1111 *res.vget_unchecked_mut(1) = T::one();
1112 }
1113
1114 res
1115 }
1116
1117 /// The column vector with a 1 as its third component, and zero elsewhere.
1118 #[inline]
1119 pub fn z() -> Self
1120 where
1121 R::Typenum: Cmp<typenum::U2, Output = Greater>,
1122 {
1123 let mut res = Self::zeros();
1124 unsafe {
1125 *res.vget_unchecked_mut(2) = T::one();
1126 }
1127
1128 res
1129 }
1130
1131 /// The column vector with a 1 as its fourth component, and zero elsewhere.
1132 #[inline]
1133 pub fn w() -> Self
1134 where
1135 R::Typenum: Cmp<typenum::U3, Output = Greater>,
1136 {
1137 let mut res = Self::zeros();
1138 unsafe {
1139 *res.vget_unchecked_mut(3) = T::one();
1140 }
1141
1142 res
1143 }
1144
1145 /// The column vector with a 1 as its fifth component, and zero elsewhere.
1146 #[inline]
1147 pub fn a() -> Self
1148 where
1149 R::Typenum: Cmp<typenum::U4, Output = Greater>,
1150 {
1151 let mut res = Self::zeros();
1152 unsafe {
1153 *res.vget_unchecked_mut(4) = T::one();
1154 }
1155
1156 res
1157 }
1158
1159 /// The column vector with a 1 as its sixth component, and zero elsewhere.
1160 #[inline]
1161 pub fn b() -> Self
1162 where
1163 R::Typenum: Cmp<typenum::U5, Output = Greater>,
1164 {
1165 let mut res = Self::zeros();
1166 unsafe {
1167 *res.vget_unchecked_mut(5) = T::one();
1168 }
1169
1170 res
1171 }
1172
1173 /// The unit column vector with a 1 as its first component, and zero elsewhere.
1174 #[inline]
1175 pub fn x_axis() -> Unit<Self>
1176 where
1177 R::Typenum: Cmp<typenum::U0, Output = Greater>,
1178 {
1179 Unit::new_unchecked(Self::x())
1180 }
1181
1182 /// The unit column vector with a 1 as its second component, and zero elsewhere.
1183 #[inline]
1184 pub fn y_axis() -> Unit<Self>
1185 where
1186 R::Typenum: Cmp<typenum::U1, Output = Greater>,
1187 {
1188 Unit::new_unchecked(Self::y())
1189 }
1190
1191 /// The unit column vector with a 1 as its third component, and zero elsewhere.
1192 #[inline]
1193 pub fn z_axis() -> Unit<Self>
1194 where
1195 R::Typenum: Cmp<typenum::U2, Output = Greater>,
1196 {
1197 Unit::new_unchecked(Self::z())
1198 }
1199
1200 /// The unit column vector with a 1 as its fourth component, and zero elsewhere.
1201 #[inline]
1202 pub fn w_axis() -> Unit<Self>
1203 where
1204 R::Typenum: Cmp<typenum::U3, Output = Greater>,
1205 {
1206 Unit::new_unchecked(Self::w())
1207 }
1208
1209 /// The unit column vector with a 1 as its fifth component, and zero elsewhere.
1210 #[inline]
1211 pub fn a_axis() -> Unit<Self>
1212 where
1213 R::Typenum: Cmp<typenum::U4, Output = Greater>,
1214 {
1215 Unit::new_unchecked(Self::a())
1216 }
1217
1218 /// The unit column vector with a 1 as its sixth component, and zero elsewhere.
1219 #[inline]
1220 pub fn b_axis() -> Unit<Self>
1221 where
1222 R::Typenum: Cmp<typenum::U5, Output = Greater>,
1223 {
1224 Unit::new_unchecked(Self::b())
1225 }
1226}