From 498b377d0e7d31a77cecd4540ce84c4a132aee98 Mon Sep 17 00:00:00 2001 From: Cryptjar Date: Fri, 18 Jun 2021 02:23:40 +0200 Subject: [PATCH 01/25] Add `into_slice[_mut]` and impl to SliceStorage[Mut]. --- src/base/matrix_slice.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/base/matrix_slice.rs b/src/base/matrix_slice.rs index 6cb713f1..2b287f33 100644 --- a/src/base/matrix_slice.rs +++ b/src/base/matrix_slice.rs @@ -77,6 +77,21 @@ macro_rules! slice_storage_impl( $T::from_raw_parts(storage.$get_addr(start.0, start.1), shape, strides) } } + + impl <'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim> + $T<'a, T, R, C, RStride, CStride> + { + /// Extracts the original slice from this storage + pub fn into_slice(self) -> &'a [T] { + let (nrows, ncols) = self.shape(); + if nrows.value() != 0 && ncols.value() != 0 { + let sz = self.linear_index(nrows.value() - 1, ncols.value() - 1); + unsafe { slice::from_raw_parts(self.ptr, sz + 1) } + } else { + unsafe { slice::from_raw_parts(self.ptr, 0) } + } + } + } } ); @@ -108,6 +123,21 @@ impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim> Clone } } +impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim> + SliceStorageMut<'a, T, R, C, RStride, CStride> +{ + /// Extracts the original slice from this storage + pub fn into_slice_mut(self) -> &'a mut [T] { + let (nrows, ncols) = self.shape(); + if nrows.value() != 0 && ncols.value() != 0 { + let sz = self.linear_index(nrows.value() - 1, ncols.value() - 1); + unsafe { slice::from_raw_parts_mut(self.ptr, sz + 1) } + } else { + unsafe { slice::from_raw_parts_mut(self.ptr, 0) } + } + } +} + macro_rules! storage_impl( ($($T: ident),* $(,)*) => {$( unsafe impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim> Storage From 801d8a61a68d1d2ecaa0c19481ac06e84fef558d Mon Sep 17 00:00:00 2001 From: Cryptjar Date: Fri, 18 Jun 2021 02:43:05 +0200 Subject: [PATCH 02/25] Add a `From` impl to convert `DVectorSlice[mut]` back to into a slice. --- src/base/conversion.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/base/conversion.rs b/src/base/conversion.rs index 532ab8ed..94fd4a3a 100644 --- a/src/base/conversion.rs +++ b/src/base/conversion.rs @@ -452,6 +452,12 @@ impl<'a, T: Scalar + Copy> From<&'a [T]> for DVectorSlice<'a, T> { } } +impl<'a, T: Scalar> From> for &'a [T] { + fn from(vec: DVectorSlice<'a, T>) -> &'a [T] { + vec.data.into_slice() + } +} + impl<'a, T: Scalar + Copy> From<&'a mut [T]> for DVectorSliceMut<'a, T> { #[inline] fn from(slice: &'a mut [T]) -> Self { @@ -459,6 +465,12 @@ impl<'a, T: Scalar + Copy> From<&'a mut [T]> for DVectorSliceMut<'a, T> { } } +impl<'a, T: Scalar> From> for &'a mut [T] { + fn from(vec: DVectorSliceMut<'a, T>) -> &'a mut [T] { + vec.data.into_slice_mut() + } +} + impl From<[OMatrix; 2]> for OMatrix where From 1554c0114e4bfdbcae24ab6bed6e22252b9be424 Mon Sep 17 00:00:00 2001 From: Cryptjar Date: Fri, 18 Jun 2021 13:18:33 +0200 Subject: [PATCH 03/25] Fix unsoundness in `into_slice` by adding `ContiguousStorage` bound. --- src/base/matrix_slice.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/base/matrix_slice.rs b/src/base/matrix_slice.rs index 2b287f33..b275fa7f 100644 --- a/src/base/matrix_slice.rs +++ b/src/base/matrix_slice.rs @@ -80,6 +80,8 @@ macro_rules! slice_storage_impl( impl <'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim> $T<'a, T, R, C, RStride, CStride> + where + Self: ContiguousStorage { /// Extracts the original slice from this storage pub fn into_slice(self) -> &'a [T] { @@ -125,6 +127,8 @@ impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim> Clone impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim> SliceStorageMut<'a, T, R, C, RStride, CStride> +where + Self: ContiguousStorageMut, { /// Extracts the original slice from this storage pub fn into_slice_mut(self) -> &'a mut [T] { From d659747fa47d2da346e3c7110d643f2eeff65500 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Fri, 18 Jun 2021 12:53:38 -0500 Subject: [PATCH 04/25] =?UTF-8?q?`&self`=20=E2=86=92=20`self`=20on=20`Copy?= =?UTF-8?q?`=20types.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/geometry/dual_quaternion.rs | 6 +++--- src/geometry/orthographic.rs | 4 ++-- src/geometry/perspective.rs | 4 ++-- src/geometry/quaternion.rs | 6 +++--- src/geometry/rotation_specialization.rs | 2 +- src/geometry/unit_complex.rs | 4 ++-- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/geometry/dual_quaternion.rs b/src/geometry/dual_quaternion.rs index 63148836..6e1e6cb9 100644 --- a/src/geometry/dual_quaternion.rs +++ b/src/geometry/dual_quaternion.rs @@ -275,7 +275,7 @@ where } impl DualQuaternion { - fn to_vector(&self) -> OVector { + fn to_vector(self) -> OVector { (*self.as_ref()).into() } } @@ -724,7 +724,7 @@ where /// ``` #[inline] #[must_use] - pub fn to_isometry(&self) -> Isometry3 { + pub fn to_isometry(self) -> Isometry3 { Isometry3::from_parts(self.translation(), self.rotation()) } @@ -875,7 +875,7 @@ where /// ``` #[inline] #[must_use] - pub fn to_homogeneous(&self) -> Matrix4 { + pub fn to_homogeneous(self) -> Matrix4 { self.to_isometry().to_homogeneous() } } diff --git a/src/geometry/orthographic.rs b/src/geometry/orthographic.rs index 17a5b969..7a151f8c 100644 --- a/src/geometry/orthographic.rs +++ b/src/geometry/orthographic.rs @@ -222,7 +222,7 @@ impl Orthographic3 { /// ``` #[inline] #[must_use] - pub fn to_homogeneous(&self) -> Matrix4 { + pub fn to_homogeneous(self) -> Matrix4 { self.matrix } @@ -270,7 +270,7 @@ impl Orthographic3 { /// ``` #[inline] #[must_use] - pub fn to_projective(&self) -> Projective3 { + pub fn to_projective(self) -> Projective3 { Projective3::from_matrix_unchecked(self.matrix) } diff --git a/src/geometry/perspective.rs b/src/geometry/perspective.rs index 6ad9707f..ae6d97b2 100644 --- a/src/geometry/perspective.rs +++ b/src/geometry/perspective.rs @@ -124,7 +124,7 @@ impl Perspective3 { /// Computes the corresponding homogeneous matrix. #[inline] #[must_use] - pub fn to_homogeneous(&self) -> Matrix4 { + pub fn to_homogeneous(self) -> Matrix4 { self.matrix.clone_owned() } @@ -145,7 +145,7 @@ impl Perspective3 { /// This transformation seen as a `Projective3`. #[inline] #[must_use] - pub fn to_projective(&self) -> Projective3 { + pub fn to_projective(self) -> Projective3 { Projective3::from_matrix_unchecked(self.matrix) } diff --git a/src/geometry/quaternion.rs b/src/geometry/quaternion.rs index 79fda90a..8523dcfa 100755 --- a/src/geometry/quaternion.rs +++ b/src/geometry/quaternion.rs @@ -1478,7 +1478,7 @@ where /// ``` #[inline] #[must_use] - pub fn to_rotation_matrix(&self) -> Rotation { + pub fn to_rotation_matrix(self) -> Rotation { let i = self.as_ref()[0]; let j = self.as_ref()[1]; let k = self.as_ref()[2]; @@ -1513,7 +1513,7 @@ where /// The angles are produced in the form (roll, pitch, yaw). #[inline] #[deprecated(note = "This is renamed to use `.euler_angles()`.")] - pub fn to_euler_angles(&self) -> (T, T, T) + pub fn to_euler_angles(self) -> (T, T, T) where T: RealField, { @@ -1561,7 +1561,7 @@ where /// ``` #[inline] #[must_use] - pub fn to_homogeneous(&self) -> Matrix4 { + pub fn to_homogeneous(self) -> Matrix4 { self.to_rotation_matrix().to_homogeneous() } diff --git a/src/geometry/rotation_specialization.rs b/src/geometry/rotation_specialization.rs index 6c9ecf21..cca27b7a 100644 --- a/src/geometry/rotation_specialization.rs +++ b/src/geometry/rotation_specialization.rs @@ -883,7 +883,7 @@ impl Rotation3 { /// /// The angles are produced in the form (roll, pitch, yaw). #[deprecated(note = "This is renamed to use `.euler_angles()`.")] - pub fn to_euler_angles(&self) -> (T, T, T) + pub fn to_euler_angles(self) -> (T, T, T) where T: RealField, { diff --git a/src/geometry/unit_complex.rs b/src/geometry/unit_complex.rs index be0c8980..d6a7316c 100755 --- a/src/geometry/unit_complex.rs +++ b/src/geometry/unit_complex.rs @@ -261,7 +261,7 @@ where /// ``` #[inline] #[must_use] - pub fn to_rotation_matrix(&self) -> Rotation2 { + pub fn to_rotation_matrix(self) -> Rotation2 { let r = self.re; let i = self.im; @@ -282,7 +282,7 @@ where /// ``` #[inline] #[must_use] - pub fn to_homogeneous(&self) -> Matrix3 { + pub fn to_homogeneous(self) -> Matrix3 { self.to_rotation_matrix().to_homogeneous() } } From 16b8f4812d5d6cfce8d312af1fa81ffe82b1caef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crozet=20S=C3=A9bastien?= Date: Sat, 26 Jun 2021 18:39:02 +0200 Subject: [PATCH 05/25] Define OPoint, a generic point with D: DimName And define Point as an alias for OPoint. --- CHANGELOG.md | 5 + src/geometry/point.rs | 115 ++++++++++++------ src/geometry/point_alias.rs | 6 +- src/geometry/point_construction.rs | 65 ++++++----- src/geometry/point_conversion.rs | 52 +++++---- src/geometry/point_coordinates.rs | 22 ++-- src/geometry/point_ops.rs | 180 ++++++++++++++++------------- 7 files changed, 266 insertions(+), 179 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 78d5c374..23b4a82e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ documented here. This project adheres to [Semantic Versioning](https://semver.org/). +## [0.28.0] +### Modified +- The `Point::new` constructors are no longer const-fn. This is due to some limitations in const-fn + not allowing custom trait-bounds. Use the `point!` macro instead to build points in const environments. + ## [0.27.1] ### Fixed - Fixed a bug in the conversion from `glam::Vec2` or `glam::DVec2` to `Isometry2`. diff --git a/src/geometry/point.rs b/src/geometry/point.rs index d25b4d7c..dfbd2f88 100644 --- a/src/geometry/point.rs +++ b/src/geometry/point.rs @@ -17,7 +17,7 @@ use simba::simd::SimdPartialOrd; use crate::base::allocator::Allocator; use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; use crate::base::iter::{MatrixIter, MatrixIterMut}; -use crate::base::{Const, DefaultAllocator, OVector, SVector, Scalar}; +use crate::base::{Const, DefaultAllocator, OVector, Scalar}; /// A point in an euclidean space. /// @@ -40,35 +40,52 @@ use crate::base::{Const, DefaultAllocator, OVector, SVector, Scalar}; /// of said transformations for details. #[repr(C)] #[derive(Debug, Clone)] -pub struct Point { +pub struct OPoint +where + DefaultAllocator: Allocator, +{ /// The coordinates of this point, i.e., the shift from the origin. - pub coords: SVector, + pub coords: OVector, } -impl hash::Hash for Point { +impl hash::Hash for OPoint +where + DefaultAllocator: Allocator, +{ fn hash(&self, state: &mut H) { self.coords.hash(state) } } -impl Copy for Point {} - -#[cfg(feature = "bytemuck")] -unsafe impl bytemuck::Zeroable for Point where - SVector: bytemuck::Zeroable +impl Copy for OPoint +where + DefaultAllocator: Allocator, + OVector: Copy, { } #[cfg(feature = "bytemuck")] -unsafe impl bytemuck::Pod for Point +unsafe impl bytemuck::Zeroable for OPoint +where + SVector: bytemuck::Zeroable, + DefaultAllocator: Allocator, +{ +} + +#[cfg(feature = "bytemuck")] +unsafe impl bytemuck::Pod for OPoint where T: Copy, SVector: bytemuck::Pod, + DefaultAllocator: Allocator, { } #[cfg(feature = "serde-serialize-no-std")] -impl Serialize for Point { +impl Serialize for OPoint +where + DefaultAllocator: Allocator, +{ fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -78,7 +95,10 @@ impl Serialize for Point { } #[cfg(feature = "serde-serialize-no-std")] -impl<'a, T: Scalar + Deserialize<'a>, const D: usize> Deserialize<'a> for Point { +impl<'a, T: Scalar + Deserialize<'a>, D: DimName> Deserialize<'a> for OPoint +where + DefaultAllocator: Allocator, +{ fn deserialize(deserializer: Des) -> Result where Des: Deserializer<'a>, @@ -90,10 +110,11 @@ impl<'a, T: Scalar + Deserialize<'a>, const D: usize> Deserialize<'a> for Point< } #[cfg(feature = "abomonation-serialize")] -impl Abomonation for Point +impl Abomonation for OPoint where T: Scalar, SVector: Abomonation, + DefaultAllocator: Allocator, { unsafe fn entomb(&self, writer: &mut W) -> IOResult<()> { self.coords.entomb(writer) @@ -108,7 +129,10 @@ where } } -impl Point { +impl OPoint +where + DefaultAllocator: Allocator, +{ /// Returns a point containing the result of `f` applied to each of its entries. /// /// # Example @@ -123,7 +147,10 @@ impl Point { /// ``` #[inline] #[must_use] - pub fn map T2>(&self, f: F) -> Point { + pub fn map T2>(&self, f: F) -> OPoint + where + DefaultAllocator: Allocator, + { self.coords.map(f).into() } @@ -163,20 +190,21 @@ impl Point { /// ``` #[inline] #[must_use] - pub fn to_homogeneous(&self) -> OVector, U1>> + pub fn to_homogeneous(&self) -> OVector> where T: One, - Const: DimNameAdd, - DefaultAllocator: Allocator, U1>>, + D: DimNameAdd, + DefaultAllocator: Allocator>, { let mut res = unsafe { crate::unimplemented_or_uninitialized_generic!( - , U1> as DimName>::name(), + as DimName>::name(), Const::<1> ) }; - res.fixed_slice_mut::(0, 0).copy_from(&self.coords); - res[(D, 0)] = T::one(); + res.generic_slice_mut((0, 0), (D::name(), Const::<1>)) + .copy_from(&self.coords); + res[(D::dim(), 0)] = T::one(); res } @@ -184,7 +212,7 @@ impl Point { /// Creates a new point with the given coordinates. #[deprecated(note = "Use Point::from(vector) instead.")] #[inline] - pub fn from_coordinates(coords: SVector) -> Self { + pub fn from_coordinates(coords: OVector) -> Self { Self { coords } } @@ -243,8 +271,7 @@ impl Point { #[inline] pub fn iter( &self, - ) -> MatrixIter, Const<1>, >>::Buffer> - { + ) -> MatrixIter, >::Buffer> { self.coords.iter() } @@ -270,8 +297,7 @@ impl Point { #[inline] pub fn iter_mut( &mut self, - ) -> MatrixIterMut, Const<1>, >>::Buffer> - { + ) -> MatrixIterMut, >::Buffer> { self.coords.iter_mut() } @@ -289,9 +315,10 @@ impl Point { } } -impl AbsDiffEq for Point +impl AbsDiffEq for OPoint where T::Epsilon: Copy, + DefaultAllocator: Allocator, { type Epsilon = T::Epsilon; @@ -306,9 +333,10 @@ where } } -impl RelativeEq for Point +impl RelativeEq for OPoint where T::Epsilon: Copy, + DefaultAllocator: Allocator, { #[inline] fn default_max_relative() -> Self::Epsilon { @@ -327,9 +355,10 @@ where } } -impl UlpsEq for Point +impl UlpsEq for OPoint where T::Epsilon: Copy, + DefaultAllocator: Allocator, { #[inline] fn default_max_ulps() -> u32 { @@ -342,16 +371,22 @@ where } } -impl Eq for Point {} +impl Eq for OPoint where DefaultAllocator: Allocator {} -impl PartialEq for Point { +impl PartialEq for OPoint +where + DefaultAllocator: Allocator, +{ #[inline] fn eq(&self, right: &Self) -> bool { self.coords == right.coords } } -impl PartialOrd for Point { +impl PartialOrd for OPoint +where + DefaultAllocator: Allocator, +{ #[inline] fn partial_cmp(&self, other: &Self) -> Option { self.coords.partial_cmp(&other.coords) @@ -381,25 +416,28 @@ impl PartialOrd for Point { /* * inf/sup */ -impl Point { +impl OPoint +where + DefaultAllocator: Allocator, +{ /// Computes the infimum (aka. componentwise min) of two points. #[inline] #[must_use] - pub fn inf(&self, other: &Self) -> Point { + pub fn inf(&self, other: &Self) -> OPoint { self.coords.inf(&other.coords).into() } /// Computes the supremum (aka. componentwise max) of two points. #[inline] #[must_use] - pub fn sup(&self, other: &Self) -> Point { + pub fn sup(&self, other: &Self) -> OPoint { self.coords.sup(&other.coords).into() } /// Computes the (infimum, supremum) of two points. #[inline] #[must_use] - pub fn inf_sup(&self, other: &Self) -> (Point, Point) { + pub fn inf_sup(&self, other: &Self) -> (OPoint, OPoint) { let (inf, sup) = self.coords.inf_sup(&other.coords); (inf.into(), sup.into()) } @@ -410,7 +448,10 @@ impl Point { * Display * */ -impl fmt::Display for Point { +impl fmt::Display for OPoint +where + DefaultAllocator: Allocator, +{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{{")?; diff --git a/src/geometry/point_alias.rs b/src/geometry/point_alias.rs index 54441b09..f5f855c9 100644 --- a/src/geometry/point_alias.rs +++ b/src/geometry/point_alias.rs @@ -1,4 +1,8 @@ -use crate::geometry::Point; +use crate::geometry::OPoint; +use crate::Const; + +/// A point with `D` elements. +pub type Point = OPoint>; /// A statically sized 1-dimensional column point. /// diff --git a/src/geometry/point_construction.rs b/src/geometry/point_construction.rs index 7e34137c..03f24cdb 100644 --- a/src/geometry/point_construction.rs +++ b/src/geometry/point_construction.rs @@ -10,22 +10,26 @@ use rand::{ use crate::base::allocator::Allocator; use crate::base::dimension::{DimNameAdd, DimNameSum, U1}; -use crate::base::{DefaultAllocator, SVector, Scalar}; +use crate::base::{DefaultAllocator, Scalar}; use crate::{ - Const, OVector, Point1, Point2, Point3, Point4, Point5, Point6, Vector1, Vector2, Vector3, - Vector4, Vector5, Vector6, + Const, DimName, OPoint, OVector, Point1, Point2, Point3, Point4, Point5, Point6, Vector1, + Vector2, Vector3, Vector4, Vector5, Vector6, }; use simba::scalar::{ClosedDiv, SupersetOf}; use crate::geometry::Point; /// # Other construction methods -impl Point { +impl OPoint +where + DefaultAllocator: Allocator, +{ /// Creates a new point with uninitialized coordinates. #[inline] pub unsafe fn new_uninitialized() -> Self { Self::from(crate::unimplemented_or_uninitialized_generic!( - Const::, Const::<1> + D::name(), + Const::<1> )) } @@ -49,7 +53,7 @@ impl Point { where T: Zero, { - Self::from(SVector::from_element(T::zero())) + Self::from(OVector::from_element(T::zero())) } /// Creates a new point from a slice. @@ -68,7 +72,7 @@ impl Point { /// ``` #[inline] pub fn from_slice(components: &[T]) -> Self { - Self::from(SVector::from_row_slice(components)) + Self::from(OVector::from_row_slice(components)) } /// Creates a new point from its homogeneous vector representation. @@ -102,14 +106,15 @@ impl Point { /// assert_eq!(pt, Some(Point2::new(1.0, 2.0))); /// ``` #[inline] - pub fn from_homogeneous(v: OVector, U1>>) -> Option + pub fn from_homogeneous(v: OVector>) -> Option where T: Scalar + Zero + One + ClosedDiv, - Const: DimNameAdd, - DefaultAllocator: Allocator, U1>>, + D: DimNameAdd, + DefaultAllocator: Allocator>, { - if !v[D].is_zero() { - let coords = v.fixed_slice::(0, 0) / v[D].inlined_clone(); + if !v[D::dim()].is_zero() { + let coords = + v.generic_slice((0, 0), (D::name(), Const::<1>)) / v[D::dim()].inlined_clone(); Some(Self::from(coords)) } else { None @@ -125,9 +130,10 @@ impl Point { /// let pt2 = pt.cast::(); /// assert_eq!(pt2, Point2::new(1.0f32, 2.0)); /// ``` - pub fn cast(self) -> Point + pub fn cast(self) -> OPoint where - Point: SupersetOf, + OPoint: SupersetOf, + DefaultAllocator: Allocator, { crate::convert(self) } @@ -138,38 +144,43 @@ impl Point { * Traits that build points. * */ -impl Bounded for Point { +impl Bounded for OPoint +where + DefaultAllocator: Allocator, +{ #[inline] fn max_value() -> Self { - Self::from(SVector::max_value()) + Self::from(OVector::max_value()) } #[inline] fn min_value() -> Self { - Self::from(SVector::min_value()) + Self::from(OVector::min_value()) } } #[cfg(feature = "rand-no-std")] -impl Distribution> for Standard +impl Distribution> for Standard where Standard: Distribution, + DefaultAllocator: Allocator, { /// Generate a `Point` where each coordinate is an independent variate from `[0, 1)`. #[inline] - fn sample<'a, G: Rng + ?Sized>(&self, rng: &mut G) -> Point { - Point::from(rng.gen::>()) + fn sample<'a, G: Rng + ?Sized>(&self, rng: &mut G) -> OPoint { + Point::from(rng.gen::>()) } } #[cfg(feature = "arbitrary")] -impl Arbitrary for Point +impl Arbitrary for OPoint where - >>::Buffer: Send, + >::Buffer: Send, + DefaultAllocator: Allocator, { #[inline] fn arbitrary(g: &mut Gen) -> Self { - Self::from(SVector::arbitrary(g)) + Self::from(OVector::arbitrary(g)) } } @@ -181,7 +192,7 @@ where // NOTE: the impl for Point1 is not with the others so that we // can add a section with the impl block comment. /// # Construction from individual components -impl Point1 { +impl Point1 { /// Initializes this point from its components. /// /// # Example @@ -192,7 +203,7 @@ impl Point1 { /// assert_eq!(p.x, 1.0); /// ``` #[inline] - pub const fn new(x: T) -> Self { + pub fn new(x: T) -> Self { Point { coords: Vector1::new(x), } @@ -200,13 +211,13 @@ impl Point1 { } macro_rules! componentwise_constructors_impl( ($($doc: expr; $Point: ident, $Vector: ident, $($args: ident:$irow: expr),*);* $(;)*) => {$( - impl $Point { + impl $Point { #[doc = "Initializes this point from its components."] #[doc = "# Example\n```"] #[doc = $doc] #[doc = "```"] #[inline] - pub const fn new($($args: T),*) -> Self { + pub fn new($($args: T),*) -> Self { Point { coords: $Vector::new($($args),*) } } } diff --git a/src/geometry/point_conversion.rs b/src/geometry/point_conversion.rs index e5ab8272..f35a9fc6 100644 --- a/src/geometry/point_conversion.rs +++ b/src/geometry/point_conversion.rs @@ -7,6 +7,7 @@ use crate::base::dimension::{DimNameAdd, DimNameSum, U1}; use crate::base::{Const, DefaultAllocator, Matrix, OVector, Scalar}; use crate::geometry::Point; +use crate::{DimName, OPoint}; /* * This file provides the following conversions: @@ -16,67 +17,69 @@ use crate::geometry::Point; * Point -> Vector (homogeneous) */ -impl SubsetOf> for Point +impl SubsetOf> for OPoint where T1: Scalar, T2: Scalar + SupersetOf, + DefaultAllocator: Allocator + Allocator, { #[inline] - fn to_superset(&self) -> Point { - Point::from(self.coords.to_superset()) + fn to_superset(&self) -> OPoint { + OPoint::from(self.coords.to_superset()) } #[inline] - fn is_in_subset(m: &Point) -> bool { + fn is_in_subset(m: &OPoint) -> bool { // TODO: is there a way to reuse the `.is_in_subset` from the matrix implementation of // SubsetOf? m.iter().all(|e| e.is_in_subset()) } #[inline] - fn from_superset_unchecked(m: &Point) -> Self { + fn from_superset_unchecked(m: &OPoint) -> Self { Self::from(Matrix::from_superset_unchecked(&m.coords)) } } -impl SubsetOf, U1>>> for Point +impl SubsetOf>> for OPoint where - Const: DimNameAdd, + D: DimNameAdd, T1: Scalar, T2: Scalar + Zero + One + ClosedDiv + SupersetOf, - DefaultAllocator: - Allocator, U1>> + Allocator, U1>>, + DefaultAllocator: Allocator + + Allocator + + Allocator> + + Allocator>, // + Allocator // + Allocator, { #[inline] - fn to_superset(&self) -> OVector, U1>> { - let p: Point = self.to_superset(); + fn to_superset(&self) -> OVector> { + let p: OPoint = self.to_superset(); p.to_homogeneous() } #[inline] - fn is_in_subset(v: &OVector, U1>>) -> bool { - crate::is_convertible::<_, OVector, U1>>>(v) && !v[D].is_zero() + fn is_in_subset(v: &OVector>) -> bool { + crate::is_convertible::<_, OVector>>(v) && !v[D::dim()].is_zero() } #[inline] - fn from_superset_unchecked(v: &OVector, U1>>) -> Self { - let coords = v.fixed_slice::(0, 0) / v[D].inlined_clone(); + fn from_superset_unchecked(v: &OVector>) -> Self { + let coords = v.generic_slice((0, 0), (D::name(), Const::<1>)) / v[D::dim()].inlined_clone(); Self { coords: crate::convert_unchecked(coords), } } } -impl From> - for OVector, U1>> +impl From> for OVector> where - Const: DimNameAdd, - DefaultAllocator: Allocator, U1>>, + D: DimNameAdd, + DefaultAllocator: Allocator> + Allocator, { #[inline] - fn from(t: Point) -> Self { + fn from(t: OPoint) -> Self { t.to_homogeneous() } } @@ -97,10 +100,13 @@ impl From> for [T; D] { } } -impl From>> for Point { +impl From> for OPoint +where + DefaultAllocator: Allocator, +{ #[inline] - fn from(coords: OVector>) -> Self { - Point { coords } + fn from(coords: OVector) -> Self { + OPoint { coords } } } diff --git a/src/geometry/point_coordinates.rs b/src/geometry/point_coordinates.rs index 8d9e9ccc..984a2fae 100644 --- a/src/geometry/point_coordinates.rs +++ b/src/geometry/point_coordinates.rs @@ -1,9 +1,9 @@ use std::ops::{Deref, DerefMut}; use crate::base::coordinates::{X, XY, XYZ, XYZW, XYZWA, XYZWAB}; -use crate::base::Scalar; +use crate::base::{Scalar, U1, U2, U3, U4, U5, U6}; -use crate::geometry::Point; +use crate::geometry::OPoint; /* * @@ -12,8 +12,8 @@ use crate::geometry::Point; */ macro_rules! deref_impl( - ($D: expr, $Target: ident $(, $comps: ident)*) => { - impl Deref for Point + ($D: ty, $Target: ident $(, $comps: ident)*) => { + impl Deref for OPoint { type Target = $Target; @@ -23,7 +23,7 @@ macro_rules! deref_impl( } } - impl DerefMut for Point + impl DerefMut for OPoint { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { @@ -33,9 +33,9 @@ macro_rules! deref_impl( } ); -deref_impl!(1, X, x); -deref_impl!(2, XY, x, y); -deref_impl!(3, XYZ, x, y, z); -deref_impl!(4, XYZW, x, y, z, w); -deref_impl!(5, XYZWA, x, y, z, w, a); -deref_impl!(6, XYZWAB, x, y, z, w, a, b); +deref_impl!(U1, X, x); +deref_impl!(U2, XY, x, y); +deref_impl!(U3, XYZ, x, y, z); +deref_impl!(U4, XYZW, x, y, z, w); +deref_impl!(U5, XYZWA, x, y, z, w, a); +deref_impl!(U6, XYZWAB, x, y, z, w, a, b); diff --git a/src/geometry/point_ops.rs b/src/geometry/point_ops.rs index 576028cc..5b019a9d 100644 --- a/src/geometry/point_ops.rs +++ b/src/geometry/point_ops.rs @@ -8,18 +8,23 @@ use simba::scalar::{ClosedAdd, ClosedDiv, ClosedMul, ClosedNeg, ClosedSub}; use crate::base::constraint::{ AreMultipliable, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint, }; -use crate::base::dimension::{Dim, U1}; +use crate::base::dimension::{Dim, DimName, U1}; use crate::base::storage::Storage; -use crate::base::{Const, Matrix, SVector, Scalar, Vector}; +use crate::base::{Const, Matrix, OVector, Scalar, Vector}; -use crate::geometry::Point; +use crate::allocator::Allocator; +use crate::geometry::{OPoint, Point}; +use crate::DefaultAllocator; /* * * Indexing. * */ -impl Index for Point { +impl Index for OPoint +where + DefaultAllocator: Allocator, +{ type Output = T; #[inline] @@ -28,7 +33,10 @@ impl Index for Point { } } -impl IndexMut for Point { +impl IndexMut for OPoint +where + DefaultAllocator: Allocator, +{ #[inline] fn index_mut(&mut self, i: usize) -> &mut Self::Output { &mut self.coords[i] @@ -40,7 +48,10 @@ impl IndexMut for Point { * Neg. * */ -impl Neg for Point { +impl Neg for OPoint +where + DefaultAllocator: Allocator, +{ type Output = Self; #[inline] @@ -49,8 +60,11 @@ impl Neg for Point { } } -impl<'a, T: Scalar + ClosedNeg, const D: usize> Neg for &'a Point { - type Output = Point; +impl<'a, T: Scalar + ClosedNeg, D: DimName> Neg for &'a OPoint +where + DefaultAllocator: Allocator, +{ + type Output = OPoint; #[inline] fn neg(self) -> Self::Output { @@ -66,102 +80,103 @@ impl<'a, T: Scalar + ClosedNeg, const D: usize> Neg for &'a Point { // Point - Point add_sub_impl!(Sub, sub, ClosedSub; - (Const, U1), (Const, U1) -> (Const, U1) - const D; for; where; - self: &'a Point, right: &'b Point, Output = SVector; + (D, U1), (D, U1) -> (D, U1) + const; for D; where D: DimName, DefaultAllocator: Allocator; + self: &'a OPoint, right: &'b OPoint, Output = OVector; &self.coords - &right.coords; 'a, 'b); add_sub_impl!(Sub, sub, ClosedSub; - (Const, U1), (Const, U1) -> (Const, U1) - const D; for; where; - self: &'a Point, right: Point, Output = SVector; + (D, U1), (D, U1) -> (D, U1) + const; for D; where D: DimName, DefaultAllocator: Allocator; + self: &'a OPoint, right: OPoint, Output = OVector; &self.coords - right.coords; 'a); add_sub_impl!(Sub, sub, ClosedSub; - (Const, U1), (Const, U1) -> (Const, U1) - const D; for; where; - self: Point, right: &'b Point, Output = SVector; + (D, U1), (D, U1) -> (D, U1) + const; for D; where D: DimName, DefaultAllocator: Allocator; + self: OPoint, right: &'b OPoint, Output = OVector; self.coords - &right.coords; 'b); add_sub_impl!(Sub, sub, ClosedSub; - (Const, U1), (Const, U1) -> (Const, U1) - const D; for; where; - self: Point, right: Point, Output = SVector; + (D, U1), (D, U1) -> (D, U1) + const; for D; where D: DimName, DefaultAllocator: Allocator; + self: OPoint, right: OPoint, Output = OVector; self.coords - right.coords; ); // Point - Vector add_sub_impl!(Sub, sub, ClosedSub; - (Const, U1), (D2, U1) -> (Const, U1) - const D1; - for D2, SB; - where D2: Dim, SB: Storage; - self: &'a Point, right: &'b Vector, Output = Point; + (D1, U1), (D2, U1) -> (D1, U1) + const; + for D1, D2, SB; + where D1: DimName, D2: Dim, SB: Storage, DefaultAllocator: Allocator; + self: &'a OPoint, right: &'b Vector, Output = OPoint; Self::Output::from(&self.coords - right); 'a, 'b); add_sub_impl!(Sub, sub, ClosedSub; - (Const, U1), (D2, U1) -> (Const, U1) - const D1; - for D2, SB; - where D2: Dim, SB: Storage; - self: &'a Point, right: Vector, Output = Point; + (D1, U1), (D2, U1) -> (D1, U1) + const; + for D1, D2, SB; + where D1: DimName, D2: Dim, SB: Storage, DefaultAllocator: Allocator; + self: &'a OPoint, right: Vector, Output = OPoint; Self::Output::from(&self.coords - &right); 'a); // TODO: should not be a ref to `right`. add_sub_impl!(Sub, sub, ClosedSub; - (Const, U1), (D2, U1) -> (Const, U1) - const D1; - for D2, SB; - where D2: Dim, SB: Storage; - self: Point, right: &'b Vector, Output = Point; + (D1, U1), (D2, U1) -> (D1, U1) + const; + for D1, D2, SB; + where D1: DimName, D2: Dim, SB: Storage, DefaultAllocator: Allocator; + self: OPoint, right: &'b Vector, Output = OPoint; Self::Output::from(self.coords - right); 'b); add_sub_impl!(Sub, sub, ClosedSub; - (Const, U1), (D2, U1) -> (Const, U1) - const D1; - for D2, SB; - where D2: Dim, SB: Storage; - self: Point, right: Vector, Output = Point; + (D1, U1), (D2, U1) -> (D1, U1) + const; + for D1, D2, SB; + where D1: DimName, D2: Dim, SB: Storage, DefaultAllocator: Allocator; + self: OPoint, right: Vector, Output = OPoint; Self::Output::from(self.coords - right); ); // Point + Vector add_sub_impl!(Add, add, ClosedAdd; - (Const, U1), (D2, U1) -> (Const, U1) - const D1; - for D2, SB; - where D2: Dim, SB: Storage; - self: &'a Point, right: &'b Vector, Output = Point; + (D1, U1), (D2, U1) -> (D1, U1) + const; + for D1, D2, SB; + where D1: DimName, D2: Dim, SB: Storage, DefaultAllocator: Allocator; + self: &'a OPoint, right: &'b Vector, Output = OPoint; Self::Output::from(&self.coords + right); 'a, 'b); add_sub_impl!(Add, add, ClosedAdd; - (Const, U1), (D2, U1) -> (Const, U1) - const D1; - for D2, SB; - where D2: Dim, SB: Storage; - self: &'a Point, right: Vector, Output = Point; + (D1, U1), (D2, U1) -> (D1, U1) + const; + for D1, D2, SB; + where D1: DimName, D2: Dim, SB: Storage, DefaultAllocator: Allocator; + self: &'a OPoint, right: Vector, Output = OPoint; Self::Output::from(&self.coords + &right); 'a); // TODO: should not be a ref to `right`. add_sub_impl!(Add, add, ClosedAdd; - (Const, U1), (D2, U1) -> (Const, U1) - const D1; - for D2, SB; - where D2: Dim, SB: Storage; - self: Point, right: &'b Vector, Output = Point; + (D1, U1), (D2, U1) -> (D1, U1) + const; + for D1, D2, SB; + where D1: DimName, D2: Dim, SB: Storage, DefaultAllocator: Allocator; + self: OPoint, right: &'b Vector, Output = OPoint; Self::Output::from(self.coords + right); 'b); add_sub_impl!(Add, add, ClosedAdd; - (Const, U1), (D2, U1) -> (Const, U1) - const D1; - for D2, SB; - where D2: Dim, SB: Storage; - self: Point, right: Vector, Output = Point; + (D1, U1), (D2, U1) -> (D1, U1) + const; + for D1, D2, SB; + where D1: DimName, D2: Dim, SB: Storage, DefaultAllocator: Allocator; + self: OPoint, right: Vector, Output = OPoint; Self::Output::from(self.coords + right); ); // TODO: replace by the shared macro: add_sub_assign_impl? macro_rules! op_assign_impl( ($($TraitAssign: ident, $method_assign: ident, $bound: ident);* $(;)*) => {$( - impl<'b, T, D2: Dim, SB, const D1: usize> $TraitAssign<&'b Vector> for Point + impl<'b, T, D1: DimName, D2: Dim, SB> $TraitAssign<&'b Vector> for OPoint where T: Scalar + $bound, SB: Storage, - ShapeConstraint: SameNumberOfRows, D2> { + ShapeConstraint: SameNumberOfRows, + DefaultAllocator: Allocator { #[inline] fn $method_assign(&mut self, right: &'b Vector) { @@ -169,10 +184,11 @@ macro_rules! op_assign_impl( } } - impl $TraitAssign> for Point + impl $TraitAssign> for OPoint where T: Scalar + $bound, SB: Storage, - ShapeConstraint: SameNumberOfRows, D2> { + ShapeConstraint: SameNumberOfRows, + DefaultAllocator: Allocator { #[inline] fn $method_assign(&mut self, right: Vector) { @@ -214,28 +230,30 @@ md_impl_all!( macro_rules! componentwise_scalarop_impl( ($Trait: ident, $method: ident, $bound: ident; $TraitAssign: ident, $method_assign: ident) => { - impl $Trait for Point + impl $Trait for OPoint + where DefaultAllocator: Allocator { - type Output = Point; + type Output = OPoint; #[inline] fn $method(self, right: T) -> Self::Output { - Point::from(self.coords.$method(right)) + OPoint::from(self.coords.$method(right)) } } - impl<'a, T: Scalar + $bound, const D: usize> $Trait for &'a Point + impl<'a, T: Scalar + $bound, D: DimName> $Trait for &'a OPoint + where DefaultAllocator: Allocator { - type Output = Point; + type Output = OPoint; #[inline] fn $method(self, right: T) -> Self::Output { - Point::from((&self.coords).$method(right)) + OPoint::from((&self.coords).$method(right)) } } - impl $TraitAssign for Point - /* where DefaultAllocator: Allocator */ + impl $TraitAssign for OPoint + where DefaultAllocator: Allocator { #[inline] fn $method_assign(&mut self, right: T) { @@ -250,23 +268,25 @@ componentwise_scalarop_impl!(Div, div, ClosedDiv; DivAssign, div_assign); macro_rules! left_scalar_mul_impl( ($($T: ty),* $(,)*) => {$( - impl Mul> for $T + impl Mul> for $T + where DefaultAllocator: Allocator<$T, D> { - type Output = Point<$T, D>; + type Output = OPoint<$T, D>; #[inline] - fn mul(self, right: Point<$T, D>) -> Self::Output { - Point::from(self * right.coords) + fn mul(self, right: OPoint<$T, D>) -> Self::Output { + OPoint::from(self * right.coords) } } - impl<'b, const D: usize> Mul<&'b Point<$T, D>> for $T + impl<'b, D: DimName> Mul<&'b OPoint<$T, D>> for $T + where DefaultAllocator: Allocator<$T, D> { - type Output = Point<$T, D>; + type Output = OPoint<$T, D>; #[inline] - fn mul(self, right: &'b Point<$T, D>) -> Self::Output { - Point::from(self * &right.coords) + fn mul(self, right: &'b OPoint<$T, D>) -> Self::Output { + OPoint::from(self * &right.coords) } } )*} From 92c26334ec67a307fdf369270a0dc1d214408517 Mon Sep 17 00:00:00 2001 From: Andreas Longva Date: Fri, 2 Jul 2021 12:01:01 +0200 Subject: [PATCH 06/25] Fix serde impls and Distribution impl for OPoint --- src/geometry/point.rs | 4 +++- src/geometry/point_construction.rs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/geometry/point.rs b/src/geometry/point.rs index dfbd2f88..e65bc535 100644 --- a/src/geometry/point.rs +++ b/src/geometry/point.rs @@ -85,6 +85,7 @@ where impl Serialize for OPoint where DefaultAllocator: Allocator, + >::Buffer: Serialize { fn serialize(&self, serializer: S) -> Result where @@ -98,12 +99,13 @@ where impl<'a, T: Scalar + Deserialize<'a>, D: DimName> Deserialize<'a> for OPoint where DefaultAllocator: Allocator, + >::Buffer: Deserialize<'a> { fn deserialize(deserializer: Des) -> Result where Des: Deserializer<'a>, { - let coords = SVector::::deserialize(deserializer)?; + let coords = OVector::::deserialize(deserializer)?; Ok(Self::from(coords)) } diff --git a/src/geometry/point_construction.rs b/src/geometry/point_construction.rs index 03f24cdb..0ffbf4d8 100644 --- a/src/geometry/point_construction.rs +++ b/src/geometry/point_construction.rs @@ -168,7 +168,7 @@ where /// Generate a `Point` where each coordinate is an independent variate from `[0, 1)`. #[inline] fn sample<'a, G: Rng + ?Sized>(&self, rng: &mut G) -> OPoint { - Point::from(rng.gen::>()) + OPoint::from(rng.gen::>()) } } From 78da5209e9d3a6baba5816e0c58f785058b09794 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Lauzier?= Date: Sat, 3 Jul 2021 23:19:07 -0400 Subject: [PATCH 07/25] Fix some clippy warnings --- src/base/allocator.rs | 1 + src/base/array_storage.rs | 8 ++------ src/base/blas.rs | 4 ++-- src/base/cg.rs | 4 ++-- src/base/construction.rs | 9 ++++++--- src/base/construction_slice.rs | 4 ++++ src/base/edition.rs | 2 ++ src/base/matrix.rs | 4 ++-- src/base/storage.rs | 1 + src/base/unit.rs | 2 +- src/base/vec_storage.rs | 2 ++ src/geometry/isometry_construction.rs | 2 +- src/geometry/perspective.rs | 2 +- src/geometry/quaternion.rs | 2 +- src/geometry/quaternion_construction.rs | 10 +++++----- src/geometry/reflection.rs | 4 ++-- src/geometry/rotation_specialization.rs | 2 +- src/geometry/transform_ops.rs | 2 +- src/geometry/translation.rs | 2 +- src/geometry/translation_construction.rs | 2 +- src/geometry/unit_complex_construction.rs | 4 ++-- src/linalg/householder.rs | 2 +- src/sparse/cs_matrix.rs | 6 ++++-- src/sparse/cs_matrix_ops.rs | 2 +- src/sparse/cs_matrix_solve.rs | 8 ++++---- src/third_party/alga/alga_dual_quaternion.rs | 8 ++++---- src/third_party/alga/alga_matrix.rs | 6 +++--- src/third_party/alga/alga_point.rs | 2 +- src/third_party/alga/alga_quaternion.rs | 18 +++++++----------- src/third_party/alga/alga_translation.rs | 8 ++++---- src/third_party/alga/alga_unit_complex.rs | 12 ++++++------ 31 files changed, 76 insertions(+), 69 deletions(-) diff --git a/src/base/allocator.rs b/src/base/allocator.rs index 062ffbc2..64871635 100644 --- a/src/base/allocator.rs +++ b/src/base/allocator.rs @@ -40,6 +40,7 @@ pub trait Reallocator: /// Reallocates a buffer of shape `(RTo, CTo)`, possibly reusing a previously allocated buffer /// `buf`. Data stored by `buf` are linearly copied to the output: /// + /// # Safety /// * The copy is performed as if both were just arrays (without a matrix structure). /// * If `buf` is larger than the output size, then extra elements of `buf` are truncated. /// * If `buf` is smaller than the output size, then extra elements of the output are left diff --git a/src/base/array_storage.rs b/src/base/array_storage.rs index 00713fb4..611bed93 100644 --- a/src/base/array_storage.rs +++ b/src/base/array_storage.rs @@ -286,11 +286,7 @@ where unsafe fn exhume<'a, 'b>(&'a mut self, mut bytes: &'b mut [u8]) -> Option<&'b mut [u8]> { for element in self.as_mut_slice() { let temp = bytes; - bytes = if let Some(remainder) = element.exhume(temp) { - remainder - } else { - return None; - } + bytes = element.exhume(temp)? } Some(bytes) } @@ -327,7 +323,7 @@ mod rkyv_impl { for ArrayStorage { fn serialize(&self, serializer: &mut S) -> Result { - Ok(self.0.serialize(serializer)?) + self.0.serialize(serializer) } } diff --git a/src/base/blas.rs b/src/base/blas.rs index a6a188bc..b705c6c1 100644 --- a/src/base/blas.rs +++ b/src/base/blas.rs @@ -1388,12 +1388,12 @@ where { work.gemv(T::one(), mid, &rhs.column(0), T::zero()); self.column_mut(0) - .gemv_tr(alpha.inlined_clone(), &rhs, work, beta.inlined_clone()); + .gemv_tr(alpha.inlined_clone(), rhs, work, beta.inlined_clone()); for j in 1..rhs.ncols() { work.gemv(T::one(), mid, &rhs.column(j), T::zero()); self.column_mut(j) - .gemv_tr(alpha.inlined_clone(), &rhs, work, beta.inlined_clone()); + .gemv_tr(alpha.inlined_clone(), rhs, work, beta.inlined_clone()); } } diff --git a/src/base/cg.rs b/src/base/cg.rs index 2b62524b..742824c7 100644 --- a/src/base/cg.rs +++ b/src/base/cg.rs @@ -386,7 +386,7 @@ impl, DimNameDiff::::name()), ) - .tr_dot(&shift); + .tr_dot(shift); let post_translation = self.generic_slice( (0, 0), (DimNameDiff::::name(), DimNameDiff::::name()), @@ -423,7 +423,7 @@ where (D::dim() - 1, 0), (Const::<1>, DimNameDiff::::name()), ); - let n = normalizer.tr_dot(&v); + let n = normalizer.tr_dot(v); if !n.is_zero() { return transform * (v / n); diff --git a/src/base/construction.rs b/src/base/construction.rs index ac9023ec..d5ecc7c1 100644 --- a/src/base/construction.rs +++ b/src/base/construction.rs @@ -53,7 +53,10 @@ impl OMatrix where DefaultAllocator: Allocator, { - /// Creates a new uninitialized matrix. If the matrix has a compile-time dimension, this panics + /// Creates a new uninitialized matrix. + /// + /// # Safety + /// If the matrix has a compile-time dimension, this panics /// if `nrows != R::to_usize()` or `ncols != C::to_usize()`. #[inline] pub unsafe fn new_uninitialized_generic(nrows: R, ncols: C) -> mem::MaybeUninit { @@ -827,7 +830,7 @@ where Standard: Distribution, { #[inline] - fn sample<'a, G: Rng + ?Sized>(&self, rng: &'a mut G) -> OMatrix { + fn sample(&self, rng: &mut G) -> OMatrix { let nrows = R::try_to_usize().unwrap_or_else(|| rng.gen_range(0..10)); let ncols = C::try_to_usize().unwrap_or_else(|| rng.gen_range(0..10)); @@ -864,7 +867,7 @@ where { /// Generate a uniformly distributed random unit vector. #[inline] - fn sample<'a, G: Rng + ?Sized>(&self, rng: &'a mut G) -> Unit> { + fn sample(&self, rng: &mut G) -> Unit> { Unit::new_normalize(OVector::from_distribution_generic( D::name(), Const::<1>, diff --git a/src/base/construction_slice.rs b/src/base/construction_slice.rs index 43f3692b..7094bdca 100644 --- a/src/base/construction_slice.rs +++ b/src/base/construction_slice.rs @@ -10,6 +10,7 @@ impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim> { /// Creates, without bound-checking, a matrix slice from an array and with dimensions and strides specified by generic types instances. /// + /// # Safety /// This method is unsafe because the input data array is not checked to contain enough elements. /// The generic types `R`, `C`, `RStride`, `CStride` can either be type-level integers or integers wrapped with `Dynamic::new()`. #[inline] @@ -59,6 +60,7 @@ impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim> impl<'a, T: Scalar, R: Dim, C: Dim> MatrixSlice<'a, T, R, C> { /// Creates, without bound-checking, a matrix slice from an array and with dimensions specified by generic types instances. /// + /// # Safety /// This method is unsafe because the input data array is not checked to contain enough elements. /// The generic types `R` and `C` can either be type-level integers or integers wrapped with `Dynamic::new()`. #[inline] @@ -146,6 +148,7 @@ impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim> { /// Creates, without bound-checking, a mutable matrix slice from an array and with dimensions and strides specified by generic types instances. /// + /// # Safety /// This method is unsafe because the input data array is not checked to contain enough elements. /// The generic types `R`, `C`, `RStride`, `CStride` can either be type-level integers or integers wrapped with `Dynamic::new()`. #[inline] @@ -217,6 +220,7 @@ impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim> impl<'a, T: Scalar, R: Dim, C: Dim> MatrixSliceMutMN<'a, T, R, C> { /// Creates, without bound-checking, a mutable matrix slice from an array and with dimensions specified by generic types instances. /// + /// # Safety /// This method is unsafe because the input data array is not checked to contain enough elements. /// The generic types `R` and `C` can either be type-level integers or integers wrapped with `Dynamic::new()`. #[inline] diff --git a/src/base/edition.rs b/src/base/edition.rs index e7ef00d2..f403f9d3 100644 --- a/src/base/edition.rs +++ b/src/base/edition.rs @@ -587,6 +587,7 @@ impl> Matrix { /// Inserts `ninsert.value()` columns starting at the `i-th` place of this matrix. /// + /// # Safety /// The added column values are not initialized. #[inline] pub unsafe fn insert_columns_generic_uninitialized( @@ -668,6 +669,7 @@ impl> Matrix { /// Inserts `ninsert.value()` rows at the `i-th` place of this matrix. /// + /// # Safety /// The added rows values are not initialized. /// This is the generic implementation of `.insert_rows(...)` and /// `.insert_fixed_rows(...)` which have nicer API interfaces. diff --git a/src/base/matrix.rs b/src/base/matrix.rs index f2da8a8a..7e5c0ce9 100644 --- a/src/base/matrix.rs +++ b/src/base/matrix.rs @@ -336,7 +336,7 @@ mod rkyv_impl { for Matrix { fn serialize(&self, serializer: &mut _S) -> Result { - Ok(self.data.serialize(serializer)?) + self.data.serialize(serializer) } } @@ -1581,7 +1581,7 @@ impl + IsNotStaticOne, S: Storage let dim = DimSum::::from_usize(self.nrows() + 1); let mut res = OMatrix::identity_generic(dim, dim); res.generic_slice_mut::((0, 0), self.data.shape()) - .copy_from(&self); + .copy_from(self); res } } diff --git a/src/base/storage.rs b/src/base/storage.rs index 1eaa9b62..6aa6a7c8 100644 --- a/src/base/storage.rs +++ b/src/base/storage.rs @@ -95,6 +95,7 @@ pub unsafe trait Storage: Debug + Sized { /// Indicates whether this data buffer stores its elements contiguously. /// + /// # Safety /// This method is unsafe because unsafe code relies on this properties to performe /// some low-lever optimizations. unsafe fn is_contiguous(&self) -> bool; diff --git a/src/base/unit.rs b/src/base/unit.rs index 32eff82f..c107bb95 100644 --- a/src/base/unit.rs +++ b/src/base/unit.rs @@ -95,7 +95,7 @@ mod rkyv_impl { impl, S: Fallible + ?Sized> Serialize for Unit { fn serialize(&self, serializer: &mut S) -> Result { - Ok(self.value.serialize(serializer)?) + self.value.serialize(serializer) } } diff --git a/src/base/vec_storage.rs b/src/base/vec_storage.rs index c312c048..cedfd25f 100644 --- a/src/base/vec_storage.rs +++ b/src/base/vec_storage.rs @@ -102,6 +102,7 @@ impl VecStorage { /// The underlying mutable data storage. /// + /// # Safety /// This is unsafe because this may cause UB if the size of the vector is changed /// by the user. #[inline] @@ -111,6 +112,7 @@ impl VecStorage { /// Resizes the underlying mutable data storage and unwraps it. /// + /// # Safety /// If `sz` is larger than the current size, additional elements are uninitialized. /// If `sz` is smaller than the current size, additional elements are truncated. #[inline] diff --git a/src/geometry/isometry_construction.rs b/src/geometry/isometry_construction.rs index e13bde29..39a1d763 100644 --- a/src/geometry/isometry_construction.rs +++ b/src/geometry/isometry_construction.rs @@ -86,7 +86,7 @@ where Standard: Distribution + Distribution, { #[inline] - fn sample<'a, G: Rng + ?Sized>(&self, rng: &'a mut G) -> Isometry { + fn sample(&self, rng: &mut G) -> Isometry { Isometry::from_parts(rng.gen(), rng.gen()) } } diff --git a/src/geometry/perspective.rs b/src/geometry/perspective.rs index 6ad9707f..359976fe 100644 --- a/src/geometry/perspective.rs +++ b/src/geometry/perspective.rs @@ -288,7 +288,7 @@ where Standard: Distribution, { /// Generate an arbitrary random variate for testing purposes. - fn sample<'a, R: Rng + ?Sized>(&self, r: &'a mut R) -> Perspective3 { + fn sample(&self, r: &mut R) -> Perspective3 { use crate::base::helper; let znear = r.gen(); let zfar = helper::reject_rand(r, |&x: &T| !(x - znear).is_zero()); diff --git a/src/geometry/quaternion.rs b/src/geometry/quaternion.rs index 79fda90a..927a3849 100755 --- a/src/geometry/quaternion.rs +++ b/src/geometry/quaternion.rs @@ -139,7 +139,7 @@ mod rkyv_impl { impl, S: Fallible + ?Sized> Serialize for Quaternion { fn serialize(&self, serializer: &mut S) -> Result { - Ok(self.coords.serialize(serializer)?) + self.coords.serialize(serializer) } } diff --git a/src/geometry/quaternion_construction.rs b/src/geometry/quaternion_construction.rs index f110e3dd..7a681bb2 100644 --- a/src/geometry/quaternion_construction.rs +++ b/src/geometry/quaternion_construction.rs @@ -171,7 +171,7 @@ where Standard: Distribution, { #[inline] - fn sample<'a, R: Rng + ?Sized>(&self, rng: &'a mut R) -> Quaternion { + fn sample(&self, rng: &mut R) -> Quaternion { Quaternion::new(rng.gen(), rng.gen(), rng.gen(), rng.gen()) } } @@ -535,10 +535,10 @@ where SC: Storage, { // TODO: code duplication with Rotation. - let c = na.cross(&nb); + let c = na.cross(nb); if let Some(axis) = Unit::try_new(c, T::default_epsilon()) { - let cos = na.dot(&nb); + let cos = na.dot(nb); // The cosinus may be out of [-1, 1] because of inaccuracies. if cos <= -T::one() { @@ -548,7 +548,7 @@ where } else { Some(Self::from_axis_angle(&axis, cos.acos() * s)) } - } else if na.dot(&nb) < T::zero() { + } else if na.dot(nb) < T::zero() { // PI // // The rotation axis is undefined but the angle not zero. This is not a @@ -860,7 +860,7 @@ where { /// Generate a uniformly distributed random rotation quaternion. #[inline] - fn sample<'a, R: Rng + ?Sized>(&self, rng: &'a mut R) -> UnitQuaternion { + fn sample(&self, rng: &mut R) -> UnitQuaternion { // Ken Shoemake's Subgroup Algorithm // Uniform random rotations. // In D. Kirk, editor, Graphics Gems III, pages 124-132. Academic, New York, 1992. diff --git a/src/geometry/reflection.rs b/src/geometry/reflection.rs index dcc754c2..45b05725 100644 --- a/src/geometry/reflection.rs +++ b/src/geometry/reflection.rs @@ -90,7 +90,7 @@ impl> Reflection { } 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`. @@ -111,6 +111,6 @@ impl> Reflection { } 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_specialization.rs b/src/geometry/rotation_specialization.rs index 6c9ecf21..e7f79888 100644 --- a/src/geometry/rotation_specialization.rs +++ b/src/geometry/rotation_specialization.rs @@ -274,7 +274,7 @@ where { /// Generate a uniformly distributed random rotation. #[inline] - fn sample<'a, R: Rng + ?Sized>(&self, rng: &'a mut R) -> Rotation2 { + fn sample(&self, rng: &mut R) -> Rotation2 { let twopi = Uniform::new(T::zero(), T::simd_two_pi()); Rotation2::new(rng.sample(twopi)) } diff --git a/src/geometry/transform_ops.rs b/src/geometry/transform_ops.rs index efbfa67b..c4ec5cfc 100644 --- a/src/geometry/transform_ops.rs +++ b/src/geometry/transform_ops.rs @@ -124,7 +124,7 @@ md_impl_all!( if C::has_normalizer() { let normalizer = self.matrix().fixed_slice::<1, D>(D, 0); - let n = normalizer.tr_dot(&rhs); + let n = normalizer.tr_dot(rhs); if !n.is_zero() { return transform * (rhs / n); diff --git a/src/geometry/translation.rs b/src/geometry/translation.rs index 18fa7e04..c667a512 100755 --- a/src/geometry/translation.rs +++ b/src/geometry/translation.rs @@ -123,7 +123,7 @@ mod rkyv_impl { impl, S: Fallible + ?Sized, const D: usize> Serialize for Translation { fn serialize(&self, serializer: &mut S) -> Result { - Ok(self.vector.serialize(serializer)?) + self.vector.serialize(serializer) } } diff --git a/src/geometry/translation_construction.rs b/src/geometry/translation_construction.rs index c6e9d7d3..5371b648 100644 --- a/src/geometry/translation_construction.rs +++ b/src/geometry/translation_construction.rs @@ -69,7 +69,7 @@ where { /// Generate an arbitrary random variate for testing purposes. #[inline] - fn sample<'a, G: Rng + ?Sized>(&self, rng: &'a mut G) -> Translation { + fn sample(&self, rng: &mut G) -> Translation { Translation::from(rng.gen::>()) } } diff --git a/src/geometry/unit_complex_construction.rs b/src/geometry/unit_complex_construction.rs index 16e605f2..a86b2277 100644 --- a/src/geometry/unit_complex_construction.rs +++ b/src/geometry/unit_complex_construction.rs @@ -383,8 +383,8 @@ where SB: Storage, SC: Storage, { - let sang = na.perp(&nb); - let cang = na.dot(&nb); + let sang = na.perp(nb); + let cang = na.dot(nb); Self::from_angle(sang.simd_atan2(cang) * s) } diff --git a/src/linalg/householder.rs b/src/linalg/householder.rs index fbb24e77..9314ee45 100644 --- a/src/linalg/householder.rs +++ b/src/linalg/householder.rs @@ -98,7 +98,7 @@ pub fn clear_row_unchecked( reflection_norm.signum().conjugate(), ); top.columns_range_mut(irow + shift..) - .tr_copy_from(&refl.axis()); + .tr_copy_from(refl.axis()); } else { top.columns_range_mut(irow + shift..).tr_copy_from(&axis); } diff --git a/src/sparse/cs_matrix.rs b/src/sparse/cs_matrix.rs index 74e13719..3a60fb5b 100644 --- a/src/sparse/cs_matrix.rs +++ b/src/sparse/cs_matrix.rs @@ -80,10 +80,12 @@ pub trait CsStorage: for<'a> CsStorageIter<'a, T, R, C> { fn shape(&self) -> (R, C); /// Retrieve the i-th row index of the underlying row index buffer. /// + /// # Safety /// No bound-checking is performed. unsafe fn row_index_unchecked(&self, i: usize) -> usize; /// The i-th value on the contiguous value buffer of this storage. /// + /// # Safety /// No bound-checking is performed. unsafe fn get_value_unchecked(&self, i: usize) -> &T; /// The i-th value on the contiguous value buffer of this storage. @@ -155,7 +157,7 @@ where #[inline] fn column_row_indices(&'a self, j: usize) -> Self::ColumnRowIndices { let rng = self.column_range(j); - self.i[rng.clone()].iter().cloned() + self.i[rng].iter().cloned() } } @@ -489,7 +491,7 @@ where // Sort the index vector. let range = self.data.column_range(j); - self.data.i[range.clone()].sort(); + self.data.i[range.clone()].sort_unstable(); // Permute the values too. for (i, irow) in range.clone().zip(self.data.i[range].iter().cloned()) { diff --git a/src/sparse/cs_matrix_ops.rs b/src/sparse/cs_matrix_ops.rs index e9daa4ae..e03b12a5 100644 --- a/src/sparse/cs_matrix_ops.rs +++ b/src/sparse/cs_matrix_ops.rs @@ -271,7 +271,7 @@ where // Keep the output sorted. let range = res.data.p[j]..nz; - res.data.i[range.clone()].sort(); + res.data.i[range.clone()].sort_unstable(); for p in range { res.data.vals[p] = workspace[res.data.i[p]].inlined_clone() diff --git a/src/sparse/cs_matrix_solve.rs b/src/sparse/cs_matrix_solve.rs index 43c5c2c7..235fcef3 100644 --- a/src/sparse/cs_matrix_solve.rs +++ b/src/sparse/cs_matrix_solve.rs @@ -63,7 +63,7 @@ impl> CsMatrix { let mut column = self.data.column_entries(j); let mut diag_found = false; - while let Some((i, val)) = column.next() { + for (i, val) in &mut column { if i == j { if val.is_zero() { return false; @@ -109,7 +109,7 @@ impl> CsMatrix { let mut column = self.data.column_entries(j); let mut diag = None; - while let Some((i, val)) = column.next() { + for (i, val) in &mut column { if i == j { if val.is_zero() { return false; @@ -151,7 +151,7 @@ impl> CsMatrix { // We don't compute a postordered reach here because it will be sorted after anyway. self.lower_triangular_reach(b, &mut reach); // We sort the reach so the result matrix has sorted indices. - reach.sort(); + reach.sort_unstable(); let mut workspace = unsafe { crate::unimplemented_or_uninitialized_generic!(b.data.shape().0, Const::<1>) }; @@ -167,7 +167,7 @@ impl> CsMatrix { let mut column = self.data.column_entries(j); let mut diag_found = false; - while let Some((i, val)) = column.next() { + for (i, val) in &mut column { if i == j { if val.is_zero() { break; diff --git a/src/third_party/alga/alga_dual_quaternion.rs b/src/third_party/alga/alga_dual_quaternion.rs index d6a5861e..bc07cfa4 100644 --- a/src/third_party/alga/alga_dual_quaternion.rs +++ b/src/third_party/alga/alga_dual_quaternion.rs @@ -267,12 +267,12 @@ impl AffineTransformation> #[inline] fn append_translation(&self, translation: &Self::Translation) -> Self { - self * Self::from_parts(translation.clone(), UnitQuaternion::identity()) + self * Self::from_parts(*translation, UnitQuaternion::identity()) } #[inline] fn prepend_translation(&self, translation: &Self::Translation) -> Self { - Self::from_parts(translation.clone(), UnitQuaternion::identity()) * self + Self::from_parts(*translation, UnitQuaternion::identity()) * self } #[inline] @@ -287,12 +287,12 @@ impl AffineTransformation> #[inline] fn append_scaling(&self, _: &Self::NonUniformScaling) -> Self { - self.clone() + *self } #[inline] fn prepend_scaling(&self, _: &Self::NonUniformScaling) -> Self { - self.clone() + *self } } diff --git a/src/third_party/alga/alga_matrix.rs b/src/third_party/alga/alga_matrix.rs index 0ddd4fdf..e55ba49e 100644 --- a/src/third_party/alga/alga_matrix.rs +++ b/src/third_party/alga/alga_matrix.rs @@ -272,12 +272,12 @@ where match Self::dimension() { 1 => { - if vs.len() == 0 { + if vs.is_empty() { let _ = f(&Self::canonical_basis_element(0)); } } 2 => { - if vs.len() == 0 { + if vs.is_empty() { let _ = f(&Self::canonical_basis_element(0)) && f(&Self::canonical_basis_element(1)); } else if vs.len() == 1 { @@ -290,7 +290,7 @@ where // Otherwise, nothing. } 3 => { - if vs.len() == 0 { + if vs.is_empty() { let _ = f(&Self::canonical_basis_element(0)) && f(&Self::canonical_basis_element(1)) && f(&Self::canonical_basis_element(2)); diff --git a/src/third_party/alga/alga_point.rs b/src/third_party/alga/alga_point.rs index f1365af4..b1919bb6 100644 --- a/src/third_party/alga/alga_point.rs +++ b/src/third_party/alga/alga_point.rs @@ -23,7 +23,7 @@ impl EuclideanSpace for #[inline] fn coordinates(&self) -> Self::Coordinates { - self.coords.clone() + self.coords } #[inline] diff --git a/src/third_party/alga/alga_quaternion.rs b/src/third_party/alga/alga_quaternion.rs index 0885f44f..7282e0f1 100755 --- a/src/third_party/alga/alga_quaternion.rs +++ b/src/third_party/alga/alga_quaternion.rs @@ -144,11 +144,7 @@ impl NormedSpace for Quaternion { #[inline] fn try_normalize(&self, min_norm: T) -> Option { - if let Some(v) = self.coords.try_normalize(min_norm) { - Some(Self::from(v)) - } else { - None - } + self.coords.try_normalize(min_norm).map(Self::from) } #[inline] @@ -234,17 +230,17 @@ impl AffineTransformation> #[inline] fn decompose(&self) -> (Id, Self, Id, Self) { - (Id::new(), self.clone(), Id::new(), Self::identity()) + (Id::new(), *self, Id::new(), Self::identity()) } #[inline] fn append_translation(&self, _: &Self::Translation) -> Self { - self.clone() + *self } #[inline] fn prepend_translation(&self, _: &Self::Translation) -> Self { - self.clone() + *self } #[inline] @@ -259,12 +255,12 @@ impl AffineTransformation> #[inline] fn append_scaling(&self, _: &Self::NonUniformScaling) -> Self { - self.clone() + *self } #[inline] fn prepend_scaling(&self, _: &Self::NonUniformScaling) -> Self { - self.clone() + *self } } @@ -278,7 +274,7 @@ impl Similarity> for UnitQuat #[inline] fn rotation(&self) -> Self { - self.clone() + *self } #[inline] diff --git a/src/third_party/alga/alga_translation.rs b/src/third_party/alga/alga_translation.rs index bca6d13f..76a68355 100755 --- a/src/third_party/alga/alga_translation.rs +++ b/src/third_party/alga/alga_translation.rs @@ -79,7 +79,7 @@ impl Transformation) -> SVector { - v.clone() + *v } } @@ -93,7 +93,7 @@ impl ProjectiveTransfor #[inline] fn inverse_transform_vector(&self, v: &SVector) -> SVector { - v.clone() + *v } } @@ -176,7 +176,7 @@ impl AlgaTranslation SVector { - self.vector.clone() + self.vector } #[inline] @@ -186,7 +186,7 @@ impl AlgaTranslation Option { - Some(Self::from(&self.vector * n)) + Some(Self::from(self.vector * n)) } #[inline] diff --git a/src/third_party/alga/alga_unit_complex.rs b/src/third_party/alga/alga_unit_complex.rs index 44dadb42..ca55691b 100755 --- a/src/third_party/alga/alga_unit_complex.rs +++ b/src/third_party/alga/alga_unit_complex.rs @@ -90,17 +90,17 @@ impl AffineTransformation> fo #[inline] fn decompose(&self) -> (Id, Self, Id, Self) { - (Id::new(), self.clone(), Id::new(), Self::identity()) + (Id::new(), *self, Id::new(), Self::identity()) } #[inline] fn append_translation(&self, _: &Self::Translation) -> Self { - self.clone() + *self } #[inline] fn prepend_translation(&self, _: &Self::Translation) -> Self { - self.clone() + *self } #[inline] @@ -115,12 +115,12 @@ impl AffineTransformation> fo #[inline] fn append_scaling(&self, _: &Self::NonUniformScaling) -> Self { - self.clone() + *self } #[inline] fn prepend_scaling(&self, _: &Self::NonUniformScaling) -> Self { - self.clone() + *self } } @@ -134,7 +134,7 @@ impl Similarity> for UnitComp #[inline] fn rotation(&self) -> Self { - self.clone() + *self } #[inline] From e77a97e8543c782342f257004addcb0429bd7841 Mon Sep 17 00:00:00 2001 From: CAD97 Date: Sun, 4 Jul 2021 17:42:39 -0500 Subject: [PATCH 08/25] Add a couple trivial const fn conversions --- src/base/dimension.rs | 2 +- src/base/unit.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/base/dimension.rs b/src/base/dimension.rs index 2b5ccec3..8573dd59 100644 --- a/src/base/dimension.rs +++ b/src/base/dimension.rs @@ -20,7 +20,7 @@ pub struct Dynamic { impl Dynamic { /// A dynamic size equal to `value`. #[inline] - pub fn new(value: usize) -> Self { + pub const fn new(value: usize) -> Self { Self { value } } } diff --git a/src/base/unit.rs b/src/base/unit.rs index 32eff82f..8571728f 100644 --- a/src/base/unit.rs +++ b/src/base/unit.rs @@ -221,7 +221,7 @@ impl Unit { impl Unit { /// Wraps the given value, assuming it is already normalized. #[inline] - pub fn new_unchecked(value: T) -> Self { + pub const fn new_unchecked(value: T) -> Self { Unit { value } } From 3b4b661756e898f6a45e6480e5244e1ebe606974 Mon Sep 17 00:00:00 2001 From: Christopher Durham Date: Mon, 5 Jul 2021 18:36:33 -0500 Subject: [PATCH 09/25] impl Hash for Transform This just fixes the types in the existing TODO to compile. --- src/geometry/transform.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/geometry/transform.rs b/src/geometry/transform.rs index 682d2bd6..7ea91cd4 100755 --- a/src/geometry/transform.rs +++ b/src/geometry/transform.rs @@ -1,6 +1,7 @@ use approx::{AbsDiffEq, RelativeEq, UlpsEq}; use std::any::Any; use std::fmt::Debug; +use std::hash; use std::marker::PhantomData; #[cfg(feature = "serde-serialize-no-std")] @@ -166,14 +167,16 @@ where _phantom: PhantomData, } -// TODO -// impl + hash::Hash, C: TCategory> hash::Hash for Transform -// where DefaultAllocator: Allocator, U1>, DimNameSum, U1>>, -// Owned, U1>, DimNameSum, U1>>: hash::Hash { -// fn hash(&self, state: &mut H) { -// self.matrix.hash(state); -// } -// } +impl hash::Hash for Transform +where + Const: DimNameAdd, + DefaultAllocator: Allocator, U1>, DimNameSum, U1>>, + Owned, U1>, DimNameSum, U1>>: hash::Hash, +{ + fn hash(&self, state: &mut H) { + self.matrix.hash(state); + } +} impl Copy for Transform where From 1eeaf3526ca3d6cde339cbb835c2d2f291df14b2 Mon Sep 17 00:00:00 2001 From: Christopher Durham Date: Mon, 5 Jul 2021 18:53:11 -0500 Subject: [PATCH 10/25] Rotation::matrix_mut_unchecked may not cause UB ...because it isn't unsafe, so clarify the documentation to match. --- src/geometry/rotation.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/geometry/rotation.rs b/src/geometry/rotation.rs index f3127fb9..b894278b 100755 --- a/src/geometry/rotation.rs +++ b/src/geometry/rotation.rs @@ -199,9 +199,9 @@ impl Rotation { /// A mutable reference to the underlying matrix representation of this rotation. /// - /// This is suffixed by "_unchecked" because this allows the user to replace the matrix by another one that is - /// non-square, non-inversible, or non-orthonormal. If one of those properties is broken, - /// subsequent method calls may be UB. + /// This is suffixed by "_unchecked" because this allows the user to replace the + /// matrix by another one that is non-inversible or non-orthonormal. If one of + /// those properties is broken, subsequent method calls may return bogus results. #[inline] pub fn matrix_mut_unchecked(&mut self) -> &mut SMatrix { &mut self.matrix From 314b4dd1031200e580b82235c082dac7f9395702 Mon Sep 17 00:00:00 2001 From: CAD97 Date: Mon, 5 Jul 2021 19:04:10 -0500 Subject: [PATCH 11/25] Remove scalar bound from geometry type defs This was inconsistently applied, with some types having , some having , and some having . This unifies all types to match the convention of Matrix: Just declare at type def time, and apply bounds on impls only. A significant advantage of this approach is const fn construction. Const fn generics currently still can't have trait bounds, so any generic const fn needs to only move opaque types around. Construction methods such as new_unchecked or from_parts can be made const by removing their generic bounds after this PR. Actual constification is left to a follow-up PR. Note that na::Transform is _not_ loosened here, as it has more complicated definition requirements. --- src/geometry/dual_quaternion.rs | 13 +++++++++++-- src/geometry/isometry.rs | 2 +- src/geometry/orthographic.rs | 2 +- src/geometry/perspective.rs | 4 ++-- src/geometry/reflection.rs | 4 ++-- src/geometry/rotation.rs | 2 +- src/geometry/similarity.rs | 2 +- 7 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/geometry/dual_quaternion.rs b/src/geometry/dual_quaternion.rs index 63148836..17533dfb 100644 --- a/src/geometry/dual_quaternion.rs +++ b/src/geometry/dual_quaternion.rs @@ -38,14 +38,23 @@ use simba::scalar::{ClosedNeg, RealField}; /// If a feature that you need is missing, feel free to open an issue or a PR. /// See https://github.com/dimforge/nalgebra/issues/487 #[repr(C)] -#[derive(Debug, Eq, PartialEq, Copy, Clone)] -pub struct DualQuaternion { +#[derive(Debug, Copy, Clone)] +pub struct DualQuaternion { /// The real component of the quaternion pub real: Quaternion, /// The dual component of the quaternion pub dual: Quaternion, } +impl Eq for DualQuaternion {} + +impl PartialEq for DualQuaternion { + #[inline] + fn eq(&self, right: &Self) -> bool { + self.real == right.real && self.dual == right.dual + } +} + impl Default for DualQuaternion { fn default() -> Self { Self { diff --git a/src/geometry/isometry.rs b/src/geometry/isometry.rs index 7d8c6e95..4e6c15d7 100755 --- a/src/geometry/isometry.rs +++ b/src/geometry/isometry.rs @@ -68,7 +68,7 @@ use crate::geometry::{AbstractRotation, Point, Translation}; DefaultAllocator: Allocator>, Owned>: Deserialize<'de>")) )] -pub struct Isometry { +pub struct Isometry { /// The pure rotational part of this isometry. pub rotation: R, /// The pure translational part of this isometry. diff --git a/src/geometry/orthographic.rs b/src/geometry/orthographic.rs index 17a5b969..36c6ae7f 100644 --- a/src/geometry/orthographic.rs +++ b/src/geometry/orthographic.rs @@ -18,7 +18,7 @@ use crate::base::{Matrix4, Vector, Vector3}; use crate::geometry::{Point3, Projective3}; /// A 3D orthographic projection stored as a homogeneous 4x4 matrix. -pub struct Orthographic3 { +pub struct Orthographic3 { matrix: Matrix4, } diff --git a/src/geometry/perspective.rs b/src/geometry/perspective.rs index 6ad9707f..5c849a60 100644 --- a/src/geometry/perspective.rs +++ b/src/geometry/perspective.rs @@ -14,12 +14,12 @@ use simba::scalar::RealField; use crate::base::dimension::U3; use crate::base::storage::Storage; -use crate::base::{Matrix4, Scalar, Vector, Vector3}; +use crate::base::{Matrix4, Vector, Vector3}; use crate::geometry::{Point3, Projective3}; /// A 3D perspective projection stored as a homogeneous 4x4 matrix. -pub struct Perspective3 { +pub struct Perspective3 { matrix: Matrix4, } diff --git a/src/geometry/reflection.rs b/src/geometry/reflection.rs index dcc754c2..51ee4e45 100644 --- a/src/geometry/reflection.rs +++ b/src/geometry/reflection.rs @@ -1,5 +1,5 @@ use crate::base::constraint::{AreMultipliable, DimEq, SameNumberOfRows, ShapeConstraint}; -use crate::base::{Const, Matrix, Scalar, Unit, Vector}; +use crate::base::{Const, Matrix, Unit, Vector}; use crate::dimension::{Dim, U1}; use crate::storage::{Storage, StorageMut}; use simba::scalar::ComplexField; @@ -7,7 +7,7 @@ use simba::scalar::ComplexField; use crate::geometry::Point; /// A reflection wrt. a plane. -pub struct Reflection> { +pub struct Reflection { axis: Vector, bias: T, } diff --git a/src/geometry/rotation.rs b/src/geometry/rotation.rs index f3127fb9..3e74af65 100755 --- a/src/geometry/rotation.rs +++ b/src/geometry/rotation.rs @@ -55,7 +55,7 @@ use crate::geometry::Point; /// #[repr(C)] #[derive(Debug)] -pub struct Rotation { +pub struct Rotation { matrix: SMatrix, } diff --git a/src/geometry/similarity.rs b/src/geometry/similarity.rs index 48ce6a85..6ae79c81 100755 --- a/src/geometry/similarity.rs +++ b/src/geometry/similarity.rs @@ -39,7 +39,7 @@ use crate::geometry::{AbstractRotation, Isometry, Point, Translation}; DefaultAllocator: Allocator>, Owned>: Deserialize<'de>")) )] -pub struct Similarity { +pub struct Similarity { /// The part of this similarity that does not include the scaling factor. pub isometry: Isometry, scaling: T, From bbd60fbc8c0d4cc02dd8495e7968cfa6995dab27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Lauzier?= Date: Mon, 5 Jul 2021 17:51:27 -0400 Subject: [PATCH 12/25] Fix some clippy warnings and typo --- CHANGELOG.md | 38 +++++----- src/base/indexing.rs | 95 ++++++++++++------------- src/base/storage.rs | 2 + src/geometry/dual_quaternion.rs | 6 +- src/geometry/orthographic.rs | 4 +- src/geometry/perspective.rs | 4 +- src/geometry/quaternion.rs | 6 +- src/geometry/rotation_specialization.rs | 2 +- src/geometry/unit_complex.rs | 4 +- src/sparse/cs_matrix.rs | 8 +-- 10 files changed, 82 insertions(+), 87 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 78d5c374..956ba534 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,7 +38,7 @@ conversions targeting the versions 0.13, 0.14, and 0.15 of `glam`. Fix a regression introduced in 0.26.0 preventing `DVector` from being serialized with `serde`. ## [0.26.0] -This releases integrates `min-const-generics` to nalgebra. See +This release integrates `min-const-generics` to nalgebra. See [our blog post](https://www.dimforge.com/blog/2021/04/12/integrating-const-generics-to-nalgebra) for details about this release. @@ -78,7 +78,7 @@ for details about this release. ## [0.25.3] ### Added -- The `Vector::simd_cap_magnitude` method to cap the magnitude of the a vector with +- The `Vector::simd_cap_magnitude` method to cap the magnitude of the vector with SIMD components. ## [0.25.2] @@ -109,7 +109,7 @@ This updates all the dependencies of nalgebra to their latest version, including ### New crate: nalgebra-sparse Alongside this release of `nalgebra`, we are releasing `nalgebra-sparse`: a crate dedicated to sparse matrix -computation with `nalgebra`. The `sparse` module of `nalgebra`itself still exists for backward compatibility +computation with `nalgebra`. The `sparse` module of `nalgebra`itself still exists for backward compatibility, but it will be deprecated soon in favor of the `nalgebra-sparse` crate. ### Added @@ -125,12 +125,12 @@ but it will be deprecated soon in favor of the `nalgebra-sparse` crate. ## [0.24.0] ### Added -* The `DualQuaternion` type. It is still work-in-progress but the basics are here: +* The `DualQuaternion` type. It is still work-in-progress, but the basics are here: creation from its real and dual part, multiplication of two dual quaternions, and normalization. ### Removed -* There is no blanket `impl PartialEq for Unit` any more. Instead, it is +* There is no blanket `impl PartialEq for Unit` anymore. Instead, it is implemented specifically for `UnitComplex`, `UnitQuaternion` and `Unit`. ## [0.23.2] @@ -157,7 +157,7 @@ In this release we improved the documentation of the matrix and vector types by: and `Vector.apply(f)`. * The `Quaternion::from([N; 4])` conversion to build a quaternion from an array of four elements. * The `Isometry::from(Translation)` conversion to build an isometry from a translation. - * The `Vector::ith_axis(i)` which build a unit vector, e.g., `Unit>` with its i-th component set to 1.0 and the + * The `Vector::ith_axis(i)` which build a unit vector, e.g., `Unit>` with its i-th component set to 1.0, and the others set to zero. * The `Isometry.lerp_slerp` and `Isometry.try_lerp_slerp` methods to interpolate between two isometries using linear interpolation for the translational part, and spherical interpolation for the rotational part. @@ -166,7 +166,7 @@ In this release we improved the documentation of the matrix and vector types by: ## [0.22.0] In this release, we are using the new version 0.2 of simba. One major change of that version is that the -use of `libm` is now opt-in when building targetting `no-std` environment. If you are using floating-point +use of `libm` is now opt-in when building targeting `no-std` environment. If you are using floating-point operations with nalgebra in a `no-std` environment, you will need to enable the new `libm` feature of nalgebra for your code to compile again. @@ -174,7 +174,7 @@ of nalgebra for your code to compile again. * The `libm` feature that enables `libm` when building for `no-std` environment. * The `libm-force` feature that enables `libm` even when building for a not `no-std` environment. * `Cholesky::new_unchecked` which build a Cholesky decomposition without checking that its input is - positive-definite. It can be use with SIMD types. + positive-definite. It can be used with SIMD types. * The `Default` trait is now implemented for matrices, and quaternions. They are all filled with zeros, except for `UnitQuaternion` which is initialized with the identity. * Matrix exponential `matrix.exp()`. @@ -345,7 +345,7 @@ library (i.e. it supports `#![no_std]`). See the corresponding [documentation](h * Add methods `.rotation_between_axis(...)` and `.scaled_rotation_between_axis(...)` to `UnitComplex` to compute the rotation matrix between two 2D **unit** vectors. * Add methods `.axis_angle()` to `UnitComplex` and `UnitQuaternion` in order to retrieve both the - unit rotation axis and the rotation angle simultaneously. + unit rotation axis, and the rotation angle simultaneously. * Add functions to construct a random matrix with a user-defined distribution: `::from_distribution(...)`. ## [0.14.0] @@ -366,7 +366,7 @@ library (i.e. it supports `#![no_std]`). See the corresponding [documentation](h the matrix `M` such that for all vector `v` we have `M * v == self.cross(&v)`. * `.iamin()` that returns the index of the vector entry with - smallest absolute value. + the smallest absolute value. * The `mint` feature that can be enabled in order to allow conversions from and to types of the [mint](https://crates.io/crates/mint) crate. * Aliases for matrix and vector slices. Their are named by adding `Slice` @@ -404,7 +404,7 @@ This adds support for serialization using the * The alias `MatrixNM` is now deprecated. Use `MatrixMN` instead (we reordered M and N to be in alphabetical order). * In-place componentwise multiplication and division - `.component_mul_mut(...)` and `.component_div_mut(...)` have bee deprecated + `.component_mul_mut(...)` and `.component_div_mut(...)` have been deprecated for a future renaming. Use `.component_mul_assign(...)` and `.component_div_assign(...)` instead. @@ -506,7 +506,7 @@ This version is a major rewrite of the library. Major changes are: All other mathematical traits, except `Axpy` have been removed from **nalgebra**. * Methods are now preferred to free functions because they do not require any - trait to be used any more. + trait to be used anymore. * Most algebraic entities can be parametrized by type-level integers to specify their dimensions. Using `Dynamic` instead of a type-level integer indicates that the dimension known at run-time only. @@ -582,7 +582,7 @@ only: * The free functions `::prepend_rotation`, `::append_rotation`, `::append_rotation_wrt_center`, `::append_rotation_wrt_point`, `::append_transformation`, and `::append_translation ` have been removed. - Instead create the rotation or translation object explicitly and use + Instead, create the rotation or translation object explicitly and use multiplication to compose it with anything else. * The free function `::outer` has been removed. Use column-vector × @@ -608,7 +608,7 @@ Binary operations are now allowed between references as well. For example ### Modified Removed unused parameters to methods from the `ApproxEq` trait. Those were -required before rust 1.0 to help type inference. The are not needed any more +required before rust 1.0 to help type inference. They are not needed any more since it now allowed to write for a type `T` that implements `ApproxEq`: `::approx_epsilon()`. This replaces the old form: `ApproxEq::approx_epsilon(None::)`. @@ -627,7 +627,7 @@ since it now allowed to write for a type `T` that implements `ApproxEq`: `UnitQuaternion::from_axisangle`. The new `::new` method now requires a not-normalized quaternion. -Methods names starting with `new_with_` now start with `from_`. This is more +Method names starting with `new_with_` now start with `from_`. This is more idiomatic in Rust. The `Norm` trait now uses an associated type instead of a type parameter. @@ -658,8 +658,8 @@ crate for vectors, rotations and points. To enable them, activate the ## [0.8.0] ### Modified - * Almost everything (types, methods, and traits) now use full names instead - of abbreviations (e.g. `Vec3` becomes `Vector3`). Most changes are abvious. + * Almost everything (types, methods, and traits) now use fulls names instead + of abbreviations (e.g. `Vec3` becomes `Vector3`). Most changes are obvious. Note however that: - `::sqnorm` becomes `::norm_squared`. - `::sqdist` becomes `::distance_squared`. @@ -693,11 +693,11 @@ you [there](https://users.nphysics.org)! ### Removed * Removed zero-sized elements `Vector0`, `Point0`. - * Removed 4-dimensional transformations `Rotation4` and `Isometry4` (which had an implementation to incomplete to be useful). + * Removed 4-dimensional transformations `Rotation4` and `Isometry4` (which had an implementation too incomplete to be useful). ### Modified * Vectors are now multipliable with isometries. This will result into a pure rotation (this is how - vectors differ from point semantically: they design directions so they are not translatable). + vectors differ from point semantically: they design directions, so they are not translatable). * `{Isometry3, Rotation3}::look_at` reimplemented and renamed to `::look_at_rh` and `::look_at_lh` to agree with the computer graphics community (in particular, the GLM library). Use the `::look_at_rh` variant to build a view matrix that diff --git a/src/base/indexing.rs b/src/base/indexing.rs index 5bc06020..5107035c 100644 --- a/src/base/indexing.rs +++ b/src/base/indexing.rs @@ -44,7 +44,7 @@ impl DimRange for usize { #[test] fn dimrange_usize() { assert_eq!(DimRange::contained_by(&0, Const::<0>), false); - assert_eq!(DimRange::contained_by(&0, Const::<1>), true); + assert!(DimRange::contained_by(&0, Const::<1>)); } impl DimRange for ops::Range { @@ -68,24 +68,23 @@ impl DimRange for ops::Range { #[test] fn dimrange_range_usize() { - use std::usize::MAX; assert_eq!(DimRange::contained_by(&(0..0), Const::<0>), false); assert_eq!(DimRange::contained_by(&(0..1), Const::<0>), false); - assert_eq!(DimRange::contained_by(&(0..1), Const::<1>), true); + assert!(DimRange::contained_by(&(0..1), Const::<1>)); + assert!(DimRange::contained_by( + &((usize::MAX - 1)..usize::MAX), + Dynamic::new(usize::MAX) + )); assert_eq!( - DimRange::contained_by(&((MAX - 1)..MAX), Dynamic::new(MAX)), - true - ); - assert_eq!( - DimRange::length(&((MAX - 1)..MAX), Dynamic::new(MAX)), + DimRange::length(&((usize::MAX - 1)..usize::MAX), Dynamic::new(usize::MAX)), Dynamic::new(1) ); assert_eq!( - DimRange::length(&(MAX..(MAX - 1)), Dynamic::new(MAX)), + DimRange::length(&(usize::MAX..(usize::MAX - 1)), Dynamic::new(usize::MAX)), Dynamic::new(0) ); assert_eq!( - DimRange::length(&(MAX..MAX), Dynamic::new(MAX)), + DimRange::length(&(usize::MAX..usize::MAX), Dynamic::new(usize::MAX)), Dynamic::new(0) ); } @@ -111,20 +110,19 @@ impl DimRange for ops::RangeFrom { #[test] fn dimrange_rangefrom_usize() { - use std::usize::MAX; assert_eq!(DimRange::contained_by(&(0..), Const::<0>), false); assert_eq!(DimRange::contained_by(&(0..), Const::<0>), false); - assert_eq!(DimRange::contained_by(&(0..), Const::<1>), true); + assert!(DimRange::contained_by(&(0..), Const::<1>)); + assert!(DimRange::contained_by( + &((usize::MAX - 1)..), + Dynamic::new(usize::MAX) + )); assert_eq!( - DimRange::contained_by(&((MAX - 1)..), Dynamic::new(MAX)), - true - ); - assert_eq!( - DimRange::length(&((MAX - 1)..), Dynamic::new(MAX)), + DimRange::length(&((usize::MAX - 1)..), Dynamic::new(usize::MAX)), Dynamic::new(1) ); assert_eq!( - DimRange::length(&(MAX..), Dynamic::new(MAX)), + DimRange::length(&(usize::MAX..), Dynamic::new(usize::MAX)), Dynamic::new(0) ); } @@ -177,7 +175,7 @@ impl DimRange for ops::RangeFull { #[test] fn dimrange_rangefull() { - assert_eq!(DimRange::contained_by(&(..), Const::<0>), true); + assert!(DimRange::contained_by(&(..), Const::<0>)); assert_eq!(DimRange::length(&(..), Const::<1>), Const::<1>); } @@ -206,32 +204,31 @@ impl DimRange for ops::RangeInclusive { #[test] fn dimrange_rangeinclusive_usize() { - use std::usize::MAX; assert_eq!(DimRange::contained_by(&(0..=0), Const::<0>), false); - assert_eq!(DimRange::contained_by(&(0..=0), Const::<1>), true); + assert!(DimRange::contained_by(&(0..=0), Const::<1>)); assert_eq!( - DimRange::contained_by(&(MAX..=MAX), Dynamic::new(MAX)), + DimRange::contained_by(&(usize::MAX..=usize::MAX), Dynamic::new(usize::MAX)), false ); assert_eq!( - DimRange::contained_by(&((MAX - 1)..=MAX), Dynamic::new(MAX)), + DimRange::contained_by(&((usize::MAX - 1)..=usize::MAX), Dynamic::new(usize::MAX)), false ); - assert_eq!( - DimRange::contained_by(&((MAX - 1)..=(MAX - 1)), Dynamic::new(MAX)), - true - ); + assert!(DimRange::contained_by( + &((usize::MAX - 1)..=(usize::MAX - 1)), + Dynamic::new(usize::MAX) + )); assert_eq!(DimRange::length(&(0..=0), Const::<1>), Dynamic::new(1)); assert_eq!( - DimRange::length(&((MAX - 1)..=MAX), Dynamic::new(MAX)), + DimRange::length(&((usize::MAX - 1)..=usize::MAX), Dynamic::new(usize::MAX)), Dynamic::new(2) ); assert_eq!( - DimRange::length(&(MAX..=(MAX - 1)), Dynamic::new(MAX)), + DimRange::length(&(usize::MAX..=(usize::MAX - 1)), Dynamic::new(usize::MAX)), Dynamic::new(0) ); assert_eq!( - DimRange::length(&(MAX..=MAX), Dynamic::new(MAX)), + DimRange::length(&(usize::MAX..=usize::MAX), Dynamic::new(usize::MAX)), Dynamic::new(1) ); } @@ -257,21 +254,20 @@ impl DimRange for ops::RangeTo { #[test] fn dimrange_rangeto_usize() { - use std::usize::MAX; - assert_eq!(DimRange::contained_by(&(..0), Const::<0>), true); + assert!(DimRange::contained_by(&(..0), Const::<0>)); assert_eq!(DimRange::contained_by(&(..1), Const::<0>), false); - assert_eq!(DimRange::contained_by(&(..0), Const::<1>), true); + assert!(DimRange::contained_by(&(..0), Const::<1>)); + assert!(DimRange::contained_by( + &(..(usize::MAX - 1)), + Dynamic::new(usize::MAX) + )); assert_eq!( - DimRange::contained_by(&(..(MAX - 1)), Dynamic::new(MAX)), - true + DimRange::length(&(..(usize::MAX - 1)), Dynamic::new(usize::MAX)), + Dynamic::new(usize::MAX - 1) ); assert_eq!( - DimRange::length(&(..(MAX - 1)), Dynamic::new(MAX)), - Dynamic::new(MAX - 1) - ); - assert_eq!( - DimRange::length(&(..MAX), Dynamic::new(MAX)), - Dynamic::new(MAX) + DimRange::length(&(..usize::MAX), Dynamic::new(usize::MAX)), + Dynamic::new(usize::MAX) ); } @@ -296,21 +292,20 @@ impl DimRange for ops::RangeToInclusive { #[test] fn dimrange_rangetoinclusive_usize() { - use std::usize::MAX; assert_eq!(DimRange::contained_by(&(..=0), Const::<0>), false); assert_eq!(DimRange::contained_by(&(..=1), Const::<0>), false); - assert_eq!(DimRange::contained_by(&(..=0), Const::<1>), true); + assert!(DimRange::contained_by(&(..=0), Const::<1>)); assert_eq!( - DimRange::contained_by(&(..=(MAX)), Dynamic::new(MAX)), + DimRange::contained_by(&(..=(usize::MAX)), Dynamic::new(usize::MAX)), false ); + assert!(DimRange::contained_by( + &(..=(usize::MAX - 1)), + Dynamic::new(usize::MAX) + )); assert_eq!( - DimRange::contained_by(&(..=(MAX - 1)), Dynamic::new(MAX)), - true - ); - assert_eq!( - DimRange::length(&(..=(MAX - 1)), Dynamic::new(MAX)), - Dynamic::new(MAX) + DimRange::length(&(..=(usize::MAX - 1)), Dynamic::new(usize::MAX)), + Dynamic::new(usize::MAX) ); } diff --git a/src/base/storage.rs b/src/base/storage.rs index 6aa6a7c8..c5afbad7 100644 --- a/src/base/storage.rs +++ b/src/base/storage.rs @@ -102,6 +102,7 @@ pub unsafe trait Storage: Debug + Sized { /// Retrieves the data buffer as a contiguous slice. /// + /// # Safety /// The matrix components may not be stored in a contiguous way, depending on the strides. /// This method is unsafe because this can yield to invalid aliasing when called on some pairs /// of matrix slices originating from the same matrix with strides. @@ -175,6 +176,7 @@ pub unsafe trait StorageMut: Storage { /// /// Matrix components may not be contiguous, depending on its strides. /// + /// # Safety /// The matrix components may not be stored in a contiguous way, depending on the strides. /// This method is unsafe because this can yield to invalid aliasing when called on some pairs /// of matrix slices originating from the same matrix with strides. diff --git a/src/geometry/dual_quaternion.rs b/src/geometry/dual_quaternion.rs index 63148836..6e1e6cb9 100644 --- a/src/geometry/dual_quaternion.rs +++ b/src/geometry/dual_quaternion.rs @@ -275,7 +275,7 @@ where } impl DualQuaternion { - fn to_vector(&self) -> OVector { + fn to_vector(self) -> OVector { (*self.as_ref()).into() } } @@ -724,7 +724,7 @@ where /// ``` #[inline] #[must_use] - pub fn to_isometry(&self) -> Isometry3 { + pub fn to_isometry(self) -> Isometry3 { Isometry3::from_parts(self.translation(), self.rotation()) } @@ -875,7 +875,7 @@ where /// ``` #[inline] #[must_use] - pub fn to_homogeneous(&self) -> Matrix4 { + pub fn to_homogeneous(self) -> Matrix4 { self.to_isometry().to_homogeneous() } } diff --git a/src/geometry/orthographic.rs b/src/geometry/orthographic.rs index 17a5b969..7a151f8c 100644 --- a/src/geometry/orthographic.rs +++ b/src/geometry/orthographic.rs @@ -222,7 +222,7 @@ impl Orthographic3 { /// ``` #[inline] #[must_use] - pub fn to_homogeneous(&self) -> Matrix4 { + pub fn to_homogeneous(self) -> Matrix4 { self.matrix } @@ -270,7 +270,7 @@ impl Orthographic3 { /// ``` #[inline] #[must_use] - pub fn to_projective(&self) -> Projective3 { + pub fn to_projective(self) -> Projective3 { Projective3::from_matrix_unchecked(self.matrix) } diff --git a/src/geometry/perspective.rs b/src/geometry/perspective.rs index 359976fe..d2c107c0 100644 --- a/src/geometry/perspective.rs +++ b/src/geometry/perspective.rs @@ -124,7 +124,7 @@ impl Perspective3 { /// Computes the corresponding homogeneous matrix. #[inline] #[must_use] - pub fn to_homogeneous(&self) -> Matrix4 { + pub fn to_homogeneous(self) -> Matrix4 { self.matrix.clone_owned() } @@ -145,7 +145,7 @@ impl Perspective3 { /// This transformation seen as a `Projective3`. #[inline] #[must_use] - pub fn to_projective(&self) -> Projective3 { + pub fn to_projective(self) -> Projective3 { Projective3::from_matrix_unchecked(self.matrix) } diff --git a/src/geometry/quaternion.rs b/src/geometry/quaternion.rs index 927a3849..3449f1ae 100755 --- a/src/geometry/quaternion.rs +++ b/src/geometry/quaternion.rs @@ -1478,7 +1478,7 @@ where /// ``` #[inline] #[must_use] - pub fn to_rotation_matrix(&self) -> Rotation { + pub fn to_rotation_matrix(self) -> Rotation { let i = self.as_ref()[0]; let j = self.as_ref()[1]; let k = self.as_ref()[2]; @@ -1513,7 +1513,7 @@ where /// The angles are produced in the form (roll, pitch, yaw). #[inline] #[deprecated(note = "This is renamed to use `.euler_angles()`.")] - pub fn to_euler_angles(&self) -> (T, T, T) + pub fn to_euler_angles(self) -> (T, T, T) where T: RealField, { @@ -1561,7 +1561,7 @@ where /// ``` #[inline] #[must_use] - pub fn to_homogeneous(&self) -> Matrix4 { + pub fn to_homogeneous(self) -> Matrix4 { self.to_rotation_matrix().to_homogeneous() } diff --git a/src/geometry/rotation_specialization.rs b/src/geometry/rotation_specialization.rs index e7f79888..2ad73c69 100644 --- a/src/geometry/rotation_specialization.rs +++ b/src/geometry/rotation_specialization.rs @@ -883,7 +883,7 @@ impl Rotation3 { /// /// The angles are produced in the form (roll, pitch, yaw). #[deprecated(note = "This is renamed to use `.euler_angles()`.")] - pub fn to_euler_angles(&self) -> (T, T, T) + pub fn to_euler_angles(self) -> (T, T, T) where T: RealField, { diff --git a/src/geometry/unit_complex.rs b/src/geometry/unit_complex.rs index be0c8980..d6a7316c 100755 --- a/src/geometry/unit_complex.rs +++ b/src/geometry/unit_complex.rs @@ -261,7 +261,7 @@ where /// ``` #[inline] #[must_use] - pub fn to_rotation_matrix(&self) -> Rotation2 { + pub fn to_rotation_matrix(self) -> Rotation2 { let r = self.re; let i = self.im; @@ -282,7 +282,7 @@ where /// ``` #[inline] #[must_use] - pub fn to_homogeneous(&self) -> Matrix3 { + pub fn to_homogeneous(self) -> Matrix3 { self.to_rotation_matrix().to_homogeneous() } } diff --git a/src/sparse/cs_matrix.rs b/src/sparse/cs_matrix.rs index 3a60fb5b..cdacd044 100644 --- a/src/sparse/cs_matrix.rs +++ b/src/sparse/cs_matrix.rs @@ -31,11 +31,9 @@ impl<'a, T: Clone> Iterator for ColumnEntries<'a, T> { if self.curr >= self.i.len() { None } else { - let res = Some( - (unsafe { self.i.get_unchecked(self.curr).clone() }, unsafe { - self.v.get_unchecked(self.curr).clone() - }), - ); + let res = Some((unsafe { *self.i.get_unchecked(self.curr) }, unsafe { + self.v.get_unchecked(self.curr).clone() + })); self.curr += 1; res } From 6e96c28ad996a81166ca2e99014b06f591f69a6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Tue, 6 Jul 2021 21:05:25 -0500 Subject: [PATCH 13/25] Trivial doc comment improvements --- nalgebra-glm/src/lib.rs | 2 +- nalgebra-lapack/src/lib.rs | 4 ++-- nalgebra-sparse/src/convert/mod.rs | 2 +- nalgebra-sparse/src/coo.rs | 2 +- nalgebra-sparse/src/csc.rs | 4 ++-- nalgebra-sparse/src/csr.rs | 4 ++-- nalgebra-sparse/src/lib.rs | 2 +- nalgebra-sparse/src/ops/mod.rs | 4 ++-- src/base/storage.rs | 2 +- src/lib.rs | 4 ++-- src/proptest/mod.rs | 6 +++--- 11 files changed, 18 insertions(+), 18 deletions(-) diff --git a/nalgebra-glm/src/lib.rs b/nalgebra-glm/src/lib.rs index df578a80..391391f4 100644 --- a/nalgebra-glm/src/lib.rs +++ b/nalgebra-glm/src/lib.rs @@ -21,7 +21,7 @@ **nalgebra-glm** using the module prefix `glm::`. For example you will write `glm::rotate(...)` instead of the more verbose `nalgebra_glm::rotate(...)`: - ```rust + ``` extern crate nalgebra_glm as glm; ``` diff --git a/nalgebra-lapack/src/lib.rs b/nalgebra-lapack/src/lib.rs index 39965a59..9a027772 100644 --- a/nalgebra-lapack/src/lib.rs +++ b/nalgebra-lapack/src/lib.rs @@ -30,7 +30,7 @@ //! the system installation of netlib without LAPACKE (note the E) or //! CBLAS: //! -//! ```.ignore +//! ```ignore //! sudo apt-get install gfortran libblas3gf liblapack3gf //! export CARGO_FEATURE_SYSTEM_NETLIB=1 //! export CARGO_FEATURE_EXCLUDE_LAPACKE=1 @@ -44,7 +44,7 @@ //! //! On macOS, do this to use Apple's Accelerate framework: //! -//! ```.ignore +//! ```ignore //! export CARGO_FEATURES="--no-default-features --features accelerate" //! cargo build ${CARGO_FEATURES} //! ``` diff --git a/nalgebra-sparse/src/convert/mod.rs b/nalgebra-sparse/src/convert/mod.rs index 77388b22..93fa5a8b 100644 --- a/nalgebra-sparse/src/convert/mod.rs +++ b/nalgebra-sparse/src/convert/mod.rs @@ -7,7 +7,7 @@ //! The following example illustrates how to convert between matrix formats with the `From` //! implementations. //! -//! ```rust +//! ``` //! use nalgebra_sparse::{csr::CsrMatrix, csc::CscMatrix, coo::CooMatrix}; //! use nalgebra::DMatrix; //! diff --git a/nalgebra-sparse/src/coo.rs b/nalgebra-sparse/src/coo.rs index 3327ed27..679dbdb2 100644 --- a/nalgebra-sparse/src/coo.rs +++ b/nalgebra-sparse/src/coo.rs @@ -20,7 +20,7 @@ use crate::SparseFormatError; /// /// # Examples /// -/// ```rust +/// ``` /// use nalgebra_sparse::{coo::CooMatrix, csr::CsrMatrix, csc::CscMatrix}; /// /// // Initialize a matrix with all zeros (no explicitly stored entries). diff --git a/nalgebra-sparse/src/csc.rs b/nalgebra-sparse/src/csc.rs index a691e1d4..15e0746c 100644 --- a/nalgebra-sparse/src/csc.rs +++ b/nalgebra-sparse/src/csc.rs @@ -19,7 +19,7 @@ use std::slice::{Iter, IterMut}; /// /// # Usage /// -/// ```rust +/// ``` /// use nalgebra_sparse::csc::CscMatrix; /// use nalgebra::{DMatrix, Matrix3x4}; /// use matrixcompare::assert_matrix_eq; @@ -97,7 +97,7 @@ use std::slice::{Iter, IterMut}; /// represents the matrix in a column-by-column fashion. The entries associated with column `j` are /// determined as follows: /// -/// ```rust +/// ``` /// # let col_offsets: Vec = vec![0, 0]; /// # let row_indices: Vec = vec![]; /// # let values: Vec = vec![]; diff --git a/nalgebra-sparse/src/csr.rs b/nalgebra-sparse/src/csr.rs index c2f9b669..4c65908b 100644 --- a/nalgebra-sparse/src/csr.rs +++ b/nalgebra-sparse/src/csr.rs @@ -19,7 +19,7 @@ use std::slice::{Iter, IterMut}; /// /// # Usage /// -/// ```rust +/// ``` /// use nalgebra_sparse::csr::CsrMatrix; /// use nalgebra::{DMatrix, Matrix3x4}; /// use matrixcompare::assert_matrix_eq; @@ -97,7 +97,7 @@ use std::slice::{Iter, IterMut}; /// represents the matrix in a row-by-row fashion. The entries associated with row `i` are /// determined as follows: /// -/// ```rust +/// ``` /// # let row_offsets: Vec = vec![0, 0]; /// # let col_indices: Vec = vec![]; /// # let values: Vec = vec![]; diff --git a/nalgebra-sparse/src/lib.rs b/nalgebra-sparse/src/lib.rs index 80351c07..d50d8e15 100644 --- a/nalgebra-sparse/src/lib.rs +++ b/nalgebra-sparse/src/lib.rs @@ -73,7 +73,7 @@ //! //! # Example: COO -> CSR -> matrix-vector product //! -//! ```rust +//! ``` //! use nalgebra_sparse::{coo::CooMatrix, csr::CsrMatrix}; //! use nalgebra::{DMatrix, DVector}; //! use matrixcompare::assert_matrix_eq; diff --git a/nalgebra-sparse/src/ops/mod.rs b/nalgebra-sparse/src/ops/mod.rs index 50d25e63..d7e6d432 100644 --- a/nalgebra-sparse/src/ops/mod.rs +++ b/nalgebra-sparse/src/ops/mod.rs @@ -90,7 +90,7 @@ //! `C <- 3.0 * C + 2.0 * A^T * B`, where `A`, `B`, `C` are matrices and `A^T` is the transpose //! of `A`. The simplest way to write this is: //! -//! ```rust +//! ``` //! # use nalgebra_sparse::csr::CsrMatrix; //! # let a = CsrMatrix::identity(10); let b = CsrMatrix::identity(10); //! # let mut c = CsrMatrix::identity(10); @@ -109,7 +109,7 @@ //! //! An alternative way to implement this expression (here using CSR matrices) is: //! -//! ```rust +//! ``` //! # use nalgebra_sparse::csr::CsrMatrix; //! # let a = CsrMatrix::identity(10); let b = CsrMatrix::identity(10); //! # let mut c = CsrMatrix::identity(10); diff --git a/src/base/storage.rs b/src/base/storage.rs index 6aa6a7c8..5150ac38 100644 --- a/src/base/storage.rs +++ b/src/base/storage.rs @@ -58,7 +58,7 @@ pub unsafe trait Storage: Debug + Sized { /// Compute the index corresponding to the irow-th row and icol-th column of this matrix. The /// index must be such that the following holds: /// - /// ```.ignore + /// ```ignore /// let lindex = self.linear_index(irow, icol); /// assert!(*self.get_unchecked(irow, icol) == *self.get_unchecked_linear(lindex)) /// ``` diff --git a/src/lib.rs b/src/lib.rs index 04bc4002..d11c9bcc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,7 +14,7 @@ and the official package manager: [cargo](https://github.com/rust-lang/cargo). Simply add the following to your `Cargo.toml` file: -```.ignore +```ignore [dependencies] // TODO: replace the * by the latest version. nalgebra = "*" @@ -26,7 +26,7 @@ Most useful functionalities of **nalgebra** are grouped in the root module `nalg However, the recommended way to use **nalgebra** is to import types and traits explicitly, and call free-functions using the `na::` prefix: -```.rust +``` #[macro_use] extern crate approx; // For the macro relative_eq! extern crate nalgebra as na; diff --git a/src/proptest/mod.rs b/src/proptest/mod.rs index d85cd6a2..794080fe 100644 --- a/src/proptest/mod.rs +++ b/src/proptest/mod.rs @@ -27,7 +27,7 @@ //! In `proptest`, it is usually preferable to have free functions that generate *strategies*. //! Currently, the [matrix](fn.matrix.html) function fills this role. The analogous function for //! column vectors is [vector](fn.vector.html). Let's take a quick look at how it may be used: -//! ```rust +//! ``` //! use nalgebra::proptest::matrix; //! use proptest::prelude::*; //! @@ -52,7 +52,7 @@ //! number of columns to vary. One way to do this is to use `proptest` combinators in combination //! with [matrix](fn.matrix.html) as follows: //! -//! ```rust +//! ``` //! use nalgebra::{Dynamic, OMatrix, Const}; //! use nalgebra::proptest::matrix; //! use proptest::prelude::*; @@ -92,7 +92,7 @@ //! //! If you don't care about the dimensions of matrices, you can write tests like these: //! -//! ```rust +//! ``` //! use nalgebra::{DMatrix, DVector, Dynamic, Matrix3, OMatrix, Vector3, U3}; //! use proptest::prelude::*; //! From 2279da446ec4899d19e83fb2a644579a3e642364 Mon Sep 17 00:00:00 2001 From: Joshua Smith Date: Wed, 7 Jul 2021 13:26:19 -0500 Subject: [PATCH 14/25] impl Borrow and BorrowMut for fixed size matrices --- src/base/conversion.rs | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/base/conversion.rs b/src/base/conversion.rs index 99639991..f840a456 100644 --- a/src/base/conversion.rs +++ b/src/base/conversion.rs @@ -2,6 +2,7 @@ use alloc::vec::Vec; use simba::scalar::{SubsetOf, SupersetOf}; use std::convert::{AsMut, AsRef, From, Into}; +use std::borrow::{Borrow, BorrowMut}; use simba::simd::{PrimitiveSimdValue, SimdValue}; @@ -192,32 +193,47 @@ impl From> for [[T; } } -macro_rules! impl_from_into_asref_2D( - ($(($NRows: ty, $NCols: ty) => ($SZRows: expr, $SZCols: expr));* $(;)*) => {$( - impl AsRef<[[T; $SZRows]; $SZCols]> for Matrix +macro_rules! impl_from_into_asref_borrow_2D( + + //does the impls on one case for either AsRef/AsMut and Borrow/BorrowMut + ( + ($NRows: ty, $NCols: ty) => ($SZRows: expr, $SZCols: expr); + $Ref:ident.$ref:ident(), $Mut:ident.$mut:ident() + ) => { + impl $Ref<[[T; $SZRows]; $SZCols]> for Matrix where S: ContiguousStorage { #[inline] - fn as_ref(&self) -> &[[T; $SZRows]; $SZCols] { + fn $ref(&self) -> &[[T; $SZRows]; $SZCols] { unsafe { &*(self.data.ptr() as *const [[T; $SZRows]; $SZCols]) } } } - impl AsMut<[[T; $SZRows]; $SZCols]> for Matrix + impl $Mut<[[T; $SZRows]; $SZCols]> for Matrix where S: ContiguousStorageMut { #[inline] - fn as_mut(&mut self) -> &mut [[T; $SZRows]; $SZCols] { + fn $mut(&mut self) -> &mut [[T; $SZRows]; $SZCols] { unsafe { &mut *(self.data.ptr_mut() as *mut [[T; $SZRows]; $SZCols]) } } } + }; + + //collects the mappings from typenum pairs to consts + ($(($NRows: ty, $NCols: ty) => ($SZRows: expr, $SZCols: expr));* $(;)*) => {$( + impl_from_into_asref_borrow_2D!( + ($NRows, $NCols) => ($SZRows, $SZCols); AsRef.as_ref(), AsMut.as_mut() + ); + impl_from_into_asref_borrow_2D!( + ($NRows, $NCols) => ($SZRows, $SZCols); Borrow.borrow(), BorrowMut.borrow_mut() + ); )*} ); // Implement for matrices with shape 2x2 .. 6x6. -impl_from_into_asref_2D!( +impl_from_into_asref_borrow_2D!( (U2, U2) => (2, 2); (U2, U3) => (2, 3); (U2, U4) => (2, 4); (U2, U5) => (2, 5); (U2, U6) => (2, 6); (U3, U2) => (3, 2); (U3, U3) => (3, 3); (U3, U4) => (3, 4); (U3, U5) => (3, 5); (U3, U6) => (3, 6); (U4, U2) => (4, 2); (U4, U3) => (4, 3); (U4, U4) => (4, 4); (U4, U5) => (4, 5); (U4, U6) => (4, 6); From 639382ea49c855c8736cc61df3185edd5cd7b170 Mon Sep 17 00:00:00 2001 From: "nathan.eckert" Date: Thu, 8 Jul 2021 11:23:41 +0200 Subject: [PATCH 15/25] Add failing test higlighting the issue --- tests/core/matrix.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/core/matrix.rs b/tests/core/matrix.rs index 7befd351..60007846 100644 --- a/tests/core/matrix.rs +++ b/tests/core/matrix.rs @@ -1108,3 +1108,30 @@ fn partial_eq_different_types() { // assert_ne!(static_mat, typenum_static_mat); //assert_ne!(typenum_static_mat, static_mat); } + + + +fn generic_omatrix_to_string( + vector: &nalgebra::OVector, + matrix: &nalgebra::OMatrix) -> (String, String) +where + D: nalgebra::Dim, + nalgebra::DefaultAllocator: nalgebra::base::allocator::Allocator, + nalgebra::DefaultAllocator: nalgebra::base::allocator::Allocator, +{ + (vector.to_string(), matrix.to_string()) +} + +#[test] +fn omatrix_to_string() { + let dvec: nalgebra::DVector = nalgebra::dvector![1.0, 2.0]; + let dmatr: nalgebra::DMatrix = nalgebra::dmatrix![1.0, 2.0; 3.0, 4.0]; + let svec: nalgebra::SVector = nalgebra::vector![1.0, 2.0]; + let smatr: nalgebra::SMatrix = nalgebra::matrix![1.0, 2.0; 3.0, 4.0]; + assert_eq!( + generic_omatrix_to_string(&dvec, &dmatr), + (dvec.to_string(), dmatr.to_string())); + assert_eq!( + generic_omatrix_to_string(&svec, &smatr), + (svec.to_string(), smatr.to_string())); +} From 92a51662bf5bdb748d32ce46c3b18b59359e8ed3 Mon Sep 17 00:00:00 2001 From: "nathan.eckert" Date: Thu, 8 Jul 2021 14:18:22 +0200 Subject: [PATCH 16/25] Remove Allocator from display --- src/base/matrix.rs | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/src/base/matrix.rs b/src/base/matrix.rs index 7e5c0ce9..319e8eb9 100644 --- a/src/base/matrix.rs +++ b/src/base/matrix.rs @@ -1819,7 +1819,6 @@ macro_rules! impl_fmt { where T: Scalar + $trait, S: Storage, - DefaultAllocator: Allocator, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { #[cfg(feature = "std")] @@ -1837,20 +1836,17 @@ macro_rules! impl_fmt { 4 } - let (nrows, ncols) = self.data.shape(); + let (nrows, ncols) = self.shape(); - if nrows.value() == 0 || ncols.value() == 0 { + if nrows == 0 || ncols == 0 { return write!(f, "[ ]"); } let mut max_length = 0; - let mut lengths: OMatrix = Matrix::zeros_generic(nrows, ncols); - let (nrows, ncols) = self.shape(); for i in 0..nrows { for j in 0..ncols { - lengths[(i, j)] = val_width(&self[(i, j)], f); - max_length = crate::max(max_length, lengths[(i, j)]); + max_length = crate::max(max_length, val_width(&self[(i, j)], f)); } } @@ -1867,7 +1863,7 @@ macro_rules! impl_fmt { for i in 0..nrows { write!(f, " │")?; for j in 0..ncols { - let number_length = lengths[(i, j)] + 1; + let number_length = val_width(&self[(i, j)], f) + 1; let pad = max_length_with_space - number_length; write!(f, " {:>thepad$}", "", thepad = pad)?; match f.precision() { @@ -1900,19 +1896,29 @@ impl_fmt!(fmt::UpperHex, "{:X}", "{:1$X}"); impl_fmt!(fmt::Binary, "{:b}", "{:.1$b}"); impl_fmt!(fmt::Pointer, "{:p}", "{:.1$p}"); -#[test] -fn lower_exp() { - let test = crate::Matrix2::new(1e6, 2e5, 2e-5, 1.); - assert_eq!( - format!("{:e}", test), - r" +#[cfg(test)] +mod tests { + #[test] + fn empty_display() { + let vec: Vec = Vec::new(); + let dvector = crate::DVector::from_vec(vec); + assert_eq!(format!("{}", dvector), "[ ]") + } + + #[test] + fn lower_exp() { + let test = crate::Matrix2::new(1e6, 2e5, 2e-5, 1.); + assert_eq!( + format!("{:e}", test), + r" ┌ ┐ │ 1e6 2e5 │ │ 2e-5 1e0 │ └ ┘ " - ) + ) + } } /// # Cross product From dd1530adc3970c243e7215d6191251545a1b0c06 Mon Sep 17 00:00:00 2001 From: "nathan.eckert" Date: Thu, 8 Jul 2021 14:20:35 +0200 Subject: [PATCH 17/25] Cargo fmt --- tests/core/matrix.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/core/matrix.rs b/tests/core/matrix.rs index 60007846..eaa252db 100644 --- a/tests/core/matrix.rs +++ b/tests/core/matrix.rs @@ -1109,11 +1109,10 @@ fn partial_eq_different_types() { //assert_ne!(typenum_static_mat, static_mat); } - - fn generic_omatrix_to_string( vector: &nalgebra::OVector, - matrix: &nalgebra::OMatrix) -> (String, String) + matrix: &nalgebra::OMatrix, +) -> (String, String) where D: nalgebra::Dim, nalgebra::DefaultAllocator: nalgebra::base::allocator::Allocator, @@ -1130,8 +1129,10 @@ fn omatrix_to_string() { let smatr: nalgebra::SMatrix = nalgebra::matrix![1.0, 2.0; 3.0, 4.0]; assert_eq!( generic_omatrix_to_string(&dvec, &dmatr), - (dvec.to_string(), dmatr.to_string())); + (dvec.to_string(), dmatr.to_string()) + ); assert_eq!( generic_omatrix_to_string(&svec, &smatr), - (svec.to_string(), smatr.to_string())); + (svec.to_string(), smatr.to_string()) + ); } From a7fe7a5d9ac741111f10ee750701e3e696f9e8d5 Mon Sep 17 00:00:00 2001 From: Joshua Smith Date: Thu, 8 Jul 2021 11:05:32 -0500 Subject: [PATCH 18/25] fixed check-fmt error --- src/base/conversion.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base/conversion.rs b/src/base/conversion.rs index f840a456..b7e39c57 100644 --- a/src/base/conversion.rs +++ b/src/base/conversion.rs @@ -1,8 +1,8 @@ #[cfg(all(feature = "alloc", not(feature = "std")))] use alloc::vec::Vec; use simba::scalar::{SubsetOf, SupersetOf}; -use std::convert::{AsMut, AsRef, From, Into}; use std::borrow::{Borrow, BorrowMut}; +use std::convert::{AsMut, AsRef, From, Into}; use simba::simd::{PrimitiveSimdValue, SimdValue}; From 04e937792b0a51dc477eb9c93b3228e54051775e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Thu, 8 Jul 2021 11:12:43 -0500 Subject: [PATCH 19/25] Removed unnecessary `unsafe` markers --- src/base/array_storage.rs | 2 +- src/base/matrix_slice.rs | 2 +- src/base/storage.rs | 44 ++++++++++++++++++++++++++++++++------- src/base/vec_storage.rs | 4 ++-- 4 files changed, 41 insertions(+), 11 deletions(-) diff --git a/src/base/array_storage.rs b/src/base/array_storage.rs index 611bed93..643bc631 100644 --- a/src/base/array_storage.rs +++ b/src/base/array_storage.rs @@ -79,7 +79,7 @@ where } #[inline] - unsafe fn is_contiguous(&self) -> bool { + fn is_contiguous(&self) -> bool { true } diff --git a/src/base/matrix_slice.rs b/src/base/matrix_slice.rs index b275fa7f..acca9a93 100644 --- a/src/base/matrix_slice.rs +++ b/src/base/matrix_slice.rs @@ -166,7 +166,7 @@ macro_rules! storage_impl( } #[inline] - unsafe fn is_contiguous(&self) -> bool { + fn is_contiguous(&self) -> bool { // Common cases that can be deduced at compile-time even if one of the dimensions // is Dynamic. if (RStride::is::() && C::is::()) || // Column vector. diff --git a/src/base/storage.rs b/src/base/storage.rs index 956ce1f0..a750904f 100644 --- a/src/base/storage.rs +++ b/src/base/storage.rs @@ -70,24 +70,36 @@ pub unsafe trait Storage: Debug + Sized { } /// Gets the address of the i-th matrix component without performing bound-checking. + /// + /// # Safety + /// If the index is out of bounds, dereferencing the result will cause undefined behavior. #[inline] - unsafe fn get_address_unchecked_linear(&self, i: usize) -> *const T { + fn get_address_unchecked_linear(&self, i: usize) -> *const T { self.ptr().wrapping_add(i) } /// Gets the address of the i-th matrix component without performing bound-checking. + /// + /// # Safety + /// If the index is out of bounds, dereferencing the result will cause undefined behavior. #[inline] - unsafe fn get_address_unchecked(&self, irow: usize, icol: usize) -> *const T { + fn get_address_unchecked(&self, irow: usize, icol: usize) -> *const T { self.get_address_unchecked_linear(self.linear_index(irow, icol)) } /// Retrieves a reference to the i-th element without bound-checking. + /// + /// # Safety + /// If the index is out of bounds, the method will cause undefined behavior. #[inline] unsafe fn get_unchecked_linear(&self, i: usize) -> &T { &*self.get_address_unchecked_linear(i) } /// Retrieves a reference to the i-th element without bound-checking. + /// + /// # Safety + /// If the index is out of bounds, the method will cause undefined behavior. #[inline] unsafe fn get_unchecked(&self, irow: usize, icol: usize) -> &T { self.get_unchecked_linear(self.linear_index(irow, icol)) @@ -96,9 +108,9 @@ pub unsafe trait Storage: Debug + Sized { /// Indicates whether this data buffer stores its elements contiguously. /// /// # Safety - /// This method is unsafe because unsafe code relies on this properties to performe - /// some low-lever optimizations. - unsafe fn is_contiguous(&self) -> bool; + /// This function must not return `true` if the underlying storage is not contiguous, + /// or undefined behaviour will occur. + fn is_contiguous(&self) -> bool; /// Retrieves the data buffer as a contiguous slice. /// @@ -131,30 +143,45 @@ pub unsafe trait StorageMut: Storage { fn ptr_mut(&mut self) -> *mut T; /// Gets the mutable address of the i-th matrix component without performing bound-checking. + /// + /// # Safety + /// If the index is out of bounds, dereferencing the result will cause undefined behavior. #[inline] - unsafe fn get_address_unchecked_linear_mut(&mut self, i: usize) -> *mut T { + fn get_address_unchecked_linear_mut(&mut self, i: usize) -> *mut T { self.ptr_mut().wrapping_add(i) } /// Gets the mutable address of the i-th matrix component without performing bound-checking. + /// + /// # Safety + /// If the index is out of bounds, dereferencing the result will cause undefined behavior. #[inline] - unsafe fn get_address_unchecked_mut(&mut self, irow: usize, icol: usize) -> *mut T { + fn get_address_unchecked_mut(&mut self, irow: usize, icol: usize) -> *mut T { let lid = self.linear_index(irow, icol); self.get_address_unchecked_linear_mut(lid) } /// Retrieves a mutable reference to the i-th element without bound-checking. + /// + /// # Safety + /// If the index is out of bounds, the method will cause undefined behavior. unsafe fn get_unchecked_linear_mut(&mut self, i: usize) -> &mut T { &mut *self.get_address_unchecked_linear_mut(i) } /// Retrieves a mutable reference to the element at `(irow, icol)` without bound-checking. + /// + /// # Safety + /// If the index is out of bounds, the method will cause undefined behavior. #[inline] unsafe fn get_unchecked_mut(&mut self, irow: usize, icol: usize) -> &mut T { &mut *self.get_address_unchecked_mut(irow, icol) } /// Swaps two elements using their linear index without bound-checking. + /// + /// # Safety + /// If the indices are out of bounds, the method will cause undefined behavior. #[inline] unsafe fn swap_unchecked_linear(&mut self, i1: usize, i2: usize) { let a = self.get_address_unchecked_linear_mut(i1); @@ -164,6 +191,9 @@ pub unsafe trait StorageMut: Storage { } /// Swaps two elements without bound-checking. + /// + /// # Safety + /// If the indices are out of bounds, the method will cause undefined behavior. #[inline] unsafe fn swap_unchecked(&mut self, row_col1: (usize, usize), row_col2: (usize, usize)) { let lid1 = self.linear_index(row_col1.0, row_col1.1); diff --git a/src/base/vec_storage.rs b/src/base/vec_storage.rs index cedfd25f..be567094 100644 --- a/src/base/vec_storage.rs +++ b/src/base/vec_storage.rs @@ -180,7 +180,7 @@ where } #[inline] - unsafe fn is_contiguous(&self) -> bool { + fn is_contiguous(&self) -> bool { true } @@ -229,7 +229,7 @@ where } #[inline] - unsafe fn is_contiguous(&self) -> bool { + fn is_contiguous(&self) -> bool { true } From 1be8964c126fdb08c7b7d7c7c4409feaab79e43d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Thu, 8 Jul 2021 11:15:08 -0500 Subject: [PATCH 20/25] Fixed indent --- src/base/matrix_slice.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base/matrix_slice.rs b/src/base/matrix_slice.rs index acca9a93..96ebe59c 100644 --- a/src/base/matrix_slice.rs +++ b/src/base/matrix_slice.rs @@ -166,7 +166,7 @@ macro_rules! storage_impl( } #[inline] - fn is_contiguous(&self) -> bool { + fn is_contiguous(&self) -> bool { // Common cases that can be deduced at compile-time even if one of the dimensions // is Dynamic. if (RStride::is::() && C::is::()) || // Column vector. From 85d07b22a3b07951f0022871fda1b88d449fcf71 Mon Sep 17 00:00:00 2001 From: CAD97 Date: Fri, 9 Jul 2021 15:30:06 -0500 Subject: [PATCH 21/25] FIx serde impl bounds --- src/geometry/isometry.rs | 6 ++++-- src/geometry/similarity.rs | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/geometry/isometry.rs b/src/geometry/isometry.rs index 4e6c15d7..333468b3 100755 --- a/src/geometry/isometry.rs +++ b/src/geometry/isometry.rs @@ -60,13 +60,15 @@ use crate::geometry::{AbstractRotation, Point, Translation}; feature = "serde-serialize-no-std", serde(bound(serialize = "R: Serialize, DefaultAllocator: Allocator>, - Owned>: Serialize")) + Owned>: Serialize, + T: Scalar")) )] #[cfg_attr( feature = "serde-serialize-no-std", serde(bound(deserialize = "R: Deserialize<'de>, DefaultAllocator: Allocator>, - Owned>: Deserialize<'de>")) + Owned>: Deserialize<'de>, + T: Scalar")) )] pub struct Isometry { /// The pure rotational part of this isometry. diff --git a/src/geometry/similarity.rs b/src/geometry/similarity.rs index 6ae79c81..19164439 100755 --- a/src/geometry/similarity.rs +++ b/src/geometry/similarity.rs @@ -27,14 +27,14 @@ use crate::geometry::{AbstractRotation, Isometry, Point, Translation}; #[cfg_attr(feature = "serde-serialize-no-std", derive(Serialize, Deserialize))] #[cfg_attr( feature = "serde-serialize-no-std", - serde(bound(serialize = "T: Serialize, + serde(bound(serialize = "T: Scalar + Serialize, R: Serialize, DefaultAllocator: Allocator>, Owned>: Serialize")) )] #[cfg_attr( feature = "serde-serialize-no-std", - serde(bound(deserialize = "T: Deserialize<'de>, + serde(bound(deserialize = "T: Scalar + Deserialize<'de>, R: Deserialize<'de>, DefaultAllocator: Allocator>, Owned>: Deserialize<'de>")) From 2ce6811e2ca9632e07cc34a78d07958a5d1633eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crozet=20S=C3=A9bastien?= Date: Sat, 10 Jul 2021 11:24:23 +0200 Subject: [PATCH 22/25] Fix compilation when enabling the bytemuck feature. --- src/geometry/point.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/geometry/point.rs b/src/geometry/point.rs index e65bc535..d4d9dbfc 100644 --- a/src/geometry/point.rs +++ b/src/geometry/point.rs @@ -67,7 +67,7 @@ where #[cfg(feature = "bytemuck")] unsafe impl bytemuck::Zeroable for OPoint where - SVector: bytemuck::Zeroable, + OVector: bytemuck::Zeroable, DefaultAllocator: Allocator, { } @@ -76,7 +76,7 @@ where unsafe impl bytemuck::Pod for OPoint where T: Copy, - SVector: bytemuck::Pod, + OVector: bytemuck::Pod, DefaultAllocator: Allocator, { } @@ -85,7 +85,7 @@ where impl Serialize for OPoint where DefaultAllocator: Allocator, - >::Buffer: Serialize + >::Buffer: Serialize, { fn serialize(&self, serializer: S) -> Result where @@ -99,7 +99,7 @@ where impl<'a, T: Scalar + Deserialize<'a>, D: DimName> Deserialize<'a> for OPoint where DefaultAllocator: Allocator, - >::Buffer: Deserialize<'a> + >::Buffer: Deserialize<'a>, { fn deserialize(deserializer: Des) -> Result where @@ -115,7 +115,7 @@ where impl Abomonation for OPoint where T: Scalar, - SVector: Abomonation, + OVector: Abomonation, DefaultAllocator: Allocator, { unsafe fn entomb(&self, writer: &mut W) -> IOResult<()> { From 02e9ac4cad2288060586229bfcc53b268161ee29 Mon Sep 17 00:00:00 2001 From: Geordon Worley Date: Sat, 10 Jul 2021 18:32:36 -0500 Subject: [PATCH 23/25] import macros from alloc to solve issues with missing format! macro, among other issues --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index d11c9bcc..c5c4dcd8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -87,7 +87,6 @@ an optimized set of tools for computer graphics and physics. Those features incl html_root_url = "https://docs.rs/nalgebra/0.25.0" )] #![cfg_attr(not(feature = "std"), no_std)] -#![cfg_attr(all(feature = "alloc", not(feature = "std")), feature(alloc))] #![cfg_attr(feature = "no_unsound_assume_init", allow(unreachable_code))] #[cfg(feature = "rand-no-std")] @@ -102,6 +101,7 @@ extern crate approx; extern crate num_traits as num; #[cfg(all(feature = "alloc", not(feature = "std")))] +#[cfg_attr(test, macro_use)] extern crate alloc; #[cfg(not(feature = "std"))] From ca1297acfb04d22474e64cb7047a0aaa99637e7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crozet=20S=C3=A9bastien?= Date: Sun, 11 Jul 2021 17:42:45 +0200 Subject: [PATCH 24/25] Release v0.28.0 --- CHANGELOG.md | 14 ++++++++++++++ Cargo.toml | 2 +- examples/cargo/Cargo.toml | 2 +- nalgebra-glm/Cargo.toml | 4 ++-- nalgebra-lapack/Cargo.toml | 6 +++--- nalgebra-macros/Cargo.toml | 2 +- nalgebra-sparse/Cargo.toml | 6 +++--- 7 files changed, 25 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f8058703..225cd731 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,23 @@ documented here. This project adheres to [Semantic Versioning](https://semver.org/). ## [0.28.0] +### Added +- Implement `Hash` for `Transform`. + ### Modified +- The `OPoint` type has been added. It takes the dimension number as a type-level integer (e.g. `Const<3>`) instead + of a const-generic. The type `Point` is now an alias for `OPoint`. This changes doesn't affect any + of the existing code using `Point`. However, it will allow the use `OPoint` in a generic context where the dimension + cannot be easily expressed as a const-generic (because of the current limitation of const-generics in Rust). +- Several clippy warnings were fixed. This results in some method signature changes (e.g. taking `self` instead of `&self`) + but this should not have any practical infulances on existing codebase. - The `Point::new` constructors are no longer const-fn. This is due to some limitations in const-fn not allowing custom trait-bounds. Use the `point!` macro instead to build points in const environments. +- `Dynamic::new` and `Unit::new_unchecked` are now const-fn. +- Methods returning `Result<(), ()>` now return `bool` instead. + +### Fixed +- Fixed a potential unsoundess issue when converting a mutable slice to a `&mut[T]`. ## [0.27.1] ### Fixed diff --git a/Cargo.toml b/Cargo.toml index 5b25b640..8f4c7876 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nalgebra" -version = "0.27.1" +version = "0.28.0" authors = [ "Sébastien Crozet " ] description = "General-purpose linear algebra library with transformations and statically-sized or dynamically-sized matrices." diff --git a/examples/cargo/Cargo.toml b/examples/cargo/Cargo.toml index e0dd983c..9020b0ec 100644 --- a/examples/cargo/Cargo.toml +++ b/examples/cargo/Cargo.toml @@ -4,7 +4,7 @@ version = "0.0.0" authors = [ "You" ] [dependencies] -nalgebra = "0.27.0" +nalgebra = "0.28.0" [[bin]] name = "example" diff --git a/nalgebra-glm/Cargo.toml b/nalgebra-glm/Cargo.toml index f97536d0..bebacab8 100644 --- a/nalgebra-glm/Cargo.toml +++ b/nalgebra-glm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nalgebra-glm" -version = "0.13.0" +version = "0.14.0" authors = ["sebcrozet "] description = "A computer-graphics oriented API for nalgebra, inspired by the C++ GLM library." @@ -27,4 +27,4 @@ abomonation-serialize = [ "nalgebra/abomonation-serialize" ] num-traits = { version = "0.2", default-features = false } approx = { version = "0.5", default-features = false } simba = { version = "0.5", default-features = false } -nalgebra = { path = "..", version = "0.27", default-features = false } +nalgebra = { path = "..", version = "0.28", default-features = false } diff --git a/nalgebra-lapack/Cargo.toml b/nalgebra-lapack/Cargo.toml index c368a3c6..86825a37 100644 --- a/nalgebra-lapack/Cargo.toml +++ b/nalgebra-lapack/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nalgebra-lapack" -version = "0.18.0" +version = "0.19.0" authors = [ "Sébastien Crozet ", "Andrew Straw " ] description = "Matrix decompositions using nalgebra matrices and Lapack bindings." @@ -29,7 +29,7 @@ accelerate = ["lapack-src/accelerate"] intel-mkl = ["lapack-src/intel-mkl"] [dependencies] -nalgebra = { version = "0.27", path = ".." } +nalgebra = { version = "0.28", path = ".." } num-traits = "0.2" num-complex = { version = "0.4", default-features = false } simba = "0.5" @@ -39,7 +39,7 @@ lapack-src = { version = "0.8", default-features = false } # clippy = "*" [dev-dependencies] -nalgebra = { version = "0.27", features = [ "arbitrary", "rand" ], path = ".." } +nalgebra = { version = "0.28", features = [ "arbitrary", "rand" ], path = ".." } proptest = { version = "1", default-features = false, features = ["std"] } quickcheck = "1" approx = "0.5" diff --git a/nalgebra-macros/Cargo.toml b/nalgebra-macros/Cargo.toml index 59eb5ba1..490950bc 100644 --- a/nalgebra-macros/Cargo.toml +++ b/nalgebra-macros/Cargo.toml @@ -21,5 +21,5 @@ quote = "1.0" proc-macro2 = "1.0" [dev-dependencies] -nalgebra = { version = "0.27.0", path = ".." } +nalgebra = { version = "0.28.0", path = ".." } trybuild = "1.0.42" diff --git a/nalgebra-sparse/Cargo.toml b/nalgebra-sparse/Cargo.toml index 4af053c2..09b6ad73 100644 --- a/nalgebra-sparse/Cargo.toml +++ b/nalgebra-sparse/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nalgebra-sparse" -version = "0.3.0" +version = "0.4.0" authors = [ "Andreas Longva", "Sébastien Crozet " ] edition = "2018" description = "Sparse matrix computation based on nalgebra." @@ -20,7 +20,7 @@ compare = [ "matrixcompare-core" ] slow-tests = [] [dependencies] -nalgebra = { version="0.27", path = "../" } +nalgebra = { version="0.28", path = "../" } num-traits = { version = "0.2", default-features = false } proptest = { version = "1.0", optional = true } matrixcompare-core = { version = "0.1.0", optional = true } @@ -28,7 +28,7 @@ matrixcompare-core = { version = "0.1.0", optional = true } [dev-dependencies] itertools = "0.10" matrixcompare = { version = "0.3.0", features = [ "proptest-support" ] } -nalgebra = { version="0.27", path = "../", features = ["compare"] } +nalgebra = { version="0.28", path = "../", features = ["compare"] } [package.metadata.docs.rs] # Enable certain features when building docs for docs.rs From 7eb5fd3ba691380a517312b3fe48d34a1beb6e70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crozet=20S=C3=A9bastien?= Date: Sun, 11 Jul 2021 17:52:45 +0200 Subject: [PATCH 25/25] Update the changelog. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 225cd731..04ea1c34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ This project adheres to [Semantic Versioning](https://semver.org/). ## [0.28.0] ### Added - Implement `Hash` for `Transform`. +- Implement `Borrow` and `BorrowMut` for contiguous slices. ### Modified - The `OPoint` type has been added. It takes the dimension number as a type-level integer (e.g. `Const<3>`) instead