nalgebra/third_party/mint/
mint_matrix.rs

1use std::convert::{AsMut, AsRef, From, Into};
2use std::mem::{self, MaybeUninit};
3use std::ptr;
4
5use crate::base::allocator::Allocator;
6use crate::base::dimension::{Const, DimName, U1, U2, U3, U4};
7use crate::base::storage::{IsContiguous, RawStorage, RawStorageMut};
8use crate::base::{DefaultAllocator, Matrix, OMatrix, Scalar};
9
10macro_rules! impl_from_into_mint_1D(
11    ($($NRows: ident => $VT:ident [$SZ: expr]);* $(;)*) => {$(
12        impl<T> From<mint::$VT<T>> for OMatrix<T, $NRows, U1>
13        where T: Scalar,
14              DefaultAllocator: Allocator<$NRows, U1> {
15            #[inline]
16            fn from(v: mint::$VT<T>) -> Self {
17                unsafe {
18                    let mut res = Matrix::uninit(<$NRows>::name(), Const::<1>);
19                    // Copy the data.
20                    ptr::copy_nonoverlapping(&v.x, res.data.ptr_mut() as *mut T, $SZ);
21                    // Prevent from being dropped the originals we just copied.
22                    mem::forget(v);
23                    // The result is now fully initialized.
24                    res.assume_init()
25                }
26            }
27        }
28
29        impl<T, S> Into<mint::$VT<T>> for Matrix<T, $NRows, U1, S>
30        where T: Scalar,
31              S: RawStorage<T, $NRows, U1> + IsContiguous {
32            #[inline]
33            fn into(self) -> mint::$VT<T> {
34                // SAFETY: this is OK thanks to the IsContiguous bound.
35                unsafe {
36                    let mut res: MaybeUninit<mint::$VT<T>> = MaybeUninit::uninit();
37                    // Copy the data.
38                    ptr::copy_nonoverlapping(self.data.ptr(), res.as_mut_ptr() as *mut T, $SZ);
39                    // Prevent from being dropped the originals we just copied.
40                    mem::forget(self);
41                    // The result is now fully initialized.
42                    res.assume_init()
43                }
44            }
45        }
46
47        impl<T, S> AsRef<mint::$VT<T>> for Matrix<T, $NRows, U1, S>
48        where T: Scalar,
49              S: RawStorage<T, $NRows, U1> + IsContiguous {
50            #[inline]
51            fn as_ref(&self) -> &mint::$VT<T> {
52                // SAFETY: this is OK thanks to the IsContiguous bound.
53                unsafe {
54                    mem::transmute(self.data.ptr())
55                }
56            }
57        }
58
59        impl<T, S> AsMut<mint::$VT<T>> for Matrix<T, $NRows, U1, S>
60        where T: Scalar,
61              S: RawStorageMut<T, $NRows, U1> + IsContiguous {
62            #[inline]
63            fn as_mut(&mut self) -> &mut mint::$VT<T> {
64                // SAFETY: this is OK thanks to the IsContiguous bound.
65                unsafe {
66                    mem::transmute(self.data.ptr_mut())
67                }
68            }
69        }
70    )*}
71);
72
73// Implement for vectors of dimension 2 .. 4.
74impl_from_into_mint_1D!(
75    U2 => Vector2[2];
76    U3 => Vector3[3];
77    U4 => Vector4[4];
78);
79
80macro_rules! impl_from_into_mint_2D(
81    ($(($NRows: ty, $NCols: ty) => $MV:ident{ $($component:ident),* }[$SZRows: expr]);* $(;)*) => {$(
82        impl<T> From<mint::$MV<T>> for OMatrix<T, $NRows, $NCols>
83        where T: Scalar,
84              DefaultAllocator: Allocator<$NRows, $NCols> {
85            #[inline]
86            fn from(m: mint::$MV<T>) -> Self {
87                unsafe {
88                    let mut res = Matrix::uninit(<$NRows>::name(), <$NCols>::name());
89                    let mut ptr = res.data.ptr_mut();
90                    $(
91                        ptr::copy_nonoverlapping(&m.$component.x, ptr as *mut T, $SZRows);
92                        ptr = ptr.offset($SZRows);
93                    )*
94                    let _ = ptr; // Just to avoid some unused assignment warnings.
95                    // Forget the original data to avoid double-free.
96                    mem::forget(m);
97                    res.assume_init()
98                }
99            }
100        }
101
102        impl<T> Into<mint::$MV<T>> for OMatrix<T, $NRows, $NCols>
103        where T: Scalar,
104              DefaultAllocator: Allocator<$NRows, $NCols> {
105            #[inline]
106            fn into(self) -> mint::$MV<T> {
107                unsafe {
108                    let mut res: MaybeUninit<mint::$MV<T>> = MaybeUninit::uninit();
109                    let mut ptr = self.data.ptr();
110                    $(
111                        ptr::copy_nonoverlapping(ptr, ptr::addr_of_mut!((*res.as_mut_ptr()).$component) as *mut T, $SZRows);
112                        ptr = ptr.offset($SZRows);
113                    )*
114                    let _ = ptr;
115                    // Forget the original data to avoid double-free.
116                    mem::forget(self);
117                    res.assume_init()
118                }
119            }
120        }
121    )*}
122);
123
124// Implement for matrices with shape 2x2 .. 4x4.
125impl_from_into_mint_2D!(
126    (U2, U2) => ColumnMatrix2{x, y}[2];
127    (U2, U3) => ColumnMatrix2x3{x, y, z}[2];
128    (U3, U3) => ColumnMatrix3{x, y, z}[3];
129    (U3, U4) => ColumnMatrix3x4{x, y, z, w}[3];
130    (U4, U4) => ColumnMatrix4{x, y, z, w}[4];
131);