diff --git a/nalgebra-sparse/src/pattern.rs b/nalgebra-sparse/src/pattern.rs index 2e490285..00300c3a 100644 --- a/nalgebra-sparse/src/pattern.rs +++ b/nalgebra-sparse/src/pattern.rs @@ -311,7 +311,7 @@ impl From for SparseFormatError { } impl fmt::Display for SparsityPatternFormatError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { SparsityPatternFormatError::InvalidOffsetArrayLength => { write!(f, "Length of offset array is not equal to (major_dim + 1).") diff --git a/src/base/blas.rs b/src/base/blas.rs index 45c6bf20..dec0af86 100644 --- a/src/base/blas.rs +++ b/src/base/blas.rs @@ -798,7 +798,7 @@ where impl, R1, C1>> Matrix, R1, C1, S> where T: Scalar + Zero + One + ClosedAdd + ClosedMul, - DefaultAllocator: Allocator, + // DefaultAllocator: Allocator, { /// Computes `alpha * a * b`, where `a` and `b` are matrices, and `alpha` is /// a scalar. diff --git a/src/base/componentwise.rs b/src/base/componentwise.rs index 02b2cae6..4ad672f4 100644 --- a/src/base/componentwise.rs +++ b/src/base/componentwise.rs @@ -146,7 +146,7 @@ macro_rules! component_binop_impl( ); /// # Componentwise operations -impl> Matrix { +impl> Matrix { component_binop_impl!( component_mul, component_mul_mut, component_mul_assign, cmpy, ClosedMul.mul.mul_assign, r" diff --git a/src/base/construction.rs b/src/base/construction.rs index 6f4893ae..3daf918b 100644 --- a/src/base/construction.rs +++ b/src/base/construction.rs @@ -683,7 +683,7 @@ where { /// Creates a new uninitialized matrix or vector. #[inline] - pub fn new_uninitialized(nrows: usize) -> OMatrix, Dynamic, C> { + pub fn new_uninitialized(nrows: usize) -> OMatrix, Dynamic, C> { Self::new_uninitialized_generic(Dynamic::new(nrows), C::name()) } } @@ -705,7 +705,10 @@ where { /// Creates a new uninitialized matrix or vector. #[inline] - pub fn new_uninitialized(nrows: usize, ncols: usize) -> OMatrix, Dynamic, Dynamic> { + pub fn new_uninitialized( + nrows: usize, + ncols: usize, + ) -> OMatrix, Dynamic, Dynamic> { Self::new_uninitialized_generic(Dynamic::new(nrows), Dynamic::new(ncols)) } } @@ -899,13 +902,11 @@ where } #[cfg(feature = "arbitrary")] -impl Arbitrary for OMatrix +impl Arbitrary for OMatrix where - R: Dim, - C: Dim, T: Arbitrary + Send, DefaultAllocator: Allocator, - Owned: Clone + Send, + Owned: Clone+Send, { #[inline] fn arbitrary(g: &mut Gen) -> Self { diff --git a/src/base/conversion.rs b/src/base/conversion.rs index 071679f0..f8e803fe 100644 --- a/src/base/conversion.rs +++ b/src/base/conversion.rs @@ -82,7 +82,7 @@ where } } -impl<'a, T: Scalar, R: Dim, C: Dim, S: Storage> IntoIterator for &'a Matrix { +impl<'a, T, R: Dim, C: Dim, S: Storage> IntoIterator for &'a Matrix { type Item = &'a T; type IntoIter = MatrixIter<'a, T, R, C, S>; @@ -92,9 +92,7 @@ impl<'a, T: Scalar, R: Dim, C: Dim, S: Storage> IntoIterator for &'a Ma } } -impl<'a, T: Scalar, R: Dim, C: Dim, S: StorageMut> IntoIterator - for &'a mut Matrix -{ +impl<'a, T, R: Dim, C: Dim, S: StorageMut> IntoIterator for &'a mut Matrix { type Item = &'a mut T; type IntoIter = MatrixIterMut<'a, T, R, C, S>; @@ -111,11 +109,13 @@ impl From<[T; D]> for SVector { } } -impl From> for [T; D] { +impl From> for [T; D] { #[inline] fn from(vec: SVector) -> Self { // TODO: unfortunately, we must clone because we can move out of an array. - vec.data.0[0].clone() + + // Counterpoint: this seems to work? + vec.data.0[0] } } @@ -125,7 +125,7 @@ where { #[inline] fn from(arr: [T; D]) -> Self { - SVector::::from(arr).transpose() + SVector::::from(arr).transpose_into() } } diff --git a/src/base/coordinates.rs b/src/base/coordinates.rs index be05d3e5..6389ccbe 100644 --- a/src/base/coordinates.rs +++ b/src/base/coordinates.rs @@ -8,7 +8,7 @@ use std::ops::{Deref, DerefMut}; use crate::base::dimension::{U1, U2, U3, U4, U5, U6}; use crate::base::storage::{ContiguousStorage, ContiguousStorageMut}; -use crate::base::{Matrix, Scalar}; +use crate::base::Matrix; /* * @@ -23,7 +23,7 @@ macro_rules! coords_impl( #[repr(C)] #[derive(Eq, PartialEq, Clone, Hash, Debug, Copy)] #[cfg_attr(feature = "serde-serialize-no-std", derive(Serialize, Deserialize))] - pub struct $T { + pub struct $T { $(pub $comps: T),* } } @@ -31,7 +31,7 @@ macro_rules! coords_impl( macro_rules! deref_impl( ($R: ty, $C: ty; $Target: ident) => { - impl Deref for Matrix + impl Deref for Matrix where S: ContiguousStorage { type Target = $Target; @@ -41,7 +41,7 @@ macro_rules! deref_impl( } } - impl DerefMut for Matrix + impl DerefMut for Matrix where S: ContiguousStorageMut { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { diff --git a/src/base/edition.rs b/src/base/edition.rs index c9dc402e..62977493 100644 --- a/src/base/edition.rs +++ b/src/base/edition.rs @@ -70,7 +70,7 @@ impl> Matrix { for (destination, source) in irows.clone().enumerate() { unsafe { *res.vget_unchecked_mut(destination) = - MaybeUninit::new(src.vget_unchecked(*source).inlined_clone()); + MaybeUninit::new(src.vget_unchecked(*source).clone()); } } } @@ -106,11 +106,12 @@ impl> Matrix { } /// # Set rows, columns, and diagonal -impl> Matrix { +impl> Matrix { /// Fills the diagonal of this matrix with the content of the given vector. #[inline] pub fn set_diagonal(&mut self, diag: &Vector) where + T: Clone, R: DimMin, S2: Storage, ShapeConstraint: DimEq, R2>, @@ -120,7 +121,7 @@ impl> Matrix { assert_eq!(diag.len(), min_nrows_ncols, "Mismatched dimensions."); for i in 0..min_nrows_ncols { - unsafe { *self.get_unchecked_mut((i, i)) = diag.vget_unchecked(i).inlined_clone() } + unsafe { *self.get_unchecked_mut((i, i)) = diag.vget_unchecked(i).clone() } } } @@ -143,6 +144,7 @@ impl> Matrix { #[inline] pub fn set_row(&mut self, i: usize, row: &RowVector) where + T: Clone, S2: Storage, ShapeConstraint: SameNumberOfColumns, { @@ -153,6 +155,7 @@ impl> Matrix { #[inline] pub fn set_column(&mut self, i: usize, column: &Vector) where + T: Clone, S2: Storage, ShapeConstraint: SameNumberOfRows, { @@ -270,7 +273,7 @@ impl> Matrix { } } -impl> Matrix { +impl> Matrix { /// Copies the upper-triangle of this matrix to its lower-triangular part. /// /// This makes the matrix symmetric. Panics if the matrix is not square. @@ -281,7 +284,7 @@ impl> Matrix { for j in 0..dim { for i in j + 1..dim { unsafe { - *self.get_unchecked_mut((i, j)) = self.get_unchecked((j, i)).inlined_clone(); + *self.get_unchecked_mut((i, j)) = self.get_unchecked((j, i)).clone(); } } } @@ -296,7 +299,7 @@ impl> Matrix { for j in 1..self.ncols() { for i in 0..j { unsafe { - *self.get_unchecked_mut((i, j)) = self.get_unchecked((j, i)).inlined_clone(); + *self.get_unchecked_mut((i, j)) = self.get_unchecked((j, i)).clone(); } } } @@ -304,7 +307,7 @@ impl> Matrix { } /// # In-place swapping -impl> Matrix { +impl> Matrix { /// Swaps two rows in-place. #[inline] pub fn swap_rows(&mut self, irow1: usize, irow2: usize) { @@ -340,7 +343,7 @@ impl> Matrix { * */ /// # Rows and columns removal -impl> Matrix { +impl> Matrix { /* * * Column removal. @@ -569,7 +572,7 @@ impl> Matrix { } /// # Rows and columns insertion -impl> Matrix { +impl> Matrix { /* * * Columns insertion. @@ -738,7 +741,7 @@ impl> Matrix { } /// # Resizing and reshaping -impl> Matrix { +impl> Matrix { /// Resizes this matrix so that it contains `new_nrows` rows and `new_ncols` columns. /// /// The values are copied such that `self[(i, j)] == result[(i, j)]`. If the result has more @@ -846,7 +849,7 @@ impl> Matrix { } if new_ncols.value() > ncols { - res.columns_range_mut(ncols..).fill(val.inlined_clone()); + res.columns_range_mut(ncols..).fill(val.clone()); } if new_nrows.value() > nrows { @@ -928,7 +931,7 @@ impl> Matrix { /// # In-place resizing #[cfg(any(feature = "std", feature = "alloc"))] -impl OMatrix { +impl OMatrix { /// Resizes this matrix in-place. /// /// The values are copied such that `self[(i, j)] == result[(i, j)]`. If the result has more @@ -948,7 +951,7 @@ impl OMatrix { } #[cfg(any(feature = "std", feature = "alloc"))] -impl OMatrix +impl OMatrix where DefaultAllocator: Allocator, { @@ -971,7 +974,7 @@ where } #[cfg(any(feature = "std", feature = "alloc"))] -impl OMatrix +impl OMatrix where DefaultAllocator: Allocator, { @@ -993,13 +996,7 @@ where } } -unsafe fn compress_rows( - data: &mut [T], - nrows: usize, - ncols: usize, - i: usize, - nremove: usize, -) { +unsafe fn compress_rows(data: &mut [T], nrows: usize, ncols: usize, i: usize, nremove: usize) { let new_nrows = nrows - nremove; if new_nrows == 0 || ncols == 0 { @@ -1032,13 +1029,7 @@ unsafe fn compress_rows( // Moves entries of a matrix buffer to make place for `ninsert` emty rows starting at the `i-th` row index. // The `data` buffer is assumed to contained at least `(nrows + ninsert) * ncols` elements. -unsafe fn extend_rows( - data: &mut [T], - nrows: usize, - ncols: usize, - i: usize, - ninsert: usize, -) { +unsafe fn extend_rows(data: &mut [T], nrows: usize, ncols: usize, i: usize, ninsert: usize) { let new_nrows = nrows + ninsert; if new_nrows == 0 || ncols == 0 { @@ -1070,7 +1061,6 @@ unsafe fn extend_rows( #[cfg(any(feature = "std", feature = "alloc"))] impl Extend for Matrix where - T: Scalar, R: Dim, S: Extend, { @@ -1118,7 +1108,6 @@ where #[cfg(any(feature = "std", feature = "alloc"))] impl Extend for Matrix where - T: Scalar, S: Extend, { /// Extend the number of rows of a `Vector` with elements @@ -1137,12 +1126,9 @@ where } #[cfg(any(feature = "std", feature = "alloc"))] -impl Extend> for Matrix +impl Extend> for Matrix where - T: Scalar, - R: Dim, S: Extend>, - RV: Dim, SV: Storage, ShapeConstraint: SameNumberOfRows, { diff --git a/src/base/matrix.rs b/src/base/matrix.rs index 299e57e1..71c3b38e 100644 --- a/src/base/matrix.rs +++ b/src/base/matrix.rs @@ -716,7 +716,34 @@ impl> Matrix { self.transpose_to(&mut res); unsafe { - // Safety: res is now fully initialized due to the guarantees of transpose_to. + // Safety: res is now fully initialized due to the guarantees of transpose_to. + res.assume_init() + } + } + + /// Transposes `self`. Does not require `T: Clone` like its other counteparts. + pub fn transpose_into(self) -> OMatrix + where + DefaultAllocator: Allocator, + { + let (nrows, ncols) = self.data.shape(); + let mut res = OMatrix::new_uninitialized_generic(ncols, nrows); + + let (nrows, ncols) = res.shape(); + + // TODO: optimize that. + for i in 0..nrows { + for j in 0..ncols { + unsafe { + *res.get_unchecked_mut((j, i)) = MaybeUninit::new(*self.get_unchecked((i, j))); + } + } + } + + // BEEP! BEEP! There's a double drop here that needs to be fixed. + + unsafe { + // Safety: res is now fully initialized due to the guarantees of transpose_to. res.assume_init() } } @@ -728,13 +755,12 @@ impl> Matrix { /// Returns a matrix containing the result of `f` applied to each of its entries. #[inline] #[must_use] - pub fn map T2>(&self, mut f: F) -> OMatrix + pub fn map T2>(&self, mut f: F) -> OMatrix where T: Clone, DefaultAllocator: Allocator, { let (nrows, ncols) = self.data.shape(); - let mut res = OMatrix::new_uninitialized_generic(nrows, ncols); for j in 0..ncols.value() { @@ -1283,6 +1309,8 @@ impl> Matrix { } } } + + // BEEP BEEEP!!!!! I'm double-freeing! OH NO!!!! (todo) } /// Fills this matrix with the content of the transpose another one via clones. @@ -1359,6 +1387,8 @@ impl> Matrix { } } } + + // BEEP BEEPP! Same thing as the non-transpose method, this is UB. } // TODO: rename `apply` to `apply_mut` and `apply_into` to `apply`? @@ -1370,6 +1400,51 @@ impl> Matrix { } } +impl, R, C>> Matrix, R, C, S> { + /// Initializes this matrix with the content of another one via clones. Both must have the same shape. + #[inline] + pub fn copy_init_from(&mut self, other: &Matrix) + where + T: Clone, + SB: Storage, + ShapeConstraint: SameNumberOfRows + SameNumberOfColumns, + { + self.copy_from_fn(other, |e| MaybeUninit::new(e.clone())) + } + + /// Initializes this matrix with the content of another one, after applying a function to + /// the entries of the other matrix. Both must have the same shape. + #[inline] + pub fn move_init_from(&mut self, other: Matrix) + where + SB: Storage, + ShapeConstraint: SameNumberOfRows + SameNumberOfColumns, + { + self.move_from_fn(other, MaybeUninit::new) + } + + /// Initializes this matrix with the content of the transpose another one via clones. + #[inline] + pub fn tr_copy_init_from(&mut self, other: &Matrix) + where + T: Clone, + SB: Storage, + ShapeConstraint: DimEq + SameNumberOfColumns, + { + self.tr_copy_from_fn(other, |e| MaybeUninit::new(e.clone())) + } + + /// Initializes this matrix with the content of the transpose another one via moves. + #[inline] + pub fn tr_move_init_from(&mut self, other: Matrix) + where + SB: Storage, + ShapeConstraint: DimEq + SameNumberOfColumns, + { + self.tr_move_from_fn(other, MaybeUninit::new) + } +} + impl> Vector { /// Gets a reference to the i-th element of this column vector without bound checking. #[inline] @@ -2185,9 +2260,8 @@ impl> Matrix AbsDiffEq for Unit> +impl AbsDiffEq for Unit> where - T: Scalar + AbsDiffEq, S: Storage, T::Epsilon: Copy, { @@ -2204,9 +2278,8 @@ where } } -impl RelativeEq for Unit> +impl RelativeEq for Unit> where - T: Scalar + RelativeEq, S: Storage, T::Epsilon: Copy, { @@ -2227,9 +2300,8 @@ where } } -impl UlpsEq for Unit> +impl UlpsEq for Unit> where - T: Scalar + UlpsEq, S: Storage, T::Epsilon: Copy, { @@ -2244,9 +2316,8 @@ where } } -impl Hash for Matrix +impl Hash for Matrix where - T: Hash, S: Storage, { fn hash(&self, state: &mut H) { diff --git a/src/base/matrix_simba.rs b/src/base/matrix_simba.rs index e0333f45..f3f2d13b 100644 --- a/src/base/matrix_simba.rs +++ b/src/base/matrix_simba.rs @@ -9,11 +9,9 @@ use crate::base::{DefaultAllocator, OMatrix, Scalar}; * Simd structures. * */ -impl SimdValue for OMatrix +impl SimdValue for OMatrix where T: Scalar + SimdValue, - R: Dim, - C: Dim, T::Element: Scalar, DefaultAllocator: Allocator + Allocator, { diff --git a/src/base/ops.rs b/src/base/ops.rs index 63538121..25921e90 100644 --- a/src/base/ops.rs +++ b/src/base/ops.rs @@ -645,7 +645,7 @@ impl MulAssign> where T: Scalar + Zero + One + ClosedAdd + ClosedMul, SB: Storage, - SA: ContiguousStorageMut + Clone, + SA: ContiguousStorageMut , ShapeConstraint: AreMultipliable, DefaultAllocator: Allocator + InnerAllocator, { @@ -660,7 +660,7 @@ impl<'b, T, R1: Dim, C1: Dim, R2: Dim, SA, SB> MulAssign<&'b Matrix, - SA: ContiguousStorageMut + Clone, + SA: ContiguousStorageMut , ShapeConstraint: AreMultipliable, // TODO: this is too restrictive. See comments for the non-ref version. DefaultAllocator: Allocator + InnerAllocator, @@ -796,7 +796,6 @@ where ShapeConstraint: SameNumberOfRows + SameNumberOfColumns + AreMultipliable, - DefaultAllocator: Allocator, { out.gemm_z(T::one(), self, rhs); } diff --git a/src/base/scalar.rs b/src/base/scalar.rs index 809e03f2..c14f3eb7 100644 --- a/src/base/scalar.rs +++ b/src/base/scalar.rs @@ -26,6 +26,8 @@ pub trait Scalar: 'static + Clone + Debug { fn inlined_clone(&self) -> Self; } +// Unfortunately, this blanket impl leads to many misleading compiler messages +// telling you to implement Copy, even though Scalar is what's really needed. impl Scalar for T { #[inline(always)] fn inlined_clone(&self) -> T { diff --git a/src/base/statistics.rs b/src/base/statistics.rs index 0e0cfc6f..2bb5ba7a 100644 --- a/src/base/statistics.rs +++ b/src/base/statistics.rs @@ -7,7 +7,7 @@ use num::Zero; use simba::scalar::{ClosedAdd, Field, SupersetOf}; /// # Folding on columns and rows -impl> Matrix { +impl> Matrix { /// Returns a row vector where each element is the result of the application of `f` on the /// corresponding column of the original matrix. #[inline] diff --git a/src/base/swizzle.rs b/src/base/swizzle.rs index 25d6375f..0c471301 100644 --- a/src/base/swizzle.rs +++ b/src/base/swizzle.rs @@ -1,4 +1,4 @@ -use crate::base::{DimName, Scalar, ToTypenum, Vector, Vector2, Vector3}; +use crate::base::{DimName, ToTypenum, Vector, Vector2, Vector3}; use crate::storage::Storage; use typenum::{self, Cmp, Greater}; @@ -11,7 +11,7 @@ macro_rules! impl_swizzle { #[must_use] pub fn $name(&self) -> $Result where D::Typenum: Cmp { - $Result::new($(self[$i].inlined_clone()),*) + $Result::new($(self[$i].clone()),*) } )* )* @@ -19,7 +19,7 @@ macro_rules! impl_swizzle { } /// # Swizzling -impl> Vector +impl> Vector where D: DimName + ToTypenum, { diff --git a/src/geometry/dual_quaternion.rs b/src/geometry/dual_quaternion.rs index ba12cb6f..0fd10590 100644 --- a/src/geometry/dual_quaternion.rs +++ b/src/geometry/dual_quaternion.rs @@ -2,15 +2,15 @@ #![allow(clippy::op_ref)] use crate::{ - Isometry3, Matrix4, Normed, OVector, Point3, Quaternion, Scalar, SimdRealField, Translation3, - Unit, UnitQuaternion, Vector3, Zero, U8, + Isometry3, Matrix4, Normed, OVector, Point3, Quaternion, SimdRealField, Translation3, Unit, + UnitQuaternion, Vector3, Zero, U8, }; use approx::{AbsDiffEq, RelativeEq, UlpsEq}; #[cfg(feature = "serde-serialize-no-std")] use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::fmt; -use simba::scalar::{ClosedNeg, RealField}; +use simba::scalar::RealField; /// A dual quaternion. /// @@ -251,10 +251,7 @@ where } #[cfg(feature = "serde-serialize-no-std")] -impl Serialize for DualQuaternion -where - T: Serialize, -{ +impl Serialize for DualQuaternion { fn serialize(&self, serializer: S) -> Result<::Ok, ::Error> where S: Serializer, @@ -264,10 +261,7 @@ where } #[cfg(feature = "serde-serialize-no-std")] -impl<'a, T: SimdRealField> Deserialize<'a> for DualQuaternion -where - T: Deserialize<'a>, -{ +impl<'a, T: Deserialize<'a>> Deserialize<'a> for DualQuaternion { fn deserialize(deserializer: Des) -> Result where Des: Deserializer<'a>, @@ -283,7 +277,7 @@ where } } -impl DualQuaternion { +impl DualQuaternion { fn to_vector(self) -> OVector { (*self.as_ref()).into() } @@ -341,14 +335,14 @@ impl> UlpsEq for DualQuaternion { /// A unit quaternions. May be used to represent a rotation followed by a translation. pub type UnitDualQuaternion = Unit>; -impl PartialEq for UnitDualQuaternion { +impl PartialEq for UnitDualQuaternion { #[inline] fn eq(&self, rhs: &Self) -> bool { self.as_ref().eq(rhs.as_ref()) } } -impl Eq for UnitDualQuaternion {} +impl Eq for UnitDualQuaternion {} impl Normed for DualQuaternion { type Norm = T::SimdRealField; @@ -376,10 +370,7 @@ impl Normed for DualQuaternion { } } -impl UnitDualQuaternion -where - T::Element: SimdRealField, -{ +impl UnitDualQuaternion { /// The underlying dual quaternion. /// /// Same as `self.as_ref()`. @@ -398,7 +389,12 @@ where pub fn dual_quaternion(&self) -> &DualQuaternion { self.as_ref() } +} +impl UnitDualQuaternion +where + T::Element: SimdRealField, +{ /// Compute the conjugate of this unit quaternion. /// /// # Example @@ -600,7 +596,7 @@ where #[must_use] pub fn sclerp(&self, other: &Self, t: T) -> Self where - T: RealField, + T: RealField + RelativeEq, { self.try_sclerp(other, t, T::default_epsilon()) .expect("DualQuaternion sclerp: ambiguous configuration.") @@ -620,7 +616,7 @@ where #[must_use] pub fn try_sclerp(&self, other: &Self, t: T, epsilon: T) -> Option where - T: RealField, + T: RealField + RelativeEq, { let two = T::one() + T::one(); let half = T::one() / two; @@ -895,7 +891,7 @@ impl Default for UnitDualQuaternion { } } -impl fmt::Display for UnitDualQuaternion { +impl fmt::Display for UnitDualQuaternion { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if let Some(axis) = self.rotation().axis() { let axis = axis.into_inner(); diff --git a/src/geometry/dual_quaternion_construction.rs b/src/geometry/dual_quaternion_construction.rs index ea4c7ee2..6396a2ae 100644 --- a/src/geometry/dual_quaternion_construction.rs +++ b/src/geometry/dual_quaternion_construction.rs @@ -1,5 +1,5 @@ use crate::{ - DualQuaternion, Isometry3, Quaternion, Scalar, SimdRealField, Translation3, UnitDualQuaternion, + DualQuaternion, Isometry3, Quaternion, SimdRealField, Translation3, UnitDualQuaternion, UnitQuaternion, }; use num::{One, Zero}; @@ -7,7 +7,7 @@ use num::{One, Zero}; use quickcheck::{Arbitrary, Gen}; use simba::scalar::SupersetOf; -impl DualQuaternion { +impl DualQuaternion { /// Creates a dual quaternion from its rotation and translation components. /// /// # Example @@ -60,7 +60,7 @@ impl DualQuaternion { /// let q2 = q.cast::(); /// assert_eq!(q2, DualQuaternion::from_real(Quaternion::new(1.0f32, 2.0, 3.0, 4.0))); /// ``` - pub fn cast(self) -> DualQuaternion + pub fn cast(self) -> DualQuaternion where DualQuaternion: SupersetOf, { @@ -156,7 +156,7 @@ impl UnitDualQuaternion { /// let q2 = q.cast::(); /// assert_eq!(q2, UnitDualQuaternion::::identity()); /// ``` - pub fn cast(self) -> UnitDualQuaternion + pub fn cast(self) -> UnitDualQuaternion where UnitDualQuaternion: SupersetOf, { diff --git a/src/geometry/dual_quaternion_conversion.rs b/src/geometry/dual_quaternion_conversion.rs index 94ef9e97..c15925a6 100644 --- a/src/geometry/dual_quaternion_conversion.rs +++ b/src/geometry/dual_quaternion_conversion.rs @@ -24,8 +24,7 @@ use crate::geometry::{ impl SubsetOf> for DualQuaternion where - T1: SimdRealField, - T2: SimdRealField + SupersetOf, + T2: SupersetOf, { #[inline] fn to_superset(&self) -> DualQuaternion { @@ -49,8 +48,7 @@ where impl SubsetOf> for UnitDualQuaternion where - T1: SimdRealField, - T2: SimdRealField + SupersetOf, + T2: SupersetOf, { #[inline] fn to_superset(&self) -> UnitDualQuaternion { diff --git a/src/geometry/dual_quaternion_ops.rs b/src/geometry/dual_quaternion_ops.rs index 2a1527ec..7d07ec2c 100644 --- a/src/geometry/dual_quaternion_ops.rs +++ b/src/geometry/dual_quaternion_ops.rs @@ -56,21 +56,21 @@ use std::ops::{ Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign, }; -impl AsRef<[T; 8]> for DualQuaternion { +impl AsRef<[T; 8]> for DualQuaternion { #[inline] fn as_ref(&self) -> &[T; 8] { unsafe { &*(self as *const Self as *const [T; 8]) } } } -impl AsMut<[T; 8]> for DualQuaternion { +impl AsMut<[T; 8]> for DualQuaternion { #[inline] fn as_mut(&mut self) -> &mut [T; 8] { unsafe { &mut *(self as *mut Self as *mut [T; 8]) } } } -impl Index for DualQuaternion { +impl Index for DualQuaternion { type Output = T; #[inline] @@ -79,7 +79,7 @@ impl Index for DualQuaternion { } } -impl IndexMut for DualQuaternion { +impl IndexMut for DualQuaternion { #[inline] fn index_mut(&mut self, i: usize) -> &mut T { &mut self.as_mut()[i] diff --git a/src/geometry/isometry.rs b/src/geometry/isometry.rs index 333468b3..cb56ad83 100755 --- a/src/geometry/isometry.rs +++ b/src/geometry/isometry.rs @@ -80,7 +80,6 @@ pub struct Isometry { #[cfg(feature = "abomonation-serialize")] impl Abomonation for Isometry where - T: SimdRealField, R: Abomonation, Translation: Abomonation, { @@ -106,10 +105,7 @@ mod rkyv_impl { use crate::{base::Scalar, geometry::Translation}; use rkyv::{offset_of, project_struct, Archive, Deserialize, Fallible, Serialize}; - impl Archive for Isometry - where - T::Archived: Scalar, - { + impl Archive for Isometry { type Archived = Isometry; type Resolver = (R::Resolver, as Archive>::Resolver); @@ -132,8 +128,8 @@ mod rkyv_impl { } } - impl, R: Serialize, S: Fallible + ?Sized, const D: usize> - Serialize for Isometry + impl, R: Serialize, S: Fallible + ?Sized, const D: usize> Serialize + for Isometry where T::Archived: Scalar, { @@ -145,7 +141,7 @@ mod rkyv_impl { } } - impl + impl Deserialize, _D> for Isometry where T::Archived: Scalar + Deserialize, @@ -160,7 +156,7 @@ mod rkyv_impl { } } -impl hash::Hash for Isometry +impl hash::Hash for Isometry where Owned>: hash::Hash, { @@ -170,12 +166,9 @@ where } } -impl Copy for Isometry where - Owned>: Copy -{ -} +impl Copy for Isometry where Owned>: Copy {} -impl Clone for Isometry { +impl Clone for Isometry { #[inline] fn clone(&self) -> Self { Self { @@ -638,7 +631,7 @@ where * Display * */ -impl fmt::Display for Isometry +impl fmt::Display for Isometry where R: fmt::Display, { diff --git a/src/geometry/point.rs b/src/geometry/point.rs index 4317a62c..a393bc2d 100644 --- a/src/geometry/point.rs +++ b/src/geometry/point.rs @@ -5,6 +5,7 @@ use std::fmt; use std::hash; #[cfg(feature = "abomonation-serialize")] use std::io::{Result as IOResult, Write}; +use std::mem::MaybeUninit; #[cfg(feature = "serde-serialize-no-std")] use serde::{Deserialize, Deserializer, Serialize, Serializer}; @@ -20,6 +21,7 @@ use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; use crate::base::iter::{MatrixIter, MatrixIterMut}; use crate::base::{Const, DefaultAllocator, OVector}; use crate::storage::Owned; +use crate::Scalar; /// A point in an euclidean space. /// @@ -41,7 +43,7 @@ use crate::storage::Owned; /// may have some other methods, e.g., `isometry.inverse_transform_point(&point)`. See the documentation /// of said transformations for details. #[repr(C)] -#[derive(Debug, Clone)] +// TODO: figure out why #[derive(Clone, Debug)] doesn't work! pub struct OPoint where DefaultAllocator: InnerAllocator, @@ -66,6 +68,16 @@ where { } +impl Clone for OPoint +where + DefaultAllocator: Allocator, + OVector: Clone, +{ + fn clone(&self) -> Self { + Self::from(self.coords.clone()) + } +} + #[cfg(feature = "bytemuck")] unsafe impl bytemuck::Zeroable for OPoint where @@ -151,7 +163,8 @@ where #[inline] #[must_use] pub fn map T2>(&self, f: F) -> OPoint - where T:Clone, + where + T: Clone, DefaultAllocator: Allocator, { self.coords.map(f).into() @@ -194,22 +207,44 @@ where #[inline] #[must_use] pub fn to_homogeneous(&self) -> OVector> + where + T: One + Clone, + D: DimNameAdd, + DefaultAllocator: Allocator>, + { + let mut res = OVector::<_, DimNameSum>::new_uninitialized(); + for i in 0..D::dim() { + unsafe { + *res.get_unchecked(i) = MaybeUninit::new(self.coords[i].clone()); + } + } + + res[(D::dim(), 0)] = MaybeUninit::new(T::one()); + + unsafe { res.assume_init() } + } + + pub fn into_homogeneous(self) -> OVector> where T: One, D: DimNameAdd, DefaultAllocator: Allocator>, { - let mut res = unsafe { - crate::unimplemented_or_uninitialized_generic!( - as DimName>::name(), - Const::<1> - ) - }; - res.generic_slice_mut((0, 0), (D::name(), Const::<1>)) - .copy_from(&self.coords); - res[(D::dim(), 0)] = T::one(); + let mut res = OVector::<_, DimNameSum>::new_uninitialized(); - res + // TODO: maybe we can move the whole array at once? Or use `into_iter` + // to avoid double-dropping. + for i in 0..D::dim() { + unsafe { + *res.get_unchecked(i) = MaybeUninit::new(self.coords[i]); + } + } + + // Fix double drop + + res[(D::dim(), 0)] = MaybeUninit::new(T::one()); + + unsafe { res.assume_init() } } /// Creates a new point with the given coordinates. @@ -415,7 +450,7 @@ where /* * inf/sup */ -impl OPoint +impl OPoint where DefaultAllocator: Allocator, { diff --git a/src/geometry/point_construction.rs b/src/geometry/point_construction.rs index 317eb8e7..34048a35 100644 --- a/src/geometry/point_construction.rs +++ b/src/geometry/point_construction.rs @@ -50,9 +50,9 @@ where #[inline] pub fn origin() -> Self where - T: Zero, + T: Zero + Clone, { - Self::from(OVector::from_element(T::zero())) + Self::from(OVector::<_, D>::zeros()) } /// Creates a new point from a slice. @@ -70,8 +70,11 @@ where /// assert_eq!(pt, Point3::new(1.0, 2.0, 3.0)); /// ``` #[inline] - pub fn from_slice(components: &[T]) -> Self { - Self::from(OVector::from_row_slice(components)) + pub fn from_slice(components: &[T]) -> Self + where + T: Clone, + { + Self::from(OVector::<_, D>::from_row_slice(components)) } /// Creates a new point from its homogeneous vector representation. @@ -175,7 +178,7 @@ where impl Arbitrary for OPoint where DefaultAllocator: Allocator, - crate::base::storage::Owned: Send, + crate::base::storage::Owned: Clone + Send, { #[inline] fn arbitrary(g: &mut Gen) -> Self { diff --git a/src/geometry/point_conversion.rs b/src/geometry/point_conversion.rs index 423b4d4f..022a7bd4 100644 --- a/src/geometry/point_conversion.rs +++ b/src/geometry/point_conversion.rs @@ -2,12 +2,11 @@ use num::{One, Zero}; use simba::scalar::{ClosedDiv, SubsetOf, SupersetOf}; use simba::simd::PrimitiveSimdValue; -use crate::base::allocator::Allocator; +use crate::base::allocator::{Allocator, InnerAllocator}; use crate::base::dimension::{DimNameAdd, DimNameSum, U1}; use crate::base::{Const, DefaultAllocator, Matrix, OVector, Scalar}; use crate::geometry::Point; -use crate::storage::Owned; use crate::{DimName, OPoint}; /* @@ -55,7 +54,7 @@ where #[inline] fn to_superset(&self) -> OVector> { let p: OPoint = self.to_superset(); - p.to_homogeneous() + p.into_homogeneous() } #[inline] @@ -79,7 +78,7 @@ where { #[inline] fn from(t: OPoint) -> Self { - t.to_homogeneous() + t.into_homogeneous() } } @@ -101,7 +100,7 @@ impl From> for [T; D] { impl From> for OPoint where - DefaultAllocator: Allocator, + DefaultAllocator: InnerAllocator, { #[inline] fn from(coords: OVector) -> Self { @@ -109,81 +108,81 @@ where } } -impl From<[Point; 2]> for Point +impl From<[Point; 2]> for Point where T: From<[::Element; 2]>, - T::Element: Copy, - Owned>: Copy, + T::Element: Scalar, { #[inline] fn from(arr: [Point; 2]) -> Self { - Self::from(OVector::from([arr[0].coords, arr[1].coords])) + Self::from(OVector::from([ + arr[0].coords.clone(), + arr[1].coords.clone(), + ])) } } -impl From<[Point; 4]> for Point +impl From<[Point; 4]> for Point where T: From<[::Element; 4]>, - T::Element: Copy, - Owned>: Copy, + T::Element: Scalar, { #[inline] fn from(arr: [Point; 4]) -> Self { Self::from(OVector::from([ - arr[0].coords, - arr[1].coords, - arr[2].coords, - arr[3].coords, + arr[0].coords.clone(), + arr[1].coords.clone(), + arr[2].coords.clone(), + arr[3].coords.clone(), ])) } } -impl From<[Point; 8]> for Point +impl From<[Point; 8]> for Point where T: From<[::Element; 8]>, - T::Element: Copy, - Owned>: Copy, + T::Element: Scalar, { #[inline] fn from(arr: [Point; 8]) -> Self { Self::from(OVector::from([ - arr[0].coords, - arr[1].coords, - arr[2].coords, - arr[3].coords, - arr[4].coords, - arr[5].coords, - arr[6].coords, - arr[7].coords, + arr[0].coords.clone(), + arr[1].coords.clone(), + arr[2].coords.clone(), + arr[3].coords.clone(), + arr[4].coords.clone(), + arr[5].coords.clone(), + arr[6].coords.clone(), + arr[7].coords.clone(), ])) } } -impl From<[Point; 16]> for Point +impl From<[Point; 16]> + for Point where T: From<[::Element; 16]>, - T::Element: Copy, - Owned>: Copy, + T::Element: Scalar, { #[inline] fn from(arr: [Point; 16]) -> Self { Self::from(OVector::from([ - arr[0].coords, - arr[1].coords, - arr[2].coords, - arr[3].coords, - arr[4].coords, - arr[5].coords, - arr[6].coords, - arr[7].coords, - arr[8].coords, - arr[9].coords, - arr[10].coords, - arr[11].coords, - arr[12].coords, - arr[13].coords, - arr[14].coords, - arr[15].coords, + arr[0].coords.clone(), + arr[1].coords.clone(), + arr[2].coords.clone(), + arr[3].coords.clone(), + arr[4].coords.clone(), + arr[5].coords.clone(), + arr[6].coords.clone(), + arr[7].coords.clone(), + arr[8].coords.clone(), + arr[9].coords.clone(), + arr[10].coords.clone(), + arr[11].coords.clone(), + arr[12].coords.clone(), + arr[13].coords.clone(), + arr[14].coords.clone(), + arr[15].coords.clone(), ])) } } diff --git a/src/geometry/point_coordinates.rs b/src/geometry/point_coordinates.rs index 984a2fae..b9bd69a3 100644 --- a/src/geometry/point_coordinates.rs +++ b/src/geometry/point_coordinates.rs @@ -1,7 +1,7 @@ use std::ops::{Deref, DerefMut}; use crate::base::coordinates::{X, XY, XYZ, XYZW, XYZWA, XYZWAB}; -use crate::base::{Scalar, U1, U2, U3, U4, U5, U6}; +use crate::base::{U1, U2, U3, U4, U5, U6}; use crate::geometry::OPoint; @@ -13,7 +13,7 @@ use crate::geometry::OPoint; macro_rules! deref_impl( ($D: ty, $Target: ident $(, $comps: ident)*) => { - impl Deref for OPoint + impl Deref for OPoint { type Target = $Target; @@ -23,7 +23,7 @@ macro_rules! deref_impl( } } - impl DerefMut for OPoint + impl DerefMut for OPoint { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { diff --git a/src/geometry/point_simba.rs b/src/geometry/point_simba.rs index 7355af0e..aa630adf 100644 --- a/src/geometry/point_simba.rs +++ b/src/geometry/point_simba.rs @@ -1,10 +1,13 @@ use simba::simd::SimdValue; use crate::base::OVector; - use crate::geometry::Point; +use crate::Scalar; -impl SimdValue for Point { +impl SimdValue for Point +where + T::Element: Scalar, +{ type Element = Point; type SimdBool = T::SimdBool; diff --git a/src/geometry/quaternion.rs b/src/geometry/quaternion.rs index b6798c9f..3550cbd1 100755 --- a/src/geometry/quaternion.rs +++ b/src/geometry/quaternion.rs @@ -57,10 +57,10 @@ impl Default for Quaternion { } #[cfg(feature = "bytemuck")] -unsafe impl bytemuck::Zeroable for Quaternion where Vector4: bytemuck::Zeroable {} +unsafe impl bytemuck::Zeroable for Quaternion where Vector4: bytemuck::Zeroable {} #[cfg(feature = "bytemuck")] -unsafe impl bytemuck::Pod for Quaternion +unsafe impl bytemuck::Pod for Quaternion where Vector4: bytemuck::Pod, T: Copy, @@ -68,7 +68,7 @@ where } #[cfg(feature = "abomonation-serialize")] -impl Abomonation for Quaternion +impl Abomonation for Quaternion where Vector4: Abomonation, { @@ -86,7 +86,7 @@ where } #[cfg(feature = "serde-serialize-no-std")] -impl Serialize for Quaternion +impl Serialize for Quaternion where Owned: Serialize, { @@ -99,7 +99,7 @@ where } #[cfg(feature = "serde-serialize-no-std")] -impl<'a, T: Scalar> Deserialize<'a> for Quaternion +impl<'a, T> Deserialize<'a> for Quaternion where Owned: Deserialize<'a>, { @@ -1045,7 +1045,7 @@ impl> UlpsEq for Quaternion { } } -impl fmt::Display for Quaternion { +impl fmt::Display for Quaternion { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, @@ -1097,7 +1097,7 @@ impl UnitQuaternion where T::Element: SimdRealField, { - /// The rotation angle in [0; pi] of this unit quaternion. + /// The rotation angle in \[0; pi\] of this unit quaternion. /// /// # Example /// ``` diff --git a/src/geometry/quaternion_conversion.rs b/src/geometry/quaternion_conversion.rs index 6dfbfbc6..ead8311f 100644 --- a/src/geometry/quaternion_conversion.rs +++ b/src/geometry/quaternion_conversion.rs @@ -28,8 +28,7 @@ use crate::geometry::{ impl SubsetOf> for Quaternion where - T1: Scalar, - T2: Scalar + SupersetOf, + T2 : SupersetOf, { #[inline] fn to_superset(&self) -> Quaternion { @@ -50,9 +49,8 @@ where } impl SubsetOf> for UnitQuaternion -where - T1: Scalar, - T2: Scalar + SupersetOf, +where + T2: SupersetOf, { #[inline] fn to_superset(&self) -> UnitQuaternion { @@ -239,14 +237,14 @@ where } } -impl From> for Quaternion { +impl From> for Quaternion { #[inline] fn from(coords: Vector4) -> Self { Self { coords } } } -impl From<[T; 4]> for Quaternion { +impl From<[T; 4]> for Quaternion { #[inline] fn from(coords: [T; 4]) -> Self { Self { diff --git a/src/geometry/quaternion_ops.rs b/src/geometry/quaternion_ops.rs index eb7a15cd..c0e11327 100644 --- a/src/geometry/quaternion_ops.rs +++ b/src/geometry/quaternion_ops.rs @@ -59,12 +59,12 @@ use std::ops::{ use crate::base::dimension::U3; use crate::base::storage::Storage; -use crate::base::{Const, Scalar, Unit, Vector, Vector3}; +use crate::base::{Const, Unit, Vector, Vector3}; use crate::SimdRealField; use crate::geometry::{Point3, Quaternion, Rotation, UnitQuaternion}; -impl Index for Quaternion { +impl Index for Quaternion { type Output = T; #[inline] @@ -73,7 +73,7 @@ impl Index for Quaternion { } } -impl IndexMut for Quaternion { +impl IndexMut for Quaternion { #[inline] fn index_mut(&mut self, i: usize) -> &mut T { &mut self.coords[i] @@ -371,12 +371,12 @@ quaternion_op_impl!( ; self: Rotation, rhs: UnitQuaternion, Output = UnitQuaternion; - UnitQuaternion::::from_rotation_matrix(&self) / rhs; ); + UnitQuaternion::::from_rotation_matrix(&self) / rhs;); // UnitQuaternion × Vector quaternion_op_impl!( Mul, mul; - SB: Storage> ; + SB: Storage>; self: &'a UnitQuaternion, rhs: &'b Vector, SB>, Output = Vector3; { diff --git a/src/geometry/reflection.rs b/src/geometry/reflection.rs index 87166b81..06d07276 100644 --- a/src/geometry/reflection.rs +++ b/src/geometry/reflection.rs @@ -1,3 +1,5 @@ +use std::mem::MaybeUninit; + use crate::base::constraint::{AreMultipliable, DimEq, SameNumberOfRows, ShapeConstraint}; use crate::base::{Const, Matrix, Unit, Vector}; use crate::dimension::{Dim, U1}; @@ -77,40 +79,42 @@ impl> Reflection { pub fn reflect_rows( &self, lhs: &mut Matrix, - work: &mut Vector, + work: &mut Vector, R2, S3>, ) where S2: StorageMut, - S3: StorageMut, + S3: StorageMut, R2>, ShapeConstraint: DimEq + AreMultipliable, { lhs.mul_to(&self.axis, work); + let mut work = unsafe { work.assume_init_mut() }; if !self.bias.is_zero() { work.add_scalar_mut(-self.bias); } let m_two: T = crate::convert(-2.0f64); - lhs.gerc(m_two, work, &self.axis, T::one()); + lhs.gerc(m_two, &work, &self.axis, T::one()); } /// Applies the reflection to the rows of `lhs`. pub fn reflect_rows_with_sign( &self, lhs: &mut Matrix, - work: &mut Vector, + work: &mut Vector, R2, S3>, sign: T, ) where S2: StorageMut, - S3: StorageMut, + S3: StorageMut, R2>, ShapeConstraint: DimEq + AreMultipliable, { lhs.mul_to(&self.axis, work); + let mut work = unsafe { work.assume_init_mut() }; if !self.bias.is_zero() { work.add_scalar_mut(-self.bias); } let m_two = sign.scale(crate::convert(-2.0f64)); - lhs.gerc(m_two, work, &self.axis, sign); + lhs.gerc(m_two, &work, &self.axis, sign); } } diff --git a/src/geometry/rotation.rs b/src/geometry/rotation.rs index 4062de0d..04ffca71 100755 --- a/src/geometry/rotation.rs +++ b/src/geometry/rotation.rs @@ -71,7 +71,7 @@ where impl Copy for Rotation where Owned, Const>: Copy {} -impl Clone for Rotation +impl Clone for Rotation where Owned, Const>: Clone, { @@ -127,7 +127,7 @@ where } } -impl Rotation { +impl Rotation { /// Creates a new rotation from the given square matrix. /// /// The matrix squareness is checked but not its orthonormality. @@ -162,7 +162,7 @@ impl Rotation { } /// # Conversion to a matrix -impl Rotation { +impl Rotation { /// A reference to the underlying matrix representation of this rotation. /// /// # Example @@ -263,7 +263,7 @@ impl Rotation { #[must_use] pub fn to_homogeneous(&self) -> OMatrix, U1>, DimNameSum, U1>> where - T: Zero + One, + T: Zero + One + Scalar, Const: DimNameAdd, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>, { diff --git a/src/geometry/transform.rs b/src/geometry/transform.rs index 7ea91cd4..1607a0b0 100755 --- a/src/geometry/transform.rs +++ b/src/geometry/transform.rs @@ -1,5 +1,6 @@ use approx::{AbsDiffEq, RelativeEq, UlpsEq}; use std::any::Any; +use std::fmt; use std::fmt::Debug; use std::hash; use std::marker::PhantomData; @@ -7,7 +8,7 @@ use std::marker::PhantomData; #[cfg(feature = "serde-serialize-no-std")] use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use simba::scalar::RealField; +use simba::scalar::{ComplexField, RealField}; use crate::base::allocator::Allocator; use crate::base::dimension::{DimNameAdd, DimNameSum, U1}; @@ -119,7 +120,7 @@ macro_rules! category_mul_impl( )*} ); -// We require stability uppon multiplication. +// We require stability upon multiplication. impl TCategoryMul for T { type Representative = T; } @@ -157,8 +158,7 @@ super_tcategory_impl!( /// It is stored as a matrix with dimensions `(D + 1, D + 1)`, e.g., it stores a 4x4 matrix for a /// 3D transformation. #[repr(C)] -#[derive(Debug)] -pub struct Transform +pub struct Transform where Const: DimNameAdd, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>, @@ -167,7 +167,7 @@ where _phantom: PhantomData, } -impl hash::Hash for Transform +impl hash::Hash for Transform where Const: DimNameAdd, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>, @@ -178,7 +178,7 @@ where } } -impl Copy for Transform +impl Copy for Transform where Const: DimNameAdd, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>, @@ -186,10 +186,11 @@ where { } -impl Clone for Transform +impl Clone for Transform where Const: DimNameAdd, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>, + Owned, U1>, DimNameSum, U1>>: Clone, { #[inline] fn clone(&self) -> Self { @@ -197,8 +198,21 @@ where } } +impl Debug for Transform +where + Const: DimNameAdd, + DefaultAllocator: Allocator, U1>, DimNameSum, U1>>, + Owned, U1>, DimNameSum, U1>>: Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Transform") + .field("matrix", &self.matrix) + .finish() + } +} + #[cfg(feature = "serde-serialize-no-std")] -impl Serialize for Transform +impl Serialize for Transform where Const: DimNameAdd, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>, @@ -213,7 +227,7 @@ where } #[cfg(feature = "serde-serialize-no-std")] -impl<'a, T: RealField, C: TCategory, const D: usize> Deserialize<'a> for Transform +impl<'a, T, C: TCategory, const D: usize> Deserialize<'a> for Transform where Const: DimNameAdd, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>, @@ -231,14 +245,14 @@ where } } -impl Eq for Transform +impl Eq for Transform where Const: DimNameAdd, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>, { } -impl PartialEq for Transform +impl PartialEq for Transform where Const: DimNameAdd, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>, @@ -249,7 +263,7 @@ where } } -impl Transform +impl Transform where Const: DimNameAdd, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>, @@ -354,7 +368,10 @@ where #[deprecated( note = "This method is redundant with automatic `Copy` and the `.clone()` method and will be removed in a future release." )] - pub fn clone_owned(&self) -> Transform { + pub fn clone_owned(&self) -> Transform + where + T: Clone, + { Transform::from_matrix_unchecked(self.matrix.clone_owned()) } @@ -372,7 +389,10 @@ where /// ``` #[inline] #[must_use] - pub fn to_homogeneous(&self) -> OMatrix, U1>, DimNameSum, U1>> { + pub fn to_homogeneous(&self) -> OMatrix, U1>, DimNameSum, U1>> + where + T: Clone, + { self.matrix().clone_owned() } @@ -401,7 +421,10 @@ where /// ``` #[inline] #[must_use = "Did you mean to use try_inverse_mut()?"] - pub fn try_inverse(self) -> Option> { + pub fn try_inverse(self) -> Option> + where + T: ComplexField, + { self.matrix .try_inverse() .map(Transform::from_matrix_unchecked) @@ -427,6 +450,7 @@ where #[must_use = "Did you mean to use inverse_mut()?"] pub fn inverse(self) -> Transform where + T: ComplexField, C: SubTCategoryOf, { // TODO: specialize for TAffine? @@ -458,7 +482,10 @@ where /// assert!(!t.try_inverse_mut()); /// ``` #[inline] - pub fn try_inverse_mut(&mut self) -> bool { + pub fn try_inverse_mut(&mut self) -> bool + where + T: ComplexField, + { self.matrix.try_inverse_mut() } @@ -482,6 +509,7 @@ where #[inline] pub fn inverse_mut(&mut self) where + T: ComplexField, C: SubTCategoryOf, { let _ = self.matrix.try_inverse_mut(); diff --git a/src/geometry/translation.rs b/src/geometry/translation.rs index c667a512..69efa4d9 100755 --- a/src/geometry/translation.rs +++ b/src/geometry/translation.rs @@ -29,7 +29,7 @@ pub struct Translation { pub vector: SVector, } -impl hash::Hash for Translation +impl hash::Hash for Translation where Owned>: hash::Hash, { @@ -38,9 +38,9 @@ where } } -impl Copy for Translation {} +impl Copy for Translation {} -impl Clone for Translation +impl Clone for Translation where Owned>: Clone, { @@ -53,7 +53,6 @@ where #[cfg(feature = "abomonation-serialize")] impl Abomonation for Translation where - T: Scalar, SVector: Abomonation, { unsafe fn entomb(&self, writer: &mut W) -> IOResult<()> { @@ -70,7 +69,7 @@ where } #[cfg(feature = "serde-serialize-no-std")] -impl Serialize for Translation +impl Serialize for Translation where Owned>: Serialize, { @@ -83,7 +82,7 @@ where } #[cfg(feature = "serde-serialize-no-std")] -impl<'a, T: Scalar, const D: usize> Deserialize<'a> for Translation +impl<'a, T, const D: usize> Deserialize<'a> for Translation where Owned>: Deserialize<'a>, { @@ -140,7 +139,7 @@ mod rkyv_impl { } } -impl Translation { +impl Translation { /// Creates a new translation from the given vector. #[inline] #[deprecated(note = "Use `::from` instead.")] @@ -166,7 +165,7 @@ impl Translation { #[must_use = "Did you mean to use inverse_mut()?"] pub fn inverse(&self) -> Translation where - T: ClosedNeg, + T: ClosedNeg + Scalar, { Translation::from(-&self.vector) } @@ -193,7 +192,7 @@ impl Translation { #[must_use] pub fn to_homogeneous(&self) -> OMatrix, U1>, DimNameSum, U1>> where - T: Zero + One, + T: Zero + One + Scalar, Const: DimNameAdd, DefaultAllocator: Allocator, U1>, DimNameSum, U1>>, { @@ -224,7 +223,7 @@ impl Translation { #[inline] pub fn inverse_mut(&mut self) where - T: ClosedNeg, + T: ClosedNeg + Scalar, { self.vector.neg_mut() } @@ -264,16 +263,16 @@ impl Translation { } } -impl Eq for Translation {} +impl Eq for Translation {} -impl PartialEq for Translation { +impl PartialEq for Translation { #[inline] fn eq(&self, right: &Translation) -> bool { self.vector == right.vector } } -impl AbsDiffEq for Translation +impl AbsDiffEq for Translation where T::Epsilon: Copy, { @@ -290,7 +289,7 @@ where } } -impl RelativeEq for Translation +impl RelativeEq for Translation where T::Epsilon: Copy, { @@ -311,7 +310,7 @@ where } } -impl UlpsEq for Translation +impl UlpsEq for Translation where T::Epsilon: Copy, { diff --git a/src/geometry/translation_conversion.rs b/src/geometry/translation_conversion.rs index d443a2f4..7c75d379 100644 --- a/src/geometry/translation_conversion.rs +++ b/src/geometry/translation_conversion.rs @@ -26,9 +26,8 @@ use crate::Point; */ impl SubsetOf> for Translation -where - T1: Scalar, - T2: Scalar + SupersetOf, +where + T2: SupersetOf, { #[inline] fn to_superset(&self) -> Translation { @@ -193,14 +192,14 @@ where } } -impl From>> for Translation { +impl From>> for Translation { #[inline] fn from(vector: OVector>) -> Self { Translation { vector } } } -impl From<[T; D]> for Translation { +impl From<[T; D]> for Translation { #[inline] fn from(coords: [T; D]) -> Self { Translation { @@ -209,14 +208,14 @@ impl From<[T; D]> for Translation { } } -impl From> for Translation { +impl From> for Translation { #[inline] fn from(pt: Point) -> Self { Translation { vector: pt.coords } } } -impl From> for [T; D] { +impl From> for [T; D] { #[inline] fn from(t: Translation) -> Self { t.vector.into() diff --git a/src/linalg/bidiagonal.rs b/src/linalg/bidiagonal.rs index 6a462988..ac40331f 100644 --- a/src/linalg/bidiagonal.rs +++ b/src/linalg/bidiagonal.rs @@ -1,10 +1,13 @@ +use std::fmt; + #[cfg(feature = "serde-serialize-no-std")] use serde::{Deserialize, Serialize}; use crate::allocator::Allocator; use crate::base::{DefaultAllocator, Matrix, OMatrix, OVector, Unit}; use crate::dimension::{Const, Dim, DimDiff, DimMin, DimMinimum, DimSub, U1}; -use crate::storage::Storage; +use crate::storage::{Owned, Storage}; +use crate::{Dynamic, }; use simba::scalar::ComplexField; use crate::geometry::Reflection; @@ -32,7 +35,6 @@ use crate::linalg::householder; OVector>: Deserialize<'de>, OVector, U1>>: Deserialize<'de>")) )] -#[derive(Clone, Debug)] pub struct Bidiagonal, C: Dim> where DimMinimum: DimSub, @@ -50,18 +52,58 @@ where upper_diagonal: bool, } +impl, C: Dim> Clone for Bidiagonal +where + DimMinimum: DimSub, + DefaultAllocator: Allocator + + Allocator> + + Allocator, U1>>, + Owned: Clone, + Owned>: Clone, + Owned, U1>>: Clone, +{ + fn clone(&self) -> Self { + Self { + uv: self.uv.clone(), + diagonal: self.diagonal.clone(), + off_diagonal: self.off_diagonal.clone(), + upper_diagonal: self.upper_diagonal, + } + } +} + impl, C: Dim> Copy for Bidiagonal where DimMinimum: DimSub, DefaultAllocator: Allocator + Allocator> + Allocator, U1>>, - OMatrix: Copy, - OVector>: Copy, - OVector, U1>>: Copy, + Owned: Copy, + Owned>: Copy, + Owned, U1>>: Copy, { } +impl, C: Dim> fmt::Debug for Bidiagonal +where + DimMinimum: DimSub, + DefaultAllocator: Allocator + + Allocator> + + Allocator, U1>>, + Owned: fmt::Debug, + Owned>: fmt::Debug, + Owned, U1>>: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Bidiagonal") + .field("uv", &self.uv) + .field("diagonal", &self.diagonal) + .field("off_diagonal", &self.off_diagonal) + .field("upper_diagonal", &self.upper_diagonal) + .finish() + } +} + impl, C: Dim> Bidiagonal where DimMinimum: DimSub, @@ -81,25 +123,25 @@ where "Cannot compute the bidiagonalization of an empty matrix." ); - let mut diagonal = - unsafe { crate::unimplemented_or_uninitialized_generic!(min_nrows_ncols, Const::<1>) }; - let mut off_diagonal = unsafe { - crate::unimplemented_or_uninitialized_generic!( - min_nrows_ncols.sub(Const::<1>), - Const::<1> - ) - }; - let mut axis_packed = - unsafe { crate::unimplemented_or_uninitialized_generic!(ncols, Const::<1>) }; - let mut work = unsafe { crate::unimplemented_or_uninitialized_generic!(nrows, Const::<1>) }; + let mut diagonal = Matrix::new_uninitialized_generic(min_nrows_ncols, Const::<1>); + let mut off_diagonal = + Matrix::new_uninitialized_generic(min_nrows_ncols.sub(Const::<1>), Const::<1>); + let mut axis_packed = Matrix::new_uninitialized_generic(ncols, Const::<1>); + let mut work = Matrix::new_uninitialized_generic(nrows, Const::<1>); let upper_diagonal = nrows.value() >= ncols.value(); if upper_diagonal { for ite in 0..dim - 1 { - householder::clear_column_unchecked(&mut matrix, &mut diagonal[ite], ite, 0, None); + householder::clear_column_unchecked( + &mut matrix, + diagonal[ite].as_mut_ptr(), + ite, + 0, + None, + ); householder::clear_row_unchecked( &mut matrix, - &mut off_diagonal[ite], + off_diagonal[ite].as_mut_ptr(), &mut axis_packed, &mut work, ite, @@ -109,7 +151,7 @@ where householder::clear_column_unchecked( &mut matrix, - &mut diagonal[dim - 1], + diagonal[dim - 1].as_mut_ptr(), dim - 1, 0, None, @@ -118,7 +160,7 @@ where for ite in 0..dim - 1 { householder::clear_row_unchecked( &mut matrix, - &mut diagonal[ite], + diagonal[ite].as_mut_ptr(), &mut axis_packed, &mut work, ite, @@ -126,7 +168,7 @@ where ); householder::clear_column_unchecked( &mut matrix, - &mut off_diagonal[ite], + off_diagonal[ite].as_mut_ptr(), ite, 1, None, @@ -135,7 +177,7 @@ where householder::clear_row_unchecked( &mut matrix, - &mut diagonal[dim - 1], + diagonal[dim - 1].as_mut_ptr(), &mut axis_packed, &mut work, dim - 1, @@ -145,8 +187,8 @@ where Bidiagonal { uv: matrix, - diagonal, - off_diagonal, + diagonal: diagonal.assume_init(), + off_diagonal: off_diagonal.assume_init(), upper_diagonal, } } @@ -243,23 +285,23 @@ where #[must_use] pub fn v_t(&self) -> OMatrix, C> where - DefaultAllocator: Allocator, C>, + DefaultAllocator: Allocator, C> + Allocator, { let (nrows, ncols) = self.uv.data.shape(); let min_nrows_ncols = nrows.min(ncols); let mut res = Matrix::identity_generic(min_nrows_ncols, ncols); - let mut work = - unsafe { crate::unimplemented_or_uninitialized_generic!(min_nrows_ncols, Const::<1>) }; - let mut axis_packed = - unsafe { crate::unimplemented_or_uninitialized_generic!(ncols, Const::<1>) }; + let mut work = Matrix::new_uninitialized_generic(min_nrows_ncols, Const::<1>); + let mut axis_packed = Matrix::new_uninitialized_generic(ncols, Const::<1>); let shift = self.axis_shift().1; for i in (0..min_nrows_ncols.value() - shift).rev() { let axis = self.uv.slice_range(i, i + shift..); let mut axis_packed = axis_packed.rows_range_mut(i + shift..); - axis_packed.tr_copy_from(&axis); + axis_packed.tr_copy_init_from(&axis); + let mut axis_packed = unsafe { axis_packed.slice_assume_init() }; + // TODO: sometimes, the axis might have a zero magnitude. let refl = Reflection::new(Unit::new_unchecked(axis_packed), T::zero()); diff --git a/src/linalg/cholesky.rs b/src/linalg/cholesky.rs index f66fb42f..375ae521 100644 --- a/src/linalg/cholesky.rs +++ b/src/linalg/cholesky.rs @@ -1,3 +1,6 @@ +use std::fmt; +use std::mem::MaybeUninit; + #[cfg(feature = "serde-serialize-no-std")] use serde::{Deserialize, Serialize}; @@ -9,7 +12,7 @@ use crate::allocator::Allocator; use crate::base::{Const, DefaultAllocator, Matrix, OMatrix, Vector}; use crate::constraint::{SameNumberOfRows, ShapeConstraint}; use crate::dimension::{Dim, DimAdd, DimDiff, DimSub, DimSum, U1}; -use crate::storage::{Storage, StorageMut}; +use crate::storage::{Owned, Storage, StorageMut}; /// The Cholesky decomposition of a symmetric-definite-positive matrix. #[cfg_attr(feature = "serde-serialize-no-std", derive(Serialize, Deserialize))] @@ -23,7 +26,6 @@ use crate::storage::{Storage, StorageMut}; serde(bound(deserialize = "DefaultAllocator: Allocator, OMatrix: Deserialize<'de>")) )] -#[derive(Clone, Debug)] pub struct Cholesky where DefaultAllocator: Allocator, @@ -34,10 +36,34 @@ where impl Copy for Cholesky where DefaultAllocator: Allocator, - OMatrix: Copy, + Owned: Copy, { } +impl Clone for Cholesky +where + DefaultAllocator: Allocator, + Owned: Clone, +{ + fn clone(&self) -> Self { + Self { + chol: self.chol.clone(), + } + } +} + +impl fmt::Debug for Cholesky +where + DefaultAllocator: Allocator, + Owned: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Cholesky") + .field("chol", &self.chol) + .finish() + } +} + impl Cholesky where DefaultAllocator: Allocator, @@ -226,6 +252,8 @@ where DefaultAllocator: Allocator, DimSum> + Allocator, ShapeConstraint: SameNumberOfRows>, { + // TODO: check that MaybeUninit manipulations are sound! + let mut col = col.into_owned(); // for an explanation of the formulas, see https://en.wikipedia.org/wiki/Cholesky_decomposition#Updating_the_decomposition let n = col.nrows(); @@ -237,20 +265,20 @@ where assert!(j < n, "j needs to be within the bound of the new matrix."); // loads the data into a new matrix with an additional jth row/column - let mut chol = unsafe { - crate::unimplemented_or_uninitialized_generic!( - self.chol.data.shape().0.add(Const::<1>), - self.chol.data.shape().1.add(Const::<1>) - ) - }; + let mut chol = Matrix::new_uninitialized_generic( + self.chol.data.shape().0.add(Const::<1>), + self.chol.data.shape().1.add(Const::<1>), + ); + + // TODO: checked that every entry is initialized EXACTLY once. chol.slice_range_mut(..j, ..j) - .copy_from(&self.chol.slice_range(..j, ..j)); + .copy_init_from(&self.chol.slice_range(..j, ..j)); chol.slice_range_mut(..j, j + 1..) - .copy_from(&self.chol.slice_range(..j, j..)); + .copy_init_from(&self.chol.slice_range(..j, j..)); chol.slice_range_mut(j + 1.., ..j) - .copy_from(&self.chol.slice_range(j.., ..j)); + .copy_init_from(&self.chol.slice_range(j.., ..j)); chol.slice_range_mut(j + 1.., j + 1..) - .copy_from(&self.chol.slice_range(j.., j..)); + .copy_init_from(&self.chol.slice_range(j.., j..)); // update the jth row let top_left_corner = self.chol.slice_range(..j, ..j); @@ -266,7 +294,7 @@ where // update the center element let center_element = T::sqrt(col_j - T::from_real(new_rowj_adjoint.norm_squared())); - chol[(j, j)] = center_element; + chol[(j, j)] = MaybeUninit::new(center_element); // update the jth column let bottom_left_corner = self.chol.slice_range(j.., ..j); @@ -277,7 +305,9 @@ where &new_rowj_adjoint, T::one() / center_element, ); - chol.slice_range_mut(j + 1.., j).copy_from(&new_colj); + chol.slice_range_mut(j + 1.., j).copy_init_from(&new_colj); + + let chol = unsafe { chol.assume_init() }; // update the bottom right corner let mut bottom_right_corner = chol.slice_range_mut(j + 1.., j + 1..); @@ -298,25 +328,27 @@ where D: DimSub, DefaultAllocator: Allocator, DimDiff> + Allocator, { + // TODO: check that MaybeUninit manipulations are sound! + let n = self.chol.nrows(); assert!(n > 0, "The matrix needs at least one column."); assert!(j < n, "j needs to be within the bound of the matrix."); // loads the data into a new matrix except for the jth row/column - let mut chol = unsafe { - crate::unimplemented_or_uninitialized_generic!( - self.chol.data.shape().0.sub(Const::<1>), - self.chol.data.shape().1.sub(Const::<1>) - ) - }; + let mut chol = Matrix::new_uninitialized_generic( + self.chol.data.shape().0.sub(Const::<1>), + self.chol.data.shape().1.sub(Const::<1>), + ); + chol.slice_range_mut(..j, ..j) - .copy_from(&self.chol.slice_range(..j, ..j)); + .copy_init_from(&self.chol.slice_range(..j, ..j)); chol.slice_range_mut(..j, j..) - .copy_from(&self.chol.slice_range(..j, j + 1..)); + .copy_init_from(&self.chol.slice_range(..j, j + 1..)); chol.slice_range_mut(j.., ..j) - .copy_from(&self.chol.slice_range(j + 1.., ..j)); + .copy_init_from(&self.chol.slice_range(j + 1.., ..j)); chol.slice_range_mut(j.., j..) - .copy_from(&self.chol.slice_range(j + 1.., j + 1..)); + .copy_init_from(&self.chol.slice_range(j + 1.., j + 1..)); + let chol = unsafe { chol.assume_init() }; // updates the bottom right corner let mut bottom_right_corner = chol.slice_range_mut(j.., j..); @@ -332,14 +364,12 @@ where /// /// This helper method is called by `rank_one_update` but also `insert_column` and `remove_column` /// where it is used on a square slice of the decomposition - fn xx_rank_one_update( + fn xx_rank_one_update( chol: &mut Matrix, x: &mut Vector, sigma: T::RealField, ) where //T: ComplexField, - Dm: Dim, - Rx: Dim, Sm: StorageMut, Sx: StorageMut, { diff --git a/src/linalg/householder.rs b/src/linalg/householder.rs index 9314ee45..c53bc4b4 100644 --- a/src/linalg/householder.rs +++ b/src/linalg/householder.rs @@ -1,5 +1,7 @@ //! Construction of householder elementary reflections. +use std::mem::MaybeUninit; + use crate::allocator::Allocator; use crate::base::{DefaultAllocator, OMatrix, OVector, Unit, Vector}; use crate::dimension::Dim; @@ -46,7 +48,7 @@ pub fn reflection_axis_mut>( #[doc(hidden)] pub fn clear_column_unchecked( matrix: &mut OMatrix, - diag_elt: &mut T, + diag_elt: *mut T, icol: usize, shift: usize, bilateral: Option<&mut OVector>, @@ -57,7 +59,9 @@ pub fn clear_column_unchecked( let mut axis = left.rows_range_mut(icol + shift..); let (reflection_norm, not_zero) = reflection_axis_mut(&mut axis); - *diag_elt = reflection_norm; + unsafe { + *diag_elt = reflection_norm; + } if not_zero { let refl = Reflection::new(Unit::new_unchecked(axis), T::zero()); @@ -74,9 +78,9 @@ pub fn clear_column_unchecked( #[doc(hidden)] pub fn clear_row_unchecked( matrix: &mut OMatrix, - diag_elt: &mut T, - axis_packed: &mut OVector, - work: &mut OVector, + diag_elt: *mut T, + axis_packed: &mut OVector, C>, + work: &mut OVector, R>, irow: usize, shift: usize, ) where @@ -88,7 +92,7 @@ pub fn clear_row_unchecked( let (reflection_norm, not_zero) = reflection_axis_mut(&mut axis); axis.conjugate_mut(); // So that reflect_rows actually cancels the first row. - *diag_elt = reflection_norm; + unsafe{ *diag_elt = reflection_norm;} if not_zero { let refl = Reflection::new(Unit::new_unchecked(axis), T::zero());