nalgebra/base/
conversion.rs

1#[cfg(all(feature = "alloc", not(feature = "std")))]
2use alloc::vec::Vec;
3use simba::scalar::{SubsetOf, SupersetOf};
4use std::borrow::{Borrow, BorrowMut};
5use std::convert::{AsMut, AsRef, From, Into};
6
7use simba::simd::{PrimitiveSimdValue, SimdValue};
8
9use crate::base::allocator::{Allocator, SameShapeAllocator};
10use crate::base::constraint::{SameNumberOfColumns, SameNumberOfRows, ShapeConstraint};
11use crate::base::dimension::{
12    Const, Dim, U1, U10, U11, U12, U13, U14, U15, U16, U2, U3, U4, U5, U6, U7, U8, U9,
13};
14#[cfg(any(feature = "std", feature = "alloc"))]
15use crate::base::dimension::{DimName, Dyn};
16use crate::base::iter::{MatrixIter, MatrixIterMut};
17use crate::base::storage::{IsContiguous, RawStorage, RawStorageMut};
18use crate::base::{
19    ArrayStorage, DVectorView, DVectorViewMut, DefaultAllocator, Matrix, MatrixView, MatrixViewMut,
20    OMatrix, Scalar,
21};
22#[cfg(any(feature = "std", feature = "alloc"))]
23use crate::base::{DVector, RowDVector, VecStorage};
24use crate::base::{ViewStorage, ViewStorageMut};
25use crate::constraint::DimEq;
26use crate::{IsNotStaticOne, RowSVector, SMatrix, SVector, VectorView, VectorViewMut};
27use std::mem::MaybeUninit;
28
29// TODO: too bad this won't work for slice conversions.
30impl<T1, T2, R1, C1, R2, C2> SubsetOf<OMatrix<T2, R2, C2>> for OMatrix<T1, R1, C1>
31where
32    R1: Dim,
33    C1: Dim,
34    R2: Dim,
35    C2: Dim,
36    T1: Scalar,
37    T2: Scalar + SupersetOf<T1>,
38    DefaultAllocator: Allocator<R2, C2> + Allocator<R1, C1> + SameShapeAllocator<R1, C1, R2, C2>,
39    ShapeConstraint: SameNumberOfRows<R1, R2> + SameNumberOfColumns<C1, C2>,
40{
41    #[inline]
42    fn to_superset(&self) -> OMatrix<T2, R2, C2> {
43        let (nrows, ncols) = self.shape();
44        let nrows2 = R2::from_usize(nrows);
45        let ncols2 = C2::from_usize(ncols);
46        let mut res = Matrix::uninit(nrows2, ncols2);
47
48        for i in 0..nrows {
49            for j in 0..ncols {
50                // Safety: all indices are in range.
51                unsafe {
52                    *res.get_unchecked_mut((i, j)) =
53                        MaybeUninit::new(T2::from_subset(self.get_unchecked((i, j))));
54                }
55            }
56        }
57
58        // Safety: res is now fully initialized.
59        unsafe { res.assume_init() }
60    }
61
62    #[inline]
63    fn is_in_subset(m: &OMatrix<T2, R2, C2>) -> bool {
64        m.iter().all(|e| e.is_in_subset())
65    }
66
67    #[inline]
68    fn from_superset_unchecked(m: &OMatrix<T2, R2, C2>) -> Self {
69        let (nrows2, ncols2) = m.shape();
70        let nrows = R1::from_usize(nrows2);
71        let ncols = C1::from_usize(ncols2);
72        let mut res = Matrix::uninit(nrows, ncols);
73
74        for i in 0..nrows2 {
75            for j in 0..ncols2 {
76                // Safety: all indices are in range.
77                unsafe {
78                    *res.get_unchecked_mut((i, j)) =
79                        MaybeUninit::new(m.get_unchecked((i, j)).to_subset_unchecked())
80                }
81            }
82        }
83
84        unsafe { res.assume_init() }
85    }
86}
87
88impl<'a, T: Scalar, R: Dim, C: Dim, S: RawStorage<T, R, C>> IntoIterator
89    for &'a Matrix<T, R, C, S>
90{
91    type Item = &'a T;
92    type IntoIter = MatrixIter<'a, T, R, C, S>;
93
94    #[inline]
95    fn into_iter(self) -> Self::IntoIter {
96        self.iter()
97    }
98}
99
100impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim> IntoIterator
101    for Matrix<T, R, C, ViewStorage<'a, T, R, C, RStride, CStride>>
102{
103    type Item = &'a T;
104    type IntoIter = MatrixIter<'a, T, R, C, ViewStorage<'a, T, R, C, RStride, CStride>>;
105
106    #[inline]
107    fn into_iter(self) -> Self::IntoIter {
108        MatrixIter::new_owned(self.data)
109    }
110}
111
112impl<'a, T: Scalar, R: Dim, C: Dim, S: RawStorageMut<T, R, C>> IntoIterator
113    for &'a mut Matrix<T, R, C, S>
114{
115    type Item = &'a mut T;
116    type IntoIter = MatrixIterMut<'a, T, R, C, S>;
117
118    #[inline]
119    fn into_iter(self) -> Self::IntoIter {
120        self.iter_mut()
121    }
122}
123
124impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim> IntoIterator
125    for Matrix<T, R, C, ViewStorageMut<'a, T, R, C, RStride, CStride>>
126{
127    type Item = &'a mut T;
128    type IntoIter = MatrixIterMut<'a, T, R, C, ViewStorageMut<'a, T, R, C, RStride, CStride>>;
129
130    #[inline]
131    fn into_iter(self) -> Self::IntoIter {
132        MatrixIterMut::new_owned_mut(self.data)
133    }
134}
135
136impl<T: Scalar, const D: usize> From<[T; D]> for SVector<T, D> {
137    #[inline]
138    fn from(arr: [T; D]) -> Self {
139        unsafe { Self::from_data_statically_unchecked(ArrayStorage([arr; 1])) }
140    }
141}
142
143impl<T: Scalar, const D: usize> From<SVector<T, D>> for [T; D] {
144    #[inline]
145    fn from(vec: SVector<T, D>) -> Self {
146        // TODO: unfortunately, we must clone because we can move out of an array.
147        vec.data.0[0].clone()
148    }
149}
150
151impl<'a, T: Scalar, RStride: Dim, CStride: Dim, const D: usize>
152    From<VectorView<'a, T, Const<D>, RStride, CStride>> for [T; D]
153{
154    #[inline]
155    fn from(vec: VectorView<'a, T, Const<D>, RStride, CStride>) -> Self {
156        vec.into_owned().into()
157    }
158}
159
160impl<'a, T: Scalar, RStride: Dim, CStride: Dim, const D: usize>
161    From<VectorViewMut<'a, T, Const<D>, RStride, CStride>> for [T; D]
162{
163    #[inline]
164    fn from(vec: VectorViewMut<'a, T, Const<D>, RStride, CStride>) -> Self {
165        vec.into_owned().into()
166    }
167}
168
169impl<T: Scalar, const D: usize> From<[T; D]> for RowSVector<T, D>
170where
171    Const<D>: IsNotStaticOne,
172{
173    #[inline]
174    fn from(arr: [T; D]) -> Self {
175        SVector::<T, D>::from(arr).transpose()
176    }
177}
178
179impl<T: Scalar, const D: usize> From<RowSVector<T, D>> for [T; D]
180where
181    Const<D>: IsNotStaticOne,
182{
183    #[inline]
184    fn from(vec: RowSVector<T, D>) -> [T; D] {
185        vec.transpose().into()
186    }
187}
188
189macro_rules! impl_from_into_asref_1D(
190    ($(($NRows: ident, $NCols: ident) => $SZ: expr);* $(;)*) => {$(
191        impl<T, S> AsRef<[T; $SZ]> for Matrix<T, $NRows, $NCols, S>
192        where T: Scalar,
193              S: RawStorage<T, $NRows, $NCols> + IsContiguous {
194            #[inline]
195            fn as_ref(&self) -> &[T; $SZ] {
196                // Safety: this is OK thanks to the IsContiguous trait.
197                unsafe {
198                    &*(self.data.ptr() as *const [T; $SZ])
199                }
200            }
201        }
202
203        impl<T, S> AsMut<[T; $SZ]> for Matrix<T, $NRows, $NCols, S>
204        where T: Scalar,
205              S: RawStorageMut<T, $NRows, $NCols> + IsContiguous {
206            #[inline]
207            fn as_mut(&mut self) -> &mut [T; $SZ] {
208                // Safety: this is OK thanks to the IsContiguous trait.
209                unsafe {
210                    &mut *(self.data.ptr_mut() as *mut [T; $SZ])
211                }
212            }
213        }
214    )*}
215);
216
217// Implement for vectors of dimension 1 .. 16.
218impl_from_into_asref_1D!(
219    // Row vectors.
220    (U1, U1 ) => 1;  (U1, U2 ) => 2;  (U1, U3 ) => 3;  (U1, U4 ) => 4;
221    (U1, U5 ) => 5;  (U1, U6 ) => 6;  (U1, U7 ) => 7;  (U1, U8 ) => 8;
222    (U1, U9 ) => 9;  (U1, U10) => 10; (U1, U11) => 11; (U1, U12) => 12;
223    (U1, U13) => 13; (U1, U14) => 14; (U1, U15) => 15; (U1, U16) => 16;
224
225    // Column vectors.
226                     (U2 , U1) => 2;  (U3 , U1) => 3;  (U4 , U1) => 4;
227    (U5 , U1) => 5;  (U6 , U1) => 6;  (U7 , U1) => 7;  (U8 , U1) => 8;
228    (U9 , U1) => 9;  (U10, U1) => 10; (U11, U1) => 11; (U12, U1) => 12;
229    (U13, U1) => 13; (U14, U1) => 14; (U15, U1) => 15; (U16, U1) => 16;
230);
231
232impl<T: Scalar, const R: usize, const C: usize> From<[[T; R]; C]> for SMatrix<T, R, C> {
233    #[inline]
234    fn from(arr: [[T; R]; C]) -> Self {
235        unsafe { Self::from_data_statically_unchecked(ArrayStorage(arr)) }
236    }
237}
238
239impl<T: Scalar, const R: usize, const C: usize> From<SMatrix<T, R, C>> for [[T; R]; C] {
240    #[inline]
241    fn from(mat: SMatrix<T, R, C>) -> Self {
242        mat.data.0
243    }
244}
245
246impl<'a, T: Scalar, RStride: Dim, CStride: Dim, const R: usize, const C: usize>
247    From<MatrixView<'a, T, Const<R>, Const<C>, RStride, CStride>> for [[T; R]; C]
248{
249    #[inline]
250    fn from(mat: MatrixView<'a, T, Const<R>, Const<C>, RStride, CStride>) -> Self {
251        mat.into_owned().into()
252    }
253}
254
255impl<'a, T: Scalar, RStride: Dim, CStride: Dim, const R: usize, const C: usize>
256    From<MatrixViewMut<'a, T, Const<R>, Const<C>, RStride, CStride>> for [[T; R]; C]
257{
258    #[inline]
259    fn from(mat: MatrixViewMut<'a, T, Const<R>, Const<C>, RStride, CStride>) -> Self {
260        mat.into_owned().into()
261    }
262}
263
264macro_rules! impl_from_into_asref_borrow_2D(
265
266    //does the impls on one case for either AsRef/AsMut and Borrow/BorrowMut
267    (
268        ($NRows: ty, $NCols: ty) => ($SZRows: expr, $SZCols: expr);
269        $Ref:ident.$ref:ident(), $Mut:ident.$mut:ident()
270    ) => {
271        impl<T: Scalar, S> $Ref<[[T; $SZRows]; $SZCols]> for Matrix<T, $NRows, $NCols, S>
272        where S: RawStorage<T, $NRows, $NCols> + IsContiguous {
273            #[inline]
274            fn $ref(&self) -> &[[T; $SZRows]; $SZCols] {
275                // Safety: OK thanks to the IsContiguous trait.
276                unsafe {
277                    &*(self.data.ptr() as *const [[T; $SZRows]; $SZCols])
278                }
279            }
280        }
281
282        impl<T: Scalar, S> $Mut<[[T; $SZRows]; $SZCols]> for Matrix<T, $NRows, $NCols, S>
283        where S: RawStorageMut<T, $NRows, $NCols> + IsContiguous {
284            #[inline]
285            fn $mut(&mut self) -> &mut [[T; $SZRows]; $SZCols] {
286                // Safety: OK thanks to the IsContiguous trait.
287                unsafe {
288                    &mut *(self.data.ptr_mut() as *mut [[T; $SZRows]; $SZCols])
289                }
290            }
291        }
292    };
293
294    //collects the mappings from typenum pairs to consts
295    ($(($NRows: ty, $NCols: ty) => ($SZRows: expr, $SZCols: expr));* $(;)*) => {$(
296        impl_from_into_asref_borrow_2D!(
297            ($NRows, $NCols) => ($SZRows, $SZCols); AsRef.as_ref(), AsMut.as_mut()
298        );
299        impl_from_into_asref_borrow_2D!(
300            ($NRows, $NCols) => ($SZRows, $SZCols); Borrow.borrow(), BorrowMut.borrow_mut()
301        );
302    )*}
303);
304
305// Implement for matrices with shape 2x2 .. 6x6.
306impl_from_into_asref_borrow_2D!(
307    (U2, U2) => (2, 2); (U2, U3) => (2, 3); (U2, U4) => (2, 4); (U2, U5) => (2, 5); (U2, U6) => (2, 6);
308    (U3, U2) => (3, 2); (U3, U3) => (3, 3); (U3, U4) => (3, 4); (U3, U5) => (3, 5); (U3, U6) => (3, 6);
309    (U4, U2) => (4, 2); (U4, U3) => (4, 3); (U4, U4) => (4, 4); (U4, U5) => (4, 5); (U4, U6) => (4, 6);
310    (U5, U2) => (5, 2); (U5, U3) => (5, 3); (U5, U4) => (5, 4); (U5, U5) => (5, 5); (U5, U6) => (5, 6);
311    (U6, U2) => (6, 2); (U6, U3) => (6, 3); (U6, U4) => (6, 4); (U6, U5) => (6, 5); (U6, U6) => (6, 6);
312);
313
314impl<'a, T, RStride, CStride, const R: usize, const C: usize>
315    From<MatrixView<'a, T, Const<R>, Const<C>, RStride, CStride>>
316    for Matrix<T, Const<R>, Const<C>, ArrayStorage<T, R, C>>
317where
318    T: Scalar,
319    RStride: Dim,
320    CStride: Dim,
321{
322    fn from(matrix_view: MatrixView<'a, T, Const<R>, Const<C>, RStride, CStride>) -> Self {
323        matrix_view.into_owned()
324    }
325}
326
327#[cfg(any(feature = "std", feature = "alloc"))]
328impl<'a, T, C, RStride, CStride> From<MatrixView<'a, T, Dyn, C, RStride, CStride>>
329    for Matrix<T, Dyn, C, VecStorage<T, Dyn, C>>
330where
331    T: Scalar,
332    C: Dim,
333    RStride: Dim,
334    CStride: Dim,
335{
336    fn from(matrix_view: MatrixView<'a, T, Dyn, C, RStride, CStride>) -> Self {
337        matrix_view.into_owned()
338    }
339}
340
341#[cfg(any(feature = "std", feature = "alloc"))]
342impl<'a, T, R, RStride, CStride> From<MatrixView<'a, T, R, Dyn, RStride, CStride>>
343    for Matrix<T, R, Dyn, VecStorage<T, R, Dyn>>
344where
345    T: Scalar,
346    R: DimName,
347    RStride: Dim,
348    CStride: Dim,
349{
350    fn from(matrix_view: MatrixView<'a, T, R, Dyn, RStride, CStride>) -> Self {
351        matrix_view.into_owned()
352    }
353}
354
355impl<'a, T, RStride, CStride, const R: usize, const C: usize>
356    From<MatrixViewMut<'a, T, Const<R>, Const<C>, RStride, CStride>>
357    for Matrix<T, Const<R>, Const<C>, ArrayStorage<T, R, C>>
358where
359    T: Scalar,
360    RStride: Dim,
361    CStride: Dim,
362{
363    fn from(matrix_view: MatrixViewMut<'a, T, Const<R>, Const<C>, RStride, CStride>) -> Self {
364        matrix_view.into_owned()
365    }
366}
367
368#[cfg(any(feature = "std", feature = "alloc"))]
369impl<'a, T, C, RStride, CStride> From<MatrixViewMut<'a, T, Dyn, C, RStride, CStride>>
370    for Matrix<T, Dyn, C, VecStorage<T, Dyn, C>>
371where
372    T: Scalar,
373    C: Dim,
374    RStride: Dim,
375    CStride: Dim,
376{
377    fn from(matrix_view: MatrixViewMut<'a, T, Dyn, C, RStride, CStride>) -> Self {
378        matrix_view.into_owned()
379    }
380}
381
382#[cfg(any(feature = "std", feature = "alloc"))]
383impl<'a, T, R, RStride, CStride> From<MatrixViewMut<'a, T, R, Dyn, RStride, CStride>>
384    for Matrix<T, R, Dyn, VecStorage<T, R, Dyn>>
385where
386    T: Scalar,
387    R: DimName,
388    RStride: Dim,
389    CStride: Dim,
390{
391    fn from(matrix_view: MatrixViewMut<'a, T, R, Dyn, RStride, CStride>) -> Self {
392        matrix_view.into_owned()
393    }
394}
395
396impl<'a, T, R, C, RView, CView, RStride, CStride, S> From<&'a Matrix<T, R, C, S>>
397    for MatrixView<'a, T, RView, CView, RStride, CStride>
398where
399    R: Dim,
400    C: Dim,
401    RView: Dim,
402    CView: Dim,
403    RStride: Dim,
404    CStride: Dim,
405    S: RawStorage<T, R, C>,
406    ShapeConstraint:
407        DimEq<R, RView> + DimEq<C, CView> + DimEq<RStride, S::RStride> + DimEq<CStride, S::CStride>,
408{
409    fn from(m: &'a Matrix<T, R, C, S>) -> Self {
410        let (row, col) = m.shape_generic();
411        let rows_result = RView::from_usize(row.value());
412        let cols_result = CView::from_usize(col.value());
413
414        let (rstride, cstride) = m.strides();
415
416        let rstride_result = RStride::from_usize(rstride);
417        let cstride_result = CStride::from_usize(cstride);
418
419        unsafe {
420            let data = ViewStorage::from_raw_parts(
421                m.data.ptr(),
422                (rows_result, cols_result),
423                (rstride_result, cstride_result),
424            );
425            Matrix::from_data_statically_unchecked(data)
426        }
427    }
428}
429
430impl<'a, T, R, C, RView, CView, RStride, CStride, S> From<&'a mut Matrix<T, R, C, S>>
431    for MatrixView<'a, T, RView, CView, RStride, CStride>
432where
433    R: Dim,
434    C: Dim,
435    RView: Dim,
436    CView: Dim,
437    RStride: Dim,
438    CStride: Dim,
439    S: RawStorage<T, R, C>,
440    ShapeConstraint:
441        DimEq<R, RView> + DimEq<C, CView> + DimEq<RStride, S::RStride> + DimEq<CStride, S::CStride>,
442{
443    fn from(m: &'a mut Matrix<T, R, C, S>) -> Self {
444        let (row, col) = m.shape_generic();
445        let rows_result = RView::from_usize(row.value());
446        let cols_result = CView::from_usize(col.value());
447
448        let (rstride, cstride) = m.strides();
449
450        let rstride_result = RStride::from_usize(rstride);
451        let cstride_result = CStride::from_usize(cstride);
452
453        unsafe {
454            let data = ViewStorage::from_raw_parts(
455                m.data.ptr(),
456                (rows_result, cols_result),
457                (rstride_result, cstride_result),
458            );
459            Matrix::from_data_statically_unchecked(data)
460        }
461    }
462}
463
464impl<'a, T, R, C, RView, CView, RStride, CStride, S> From<&'a mut Matrix<T, R, C, S>>
465    for MatrixViewMut<'a, T, RView, CView, RStride, CStride>
466where
467    R: Dim,
468    C: Dim,
469    RView: Dim,
470    CView: Dim,
471    RStride: Dim,
472    CStride: Dim,
473    S: RawStorageMut<T, R, C>,
474    ShapeConstraint:
475        DimEq<R, RView> + DimEq<C, CView> + DimEq<RStride, S::RStride> + DimEq<CStride, S::CStride>,
476{
477    fn from(m: &'a mut Matrix<T, R, C, S>) -> Self {
478        let (row, col) = m.shape_generic();
479        let rows_result = RView::from_usize(row.value());
480        let cols_result = CView::from_usize(col.value());
481
482        let (rstride, cstride) = m.strides();
483
484        let rstride_result = RStride::from_usize(rstride);
485        let cstride_result = CStride::from_usize(cstride);
486
487        unsafe {
488            let data = ViewStorageMut::from_raw_parts(
489                m.data.ptr_mut(),
490                (rows_result, cols_result),
491                (rstride_result, cstride_result),
492            );
493            Matrix::from_data_statically_unchecked(data)
494        }
495    }
496}
497
498#[cfg(any(feature = "std", feature = "alloc"))]
499impl<T: Scalar> From<Vec<T>> for DVector<T> {
500    #[inline]
501    fn from(vec: Vec<T>) -> Self {
502        Self::from_vec(vec)
503    }
504}
505
506#[cfg(any(feature = "std", feature = "alloc"))]
507impl<T: Scalar> From<Vec<T>> for RowDVector<T> {
508    #[inline]
509    fn from(vec: Vec<T>) -> Self {
510        Self::from_vec(vec)
511    }
512}
513
514impl<'a, T: Scalar + Copy, R: Dim, C: Dim, S: RawStorage<T, R, C> + IsContiguous>
515    From<&'a Matrix<T, R, C, S>> for &'a [T]
516{
517    #[inline]
518    fn from(matrix: &'a Matrix<T, R, C, S>) -> Self {
519        matrix.as_slice()
520    }
521}
522
523impl<'a, T: Scalar + Copy, R: Dim, C: Dim, S: RawStorageMut<T, R, C> + IsContiguous>
524    From<&'a mut Matrix<T, R, C, S>> for &'a mut [T]
525{
526    #[inline]
527    fn from(matrix: &'a mut Matrix<T, R, C, S>) -> Self {
528        matrix.as_mut_slice()
529    }
530}
531
532impl<'a, T: Scalar + Copy> From<&'a [T]> for DVectorView<'a, T> {
533    #[inline]
534    fn from(slice: &'a [T]) -> Self {
535        Self::from_slice(slice, slice.len())
536    }
537}
538
539impl<'a, T: Scalar> From<DVectorView<'a, T>> for &'a [T] {
540    fn from(vec: DVectorView<'a, T>) -> &'a [T] {
541        vec.data.into_slice()
542    }
543}
544
545impl<'a, T: Scalar + Copy> From<&'a mut [T]> for DVectorViewMut<'a, T> {
546    #[inline]
547    fn from(slice: &'a mut [T]) -> Self {
548        Self::from_slice(slice, slice.len())
549    }
550}
551
552impl<'a, T: Scalar> From<DVectorViewMut<'a, T>> for &'a mut [T] {
553    fn from(vec: DVectorViewMut<'a, T>) -> &'a mut [T] {
554        vec.data.into_slice_mut()
555    }
556}
557
558impl<T: Scalar + PrimitiveSimdValue, R: Dim, C: Dim> From<[OMatrix<T::Element, R, C>; 2]>
559    for OMatrix<T, R, C>
560where
561    T: From<[<T as SimdValue>::Element; 2]>,
562    T::Element: Scalar + SimdValue,
563    DefaultAllocator: Allocator<R, C>,
564{
565    #[inline]
566    fn from(arr: [OMatrix<T::Element, R, C>; 2]) -> Self {
567        let (nrows, ncols) = arr[0].shape_generic();
568
569        Self::from_fn_generic(nrows, ncols, |i, j| {
570            [arr[0][(i, j)].clone(), arr[1][(i, j)].clone()].into()
571        })
572    }
573}
574
575impl<T: Scalar + PrimitiveSimdValue, R: Dim, C: Dim> From<[OMatrix<T::Element, R, C>; 4]>
576    for OMatrix<T, R, C>
577where
578    T: From<[<T as SimdValue>::Element; 4]>,
579    T::Element: Scalar + SimdValue,
580    DefaultAllocator: Allocator<R, C>,
581{
582    #[inline]
583    fn from(arr: [OMatrix<T::Element, R, C>; 4]) -> Self {
584        let (nrows, ncols) = arr[0].shape_generic();
585
586        Self::from_fn_generic(nrows, ncols, |i, j| {
587            [
588                arr[0][(i, j)].clone(),
589                arr[1][(i, j)].clone(),
590                arr[2][(i, j)].clone(),
591                arr[3][(i, j)].clone(),
592            ]
593            .into()
594        })
595    }
596}
597
598impl<T: Scalar + PrimitiveSimdValue, R: Dim, C: Dim> From<[OMatrix<T::Element, R, C>; 8]>
599    for OMatrix<T, R, C>
600where
601    T: From<[<T as SimdValue>::Element; 8]>,
602    T::Element: Scalar + SimdValue,
603    DefaultAllocator: Allocator<R, C>,
604{
605    #[inline]
606    fn from(arr: [OMatrix<T::Element, R, C>; 8]) -> Self {
607        let (nrows, ncols) = arr[0].shape_generic();
608
609        Self::from_fn_generic(nrows, ncols, |i, j| {
610            [
611                arr[0][(i, j)].clone(),
612                arr[1][(i, j)].clone(),
613                arr[2][(i, j)].clone(),
614                arr[3][(i, j)].clone(),
615                arr[4][(i, j)].clone(),
616                arr[5][(i, j)].clone(),
617                arr[6][(i, j)].clone(),
618                arr[7][(i, j)].clone(),
619            ]
620            .into()
621        })
622    }
623}
624
625impl<T: Scalar + PrimitiveSimdValue, R: Dim, C: Dim> From<[OMatrix<T::Element, R, C>; 16]>
626    for OMatrix<T, R, C>
627where
628    T: From<[<T as SimdValue>::Element; 16]>,
629    T::Element: Scalar + SimdValue,
630    DefaultAllocator: Allocator<R, C>,
631{
632    fn from(arr: [OMatrix<T::Element, R, C>; 16]) -> Self {
633        let (nrows, ncols) = arr[0].shape_generic();
634
635        Self::from_fn_generic(nrows, ncols, |i, j| {
636            [
637                arr[0][(i, j)].clone(),
638                arr[1][(i, j)].clone(),
639                arr[2][(i, j)].clone(),
640                arr[3][(i, j)].clone(),
641                arr[4][(i, j)].clone(),
642                arr[5][(i, j)].clone(),
643                arr[6][(i, j)].clone(),
644                arr[7][(i, j)].clone(),
645                arr[8][(i, j)].clone(),
646                arr[9][(i, j)].clone(),
647                arr[10][(i, j)].clone(),
648                arr[11][(i, j)].clone(),
649                arr[12][(i, j)].clone(),
650                arr[13][(i, j)].clone(),
651                arr[14][(i, j)].clone(),
652                arr[15][(i, j)].clone(),
653            ]
654            .into()
655        })
656    }
657}