From 7acd4ecdccc9cbb4a8c412970755055c226a37f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crozet=20S=C3=A9bastien?= Date: Fri, 4 Jun 2021 10:52:28 +0200 Subject: [PATCH 01/42] Fix bug in the glam conversion Vec2 -> Isometry2 --- src/third_party/glam/common/glam_isometry.rs | 22 ++++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/third_party/glam/common/glam_isometry.rs b/src/third_party/glam/common/glam_isometry.rs index 6bd970d2..3a8d4961 100644 --- a/src/third_party/glam/common/glam_isometry.rs +++ b/src/third_party/glam/common/glam_isometry.rs @@ -1,5 +1,5 @@ use super::glam::{DMat3, DMat4, DQuat, DVec2, DVec3, Mat3, Mat4, Quat, Vec2, Vec3}; -use crate::{Isometry2, Isometry3, Matrix3, Matrix4}; +use crate::{Isometry2, Isometry3, Matrix3, Matrix4, Translation3, UnitQuaternion, Vector2}; use std::convert::TryFrom; impl From> for Mat3 { @@ -102,61 +102,61 @@ impl From<(DVec2, f64)> for Isometry2 { impl From for Isometry3 { fn from(rot: Quat) -> Self { - Isometry3::from_parts(crate::one(), rot.into()) + Isometry3::from_parts(Translation3::identity(), rot.into()) } } impl From for Isometry3 { fn from(rot: DQuat) -> Self { - Isometry3::from_parts(crate::one(), rot.into()) + Isometry3::from_parts(Translation3::identity(), rot.into()) } } impl From for Isometry2 { fn from(rot: Quat) -> Self { - Isometry2::new(crate::zero(), rot.to_axis_angle().1) + Isometry2::new(Vector2::zeros(), rot.to_axis_angle().1) } } impl From for Isometry2 { fn from(rot: DQuat) -> Self { - Isometry2::new(crate::zero(), rot.to_axis_angle().1) + Isometry2::new(Vector2::zeros(), rot.to_axis_angle().1) } } impl From for Isometry3 { fn from(tra: Vec3) -> Self { - Isometry3::from_parts(tra.into(), crate::one()) + Isometry3::from_parts(tra.into(), UnitQuaternion::identity()) } } impl From for Isometry3 { fn from(tra: DVec3) -> Self { - Isometry3::from_parts(tra.into(), crate::one()) + Isometry3::from_parts(tra.into(), UnitQuaternion::identity()) } } impl From for Isometry2 { fn from(tra: Vec2) -> Self { - Isometry2::new(tra.into(), crate::one()) + Isometry2::new(tra.into(), 0.0) } } impl From for Isometry2 { fn from(tra: DVec2) -> Self { - Isometry2::new(tra.into(), crate::one()) + Isometry2::new(tra.into(), 0.0) } } impl From for Isometry2 { fn from(tra: Vec3) -> Self { - Isometry2::new([tra.x, tra.y].into(), crate::one()) + Isometry2::new([tra.x, tra.y].into(), 0.0) } } impl From for Isometry2 { fn from(tra: DVec3) -> Self { - Isometry2::new([tra.x, tra.y].into(), crate::one()) + Isometry2::new([tra.x, tra.y].into(), 0.0) } } From d7288bfd287cc0c6b32085b54486e2520d36e58b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Crozet=20S=C3=A9bastien?= Date: Fri, 4 Jun 2021 11:08:54 +0200 Subject: [PATCH 02/42] Release v0.27.1 --- CHANGELOG.md | 4 ++++ Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2783416b..78d5c374 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ documented here. This project adheres to [Semantic Versioning](https://semver.org/). +## [0.27.1] +### Fixed +- Fixed a bug in the conversion from `glam::Vec2` or `glam::DVec2` to `Isometry2`. + ## [0.27.0] This removes the `convert-glam` and `convert-glam-unchecked` optional features. Instead, this adds the `convert-glam013`, `convert-glam014`, and `convert-glam015` optional features for diff --git a/Cargo.toml b/Cargo.toml index 5c2ad286..5b25b640 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nalgebra" -version = "0.27.0" +version = "0.27.1" authors = [ "Sébastien Crozet " ] description = "General-purpose linear algebra library with transformations and statically-sized or dynamically-sized matrices." From 925fc1edd70f619b24f3a491fce2b0fdeb8f9d30 Mon Sep 17 00:00:00 2001 From: Malte Tammena Date: Wed, 24 Mar 2021 16:28:14 +0100 Subject: [PATCH 03/42] Annotate functions with #[must_use] where appropriate --- src/base/norm.rs | 2 ++ src/lib.rs | 2 ++ src/linalg/cholesky.rs | 2 ++ src/linalg/col_piv_qr.rs | 1 + src/linalg/exp.rs | 1 + src/linalg/full_piv_lu.rs | 1 + src/linalg/givens.rs | 1 + src/linalg/lu.rs | 1 + src/linalg/qr.rs | 1 + src/linalg/solve.rs | 12 ++++++++++++ src/sparse/cs_matrix.rs | 1 + src/sparse/cs_matrix_solve.rs | 3 +++ 12 files changed, 28 insertions(+) diff --git a/src/base/norm.rs b/src/base/norm.rs index 251bf661..ab44ed02 100644 --- a/src/base/norm.rs +++ b/src/base/norm.rs @@ -340,6 +340,7 @@ impl> Matrix { } /// Returns a new vector with the same magnitude as `self` clamped between `0.0` and `max`. + #[must_use = "This function does not mutate self but returns a new clamped version."] #[inline] pub fn cap_magnitude(&self, max: T::RealField) -> OMatrix where @@ -356,6 +357,7 @@ impl> Matrix { } /// Returns a new vector with the same magnitude as `self` clamped between `0.0` and `max`. + #[must_use = "This function does not mutate self but returns a new clamped version."] #[inline] pub fn simd_cap_magnitude(&self, max: T::SimdRealField) -> OMatrix where diff --git a/src/lib.rs b/src/lib.rs index 8378b272..f0f62fe1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -184,6 +184,7 @@ pub fn zero() -> T { /// Wraps `val` into the range `[min, max]` using modular arithmetics. /// /// The range must not be empty. +#[must_use = "This function does not mutate `val`."] #[inline] pub fn wrap(mut val: T, min: T, max: T) -> T where @@ -219,6 +220,7 @@ where /// * If `min < val < max`, this returns `val`. /// * If `val <= min`, this returns `min`. /// * If `val >= max`, this returns `max`. +#[must_use = "This function does not mutate `val`."] #[inline] pub fn clamp(val: T, min: T, max: T) -> T { if val > min { diff --git a/src/linalg/cholesky.rs b/src/linalg/cholesky.rs index 24a6bcf5..eb2ebc9f 100644 --- a/src/linalg/cholesky.rs +++ b/src/linalg/cholesky.rs @@ -119,6 +119,7 @@ where /// Returns the solution of the system `self * x = b` where `self` is the decomposed matrix and /// `x` the unknown. + #[must_use = "Did you mean to use solve_mut()"] pub fn solve(&self, b: &Matrix) -> OMatrix where S2: Storage, @@ -131,6 +132,7 @@ where } /// Computes the inverse of the decomposed matrix. + #[must_use = "This function does not mutate self. Consider using the return value or dropping the function call."] pub fn inverse(&self) -> OMatrix { let shape = self.chol.data.shape(); let mut res = OMatrix::identity_generic(shape.0, shape.1); diff --git a/src/linalg/col_piv_qr.rs b/src/linalg/col_piv_qr.rs index 10997b43..3640785d 100644 --- a/src/linalg/col_piv_qr.rs +++ b/src/linalg/col_piv_qr.rs @@ -201,6 +201,7 @@ where /// Solves the linear system `self * x = b`, where `x` is the unknown to be determined. /// /// Returns `None` if `self` is not invertible. + #[must_use = "Did you mean to use solve_mut()?"] pub fn solve( &self, b: &Matrix, diff --git a/src/linalg/exp.rs b/src/linalg/exp.rs index 598c6350..b93055c5 100644 --- a/src/linalg/exp.rs +++ b/src/linalg/exp.rs @@ -435,6 +435,7 @@ where + Allocator, { /// Computes exponential of this matrix + #[must_use = "This function does not mutate self. Consider using the return value or dropping the function call."] pub fn exp(&self) -> Self { // Simple case if self.nrows() == 1 { diff --git a/src/linalg/full_piv_lu.rs b/src/linalg/full_piv_lu.rs index 1555913b..af9609de 100644 --- a/src/linalg/full_piv_lu.rs +++ b/src/linalg/full_piv_lu.rs @@ -159,6 +159,7 @@ where /// Solves the linear system `self * x = b`, where `x` is the unknown to be determined. /// /// Returns `None` if the decomposed matrix is not invertible. + #[must_use = "Did you mean to use solve_mut()?"] pub fn solve( &self, b: &Matrix, diff --git a/src/linalg/givens.rs b/src/linalg/givens.rs index 6073634e..9a65f331 100644 --- a/src/linalg/givens.rs +++ b/src/linalg/givens.rs @@ -99,6 +99,7 @@ impl GivensRotation { } /// The inverse of this givens rotation. + #[must_use = "This function does not mutate self."] pub fn inverse(&self) -> Self { Self { c: self.c, diff --git a/src/linalg/lu.rs b/src/linalg/lu.rs index fce3f3cb..855a53f7 100644 --- a/src/linalg/lu.rs +++ b/src/linalg/lu.rs @@ -213,6 +213,7 @@ where /// Solves the linear system `self * x = b`, where `x` is the unknown to be determined. /// /// Returns `None` if `self` is not invertible. + #[must_use = "Did you mean to use solve_mut()?"] pub fn solve( &self, b: &Matrix, diff --git a/src/linalg/qr.rs b/src/linalg/qr.rs index 6d5274e4..103916a0 100644 --- a/src/linalg/qr.rs +++ b/src/linalg/qr.rs @@ -164,6 +164,7 @@ where /// Solves the linear system `self * x = b`, where `x` is the unknown to be determined. /// /// Returns `None` if `self` is not invertible. + #[must_use = "Did you mean to use solve_mut()"] pub fn solve( &self, b: &Matrix, diff --git a/src/linalg/solve.rs b/src/linalg/solve.rs index 8fdab47e..7f9b7dae 100644 --- a/src/linalg/solve.rs +++ b/src/linalg/solve.rs @@ -10,6 +10,7 @@ use crate::base::{DVectorSlice, DefaultAllocator, Matrix, OMatrix, SquareMatrix, impl> SquareMatrix { /// Computes the solution of the linear system `self . x = b` where `x` is the unknown and only /// the lower-triangular part of `self` (including the diagonal) is considered not-zero. + #[must_use = "Did you mean to use solve_lower_triangular_mut()?"] #[inline] pub fn solve_lower_triangular( &self, @@ -30,6 +31,7 @@ impl> SquareMatrix { /// Computes the solution of the linear system `self . x = b` where `x` is the unknown and only /// the upper-triangular part of `self` (including the diagonal) is considered not-zero. + #[must_use = "Did you mean to use solve_upper_triangular_mut()?"] #[inline] pub fn solve_upper_triangular( &self, @@ -186,6 +188,7 @@ impl> SquareMatrix { */ /// Computes the solution of the linear system `self.transpose() . x = b` where `x` is the unknown and only /// the lower-triangular part of `self` (including the diagonal) is considered not-zero. + #[must_use = "Did you mean to use tr_solve_lower_triangular_mut()?"] #[inline] pub fn tr_solve_lower_triangular( &self, @@ -206,6 +209,7 @@ impl> SquareMatrix { /// Computes the solution of the linear system `self.transpose() . x = b` where `x` is the unknown and only /// the upper-triangular part of `self` (including the diagonal) is considered not-zero. + #[must_use = "Did you mean to use tr_solve_upper_triangular_mut()?"] #[inline] pub fn tr_solve_upper_triangular( &self, @@ -276,6 +280,7 @@ impl> SquareMatrix { /// Computes the solution of the linear system `self.adjoint() . x = b` where `x` is the unknown and only /// the lower-triangular part of `self` (including the diagonal) is considered not-zero. + #[must_use = "Did you mean to use ad_solve_lower_triangular_mut()?"] #[inline] pub fn ad_solve_lower_triangular( &self, @@ -296,6 +301,7 @@ impl> SquareMatrix { /// Computes the solution of the linear system `self.adjoint() . x = b` where `x` is the unknown and only /// the upper-triangular part of `self` (including the diagonal) is considered not-zero. + #[must_use = "Did you mean to use ad_solve_upper_triangular_mut()?"] #[inline] pub fn ad_solve_upper_triangular( &self, @@ -443,6 +449,7 @@ impl> SquareMatrix { impl> SquareMatrix { /// Computes the solution of the linear system `self . x = b` where `x` is the unknown and only /// the lower-triangular part of `self` (including the diagonal) is considered not-zero. + #[must_use = "Did you mean to use solve_lower_triangular_unchecked_mut()?"] #[inline] pub fn solve_lower_triangular_unchecked( &self, @@ -460,6 +467,7 @@ impl> SquareMatrix { /// Computes the solution of the linear system `self . x = b` where `x` is the unknown and only /// the upper-triangular part of `self` (including the diagonal) is considered not-zero. + #[must_use = "Did you mean to use solve_upper_triangular_unchecked_mut()?"] #[inline] pub fn solve_upper_triangular_unchecked( &self, @@ -578,6 +586,7 @@ impl> SquareMatrix { */ /// Computes the solution of the linear system `self.transpose() . x = b` where `x` is the unknown and only /// the lower-triangular part of `self` (including the diagonal) is considered not-zero. + #[must_use = "Did you mean to use tr_solve_lower_triangular_unchecked_mut()?"] #[inline] pub fn tr_solve_lower_triangular_unchecked( &self, @@ -595,6 +604,7 @@ impl> SquareMatrix { /// Computes the solution of the linear system `self.transpose() . x = b` where `x` is the unknown and only /// the upper-triangular part of `self` (including the diagonal) is considered not-zero. + #[must_use = "Did you mean to use tr_solve_upper_triangular_unchecked_mut()?"] #[inline] pub fn tr_solve_upper_triangular_unchecked( &self, @@ -648,6 +658,7 @@ impl> SquareMatrix { /// Computes the solution of the linear system `self.adjoint() . x = b` where `x` is the unknown and only /// the lower-triangular part of `self` (including the diagonal) is considered not-zero. + #[must_use = "Did you mean to use ad_solve_lower_triangular_unchecked_mut()?"] #[inline] pub fn ad_solve_lower_triangular_unchecked( &self, @@ -665,6 +676,7 @@ impl> SquareMatrix { /// Computes the solution of the linear system `self.adjoint() . x = b` where `x` is the unknown and only /// the upper-triangular part of `self` (including the diagonal) is considered not-zero. + #[must_use = "Did you mean to use ad_solve_upper_triangular_unchecked_mut()?"] #[inline] pub fn ad_solve_upper_triangular_unchecked( &self, diff --git a/src/sparse/cs_matrix.rs b/src/sparse/cs_matrix.rs index c4a0c901..2dc8467e 100644 --- a/src/sparse/cs_matrix.rs +++ b/src/sparse/cs_matrix.rs @@ -409,6 +409,7 @@ impl> CsMatrix { } /// Computes the transpose of this sparse matrix. + #[must_use = "This function does not mutate the matrix. Consider using the return value or removing the function call. There's also transpose_mut() for square matrices."] pub fn transpose(&self) -> CsMatrix where DefaultAllocator: Allocator, diff --git a/src/sparse/cs_matrix_solve.rs b/src/sparse/cs_matrix_solve.rs index 52065747..33d811cf 100644 --- a/src/sparse/cs_matrix_solve.rs +++ b/src/sparse/cs_matrix_solve.rs @@ -6,6 +6,7 @@ use crate::{Const, DefaultAllocator, Dim, Matrix, OMatrix, OVector, RealField}; impl> CsMatrix { /// Solve a lower-triangular system with a dense right-hand-side. + #[must_use = "Did you mean to use solve_lower_triangular_mut()?"] pub fn solve_lower_triangular( &self, b: &Matrix, @@ -24,6 +25,7 @@ impl> CsMatrix { } /// Solve a lower-triangular system with `self` transposed and a dense right-hand-side. + #[must_use = "Did you mean to use tr_solve_lower_triangular_mut()?"] pub fn tr_solve_lower_triangular( &self, b: &Matrix, @@ -135,6 +137,7 @@ impl> CsMatrix { } /// Solve a lower-triangular system with a sparse right-hand-side. + #[must_use = "This function has no side effects. Consider using the return value or removing the function call."] pub fn solve_lower_triangular_cs( &self, b: &CsVector, From d85c10a73cd1b922acd3ac3af6cf28fe5ef7d2d9 Mon Sep 17 00:00:00 2001 From: Malte Tammena Date: Sun, 6 Jun 2021 11:34:29 +0200 Subject: [PATCH 04/42] Add some missing question marks --- src/linalg/cholesky.rs | 2 +- src/linalg/qr.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/linalg/cholesky.rs b/src/linalg/cholesky.rs index eb2ebc9f..fa090852 100644 --- a/src/linalg/cholesky.rs +++ b/src/linalg/cholesky.rs @@ -119,7 +119,7 @@ where /// Returns the solution of the system `self * x = b` where `self` is the decomposed matrix and /// `x` the unknown. - #[must_use = "Did you mean to use solve_mut()"] + #[must_use = "Did you mean to use solve_mut()?"] pub fn solve(&self, b: &Matrix) -> OMatrix where S2: Storage, diff --git a/src/linalg/qr.rs b/src/linalg/qr.rs index 103916a0..a0fd898e 100644 --- a/src/linalg/qr.rs +++ b/src/linalg/qr.rs @@ -164,7 +164,7 @@ where /// Solves the linear system `self * x = b`, where `x` is the unknown to be determined. /// /// Returns `None` if `self` is not invertible. - #[must_use = "Did you mean to use solve_mut()"] + #[must_use = "Did you mean to use solve_mut()?"] pub fn solve( &self, b: &Matrix, From 39aa52d0194719fd9cf12381f2375767ebfffec2 Mon Sep 17 00:00:00 2001 From: Malte Tammena Date: Sun, 6 Jun 2021 14:46:36 +0200 Subject: [PATCH 05/42] Add must_use annotations in src/**/*.rs --- src/base/blas.rs | 3 ++ src/base/componentwise.rs | 5 ++ src/base/edition.rs | 4 ++ src/base/indexing.rs | 3 ++ src/base/interpolation.rs | 4 ++ src/base/matrix.rs | 31 ++++++++++++ src/base/matrix_slice.rs | 3 ++ src/base/min_max.rs | 15 ++++++ src/base/norm.rs | 12 ++++- src/base/ops.rs | 3 ++ src/base/properties.rs | 7 +++ src/base/statistics.rs | 15 ++++++ src/base/swizzle.rs | 1 + src/base/vec_storage.rs | 3 ++ src/geometry/dual_quaternion.rs | 17 ++++++- src/geometry/isometry.rs | 8 +++ src/geometry/isometry_interpolation.rs | 6 +++ src/geometry/orthographic.rs | 14 ++++++ src/geometry/perspective.rs | 12 +++++ src/geometry/point.rs | 8 +++ src/geometry/quaternion.rs | 61 +++++++++++++++++++++++ src/geometry/reflection.rs | 1 + src/geometry/rotation.rs | 7 +++ src/geometry/rotation_interpolation.rs | 3 ++ src/geometry/rotation_specialization.rs | 13 +++++ src/geometry/similarity.rs | 6 +++ src/geometry/swizzle.rs | 1 + src/geometry/transform.rs | 6 +++ src/geometry/translation.rs | 3 ++ src/geometry/unit_complex.rs | 14 ++++++ src/geometry/unit_complex_construction.rs | 3 ++ src/linalg/bidiagonal.rs | 6 +++ src/linalg/cholesky.rs | 4 ++ src/linalg/col_piv_qr.rs | 6 +++ src/linalg/convolution.rs | 1 + src/linalg/determinant.rs | 1 + src/linalg/full_piv_lu.rs | 7 +++ src/linalg/givens.rs | 2 + src/linalg/hessenberg.rs | 2 + src/linalg/lu.rs | 6 +++ src/linalg/permutation_sequence.rs | 3 ++ src/linalg/qr.rs | 4 ++ src/linalg/schur.rs | 4 ++ src/linalg/svd.rs | 3 ++ src/linalg/symmetric_eigen.rs | 2 + src/linalg/symmetric_tridiagonal.rs | 3 ++ src/linalg/udu.rs | 1 + src/sparse/cs_matrix.rs | 9 ++++ src/sparse/cs_matrix_cholesky.rs | 1 + 49 files changed, 354 insertions(+), 3 deletions(-) diff --git a/src/base/blas.rs b/src/base/blas.rs index 05705f17..f3e3fb91 100644 --- a/src/base/blas.rs +++ b/src/base/blas.rs @@ -193,6 +193,7 @@ where /// ``` /// #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn dot(&self, rhs: &Matrix) -> T where SB: Storage, @@ -221,6 +222,7 @@ where /// assert_ne!(vec1.dotc(&vec2), vec1.dot(&vec2)); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn dotc(&self, rhs: &Matrix) -> T where T: SimdComplexField, @@ -248,6 +250,7 @@ where /// assert_eq!(mat1.tr_dot(&mat2), 9.1); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn tr_dot(&self, rhs: &Matrix) -> T where SB: Storage, diff --git a/src/base/componentwise.rs b/src/base/componentwise.rs index 2ba49b2a..1a3ad284 100644 --- a/src/base/componentwise.rs +++ b/src/base/componentwise.rs @@ -28,6 +28,7 @@ impl> Matrix { /// assert_eq!(a.abs(), Matrix2::new(0.0, 1.0, 2.0, 3.0)) /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn abs(&self) -> OMatrix where T: Signed, @@ -49,6 +50,7 @@ macro_rules! component_binop_impl( ($($binop: ident, $binop_mut: ident, $binop_assign: ident, $cmpy: ident, $Trait: ident . $op: ident . $op_assign: ident, $desc:expr, $desc_cmpy:expr, $desc_mut:expr);* $(;)*) => {$( #[doc = $desc] #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn $binop(&self, rhs: &Matrix) -> MatrixComponentOp where T: $Trait, R2: Dim, C2: Dim, @@ -251,6 +253,7 @@ impl> Matrix /// assert_eq!(u.inf(&v), expected) /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn inf(&self, other: &Self) -> OMatrix where T: SimdPartialOrd, @@ -271,6 +274,7 @@ impl> Matrix /// assert_eq!(u.sup(&v), expected) /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn sup(&self, other: &Self) -> OMatrix where T: SimdPartialOrd, @@ -291,6 +295,7 @@ impl> Matrix /// assert_eq!(u.inf_sup(&v), expected) /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn inf_sup(&self, other: &Self) -> (OMatrix, OMatrix) where T: SimdPartialOrd, diff --git a/src/base/edition.rs b/src/base/edition.rs index 17c08c98..459dfcb2 100644 --- a/src/base/edition.rs +++ b/src/base/edition.rs @@ -18,6 +18,7 @@ use crate::base::{DefaultAllocator, Matrix, OMatrix, RowVector, Scalar, Vector}; impl> Matrix { /// Extracts the upper triangular part of this matrix (including the diagonal). #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn upper_triangle(&self) -> OMatrix where DefaultAllocator: Allocator, @@ -30,6 +31,7 @@ impl> Matrix { /// Extracts the lower triangular part of this matrix (including the diagonal). #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn lower_triangle(&self) -> OMatrix where DefaultAllocator: Allocator, @@ -42,6 +44,7 @@ impl> Matrix { /// Creates a new matrix by extracting the given set of rows from `self`. #[cfg(any(feature = "std", feature = "alloc"))] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn select_rows<'a, I>(&self, irows: I) -> OMatrix where I: IntoIterator, @@ -78,6 +81,7 @@ impl> Matrix { /// Creates a new matrix by extracting the given set of columns from `self`. #[cfg(any(feature = "std", feature = "alloc"))] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn select_columns<'a, I>(&self, icols: I) -> OMatrix where I: IntoIterator, diff --git a/src/base/indexing.rs b/src/base/indexing.rs index 3e0c085e..aa5ae942 100644 --- a/src/base/indexing.rs +++ b/src/base/indexing.rs @@ -485,6 +485,7 @@ impl> Matrix { /// Produces a view of the data at the given index, or /// `None` if the index is out of bounds. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn get<'a, I>(&'a self, index: I) -> Option where I: MatrixIndex<'a, T, R, C, S>, @@ -506,6 +507,7 @@ impl> Matrix { /// Produces a view of the data at the given index, or /// panics if the index is out of bounds. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn index<'a, I>(&'a self, index: I) -> I::Output where I: MatrixIndex<'a, T, R, C, S>, @@ -527,6 +529,7 @@ impl> Matrix { /// Produces a view of the data at the given index, without doing /// any bounds checking. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub unsafe fn get_unchecked<'a, I>(&'a self, index: I) -> I::Output where I: MatrixIndex<'a, T, R, C, S>, diff --git a/src/base/interpolation.rs b/src/base/interpolation.rs index c008743a..9dd72b5a 100644 --- a/src/base/interpolation.rs +++ b/src/base/interpolation.rs @@ -20,6 +20,7 @@ impl>(&self, rhs: &Vector, t: T) -> OVector where DefaultAllocator: Allocator, @@ -45,6 +46,7 @@ impl>(&self, rhs: &Vector, t: T) -> OVector where T: RealField, @@ -72,6 +74,7 @@ impl> Unit> { /// /// assert_eq!(v, v2); /// ``` + #[must_use = "This function does not mutate self. You should use the return value."] pub fn slerp>( &self, rhs: &Unit>, @@ -89,6 +92,7 @@ impl> Unit> { /// /// Returns `None` if the two vectors are almost collinear and with opposite direction /// (in this case, there is an infinity of possible results). + #[must_use = "This function does not mutate self. You should use the return value."] pub fn try_slerp>( &self, rhs: &Unit>, diff --git a/src/base/matrix.rs b/src/base/matrix.rs index bc9942be..ebd22d31 100644 --- a/src/base/matrix.rs +++ b/src/base/matrix.rs @@ -441,6 +441,7 @@ impl> Matrix { /// let mat = Matrix3x4::::zeros(); /// assert_eq!(mat.shape(), (3, 4)); #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn shape(&self) -> (usize, usize) { let (nrows, ncols) = self.data.shape(); (nrows.value(), ncols.value()) @@ -455,6 +456,7 @@ impl> Matrix { /// let mat = Matrix3x4::::zeros(); /// assert_eq!(mat.nrows(), 3); #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn nrows(&self) -> usize { self.shape().0 } @@ -468,6 +470,7 @@ impl> Matrix { /// let mat = Matrix3x4::::zeros(); /// assert_eq!(mat.ncols(), 4); #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn ncols(&self) -> usize { self.shape().1 } @@ -483,6 +486,7 @@ impl> Matrix { /// // The column strides is the number of steps (here 2) multiplied by the corresponding dimension. /// assert_eq!(mat.strides(), (1, 10)); #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn strides(&self) -> (usize, usize) { let (srows, scols) = self.data.strides(); (srows.value(), scols.value()) @@ -501,6 +505,7 @@ impl> Matrix { /// assert_eq!(m[i], m[3]); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn vector_to_matrix_index(&self, i: usize) -> (usize, usize) { let (nrows, ncols) = self.shape(); @@ -529,6 +534,7 @@ impl> Matrix { /// assert_eq!(unsafe { *ptr }, m[0]); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn as_ptr(&self) -> *const T { self.data.ptr() } @@ -537,6 +543,7 @@ impl> Matrix { /// /// See `relative_eq` from the `RelativeEq` trait for more details. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn relative_eq( &self, other: &Matrix, @@ -559,6 +566,7 @@ impl> Matrix { /// Tests whether `self` and `rhs` are exactly equal. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn eq(&self, other: &Matrix) -> bool where T: PartialEq, @@ -609,6 +617,7 @@ impl> Matrix { /// Clones this matrix to one that owns its data. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn clone_owned(&self) -> OMatrix where DefaultAllocator: Allocator, @@ -619,6 +628,7 @@ impl> Matrix { /// Clones this matrix into one that owns its data. The actual type of the result depends on /// matrix storage combination rules for addition. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn clone_owned_sum(&self) -> MatrixSum where R2: Dim, @@ -692,6 +702,7 @@ impl> Matrix { impl> Matrix { /// Returns a matrix containing the result of `f` applied to each of its entries. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn map T2>(&self, mut f: F) -> OMatrix where DefaultAllocator: Allocator, @@ -738,6 +749,7 @@ impl> Matrix { /// - If the matrix has has least one component, then `init_f` is called with the first component /// to compute the initial value. Folding then continues on all the remaining components of the matrix. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn fold_with( &self, init_f: impl FnOnce(Option<&T>) -> T2, @@ -751,6 +763,7 @@ impl> Matrix { /// Returns a matrix containing the result of `f` applied to each of its entries. Unlike `map`, /// `f` also gets passed the row and column index, i.e. `f(row, col, value)`. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn map_with_location T2>( &self, mut f: F, @@ -778,6 +791,7 @@ impl> Matrix { /// Returns a matrix containing the result of `f` applied to each entries of `self` and /// `rhs`. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn zip_map(&self, rhs: &Matrix, mut f: F) -> OMatrix where T2: Scalar, @@ -813,6 +827,7 @@ impl> Matrix { /// Returns a matrix containing the result of `f` applied to each entries of `self` and /// `b`, and `c`. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn zip_zip_map( &self, b: &Matrix, @@ -860,6 +875,7 @@ impl> Matrix { /// Folds a function `f` on each entry of `self`. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn fold(&self, init: Acc, mut f: impl FnMut(Acc, T) -> Acc) -> Acc { let (nrows, ncols) = self.data.shape(); @@ -879,6 +895,7 @@ impl> Matrix { /// Folds a function `f` on each pairs of entries from `self` and `rhs`. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn zip_fold( &self, rhs: &Matrix, @@ -1238,6 +1255,7 @@ impl> Matrix { impl> Vector { /// Gets a reference to the i-th element of this column vector without bound checking. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub unsafe fn vget_unchecked(&self, i: usize) -> &T { debug_assert!(i < self.nrows(), "Vector index out of bounds."); let i = i * self.strides().0; @@ -1258,6 +1276,7 @@ impl> Vector { impl> Matrix { /// Extracts a slice containing the entire matrix entries ordered column-by-columns. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn as_slice(&self) -> &[T] { self.data.as_slice() } @@ -1446,6 +1465,7 @@ impl> Matrix { impl> SquareMatrix { /// The diagonal of this matrix. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn diagonal(&self) -> OVector where DefaultAllocator: Allocator, @@ -1457,6 +1477,7 @@ impl> SquareMatrix { /// /// This is a more efficient version of `self.diagonal().map(f)` since this /// allocates only once. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn map_diagonal(&self, mut f: impl FnMut(T) -> T2) -> OVector where DefaultAllocator: Allocator, @@ -1481,6 +1502,7 @@ impl> SquareMatrix { /// Computes a trace of a square matrix, i.e., the sum of its diagonal elements. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn trace(&self) -> T where T: Scalar + Zero + ClosedAdd, @@ -1504,6 +1526,7 @@ impl> SquareMatrix { impl> SquareMatrix { /// The symmetric part of `self`, i.e., `0.5 * (self + self.transpose())`. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn symmetric_part(&self) -> OMatrix where DefaultAllocator: Allocator, @@ -1520,6 +1543,7 @@ impl> SquareMatrix { /// The hermitian part of `self`, i.e., `0.5 * (self + self.adjoint())`. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn hermitian_part(&self) -> OMatrix where DefaultAllocator: Allocator, @@ -1542,6 +1566,7 @@ impl + IsNotStaticOne, S: Storage /// Yields the homogeneous matrix for this matrix, i.e., appending an additional dimension and /// and setting the diagonal element to `1`. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn to_homogeneous(&self) -> OMatrix, DimSum> where DefaultAllocator: Allocator, DimSum>, @@ -1562,6 +1587,7 @@ impl, S: Storage> Vector { /// Computes the coordinates in projective space of this vector, i.e., appends a `0` to its /// coordinates. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn to_homogeneous(&self) -> OVector> where DefaultAllocator: Allocator>, @@ -1589,6 +1615,7 @@ impl, S: Storage> Vector { impl, S: Storage> Vector { /// Constructs a new vector of higher dimension by appending `element` to the end of `self`. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn push(&self, element: T) -> OVector> where DefaultAllocator: Allocator>, @@ -1891,6 +1918,7 @@ impl(&self, b: &Matrix) -> T where R2: Dim, @@ -1920,6 +1948,7 @@ impl(&self, b: &Matrix) -> MatrixCross where R2: Dim, @@ -1993,6 +2022,7 @@ impl> Vector { /// Computes the matrix `M` such that for all vector `v` we have `M * v == self.cross(&v)`. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn cross_matrix(&self) -> OMatrix { OMatrix::::new( T::zero(), @@ -2011,6 +2041,7 @@ impl> Vector { impl> Matrix { /// The smallest angle between two vectors. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn angle(&self, other: &Matrix) -> T::SimdRealField where SB: Storage, diff --git a/src/base/matrix_slice.rs b/src/base/matrix_slice.rs index 6b03c7b2..646acbc6 100644 --- a/src/base/matrix_slice.rs +++ b/src/base/matrix_slice.rs @@ -812,6 +812,7 @@ impl> Matrix { /// Slices a sub-matrix containing the rows indexed by the range `rows` and the columns indexed /// by the range `cols`. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn slice_range( &self, rows: RowRange, @@ -830,6 +831,7 @@ impl> Matrix { /// Slice containing all the rows indexed by the range `rows`. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn rows_range>( &self, rows: RowRange, @@ -839,6 +841,7 @@ impl> Matrix { /// Slice containing all the columns indexed by the range `rows`. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn columns_range>( &self, cols: ColRange, diff --git a/src/base/min_max.rs b/src/base/min_max.rs index d532d87a..ba109380 100644 --- a/src/base/min_max.rs +++ b/src/base/min_max.rs @@ -13,6 +13,7 @@ impl> Matrix { /// assert_eq!(Vector3::new(-1.0, -2.0, -3.0).amax(), 3.0); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn amax(&self) -> T where T: Zero + SimdSigned + SimdPartialOrd, @@ -33,6 +34,7 @@ impl> Matrix { /// Complex::new(1.0, 3.0)).camax(), 5.0); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn camax(&self) -> T::SimdRealField where T: SimdComplexField, @@ -52,6 +54,7 @@ impl> Matrix { /// assert_eq!(Vector3::new(5u32, 2, 3).max(), 5); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn max(&self) -> T where T: SimdPartialOrd + Zero, @@ -70,6 +73,7 @@ impl> Matrix { /// assert_eq!(Vector3::new(10.0, 2.0, 30.0).amin(), 2.0); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn amin(&self) -> T where T: Zero + SimdPartialOrd + SimdSigned, @@ -90,6 +94,7 @@ impl> Matrix { /// Complex::new(1.0, 3.0)).camin(), 3.0); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn camin(&self) -> T::SimdRealField where T: SimdComplexField, @@ -112,6 +117,7 @@ impl> Matrix { /// assert_eq!(Vector3::new(5u32, 2, 3).min(), 2); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn min(&self) -> T where T: SimdPartialOrd + Zero, @@ -136,6 +142,7 @@ impl> Matrix { /// assert_eq!(mat.icamax_full(), (1, 0)); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn icamax_full(&self) -> (usize, usize) where T: ComplexField, @@ -172,6 +179,7 @@ impl> Matri /// assert_eq!(mat.iamax_full(), (1, 2)); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn iamax_full(&self) -> (usize, usize) { assert!(!self.is_empty(), "The input matrix must not be empty."); @@ -209,6 +217,7 @@ impl> Vector { /// assert_eq!(vec.icamax(), 2); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn icamax(&self) -> usize where T: ComplexField, @@ -240,6 +249,7 @@ impl> Vector { /// assert_eq!(vec.argmax(), (2, 13)); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn argmax(&self) -> (usize, T) where T: PartialOrd, @@ -271,6 +281,7 @@ impl> Vector { /// assert_eq!(vec.imax(), 2); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn imax(&self) -> usize where T: PartialOrd, @@ -288,6 +299,7 @@ impl> Vector { /// assert_eq!(vec.iamax(), 1); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn iamax(&self) -> usize where T: PartialOrd + Signed, @@ -319,6 +331,7 @@ impl> Vector { /// assert_eq!(vec.argmin(), (1, -15)); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn argmin(&self) -> (usize, T) where T: PartialOrd, @@ -350,6 +363,7 @@ impl> Vector { /// assert_eq!(vec.imin(), 1); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn imin(&self) -> usize where T: PartialOrd, @@ -367,6 +381,7 @@ impl> Vector { /// assert_eq!(vec.iamin(), 0); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn iamin(&self) -> usize where T: PartialOrd + Signed, diff --git a/src/base/norm.rs b/src/base/norm.rs index ab44ed02..0cf42906 100644 --- a/src/base/norm.rs +++ b/src/base/norm.rs @@ -158,6 +158,7 @@ impl Norm for UniformNorm { impl> Matrix { /// The squared L2 norm of this vector. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn norm_squared(&self) -> T::SimdRealField where T: SimdComplexField, @@ -176,6 +177,7 @@ impl> Matrix { /// /// Use `.apply_norm` to apply a custom norm. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn norm(&self) -> T::SimdRealField where T: SimdComplexField, @@ -187,6 +189,7 @@ impl> Matrix { /// /// Use `.apply_metric_distance` to apply a custom norm. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn metric_distance(&self, rhs: &Matrix) -> T::SimdRealField where T: SimdComplexField, @@ -211,6 +214,7 @@ impl> Matrix { /// assert_eq!(v.apply_norm(&EuclideanNorm), v.norm()); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn apply_norm(&self, norm: &impl Norm) -> T::SimdRealField where T: SimdComplexField, @@ -233,6 +237,7 @@ impl> Matrix { /// assert_eq!(v1.apply_metric_distance(&v2, &EuclideanNorm), (v1 - v2).norm()); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn apply_metric_distance( &self, rhs: &Matrix, @@ -254,6 +259,7 @@ impl> Matrix { /// /// This function is simply implemented as a call to `norm()` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn magnitude(&self) -> T::SimdRealField where T: SimdComplexField, @@ -267,6 +273,7 @@ impl> Matrix { /// /// This function is simply implemented as a call to `norm_squared()` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn magnitude_squared(&self) -> T::SimdRealField where T: SimdComplexField, @@ -298,6 +305,7 @@ impl> Matrix { /// The Lp norm of this matrix. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn lp_norm(&self, p: i32) -> T::SimdRealField where T: SimdComplexField, @@ -340,8 +348,8 @@ impl> Matrix { } /// Returns a new vector with the same magnitude as `self` clamped between `0.0` and `max`. - #[must_use = "This function does not mutate self but returns a new clamped version."] #[inline] + #[must_use = "This function does not mutate self but returns a new clamped version."] pub fn cap_magnitude(&self, max: T::RealField) -> OMatrix where T: ComplexField, @@ -357,8 +365,8 @@ impl> Matrix { } /// Returns a new vector with the same magnitude as `self` clamped between `0.0` and `max`. - #[must_use = "This function does not mutate self but returns a new clamped version."] #[inline] + #[must_use = "This function does not mutate self but returns a new clamped version."] pub fn simd_cap_magnitude(&self, max: T::SimdRealField) -> OMatrix where T: SimdComplexField, diff --git a/src/base/ops.rs b/src/base/ops.rs index 8917efb1..b23a85e6 100644 --- a/src/base/ops.rs +++ b/src/base/ops.rs @@ -676,6 +676,7 @@ where { /// Equivalent to `self.transpose() * rhs`. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn tr_mul(&self, rhs: &Matrix) -> OMatrix where SB: Storage, @@ -692,6 +693,7 @@ where /// Equivalent to `self.adjoint() * rhs`. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn ad_mul(&self, rhs: &Matrix) -> OMatrix where T: SimdComplexField, @@ -801,6 +803,7 @@ where /// The kronecker product of two matrices (aka. tensor product of the corresponding linear /// maps). + #[must_use = "This function does not mutate self. You should use the return value."] pub fn kronecker( &self, rhs: &Matrix, diff --git a/src/base/properties.rs b/src/base/properties.rs index 1cbff719..e5645ce0 100644 --- a/src/base/properties.rs +++ b/src/base/properties.rs @@ -20,6 +20,7 @@ impl> Matrix { /// assert_eq!(mat.len(), 12); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn len(&self) -> usize { let (nrows, ncols) = self.shape(); nrows * ncols @@ -35,12 +36,14 @@ impl> Matrix { /// assert!(!mat.is_empty()); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn is_empty(&self) -> bool { self.len() == 0 } /// Indicates if this is a square matrix. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn is_square(&self) -> bool { let (nrows, ncols) = self.shape(); nrows == ncols @@ -52,6 +55,7 @@ impl> Matrix { /// If the matrix is diagonal, this checks that diagonal elements (i.e. at coordinates `(i, i)` /// for i from `0` to `min(R, C)`) are equal one; and that all other elements are zero. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn is_identity(&self, eps: T::Epsilon) -> bool where T: Zero + One + RelativeEq, @@ -112,6 +116,7 @@ impl> Matrix { /// In this definition `Id` is approximately equal to the identity matrix with a relative error /// equal to `eps`. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn is_orthogonal(&self, eps: T::Epsilon) -> bool where T: Zero + One + ClosedAdd + ClosedMul + RelativeEq, @@ -129,6 +134,7 @@ where { /// Checks that this matrix is orthogonal and has a determinant equal to 1. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn is_special_orthogonal(&self, eps: T) -> bool where D: DimMin, @@ -139,6 +145,7 @@ where /// Returns `true` if this matrix is invertible. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn is_invertible(&self) -> bool { // TODO: improve this? self.clone_owned().try_inverse().is_some() diff --git a/src/base/statistics.rs b/src/base/statistics.rs index 8f6c77ce..0b3a8279 100644 --- a/src/base/statistics.rs +++ b/src/base/statistics.rs @@ -9,6 +9,7 @@ impl> Matrix { /// Returns a row vector where each element is the result of the application of `f` on the /// corresponding column of the original matrix. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn compress_rows( &self, f: impl Fn(VectorSlice) -> T, @@ -35,6 +36,7 @@ impl> Matrix { /// /// This is the same as `self.compress_rows(f).transpose()`. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn compress_rows_tr( &self, f: impl Fn(VectorSlice) -> T, @@ -58,6 +60,7 @@ impl> Matrix { /// Returns a column vector resulting from the folding of `f` on each column of this matrix. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn compress_columns( &self, init: OVector, @@ -95,6 +98,7 @@ impl> Matrix { /// assert_eq!(m.sum(), 21.0); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn sum(&self) -> T where T: ClosedAdd + Zero, @@ -120,6 +124,7 @@ impl> Matrix { /// assert_eq!(mint.row_sum(), RowVector2::new(9,12)); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn row_sum(&self) -> RowOVector where T: ClosedAdd + Zero, @@ -144,6 +149,7 @@ impl> Matrix { /// assert_eq!(mint.row_sum_tr(), Vector2::new(9,12)); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn row_sum_tr(&self) -> OVector where T: ClosedAdd + Zero, @@ -168,6 +174,7 @@ impl> Matrix { /// assert_eq!(mint.column_sum(), Vector3::new(3,7,11)); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn column_sum(&self) -> OVector where T: ClosedAdd + Zero, @@ -197,6 +204,7 @@ impl> Matrix { /// assert_relative_eq!(m.variance(), 35.0 / 12.0, epsilon = 1.0e-8); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn variance(&self) -> T where T: Field + SupersetOf, @@ -226,6 +234,7 @@ impl> Matrix { /// assert_eq!(m.row_variance(), RowVector3::new(2.25, 2.25, 2.25)); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn row_variance(&self) -> RowOVector where T: Field + SupersetOf, @@ -246,6 +255,7 @@ impl> Matrix { /// assert_eq!(m.row_variance_tr(), Vector3::new(2.25, 2.25, 2.25)); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn row_variance_tr(&self) -> OVector where T: Field + SupersetOf, @@ -267,6 +277,7 @@ impl> Matrix { /// assert_relative_eq!(m.column_variance(), Vector2::new(2.0 / 3.0, 2.0 / 3.0), epsilon = 1.0e-8); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn column_variance(&self) -> OVector where T: Field + SupersetOf, @@ -306,6 +317,7 @@ impl> Matrix { /// assert_eq!(m.mean(), 3.5); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn mean(&self) -> T where T: Field + SupersetOf, @@ -331,6 +343,7 @@ impl> Matrix { /// assert_eq!(m.row_mean(), RowVector3::new(2.5, 3.5, 4.5)); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn row_mean(&self) -> RowOVector where T: Field + SupersetOf, @@ -351,6 +364,7 @@ impl> Matrix { /// assert_eq!(m.row_mean_tr(), Vector3::new(2.5, 3.5, 4.5)); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn row_mean_tr(&self) -> OVector where T: Field + SupersetOf, @@ -371,6 +385,7 @@ impl> Matrix { /// assert_eq!(m.column_mean(), Vector2::new(2.0, 5.0)); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn column_mean(&self) -> OVector where T: Field + SupersetOf, diff --git a/src/base/swizzle.rs b/src/base/swizzle.rs index 1e2f0e4c..76fecda2 100644 --- a/src/base/swizzle.rs +++ b/src/base/swizzle.rs @@ -8,6 +8,7 @@ macro_rules! impl_swizzle { $( /// Builds a new vector from components of `self`. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn $name(&self) -> $Result where D::Typenum: Cmp { $Result::new($(self[$i].inlined_clone()),*) diff --git a/src/base/vec_storage.rs b/src/base/vec_storage.rs index 8b2d2ef2..48a25b20 100644 --- a/src/base/vec_storage.rs +++ b/src/base/vec_storage.rs @@ -95,6 +95,7 @@ impl VecStorage { /// The underlying data storage. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn as_vec(&self) -> &Vec { &self.data } @@ -129,12 +130,14 @@ impl VecStorage { /// The number of elements on the underlying vector. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn len(&self) -> usize { self.data.len() } /// Returns true if the underlying vector contains no elements. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn is_empty(&self) -> bool { self.len() == 0 } diff --git a/src/geometry/dual_quaternion.rs b/src/geometry/dual_quaternion.rs index b6b127ce..04252b22 100644 --- a/src/geometry/dual_quaternion.rs +++ b/src/geometry/dual_quaternion.rs @@ -232,6 +232,7 @@ where /// )); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn lerp(&self, other: &Self, t: T) -> Self { self * (T::one() - t) + other * t } @@ -381,6 +382,7 @@ where /// )); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn dual_quaternion(&self) -> &DualQuaternion { self.as_ref() } @@ -463,7 +465,6 @@ where /// assert_relative_eq!(inv * unit, UnitDualQuaternion::identity(), epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "Did you mean to use inverse_mut()?"] pub fn inverse_mut(&mut self) { let quat = self.as_mut_unchecked(); quat.real = Unit::new_unchecked(quat.real).inverse().into_inner(); @@ -486,6 +487,7 @@ where /// assert_relative_eq!(dq_to * dq1, dq2, epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn isometry_to(&self, other: &Self) -> Self { other / self } @@ -518,6 +520,7 @@ where /// ); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn lerp(&self, other: &Self, t: T) -> DualQuaternion { self.as_ref().lerp(other.as_ref(), t) } @@ -546,6 +549,7 @@ where /// ), epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn nlerp(&self, other: &Self, t: T) -> Self { let mut res = self.lerp(other, t); let _ = res.normalize_mut(); @@ -581,6 +585,7 @@ where /// ); /// assert_relative_eq!(dq.translation().vector.y, 3.0, epsilon = 1.0e-6); #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn sclerp(&self, other: &Self, t: T) -> Self where T: RealField, @@ -600,6 +605,7 @@ where /// * `epsilon`: the value below which the sinus of the angle separating both quaternion /// must be to return `None`. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn try_sclerp(&self, other: &Self, t: T, epsilon: T) -> Option where T: RealField, @@ -667,6 +673,7 @@ where /// ); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn rotation(&self) -> UnitQuaternion { Unit::new_unchecked(self.as_ref().real) } @@ -686,6 +693,7 @@ where /// ); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn translation(&self) -> Translation3 { let two = T::one() + T::one(); Translation3::from( @@ -712,6 +720,7 @@ where /// assert_relative_eq!(iso.translation.vector, translation, epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn to_isometry(&self) -> Isometry3 { Isometry3::from_parts(self.translation(), self.rotation()) } @@ -735,6 +744,7 @@ where /// ); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn transform_point(&self, pt: &Point3) -> Point3 { self * pt } @@ -758,6 +768,7 @@ where /// ); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn transform_vector(&self, v: &Vector3) -> Vector3 { self * v } @@ -781,6 +792,7 @@ where /// ); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn inverse_transform_point(&self, pt: &Point3) -> Point3 { self.inverse() * pt } @@ -805,6 +817,7 @@ where /// ); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn inverse_transform_vector(&self, v: &Vector3) -> Vector3 { self.inverse() * v } @@ -830,6 +843,7 @@ where /// ); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn inverse_transform_unit_vector(&self, v: &Unit>) -> Unit> { self.inverse() * v } @@ -857,6 +871,7 @@ where /// assert_relative_eq!(dq.to_homogeneous(), expected, epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn to_homogeneous(&self) -> Matrix4 { self.to_isometry().to_homogeneous() } diff --git a/src/geometry/isometry.rs b/src/geometry/isometry.rs index d307c393..19e2ed52 100755 --- a/src/geometry/isometry.rs +++ b/src/geometry/isometry.rs @@ -267,6 +267,7 @@ where /// assert_eq!(iso1.inverse() * iso2, iso1.inv_mul(&iso2)); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn inv_mul(&self, rhs: &Isometry) -> Self { let inv_rot1 = self.rotation.inverse(); let tr_12 = rhs.translation.vector.clone() - self.translation.vector.clone(); @@ -384,6 +385,7 @@ where /// assert_relative_eq!(transformed_point, Point3::new(3.0, 2.0, 2.0), epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn transform_point(&self, pt: &Point) -> Point { self * pt } @@ -407,6 +409,7 @@ where /// assert_relative_eq!(transformed_point, Vector3::new(3.0, 2.0, -1.0), epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn transform_vector(&self, v: &SVector) -> SVector { self * v } @@ -429,6 +432,7 @@ where /// assert_relative_eq!(transformed_point, Point3::new(0.0, 2.0, 1.0), epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn inverse_transform_point(&self, pt: &Point) -> Point { self.rotation .inverse_transform_point(&(pt - &self.translation.vector)) @@ -453,6 +457,7 @@ where /// assert_relative_eq!(transformed_point, Vector3::new(-3.0, 2.0, 1.0), epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn inverse_transform_vector(&self, v: &SVector) -> SVector { self.rotation.inverse_transform_vector(v) } @@ -476,6 +481,7 @@ where /// assert_relative_eq!(transformed_point, -Vector3::y_axis(), epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn inverse_transform_unit_vector(&self, v: &Unit>) -> Unit> { self.rotation.inverse_transform_unit_vector(v) } @@ -505,6 +511,7 @@ impl Isometry { /// assert_relative_eq!(iso.to_homogeneous(), expected, epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn to_homogeneous(&self) -> OMatrix, U1>, DimNameSum, U1>> where Const: DimNameAdd, @@ -536,6 +543,7 @@ impl Isometry { /// assert_relative_eq!(iso.to_matrix(), expected, epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn to_matrix(&self) -> OMatrix, U1>, DimNameSum, U1>> where Const: DimNameAdd, diff --git a/src/geometry/isometry_interpolation.rs b/src/geometry/isometry_interpolation.rs index 2ee5461a..1133ae26 100644 --- a/src/geometry/isometry_interpolation.rs +++ b/src/geometry/isometry_interpolation.rs @@ -26,6 +26,7 @@ impl Isometry3 { /// assert_eq!(iso3.rotation.euler_angles(), (std::f32::consts::FRAC_PI_2, 0.0, 0.0)); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn lerp_slerp(&self, other: &Self, t: T) -> Self where T: RealField, @@ -59,6 +60,7 @@ impl Isometry3 { /// assert_eq!(iso3.rotation.euler_angles(), (std::f32::consts::FRAC_PI_2, 0.0, 0.0)); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn try_lerp_slerp(&self, other: &Self, t: T, epsilon: T) -> Option where T: RealField, @@ -94,6 +96,7 @@ impl IsometryMatrix3 { /// assert_eq!(iso3.rotation.euler_angles(), (std::f32::consts::FRAC_PI_2, 0.0, 0.0)); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn lerp_slerp(&self, other: &Self, t: T) -> Self where T: RealField, @@ -127,6 +130,7 @@ impl IsometryMatrix3 { /// assert_eq!(iso3.rotation.euler_angles(), (std::f32::consts::FRAC_PI_2, 0.0, 0.0)); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn try_lerp_slerp(&self, other: &Self, t: T, epsilon: T) -> Option where T: RealField, @@ -163,6 +167,7 @@ impl Isometry2 { /// assert_relative_eq!(iso3.rotation.angle(), std::f32::consts::FRAC_PI_2); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn lerp_slerp(&self, other: &Self, t: T) -> Self where T: RealField, @@ -199,6 +204,7 @@ impl IsometryMatrix2 { /// assert_relative_eq!(iso3.rotation.angle(), std::f32::consts::FRAC_PI_2); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn lerp_slerp(&self, other: &Self, t: T) -> Self where T: RealField, diff --git a/src/geometry/orthographic.rs b/src/geometry/orthographic.rs index d6136cec..1a02ebc8 100644 --- a/src/geometry/orthographic.rs +++ b/src/geometry/orthographic.rs @@ -188,6 +188,7 @@ impl Orthographic3 { /// assert_relative_eq!(proj.as_matrix() * inv, Matrix4::identity()); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn inverse(&self) -> Matrix4 { let mut res = self.to_homogeneous(); @@ -221,6 +222,7 @@ impl Orthographic3 { /// assert_eq!(proj.to_homogeneous(), expected); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn to_homogeneous(&self) -> Matrix4 { self.matrix } @@ -240,6 +242,7 @@ impl Orthographic3 { /// assert_eq!(*proj.as_matrix(), expected); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn as_matrix(&self) -> &Matrix4 { &self.matrix } @@ -253,6 +256,7 @@ impl Orthographic3 { /// assert_eq!(proj.as_projective().to_homogeneous(), proj.to_homogeneous()); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn as_projective(&self) -> &Projective3 { unsafe { mem::transmute(self) } } @@ -266,6 +270,7 @@ impl Orthographic3 { /// assert_eq!(proj.to_projective().to_homogeneous(), proj.to_homogeneous()); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn to_projective(&self) -> Projective3 { Projective3::from_matrix_unchecked(self.matrix) } @@ -310,6 +315,7 @@ impl Orthographic3 { /// assert_relative_eq!(proj.left(), 10.0, epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn left(&self) -> T { (-T::one() - self.matrix[(0, 3)]) / self.matrix[(0, 0)] } @@ -326,6 +332,7 @@ impl Orthographic3 { /// assert_relative_eq!(proj.right(), 1.0, epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn right(&self) -> T { (T::one() - self.matrix[(0, 3)]) / self.matrix[(0, 0)] } @@ -342,6 +349,7 @@ impl Orthographic3 { /// assert_relative_eq!(proj.bottom(), 20.0, epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn bottom(&self) -> T { (-T::one() - self.matrix[(1, 3)]) / self.matrix[(1, 1)] } @@ -358,6 +366,7 @@ impl Orthographic3 { /// assert_relative_eq!(proj.top(), 2.0, epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn top(&self) -> T { (T::one() - self.matrix[(1, 3)]) / self.matrix[(1, 1)] } @@ -374,6 +383,7 @@ impl Orthographic3 { /// assert_relative_eq!(proj.znear(), 1000.0, epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn znear(&self) -> T { (T::one() + self.matrix[(2, 3)]) / self.matrix[(2, 2)] } @@ -390,6 +400,7 @@ impl Orthographic3 { /// assert_relative_eq!(proj.zfar(), 0.1, epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn zfar(&self) -> T { (-T::one() + self.matrix[(2, 3)]) / self.matrix[(2, 2)] } @@ -422,6 +433,7 @@ impl Orthographic3 { /// assert_relative_eq!(proj.project_point(&p8), Point3::new( 1.0, 1.0, 1.0)); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn project_point(&self, p: &Point3) -> Point3 { Point3::new( self.matrix[(0, 0)] * p[0] + self.matrix[(0, 3)], @@ -457,6 +469,7 @@ impl Orthographic3 { /// assert_relative_eq!(proj.unproject_point(&p8), Point3::new(10.0, 20.0, -1000.0), epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn unproject_point(&self, p: &Point3) -> Point3 { Point3::new( (p[0] - self.matrix[(0, 3)]) / self.matrix[(0, 0)], @@ -485,6 +498,7 @@ impl Orthographic3 { /// assert_relative_eq!(proj.project_vector(&v3), Vector3::z() * -2.0 / 999.9); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn project_vector(&self, p: &Vector) -> Vector3 where SB: Storage, diff --git a/src/geometry/perspective.rs b/src/geometry/perspective.rs index fac8fa99..c300b292 100644 --- a/src/geometry/perspective.rs +++ b/src/geometry/perspective.rs @@ -104,6 +104,7 @@ impl Perspective3 { /// Retrieves the inverse of the underlying homogeneous matrix. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn inverse(&self) -> Matrix4 { let mut res = self.to_homogeneous(); @@ -123,24 +124,28 @@ impl Perspective3 { /// Computes the corresponding homogeneous matrix. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn to_homogeneous(&self) -> Matrix4 { self.matrix.clone_owned() } /// A reference to the underlying homogeneous transformation matrix. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn as_matrix(&self) -> &Matrix4 { &self.matrix } /// A reference to this transformation seen as a `Projective3`. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn as_projective(&self) -> &Projective3 { unsafe { mem::transmute(self) } } /// This transformation seen as a `Projective3`. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn to_projective(&self) -> Projective3 { Projective3::from_matrix_unchecked(self.matrix) } @@ -161,18 +166,21 @@ impl Perspective3 { /// Gets the `width / height` aspect ratio of the view frustum. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn aspect(&self) -> T { self.matrix[(1, 1)] / self.matrix[(0, 0)] } /// Gets the y field of view of the view frustum. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn fovy(&self) -> T { (T::one() / self.matrix[(1, 1)]).atan() * crate::convert(2.0) } /// Gets the near plane offset of the view frustum. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn znear(&self) -> T { let ratio = (-self.matrix[(2, 2)] + T::one()) / (-self.matrix[(2, 2)] - T::one()); @@ -182,6 +190,7 @@ impl Perspective3 { /// Gets the far plane offset of the view frustum. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn zfar(&self) -> T { let ratio = (-self.matrix[(2, 2)] + T::one()) / (-self.matrix[(2, 2)] - T::one()); @@ -193,6 +202,7 @@ impl Perspective3 { // TODO: when we get specialization, specialize the Mul impl instead. /// Projects a point. Faster than matrix multiplication. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn project_point(&self, p: &Point3) -> Point3 { let inverse_denom = -T::one() / p[2]; Point3::new( @@ -204,6 +214,7 @@ impl Perspective3 { /// Un-projects a point. Faster than multiplication by the matrix inverse. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn unproject_point(&self, p: &Point3) -> Point3 { let inverse_denom = self.matrix[(2, 3)] / (p[2] + self.matrix[(2, 2)]); @@ -217,6 +228,7 @@ impl Perspective3 { // TODO: when we get specialization, specialize the Mul impl instead. /// Projects a vector. Faster than matrix multiplication. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn project_vector(&self, p: &Vector) -> Vector3 where SB: Storage, diff --git a/src/geometry/point.rs b/src/geometry/point.rs index 60fa9156..8a9bb040 100644 --- a/src/geometry/point.rs +++ b/src/geometry/point.rs @@ -122,6 +122,7 @@ impl Point { /// assert_eq!(p.map(|e| e as u32), Point3::new(1, 2, 3)); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn map T2>(&self, f: F) -> Point { self.coords.map(f).into() } @@ -161,6 +162,7 @@ impl Point { /// assert_eq!(p.to_homogeneous(), Vector4::new(10.0, 20.0, 30.0, 1.0)); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn to_homogeneous(&self) -> OVector, U1>> where T: One, @@ -199,6 +201,7 @@ impl Point { /// assert_eq!(p.len(), 3); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn len(&self) -> usize { self.coords.len() } @@ -212,6 +215,7 @@ impl Point { /// assert!(!p.is_empty()); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn is_empty(&self) -> bool { self.len() == 0 } @@ -246,6 +250,7 @@ impl Point { /// Gets a reference to i-th element of this point without bound-checking. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub unsafe fn get_unchecked(&self, i: usize) -> &T { self.coords.vget_unchecked(i) } @@ -378,18 +383,21 @@ impl PartialOrd for Point { impl Point { /// Computes the infimum (aka. componentwise min) of two points. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn inf(&self, other: &Self) -> Point { self.coords.inf(&other.coords).into() } /// Computes the supremum (aka. componentwise max) of two points. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn sup(&self, other: &Self) -> Point { self.coords.sup(&other.coords).into() } /// Computes the (infimum, supremum) of two points. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn inf_sup(&self, other: &Self) -> (Point, Point) { let (inf, sup) = self.coords.inf_sup(&other.coords); (inf.into(), sup.into()) diff --git a/src/geometry/quaternion.rs b/src/geometry/quaternion.rs index 6852335b..79bca5ac 100755 --- a/src/geometry/quaternion.rs +++ b/src/geometry/quaternion.rs @@ -191,6 +191,7 @@ where /// The imaginary part of this quaternion. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn imag(&self) -> Vector3 { self.coords.xyz() } @@ -223,6 +224,7 @@ where /// assert_eq!(q1.lerp(&q2, 0.1), Quaternion::new(1.9, 3.8, 5.7, 7.6)); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn lerp(&self, other: &Self, t: T) -> Self { self * (T::one() - t) + other * t } @@ -238,6 +240,7 @@ where /// assert_eq!(q.vector()[2], 4.0); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn vector(&self) -> MatrixSlice, CStride> { self.coords.fixed_rows::<3>(0) } @@ -251,6 +254,7 @@ where /// assert_eq!(q.scalar(), 1.0); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn scalar(&self) -> T { self.coords[3] } @@ -266,6 +270,7 @@ where /// assert_eq!(*q.as_vector(), Vector4::new(2.0, 3.0, 4.0, 1.0)); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn as_vector(&self) -> &Vector4 { &self.coords } @@ -280,6 +285,7 @@ where /// assert_relative_eq!(q.norm(), 5.47722557, epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn norm(&self) -> T { self.coords.norm() } @@ -297,6 +303,7 @@ where /// assert_relative_eq!(q.magnitude(), 5.47722557, epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn magnitude(&self) -> T { self.norm() } @@ -310,6 +317,7 @@ where /// assert_eq!(q.magnitude_squared(), 30.0); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn norm_squared(&self) -> T { self.coords.norm_squared() } @@ -326,6 +334,7 @@ where /// assert_eq!(q.magnitude_squared(), 30.0); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn magnitude_squared(&self) -> T { self.norm_squared() } @@ -340,6 +349,7 @@ where /// assert_eq!(q1.dot(&q2), 70.0); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn dot(&self, rhs: &Self) -> T { self.coords.dot(&rhs.coords) } @@ -409,6 +419,7 @@ where /// let result = a.inner(&b); /// assert_relative_eq!(expected, result, epsilon = 1.0e-5); #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn inner(&self, other: &Self) -> Self { (self * other + other * self).half() } @@ -428,6 +439,7 @@ where /// assert_relative_eq!(expected, result, epsilon = 1.0e-5); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn outer(&self, other: &Self) -> Self { #[allow(clippy::eq_op)] (self * other - other * self).half() @@ -448,6 +460,7 @@ where /// assert_relative_eq!(expected, result, epsilon = 1.0e-5); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn project(&self, other: &Self) -> Option where T: RealField, @@ -470,6 +483,7 @@ where /// assert_relative_eq!(expected, result, epsilon = 1.0e-5); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn reject(&self, other: &Self) -> Option where T: RealField, @@ -492,6 +506,7 @@ where /// assert_eq!(half_ang, f32::consts::FRAC_PI_2); /// assert_eq!(axis, Some(Vector3::x_axis())); /// ``` + #[must_use = "This function does not mutate self. You should use the return value."] pub fn polar_decomposition(&self) -> (T, T, Option>>) where T: RealField, @@ -519,6 +534,7 @@ where /// assert_relative_eq!(q.ln(), Quaternion::new(1.683647, 1.190289, 0.0, 0.0), epsilon = 1.0e-6) /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn ln(&self) -> Self { let n = self.norm(); let v = self.vector(); @@ -537,6 +553,7 @@ where /// assert_relative_eq!(q.exp(), Quaternion::new(2.0, 5.0, 0.0, 0.0), epsilon = 1.0e-5) /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn exp(&self) -> Self { self.exp_eps(T::simd_default_epsilon()) } @@ -556,6 +573,7 @@ where /// assert_eq!(q.exp_eps(1.0e-6), Quaternion::identity()); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn exp_eps(&self, eps: T) -> Self { let v = self.vector(); let nn = v.norm_squared(); @@ -579,6 +597,7 @@ where /// assert_relative_eq!(q.powf(1.5), Quaternion::new( -6.2576659, 4.1549037, 6.2323556, 8.3098075), epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn powf(&self, n: T) -> Self { (self.ln() * n).exp() } @@ -674,18 +693,21 @@ where /// Calculates square of a quaternion. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn squared(&self) -> Self { self * self } /// Divides quaternion into two. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn half(&self) -> Self { self / crate::convert(2.0f64) } /// Calculates square root. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn sqrt(&self) -> Self { self.powf(crate::convert(0.5)) } @@ -694,12 +716,14 @@ where /// /// A quaternion is pure if it has no real part (`self.w == 0.0`). #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn is_pure(&self) -> bool { self.w.is_zero() } /// Convert quaternion to pure quaternion. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn pure(&self) -> Self { Self::from_imag(self.imag()) } @@ -708,6 +732,7 @@ where /// /// Calculates B-1 * A where A = self, B = other. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn left_div(&self, other: &Self) -> Option where T: RealField, @@ -730,6 +755,7 @@ where /// assert_relative_eq!(expected, result, epsilon = 1.0e-7); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn right_div(&self, other: &Self) -> Option where T: RealField, @@ -749,6 +775,7 @@ where /// assert_relative_eq!(expected, result, epsilon = 1.0e-7); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn cos(&self) -> Self { let z = self.imag().magnitude(); let w = -self.w.simd_sin() * z.simd_sinhc(); @@ -766,6 +793,7 @@ where /// assert_relative_eq!(input, result, epsilon = 1.0e-7); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn acos(&self) -> Self { let u = Self::from_imag(self.imag().normalize()); let identity = Self::identity(); @@ -787,6 +815,7 @@ where /// assert_relative_eq!(expected, result, epsilon = 1.0e-7); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn sin(&self) -> Self { let z = self.imag().magnitude(); let w = self.w.simd_cos() * z.simd_sinhc(); @@ -804,6 +833,7 @@ where /// assert_relative_eq!(input, result, epsilon = 1.0e-7); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn asin(&self) -> Self { let u = Self::from_imag(self.imag().normalize()); let identity = Self::identity(); @@ -825,6 +855,7 @@ where /// assert_relative_eq!(expected, result, epsilon = 1.0e-7); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn tan(&self) -> Self where T: RealField, @@ -843,6 +874,7 @@ where /// assert_relative_eq!(input, result, epsilon = 1.0e-7); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn atan(&self) -> Self where T: RealField, @@ -867,6 +899,7 @@ where /// assert_relative_eq!(expected, result, epsilon = 1.0e-7); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn sinh(&self) -> Self { (self.exp() - (-self).exp()).half() } @@ -883,6 +916,7 @@ where /// assert_relative_eq!(expected, result, epsilon = 1.0e-7); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn asinh(&self) -> Self { let identity = Self::identity(); (self + (identity + self.squared()).sqrt()).ln() @@ -900,6 +934,7 @@ where /// assert_relative_eq!(expected, result, epsilon = 1.0e-7); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn cosh(&self) -> Self { (self.exp() + (-self).exp()).half() } @@ -916,6 +951,7 @@ where /// assert_relative_eq!(expected, result, epsilon = 1.0e-7); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn acosh(&self) -> Self { let identity = Self::identity(); (self + (self + identity).sqrt() * (self - identity).sqrt()).ln() @@ -933,6 +969,7 @@ where /// assert_relative_eq!(expected, result, epsilon = 1.0e-7); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn tanh(&self) -> Self where T: RealField, @@ -952,6 +989,7 @@ where /// assert_relative_eq!(expected, result, epsilon = 1.0e-7); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn atanh(&self) -> Self { let identity = Self::identity(); ((identity + self).ln() - (identity - self).ln()).half() @@ -1069,6 +1107,7 @@ where /// assert_eq!(rot.angle(), 1.78); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn angle(&self) -> T { let w = self.quaternion().scalar().simd_abs(); self.quaternion().imag().norm().simd_atan2(w) * crate::convert(2.0f64) @@ -1085,6 +1124,7 @@ where /// assert_eq!(*axis.quaternion(), Quaternion::new(1.0, 0.0, 0.0, 0.0)); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn quaternion(&self) -> &Quaternion { self.as_ref() } @@ -1133,6 +1173,7 @@ where /// assert_relative_eq!(rot1.angle_to(&rot2), 1.0045657, epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn angle_to(&self, other: &Self) -> T { let delta = self.rotation_to(other); delta.angle() @@ -1152,6 +1193,7 @@ where /// assert_relative_eq!(rot_to * rot1, rot2, epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn rotation_to(&self, other: &Self) -> Self { other / self } @@ -1168,6 +1210,7 @@ where /// assert_eq!(q1.lerp(&q2, 0.1), Quaternion::new(0.9, 0.1, 0.0, 0.0)); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn lerp(&self, other: &Self, t: T) -> Quaternion { self.as_ref().lerp(other.as_ref(), t) } @@ -1184,6 +1227,7 @@ where /// assert_eq!(q1.nlerp(&q2, 0.1), UnitQuaternion::new_normalize(Quaternion::new(0.9, 0.1, 0.0, 0.0))); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn nlerp(&self, other: &Self, t: T) -> Self { let mut res = self.lerp(other, t); let _ = res.normalize_mut(); @@ -1209,6 +1253,7 @@ where /// assert_eq!(q.euler_angles(), (std::f32::consts::FRAC_PI_2, 0.0, 0.0)); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn slerp(&self, other: &Self, t: T) -> Self where T: RealField, @@ -1228,6 +1273,7 @@ where /// * `epsilon`: the value below which the sinus of the angle separating both quaternion /// must be to return `None`. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn try_slerp(&self, other: &Self, t: T, epsilon: T) -> Option where T: RealField, @@ -1287,6 +1333,7 @@ where /// assert!(rot.axis().is_none()); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn axis(&self) -> Option>> where T: RealField, @@ -1311,6 +1358,7 @@ where /// assert_relative_eq!(rot.scaled_axis(), axisangle, epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn scaled_axis(&self) -> Vector3 where T: RealField, @@ -1339,6 +1387,7 @@ where /// assert!(rot.axis_angle().is_none()); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn axis_angle(&self) -> Option<(Unit>, T)> where T: RealField, @@ -1350,6 +1399,7 @@ where /// /// Note that this function yields a `Quaternion` because it loses the unit property. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn exp(&self) -> Quaternion { self.as_ref().exp() } @@ -1369,6 +1419,7 @@ where /// assert_relative_eq!(q.ln().vector().into_owned(), axisangle, epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn ln(&self) -> Quaternion where T: RealField, @@ -1397,6 +1448,7 @@ where /// assert_eq!(pow.angle(), 2.4); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn powf(&self, n: T) -> Self where T: RealField, @@ -1425,6 +1477,7 @@ where /// assert_relative_eq!(*rot.matrix(), expected, epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn to_rotation_matrix(&self) -> Rotation { let i = self.as_ref()[0]; let j = self.as_ref()[1]; @@ -1482,6 +1535,7 @@ where /// assert_relative_eq!(euler.2, 0.3, epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn euler_angles(&self) -> (T, T, T) where T: RealField, @@ -1506,6 +1560,7 @@ where /// assert_relative_eq!(rot.to_homogeneous(), expected, epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn to_homogeneous(&self) -> Matrix4 { self.to_rotation_matrix().to_homogeneous() } @@ -1526,6 +1581,7 @@ where /// assert_relative_eq!(transformed_point, Point3::new(3.0, 2.0, -1.0), epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn transform_point(&self, pt: &Point3) -> Point3 { self * pt } @@ -1546,6 +1602,7 @@ where /// assert_relative_eq!(transformed_vector, Vector3::new(3.0, 2.0, -1.0), epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn transform_vector(&self, v: &Vector3) -> Vector3 { self * v } @@ -1566,6 +1623,7 @@ where /// assert_relative_eq!(transformed_point, Point3::new(-3.0, 2.0, 1.0), epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn inverse_transform_point(&self, pt: &Point3) -> Point3 { // TODO: would it be useful performancewise not to call inverse explicitly (i-e. implement // the inverse transformation explicitly here) ? @@ -1588,6 +1646,7 @@ where /// assert_relative_eq!(transformed_vector, Vector3::new(-3.0, 2.0, 1.0), epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn inverse_transform_vector(&self, v: &Vector3) -> Vector3 { self.inverse() * v } @@ -1608,6 +1667,7 @@ where /// assert_relative_eq!(transformed_vector, -Vector3::y_axis(), epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn inverse_transform_unit_vector(&self, v: &Unit>) -> Unit> { self.inverse() * v } @@ -1616,6 +1676,7 @@ where /// /// This is faster, but approximate, way to compute `UnitQuaternion::new(axisangle) * self`. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn append_axisangle_linearized(&self, axisangle: &Vector3) -> Self { let half: T = crate::convert(0.5); let q1 = self.into_inner(); diff --git a/src/geometry/reflection.rs b/src/geometry/reflection.rs index e48c700a..7a34d972 100644 --- a/src/geometry/reflection.rs +++ b/src/geometry/reflection.rs @@ -34,6 +34,7 @@ impl> Reflection { } /// The reflexion axis. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn axis(&self) -> &Vector { &self.axis } diff --git a/src/geometry/rotation.rs b/src/geometry/rotation.rs index 7b4d609a..9950568d 100755 --- a/src/geometry/rotation.rs +++ b/src/geometry/rotation.rs @@ -185,6 +185,7 @@ impl Rotation { /// assert_eq!(*rot.matrix(), expected); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn matrix(&self) -> &SMatrix { &self.matrix } @@ -262,6 +263,7 @@ impl Rotation { /// assert_eq!(rot.to_homogeneous(), expected); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn to_homogeneous(&self) -> OMatrix, U1>, DimNameSum, U1>> where T: Zero + One, @@ -403,6 +405,7 @@ where /// assert_relative_eq!(transformed_point, Point3::new(3.0, 2.0, -1.0), epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn transform_point(&self, pt: &Point) -> Point { self * pt } @@ -422,6 +425,7 @@ where /// assert_relative_eq!(transformed_vector, Vector3::new(3.0, 2.0, -1.0), epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn transform_vector(&self, v: &SVector) -> SVector { self * v } @@ -441,6 +445,7 @@ where /// assert_relative_eq!(transformed_point, Point3::new(-3.0, 2.0, 1.0), epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn inverse_transform_point(&self, pt: &Point) -> Point { Point::from(self.inverse_transform_vector(&pt.coords)) } @@ -460,6 +465,7 @@ where /// assert_relative_eq!(transformed_vector, Vector3::new(-3.0, 2.0, 1.0), epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn inverse_transform_vector(&self, v: &SVector) -> SVector { self.matrix().tr_mul(v) } @@ -479,6 +485,7 @@ where /// assert_relative_eq!(transformed_vector, -Vector3::y_axis(), epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn inverse_transform_unit_vector(&self, v: &Unit>) -> Unit> { Unit::new_unchecked(self.inverse_transform_vector(&**v)) } diff --git a/src/geometry/rotation_interpolation.rs b/src/geometry/rotation_interpolation.rs index bf1c9094..6c724b21 100644 --- a/src/geometry/rotation_interpolation.rs +++ b/src/geometry/rotation_interpolation.rs @@ -18,6 +18,7 @@ impl Rotation2 { /// assert_relative_eq!(rot.angle(), std::f32::consts::FRAC_PI_2); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn slerp(&self, other: &Self, t: T) -> Self where T::Element: SimdRealField, @@ -47,6 +48,7 @@ impl Rotation3 { /// assert_eq!(q.euler_angles(), (std::f32::consts::FRAC_PI_2, 0.0, 0.0)); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn slerp(&self, other: &Self, t: T) -> Self where T: RealField, @@ -67,6 +69,7 @@ impl Rotation3 { /// * `epsilon`: the value below which the sinus of the angle separating both rotations /// must be to return `None`. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn try_slerp(&self, other: &Self, t: T, epsilon: T) -> Option where T: RealField, diff --git a/src/geometry/rotation_specialization.rs b/src/geometry/rotation_specialization.rs index bb71f4f8..4000e239 100644 --- a/src/geometry/rotation_specialization.rs +++ b/src/geometry/rotation_specialization.rs @@ -186,6 +186,7 @@ impl Rotation2 { /// assert_relative_eq!(rot_to.inverse() * rot2, rot1); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn rotation_to(&self, other: &Self) -> Self { other * self.inverse() } @@ -215,6 +216,7 @@ impl Rotation2 { /// assert_relative_eq!(pow.angle(), 2.0 * 0.78); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn powf(&self, n: T) -> Self { Self::new(self.angle() * n) } @@ -232,6 +234,7 @@ impl Rotation2 { /// assert_relative_eq!(rot.angle(), 1.78); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn angle(&self) -> T { self.matrix()[(1, 0)].simd_atan2(self.matrix()[(0, 0)]) } @@ -247,6 +250,7 @@ impl Rotation2 { /// assert_relative_eq!(rot1.angle_to(&rot2), 1.6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn angle_to(&self, other: &Self) -> T { self.rotation_to(other).angle() } @@ -256,6 +260,7 @@ impl Rotation2 { /// This is generally used in the context of generic programming. Using /// the `.angle()` method instead is more common. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn scaled_axis(&self) -> SVector { Vector1::new(self.angle()) } @@ -640,6 +645,7 @@ where /// assert_relative_eq!(rot_to * rot1, rot2, epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn rotation_to(&self, other: &Self) -> Self { other * self.inverse() } @@ -659,6 +665,7 @@ where /// assert_eq!(pow.angle(), 2.4); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn powf(&self, n: T) -> Self where T: RealField, @@ -765,6 +772,7 @@ impl Rotation3 { /// assert_relative_eq!(rot.angle(), 1.78); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn angle(&self) -> T { ((self.matrix()[(0, 0)] + self.matrix()[(1, 1)] + self.matrix()[(2, 2)] - T::one()) / crate::convert(2.0)) @@ -787,6 +795,7 @@ impl Rotation3 { /// assert!(rot.axis().is_none()); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn axis(&self) -> Option>> where T: RealField, @@ -811,6 +820,7 @@ impl Rotation3 { /// assert_relative_eq!(rot.scaled_axis(), axisangle, epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn scaled_axis(&self) -> Vector3 where T: RealField, @@ -842,6 +852,7 @@ impl Rotation3 { /// assert!(rot.axis_angle().is_none()); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn axis_angle(&self) -> Option<(Unit>, T)> where T: RealField, @@ -864,6 +875,7 @@ impl Rotation3 { /// assert_relative_eq!(rot1.angle_to(&rot2), 1.0045657, epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn angle_to(&self, other: &Self) -> T where T::Element: SimdRealField, @@ -896,6 +908,7 @@ impl Rotation3 { /// assert_relative_eq!(euler.1, 0.2, epsilon = 1.0e-6); /// assert_relative_eq!(euler.2, 0.3, epsilon = 1.0e-6); /// ``` + #[must_use = "This function does not mutate self. You should use the return value."] pub fn euler_angles(&self) -> (T, T, T) where T: RealField, diff --git a/src/geometry/similarity.rs b/src/geometry/similarity.rs index b6e2c379..6a1fe095 100755 --- a/src/geometry/similarity.rs +++ b/src/geometry/similarity.rs @@ -122,6 +122,7 @@ where impl Similarity { /// The scaling factor of this similarity transformation. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn scaling(&self) -> T { self.scaling.inlined_clone() } @@ -248,6 +249,7 @@ where /// assert_relative_eq!(transformed_point, Point3::new(19.0, 17.0, -9.0), epsilon = 1.0e-5); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn transform_point(&self, pt: &Point) -> Point { self * pt } @@ -269,6 +271,7 @@ where /// assert_relative_eq!(transformed_vector, Vector3::new(18.0, 15.0, -12.0), epsilon = 1.0e-5); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn transform_vector(&self, v: &SVector) -> SVector { self * v } @@ -289,6 +292,7 @@ where /// assert_relative_eq!(transformed_point, Point3::new(-1.5, 1.5, 1.5), epsilon = 1.0e-5); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn inverse_transform_point(&self, pt: &Point) -> Point { self.isometry.inverse_transform_point(pt) / self.scaling() } @@ -309,6 +313,7 @@ where /// assert_relative_eq!(transformed_vector, Vector3::new(-3.0, 2.5, 2.0), epsilon = 1.0e-5); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn inverse_transform_vector(&self, v: &SVector) -> SVector { self.isometry.inverse_transform_vector(v) / self.scaling() } @@ -321,6 +326,7 @@ where impl Similarity { /// Converts this similarity into its equivalent homogeneous transformation matrix. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn to_homogeneous(&self) -> OMatrix, U1>, DimNameSum, U1>> where Const: DimNameAdd, diff --git a/src/geometry/swizzle.rs b/src/geometry/swizzle.rs index 6e4c6df8..74f423ff 100644 --- a/src/geometry/swizzle.rs +++ b/src/geometry/swizzle.rs @@ -8,6 +8,7 @@ macro_rules! impl_swizzle { $( /// Builds a new point from components of `self`. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn $name(&self) -> $Result where as ToTypenum>::Typenum: Cmp { $Result::new($(self[$i].inlined_clone()),*) diff --git a/src/geometry/transform.rs b/src/geometry/transform.rs index c7fce902..a62c5ede 100755 --- a/src/geometry/transform.rs +++ b/src/geometry/transform.rs @@ -301,6 +301,7 @@ where /// assert_eq!(*t.matrix(), m); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn matrix(&self) -> &OMatrix, U1>, DimNameSum, U1>> { &self.matrix } @@ -367,6 +368,7 @@ where /// assert_eq!(t.into_inner(), m); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn to_homogeneous(&self) -> OMatrix, U1>, DimNameSum, U1>> { self.matrix().clone_owned() } @@ -498,6 +500,7 @@ where /// /// This is the same as the multiplication `self * pt`. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn transform_point(&self, pt: &Point) -> Point { self * pt } @@ -507,6 +510,7 @@ where /// /// This is the same as the multiplication `self * v`. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn transform_vector(&self, v: &SVector) -> SVector { self * v } @@ -524,6 +528,7 @@ where /// This may be cheaper than inverting the transformation and transforming /// the point. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn inverse_transform_point(&self, pt: &Point) -> Point { self.clone().inverse() * pt } @@ -532,6 +537,7 @@ where /// This may be cheaper than inverting the transformation and transforming /// the vector. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn inverse_transform_vector(&self, v: &SVector) -> SVector { self.clone().inverse() * v } diff --git a/src/geometry/translation.rs b/src/geometry/translation.rs index dcb7b603..98ee4636 100755 --- a/src/geometry/translation.rs +++ b/src/geometry/translation.rs @@ -190,6 +190,7 @@ impl Translation { /// assert_eq!(t.to_homogeneous(), expected); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn to_homogeneous(&self) -> OMatrix, U1>, DimNameSum, U1>> where T: Zero + One, @@ -241,6 +242,7 @@ impl Translation { /// let transformed_point = t.transform_point(&Point3::new(4.0, 5.0, 6.0)); /// assert_eq!(transformed_point, Point3::new(5.0, 7.0, 9.0)); #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn transform_point(&self, pt: &Point) -> Point { pt + &self.vector } @@ -256,6 +258,7 @@ impl Translation { /// let transformed_point = t.inverse_transform_point(&Point3::new(4.0, 5.0, 6.0)); /// assert_eq!(transformed_point, Point3::new(3.0, 3.0, 3.0)); #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn inverse_transform_point(&self, pt: &Point) -> Point { pt - &self.vector } diff --git a/src/geometry/unit_complex.rs b/src/geometry/unit_complex.rs index fe2e87ba..414ca425 100755 --- a/src/geometry/unit_complex.rs +++ b/src/geometry/unit_complex.rs @@ -84,6 +84,7 @@ where /// assert_eq!(rot.angle(), 1.78); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn angle(&self) -> T { self.im.simd_atan2(self.re) } @@ -98,6 +99,7 @@ where /// assert_eq!(rot.sin_angle(), angle.sin()); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn sin_angle(&self) -> T { self.im } @@ -112,6 +114,7 @@ where /// assert_eq!(rot.cos_angle(),angle.cos()); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn cos_angle(&self) -> T { self.re } @@ -121,6 +124,7 @@ where /// This is generally used in the context of generic programming. Using /// the `.angle()` method instead is more common. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn scaled_axis(&self) -> Vector1 { Vector1::new(self.angle()) } @@ -131,6 +135,7 @@ where /// the `.angle()` method instead is more common. /// Returns `None` if the angle is zero. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn axis_angle(&self) -> Option<(Unit>, T)> where T: RealField, @@ -157,6 +162,7 @@ where /// assert_relative_eq!(rot1.angle_to(&rot2), 1.6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn angle_to(&self, other: &Self) -> T { let delta = self.rotation_to(other); delta.angle() @@ -254,6 +260,7 @@ where /// assert_eq!(rot.to_rotation_matrix(), expected); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn to_rotation_matrix(&self) -> Rotation2 { let r = self.re; let i = self.im; @@ -274,6 +281,7 @@ where /// assert_eq!(rot.to_homogeneous(), expected); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn to_homogeneous(&self) -> Matrix3 { self.to_rotation_matrix().to_homogeneous() } @@ -298,6 +306,7 @@ where /// assert_relative_eq!(transformed_point, Point2::new(-2.0, 1.0), epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn transform_point(&self, pt: &Point2) -> Point2 { self * pt } @@ -316,6 +325,7 @@ where /// assert_relative_eq!(transformed_vector, Vector2::new(-2.0, 1.0), epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn transform_vector(&self, v: &Vector2) -> Vector2 { self * v } @@ -332,6 +342,7 @@ where /// assert_relative_eq!(transformed_point, Point2::new(2.0, -1.0), epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn inverse_transform_point(&self, pt: &Point2) -> Point2 { // TODO: would it be useful performancewise not to call inverse explicitly (i-e. implement // the inverse transformation explicitly here) ? @@ -350,6 +361,7 @@ where /// assert_relative_eq!(transformed_vector, Vector2::new(2.0, -1.0), epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn inverse_transform_vector(&self, v: &Vector2) -> Vector2 { self.inverse() * v } @@ -366,6 +378,7 @@ where /// assert_relative_eq!(transformed_vector, -Vector2::y_axis(), epsilon = 1.0e-6); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn inverse_transform_unit_vector(&self, v: &Unit>) -> Unit> { self.inverse() * v } @@ -392,6 +405,7 @@ where /// assert_relative_eq!(rot.angle(), std::f32::consts::FRAC_PI_2); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn slerp(&self, other: &Self, t: T) -> Self { Self::new(self.angle() * (T::one() - t) + other.angle() * t) } diff --git a/src/geometry/unit_complex_construction.rs b/src/geometry/unit_complex_construction.rs index 62a9b416..6a3ad6de 100644 --- a/src/geometry/unit_complex_construction.rs +++ b/src/geometry/unit_complex_construction.rs @@ -148,6 +148,7 @@ where /// assert_eq!(*rot.complex(), Complex::new(angle.cos(), angle.sin())); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn complex(&self) -> &Complex { self.as_ref() } @@ -244,6 +245,7 @@ where /// assert_relative_eq!(rot_to.inverse() * rot2, rot1); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn rotation_to(&self, other: &Self) -> Self { other / self } @@ -262,6 +264,7 @@ where /// assert_relative_eq!(pow.angle(), 2.0 * 0.78); /// ``` #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn powf(&self, n: T) -> Self { Self::from_angle(self.angle() * n) } diff --git a/src/linalg/bidiagonal.rs b/src/linalg/bidiagonal.rs index a125ce18..d8997196 100644 --- a/src/linalg/bidiagonal.rs +++ b/src/linalg/bidiagonal.rs @@ -153,6 +153,7 @@ where /// Indicates whether this decomposition contains an upper-diagonal matrix. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn is_upper_diagonal(&self) -> bool { self.upper_diagonal } @@ -188,6 +189,7 @@ where /// Retrieves the upper trapezoidal submatrix `R` of this decomposition. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn d(&self) -> OMatrix, DimMinimum> where DefaultAllocator: Allocator, DimMinimum>, @@ -207,6 +209,7 @@ where /// Computes the orthogonal matrix `U` of this `U * D * V` decomposition. // TODO: code duplication with householder::assemble_q. // Except that we are returning a rectangular matrix here. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn u(&self) -> OMatrix> where DefaultAllocator: Allocator>, @@ -237,6 +240,7 @@ where } /// Computes the orthogonal matrix `V_t` of this `U * D * V_t` decomposition. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn v_t(&self) -> OMatrix, C> where DefaultAllocator: Allocator, C>, @@ -274,6 +278,7 @@ where } /// The diagonal part of this decomposed matrix. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn diagonal(&self) -> OVector> where DefaultAllocator: Allocator>, @@ -282,6 +287,7 @@ where } /// The off-diagonal part of this decomposed matrix. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn off_diagonal(&self) -> OVector, U1>> where DefaultAllocator: Allocator, U1>>, diff --git a/src/linalg/cholesky.rs b/src/linalg/cholesky.rs index fa090852..60f1f0f5 100644 --- a/src/linalg/cholesky.rs +++ b/src/linalg/cholesky.rs @@ -92,6 +92,7 @@ where /// Retrieves the lower-triangular factor of the Cholesky decomposition with its strictly /// uppen-triangular part filled with zeros. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn l(&self) -> OMatrix { self.chol.lower_triangle() } @@ -101,6 +102,7 @@ where /// /// This is an allocation-less version of `self.l()`. The values of the strict upper-triangular /// part are garbage and should be ignored by further computations. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn l_dirty(&self) -> &OMatrix { &self.chol } @@ -142,6 +144,7 @@ where } /// Computes the determinant of the decomposed matrix. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn determinant(&self) -> T::SimdRealField { let dim = self.chol.nrows(); let mut prod_diag = T::one(); @@ -289,6 +292,7 @@ where /// Updates the decomposition such that we get the decomposition of the factored matrix with its `j`th column removed. /// Since the matrix is square, the `j`th row will also be removed. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn remove_column(&self, j: usize) -> Cholesky> where D: DimSub, diff --git a/src/linalg/col_piv_qr.rs b/src/linalg/col_piv_qr.rs index 3640785d..e48263fd 100644 --- a/src/linalg/col_piv_qr.rs +++ b/src/linalg/col_piv_qr.rs @@ -95,6 +95,7 @@ where /// Retrieves the upper trapezoidal submatrix `R` of this decomposition. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn r(&self) -> OMatrix, C> where DefaultAllocator: Allocator, C>, @@ -126,6 +127,7 @@ where } /// Computes the orthogonal matrix `Q` of this decomposition. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn q(&self) -> OMatrix> where DefaultAllocator: Allocator>, @@ -150,6 +152,7 @@ where } /// Retrieves the column permutation of this decomposition. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn p(&self) -> &PermutationSequence> { &self.p } @@ -284,6 +287,7 @@ where /// Computes the inverse of the decomposed matrix. /// /// Returns `None` if the decomposed matrix is not invertible. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn try_inverse(&self) -> Option> { assert!( self.col_piv_qr.is_square(), @@ -302,6 +306,7 @@ where } /// Indicates if the decomposed matrix is invertible. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn is_invertible(&self) -> bool { assert!( self.col_piv_qr.is_square(), @@ -318,6 +323,7 @@ where } /// Computes the determinant of the decomposed matrix. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn determinant(&self) -> T { let dim = self.col_piv_qr.nrows(); assert!( diff --git a/src/linalg/convolution.rs b/src/linalg/convolution.rs index 2729b66b..075b3508 100644 --- a/src/linalg/convolution.rs +++ b/src/linalg/convolution.rs @@ -112,6 +112,7 @@ impl> Vector { /// /// # Errors /// Inputs must satisfy `self.len() >= kernel.len() > 0`. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn convolve_same(&self, kernel: Vector) -> OVector where D2: Dim, diff --git a/src/linalg/determinant.rs b/src/linalg/determinant.rs index aa04ff3f..43478261 100644 --- a/src/linalg/determinant.rs +++ b/src/linalg/determinant.rs @@ -12,6 +12,7 @@ impl, S: Storage> SquareMatri /// /// If the matrix has a dimension larger than 3, an LU decomposition is used. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn determinant(&self) -> T where DefaultAllocator: Allocator + Allocator<(usize, usize), D>, diff --git a/src/linalg/full_piv_lu.rs b/src/linalg/full_piv_lu.rs index af9609de..9ce6c24d 100644 --- a/src/linalg/full_piv_lu.rs +++ b/src/linalg/full_piv_lu.rs @@ -96,6 +96,7 @@ where /// The lower triangular matrix of this decomposition. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn l(&self) -> OMatrix> where DefaultAllocator: Allocator>, @@ -109,6 +110,7 @@ where /// The upper triangular matrix of this decomposition. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn u(&self) -> OMatrix, C> where DefaultAllocator: Allocator, C>, @@ -119,12 +121,14 @@ where /// The row permutations of this decomposition. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn p(&self) -> &PermutationSequence> { &self.p } /// The column permutations of this decomposition. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn q(&self) -> &PermutationSequence> { &self.q } @@ -211,6 +215,7 @@ where /// Computes the inverse of the decomposed matrix. /// /// Returns `None` if the decomposed matrix is not invertible. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn try_inverse(&self) -> Option> { assert!( self.lu.is_square(), @@ -228,6 +233,7 @@ where } /// Indicates if the decomposed matrix is invertible. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn is_invertible(&self) -> bool { assert!( self.lu.is_square(), @@ -239,6 +245,7 @@ where } /// Computes the determinant of the decomposed matrix. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn determinant(&self) -> T { assert!( self.lu.is_square(), diff --git a/src/linalg/givens.rs b/src/linalg/givens.rs index 9a65f331..e555cbfb 100644 --- a/src/linalg/givens.rs +++ b/src/linalg/givens.rs @@ -89,11 +89,13 @@ impl GivensRotation { } /// The cos part of this roration. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn c(&self) -> T::RealField { self.c } /// The sin part of this roration. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn s(&self) -> T { self.s } diff --git a/src/linalg/hessenberg.rs b/src/linalg/hessenberg.rs index be6f667c..e6201685 100644 --- a/src/linalg/hessenberg.rs +++ b/src/linalg/hessenberg.rs @@ -116,6 +116,7 @@ where /// /// This is less efficient than `.unpack_h()` as it allocates a new matrix. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn h(&self) -> OMatrix { let dim = self.hess.nrows(); let mut res = self.hess.clone(); @@ -126,6 +127,7 @@ where } /// Computes the orthogonal matrix `Q` of this decomposition. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn q(&self) -> OMatrix { householder::assemble_q(&self.hess, self.subdiag.as_slice()) } diff --git a/src/linalg/lu.rs b/src/linalg/lu.rs index 855a53f7..0c5dfe15 100644 --- a/src/linalg/lu.rs +++ b/src/linalg/lu.rs @@ -127,6 +127,7 @@ where /// The lower triangular matrix of this decomposition. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn l(&self) -> OMatrix> where DefaultAllocator: Allocator>, @@ -170,6 +171,7 @@ where /// The upper triangular matrix of this decomposition. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn u(&self) -> OMatrix, C> where DefaultAllocator: Allocator, C>, @@ -180,6 +182,7 @@ where /// The row permutations of this decomposition. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn p(&self) -> &PermutationSequence> { &self.p } @@ -258,6 +261,7 @@ where /// Computes the inverse of the decomposed matrix. /// /// Returns `None` if the matrix is not invertible. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn try_inverse(&self) -> Option> { assert!( self.lu.is_square(), @@ -292,6 +296,7 @@ where } /// Computes the determinant of the decomposed matrix. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn determinant(&self) -> T { let dim = self.lu.nrows(); assert!( @@ -308,6 +313,7 @@ where } /// Indicates if the decomposed matrix is invertible. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn is_invertible(&self) -> bool { assert!( self.lu.is_square(), diff --git a/src/linalg/permutation_sequence.rs b/src/linalg/permutation_sequence.rs index 4cc8cb25..a852f0c9 100644 --- a/src/linalg/permutation_sequence.rs +++ b/src/linalg/permutation_sequence.rs @@ -140,17 +140,20 @@ where } /// The number of non-identity permutations applied by this sequence. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn len(&self) -> usize { self.len } /// Returns true if the permutation sequence contains no elements. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn is_empty(&self) -> bool { self.len() == 0 } /// The determinant of the matrix corresponding to this permutation. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn determinant(&self) -> T { if self.len % 2 == 0 { T::one() diff --git a/src/linalg/qr.rs b/src/linalg/qr.rs index a0fd898e..2fa308ff 100644 --- a/src/linalg/qr.rs +++ b/src/linalg/qr.rs @@ -70,6 +70,7 @@ where /// Retrieves the upper trapezoidal submatrix `R` of this decomposition. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn r(&self) -> OMatrix, C> where DefaultAllocator: Allocator, C>, @@ -96,6 +97,7 @@ where } /// Computes the orthogonal matrix `Q` of this decomposition. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn q(&self) -> OMatrix> where DefaultAllocator: Allocator>, @@ -244,6 +246,7 @@ where /// Computes the inverse of the decomposed matrix. /// /// Returns `None` if the decomposed matrix is not invertible. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn try_inverse(&self) -> Option> { assert!( self.qr.is_square(), @@ -262,6 +265,7 @@ where } /// Indicates if the decomposed matrix is invertible. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn is_invertible(&self) -> bool { assert!( self.qr.is_square(), diff --git a/src/linalg/schur.rs b/src/linalg/schur.rs index 1903b717..4f9271f7 100644 --- a/src/linalg/schur.rs +++ b/src/linalg/schur.rs @@ -385,6 +385,7 @@ where /// Computes the real eigenvalues of the decomposed matrix. /// /// Return `None` if some eigenvalues are complex. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn eigenvalues(&self) -> Option> { let mut out = unsafe { crate::unimplemented_or_uninitialized_generic!(self.t.data.shape().0, Const::<1>) @@ -397,6 +398,7 @@ where } /// Computes the complex eigenvalues of the decomposed matrix. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn complex_eigenvalues(&self) -> OVector, D> where T: RealField, @@ -509,6 +511,7 @@ where + Allocator, { /// Computes the eigenvalues of this matrix. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn eigenvalues(&self) -> Option> { assert!( self.is_square(), @@ -551,6 +554,7 @@ where } /// Computes the eigenvalues of this matrix. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn complex_eigenvalues(&self) -> OVector, D> // TODO: add balancing? where diff --git a/src/linalg/svd.rs b/src/linalg/svd.rs index 2f5e6a63..b579eb54 100644 --- a/src/linalg/svd.rs +++ b/src/linalg/svd.rs @@ -502,6 +502,7 @@ where /// Computes the rank of the decomposed matrix, i.e., the number of singular values greater /// than `eps`. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn rank(&self, eps: T::RealField) -> usize { assert!( eps >= T::RealField::zero(), @@ -615,6 +616,7 @@ where + Allocator, U1>>, { /// Computes the singular values of this matrix. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn singular_values(&self) -> OVector> { SVD::new(self.clone_owned(), false, false).singular_values } @@ -622,6 +624,7 @@ where /// Computes the rank of this matrix. /// /// All singular values below `eps` are considered equal to 0. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn rank(&self, eps: T::RealField) -> usize { let svd = SVD::new(self.clone_owned(), false, false); svd.rank(eps) diff --git a/src/linalg/symmetric_eigen.rs b/src/linalg/symmetric_eigen.rs index 6e3b67fe..d0409e95 100644 --- a/src/linalg/symmetric_eigen.rs +++ b/src/linalg/symmetric_eigen.rs @@ -268,6 +268,7 @@ where /// Rebuild the original matrix. /// /// This is useful if some of the eigenvalues have been manually modified. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn recompose(&self) -> OMatrix { let mut u_t = self.eigenvectors.clone(); for i in 0..self.eigenvalues.len() { @@ -311,6 +312,7 @@ where /// Computes the eigenvalues of this symmetric matrix. /// /// Only the lower-triangular part of the matrix is read. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn symmetric_eigenvalues(&self) -> OVector { SymmetricEigen::do_decompose( self.clone_owned(), diff --git a/src/linalg/symmetric_tridiagonal.rs b/src/linalg/symmetric_tridiagonal.rs index 9937f76b..82a2433b 100644 --- a/src/linalg/symmetric_tridiagonal.rs +++ b/src/linalg/symmetric_tridiagonal.rs @@ -131,6 +131,7 @@ where } /// The diagonal components of this decomposition. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn diagonal(&self) -> OVector where DefaultAllocator: Allocator, @@ -139,6 +140,7 @@ where } /// The off-diagonal components of this decomposition. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn off_diagonal(&self) -> OVector> where DefaultAllocator: Allocator>, @@ -147,6 +149,7 @@ where } /// Computes the orthogonal matrix `Q` of this decomposition. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn q(&self) -> OMatrix { householder::assemble_q(&self.tri, self.off_diagonal.as_slice()) } diff --git a/src/linalg/udu.rs b/src/linalg/udu.rs index 4d3aca6c..786e14bc 100644 --- a/src/linalg/udu.rs +++ b/src/linalg/udu.rs @@ -92,6 +92,7 @@ where } /// Returns the diagonal elements as a matrix + #[must_use = "This function does not mutate self. You should use the return value."] pub fn d_matrix(&self) -> OMatrix { OMatrix::from_diagonal(&self.d) } diff --git a/src/sparse/cs_matrix.rs b/src/sparse/cs_matrix.rs index 2dc8467e..f46dfdc2 100644 --- a/src/sparse/cs_matrix.rs +++ b/src/sparse/cs_matrix.rs @@ -119,16 +119,19 @@ where DefaultAllocator: Allocator, { /// The value buffer of this storage. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn values(&self) -> &[T] { &self.vals } /// The column shifts buffer. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn p(&self) -> &[usize] { self.p.as_slice() } /// The row index buffers. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn i(&self) -> &[usize] { &self.i } @@ -356,27 +359,32 @@ impl> CsMatrix { } /// The size of the data buffer. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn len(&self) -> usize { self.data.len() } /// The number of rows of this matrix. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn nrows(&self) -> usize { self.data.shape().0.value() } /// The number of rows of this matrix. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn ncols(&self) -> usize { self.data.shape().1.value() } /// The shape of this matrix. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn shape(&self) -> (usize, usize) { let (nrows, ncols) = self.data.shape(); (nrows.value(), ncols.value()) } /// Whether this matrix is square or not. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn is_square(&self) -> bool { let (nrows, ncols) = self.data.shape(); nrows.value() == ncols.value() @@ -391,6 +399,7 @@ impl> CsMatrix { /// If at any time this `is_sorted` method returns `false`, then, something went wrong /// and an issue should be open on the nalgebra repository with details on how to reproduce /// this. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn is_sorted(&self) -> bool { for j in 0..self.ncols() { let mut curr = None; diff --git a/src/sparse/cs_matrix_cholesky.rs b/src/sparse/cs_matrix_cholesky.rs index 4cd61d2a..5891f0ad 100644 --- a/src/sparse/cs_matrix_cholesky.rs +++ b/src/sparse/cs_matrix_cholesky.rs @@ -67,6 +67,7 @@ where } /// The lower-triangular matrix of the cholesky decomposition. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn l(&self) -> Option<&CsMatrix> { if self.ok { Some(&self.l) From 42a2c745714f3d481a1ed99119a94ac730571e92 Mon Sep 17 00:00:00 2001 From: Malte Tammena Date: Sun, 6 Jun 2021 15:28:37 +0200 Subject: [PATCH 06/42] Finish initial must_use annotations --- nalgebra-lapack/src/cholesky.rs | 2 ++ nalgebra-lapack/src/eigen.rs | 1 + nalgebra-lapack/src/hessenberg.rs | 2 ++ nalgebra-lapack/src/lu.rs | 4 ++++ nalgebra-lapack/src/qr.rs | 2 ++ nalgebra-lapack/src/schur.rs | 2 ++ nalgebra-lapack/src/svd.rs | 2 ++ nalgebra-lapack/src/symmetric_eigen.rs | 2 ++ nalgebra-sparse/src/coo.rs | 6 +++++ nalgebra-sparse/src/cs.rs | 13 +++++++++++ nalgebra-sparse/src/csc.rs | 22 +++++++++++++++++++ nalgebra-sparse/src/csr.rs | 22 +++++++++++++++++++ nalgebra-sparse/src/factorization/cholesky.rs | 3 +++ nalgebra-sparse/src/lib.rs | 1 + nalgebra-sparse/src/ops/mod.rs | 2 ++ nalgebra-sparse/src/ops/serial/mod.rs | 2 ++ nalgebra-sparse/src/pattern.rs | 9 ++++++++ 17 files changed, 97 insertions(+) diff --git a/nalgebra-lapack/src/cholesky.rs b/nalgebra-lapack/src/cholesky.rs index fbbf6fd4..b271ca51 100644 --- a/nalgebra-lapack/src/cholesky.rs +++ b/nalgebra-lapack/src/cholesky.rs @@ -80,6 +80,7 @@ where } /// Retrieves the lower-triangular factor of the cholesky decomposition. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn l(&self) -> OMatrix { let mut res = self.l.clone(); res.fill_upper_triangle(Zero::zero(), 1); @@ -91,6 +92,7 @@ where /// /// This is an allocation-less version of `self.l()`. The values of the strict upper-triangular /// part are garbage and should be ignored by further computations. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn l_dirty(&self) -> &OMatrix { &self.l } diff --git a/nalgebra-lapack/src/eigen.rs b/nalgebra-lapack/src/eigen.rs index cbe1555a..993f8987 100644 --- a/nalgebra-lapack/src/eigen.rs +++ b/nalgebra-lapack/src/eigen.rs @@ -302,6 +302,7 @@ where /// The determinant of the decomposed matrix. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn determinant(&self) -> T { let mut det = T::one(); for e in self.eigenvalues.iter() { diff --git a/nalgebra-lapack/src/hessenberg.rs b/nalgebra-lapack/src/hessenberg.rs index b025a8bf..47018004 100644 --- a/nalgebra-lapack/src/hessenberg.rs +++ b/nalgebra-lapack/src/hessenberg.rs @@ -89,6 +89,7 @@ where /// Computes the hessenberg matrix of this decomposition. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn h(&self) -> OMatrix { let mut h = self.h.clone_owned(); h.fill_lower_triangle(T::zero(), 2); @@ -109,6 +110,7 @@ where /// Computes the unitary matrix `Q` of this decomposition. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn q(&self) -> OMatrix { let n = self.h.nrows() as i32; let mut q = self.h.clone_owned(); diff --git a/nalgebra-lapack/src/lu.rs b/nalgebra-lapack/src/lu.rs index 5ca5f143..a163629d 100644 --- a/nalgebra-lapack/src/lu.rs +++ b/nalgebra-lapack/src/lu.rs @@ -85,6 +85,7 @@ where /// Gets the lower-triangular matrix part of the decomposition. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn l(&self) -> OMatrix> { let (nrows, ncols) = self.lu.data.shape(); let mut res = self.lu.columns_generic(0, nrows.min(ncols)).into_owned(); @@ -97,6 +98,7 @@ where /// Gets the upper-triangular matrix part of the decomposition. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn u(&self) -> OMatrix, C> { let (nrows, ncols) = self.lu.data.shape(); let mut res = self.lu.rows_generic(0, nrows.min(ncols)).into_owned(); @@ -111,6 +113,7 @@ where /// Computing the permutation matrix explicitly is costly and usually not necessary. /// To permute rows of a matrix or vector, use the method `self.permute(...)` instead. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn p(&self) -> OMatrix { let (dim, _) = self.lu.data.shape(); let mut id = Matrix::identity_generic(dim, dim); @@ -124,6 +127,7 @@ where /// Gets the LAPACK permutation indices. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn permutation_indices(&self) -> &OVector> { &self.p } diff --git a/nalgebra-lapack/src/qr.rs b/nalgebra-lapack/src/qr.rs index b58c3f35..8c32b299 100644 --- a/nalgebra-lapack/src/qr.rs +++ b/nalgebra-lapack/src/qr.rs @@ -92,6 +92,7 @@ where /// Retrieves the upper trapezoidal submatrix `R` of this decomposition. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn r(&self) -> OMatrix, C> { let (nrows, ncols) = self.qr.data.shape(); self.qr.rows_generic(0, nrows.min(ncols)).upper_triangle() @@ -117,6 +118,7 @@ where /// Computes the orthogonal matrix `Q` of this decomposition. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn q(&self) -> OMatrix> { let (nrows, ncols) = self.qr.data.shape(); let min_nrows_ncols = nrows.min(ncols); diff --git a/nalgebra-lapack/src/schur.rs b/nalgebra-lapack/src/schur.rs index a850f01d..602e0ec1 100644 --- a/nalgebra-lapack/src/schur.rs +++ b/nalgebra-lapack/src/schur.rs @@ -138,6 +138,7 @@ where /// Computes the real eigenvalues of the decomposed matrix. /// /// Return `None` if some eigenvalues are complex. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn eigenvalues(&self) -> Option> { if self.im.iter().all(|e| e.is_zero()) { Some(self.re.clone()) @@ -147,6 +148,7 @@ where } /// Computes the complex eigenvalues of the decomposed matrix. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn complex_eigenvalues(&self) -> OVector, D> where DefaultAllocator: Allocator, D>, diff --git a/nalgebra-lapack/src/svd.rs b/nalgebra-lapack/src/svd.rs index f6b907b6..7256e984 100644 --- a/nalgebra-lapack/src/svd.rs +++ b/nalgebra-lapack/src/svd.rs @@ -175,6 +175,7 @@ macro_rules! svd_impl( /// /// All singular value below epsilon will be set to zero instead of being inverted. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn pseudo_inverse(&self, epsilon: $t) -> OMatrix<$t, C, R> { let nrows = self.u.data.shape().0; let ncols = self.vt.data.shape().1; @@ -207,6 +208,7 @@ macro_rules! svd_impl( /// This is the number of singular values that are not too small (i.e. greater than /// the given `epsilon`). #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn rank(&self, epsilon: $t) -> usize { let mut i = 0; diff --git a/nalgebra-lapack/src/symmetric_eigen.rs b/nalgebra-lapack/src/symmetric_eigen.rs index 0cd6bfc1..d2150598 100644 --- a/nalgebra-lapack/src/symmetric_eigen.rs +++ b/nalgebra-lapack/src/symmetric_eigen.rs @@ -138,6 +138,7 @@ where /// The determinant of the decomposed matrix. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn determinant(&self) -> T { let mut det = T::one(); for e in self.eigenvalues.iter() { @@ -150,6 +151,7 @@ where /// Rebuild the original matrix. /// /// This is useful if some of the eigenvalues have been manually modified. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn recompose(&self) -> OMatrix { let mut u_t = self.eigenvectors.clone(); for i in 0..self.eigenvalues.len() { diff --git a/nalgebra-sparse/src/coo.rs b/nalgebra-sparse/src/coo.rs index 364083a9..820e4e38 100644 --- a/nalgebra-sparse/src/coo.rs +++ b/nalgebra-sparse/src/coo.rs @@ -173,12 +173,14 @@ impl CooMatrix { /// The number of rows in the matrix. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn nrows(&self) -> usize { self.nrows } /// The number of columns in the matrix. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn ncols(&self) -> usize { self.ncols } @@ -189,21 +191,25 @@ impl CooMatrix { /// entries, then it may have a different number of non-zeros as reported by `nnz()` compared /// to its CSR representation. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn nnz(&self) -> usize { self.values.len() } /// The row indices of the explicitly stored entries. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn row_indices(&self) -> &[usize] { &self.row_indices } /// The column indices of the explicitly stored entries. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn col_indices(&self) -> &[usize] { &self.col_indices } /// The values of the explicitly stored entries. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn values(&self) -> &[T] { &self.values } diff --git a/nalgebra-sparse/src/cs.rs b/nalgebra-sparse/src/cs.rs index d6f9b229..10492801 100644 --- a/nalgebra-sparse/src/cs.rs +++ b/nalgebra-sparse/src/cs.rs @@ -32,11 +32,13 @@ impl CsMatrix { } #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn pattern(&self) -> &SparsityPattern { &self.sparsity_pattern } #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn values(&self) -> &[T] { &self.values } @@ -48,6 +50,7 @@ impl CsMatrix { /// Returns the raw data represented as a tuple `(major_offsets, minor_indices, values)`. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn cs_data(&self) -> (&[usize], &[usize], &[T]) { let pattern = self.pattern(); ( @@ -88,6 +91,7 @@ impl CsMatrix { /// Internal method for simplifying access to a lane's data #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn get_index_range(&self, row_index: usize) -> Option> { let row_begin = *self.sparsity_pattern.major_offsets().get(row_index)?; let row_end = *self.sparsity_pattern.major_offsets().get(row_index + 1)?; @@ -111,6 +115,7 @@ impl CsMatrix { /// Returns an entry for the given major/minor indices, or `None` if the indices are out /// of bounds. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn get_entry(&self, major_index: usize, minor_index: usize) -> Option> { let row_range = self.get_index_range(major_index)?; let (_, minor_indices, values) = self.cs_data(); @@ -139,6 +144,7 @@ impl CsMatrix { get_mut_entry_from_slices(minor_dim, minor_indices, values, minor_index) } + #[must_use = "This function does not mutate self. You should use the return value."] pub fn get_lane(&self, index: usize) -> Option> { let range = self.get_index_range(index)?; let (_, minor_indices, values) = self.cs_data(); @@ -172,6 +178,7 @@ impl CsMatrix { } #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn filter

(&self, predicate: P) -> Self where T: Clone, @@ -207,6 +214,7 @@ impl CsMatrix { } /// Returns the diagonal of the matrix as a sparse matrix. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn diagonal_as_matrix(&self) -> Self where T: Clone, @@ -372,26 +380,31 @@ macro_rules! impl_cs_lane_common_methods { ($name:ty) => { impl<'a, T> $name { #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn minor_dim(&self) -> usize { self.minor_dim } #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn nnz(&self) -> usize { self.minor_indices.len() } #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn minor_indices(&self) -> &[usize] { self.minor_indices } #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn values(&self) -> &[T] { self.values } #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn get_entry(&self, global_col_index: usize) -> Option> { get_entry_from_slices( self.minor_dim, diff --git a/nalgebra-sparse/src/csc.rs b/nalgebra-sparse/src/csc.rs index 6a88c1d5..e5fb9465 100644 --- a/nalgebra-sparse/src/csc.rs +++ b/nalgebra-sparse/src/csc.rs @@ -192,12 +192,14 @@ impl CscMatrix { /// The number of rows in the matrix. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn nrows(&self) -> usize { self.cs.pattern().minor_dim() } /// The number of columns in the matrix. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn ncols(&self) -> usize { self.cs.pattern().major_dim() } @@ -208,24 +210,28 @@ impl CscMatrix { /// number of algebraically zero entries in the matrix. Explicitly stored entries can still /// be zero. Corresponds to the number of entries in the sparsity pattern. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn nnz(&self) -> usize { self.pattern().nnz() } /// The column offsets defining part of the CSC format. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn col_offsets(&self) -> &[usize] { self.pattern().major_offsets() } /// The row indices defining part of the CSC format. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn row_indices(&self) -> &[usize] { self.pattern().minor_indices() } /// The non-zero values defining part of the CSC format. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn values(&self) -> &[T] { self.cs.values() } @@ -298,6 +304,7 @@ impl CscMatrix { /// ------ /// Panics if column index is out of bounds. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn col(&self, index: usize) -> CscCol { self.get_col(index).expect("Row index must be in bounds") } @@ -315,6 +322,7 @@ impl CscMatrix { /// Return the column at the given column index, or `None` if out of bounds. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn get_col(&self, index: usize) -> Option> { self.cs.get_lane(index).map(|lane| CscCol { lane }) } @@ -381,6 +389,7 @@ impl CscMatrix { } /// Returns a reference to the underlying sparsity pattern. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn pattern(&self) -> &SparsityPattern { self.cs.pattern() } @@ -397,6 +406,7 @@ impl CscMatrix { /// /// Each call to this function incurs the cost of a binary search among the explicitly /// stored row entries for the given column. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn get_entry(&self, row_index: usize, col_index: usize) -> Option> { self.cs.get_entry(col_index, row_index) } @@ -422,6 +432,7 @@ impl CscMatrix { /// Panics /// ------ /// Panics if `row_index` or `col_index` is out of bounds. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn index_entry(&self, row_index: usize, col_index: usize) -> SparseEntry { self.get_entry(row_index, col_index) .expect("Out of bounds matrix indices encountered") @@ -441,6 +452,7 @@ impl CscMatrix { } /// Returns a triplet of slices `(col_offsets, row_indices, values)` that make up the CSC data. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn csc_data(&self) -> (&[usize], &[usize], &[T]) { self.cs.cs_data() } @@ -453,6 +465,7 @@ impl CscMatrix { /// Creates a sparse matrix that contains only the explicit entries decided by the /// given predicate. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn filter

(&self, predicate: P) -> Self where T: Clone, @@ -470,6 +483,7 @@ impl CscMatrix { /// Returns a new matrix representing the upper triangular part of this matrix. /// /// The result includes the diagonal of the matrix. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn upper_triangle(&self) -> Self where T: Clone, @@ -480,6 +494,7 @@ impl CscMatrix { /// Returns a new matrix representing the lower triangular part of this matrix. /// /// The result includes the diagonal of the matrix. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn lower_triangle(&self) -> Self where T: Clone, @@ -488,6 +503,7 @@ impl CscMatrix { } /// Returns the diagonal of the matrix as a sparse matrix. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn diagonal_as_csc(&self) -> Self where T: Clone, @@ -498,6 +514,7 @@ impl CscMatrix { } /// Compute the transpose of the matrix. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn transpose(&self) -> CscMatrix where T: Scalar, @@ -617,24 +634,28 @@ macro_rules! impl_csc_col_common_methods { impl<'a, T> $name { /// The number of global rows in the column. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn nrows(&self) -> usize { self.lane.minor_dim() } /// The number of non-zeros in this column. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn nnz(&self) -> usize { self.lane.nnz() } /// The row indices corresponding to explicitly stored entries in this column. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn row_indices(&self) -> &[usize] { self.lane.minor_indices() } /// The values corresponding to explicitly stored entries in this column. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn values(&self) -> &[T] { self.lane.values() } @@ -643,6 +664,7 @@ macro_rules! impl_csc_col_common_methods { /// /// Each call to this function incurs the cost of a binary search among the explicitly /// stored row entries. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn get_entry(&self, global_row_index: usize) -> Option> { self.lane.get_entry(global_row_index) } diff --git a/nalgebra-sparse/src/csr.rs b/nalgebra-sparse/src/csr.rs index ded189eb..f5d64627 100644 --- a/nalgebra-sparse/src/csr.rs +++ b/nalgebra-sparse/src/csr.rs @@ -192,12 +192,14 @@ impl CsrMatrix { /// The number of rows in the matrix. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn nrows(&self) -> usize { self.cs.pattern().major_dim() } /// The number of columns in the matrix. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn ncols(&self) -> usize { self.cs.pattern().minor_dim() } @@ -208,12 +210,14 @@ impl CsrMatrix { /// number of algebraically zero entries in the matrix. Explicitly stored entries can still /// be zero. Corresponds to the number of entries in the sparsity pattern. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn nnz(&self) -> usize { self.cs.pattern().nnz() } /// The row offsets defining part of the CSR format. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn row_offsets(&self) -> &[usize] { let (offsets, _, _) = self.cs.cs_data(); offsets @@ -221,6 +225,7 @@ impl CsrMatrix { /// The column indices defining part of the CSR format. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn col_indices(&self) -> &[usize] { let (_, indices, _) = self.cs.cs_data(); indices @@ -228,6 +233,7 @@ impl CsrMatrix { /// The non-zero values defining part of the CSR format. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn values(&self) -> &[T] { self.cs.values() } @@ -300,6 +306,7 @@ impl CsrMatrix { /// ------ /// Panics if row index is out of bounds. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn row(&self, index: usize) -> CsrRow { self.get_row(index).expect("Row index must be in bounds") } @@ -317,6 +324,7 @@ impl CsrMatrix { /// Return the row at the given row index, or `None` if out of bounds. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn get_row(&self, index: usize) -> Option> { self.cs.get_lane(index).map(|lane| CsrRow { lane }) } @@ -383,6 +391,7 @@ impl CsrMatrix { } /// Returns a reference to the underlying sparsity pattern. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn pattern(&self) -> &SparsityPattern { self.cs.pattern() } @@ -399,6 +408,7 @@ impl CsrMatrix { /// /// Each call to this function incurs the cost of a binary search among the explicitly /// stored column entries for the given row. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn get_entry(&self, row_index: usize, col_index: usize) -> Option> { self.cs.get_entry(row_index, col_index) } @@ -424,6 +434,7 @@ impl CsrMatrix { /// Panics /// ------ /// Panics if `row_index` or `col_index` is out of bounds. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn index_entry(&self, row_index: usize, col_index: usize) -> SparseEntry { self.get_entry(row_index, col_index) .expect("Out of bounds matrix indices encountered") @@ -443,6 +454,7 @@ impl CsrMatrix { } /// Returns a triplet of slices `(row_offsets, col_indices, values)` that make up the CSR data. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn csr_data(&self) -> (&[usize], &[usize], &[T]) { self.cs.cs_data() } @@ -455,6 +467,7 @@ impl CsrMatrix { /// Creates a sparse matrix that contains only the explicit entries decided by the /// given predicate. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn filter

(&self, predicate: P) -> Self where T: Clone, @@ -470,6 +483,7 @@ impl CsrMatrix { /// Returns a new matrix representing the upper triangular part of this matrix. /// /// The result includes the diagonal of the matrix. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn upper_triangle(&self) -> Self where T: Clone, @@ -480,6 +494,7 @@ impl CsrMatrix { /// Returns a new matrix representing the lower triangular part of this matrix. /// /// The result includes the diagonal of the matrix. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn lower_triangle(&self) -> Self where T: Clone, @@ -488,6 +503,7 @@ impl CsrMatrix { } /// Returns the diagonal of the matrix as a sparse matrix. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn diagonal_as_csr(&self) -> Self where T: Clone, @@ -498,6 +514,7 @@ impl CsrMatrix { } /// Compute the transpose of the matrix. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn transpose(&self) -> CsrMatrix where T: Scalar, @@ -617,24 +634,28 @@ macro_rules! impl_csr_row_common_methods { impl<'a, T> $name { /// The number of global columns in the row. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn ncols(&self) -> usize { self.lane.minor_dim() } /// The number of non-zeros in this row. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn nnz(&self) -> usize { self.lane.nnz() } /// The column indices corresponding to explicitly stored entries in this row. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn col_indices(&self) -> &[usize] { self.lane.minor_indices() } /// The values corresponding to explicitly stored entries in this row. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn values(&self) -> &[T] { self.lane.values() } @@ -644,6 +665,7 @@ macro_rules! impl_csr_row_common_methods { /// Each call to this function incurs the cost of a binary search among the explicitly /// stored column entries. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn get_entry(&self, global_col_index: usize) -> Option> { self.lane.get_entry(global_col_index) } diff --git a/nalgebra-sparse/src/factorization/cholesky.rs b/nalgebra-sparse/src/factorization/cholesky.rs index a18761c9..662d82ae 100644 --- a/nalgebra-sparse/src/factorization/cholesky.rs +++ b/nalgebra-sparse/src/factorization/cholesky.rs @@ -42,6 +42,7 @@ impl CscSymbolicCholesky { } /// The pattern of the Cholesky factor `L`. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn l_pattern(&self) -> &SparsityPattern { &self.l_pattern } @@ -171,6 +172,7 @@ impl CscCholesky { } /// Returns a reference to the Cholesky factor `L`. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn l(&self) -> &CscMatrix { &self.l_factor } @@ -260,6 +262,7 @@ impl CscCholesky { /// # Panics /// /// Panics if `B` is not square. + #[must_use = "Did you mean to use solve_mut()?"] pub fn solve<'a>(&'a self, b: impl Into>) -> DMatrix { let b = b.into(); let mut output = b.clone_owned(); diff --git a/nalgebra-sparse/src/lib.rs b/nalgebra-sparse/src/lib.rs index 4b96717c..a56d0f46 100644 --- a/nalgebra-sparse/src/lib.rs +++ b/nalgebra-sparse/src/lib.rs @@ -170,6 +170,7 @@ pub struct SparseFormatError { impl SparseFormatError { /// The type of error. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn kind(&self) -> &SparseFormatErrorKind { &self.kind } diff --git a/nalgebra-sparse/src/ops/mod.rs b/nalgebra-sparse/src/ops/mod.rs index a6a21fbc..1e65ea36 100644 --- a/nalgebra-sparse/src/ops/mod.rs +++ b/nalgebra-sparse/src/ops/mod.rs @@ -140,11 +140,13 @@ pub enum Op { impl Op { /// Returns a reference to the inner value that the operation applies to. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn inner_ref(&self) -> &T { self.as_ref().into_inner() } /// Returns an `Op` applied to a reference of the inner value. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn as_ref(&self) -> Op<&T> { match self { Op::NoOp(obj) => Op::NoOp(&obj), diff --git a/nalgebra-sparse/src/ops/serial/mod.rs b/nalgebra-sparse/src/ops/serial/mod.rs index 82285e86..4a89daa1 100644 --- a/nalgebra-sparse/src/ops/serial/mod.rs +++ b/nalgebra-sparse/src/ops/serial/mod.rs @@ -96,11 +96,13 @@ impl OperationError { } /// The operation error kind. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn kind(&self) -> &OperationErrorKind { &self.error_kind } /// The underlying error message. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn message(&self) -> &str { self.message.as_str() } diff --git a/nalgebra-sparse/src/pattern.rs b/nalgebra-sparse/src/pattern.rs index 08552d6a..59eedc4c 100644 --- a/nalgebra-sparse/src/pattern.rs +++ b/nalgebra-sparse/src/pattern.rs @@ -60,18 +60,21 @@ impl SparsityPattern { /// The offsets for the major dimension. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn major_offsets(&self) -> &[usize] { &self.major_offsets } /// The indices for the minor dimension. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn minor_indices(&self) -> &[usize] { &self.minor_indices } /// The number of major lanes in the pattern. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn major_dim(&self) -> usize { assert!(self.major_offsets.len() > 0); self.major_offsets.len() - 1 @@ -79,12 +82,14 @@ impl SparsityPattern { /// The number of minor lanes in the pattern. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn minor_dim(&self) -> usize { self.minor_dim } /// The number of "non-zeros", i.e. explicitly stored entries in the pattern. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn nnz(&self) -> usize { self.minor_indices.len() } @@ -96,12 +101,14 @@ impl SparsityPattern { /// /// Panics if `major_index` is out of bounds. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn lane(&self, major_index: usize) -> &[usize] { self.get_lane(major_index).unwrap() } /// Get the lane at the given index, or `None` if out of bounds. #[inline] + #[must_use = "This function does not mutate self. You should use the return value."] pub fn get_lane(&self, major_index: usize) -> Option<&[usize]> { let offset_begin = *self.major_offsets().get(major_index)?; let offset_end = *self.major_offsets().get(major_index + 1)?; @@ -197,6 +204,7 @@ impl SparsityPattern { /// assert_eq!(entries, vec![(0, 0), (0, 2), (1, 1), (2, 0)]); /// ``` /// + #[must_use = "This function does not mutate self. You should use the return value."] pub fn entries(&self) -> SparsityPatternIter { SparsityPatternIter::from_pattern(self) } @@ -228,6 +236,7 @@ impl SparsityPattern { /// /// This is analogous to matrix transposition, i.e. an entry `(i, j)` becomes `(j, i)` in the /// new pattern. + #[must_use = "This function does not mutate self. You should use the return value."] pub fn transpose(&self) -> Self { // By using unit () values, we can use the same routines as for CSR/CSC matrices let values = vec![(); self.nnz()]; From 9fb963017fa5c97b476052ab9a36c711805eeaa0 Mon Sep 17 00:00:00 2001 From: Malte Tammena Date: Mon, 7 Jun 2021 16:34:03 +0200 Subject: [PATCH 07/42] Simplify default `#[must_use]` annotation --- nalgebra-lapack/src/cholesky.rs | 4 +- nalgebra-lapack/src/eigen.rs | 2 +- nalgebra-lapack/src/hessenberg.rs | 4 +- nalgebra-lapack/src/lu.rs | 8 +- nalgebra-lapack/src/qr.rs | 4 +- nalgebra-lapack/src/schur.rs | 4 +- nalgebra-lapack/src/svd.rs | 4 +- nalgebra-lapack/src/symmetric_eigen.rs | 4 +- nalgebra-sparse/src/coo.rs | 12 +- nalgebra-sparse/src/cs.rs | 26 ++-- nalgebra-sparse/src/csc.rs | 44 +++---- nalgebra-sparse/src/csr.rs | 44 +++---- nalgebra-sparse/src/factorization/cholesky.rs | 4 +- nalgebra-sparse/src/lib.rs | 2 +- nalgebra-sparse/src/ops/mod.rs | 4 +- nalgebra-sparse/src/ops/serial/mod.rs | 4 +- nalgebra-sparse/src/pattern.rs | 18 +-- src/base/blas.rs | 6 +- src/base/componentwise.rs | 10 +- src/base/edition.rs | 8 +- src/base/indexing.rs | 6 +- src/base/interpolation.rs | 8 +- src/base/matrix.rs | 62 ++++----- src/base/matrix_slice.rs | 6 +- src/base/min_max.rs | 30 ++--- src/base/norm.rs | 16 +-- src/base/ops.rs | 6 +- src/base/properties.rs | 14 +- src/base/statistics.rs | 30 ++--- src/base/swizzle.rs | 2 +- src/base/vec_storage.rs | 6 +- src/geometry/dual_quaternion.rs | 32 ++--- src/geometry/isometry.rs | 16 +-- src/geometry/isometry_interpolation.rs | 12 +- src/geometry/orthographic.rs | 28 ++-- src/geometry/perspective.rs | 24 ++-- src/geometry/point.rs | 16 +-- src/geometry/quaternion.rs | 122 +++++++++--------- src/geometry/reflection.rs | 2 +- src/geometry/rotation.rs | 14 +- src/geometry/rotation_interpolation.rs | 6 +- src/geometry/rotation_specialization.rs | 26 ++-- src/geometry/similarity.rs | 12 +- src/geometry/swizzle.rs | 2 +- src/geometry/transform.rs | 12 +- src/geometry/translation.rs | 6 +- src/geometry/unit_complex.rs | 28 ++-- src/geometry/unit_complex_construction.rs | 6 +- src/linalg/bidiagonal.rs | 12 +- src/linalg/cholesky.rs | 8 +- src/linalg/col_piv_qr.rs | 12 +- src/linalg/convolution.rs | 2 +- src/linalg/determinant.rs | 2 +- src/linalg/full_piv_lu.rs | 14 +- src/linalg/givens.rs | 4 +- src/linalg/hessenberg.rs | 4 +- src/linalg/lu.rs | 12 +- src/linalg/permutation_sequence.rs | 6 +- src/linalg/qr.rs | 8 +- src/linalg/schur.rs | 8 +- src/linalg/svd.rs | 6 +- src/linalg/symmetric_eigen.rs | 4 +- src/linalg/symmetric_tridiagonal.rs | 6 +- src/linalg/udu.rs | 2 +- src/sparse/cs_matrix.rs | 18 +-- src/sparse/cs_matrix_cholesky.rs | 2 +- 66 files changed, 448 insertions(+), 448 deletions(-) diff --git a/nalgebra-lapack/src/cholesky.rs b/nalgebra-lapack/src/cholesky.rs index b271ca51..bc3515a5 100644 --- a/nalgebra-lapack/src/cholesky.rs +++ b/nalgebra-lapack/src/cholesky.rs @@ -80,7 +80,7 @@ where } /// Retrieves the lower-triangular factor of the cholesky decomposition. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn l(&self) -> OMatrix { let mut res = self.l.clone(); res.fill_upper_triangle(Zero::zero(), 1); @@ -92,7 +92,7 @@ where /// /// This is an allocation-less version of `self.l()`. The values of the strict upper-triangular /// part are garbage and should be ignored by further computations. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn l_dirty(&self) -> &OMatrix { &self.l } diff --git a/nalgebra-lapack/src/eigen.rs b/nalgebra-lapack/src/eigen.rs index 993f8987..1bca79a5 100644 --- a/nalgebra-lapack/src/eigen.rs +++ b/nalgebra-lapack/src/eigen.rs @@ -302,7 +302,7 @@ where /// The determinant of the decomposed matrix. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn determinant(&self) -> T { let mut det = T::one(); for e in self.eigenvalues.iter() { diff --git a/nalgebra-lapack/src/hessenberg.rs b/nalgebra-lapack/src/hessenberg.rs index 47018004..c5765022 100644 --- a/nalgebra-lapack/src/hessenberg.rs +++ b/nalgebra-lapack/src/hessenberg.rs @@ -89,7 +89,7 @@ where /// Computes the hessenberg matrix of this decomposition. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn h(&self) -> OMatrix { let mut h = self.h.clone_owned(); h.fill_lower_triangle(T::zero(), 2); @@ -110,7 +110,7 @@ where /// Computes the unitary matrix `Q` of this decomposition. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn q(&self) -> OMatrix { let n = self.h.nrows() as i32; let mut q = self.h.clone_owned(); diff --git a/nalgebra-lapack/src/lu.rs b/nalgebra-lapack/src/lu.rs index a163629d..2130fc7e 100644 --- a/nalgebra-lapack/src/lu.rs +++ b/nalgebra-lapack/src/lu.rs @@ -85,7 +85,7 @@ where /// Gets the lower-triangular matrix part of the decomposition. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn l(&self) -> OMatrix> { let (nrows, ncols) = self.lu.data.shape(); let mut res = self.lu.columns_generic(0, nrows.min(ncols)).into_owned(); @@ -98,7 +98,7 @@ where /// Gets the upper-triangular matrix part of the decomposition. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn u(&self) -> OMatrix, C> { let (nrows, ncols) = self.lu.data.shape(); let mut res = self.lu.rows_generic(0, nrows.min(ncols)).into_owned(); @@ -113,7 +113,7 @@ where /// Computing the permutation matrix explicitly is costly and usually not necessary. /// To permute rows of a matrix or vector, use the method `self.permute(...)` instead. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn p(&self) -> OMatrix { let (dim, _) = self.lu.data.shape(); let mut id = Matrix::identity_generic(dim, dim); @@ -127,7 +127,7 @@ where /// Gets the LAPACK permutation indices. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn permutation_indices(&self) -> &OVector> { &self.p } diff --git a/nalgebra-lapack/src/qr.rs b/nalgebra-lapack/src/qr.rs index 8c32b299..7b2d5df6 100644 --- a/nalgebra-lapack/src/qr.rs +++ b/nalgebra-lapack/src/qr.rs @@ -92,7 +92,7 @@ where /// Retrieves the upper trapezoidal submatrix `R` of this decomposition. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn r(&self) -> OMatrix, C> { let (nrows, ncols) = self.qr.data.shape(); self.qr.rows_generic(0, nrows.min(ncols)).upper_triangle() @@ -118,7 +118,7 @@ where /// Computes the orthogonal matrix `Q` of this decomposition. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn q(&self) -> OMatrix> { let (nrows, ncols) = self.qr.data.shape(); let min_nrows_ncols = nrows.min(ncols); diff --git a/nalgebra-lapack/src/schur.rs b/nalgebra-lapack/src/schur.rs index 602e0ec1..3bee2635 100644 --- a/nalgebra-lapack/src/schur.rs +++ b/nalgebra-lapack/src/schur.rs @@ -138,7 +138,7 @@ where /// Computes the real eigenvalues of the decomposed matrix. /// /// Return `None` if some eigenvalues are complex. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn eigenvalues(&self) -> Option> { if self.im.iter().all(|e| e.is_zero()) { Some(self.re.clone()) @@ -148,7 +148,7 @@ where } /// Computes the complex eigenvalues of the decomposed matrix. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn complex_eigenvalues(&self) -> OVector, D> where DefaultAllocator: Allocator, D>, diff --git a/nalgebra-lapack/src/svd.rs b/nalgebra-lapack/src/svd.rs index 7256e984..3357e621 100644 --- a/nalgebra-lapack/src/svd.rs +++ b/nalgebra-lapack/src/svd.rs @@ -175,7 +175,7 @@ macro_rules! svd_impl( /// /// All singular value below epsilon will be set to zero instead of being inverted. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn pseudo_inverse(&self, epsilon: $t) -> OMatrix<$t, C, R> { let nrows = self.u.data.shape().0; let ncols = self.vt.data.shape().1; @@ -208,7 +208,7 @@ macro_rules! svd_impl( /// This is the number of singular values that are not too small (i.e. greater than /// the given `epsilon`). #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn rank(&self, epsilon: $t) -> usize { let mut i = 0; diff --git a/nalgebra-lapack/src/symmetric_eigen.rs b/nalgebra-lapack/src/symmetric_eigen.rs index d2150598..d276437e 100644 --- a/nalgebra-lapack/src/symmetric_eigen.rs +++ b/nalgebra-lapack/src/symmetric_eigen.rs @@ -138,7 +138,7 @@ where /// The determinant of the decomposed matrix. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn determinant(&self) -> T { let mut det = T::one(); for e in self.eigenvalues.iter() { @@ -151,7 +151,7 @@ where /// Rebuild the original matrix. /// /// This is useful if some of the eigenvalues have been manually modified. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn recompose(&self) -> OMatrix { let mut u_t = self.eigenvectors.clone(); for i in 0..self.eigenvalues.len() { diff --git a/nalgebra-sparse/src/coo.rs b/nalgebra-sparse/src/coo.rs index 820e4e38..caf74654 100644 --- a/nalgebra-sparse/src/coo.rs +++ b/nalgebra-sparse/src/coo.rs @@ -173,14 +173,14 @@ impl CooMatrix { /// The number of rows in the matrix. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn nrows(&self) -> usize { self.nrows } /// The number of columns in the matrix. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn ncols(&self) -> usize { self.ncols } @@ -191,25 +191,25 @@ impl CooMatrix { /// entries, then it may have a different number of non-zeros as reported by `nnz()` compared /// to its CSR representation. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn nnz(&self) -> usize { self.values.len() } /// The row indices of the explicitly stored entries. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn row_indices(&self) -> &[usize] { &self.row_indices } /// The column indices of the explicitly stored entries. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn col_indices(&self) -> &[usize] { &self.col_indices } /// The values of the explicitly stored entries. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn values(&self) -> &[T] { &self.values } diff --git a/nalgebra-sparse/src/cs.rs b/nalgebra-sparse/src/cs.rs index 10492801..a5a65f33 100644 --- a/nalgebra-sparse/src/cs.rs +++ b/nalgebra-sparse/src/cs.rs @@ -32,13 +32,13 @@ impl CsMatrix { } #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn pattern(&self) -> &SparsityPattern { &self.sparsity_pattern } #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn values(&self) -> &[T] { &self.values } @@ -50,7 +50,7 @@ impl CsMatrix { /// Returns the raw data represented as a tuple `(major_offsets, minor_indices, values)`. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn cs_data(&self) -> (&[usize], &[usize], &[T]) { let pattern = self.pattern(); ( @@ -91,7 +91,7 @@ impl CsMatrix { /// Internal method for simplifying access to a lane's data #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn get_index_range(&self, row_index: usize) -> Option> { let row_begin = *self.sparsity_pattern.major_offsets().get(row_index)?; let row_end = *self.sparsity_pattern.major_offsets().get(row_index + 1)?; @@ -115,7 +115,7 @@ impl CsMatrix { /// Returns an entry for the given major/minor indices, or `None` if the indices are out /// of bounds. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn get_entry(&self, major_index: usize, minor_index: usize) -> Option> { let row_range = self.get_index_range(major_index)?; let (_, minor_indices, values) = self.cs_data(); @@ -144,7 +144,7 @@ impl CsMatrix { get_mut_entry_from_slices(minor_dim, minor_indices, values, minor_index) } - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn get_lane(&self, index: usize) -> Option> { let range = self.get_index_range(index)?; let (_, minor_indices, values) = self.cs_data(); @@ -178,7 +178,7 @@ impl CsMatrix { } #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn filter

(&self, predicate: P) -> Self where T: Clone, @@ -214,7 +214,7 @@ impl CsMatrix { } /// Returns the diagonal of the matrix as a sparse matrix. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn diagonal_as_matrix(&self) -> Self where T: Clone, @@ -380,31 +380,31 @@ macro_rules! impl_cs_lane_common_methods { ($name:ty) => { impl<'a, T> $name { #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn minor_dim(&self) -> usize { self.minor_dim } #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn nnz(&self) -> usize { self.minor_indices.len() } #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn minor_indices(&self) -> &[usize] { self.minor_indices } #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn values(&self) -> &[T] { self.values } #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn get_entry(&self, global_col_index: usize) -> Option> { get_entry_from_slices( self.minor_dim, diff --git a/nalgebra-sparse/src/csc.rs b/nalgebra-sparse/src/csc.rs index e5fb9465..65e1c409 100644 --- a/nalgebra-sparse/src/csc.rs +++ b/nalgebra-sparse/src/csc.rs @@ -192,14 +192,14 @@ impl CscMatrix { /// The number of rows in the matrix. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn nrows(&self) -> usize { self.cs.pattern().minor_dim() } /// The number of columns in the matrix. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn ncols(&self) -> usize { self.cs.pattern().major_dim() } @@ -210,28 +210,28 @@ impl CscMatrix { /// number of algebraically zero entries in the matrix. Explicitly stored entries can still /// be zero. Corresponds to the number of entries in the sparsity pattern. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn nnz(&self) -> usize { self.pattern().nnz() } /// The column offsets defining part of the CSC format. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn col_offsets(&self) -> &[usize] { self.pattern().major_offsets() } /// The row indices defining part of the CSC format. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn row_indices(&self) -> &[usize] { self.pattern().minor_indices() } /// The non-zero values defining part of the CSC format. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn values(&self) -> &[T] { self.cs.values() } @@ -304,7 +304,7 @@ impl CscMatrix { /// ------ /// Panics if column index is out of bounds. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn col(&self, index: usize) -> CscCol { self.get_col(index).expect("Row index must be in bounds") } @@ -322,7 +322,7 @@ impl CscMatrix { /// Return the column at the given column index, or `None` if out of bounds. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn get_col(&self, index: usize) -> Option> { self.cs.get_lane(index).map(|lane| CscCol { lane }) } @@ -389,7 +389,7 @@ impl CscMatrix { } /// Returns a reference to the underlying sparsity pattern. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn pattern(&self) -> &SparsityPattern { self.cs.pattern() } @@ -406,7 +406,7 @@ impl CscMatrix { /// /// Each call to this function incurs the cost of a binary search among the explicitly /// stored row entries for the given column. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn get_entry(&self, row_index: usize, col_index: usize) -> Option> { self.cs.get_entry(col_index, row_index) } @@ -432,7 +432,7 @@ impl CscMatrix { /// Panics /// ------ /// Panics if `row_index` or `col_index` is out of bounds. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn index_entry(&self, row_index: usize, col_index: usize) -> SparseEntry { self.get_entry(row_index, col_index) .expect("Out of bounds matrix indices encountered") @@ -452,7 +452,7 @@ impl CscMatrix { } /// Returns a triplet of slices `(col_offsets, row_indices, values)` that make up the CSC data. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn csc_data(&self) -> (&[usize], &[usize], &[T]) { self.cs.cs_data() } @@ -465,7 +465,7 @@ impl CscMatrix { /// Creates a sparse matrix that contains only the explicit entries decided by the /// given predicate. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn filter

(&self, predicate: P) -> Self where T: Clone, @@ -483,7 +483,7 @@ impl CscMatrix { /// Returns a new matrix representing the upper triangular part of this matrix. /// /// The result includes the diagonal of the matrix. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn upper_triangle(&self) -> Self where T: Clone, @@ -494,7 +494,7 @@ impl CscMatrix { /// Returns a new matrix representing the lower triangular part of this matrix. /// /// The result includes the diagonal of the matrix. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn lower_triangle(&self) -> Self where T: Clone, @@ -503,7 +503,7 @@ impl CscMatrix { } /// Returns the diagonal of the matrix as a sparse matrix. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn diagonal_as_csc(&self) -> Self where T: Clone, @@ -514,7 +514,7 @@ impl CscMatrix { } /// Compute the transpose of the matrix. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn transpose(&self) -> CscMatrix where T: Scalar, @@ -634,28 +634,28 @@ macro_rules! impl_csc_col_common_methods { impl<'a, T> $name { /// The number of global rows in the column. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn nrows(&self) -> usize { self.lane.minor_dim() } /// The number of non-zeros in this column. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn nnz(&self) -> usize { self.lane.nnz() } /// The row indices corresponding to explicitly stored entries in this column. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn row_indices(&self) -> &[usize] { self.lane.minor_indices() } /// The values corresponding to explicitly stored entries in this column. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn values(&self) -> &[T] { self.lane.values() } @@ -664,7 +664,7 @@ macro_rules! impl_csc_col_common_methods { /// /// Each call to this function incurs the cost of a binary search among the explicitly /// stored row entries. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn get_entry(&self, global_row_index: usize) -> Option> { self.lane.get_entry(global_row_index) } diff --git a/nalgebra-sparse/src/csr.rs b/nalgebra-sparse/src/csr.rs index f5d64627..86b4272c 100644 --- a/nalgebra-sparse/src/csr.rs +++ b/nalgebra-sparse/src/csr.rs @@ -192,14 +192,14 @@ impl CsrMatrix { /// The number of rows in the matrix. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn nrows(&self) -> usize { self.cs.pattern().major_dim() } /// The number of columns in the matrix. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn ncols(&self) -> usize { self.cs.pattern().minor_dim() } @@ -210,14 +210,14 @@ impl CsrMatrix { /// number of algebraically zero entries in the matrix. Explicitly stored entries can still /// be zero. Corresponds to the number of entries in the sparsity pattern. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn nnz(&self) -> usize { self.cs.pattern().nnz() } /// The row offsets defining part of the CSR format. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn row_offsets(&self) -> &[usize] { let (offsets, _, _) = self.cs.cs_data(); offsets @@ -225,7 +225,7 @@ impl CsrMatrix { /// The column indices defining part of the CSR format. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn col_indices(&self) -> &[usize] { let (_, indices, _) = self.cs.cs_data(); indices @@ -233,7 +233,7 @@ impl CsrMatrix { /// The non-zero values defining part of the CSR format. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn values(&self) -> &[T] { self.cs.values() } @@ -306,7 +306,7 @@ impl CsrMatrix { /// ------ /// Panics if row index is out of bounds. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn row(&self, index: usize) -> CsrRow { self.get_row(index).expect("Row index must be in bounds") } @@ -324,7 +324,7 @@ impl CsrMatrix { /// Return the row at the given row index, or `None` if out of bounds. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn get_row(&self, index: usize) -> Option> { self.cs.get_lane(index).map(|lane| CsrRow { lane }) } @@ -391,7 +391,7 @@ impl CsrMatrix { } /// Returns a reference to the underlying sparsity pattern. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn pattern(&self) -> &SparsityPattern { self.cs.pattern() } @@ -408,7 +408,7 @@ impl CsrMatrix { /// /// Each call to this function incurs the cost of a binary search among the explicitly /// stored column entries for the given row. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn get_entry(&self, row_index: usize, col_index: usize) -> Option> { self.cs.get_entry(row_index, col_index) } @@ -434,7 +434,7 @@ impl CsrMatrix { /// Panics /// ------ /// Panics if `row_index` or `col_index` is out of bounds. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn index_entry(&self, row_index: usize, col_index: usize) -> SparseEntry { self.get_entry(row_index, col_index) .expect("Out of bounds matrix indices encountered") @@ -454,7 +454,7 @@ impl CsrMatrix { } /// Returns a triplet of slices `(row_offsets, col_indices, values)` that make up the CSR data. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn csr_data(&self) -> (&[usize], &[usize], &[T]) { self.cs.cs_data() } @@ -467,7 +467,7 @@ impl CsrMatrix { /// Creates a sparse matrix that contains only the explicit entries decided by the /// given predicate. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn filter

(&self, predicate: P) -> Self where T: Clone, @@ -483,7 +483,7 @@ impl CsrMatrix { /// Returns a new matrix representing the upper triangular part of this matrix. /// /// The result includes the diagonal of the matrix. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn upper_triangle(&self) -> Self where T: Clone, @@ -494,7 +494,7 @@ impl CsrMatrix { /// Returns a new matrix representing the lower triangular part of this matrix. /// /// The result includes the diagonal of the matrix. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn lower_triangle(&self) -> Self where T: Clone, @@ -503,7 +503,7 @@ impl CsrMatrix { } /// Returns the diagonal of the matrix as a sparse matrix. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn diagonal_as_csr(&self) -> Self where T: Clone, @@ -514,7 +514,7 @@ impl CsrMatrix { } /// Compute the transpose of the matrix. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn transpose(&self) -> CsrMatrix where T: Scalar, @@ -634,28 +634,28 @@ macro_rules! impl_csr_row_common_methods { impl<'a, T> $name { /// The number of global columns in the row. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn ncols(&self) -> usize { self.lane.minor_dim() } /// The number of non-zeros in this row. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn nnz(&self) -> usize { self.lane.nnz() } /// The column indices corresponding to explicitly stored entries in this row. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn col_indices(&self) -> &[usize] { self.lane.minor_indices() } /// The values corresponding to explicitly stored entries in this row. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn values(&self) -> &[T] { self.lane.values() } @@ -665,7 +665,7 @@ macro_rules! impl_csr_row_common_methods { /// Each call to this function incurs the cost of a binary search among the explicitly /// stored column entries. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn get_entry(&self, global_col_index: usize) -> Option> { self.lane.get_entry(global_col_index) } diff --git a/nalgebra-sparse/src/factorization/cholesky.rs b/nalgebra-sparse/src/factorization/cholesky.rs index 662d82ae..0acc428d 100644 --- a/nalgebra-sparse/src/factorization/cholesky.rs +++ b/nalgebra-sparse/src/factorization/cholesky.rs @@ -42,7 +42,7 @@ impl CscSymbolicCholesky { } /// The pattern of the Cholesky factor `L`. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn l_pattern(&self) -> &SparsityPattern { &self.l_pattern } @@ -172,7 +172,7 @@ impl CscCholesky { } /// Returns a reference to the Cholesky factor `L`. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn l(&self) -> &CscMatrix { &self.l_factor } diff --git a/nalgebra-sparse/src/lib.rs b/nalgebra-sparse/src/lib.rs index a56d0f46..6f28917d 100644 --- a/nalgebra-sparse/src/lib.rs +++ b/nalgebra-sparse/src/lib.rs @@ -170,7 +170,7 @@ pub struct SparseFormatError { impl SparseFormatError { /// The type of error. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn kind(&self) -> &SparseFormatErrorKind { &self.kind } diff --git a/nalgebra-sparse/src/ops/mod.rs b/nalgebra-sparse/src/ops/mod.rs index 1e65ea36..50d25e63 100644 --- a/nalgebra-sparse/src/ops/mod.rs +++ b/nalgebra-sparse/src/ops/mod.rs @@ -140,13 +140,13 @@ pub enum Op { impl Op { /// Returns a reference to the inner value that the operation applies to. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn inner_ref(&self) -> &T { self.as_ref().into_inner() } /// Returns an `Op` applied to a reference of the inner value. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn as_ref(&self) -> Op<&T> { match self { Op::NoOp(obj) => Op::NoOp(&obj), diff --git a/nalgebra-sparse/src/ops/serial/mod.rs b/nalgebra-sparse/src/ops/serial/mod.rs index 4a89daa1..4b0cc904 100644 --- a/nalgebra-sparse/src/ops/serial/mod.rs +++ b/nalgebra-sparse/src/ops/serial/mod.rs @@ -96,13 +96,13 @@ impl OperationError { } /// The operation error kind. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn kind(&self) -> &OperationErrorKind { &self.error_kind } /// The underlying error message. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn message(&self) -> &str { self.message.as_str() } diff --git a/nalgebra-sparse/src/pattern.rs b/nalgebra-sparse/src/pattern.rs index 59eedc4c..2e490285 100644 --- a/nalgebra-sparse/src/pattern.rs +++ b/nalgebra-sparse/src/pattern.rs @@ -60,21 +60,21 @@ impl SparsityPattern { /// The offsets for the major dimension. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn major_offsets(&self) -> &[usize] { &self.major_offsets } /// The indices for the minor dimension. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn minor_indices(&self) -> &[usize] { &self.minor_indices } /// The number of major lanes in the pattern. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn major_dim(&self) -> usize { assert!(self.major_offsets.len() > 0); self.major_offsets.len() - 1 @@ -82,14 +82,14 @@ impl SparsityPattern { /// The number of minor lanes in the pattern. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn minor_dim(&self) -> usize { self.minor_dim } /// The number of "non-zeros", i.e. explicitly stored entries in the pattern. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn nnz(&self) -> usize { self.minor_indices.len() } @@ -101,14 +101,14 @@ impl SparsityPattern { /// /// Panics if `major_index` is out of bounds. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn lane(&self, major_index: usize) -> &[usize] { self.get_lane(major_index).unwrap() } /// Get the lane at the given index, or `None` if out of bounds. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn get_lane(&self, major_index: usize) -> Option<&[usize]> { let offset_begin = *self.major_offsets().get(major_index)?; let offset_end = *self.major_offsets().get(major_index + 1)?; @@ -204,7 +204,7 @@ impl SparsityPattern { /// assert_eq!(entries, vec![(0, 0), (0, 2), (1, 1), (2, 0)]); /// ``` /// - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn entries(&self) -> SparsityPatternIter { SparsityPatternIter::from_pattern(self) } @@ -236,7 +236,7 @@ impl SparsityPattern { /// /// This is analogous to matrix transposition, i.e. an entry `(i, j)` becomes `(j, i)` in the /// new pattern. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn transpose(&self) -> Self { // By using unit () values, we can use the same routines as for CSR/CSC matrices let values = vec![(); self.nnz()]; diff --git a/src/base/blas.rs b/src/base/blas.rs index f3e3fb91..9617e46a 100644 --- a/src/base/blas.rs +++ b/src/base/blas.rs @@ -193,7 +193,7 @@ where /// ``` /// #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn dot(&self, rhs: &Matrix) -> T where SB: Storage, @@ -222,7 +222,7 @@ where /// assert_ne!(vec1.dotc(&vec2), vec1.dot(&vec2)); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn dotc(&self, rhs: &Matrix) -> T where T: SimdComplexField, @@ -250,7 +250,7 @@ where /// assert_eq!(mat1.tr_dot(&mat2), 9.1); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn tr_dot(&self, rhs: &Matrix) -> T where SB: Storage, diff --git a/src/base/componentwise.rs b/src/base/componentwise.rs index 1a3ad284..02b2cae6 100644 --- a/src/base/componentwise.rs +++ b/src/base/componentwise.rs @@ -28,7 +28,7 @@ impl> Matrix { /// assert_eq!(a.abs(), Matrix2::new(0.0, 1.0, 2.0, 3.0)) /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn abs(&self) -> OMatrix where T: Signed, @@ -50,7 +50,7 @@ macro_rules! component_binop_impl( ($($binop: ident, $binop_mut: ident, $binop_assign: ident, $cmpy: ident, $Trait: ident . $op: ident . $op_assign: ident, $desc:expr, $desc_cmpy:expr, $desc_mut:expr);* $(;)*) => {$( #[doc = $desc] #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn $binop(&self, rhs: &Matrix) -> MatrixComponentOp where T: $Trait, R2: Dim, C2: Dim, @@ -253,7 +253,7 @@ impl> Matrix /// assert_eq!(u.inf(&v), expected) /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn inf(&self, other: &Self) -> OMatrix where T: SimdPartialOrd, @@ -274,7 +274,7 @@ impl> Matrix /// assert_eq!(u.sup(&v), expected) /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn sup(&self, other: &Self) -> OMatrix where T: SimdPartialOrd, @@ -295,7 +295,7 @@ impl> Matrix /// assert_eq!(u.inf_sup(&v), expected) /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn inf_sup(&self, other: &Self) -> (OMatrix, OMatrix) where T: SimdPartialOrd, diff --git a/src/base/edition.rs b/src/base/edition.rs index 459dfcb2..82c537fc 100644 --- a/src/base/edition.rs +++ b/src/base/edition.rs @@ -18,7 +18,7 @@ use crate::base::{DefaultAllocator, Matrix, OMatrix, RowVector, Scalar, Vector}; impl> Matrix { /// Extracts the upper triangular part of this matrix (including the diagonal). #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn upper_triangle(&self) -> OMatrix where DefaultAllocator: Allocator, @@ -31,7 +31,7 @@ impl> Matrix { /// Extracts the lower triangular part of this matrix (including the diagonal). #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn lower_triangle(&self) -> OMatrix where DefaultAllocator: Allocator, @@ -44,7 +44,7 @@ impl> Matrix { /// Creates a new matrix by extracting the given set of rows from `self`. #[cfg(any(feature = "std", feature = "alloc"))] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn select_rows<'a, I>(&self, irows: I) -> OMatrix where I: IntoIterator, @@ -81,7 +81,7 @@ impl> Matrix { /// Creates a new matrix by extracting the given set of columns from `self`. #[cfg(any(feature = "std", feature = "alloc"))] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn select_columns<'a, I>(&self, icols: I) -> OMatrix where I: IntoIterator, diff --git a/src/base/indexing.rs b/src/base/indexing.rs index aa5ae942..9ddf8776 100644 --- a/src/base/indexing.rs +++ b/src/base/indexing.rs @@ -485,7 +485,7 @@ impl> Matrix { /// Produces a view of the data at the given index, or /// `None` if the index is out of bounds. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn get<'a, I>(&'a self, index: I) -> Option where I: MatrixIndex<'a, T, R, C, S>, @@ -507,7 +507,7 @@ impl> Matrix { /// Produces a view of the data at the given index, or /// panics if the index is out of bounds. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn index<'a, I>(&'a self, index: I) -> I::Output where I: MatrixIndex<'a, T, R, C, S>, @@ -529,7 +529,7 @@ impl> Matrix { /// Produces a view of the data at the given index, without doing /// any bounds checking. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub unsafe fn get_unchecked<'a, I>(&'a self, index: I) -> I::Output where I: MatrixIndex<'a, T, R, C, S>, diff --git a/src/base/interpolation.rs b/src/base/interpolation.rs index 9dd72b5a..d5661e40 100644 --- a/src/base/interpolation.rs +++ b/src/base/interpolation.rs @@ -20,7 +20,7 @@ impl>(&self, rhs: &Vector, t: T) -> OVector where DefaultAllocator: Allocator, @@ -46,7 +46,7 @@ impl>(&self, rhs: &Vector, t: T) -> OVector where T: RealField, @@ -74,7 +74,7 @@ impl> Unit> { /// /// assert_eq!(v, v2); /// ``` - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn slerp>( &self, rhs: &Unit>, @@ -92,7 +92,7 @@ impl> Unit> { /// /// Returns `None` if the two vectors are almost collinear and with opposite direction /// (in this case, there is an infinity of possible results). - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn try_slerp>( &self, rhs: &Unit>, diff --git a/src/base/matrix.rs b/src/base/matrix.rs index ebd22d31..6d2468bb 100644 --- a/src/base/matrix.rs +++ b/src/base/matrix.rs @@ -441,7 +441,7 @@ impl> Matrix { /// let mat = Matrix3x4::::zeros(); /// assert_eq!(mat.shape(), (3, 4)); #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn shape(&self) -> (usize, usize) { let (nrows, ncols) = self.data.shape(); (nrows.value(), ncols.value()) @@ -456,7 +456,7 @@ impl> Matrix { /// let mat = Matrix3x4::::zeros(); /// assert_eq!(mat.nrows(), 3); #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn nrows(&self) -> usize { self.shape().0 } @@ -470,7 +470,7 @@ impl> Matrix { /// let mat = Matrix3x4::::zeros(); /// assert_eq!(mat.ncols(), 4); #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn ncols(&self) -> usize { self.shape().1 } @@ -486,7 +486,7 @@ impl> Matrix { /// // The column strides is the number of steps (here 2) multiplied by the corresponding dimension. /// assert_eq!(mat.strides(), (1, 10)); #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn strides(&self) -> (usize, usize) { let (srows, scols) = self.data.strides(); (srows.value(), scols.value()) @@ -505,7 +505,7 @@ impl> Matrix { /// assert_eq!(m[i], m[3]); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn vector_to_matrix_index(&self, i: usize) -> (usize, usize) { let (nrows, ncols) = self.shape(); @@ -534,7 +534,7 @@ impl> Matrix { /// assert_eq!(unsafe { *ptr }, m[0]); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn as_ptr(&self) -> *const T { self.data.ptr() } @@ -543,7 +543,7 @@ impl> Matrix { /// /// See `relative_eq` from the `RelativeEq` trait for more details. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn relative_eq( &self, other: &Matrix, @@ -566,7 +566,7 @@ impl> Matrix { /// Tests whether `self` and `rhs` are exactly equal. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn eq(&self, other: &Matrix) -> bool where T: PartialEq, @@ -617,7 +617,7 @@ impl> Matrix { /// Clones this matrix to one that owns its data. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn clone_owned(&self) -> OMatrix where DefaultAllocator: Allocator, @@ -628,7 +628,7 @@ impl> Matrix { /// Clones this matrix into one that owns its data. The actual type of the result depends on /// matrix storage combination rules for addition. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn clone_owned_sum(&self) -> MatrixSum where R2: Dim, @@ -702,7 +702,7 @@ impl> Matrix { impl> Matrix { /// Returns a matrix containing the result of `f` applied to each of its entries. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn map T2>(&self, mut f: F) -> OMatrix where DefaultAllocator: Allocator, @@ -749,7 +749,7 @@ impl> Matrix { /// - If the matrix has has least one component, then `init_f` is called with the first component /// to compute the initial value. Folding then continues on all the remaining components of the matrix. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn fold_with( &self, init_f: impl FnOnce(Option<&T>) -> T2, @@ -763,7 +763,7 @@ impl> Matrix { /// Returns a matrix containing the result of `f` applied to each of its entries. Unlike `map`, /// `f` also gets passed the row and column index, i.e. `f(row, col, value)`. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn map_with_location T2>( &self, mut f: F, @@ -791,7 +791,7 @@ impl> Matrix { /// Returns a matrix containing the result of `f` applied to each entries of `self` and /// `rhs`. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn zip_map(&self, rhs: &Matrix, mut f: F) -> OMatrix where T2: Scalar, @@ -827,7 +827,7 @@ impl> Matrix { /// Returns a matrix containing the result of `f` applied to each entries of `self` and /// `b`, and `c`. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn zip_zip_map( &self, b: &Matrix, @@ -875,7 +875,7 @@ impl> Matrix { /// Folds a function `f` on each entry of `self`. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn fold(&self, init: Acc, mut f: impl FnMut(Acc, T) -> Acc) -> Acc { let (nrows, ncols) = self.data.shape(); @@ -895,7 +895,7 @@ impl> Matrix { /// Folds a function `f` on each pairs of entries from `self` and `rhs`. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn zip_fold( &self, rhs: &Matrix, @@ -1255,7 +1255,7 @@ impl> Matrix { impl> Vector { /// Gets a reference to the i-th element of this column vector without bound checking. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub unsafe fn vget_unchecked(&self, i: usize) -> &T { debug_assert!(i < self.nrows(), "Vector index out of bounds."); let i = i * self.strides().0; @@ -1276,7 +1276,7 @@ impl> Vector { impl> Matrix { /// Extracts a slice containing the entire matrix entries ordered column-by-columns. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn as_slice(&self) -> &[T] { self.data.as_slice() } @@ -1465,7 +1465,7 @@ impl> Matrix { impl> SquareMatrix { /// The diagonal of this matrix. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn diagonal(&self) -> OVector where DefaultAllocator: Allocator, @@ -1477,7 +1477,7 @@ impl> SquareMatrix { /// /// This is a more efficient version of `self.diagonal().map(f)` since this /// allocates only once. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn map_diagonal(&self, mut f: impl FnMut(T) -> T2) -> OVector where DefaultAllocator: Allocator, @@ -1502,7 +1502,7 @@ impl> SquareMatrix { /// Computes a trace of a square matrix, i.e., the sum of its diagonal elements. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn trace(&self) -> T where T: Scalar + Zero + ClosedAdd, @@ -1526,7 +1526,7 @@ impl> SquareMatrix { impl> SquareMatrix { /// The symmetric part of `self`, i.e., `0.5 * (self + self.transpose())`. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn symmetric_part(&self) -> OMatrix where DefaultAllocator: Allocator, @@ -1543,7 +1543,7 @@ impl> SquareMatrix { /// The hermitian part of `self`, i.e., `0.5 * (self + self.adjoint())`. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn hermitian_part(&self) -> OMatrix where DefaultAllocator: Allocator, @@ -1566,7 +1566,7 @@ impl + IsNotStaticOne, S: Storage /// Yields the homogeneous matrix for this matrix, i.e., appending an additional dimension and /// and setting the diagonal element to `1`. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn to_homogeneous(&self) -> OMatrix, DimSum> where DefaultAllocator: Allocator, DimSum>, @@ -1587,7 +1587,7 @@ impl, S: Storage> Vector { /// Computes the coordinates in projective space of this vector, i.e., appends a `0` to its /// coordinates. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn to_homogeneous(&self) -> OVector> where DefaultAllocator: Allocator>, @@ -1615,7 +1615,7 @@ impl, S: Storage> Vector { impl, S: Storage> Vector { /// Constructs a new vector of higher dimension by appending `element` to the end of `self`. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn push(&self, element: T) -> OVector> where DefaultAllocator: Allocator>, @@ -1918,7 +1918,7 @@ impl(&self, b: &Matrix) -> T where R2: Dim, @@ -1948,7 +1948,7 @@ impl(&self, b: &Matrix) -> MatrixCross where R2: Dim, @@ -2022,7 +2022,7 @@ impl> Vector { /// Computes the matrix `M` such that for all vector `v` we have `M * v == self.cross(&v)`. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn cross_matrix(&self) -> OMatrix { OMatrix::::new( T::zero(), @@ -2041,7 +2041,7 @@ impl> Vector { impl> Matrix { /// The smallest angle between two vectors. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn angle(&self, other: &Matrix) -> T::SimdRealField where SB: Storage, diff --git a/src/base/matrix_slice.rs b/src/base/matrix_slice.rs index 646acbc6..ffe95c8a 100644 --- a/src/base/matrix_slice.rs +++ b/src/base/matrix_slice.rs @@ -812,7 +812,7 @@ impl> Matrix { /// Slices a sub-matrix containing the rows indexed by the range `rows` and the columns indexed /// by the range `cols`. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn slice_range( &self, rows: RowRange, @@ -831,7 +831,7 @@ impl> Matrix { /// Slice containing all the rows indexed by the range `rows`. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn rows_range>( &self, rows: RowRange, @@ -841,7 +841,7 @@ impl> Matrix { /// Slice containing all the columns indexed by the range `rows`. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn columns_range>( &self, cols: ColRange, diff --git a/src/base/min_max.rs b/src/base/min_max.rs index ba109380..83e62d10 100644 --- a/src/base/min_max.rs +++ b/src/base/min_max.rs @@ -13,7 +13,7 @@ impl> Matrix { /// assert_eq!(Vector3::new(-1.0, -2.0, -3.0).amax(), 3.0); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn amax(&self) -> T where T: Zero + SimdSigned + SimdPartialOrd, @@ -34,7 +34,7 @@ impl> Matrix { /// Complex::new(1.0, 3.0)).camax(), 5.0); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn camax(&self) -> T::SimdRealField where T: SimdComplexField, @@ -54,7 +54,7 @@ impl> Matrix { /// assert_eq!(Vector3::new(5u32, 2, 3).max(), 5); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn max(&self) -> T where T: SimdPartialOrd + Zero, @@ -73,7 +73,7 @@ impl> Matrix { /// assert_eq!(Vector3::new(10.0, 2.0, 30.0).amin(), 2.0); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn amin(&self) -> T where T: Zero + SimdPartialOrd + SimdSigned, @@ -94,7 +94,7 @@ impl> Matrix { /// Complex::new(1.0, 3.0)).camin(), 3.0); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn camin(&self) -> T::SimdRealField where T: SimdComplexField, @@ -117,7 +117,7 @@ impl> Matrix { /// assert_eq!(Vector3::new(5u32, 2, 3).min(), 2); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn min(&self) -> T where T: SimdPartialOrd + Zero, @@ -142,7 +142,7 @@ impl> Matrix { /// assert_eq!(mat.icamax_full(), (1, 0)); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn icamax_full(&self) -> (usize, usize) where T: ComplexField, @@ -179,7 +179,7 @@ impl> Matri /// assert_eq!(mat.iamax_full(), (1, 2)); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn iamax_full(&self) -> (usize, usize) { assert!(!self.is_empty(), "The input matrix must not be empty."); @@ -217,7 +217,7 @@ impl> Vector { /// assert_eq!(vec.icamax(), 2); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn icamax(&self) -> usize where T: ComplexField, @@ -249,7 +249,7 @@ impl> Vector { /// assert_eq!(vec.argmax(), (2, 13)); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn argmax(&self) -> (usize, T) where T: PartialOrd, @@ -281,7 +281,7 @@ impl> Vector { /// assert_eq!(vec.imax(), 2); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn imax(&self) -> usize where T: PartialOrd, @@ -299,7 +299,7 @@ impl> Vector { /// assert_eq!(vec.iamax(), 1); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn iamax(&self) -> usize where T: PartialOrd + Signed, @@ -331,7 +331,7 @@ impl> Vector { /// assert_eq!(vec.argmin(), (1, -15)); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn argmin(&self) -> (usize, T) where T: PartialOrd, @@ -363,7 +363,7 @@ impl> Vector { /// assert_eq!(vec.imin(), 1); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn imin(&self) -> usize where T: PartialOrd, @@ -381,7 +381,7 @@ impl> Vector { /// assert_eq!(vec.iamin(), 0); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn iamin(&self) -> usize where T: PartialOrd + Signed, diff --git a/src/base/norm.rs b/src/base/norm.rs index 0cf42906..d0c96cd3 100644 --- a/src/base/norm.rs +++ b/src/base/norm.rs @@ -158,7 +158,7 @@ impl Norm for UniformNorm { impl> Matrix { /// The squared L2 norm of this vector. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn norm_squared(&self) -> T::SimdRealField where T: SimdComplexField, @@ -177,7 +177,7 @@ impl> Matrix { /// /// Use `.apply_norm` to apply a custom norm. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn norm(&self) -> T::SimdRealField where T: SimdComplexField, @@ -189,7 +189,7 @@ impl> Matrix { /// /// Use `.apply_metric_distance` to apply a custom norm. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn metric_distance(&self, rhs: &Matrix) -> T::SimdRealField where T: SimdComplexField, @@ -214,7 +214,7 @@ impl> Matrix { /// assert_eq!(v.apply_norm(&EuclideanNorm), v.norm()); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn apply_norm(&self, norm: &impl Norm) -> T::SimdRealField where T: SimdComplexField, @@ -237,7 +237,7 @@ impl> Matrix { /// assert_eq!(v1.apply_metric_distance(&v2, &EuclideanNorm), (v1 - v2).norm()); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn apply_metric_distance( &self, rhs: &Matrix, @@ -259,7 +259,7 @@ impl> Matrix { /// /// This function is simply implemented as a call to `norm()` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn magnitude(&self) -> T::SimdRealField where T: SimdComplexField, @@ -273,7 +273,7 @@ impl> Matrix { /// /// This function is simply implemented as a call to `norm_squared()` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn magnitude_squared(&self) -> T::SimdRealField where T: SimdComplexField, @@ -305,7 +305,7 @@ impl> Matrix { /// The Lp norm of this matrix. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn lp_norm(&self, p: i32) -> T::SimdRealField where T: SimdComplexField, diff --git a/src/base/ops.rs b/src/base/ops.rs index b23a85e6..d9be71a7 100644 --- a/src/base/ops.rs +++ b/src/base/ops.rs @@ -676,7 +676,7 @@ where { /// Equivalent to `self.transpose() * rhs`. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn tr_mul(&self, rhs: &Matrix) -> OMatrix where SB: Storage, @@ -693,7 +693,7 @@ where /// Equivalent to `self.adjoint() * rhs`. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn ad_mul(&self, rhs: &Matrix) -> OMatrix where T: SimdComplexField, @@ -803,7 +803,7 @@ where /// The kronecker product of two matrices (aka. tensor product of the corresponding linear /// maps). - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn kronecker( &self, rhs: &Matrix, diff --git a/src/base/properties.rs b/src/base/properties.rs index e5645ce0..9e250119 100644 --- a/src/base/properties.rs +++ b/src/base/properties.rs @@ -20,7 +20,7 @@ impl> Matrix { /// assert_eq!(mat.len(), 12); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn len(&self) -> usize { let (nrows, ncols) = self.shape(); nrows * ncols @@ -36,14 +36,14 @@ impl> Matrix { /// assert!(!mat.is_empty()); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn is_empty(&self) -> bool { self.len() == 0 } /// Indicates if this is a square matrix. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn is_square(&self) -> bool { let (nrows, ncols) = self.shape(); nrows == ncols @@ -55,7 +55,7 @@ impl> Matrix { /// If the matrix is diagonal, this checks that diagonal elements (i.e. at coordinates `(i, i)` /// for i from `0` to `min(R, C)`) are equal one; and that all other elements are zero. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn is_identity(&self, eps: T::Epsilon) -> bool where T: Zero + One + RelativeEq, @@ -116,7 +116,7 @@ impl> Matrix { /// In this definition `Id` is approximately equal to the identity matrix with a relative error /// equal to `eps`. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn is_orthogonal(&self, eps: T::Epsilon) -> bool where T: Zero + One + ClosedAdd + ClosedMul + RelativeEq, @@ -134,7 +134,7 @@ where { /// Checks that this matrix is orthogonal and has a determinant equal to 1. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn is_special_orthogonal(&self, eps: T) -> bool where D: DimMin, @@ -145,7 +145,7 @@ where /// Returns `true` if this matrix is invertible. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn is_invertible(&self) -> bool { // TODO: improve this? self.clone_owned().try_inverse().is_some() diff --git a/src/base/statistics.rs b/src/base/statistics.rs index 0b3a8279..59d78482 100644 --- a/src/base/statistics.rs +++ b/src/base/statistics.rs @@ -9,7 +9,7 @@ impl> Matrix { /// Returns a row vector where each element is the result of the application of `f` on the /// corresponding column of the original matrix. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn compress_rows( &self, f: impl Fn(VectorSlice) -> T, @@ -36,7 +36,7 @@ impl> Matrix { /// /// This is the same as `self.compress_rows(f).transpose()`. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn compress_rows_tr( &self, f: impl Fn(VectorSlice) -> T, @@ -60,7 +60,7 @@ impl> Matrix { /// Returns a column vector resulting from the folding of `f` on each column of this matrix. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn compress_columns( &self, init: OVector, @@ -98,7 +98,7 @@ impl> Matrix { /// assert_eq!(m.sum(), 21.0); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn sum(&self) -> T where T: ClosedAdd + Zero, @@ -124,7 +124,7 @@ impl> Matrix { /// assert_eq!(mint.row_sum(), RowVector2::new(9,12)); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn row_sum(&self) -> RowOVector where T: ClosedAdd + Zero, @@ -149,7 +149,7 @@ impl> Matrix { /// assert_eq!(mint.row_sum_tr(), Vector2::new(9,12)); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn row_sum_tr(&self) -> OVector where T: ClosedAdd + Zero, @@ -174,7 +174,7 @@ impl> Matrix { /// assert_eq!(mint.column_sum(), Vector3::new(3,7,11)); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn column_sum(&self) -> OVector where T: ClosedAdd + Zero, @@ -204,7 +204,7 @@ impl> Matrix { /// assert_relative_eq!(m.variance(), 35.0 / 12.0, epsilon = 1.0e-8); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn variance(&self) -> T where T: Field + SupersetOf, @@ -234,7 +234,7 @@ impl> Matrix { /// assert_eq!(m.row_variance(), RowVector3::new(2.25, 2.25, 2.25)); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn row_variance(&self) -> RowOVector where T: Field + SupersetOf, @@ -255,7 +255,7 @@ impl> Matrix { /// assert_eq!(m.row_variance_tr(), Vector3::new(2.25, 2.25, 2.25)); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn row_variance_tr(&self) -> OVector where T: Field + SupersetOf, @@ -277,7 +277,7 @@ impl> Matrix { /// assert_relative_eq!(m.column_variance(), Vector2::new(2.0 / 3.0, 2.0 / 3.0), epsilon = 1.0e-8); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn column_variance(&self) -> OVector where T: Field + SupersetOf, @@ -317,7 +317,7 @@ impl> Matrix { /// assert_eq!(m.mean(), 3.5); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn mean(&self) -> T where T: Field + SupersetOf, @@ -343,7 +343,7 @@ impl> Matrix { /// assert_eq!(m.row_mean(), RowVector3::new(2.5, 3.5, 4.5)); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn row_mean(&self) -> RowOVector where T: Field + SupersetOf, @@ -364,7 +364,7 @@ impl> Matrix { /// assert_eq!(m.row_mean_tr(), Vector3::new(2.5, 3.5, 4.5)); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn row_mean_tr(&self) -> OVector where T: Field + SupersetOf, @@ -385,7 +385,7 @@ impl> Matrix { /// assert_eq!(m.column_mean(), Vector2::new(2.0, 5.0)); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn column_mean(&self) -> OVector where T: Field + SupersetOf, diff --git a/src/base/swizzle.rs b/src/base/swizzle.rs index 76fecda2..25d6375f 100644 --- a/src/base/swizzle.rs +++ b/src/base/swizzle.rs @@ -8,7 +8,7 @@ macro_rules! impl_swizzle { $( /// Builds a new vector from components of `self`. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn $name(&self) -> $Result where D::Typenum: Cmp { $Result::new($(self[$i].inlined_clone()),*) diff --git a/src/base/vec_storage.rs b/src/base/vec_storage.rs index 48a25b20..14490674 100644 --- a/src/base/vec_storage.rs +++ b/src/base/vec_storage.rs @@ -95,7 +95,7 @@ impl VecStorage { /// The underlying data storage. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn as_vec(&self) -> &Vec { &self.data } @@ -130,14 +130,14 @@ impl VecStorage { /// The number of elements on the underlying vector. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn len(&self) -> usize { self.data.len() } /// Returns true if the underlying vector contains no elements. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn is_empty(&self) -> bool { self.len() == 0 } diff --git a/src/geometry/dual_quaternion.rs b/src/geometry/dual_quaternion.rs index 04252b22..83912b9e 100644 --- a/src/geometry/dual_quaternion.rs +++ b/src/geometry/dual_quaternion.rs @@ -232,7 +232,7 @@ where /// )); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn lerp(&self, other: &Self, t: T) -> Self { self * (T::one() - t) + other * t } @@ -382,7 +382,7 @@ where /// )); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn dual_quaternion(&self) -> &DualQuaternion { self.as_ref() } @@ -487,7 +487,7 @@ where /// assert_relative_eq!(dq_to * dq1, dq2, epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn isometry_to(&self, other: &Self) -> Self { other / self } @@ -520,7 +520,7 @@ where /// ); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn lerp(&self, other: &Self, t: T) -> DualQuaternion { self.as_ref().lerp(other.as_ref(), t) } @@ -549,7 +549,7 @@ where /// ), epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn nlerp(&self, other: &Self, t: T) -> Self { let mut res = self.lerp(other, t); let _ = res.normalize_mut(); @@ -585,7 +585,7 @@ where /// ); /// assert_relative_eq!(dq.translation().vector.y, 3.0, epsilon = 1.0e-6); #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn sclerp(&self, other: &Self, t: T) -> Self where T: RealField, @@ -605,7 +605,7 @@ where /// * `epsilon`: the value below which the sinus of the angle separating both quaternion /// must be to return `None`. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn try_sclerp(&self, other: &Self, t: T, epsilon: T) -> Option where T: RealField, @@ -673,7 +673,7 @@ where /// ); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn rotation(&self) -> UnitQuaternion { Unit::new_unchecked(self.as_ref().real) } @@ -693,7 +693,7 @@ where /// ); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn translation(&self) -> Translation3 { let two = T::one() + T::one(); Translation3::from( @@ -720,7 +720,7 @@ where /// assert_relative_eq!(iso.translation.vector, translation, epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn to_isometry(&self) -> Isometry3 { Isometry3::from_parts(self.translation(), self.rotation()) } @@ -744,7 +744,7 @@ where /// ); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn transform_point(&self, pt: &Point3) -> Point3 { self * pt } @@ -768,7 +768,7 @@ where /// ); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn transform_vector(&self, v: &Vector3) -> Vector3 { self * v } @@ -792,7 +792,7 @@ where /// ); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn inverse_transform_point(&self, pt: &Point3) -> Point3 { self.inverse() * pt } @@ -817,7 +817,7 @@ where /// ); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn inverse_transform_vector(&self, v: &Vector3) -> Vector3 { self.inverse() * v } @@ -843,7 +843,7 @@ where /// ); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn inverse_transform_unit_vector(&self, v: &Unit>) -> Unit> { self.inverse() * v } @@ -871,7 +871,7 @@ where /// assert_relative_eq!(dq.to_homogeneous(), expected, epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn to_homogeneous(&self) -> Matrix4 { self.to_isometry().to_homogeneous() } diff --git a/src/geometry/isometry.rs b/src/geometry/isometry.rs index 19e2ed52..6d3e9127 100755 --- a/src/geometry/isometry.rs +++ b/src/geometry/isometry.rs @@ -267,7 +267,7 @@ where /// assert_eq!(iso1.inverse() * iso2, iso1.inv_mul(&iso2)); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn inv_mul(&self, rhs: &Isometry) -> Self { let inv_rot1 = self.rotation.inverse(); let tr_12 = rhs.translation.vector.clone() - self.translation.vector.clone(); @@ -385,7 +385,7 @@ where /// assert_relative_eq!(transformed_point, Point3::new(3.0, 2.0, 2.0), epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn transform_point(&self, pt: &Point) -> Point { self * pt } @@ -409,7 +409,7 @@ where /// assert_relative_eq!(transformed_point, Vector3::new(3.0, 2.0, -1.0), epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn transform_vector(&self, v: &SVector) -> SVector { self * v } @@ -432,7 +432,7 @@ where /// assert_relative_eq!(transformed_point, Point3::new(0.0, 2.0, 1.0), epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn inverse_transform_point(&self, pt: &Point) -> Point { self.rotation .inverse_transform_point(&(pt - &self.translation.vector)) @@ -457,7 +457,7 @@ where /// assert_relative_eq!(transformed_point, Vector3::new(-3.0, 2.0, 1.0), epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn inverse_transform_vector(&self, v: &SVector) -> SVector { self.rotation.inverse_transform_vector(v) } @@ -481,7 +481,7 @@ where /// assert_relative_eq!(transformed_point, -Vector3::y_axis(), epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn inverse_transform_unit_vector(&self, v: &Unit>) -> Unit> { self.rotation.inverse_transform_unit_vector(v) } @@ -511,7 +511,7 @@ impl Isometry { /// assert_relative_eq!(iso.to_homogeneous(), expected, epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn to_homogeneous(&self) -> OMatrix, U1>, DimNameSum, U1>> where Const: DimNameAdd, @@ -543,7 +543,7 @@ impl Isometry { /// assert_relative_eq!(iso.to_matrix(), expected, epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn to_matrix(&self) -> OMatrix, U1>, DimNameSum, U1>> where Const: DimNameAdd, diff --git a/src/geometry/isometry_interpolation.rs b/src/geometry/isometry_interpolation.rs index 1133ae26..356dbdad 100644 --- a/src/geometry/isometry_interpolation.rs +++ b/src/geometry/isometry_interpolation.rs @@ -26,7 +26,7 @@ impl Isometry3 { /// assert_eq!(iso3.rotation.euler_angles(), (std::f32::consts::FRAC_PI_2, 0.0, 0.0)); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn lerp_slerp(&self, other: &Self, t: T) -> Self where T: RealField, @@ -60,7 +60,7 @@ impl Isometry3 { /// assert_eq!(iso3.rotation.euler_angles(), (std::f32::consts::FRAC_PI_2, 0.0, 0.0)); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn try_lerp_slerp(&self, other: &Self, t: T, epsilon: T) -> Option where T: RealField, @@ -96,7 +96,7 @@ impl IsometryMatrix3 { /// assert_eq!(iso3.rotation.euler_angles(), (std::f32::consts::FRAC_PI_2, 0.0, 0.0)); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn lerp_slerp(&self, other: &Self, t: T) -> Self where T: RealField, @@ -130,7 +130,7 @@ impl IsometryMatrix3 { /// assert_eq!(iso3.rotation.euler_angles(), (std::f32::consts::FRAC_PI_2, 0.0, 0.0)); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn try_lerp_slerp(&self, other: &Self, t: T, epsilon: T) -> Option where T: RealField, @@ -167,7 +167,7 @@ impl Isometry2 { /// assert_relative_eq!(iso3.rotation.angle(), std::f32::consts::FRAC_PI_2); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn lerp_slerp(&self, other: &Self, t: T) -> Self where T: RealField, @@ -204,7 +204,7 @@ impl IsometryMatrix2 { /// assert_relative_eq!(iso3.rotation.angle(), std::f32::consts::FRAC_PI_2); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn lerp_slerp(&self, other: &Self, t: T) -> Self where T: RealField, diff --git a/src/geometry/orthographic.rs b/src/geometry/orthographic.rs index 1a02ebc8..6cc4dacc 100644 --- a/src/geometry/orthographic.rs +++ b/src/geometry/orthographic.rs @@ -188,7 +188,7 @@ impl Orthographic3 { /// assert_relative_eq!(proj.as_matrix() * inv, Matrix4::identity()); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn inverse(&self) -> Matrix4 { let mut res = self.to_homogeneous(); @@ -222,7 +222,7 @@ impl Orthographic3 { /// assert_eq!(proj.to_homogeneous(), expected); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn to_homogeneous(&self) -> Matrix4 { self.matrix } @@ -242,7 +242,7 @@ impl Orthographic3 { /// assert_eq!(*proj.as_matrix(), expected); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn as_matrix(&self) -> &Matrix4 { &self.matrix } @@ -256,7 +256,7 @@ impl Orthographic3 { /// assert_eq!(proj.as_projective().to_homogeneous(), proj.to_homogeneous()); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn as_projective(&self) -> &Projective3 { unsafe { mem::transmute(self) } } @@ -270,7 +270,7 @@ impl Orthographic3 { /// assert_eq!(proj.to_projective().to_homogeneous(), proj.to_homogeneous()); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn to_projective(&self) -> Projective3 { Projective3::from_matrix_unchecked(self.matrix) } @@ -315,7 +315,7 @@ impl Orthographic3 { /// assert_relative_eq!(proj.left(), 10.0, epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn left(&self) -> T { (-T::one() - self.matrix[(0, 3)]) / self.matrix[(0, 0)] } @@ -332,7 +332,7 @@ impl Orthographic3 { /// assert_relative_eq!(proj.right(), 1.0, epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn right(&self) -> T { (T::one() - self.matrix[(0, 3)]) / self.matrix[(0, 0)] } @@ -349,7 +349,7 @@ impl Orthographic3 { /// assert_relative_eq!(proj.bottom(), 20.0, epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn bottom(&self) -> T { (-T::one() - self.matrix[(1, 3)]) / self.matrix[(1, 1)] } @@ -366,7 +366,7 @@ impl Orthographic3 { /// assert_relative_eq!(proj.top(), 2.0, epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn top(&self) -> T { (T::one() - self.matrix[(1, 3)]) / self.matrix[(1, 1)] } @@ -383,7 +383,7 @@ impl Orthographic3 { /// assert_relative_eq!(proj.znear(), 1000.0, epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn znear(&self) -> T { (T::one() + self.matrix[(2, 3)]) / self.matrix[(2, 2)] } @@ -400,7 +400,7 @@ impl Orthographic3 { /// assert_relative_eq!(proj.zfar(), 0.1, epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn zfar(&self) -> T { (-T::one() + self.matrix[(2, 3)]) / self.matrix[(2, 2)] } @@ -433,7 +433,7 @@ impl Orthographic3 { /// assert_relative_eq!(proj.project_point(&p8), Point3::new( 1.0, 1.0, 1.0)); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn project_point(&self, p: &Point3) -> Point3 { Point3::new( self.matrix[(0, 0)] * p[0] + self.matrix[(0, 3)], @@ -469,7 +469,7 @@ impl Orthographic3 { /// assert_relative_eq!(proj.unproject_point(&p8), Point3::new(10.0, 20.0, -1000.0), epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn unproject_point(&self, p: &Point3) -> Point3 { Point3::new( (p[0] - self.matrix[(0, 3)]) / self.matrix[(0, 0)], @@ -498,7 +498,7 @@ impl Orthographic3 { /// assert_relative_eq!(proj.project_vector(&v3), Vector3::z() * -2.0 / 999.9); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn project_vector(&self, p: &Vector) -> Vector3 where SB: Storage, diff --git a/src/geometry/perspective.rs b/src/geometry/perspective.rs index c300b292..65aee5fd 100644 --- a/src/geometry/perspective.rs +++ b/src/geometry/perspective.rs @@ -104,7 +104,7 @@ impl Perspective3 { /// Retrieves the inverse of the underlying homogeneous matrix. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn inverse(&self) -> Matrix4 { let mut res = self.to_homogeneous(); @@ -124,28 +124,28 @@ impl Perspective3 { /// Computes the corresponding homogeneous matrix. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn to_homogeneous(&self) -> Matrix4 { self.matrix.clone_owned() } /// A reference to the underlying homogeneous transformation matrix. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn as_matrix(&self) -> &Matrix4 { &self.matrix } /// A reference to this transformation seen as a `Projective3`. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn as_projective(&self) -> &Projective3 { unsafe { mem::transmute(self) } } /// This transformation seen as a `Projective3`. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn to_projective(&self) -> Projective3 { Projective3::from_matrix_unchecked(self.matrix) } @@ -166,21 +166,21 @@ impl Perspective3 { /// Gets the `width / height` aspect ratio of the view frustum. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn aspect(&self) -> T { self.matrix[(1, 1)] / self.matrix[(0, 0)] } /// Gets the y field of view of the view frustum. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn fovy(&self) -> T { (T::one() / self.matrix[(1, 1)]).atan() * crate::convert(2.0) } /// Gets the near plane offset of the view frustum. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn znear(&self) -> T { let ratio = (-self.matrix[(2, 2)] + T::one()) / (-self.matrix[(2, 2)] - T::one()); @@ -190,7 +190,7 @@ impl Perspective3 { /// Gets the far plane offset of the view frustum. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn zfar(&self) -> T { let ratio = (-self.matrix[(2, 2)] + T::one()) / (-self.matrix[(2, 2)] - T::one()); @@ -202,7 +202,7 @@ impl Perspective3 { // TODO: when we get specialization, specialize the Mul impl instead. /// Projects a point. Faster than matrix multiplication. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn project_point(&self, p: &Point3) -> Point3 { let inverse_denom = -T::one() / p[2]; Point3::new( @@ -214,7 +214,7 @@ impl Perspective3 { /// Un-projects a point. Faster than multiplication by the matrix inverse. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn unproject_point(&self, p: &Point3) -> Point3 { let inverse_denom = self.matrix[(2, 3)] / (p[2] + self.matrix[(2, 2)]); @@ -228,7 +228,7 @@ impl Perspective3 { // TODO: when we get specialization, specialize the Mul impl instead. /// Projects a vector. Faster than matrix multiplication. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn project_vector(&self, p: &Vector) -> Vector3 where SB: Storage, diff --git a/src/geometry/point.rs b/src/geometry/point.rs index 8a9bb040..89db12cc 100644 --- a/src/geometry/point.rs +++ b/src/geometry/point.rs @@ -122,7 +122,7 @@ impl Point { /// assert_eq!(p.map(|e| e as u32), Point3::new(1, 2, 3)); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn map T2>(&self, f: F) -> Point { self.coords.map(f).into() } @@ -162,7 +162,7 @@ impl Point { /// assert_eq!(p.to_homogeneous(), Vector4::new(10.0, 20.0, 30.0, 1.0)); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn to_homogeneous(&self) -> OVector, U1>> where T: One, @@ -201,7 +201,7 @@ impl Point { /// assert_eq!(p.len(), 3); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn len(&self) -> usize { self.coords.len() } @@ -215,7 +215,7 @@ impl Point { /// assert!(!p.is_empty()); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn is_empty(&self) -> bool { self.len() == 0 } @@ -250,7 +250,7 @@ impl Point { /// Gets a reference to i-th element of this point without bound-checking. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub unsafe fn get_unchecked(&self, i: usize) -> &T { self.coords.vget_unchecked(i) } @@ -383,21 +383,21 @@ impl PartialOrd for Point { impl Point { /// Computes the infimum (aka. componentwise min) of two points. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn inf(&self, other: &Self) -> Point { self.coords.inf(&other.coords).into() } /// Computes the supremum (aka. componentwise max) of two points. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn sup(&self, other: &Self) -> Point { self.coords.sup(&other.coords).into() } /// Computes the (infimum, supremum) of two points. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn inf_sup(&self, other: &Self) -> (Point, Point) { let (inf, sup) = self.coords.inf_sup(&other.coords); (inf.into(), sup.into()) diff --git a/src/geometry/quaternion.rs b/src/geometry/quaternion.rs index 79bca5ac..79fda90a 100755 --- a/src/geometry/quaternion.rs +++ b/src/geometry/quaternion.rs @@ -191,7 +191,7 @@ where /// The imaginary part of this quaternion. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn imag(&self) -> Vector3 { self.coords.xyz() } @@ -224,7 +224,7 @@ where /// assert_eq!(q1.lerp(&q2, 0.1), Quaternion::new(1.9, 3.8, 5.7, 7.6)); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn lerp(&self, other: &Self, t: T) -> Self { self * (T::one() - t) + other * t } @@ -240,7 +240,7 @@ where /// assert_eq!(q.vector()[2], 4.0); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn vector(&self) -> MatrixSlice, CStride> { self.coords.fixed_rows::<3>(0) } @@ -254,7 +254,7 @@ where /// assert_eq!(q.scalar(), 1.0); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn scalar(&self) -> T { self.coords[3] } @@ -270,7 +270,7 @@ where /// assert_eq!(*q.as_vector(), Vector4::new(2.0, 3.0, 4.0, 1.0)); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn as_vector(&self) -> &Vector4 { &self.coords } @@ -285,7 +285,7 @@ where /// assert_relative_eq!(q.norm(), 5.47722557, epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn norm(&self) -> T { self.coords.norm() } @@ -303,7 +303,7 @@ where /// assert_relative_eq!(q.magnitude(), 5.47722557, epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn magnitude(&self) -> T { self.norm() } @@ -317,7 +317,7 @@ where /// assert_eq!(q.magnitude_squared(), 30.0); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn norm_squared(&self) -> T { self.coords.norm_squared() } @@ -334,7 +334,7 @@ where /// assert_eq!(q.magnitude_squared(), 30.0); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn magnitude_squared(&self) -> T { self.norm_squared() } @@ -349,7 +349,7 @@ where /// assert_eq!(q1.dot(&q2), 70.0); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn dot(&self, rhs: &Self) -> T { self.coords.dot(&rhs.coords) } @@ -419,7 +419,7 @@ where /// let result = a.inner(&b); /// assert_relative_eq!(expected, result, epsilon = 1.0e-5); #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn inner(&self, other: &Self) -> Self { (self * other + other * self).half() } @@ -439,7 +439,7 @@ where /// assert_relative_eq!(expected, result, epsilon = 1.0e-5); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn outer(&self, other: &Self) -> Self { #[allow(clippy::eq_op)] (self * other - other * self).half() @@ -460,7 +460,7 @@ where /// assert_relative_eq!(expected, result, epsilon = 1.0e-5); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn project(&self, other: &Self) -> Option where T: RealField, @@ -483,7 +483,7 @@ where /// assert_relative_eq!(expected, result, epsilon = 1.0e-5); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn reject(&self, other: &Self) -> Option where T: RealField, @@ -506,7 +506,7 @@ where /// assert_eq!(half_ang, f32::consts::FRAC_PI_2); /// assert_eq!(axis, Some(Vector3::x_axis())); /// ``` - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn polar_decomposition(&self) -> (T, T, Option>>) where T: RealField, @@ -534,7 +534,7 @@ where /// assert_relative_eq!(q.ln(), Quaternion::new(1.683647, 1.190289, 0.0, 0.0), epsilon = 1.0e-6) /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn ln(&self) -> Self { let n = self.norm(); let v = self.vector(); @@ -553,7 +553,7 @@ where /// assert_relative_eq!(q.exp(), Quaternion::new(2.0, 5.0, 0.0, 0.0), epsilon = 1.0e-5) /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn exp(&self) -> Self { self.exp_eps(T::simd_default_epsilon()) } @@ -573,7 +573,7 @@ where /// assert_eq!(q.exp_eps(1.0e-6), Quaternion::identity()); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn exp_eps(&self, eps: T) -> Self { let v = self.vector(); let nn = v.norm_squared(); @@ -597,7 +597,7 @@ where /// assert_relative_eq!(q.powf(1.5), Quaternion::new( -6.2576659, 4.1549037, 6.2323556, 8.3098075), epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn powf(&self, n: T) -> Self { (self.ln() * n).exp() } @@ -693,21 +693,21 @@ where /// Calculates square of a quaternion. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn squared(&self) -> Self { self * self } /// Divides quaternion into two. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn half(&self) -> Self { self / crate::convert(2.0f64) } /// Calculates square root. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn sqrt(&self) -> Self { self.powf(crate::convert(0.5)) } @@ -716,14 +716,14 @@ where /// /// A quaternion is pure if it has no real part (`self.w == 0.0`). #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn is_pure(&self) -> bool { self.w.is_zero() } /// Convert quaternion to pure quaternion. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn pure(&self) -> Self { Self::from_imag(self.imag()) } @@ -732,7 +732,7 @@ where /// /// Calculates B-1 * A where A = self, B = other. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn left_div(&self, other: &Self) -> Option where T: RealField, @@ -755,7 +755,7 @@ where /// assert_relative_eq!(expected, result, epsilon = 1.0e-7); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn right_div(&self, other: &Self) -> Option where T: RealField, @@ -775,7 +775,7 @@ where /// assert_relative_eq!(expected, result, epsilon = 1.0e-7); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn cos(&self) -> Self { let z = self.imag().magnitude(); let w = -self.w.simd_sin() * z.simd_sinhc(); @@ -793,7 +793,7 @@ where /// assert_relative_eq!(input, result, epsilon = 1.0e-7); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn acos(&self) -> Self { let u = Self::from_imag(self.imag().normalize()); let identity = Self::identity(); @@ -815,7 +815,7 @@ where /// assert_relative_eq!(expected, result, epsilon = 1.0e-7); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn sin(&self) -> Self { let z = self.imag().magnitude(); let w = self.w.simd_cos() * z.simd_sinhc(); @@ -833,7 +833,7 @@ where /// assert_relative_eq!(input, result, epsilon = 1.0e-7); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn asin(&self) -> Self { let u = Self::from_imag(self.imag().normalize()); let identity = Self::identity(); @@ -855,7 +855,7 @@ where /// assert_relative_eq!(expected, result, epsilon = 1.0e-7); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn tan(&self) -> Self where T: RealField, @@ -874,7 +874,7 @@ where /// assert_relative_eq!(input, result, epsilon = 1.0e-7); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn atan(&self) -> Self where T: RealField, @@ -899,7 +899,7 @@ where /// assert_relative_eq!(expected, result, epsilon = 1.0e-7); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn sinh(&self) -> Self { (self.exp() - (-self).exp()).half() } @@ -916,7 +916,7 @@ where /// assert_relative_eq!(expected, result, epsilon = 1.0e-7); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn asinh(&self) -> Self { let identity = Self::identity(); (self + (identity + self.squared()).sqrt()).ln() @@ -934,7 +934,7 @@ where /// assert_relative_eq!(expected, result, epsilon = 1.0e-7); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn cosh(&self) -> Self { (self.exp() + (-self).exp()).half() } @@ -951,7 +951,7 @@ where /// assert_relative_eq!(expected, result, epsilon = 1.0e-7); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn acosh(&self) -> Self { let identity = Self::identity(); (self + (self + identity).sqrt() * (self - identity).sqrt()).ln() @@ -969,7 +969,7 @@ where /// assert_relative_eq!(expected, result, epsilon = 1.0e-7); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn tanh(&self) -> Self where T: RealField, @@ -989,7 +989,7 @@ where /// assert_relative_eq!(expected, result, epsilon = 1.0e-7); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn atanh(&self) -> Self { let identity = Self::identity(); ((identity + self).ln() - (identity - self).ln()).half() @@ -1107,7 +1107,7 @@ where /// assert_eq!(rot.angle(), 1.78); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn angle(&self) -> T { let w = self.quaternion().scalar().simd_abs(); self.quaternion().imag().norm().simd_atan2(w) * crate::convert(2.0f64) @@ -1124,7 +1124,7 @@ where /// assert_eq!(*axis.quaternion(), Quaternion::new(1.0, 0.0, 0.0, 0.0)); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn quaternion(&self) -> &Quaternion { self.as_ref() } @@ -1173,7 +1173,7 @@ where /// assert_relative_eq!(rot1.angle_to(&rot2), 1.0045657, epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn angle_to(&self, other: &Self) -> T { let delta = self.rotation_to(other); delta.angle() @@ -1193,7 +1193,7 @@ where /// assert_relative_eq!(rot_to * rot1, rot2, epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn rotation_to(&self, other: &Self) -> Self { other / self } @@ -1210,7 +1210,7 @@ where /// assert_eq!(q1.lerp(&q2, 0.1), Quaternion::new(0.9, 0.1, 0.0, 0.0)); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn lerp(&self, other: &Self, t: T) -> Quaternion { self.as_ref().lerp(other.as_ref(), t) } @@ -1227,7 +1227,7 @@ where /// assert_eq!(q1.nlerp(&q2, 0.1), UnitQuaternion::new_normalize(Quaternion::new(0.9, 0.1, 0.0, 0.0))); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn nlerp(&self, other: &Self, t: T) -> Self { let mut res = self.lerp(other, t); let _ = res.normalize_mut(); @@ -1253,7 +1253,7 @@ where /// assert_eq!(q.euler_angles(), (std::f32::consts::FRAC_PI_2, 0.0, 0.0)); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn slerp(&self, other: &Self, t: T) -> Self where T: RealField, @@ -1273,7 +1273,7 @@ where /// * `epsilon`: the value below which the sinus of the angle separating both quaternion /// must be to return `None`. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn try_slerp(&self, other: &Self, t: T, epsilon: T) -> Option where T: RealField, @@ -1333,7 +1333,7 @@ where /// assert!(rot.axis().is_none()); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn axis(&self) -> Option>> where T: RealField, @@ -1358,7 +1358,7 @@ where /// assert_relative_eq!(rot.scaled_axis(), axisangle, epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn scaled_axis(&self) -> Vector3 where T: RealField, @@ -1387,7 +1387,7 @@ where /// assert!(rot.axis_angle().is_none()); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn axis_angle(&self) -> Option<(Unit>, T)> where T: RealField, @@ -1399,7 +1399,7 @@ where /// /// Note that this function yields a `Quaternion` because it loses the unit property. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn exp(&self) -> Quaternion { self.as_ref().exp() } @@ -1419,7 +1419,7 @@ where /// assert_relative_eq!(q.ln().vector().into_owned(), axisangle, epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn ln(&self) -> Quaternion where T: RealField, @@ -1448,7 +1448,7 @@ where /// assert_eq!(pow.angle(), 2.4); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn powf(&self, n: T) -> Self where T: RealField, @@ -1477,7 +1477,7 @@ where /// assert_relative_eq!(*rot.matrix(), expected, epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn to_rotation_matrix(&self) -> Rotation { let i = self.as_ref()[0]; let j = self.as_ref()[1]; @@ -1535,7 +1535,7 @@ where /// assert_relative_eq!(euler.2, 0.3, epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn euler_angles(&self) -> (T, T, T) where T: RealField, @@ -1560,7 +1560,7 @@ where /// assert_relative_eq!(rot.to_homogeneous(), expected, epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn to_homogeneous(&self) -> Matrix4 { self.to_rotation_matrix().to_homogeneous() } @@ -1581,7 +1581,7 @@ where /// assert_relative_eq!(transformed_point, Point3::new(3.0, 2.0, -1.0), epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn transform_point(&self, pt: &Point3) -> Point3 { self * pt } @@ -1602,7 +1602,7 @@ where /// assert_relative_eq!(transformed_vector, Vector3::new(3.0, 2.0, -1.0), epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn transform_vector(&self, v: &Vector3) -> Vector3 { self * v } @@ -1623,7 +1623,7 @@ where /// assert_relative_eq!(transformed_point, Point3::new(-3.0, 2.0, 1.0), epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn inverse_transform_point(&self, pt: &Point3) -> Point3 { // TODO: would it be useful performancewise not to call inverse explicitly (i-e. implement // the inverse transformation explicitly here) ? @@ -1646,7 +1646,7 @@ where /// assert_relative_eq!(transformed_vector, Vector3::new(-3.0, 2.0, 1.0), epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn inverse_transform_vector(&self, v: &Vector3) -> Vector3 { self.inverse() * v } @@ -1667,7 +1667,7 @@ where /// assert_relative_eq!(transformed_vector, -Vector3::y_axis(), epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn inverse_transform_unit_vector(&self, v: &Unit>) -> Unit> { self.inverse() * v } @@ -1676,7 +1676,7 @@ where /// /// This is faster, but approximate, way to compute `UnitQuaternion::new(axisangle) * self`. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn append_axisangle_linearized(&self, axisangle: &Vector3) -> Self { let half: T = crate::convert(0.5); let q1 = self.into_inner(); diff --git a/src/geometry/reflection.rs b/src/geometry/reflection.rs index 7a34d972..dcc754c2 100644 --- a/src/geometry/reflection.rs +++ b/src/geometry/reflection.rs @@ -34,7 +34,7 @@ impl> Reflection { } /// The reflexion axis. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn axis(&self) -> &Vector { &self.axis } diff --git a/src/geometry/rotation.rs b/src/geometry/rotation.rs index 9950568d..f3127fb9 100755 --- a/src/geometry/rotation.rs +++ b/src/geometry/rotation.rs @@ -185,7 +185,7 @@ impl Rotation { /// assert_eq!(*rot.matrix(), expected); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn matrix(&self) -> &SMatrix { &self.matrix } @@ -263,7 +263,7 @@ impl Rotation { /// assert_eq!(rot.to_homogeneous(), expected); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn to_homogeneous(&self) -> OMatrix, U1>, DimNameSum, U1>> where T: Zero + One, @@ -405,7 +405,7 @@ where /// assert_relative_eq!(transformed_point, Point3::new(3.0, 2.0, -1.0), epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn transform_point(&self, pt: &Point) -> Point { self * pt } @@ -425,7 +425,7 @@ where /// assert_relative_eq!(transformed_vector, Vector3::new(3.0, 2.0, -1.0), epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn transform_vector(&self, v: &SVector) -> SVector { self * v } @@ -445,7 +445,7 @@ where /// assert_relative_eq!(transformed_point, Point3::new(-3.0, 2.0, 1.0), epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn inverse_transform_point(&self, pt: &Point) -> Point { Point::from(self.inverse_transform_vector(&pt.coords)) } @@ -465,7 +465,7 @@ where /// assert_relative_eq!(transformed_vector, Vector3::new(-3.0, 2.0, 1.0), epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn inverse_transform_vector(&self, v: &SVector) -> SVector { self.matrix().tr_mul(v) } @@ -485,7 +485,7 @@ where /// assert_relative_eq!(transformed_vector, -Vector3::y_axis(), epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn inverse_transform_unit_vector(&self, v: &Unit>) -> Unit> { Unit::new_unchecked(self.inverse_transform_vector(&**v)) } diff --git a/src/geometry/rotation_interpolation.rs b/src/geometry/rotation_interpolation.rs index 6c724b21..6b5a5c11 100644 --- a/src/geometry/rotation_interpolation.rs +++ b/src/geometry/rotation_interpolation.rs @@ -18,7 +18,7 @@ impl Rotation2 { /// assert_relative_eq!(rot.angle(), std::f32::consts::FRAC_PI_2); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn slerp(&self, other: &Self, t: T) -> Self where T::Element: SimdRealField, @@ -48,7 +48,7 @@ impl Rotation3 { /// assert_eq!(q.euler_angles(), (std::f32::consts::FRAC_PI_2, 0.0, 0.0)); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn slerp(&self, other: &Self, t: T) -> Self where T: RealField, @@ -69,7 +69,7 @@ impl Rotation3 { /// * `epsilon`: the value below which the sinus of the angle separating both rotations /// must be to return `None`. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn try_slerp(&self, other: &Self, t: T, epsilon: T) -> Option where T: RealField, diff --git a/src/geometry/rotation_specialization.rs b/src/geometry/rotation_specialization.rs index 4000e239..a89f5845 100644 --- a/src/geometry/rotation_specialization.rs +++ b/src/geometry/rotation_specialization.rs @@ -186,7 +186,7 @@ impl Rotation2 { /// assert_relative_eq!(rot_to.inverse() * rot2, rot1); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn rotation_to(&self, other: &Self) -> Self { other * self.inverse() } @@ -216,7 +216,7 @@ impl Rotation2 { /// assert_relative_eq!(pow.angle(), 2.0 * 0.78); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn powf(&self, n: T) -> Self { Self::new(self.angle() * n) } @@ -234,7 +234,7 @@ impl Rotation2 { /// assert_relative_eq!(rot.angle(), 1.78); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn angle(&self) -> T { self.matrix()[(1, 0)].simd_atan2(self.matrix()[(0, 0)]) } @@ -250,7 +250,7 @@ impl Rotation2 { /// assert_relative_eq!(rot1.angle_to(&rot2), 1.6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn angle_to(&self, other: &Self) -> T { self.rotation_to(other).angle() } @@ -260,7 +260,7 @@ impl Rotation2 { /// This is generally used in the context of generic programming. Using /// the `.angle()` method instead is more common. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn scaled_axis(&self) -> SVector { Vector1::new(self.angle()) } @@ -645,7 +645,7 @@ where /// assert_relative_eq!(rot_to * rot1, rot2, epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn rotation_to(&self, other: &Self) -> Self { other * self.inverse() } @@ -665,7 +665,7 @@ where /// assert_eq!(pow.angle(), 2.4); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn powf(&self, n: T) -> Self where T: RealField, @@ -772,7 +772,7 @@ impl Rotation3 { /// assert_relative_eq!(rot.angle(), 1.78); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn angle(&self) -> T { ((self.matrix()[(0, 0)] + self.matrix()[(1, 1)] + self.matrix()[(2, 2)] - T::one()) / crate::convert(2.0)) @@ -795,7 +795,7 @@ impl Rotation3 { /// assert!(rot.axis().is_none()); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn axis(&self) -> Option>> where T: RealField, @@ -820,7 +820,7 @@ impl Rotation3 { /// assert_relative_eq!(rot.scaled_axis(), axisangle, epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn scaled_axis(&self) -> Vector3 where T: RealField, @@ -852,7 +852,7 @@ impl Rotation3 { /// assert!(rot.axis_angle().is_none()); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn axis_angle(&self) -> Option<(Unit>, T)> where T: RealField, @@ -875,7 +875,7 @@ impl Rotation3 { /// assert_relative_eq!(rot1.angle_to(&rot2), 1.0045657, epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn angle_to(&self, other: &Self) -> T where T::Element: SimdRealField, @@ -908,7 +908,7 @@ impl Rotation3 { /// assert_relative_eq!(euler.1, 0.2, epsilon = 1.0e-6); /// assert_relative_eq!(euler.2, 0.3, epsilon = 1.0e-6); /// ``` - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn euler_angles(&self) -> (T, T, T) where T: RealField, diff --git a/src/geometry/similarity.rs b/src/geometry/similarity.rs index 6a1fe095..516b95c5 100755 --- a/src/geometry/similarity.rs +++ b/src/geometry/similarity.rs @@ -122,7 +122,7 @@ where impl Similarity { /// The scaling factor of this similarity transformation. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn scaling(&self) -> T { self.scaling.inlined_clone() } @@ -249,7 +249,7 @@ where /// assert_relative_eq!(transformed_point, Point3::new(19.0, 17.0, -9.0), epsilon = 1.0e-5); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn transform_point(&self, pt: &Point) -> Point { self * pt } @@ -271,7 +271,7 @@ where /// assert_relative_eq!(transformed_vector, Vector3::new(18.0, 15.0, -12.0), epsilon = 1.0e-5); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn transform_vector(&self, v: &SVector) -> SVector { self * v } @@ -292,7 +292,7 @@ where /// assert_relative_eq!(transformed_point, Point3::new(-1.5, 1.5, 1.5), epsilon = 1.0e-5); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn inverse_transform_point(&self, pt: &Point) -> Point { self.isometry.inverse_transform_point(pt) / self.scaling() } @@ -313,7 +313,7 @@ where /// assert_relative_eq!(transformed_vector, Vector3::new(-3.0, 2.5, 2.0), epsilon = 1.0e-5); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn inverse_transform_vector(&self, v: &SVector) -> SVector { self.isometry.inverse_transform_vector(v) / self.scaling() } @@ -326,7 +326,7 @@ where impl Similarity { /// Converts this similarity into its equivalent homogeneous transformation matrix. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn to_homogeneous(&self) -> OMatrix, U1>, DimNameSum, U1>> where Const: DimNameAdd, diff --git a/src/geometry/swizzle.rs b/src/geometry/swizzle.rs index 74f423ff..0ad51f00 100644 --- a/src/geometry/swizzle.rs +++ b/src/geometry/swizzle.rs @@ -8,7 +8,7 @@ macro_rules! impl_swizzle { $( /// Builds a new point from components of `self`. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn $name(&self) -> $Result where as ToTypenum>::Typenum: Cmp { $Result::new($(self[$i].inlined_clone()),*) diff --git a/src/geometry/transform.rs b/src/geometry/transform.rs index a62c5ede..8c294b15 100755 --- a/src/geometry/transform.rs +++ b/src/geometry/transform.rs @@ -301,7 +301,7 @@ where /// assert_eq!(*t.matrix(), m); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn matrix(&self) -> &OMatrix, U1>, DimNameSum, U1>> { &self.matrix } @@ -368,7 +368,7 @@ where /// assert_eq!(t.into_inner(), m); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn to_homogeneous(&self) -> OMatrix, U1>, DimNameSum, U1>> { self.matrix().clone_owned() } @@ -500,7 +500,7 @@ where /// /// This is the same as the multiplication `self * pt`. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn transform_point(&self, pt: &Point) -> Point { self * pt } @@ -510,7 +510,7 @@ where /// /// This is the same as the multiplication `self * v`. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn transform_vector(&self, v: &SVector) -> SVector { self * v } @@ -528,7 +528,7 @@ where /// This may be cheaper than inverting the transformation and transforming /// the point. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn inverse_transform_point(&self, pt: &Point) -> Point { self.clone().inverse() * pt } @@ -537,7 +537,7 @@ where /// This may be cheaper than inverting the transformation and transforming /// the vector. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn inverse_transform_vector(&self, v: &SVector) -> SVector { self.clone().inverse() * v } diff --git a/src/geometry/translation.rs b/src/geometry/translation.rs index 98ee4636..1476e75b 100755 --- a/src/geometry/translation.rs +++ b/src/geometry/translation.rs @@ -190,7 +190,7 @@ impl Translation { /// assert_eq!(t.to_homogeneous(), expected); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn to_homogeneous(&self) -> OMatrix, U1>, DimNameSum, U1>> where T: Zero + One, @@ -242,7 +242,7 @@ impl Translation { /// let transformed_point = t.transform_point(&Point3::new(4.0, 5.0, 6.0)); /// assert_eq!(transformed_point, Point3::new(5.0, 7.0, 9.0)); #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn transform_point(&self, pt: &Point) -> Point { pt + &self.vector } @@ -258,7 +258,7 @@ impl Translation { /// let transformed_point = t.inverse_transform_point(&Point3::new(4.0, 5.0, 6.0)); /// assert_eq!(transformed_point, Point3::new(3.0, 3.0, 3.0)); #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn inverse_transform_point(&self, pt: &Point) -> Point { pt - &self.vector } diff --git a/src/geometry/unit_complex.rs b/src/geometry/unit_complex.rs index 414ca425..be0c8980 100755 --- a/src/geometry/unit_complex.rs +++ b/src/geometry/unit_complex.rs @@ -84,7 +84,7 @@ where /// assert_eq!(rot.angle(), 1.78); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn angle(&self) -> T { self.im.simd_atan2(self.re) } @@ -99,7 +99,7 @@ where /// assert_eq!(rot.sin_angle(), angle.sin()); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn sin_angle(&self) -> T { self.im } @@ -114,7 +114,7 @@ where /// assert_eq!(rot.cos_angle(),angle.cos()); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn cos_angle(&self) -> T { self.re } @@ -124,7 +124,7 @@ where /// This is generally used in the context of generic programming. Using /// the `.angle()` method instead is more common. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn scaled_axis(&self) -> Vector1 { Vector1::new(self.angle()) } @@ -135,7 +135,7 @@ where /// the `.angle()` method instead is more common. /// Returns `None` if the angle is zero. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn axis_angle(&self) -> Option<(Unit>, T)> where T: RealField, @@ -162,7 +162,7 @@ where /// assert_relative_eq!(rot1.angle_to(&rot2), 1.6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn angle_to(&self, other: &Self) -> T { let delta = self.rotation_to(other); delta.angle() @@ -260,7 +260,7 @@ where /// assert_eq!(rot.to_rotation_matrix(), expected); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn to_rotation_matrix(&self) -> Rotation2 { let r = self.re; let i = self.im; @@ -281,7 +281,7 @@ where /// assert_eq!(rot.to_homogeneous(), expected); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn to_homogeneous(&self) -> Matrix3 { self.to_rotation_matrix().to_homogeneous() } @@ -306,7 +306,7 @@ where /// assert_relative_eq!(transformed_point, Point2::new(-2.0, 1.0), epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn transform_point(&self, pt: &Point2) -> Point2 { self * pt } @@ -325,7 +325,7 @@ where /// assert_relative_eq!(transformed_vector, Vector2::new(-2.0, 1.0), epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn transform_vector(&self, v: &Vector2) -> Vector2 { self * v } @@ -342,7 +342,7 @@ where /// assert_relative_eq!(transformed_point, Point2::new(2.0, -1.0), epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn inverse_transform_point(&self, pt: &Point2) -> Point2 { // TODO: would it be useful performancewise not to call inverse explicitly (i-e. implement // the inverse transformation explicitly here) ? @@ -361,7 +361,7 @@ where /// assert_relative_eq!(transformed_vector, Vector2::new(2.0, -1.0), epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn inverse_transform_vector(&self, v: &Vector2) -> Vector2 { self.inverse() * v } @@ -378,7 +378,7 @@ where /// assert_relative_eq!(transformed_vector, -Vector2::y_axis(), epsilon = 1.0e-6); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn inverse_transform_unit_vector(&self, v: &Unit>) -> Unit> { self.inverse() * v } @@ -405,7 +405,7 @@ where /// assert_relative_eq!(rot.angle(), std::f32::consts::FRAC_PI_2); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn slerp(&self, other: &Self, t: T) -> Self { Self::new(self.angle() * (T::one() - t) + other.angle() * t) } diff --git a/src/geometry/unit_complex_construction.rs b/src/geometry/unit_complex_construction.rs index 6a3ad6de..16e605f2 100644 --- a/src/geometry/unit_complex_construction.rs +++ b/src/geometry/unit_complex_construction.rs @@ -148,7 +148,7 @@ where /// assert_eq!(*rot.complex(), Complex::new(angle.cos(), angle.sin())); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn complex(&self) -> &Complex { self.as_ref() } @@ -245,7 +245,7 @@ where /// assert_relative_eq!(rot_to.inverse() * rot2, rot1); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn rotation_to(&self, other: &Self) -> Self { other / self } @@ -264,7 +264,7 @@ where /// assert_relative_eq!(pow.angle(), 2.0 * 0.78); /// ``` #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn powf(&self, n: T) -> Self { Self::from_angle(self.angle() * n) } diff --git a/src/linalg/bidiagonal.rs b/src/linalg/bidiagonal.rs index d8997196..6a462988 100644 --- a/src/linalg/bidiagonal.rs +++ b/src/linalg/bidiagonal.rs @@ -153,7 +153,7 @@ where /// Indicates whether this decomposition contains an upper-diagonal matrix. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn is_upper_diagonal(&self) -> bool { self.upper_diagonal } @@ -189,7 +189,7 @@ where /// Retrieves the upper trapezoidal submatrix `R` of this decomposition. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn d(&self) -> OMatrix, DimMinimum> where DefaultAllocator: Allocator, DimMinimum>, @@ -209,7 +209,7 @@ where /// Computes the orthogonal matrix `U` of this `U * D * V` decomposition. // TODO: code duplication with householder::assemble_q. // Except that we are returning a rectangular matrix here. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn u(&self) -> OMatrix> where DefaultAllocator: Allocator>, @@ -240,7 +240,7 @@ where } /// Computes the orthogonal matrix `V_t` of this `U * D * V_t` decomposition. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn v_t(&self) -> OMatrix, C> where DefaultAllocator: Allocator, C>, @@ -278,7 +278,7 @@ where } /// The diagonal part of this decomposed matrix. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn diagonal(&self) -> OVector> where DefaultAllocator: Allocator>, @@ -287,7 +287,7 @@ where } /// The off-diagonal part of this decomposed matrix. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn off_diagonal(&self) -> OVector, U1>> where DefaultAllocator: Allocator, U1>>, diff --git a/src/linalg/cholesky.rs b/src/linalg/cholesky.rs index 60f1f0f5..1e352560 100644 --- a/src/linalg/cholesky.rs +++ b/src/linalg/cholesky.rs @@ -92,7 +92,7 @@ where /// Retrieves the lower-triangular factor of the Cholesky decomposition with its strictly /// uppen-triangular part filled with zeros. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn l(&self) -> OMatrix { self.chol.lower_triangle() } @@ -102,7 +102,7 @@ where /// /// This is an allocation-less version of `self.l()`. The values of the strict upper-triangular /// part are garbage and should be ignored by further computations. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn l_dirty(&self) -> &OMatrix { &self.chol } @@ -144,7 +144,7 @@ where } /// Computes the determinant of the decomposed matrix. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn determinant(&self) -> T::SimdRealField { let dim = self.chol.nrows(); let mut prod_diag = T::one(); @@ -292,7 +292,7 @@ where /// Updates the decomposition such that we get the decomposition of the factored matrix with its `j`th column removed. /// Since the matrix is square, the `j`th row will also be removed. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn remove_column(&self, j: usize) -> Cholesky> where D: DimSub, diff --git a/src/linalg/col_piv_qr.rs b/src/linalg/col_piv_qr.rs index e48263fd..1a56d2cb 100644 --- a/src/linalg/col_piv_qr.rs +++ b/src/linalg/col_piv_qr.rs @@ -95,7 +95,7 @@ where /// Retrieves the upper trapezoidal submatrix `R` of this decomposition. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn r(&self) -> OMatrix, C> where DefaultAllocator: Allocator, C>, @@ -127,7 +127,7 @@ where } /// Computes the orthogonal matrix `Q` of this decomposition. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn q(&self) -> OMatrix> where DefaultAllocator: Allocator>, @@ -152,7 +152,7 @@ where } /// Retrieves the column permutation of this decomposition. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn p(&self) -> &PermutationSequence> { &self.p } @@ -287,7 +287,7 @@ where /// Computes the inverse of the decomposed matrix. /// /// Returns `None` if the decomposed matrix is not invertible. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn try_inverse(&self) -> Option> { assert!( self.col_piv_qr.is_square(), @@ -306,7 +306,7 @@ where } /// Indicates if the decomposed matrix is invertible. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn is_invertible(&self) -> bool { assert!( self.col_piv_qr.is_square(), @@ -323,7 +323,7 @@ where } /// Computes the determinant of the decomposed matrix. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn determinant(&self) -> T { let dim = self.col_piv_qr.nrows(); assert!( diff --git a/src/linalg/convolution.rs b/src/linalg/convolution.rs index 075b3508..36cea3a0 100644 --- a/src/linalg/convolution.rs +++ b/src/linalg/convolution.rs @@ -112,7 +112,7 @@ impl> Vector { /// /// # Errors /// Inputs must satisfy `self.len() >= kernel.len() > 0`. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn convolve_same(&self, kernel: Vector) -> OVector where D2: Dim, diff --git a/src/linalg/determinant.rs b/src/linalg/determinant.rs index 43478261..22b681f5 100644 --- a/src/linalg/determinant.rs +++ b/src/linalg/determinant.rs @@ -12,7 +12,7 @@ impl, S: Storage> SquareMatri /// /// If the matrix has a dimension larger than 3, an LU decomposition is used. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn determinant(&self) -> T where DefaultAllocator: Allocator + Allocator<(usize, usize), D>, diff --git a/src/linalg/full_piv_lu.rs b/src/linalg/full_piv_lu.rs index 9ce6c24d..f08af55c 100644 --- a/src/linalg/full_piv_lu.rs +++ b/src/linalg/full_piv_lu.rs @@ -96,7 +96,7 @@ where /// The lower triangular matrix of this decomposition. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn l(&self) -> OMatrix> where DefaultAllocator: Allocator>, @@ -110,7 +110,7 @@ where /// The upper triangular matrix of this decomposition. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn u(&self) -> OMatrix, C> where DefaultAllocator: Allocator, C>, @@ -121,14 +121,14 @@ where /// The row permutations of this decomposition. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn p(&self) -> &PermutationSequence> { &self.p } /// The column permutations of this decomposition. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn q(&self) -> &PermutationSequence> { &self.q } @@ -215,7 +215,7 @@ where /// Computes the inverse of the decomposed matrix. /// /// Returns `None` if the decomposed matrix is not invertible. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn try_inverse(&self) -> Option> { assert!( self.lu.is_square(), @@ -233,7 +233,7 @@ where } /// Indicates if the decomposed matrix is invertible. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn is_invertible(&self) -> bool { assert!( self.lu.is_square(), @@ -245,7 +245,7 @@ where } /// Computes the determinant of the decomposed matrix. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn determinant(&self) -> T { assert!( self.lu.is_square(), diff --git a/src/linalg/givens.rs b/src/linalg/givens.rs index e555cbfb..8be91fe1 100644 --- a/src/linalg/givens.rs +++ b/src/linalg/givens.rs @@ -89,13 +89,13 @@ impl GivensRotation { } /// The cos part of this roration. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn c(&self) -> T::RealField { self.c } /// The sin part of this roration. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn s(&self) -> T { self.s } diff --git a/src/linalg/hessenberg.rs b/src/linalg/hessenberg.rs index e6201685..6b8ecfee 100644 --- a/src/linalg/hessenberg.rs +++ b/src/linalg/hessenberg.rs @@ -116,7 +116,7 @@ where /// /// This is less efficient than `.unpack_h()` as it allocates a new matrix. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn h(&self) -> OMatrix { let dim = self.hess.nrows(); let mut res = self.hess.clone(); @@ -127,7 +127,7 @@ where } /// Computes the orthogonal matrix `Q` of this decomposition. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn q(&self) -> OMatrix { householder::assemble_q(&self.hess, self.subdiag.as_slice()) } diff --git a/src/linalg/lu.rs b/src/linalg/lu.rs index 0c5dfe15..36a00807 100644 --- a/src/linalg/lu.rs +++ b/src/linalg/lu.rs @@ -127,7 +127,7 @@ where /// The lower triangular matrix of this decomposition. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn l(&self) -> OMatrix> where DefaultAllocator: Allocator>, @@ -171,7 +171,7 @@ where /// The upper triangular matrix of this decomposition. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn u(&self) -> OMatrix, C> where DefaultAllocator: Allocator, C>, @@ -182,7 +182,7 @@ where /// The row permutations of this decomposition. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn p(&self) -> &PermutationSequence> { &self.p } @@ -261,7 +261,7 @@ where /// Computes the inverse of the decomposed matrix. /// /// Returns `None` if the matrix is not invertible. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn try_inverse(&self) -> Option> { assert!( self.lu.is_square(), @@ -296,7 +296,7 @@ where } /// Computes the determinant of the decomposed matrix. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn determinant(&self) -> T { let dim = self.lu.nrows(); assert!( @@ -313,7 +313,7 @@ where } /// Indicates if the decomposed matrix is invertible. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn is_invertible(&self) -> bool { assert!( self.lu.is_square(), diff --git a/src/linalg/permutation_sequence.rs b/src/linalg/permutation_sequence.rs index a852f0c9..ea868b5a 100644 --- a/src/linalg/permutation_sequence.rs +++ b/src/linalg/permutation_sequence.rs @@ -140,20 +140,20 @@ where } /// The number of non-identity permutations applied by this sequence. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn len(&self) -> usize { self.len } /// Returns true if the permutation sequence contains no elements. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn is_empty(&self) -> bool { self.len() == 0 } /// The determinant of the matrix corresponding to this permutation. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn determinant(&self) -> T { if self.len % 2 == 0 { T::one() diff --git a/src/linalg/qr.rs b/src/linalg/qr.rs index 2fa308ff..4bdbb364 100644 --- a/src/linalg/qr.rs +++ b/src/linalg/qr.rs @@ -70,7 +70,7 @@ where /// Retrieves the upper trapezoidal submatrix `R` of this decomposition. #[inline] - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn r(&self) -> OMatrix, C> where DefaultAllocator: Allocator, C>, @@ -97,7 +97,7 @@ where } /// Computes the orthogonal matrix `Q` of this decomposition. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn q(&self) -> OMatrix> where DefaultAllocator: Allocator>, @@ -246,7 +246,7 @@ where /// Computes the inverse of the decomposed matrix. /// /// Returns `None` if the decomposed matrix is not invertible. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn try_inverse(&self) -> Option> { assert!( self.qr.is_square(), @@ -265,7 +265,7 @@ where } /// Indicates if the decomposed matrix is invertible. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn is_invertible(&self) -> bool { assert!( self.qr.is_square(), diff --git a/src/linalg/schur.rs b/src/linalg/schur.rs index 4f9271f7..16b8c66d 100644 --- a/src/linalg/schur.rs +++ b/src/linalg/schur.rs @@ -385,7 +385,7 @@ where /// Computes the real eigenvalues of the decomposed matrix. /// /// Return `None` if some eigenvalues are complex. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn eigenvalues(&self) -> Option> { let mut out = unsafe { crate::unimplemented_or_uninitialized_generic!(self.t.data.shape().0, Const::<1>) @@ -398,7 +398,7 @@ where } /// Computes the complex eigenvalues of the decomposed matrix. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn complex_eigenvalues(&self) -> OVector, D> where T: RealField, @@ -511,7 +511,7 @@ where + Allocator, { /// Computes the eigenvalues of this matrix. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn eigenvalues(&self) -> Option> { assert!( self.is_square(), @@ -554,7 +554,7 @@ where } /// Computes the eigenvalues of this matrix. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn complex_eigenvalues(&self) -> OVector, D> // TODO: add balancing? where diff --git a/src/linalg/svd.rs b/src/linalg/svd.rs index b579eb54..f559c9fa 100644 --- a/src/linalg/svd.rs +++ b/src/linalg/svd.rs @@ -502,7 +502,7 @@ where /// Computes the rank of the decomposed matrix, i.e., the number of singular values greater /// than `eps`. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn rank(&self, eps: T::RealField) -> usize { assert!( eps >= T::RealField::zero(), @@ -616,7 +616,7 @@ where + Allocator, U1>>, { /// Computes the singular values of this matrix. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn singular_values(&self) -> OVector> { SVD::new(self.clone_owned(), false, false).singular_values } @@ -624,7 +624,7 @@ where /// Computes the rank of this matrix. /// /// All singular values below `eps` are considered equal to 0. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn rank(&self, eps: T::RealField) -> usize { let svd = SVD::new(self.clone_owned(), false, false); svd.rank(eps) diff --git a/src/linalg/symmetric_eigen.rs b/src/linalg/symmetric_eigen.rs index d0409e95..25dab08c 100644 --- a/src/linalg/symmetric_eigen.rs +++ b/src/linalg/symmetric_eigen.rs @@ -268,7 +268,7 @@ where /// Rebuild the original matrix. /// /// This is useful if some of the eigenvalues have been manually modified. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn recompose(&self) -> OMatrix { let mut u_t = self.eigenvectors.clone(); for i in 0..self.eigenvalues.len() { @@ -312,7 +312,7 @@ where /// Computes the eigenvalues of this symmetric matrix. /// /// Only the lower-triangular part of the matrix is read. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn symmetric_eigenvalues(&self) -> OVector { SymmetricEigen::do_decompose( self.clone_owned(), diff --git a/src/linalg/symmetric_tridiagonal.rs b/src/linalg/symmetric_tridiagonal.rs index 82a2433b..c7e87ba8 100644 --- a/src/linalg/symmetric_tridiagonal.rs +++ b/src/linalg/symmetric_tridiagonal.rs @@ -131,7 +131,7 @@ where } /// The diagonal components of this decomposition. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn diagonal(&self) -> OVector where DefaultAllocator: Allocator, @@ -140,7 +140,7 @@ where } /// The off-diagonal components of this decomposition. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn off_diagonal(&self) -> OVector> where DefaultAllocator: Allocator>, @@ -149,7 +149,7 @@ where } /// Computes the orthogonal matrix `Q` of this decomposition. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn q(&self) -> OMatrix { householder::assemble_q(&self.tri, self.off_diagonal.as_slice()) } diff --git a/src/linalg/udu.rs b/src/linalg/udu.rs index 786e14bc..7b4a9cc9 100644 --- a/src/linalg/udu.rs +++ b/src/linalg/udu.rs @@ -92,7 +92,7 @@ where } /// Returns the diagonal elements as a matrix - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn d_matrix(&self) -> OMatrix { OMatrix::from_diagonal(&self.d) } diff --git a/src/sparse/cs_matrix.rs b/src/sparse/cs_matrix.rs index f46dfdc2..74e13719 100644 --- a/src/sparse/cs_matrix.rs +++ b/src/sparse/cs_matrix.rs @@ -119,19 +119,19 @@ where DefaultAllocator: Allocator, { /// The value buffer of this storage. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn values(&self) -> &[T] { &self.vals } /// The column shifts buffer. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn p(&self) -> &[usize] { self.p.as_slice() } /// The row index buffers. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn i(&self) -> &[usize] { &self.i } @@ -359,32 +359,32 @@ impl> CsMatrix { } /// The size of the data buffer. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn len(&self) -> usize { self.data.len() } /// The number of rows of this matrix. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn nrows(&self) -> usize { self.data.shape().0.value() } /// The number of rows of this matrix. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn ncols(&self) -> usize { self.data.shape().1.value() } /// The shape of this matrix. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn shape(&self) -> (usize, usize) { let (nrows, ncols) = self.data.shape(); (nrows.value(), ncols.value()) } /// Whether this matrix is square or not. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn is_square(&self) -> bool { let (nrows, ncols) = self.data.shape(); nrows.value() == ncols.value() @@ -399,7 +399,7 @@ impl> CsMatrix { /// If at any time this `is_sorted` method returns `false`, then, something went wrong /// and an issue should be open on the nalgebra repository with details on how to reproduce /// this. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn is_sorted(&self) -> bool { for j in 0..self.ncols() { let mut curr = None; diff --git a/src/sparse/cs_matrix_cholesky.rs b/src/sparse/cs_matrix_cholesky.rs index 5891f0ad..6d52d0a6 100644 --- a/src/sparse/cs_matrix_cholesky.rs +++ b/src/sparse/cs_matrix_cholesky.rs @@ -67,7 +67,7 @@ where } /// The lower-triangular matrix of the cholesky decomposition. - #[must_use = "This function does not mutate self. You should use the return value."] + #[must_use] pub fn l(&self) -> Option<&CsMatrix> { if self.ok { Some(&self.l) From e1fe76235f879094da59f142699e00f420fd80e2 Mon Sep 17 00:00:00 2001 From: Malte Tammena Date: Mon, 7 Jun 2021 16:44:59 +0200 Subject: [PATCH 08/42] Normalize `#[must_use]` hints --- src/base/norm.rs | 4 ++-- src/lib.rs | 4 ++-- src/linalg/cholesky.rs | 2 +- src/linalg/exp.rs | 2 +- src/sparse/cs_matrix_solve.rs | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/base/norm.rs b/src/base/norm.rs index d0c96cd3..09e11f7e 100644 --- a/src/base/norm.rs +++ b/src/base/norm.rs @@ -349,7 +349,7 @@ impl> Matrix { /// Returns a new vector with the same magnitude as `self` clamped between `0.0` and `max`. #[inline] - #[must_use = "This function does not mutate self but returns a new clamped version."] + #[must_use] pub fn cap_magnitude(&self, max: T::RealField) -> OMatrix where T: ComplexField, @@ -366,7 +366,7 @@ impl> Matrix { /// Returns a new vector with the same magnitude as `self` clamped between `0.0` and `max`. #[inline] - #[must_use = "This function does not mutate self but returns a new clamped version."] + #[must_use] pub fn simd_cap_magnitude(&self, max: T::SimdRealField) -> OMatrix where T: SimdComplexField, diff --git a/src/lib.rs b/src/lib.rs index f0f62fe1..a978d5f5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -184,7 +184,7 @@ pub fn zero() -> T { /// Wraps `val` into the range `[min, max]` using modular arithmetics. /// /// The range must not be empty. -#[must_use = "This function does not mutate `val`."] +#[must_use] #[inline] pub fn wrap(mut val: T, min: T, max: T) -> T where @@ -220,7 +220,7 @@ where /// * If `min < val < max`, this returns `val`. /// * If `val <= min`, this returns `min`. /// * If `val >= max`, this returns `max`. -#[must_use = "This function does not mutate `val`."] +#[must_use] #[inline] pub fn clamp(val: T, min: T, max: T) -> T { if val > min { diff --git a/src/linalg/cholesky.rs b/src/linalg/cholesky.rs index 1e352560..f66fb42f 100644 --- a/src/linalg/cholesky.rs +++ b/src/linalg/cholesky.rs @@ -134,7 +134,7 @@ where } /// Computes the inverse of the decomposed matrix. - #[must_use = "This function does not mutate self. Consider using the return value or dropping the function call."] + #[must_use] pub fn inverse(&self) -> OMatrix { let shape = self.chol.data.shape(); let mut res = OMatrix::identity_generic(shape.0, shape.1); diff --git a/src/linalg/exp.rs b/src/linalg/exp.rs index b93055c5..acb2b9e3 100644 --- a/src/linalg/exp.rs +++ b/src/linalg/exp.rs @@ -435,7 +435,7 @@ where + Allocator, { /// Computes exponential of this matrix - #[must_use = "This function does not mutate self. Consider using the return value or dropping the function call."] + #[must_use] pub fn exp(&self) -> Self { // Simple case if self.nrows() == 1 { diff --git a/src/sparse/cs_matrix_solve.rs b/src/sparse/cs_matrix_solve.rs index 33d811cf..43c5c2c7 100644 --- a/src/sparse/cs_matrix_solve.rs +++ b/src/sparse/cs_matrix_solve.rs @@ -137,7 +137,7 @@ impl> CsMatrix { } /// Solve a lower-triangular system with a sparse right-hand-side. - #[must_use = "This function has no side effects. Consider using the return value or removing the function call."] + #[must_use] pub fn solve_lower_triangular_cs( &self, b: &CsVector, From 38e9a5da33b1c53ff4f4dded843b5fb26ffb153b Mon Sep 17 00:00:00 2001 From: Malte Tammena Date: Mon, 7 Jun 2021 17:10:21 +0200 Subject: [PATCH 09/42] Annotate `get_mut`/`slice`-like functions with `#[must_use]` --- nalgebra-sparse/src/csc.rs | 2 ++ nalgebra-sparse/src/csr.rs | 2 ++ src/base/indexing.rs | 2 ++ src/base/matrix.rs | 2 ++ src/geometry/point.rs | 1 + 5 files changed, 9 insertions(+) diff --git a/nalgebra-sparse/src/csc.rs b/nalgebra-sparse/src/csc.rs index 65e1c409..a691e1d4 100644 --- a/nalgebra-sparse/src/csc.rs +++ b/nalgebra-sparse/src/csc.rs @@ -329,6 +329,7 @@ impl CscMatrix { /// Mutable column access for the given column index, or `None` if out of bounds. #[inline] + #[must_use] pub fn get_col_mut(&mut self, index: usize) -> Option> { self.cs.get_lane_mut(index).map(|lane| CscColMut { lane }) } @@ -691,6 +692,7 @@ impl<'a, T> CscColMut<'a, T> { } /// Returns a mutable entry for the given global row index. + #[must_use] pub fn get_entry_mut(&mut self, global_row_index: usize) -> Option> { self.lane.get_entry_mut(global_row_index) } diff --git a/nalgebra-sparse/src/csr.rs b/nalgebra-sparse/src/csr.rs index 86b4272c..c2f9b669 100644 --- a/nalgebra-sparse/src/csr.rs +++ b/nalgebra-sparse/src/csr.rs @@ -331,6 +331,7 @@ impl CsrMatrix { /// Mutable row access for the given row index, or `None` if out of bounds. #[inline] + #[must_use] pub fn get_row_mut(&mut self, index: usize) -> Option> { self.cs.get_lane_mut(index).map(|lane| CsrRowMut { lane }) } @@ -695,6 +696,7 @@ impl<'a, T> CsrRowMut<'a, T> { /// Returns a mutable entry for the given global column index. #[inline] + #[must_use] pub fn get_entry_mut(&mut self, global_col_index: usize) -> Option> { self.lane.get_entry_mut(global_col_index) } diff --git a/src/base/indexing.rs b/src/base/indexing.rs index 9ddf8776..5bc06020 100644 --- a/src/base/indexing.rs +++ b/src/base/indexing.rs @@ -496,6 +496,7 @@ impl> Matrix { /// Produces a mutable view of the data at the given index, or /// `None` if the index is out of bounds. #[inline] + #[must_use] pub fn get_mut<'a, I>(&'a mut self, index: I) -> Option where S: StorageMut, @@ -540,6 +541,7 @@ impl> Matrix { /// Returns a mutable view of the data at the given index, without doing /// any bounds checking. #[inline] + #[must_use] pub unsafe fn get_unchecked_mut<'a, I>(&'a mut self, index: I) -> I::OutputMut where S: StorageMut, diff --git a/src/base/matrix.rs b/src/base/matrix.rs index 6d2468bb..5214bb6f 100644 --- a/src/base/matrix.rs +++ b/src/base/matrix.rs @@ -1266,6 +1266,7 @@ impl> Vector { impl> Vector { /// Gets a mutable reference to the i-th element of this column vector without bound checking. #[inline] + #[must_use] pub unsafe fn vget_unchecked_mut(&mut self, i: usize) -> &mut T { debug_assert!(i < self.nrows(), "Vector index out of bounds."); let i = i * self.strides().0; @@ -1285,6 +1286,7 @@ impl> Matrix> Matrix { /// Extracts a mutable slice containing the entire matrix entries ordered column-by-columns. #[inline] + #[must_use] pub fn as_mut_slice(&mut self) -> &mut [T] { self.data.as_mut_slice() } diff --git a/src/geometry/point.rs b/src/geometry/point.rs index 89db12cc..d25b4d7c 100644 --- a/src/geometry/point.rs +++ b/src/geometry/point.rs @@ -277,6 +277,7 @@ impl Point { /// Gets a mutable reference to i-th element of this point without bound-checking. #[inline] + #[must_use] pub unsafe fn get_unchecked_mut(&mut self, i: usize) -> &mut T { self.coords.vget_unchecked_mut(i) } From 9eb9ad603fe718395bf092e0b599ec78de9f6f44 Mon Sep 17 00:00:00 2001 From: Malte Tammena Date: Mon, 7 Jun 2021 17:24:43 +0200 Subject: [PATCH 10/42] Add `get_mut` annotations (second try) --- nalgebra-sparse/src/cs.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nalgebra-sparse/src/cs.rs b/nalgebra-sparse/src/cs.rs index a5a65f33..cde0a3e2 100644 --- a/nalgebra-sparse/src/cs.rs +++ b/nalgebra-sparse/src/cs.rs @@ -156,6 +156,7 @@ impl CsMatrix { } #[inline] + #[must_use] pub fn get_lane_mut(&mut self, index: usize) -> Option> { let range = self.get_index_range(index)?; let minor_dim = self.pattern().minor_dim(); @@ -429,6 +430,7 @@ impl<'a, T> CsLaneMut<'a, T> { (self.minor_indices, self.values) } + #[must_use] pub fn get_entry_mut(&mut self, global_minor_index: usize) -> Option> { get_mut_entry_from_slices( self.minor_dim, From e6e7efba8a924ca937e689f59d6984207f5b93c1 Mon Sep 17 00:00:00 2001 From: Paul Jakob Schroeder Date: Mon, 7 Jun 2021 10:13:43 -0400 Subject: [PATCH 11/42] COO: add push_matrix fn - This function allows one to add entire dense matrices to a sparse COO matrix. - Added a small mention of this new function in the example in lib.rs --- nalgebra-sparse/src/coo.rs | 37 ++++++++++ nalgebra-sparse/src/lib.rs | 3 + nalgebra-sparse/tests/unit_tests/coo.rs | 92 +++++++++++++++++++++++++ 3 files changed, 132 insertions(+) diff --git a/nalgebra-sparse/src/coo.rs b/nalgebra-sparse/src/coo.rs index caf74654..3327ed27 100644 --- a/nalgebra-sparse/src/coo.rs +++ b/nalgebra-sparse/src/coo.rs @@ -45,6 +45,43 @@ pub struct CooMatrix { values: Vec, } +impl CooMatrix { + /// Pushes a dense matrix into the sparse one. + /// + /// This adds the dense matrix `m` starting at the `r`th row and `c`th column + /// to the matrix. + /// + /// Panics + /// ------ + /// + /// Panics if any part of the dense matrix is out of bounds of the sparse matrix + /// when inserted at `(r, c)`. + #[inline] + pub fn push_matrix>( + &mut self, + r: usize, + c: usize, + m: &na::Matrix, + ) { + let block_nrows = m.nrows(); + let block_ncols = m.ncols(); + let max_row_with_block = r + block_nrows - 1; + let max_col_with_block = c + block_ncols - 1; + assert!(max_row_with_block < self.nrows); + assert!(max_col_with_block < self.ncols); + + self.reserve(block_ncols * block_nrows); + + for (col_idx, col) in m.column_iter().enumerate() { + for (row_idx, v) in col.iter().enumerate() { + self.row_indices.push(r + row_idx); + self.col_indices.push(c + col_idx); + self.values.push(v.clone()); + } + } + } +} + impl CooMatrix { /// Construct a zero COO matrix of the given dimensions. /// diff --git a/nalgebra-sparse/src/lib.rs b/nalgebra-sparse/src/lib.rs index 6f28917d..80351c07 100644 --- a/nalgebra-sparse/src/lib.rs +++ b/nalgebra-sparse/src/lib.rs @@ -93,6 +93,9 @@ //! coo.push(1, 2, 1.3); //! coo.push(2, 2, 4.1); //! +//! // ... or add entire dense matrices like so: +//! // coo.push_matrix(0, 0, &dense); +//! //! // The simplest way to construct a CSR matrix is to first construct a COO matrix, and //! // then convert it to CSR. The `From` trait is implemented for conversions between different //! // sparse matrix types. diff --git a/nalgebra-sparse/tests/unit_tests/coo.rs b/nalgebra-sparse/tests/unit_tests/coo.rs index c9fa1778..c70c5f97 100644 --- a/nalgebra-sparse/tests/unit_tests/coo.rs +++ b/nalgebra-sparse/tests/unit_tests/coo.rs @@ -252,3 +252,95 @@ fn coo_push_out_of_bounds_entries() { assert_panics!(coo.clone().push(3, 2, 1)); } } + +#[test] +fn coo_push_matrix_valid_entries() { + let mut coo = CooMatrix::new(3, 3); + + // Works with static + { + // new is row-major... + let inserted = nalgebra::SMatrix::::new(1, 2, 3, 4); + coo.push_matrix(1, 1, &inserted); + + // insert happens column-major, so expect transposition when read this way + assert_eq!( + coo.triplet_iter().collect::>(), + vec![(1, 1, &1), (2, 1, &3), (1, 2, &2), (2, 2, &4)] + ); + } + + // Works with owned dynamic + { + let inserted = nalgebra::DMatrix::::repeat(1, 2, 5); + coo.push_matrix(0, 0, &inserted); + + assert_eq!( + coo.triplet_iter().collect::>(), + vec![ + (1, 1, &1), + (2, 1, &3), + (1, 2, &2), + (2, 2, &4), + (0, 0, &5), + (0, 1, &5) + ] + ); + } + + // Works with sliced + { + let source = nalgebra::SMatrix::::new(6, 7, 8, 9); + let sliced = source.fixed_slice::<2, 1>(0, 0); + coo.push_matrix(1, 0, &sliced); + + assert_eq!( + coo.triplet_iter().collect::>(), + vec![ + (1, 1, &1), + (2, 1, &3), + (1, 2, &2), + (2, 2, &4), + (0, 0, &5), + (0, 1, &5), + (1, 0, &6), + (2, 0, &8) + ] + ); + } +} + +#[test] +fn coo_push_matrix_out_of_bounds_entries() { + // 0x0 + { + let inserted = nalgebra::SMatrix::::new(1); + assert_panics!(CooMatrix::new(0, 0).push_matrix(0, 0, &inserted)); + } + // 0x1 + { + let inserted = nalgebra::SMatrix::::new(1); + assert_panics!(CooMatrix::new(1, 0).push_matrix(0, 0, &inserted)); + } + // 1x0 + { + let inserted = nalgebra::SMatrix::::new(1); + assert_panics!(CooMatrix::new(0, 1).push_matrix(0, 0, &inserted)); + } + + // 3x3 exceeds col-dim + { + let inserted = nalgebra::SMatrix::::repeat(1); + assert_panics!(CooMatrix::new(3, 3).push_matrix(0, 2, &inserted)); + } + // 3x3 exceeds row-dim + { + let inserted = nalgebra::SMatrix::::repeat(1); + assert_panics!(CooMatrix::new(3, 3).push_matrix(2, 0, &inserted)); + } + // 3x3 exceeds row-dim and row-dim + { + let inserted = nalgebra::SMatrix::::repeat(1); + assert_panics!(CooMatrix::new(3, 3).push_matrix(2, 2, &inserted)); + } +} From 885bbdaf971a7706f0f29557e15791c4a0fc19a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Thu, 17 Jun 2021 02:42:47 -0500 Subject: [PATCH 12/42] Implemented `SliceRange` for `RangeInclusive` (#911) --- src/base/matrix_slice.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/base/matrix_slice.rs b/src/base/matrix_slice.rs index ffe95c8a..129493d6 100644 --- a/src/base/matrix_slice.rs +++ b/src/base/matrix_slice.rs @@ -1,5 +1,5 @@ use std::marker::PhantomData; -use std::ops::{Range, RangeFrom, RangeFull, RangeTo}; +use std::ops::{Range, RangeFrom, RangeFull, RangeInclusive, RangeTo}; use std::slice; use crate::base::allocator::Allocator; @@ -806,6 +806,25 @@ impl SliceRange for RangeFull { } } +impl SliceRange for RangeInclusive { + type Size = Dynamic; + + #[inline(always)] + fn begin(&self, _: D) -> usize { + *self.start() + } + + #[inline(always)] + fn end(&self, _: D) -> usize { + *self.end() + 1 + } + + #[inline(always)] + fn size(&self, _: D) -> Self::Size { + Dynamic::new(*self.end() + 1 - *self.start()) + } +} + // TODO: see how much of this overlaps with the general indexing // methods from indexing.rs. impl> Matrix { From 7643a24cc1659d92952a95be8c1d6412bf94c13f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Thu, 17 Jun 2021 02:44:06 -0500 Subject: [PATCH 13/42] `Result<(), ()>` to `bool` (#916) --- src/linalg/pow.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/linalg/pow.rs b/src/linalg/pow.rs index 33759a90..74da2cfe 100644 --- a/src/linalg/pow.rs +++ b/src/linalg/pow.rs @@ -18,23 +18,22 @@ where { /// Attempts to raise this matrix to an integral power `e` in-place. If this /// matrix is non-invertible and `e` is negative, it leaves this matrix - /// untouched and returns `Err(())`. Otherwise, it returns `Ok(())` and + /// untouched and returns `false`. Otherwise, it returns `true` and /// overwrites this matrix with the result. - #[must_use] - pub fn pow_mut(&mut self, mut e: I) -> Result<(), ()> { + pub fn pow_mut(&mut self, mut e: I) -> bool { let zero = I::zero(); // A matrix raised to the zeroth power is just the identity. if e == zero { self.fill_with_identity(); - return Ok(()); + return true; } // If e is negative, we compute the inverse matrix, then raise it to the // power of -e. if e < zero { if !self.try_inverse_mut() { - return Err(()); + return false; } } @@ -58,7 +57,7 @@ where multiplier.copy_from(&buf); if e == zero { - return Ok(()); + return true; } } } @@ -77,9 +76,10 @@ where pub fn pow(&self, e: I) -> Option> { let mut clone = self.clone_owned(); - match clone.pow_mut(e) { - Ok(()) => Some(clone), - Err(()) => None, + if clone.pow_mut(e) { + Some(clone) + } else { + None } } } From d64e799fc931a5d2c8691bea83eb4b0f677855a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Thu, 17 Jun 2021 02:45:33 -0500 Subject: [PATCH 14/42] Fixes #909 (#917) --- src/geometry/rotation_interpolation.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/geometry/rotation_interpolation.rs b/src/geometry/rotation_interpolation.rs index 6b5a5c11..dc029d20 100644 --- a/src/geometry/rotation_interpolation.rs +++ b/src/geometry/rotation_interpolation.rs @@ -74,8 +74,8 @@ impl Rotation3 { where T: RealField, { - let q1 = Rotation3::from(*self); - let q2 = Rotation3::from(*other); + let q1 = UnitQuaternion::from(*self); + let q2 = UnitQuaternion::from(*other); q1.try_slerp(&q2, t, epsilon).map(|q| q.into()) } } From 38add0b00df2bfba89b8e753e7cb16fcf4ae93c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Crozet?= Date: Thu, 17 Jun 2021 09:46:49 +0200 Subject: [PATCH 15/42] Fix potential undoundness with Storage::as_slice and Storage::as_mut_slice (#905) --- src/base/array_storage.rs | 10 +++--- src/base/blas.rs | 16 +++++---- src/base/default_allocator.rs | 2 +- src/base/edition.rs | 2 +- src/base/matrix_slice.rs | 14 ++++---- src/base/ops.rs | 61 ++++++++++++++++------------------- src/base/storage.rs | 31 +++++++++++++++--- src/base/vec_storage.rs | 12 +++---- src/linalg/inverse.rs | 2 +- 9 files changed, 85 insertions(+), 65 deletions(-) diff --git a/src/base/array_storage.rs b/src/base/array_storage.rs index 6d681ed5..00713fb4 100644 --- a/src/base/array_storage.rs +++ b/src/base/array_storage.rs @@ -79,7 +79,7 @@ where } #[inline] - fn is_contiguous(&self) -> bool { + unsafe fn is_contiguous(&self) -> bool { true } @@ -101,8 +101,8 @@ where } #[inline] - fn as_slice(&self) -> &[T] { - unsafe { std::slice::from_raw_parts(self.ptr(), R * C) } + unsafe fn as_slice_unchecked(&self) -> &[T] { + std::slice::from_raw_parts(self.ptr(), R * C) } } @@ -118,8 +118,8 @@ where } #[inline] - fn as_mut_slice(&mut self) -> &mut [T] { - unsafe { std::slice::from_raw_parts_mut(self.ptr_mut(), R * C) } + unsafe fn as_mut_slice_unchecked(&mut self) -> &mut [T] { + std::slice::from_raw_parts_mut(self.ptr_mut(), R * C) } } diff --git a/src/base/blas.rs b/src/base/blas.rs index 9617e46a..35133bb6 100644 --- a/src/base/blas.rs +++ b/src/base/blas.rs @@ -344,13 +344,17 @@ where let rstride1 = self.strides().0; let rstride2 = x.strides().0; - let y = self.data.as_mut_slice(); - let x = x.data.as_slice(); + unsafe { + // SAFETY: the conversion to slices is OK because we access the + // elements taking the strides into account. + let y = self.data.as_mut_slice_unchecked(); + let x = x.data.as_slice_unchecked(); - if !b.is_zero() { - array_axcpy(y, a, x, c, b, rstride1, rstride2, x.len()); - } else { - array_axc(y, a, x, c, rstride1, rstride2, x.len()); + if !b.is_zero() { + array_axcpy(y, a, x, c, b, rstride1, rstride2, x.len()); + } else { + array_axc(y, a, x, c, rstride1, rstride2, x.len()); + } } } diff --git a/src/base/default_allocator.rs b/src/base/default_allocator.rs index a9f994fe..4bfa11a8 100644 --- a/src/base/default_allocator.rs +++ b/src/base/default_allocator.rs @@ -16,7 +16,7 @@ use crate::base::array_storage::ArrayStorage; #[cfg(any(feature = "alloc", feature = "std"))] use crate::base::dimension::Dynamic; use crate::base::dimension::{Dim, DimName}; -use crate::base::storage::{Storage, StorageMut}; +use crate::base::storage::{ContiguousStorageMut, Storage, StorageMut}; #[cfg(any(feature = "std", feature = "alloc"))] use crate::base::vec_storage::VecStorage; use crate::base::Scalar; diff --git a/src/base/edition.rs b/src/base/edition.rs index 82c537fc..e7ef00d2 100644 --- a/src/base/edition.rs +++ b/src/base/edition.rs @@ -11,7 +11,7 @@ use crate::base::constraint::{DimEq, SameNumberOfColumns, SameNumberOfRows, Shap #[cfg(any(feature = "std", feature = "alloc"))] use crate::base::dimension::Dynamic; use crate::base::dimension::{Const, Dim, DimAdd, DimDiff, DimMin, DimMinimum, DimSub, DimSum, U1}; -use crate::base::storage::{ReshapableStorage, Storage, StorageMut}; +use crate::base::storage::{ContiguousStorageMut, ReshapableStorage, Storage, StorageMut}; use crate::base::{DefaultAllocator, Matrix, OMatrix, RowVector, Scalar, Vector}; /// # Rows and columns extraction diff --git a/src/base/matrix_slice.rs b/src/base/matrix_slice.rs index 129493d6..6cb713f1 100644 --- a/src/base/matrix_slice.rs +++ b/src/base/matrix_slice.rs @@ -132,7 +132,7 @@ macro_rules! storage_impl( } #[inline] - fn is_contiguous(&self) -> bool { + unsafe 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. @@ -162,14 +162,14 @@ macro_rules! storage_impl( } #[inline] - fn as_slice(&self) -> &[T] { + unsafe fn as_slice_unchecked(&self) -> &[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) } + slice::from_raw_parts(self.ptr, sz + 1) } else { - unsafe { slice::from_raw_parts(self.ptr, 0) } + slice::from_raw_parts(self.ptr, 0) } } } @@ -187,13 +187,13 @@ unsafe impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim> StorageMu } #[inline] - fn as_mut_slice(&mut self) -> &mut [T] { + unsafe fn as_mut_slice_unchecked(&mut self) -> &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) } + slice::from_raw_parts_mut(self.ptr, sz + 1) } else { - unsafe { slice::from_raw_parts_mut(self.ptr, 0) } + slice::from_raw_parts_mut(self.ptr, 0) } } } diff --git a/src/base/ops.rs b/src/base/ops.rs index d9be71a7..f0780f7f 100644 --- a/src/base/ops.rs +++ b/src/base/ops.rs @@ -158,20 +158,17 @@ macro_rules! componentwise_binop_impl( // This is the most common case and should be deduced at compile-time. // TODO: use specialization instead? - if self.data.is_contiguous() && rhs.data.is_contiguous() && out.data.is_contiguous() { - let arr1 = self.data.as_slice(); - let arr2 = rhs.data.as_slice(); - let out = out.data.as_mut_slice(); - for i in 0 .. arr1.len() { - unsafe { + unsafe { + if self.data.is_contiguous() && rhs.data.is_contiguous() && out.data.is_contiguous() { + let arr1 = self.data.as_slice_unchecked(); + let arr2 = rhs.data.as_slice_unchecked(); + let out = out.data.as_mut_slice_unchecked(); + for i in 0 .. arr1.len() { *out.get_unchecked_mut(i) = arr1.get_unchecked(i).inlined_clone().$method(arr2.get_unchecked(i).inlined_clone()); } - } - } - else { - for j in 0 .. self.ncols() { - for i in 0 .. self.nrows() { - unsafe { + } else { + for j in 0 .. self.ncols() { + for i in 0 .. self.nrows() { let val = self.get_unchecked((i, j)).inlined_clone().$method(rhs.get_unchecked((i, j)).inlined_clone()); *out.get_unchecked_mut((i, j)) = val; } @@ -191,19 +188,17 @@ macro_rules! componentwise_binop_impl( // This is the most common case and should be deduced at compile-time. // TODO: use specialization instead? - if self.data.is_contiguous() && rhs.data.is_contiguous() { - let arr1 = self.data.as_mut_slice(); - let arr2 = rhs.data.as_slice(); - for i in 0 .. arr2.len() { - unsafe { + unsafe { + if self.data.is_contiguous() && rhs.data.is_contiguous() { + let arr1 = self.data.as_mut_slice_unchecked(); + let arr2 = rhs.data.as_slice_unchecked(); + + for i in 0 .. arr2.len() { arr1.get_unchecked_mut(i).$method_assign(arr2.get_unchecked(i).inlined_clone()); } - } - } - else { - for j in 0 .. rhs.ncols() { - for i in 0 .. rhs.nrows() { - unsafe { + } else { + for j in 0 .. rhs.ncols() { + for i in 0 .. rhs.nrows() { self.get_unchecked_mut((i, j)).$method_assign(rhs.get_unchecked((i, j)).inlined_clone()) } } @@ -221,20 +216,18 @@ macro_rules! componentwise_binop_impl( // This is the most common case and should be deduced at compile-time. // TODO: use specialization instead? - if self.data.is_contiguous() && rhs.data.is_contiguous() { - let arr1 = self.data.as_slice(); - let arr2 = rhs.data.as_mut_slice(); - for i in 0 .. arr1.len() { - unsafe { + unsafe { + if self.data.is_contiguous() && rhs.data.is_contiguous() { + let arr1 = self.data.as_slice_unchecked(); + let arr2 = rhs.data.as_mut_slice_unchecked(); + + for i in 0 .. arr1.len() { let res = arr1.get_unchecked(i).inlined_clone().$method(arr2.get_unchecked(i).inlined_clone()); *arr2.get_unchecked_mut(i) = res; } - } - } - else { - for j in 0 .. self.ncols() { - for i in 0 .. self.nrows() { - unsafe { + } else { + for j in 0 .. self.ncols() { + for i in 0 .. self.nrows() { let r = rhs.get_unchecked_mut((i, j)); *r = self.get_unchecked((i, j)).inlined_clone().$method(r.inlined_clone()) } diff --git a/src/base/storage.rs b/src/base/storage.rs index 0238b36c..1e8d5dfb 100644 --- a/src/base/storage.rs +++ b/src/base/storage.rs @@ -94,12 +94,19 @@ pub unsafe trait Storage: Debug + Sized { } /// Indicates whether this data buffer stores its elements contiguously. - fn is_contiguous(&self) -> bool; + /// + /// This method is unsafe because unsafe code relies on this properties to performe + /// some low-lever optimizations. + unsafe fn is_contiguous(&self) -> bool; /// Retrieves the data buffer as a contiguous slice. /// /// The matrix components may not be stored in a contiguous way, depending on the strides. - fn as_slice(&self) -> &[T]; + /// 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. + /// + /// Call the safe alternative `matrix.as_slice()` instead. + unsafe fn as_slice_unchecked(&self) -> &[T]; /// Builds a matrix data storage that does not contain any reference. fn into_owned(self) -> Owned @@ -165,8 +172,12 @@ pub unsafe trait StorageMut: Storage { /// Retrieves the mutable data buffer as a contiguous slice. /// - /// Matrix components may not be contiguous, depending on its strides. - fn as_mut_slice(&mut self) -> &mut [T]; + /// Matrix components may not be contiguous, depending on its strides. + /// + /// 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. + unsafe fn as_mut_slice_unchecked(&mut self) -> &mut [T]; } /// A matrix storage that is stored contiguously in memory. @@ -177,6 +188,12 @@ pub unsafe trait StorageMut: Storage { pub unsafe trait ContiguousStorage: Storage { + /// Converts this data storage to a contiguous slice. + fn as_slice(&self) -> &[T] { + // SAFETY: this is safe because this trait guarantees the fact + // that the data is stored contiguously. + unsafe { self.as_slice_unchecked() } + } } /// A mutable matrix storage that is stored contiguously in memory. @@ -187,6 +204,12 @@ pub unsafe trait ContiguousStorage: pub unsafe trait ContiguousStorageMut: ContiguousStorage + StorageMut { + /// Converts this data storage to a contiguous mutable slice. + fn as_mut_slice(&mut self) -> &mut [T] { + // SAFETY: this is safe because this trait guarantees the fact + // that the data is stored contiguously. + unsafe { self.as_mut_slice_unchecked() } + } } /// A matrix storage that can be reshaped in-place. diff --git a/src/base/vec_storage.rs b/src/base/vec_storage.rs index 14490674..cc5f0ab3 100644 --- a/src/base/vec_storage.rs +++ b/src/base/vec_storage.rs @@ -178,7 +178,7 @@ where } #[inline] - fn is_contiguous(&self) -> bool { + unsafe fn is_contiguous(&self) -> bool { true } @@ -199,7 +199,7 @@ where } #[inline] - fn as_slice(&self) -> &[T] { + unsafe fn as_slice_unchecked(&self) -> &[T] { &self.data } } @@ -227,7 +227,7 @@ where } #[inline] - fn is_contiguous(&self) -> bool { + unsafe fn is_contiguous(&self) -> bool { true } @@ -248,7 +248,7 @@ where } #[inline] - fn as_slice(&self) -> &[T] { + unsafe fn as_slice_unchecked(&self) -> &[T] { &self.data } } @@ -268,7 +268,7 @@ where } #[inline] - fn as_mut_slice(&mut self) -> &mut [T] { + unsafe fn as_mut_slice_unchecked(&mut self) -> &mut [T] { &mut self.data[..] } } @@ -329,7 +329,7 @@ where } #[inline] - fn as_mut_slice(&mut self) -> &mut [T] { + unsafe fn as_mut_slice_unchecked(&mut self) -> &mut [T] { &mut self.data[..] } } diff --git a/src/linalg/inverse.rs b/src/linalg/inverse.rs index f56a95ec..28b148a1 100644 --- a/src/linalg/inverse.rs +++ b/src/linalg/inverse.rs @@ -127,7 +127,7 @@ fn do_inverse4>( where DefaultAllocator: Allocator, { - let m = m.data.as_slice(); + let m = m.as_slice(); out[(0, 0)] = m[5] * m[10] * m[15] - m[5] * m[11] * m[14] - m[9] * m[6] * m[15] + m[9] * m[7] * m[14] From 498b377d0e7d31a77cecd4540ce84c4a132aee98 Mon Sep 17 00:00:00 2001 From: Cryptjar Date: Fri, 18 Jun 2021 02:23:40 +0200 Subject: [PATCH 16/42] 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 17/42] 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 c5f240cc281120b987a76bef213ba1007138a89c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Thu, 17 Jun 2021 19:51:00 -0500 Subject: [PATCH 18/42] Fixed potential UB --- src/base/storage.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/base/storage.rs b/src/base/storage.rs index 1e8d5dfb..1eaa9b62 100644 --- a/src/base/storage.rs +++ b/src/base/storage.rs @@ -1,7 +1,7 @@ //! Abstract definition of a matrix data storage. use std::fmt::Debug; -use std::mem; +use std::ptr; use crate::base::allocator::{Allocator, SameShapeC, SameShapeR}; use crate::base::default_allocator::DefaultAllocator; @@ -158,7 +158,7 @@ pub unsafe trait StorageMut: Storage { let a = self.get_address_unchecked_linear_mut(i1); let b = self.get_address_unchecked_linear_mut(i2); - mem::swap(&mut *a, &mut *b); + ptr::swap(a, b); } /// Swaps two elements without bound-checking. From 281b1403654cc8c66840a7d4a7fb21b1a56bb75d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Violeta=20Hern=C3=A1ndez?= Date: Fri, 18 Jun 2021 02:45:37 -0500 Subject: [PATCH 19/42] Fix most clippy warnings --- src/base/blas.rs | 2 + src/base/construction.rs | 1 + src/base/conversion.rs | 43 +++++++------- src/base/coordinates.rs | 5 +- src/base/iter.rs | 12 ++-- src/base/matrix.rs | 1 + src/base/ops.rs | 2 +- src/base/unit.rs | 7 +-- src/base/vec_storage.rs | 6 +- src/geometry/dual_quaternion.rs | 9 ++- src/geometry/dual_quaternion_construction.rs | 4 +- src/geometry/dual_quaternion_ops.rs | 26 +++++---- src/geometry/isometry.rs | 4 +- src/geometry/isometry_conversion.rs | 58 +++++++++---------- src/geometry/isometry_ops.rs | 47 ++++++++------- src/geometry/orthographic.rs | 3 +- src/geometry/perspective.rs | 8 +-- src/geometry/point_conversion.rs | 6 +- src/geometry/quaternion_coordinates.rs | 5 +- src/geometry/quaternion_ops.rs | 3 + src/geometry/rotation_conversion.rs | 61 ++++++++++---------- src/geometry/rotation_specialization.rs | 6 +- src/geometry/similarity.rs | 2 +- src/geometry/similarity_conversion.rs | 58 +++++++++---------- src/geometry/similarity_ops.rs | 5 +- src/geometry/transform.rs | 8 +-- src/geometry/transform_ops.rs | 3 + src/geometry/translation.rs | 2 +- src/geometry/translation_conversion.rs | 12 ++-- src/geometry/translation_coordinates.rs | 8 +-- src/geometry/unit_complex_ops.rs | 27 +++++---- src/lib.rs | 15 ++--- src/linalg/balancing.rs | 39 +++++++------ src/linalg/exp.rs | 33 ++++++----- src/linalg/pow.rs | 6 +- src/linalg/schur.rs | 1 + src/linalg/svd.rs | 33 ++++++----- src/linalg/symmetric_eigen.rs | 37 ++++++------ tests/linalg/convolution.rs | 8 ++- 39 files changed, 318 insertions(+), 298 deletions(-) diff --git a/src/base/blas.rs b/src/base/blas.rs index 35133bb6..a6a188bc 100644 --- a/src/base/blas.rs +++ b/src/base/blas.rs @@ -278,6 +278,7 @@ where } } +#[allow(clippy::too_many_arguments)] fn array_axcpy( y: &mut [T], a: T, @@ -334,6 +335,7 @@ where /// assert_eq!(vec1, Vector3::new(6.0, 12.0, 18.0)); /// ``` #[inline] + #[allow(clippy::many_single_char_names)] pub fn axcpy(&mut self, a: T, x: &Vector, c: T, b: T) where SB: Storage, diff --git a/src/base/construction.rs b/src/base/construction.rs index e3e56b53..ac9023ec 100644 --- a/src/base/construction.rs +++ b/src/base/construction.rs @@ -906,6 +906,7 @@ macro_rules! componentwise_constructors_impl( impl Matrix, Const<$C>, ArrayStorage> { /// Initializes this matrix from its components. #[inline] + #[allow(clippy::too_many_arguments)] pub const fn new($($($args: T),*),*) -> Self { unsafe { Self::from_data_statically_unchecked( diff --git a/src/base/conversion.rs b/src/base/conversion.rs index 532ab8ed..99639991 100644 --- a/src/base/conversion.rs +++ b/src/base/conversion.rs @@ -2,7 +2,6 @@ use alloc::vec::Vec; use simba::scalar::{SubsetOf, SupersetOf}; use std::convert::{AsMut, AsRef, From, Into}; -use std::mem; use simba::simd::{PrimitiveSimdValue, SimdValue}; @@ -110,11 +109,11 @@ impl From<[T; D]> for SVector { } } -impl Into<[T; D]> for SVector { +impl From> for [T; D] { #[inline] - fn into(self) -> [T; D] { + fn from(vec: SVector) -> Self { // TODO: unfortunately, we must clone because we can move out of an array. - self.data.0[0].clone() + vec.data.0[0].clone() } } @@ -128,13 +127,13 @@ where } } -impl Into<[T; D]> for RowSVector +impl From> for [T; D] where Const: IsNotStaticOne, { #[inline] - fn into(self) -> [T; D] { - self.transpose().into() + fn from(vec: RowSVector) -> [T; D] { + vec.transpose().into() } } @@ -146,7 +145,7 @@ macro_rules! impl_from_into_asref_1D( #[inline] fn as_ref(&self) -> &[T; $SZ] { unsafe { - mem::transmute(self.data.ptr()) + &*(self.data.ptr() as *const [T; $SZ]) } } } @@ -157,7 +156,7 @@ macro_rules! impl_from_into_asref_1D( #[inline] fn as_mut(&mut self) -> &mut [T; $SZ] { unsafe { - mem::transmute(self.data.ptr_mut()) + &mut *(self.data.ptr_mut() as *mut [T; $SZ]) } } } @@ -186,10 +185,10 @@ impl From<[[T; R]; C]> for SMatrix Into<[[T; R]; C]> for SMatrix { +impl From> for [[T; R]; C] { #[inline] - fn into(self) -> [[T; R]; C] { - self.data.0 + fn from(vec: SMatrix) -> Self { + vec.data.0 } } @@ -200,7 +199,7 @@ macro_rules! impl_from_into_asref_2D( #[inline] fn as_ref(&self) -> &[[T; $SZRows]; $SZCols] { unsafe { - mem::transmute(self.data.ptr()) + &*(self.data.ptr() as *const [[T; $SZRows]; $SZCols]) } } } @@ -210,7 +209,7 @@ macro_rules! impl_from_into_asref_2D( #[inline] fn as_mut(&mut self) -> &mut [[T; $SZRows]; $SZCols] { unsafe { - mem::transmute(self.data.ptr_mut()) + &mut *(self.data.ptr_mut() as *mut [[T; $SZRows]; $SZCols]) } } } @@ -427,21 +426,21 @@ impl<'a, T: Scalar> From> for DVector { } } -impl<'a, T: Scalar + Copy, R: Dim, C: Dim, S: ContiguousStorage> Into<&'a [T]> - for &'a Matrix +impl<'a, T: Scalar + Copy, R: Dim, C: Dim, S: ContiguousStorage> + From<&'a Matrix> for &'a [T] { #[inline] - fn into(self) -> &'a [T] { - self.as_slice() + fn from(matrix: &'a Matrix) -> Self { + matrix.as_slice() } } -impl<'a, T: Scalar + Copy, R: Dim, C: Dim, S: ContiguousStorageMut> Into<&'a mut [T]> - for &'a mut Matrix +impl<'a, T: Scalar + Copy, R: Dim, C: Dim, S: ContiguousStorageMut> + From<&'a mut Matrix> for &'a mut [T] { #[inline] - fn into(self) -> &'a mut [T] { - self.as_mut_slice() + fn from(matrix: &'a mut Matrix) -> Self { + matrix.as_mut_slice() } } diff --git a/src/base/coordinates.rs b/src/base/coordinates.rs index bf69b09e..be05d3e5 100644 --- a/src/base/coordinates.rs +++ b/src/base/coordinates.rs @@ -4,7 +4,6 @@ //! components using their names. For example, if `v` is a 3D vector, one can write `v.z` instead //! of `v[2]`. -use std::mem; use std::ops::{Deref, DerefMut}; use crate::base::dimension::{U1, U2, U3, U4, U5, U6}; @@ -38,7 +37,7 @@ macro_rules! deref_impl( #[inline] fn deref(&self) -> &Self::Target { - unsafe { mem::transmute(self.data.ptr()) } + unsafe { &*(self.data.ptr() as *const Self::Target) } } } @@ -46,7 +45,7 @@ macro_rules! deref_impl( where S: ContiguousStorageMut { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { - unsafe { mem::transmute(self.data.ptr_mut()) } + unsafe { &mut *(self.data.ptr_mut() as *mut Self::Target) } } } } diff --git a/src/base/iter.rs b/src/base/iter.rs index 1592299d..0e13e4d3 100644 --- a/src/base/iter.rs +++ b/src/base/iter.rs @@ -96,6 +96,10 @@ macro_rules! iterator { let stride = self.strides.0.value(); self.ptr = self.ptr.add(stride); } + + // We want either `& *last` or `&mut *last` here, depending + // on the mutability of `$Ref`. + #[allow(clippy::transmute_ptr_to_ref)] Some(mem::transmute(old)) } } @@ -139,13 +143,13 @@ macro_rules! iterator { let inner_remaining = self.size % inner_size; // Compute pointer to last element - let last = self.ptr.offset( - (outer_remaining * outer_stride + inner_remaining * inner_stride) - as isize, - ); + let last = self + .ptr + .add((outer_remaining * outer_stride + inner_remaining * inner_stride)); // We want either `& *last` or `&mut *last` here, depending // on the mutability of `$Ref`. + #[allow(clippy::transmute_ptr_to_ref)] Some(mem::transmute(last)) } } diff --git a/src/base/matrix.rs b/src/base/matrix.rs index 5214bb6f..f2da8a8a 100644 --- a/src/base/matrix.rs +++ b/src/base/matrix.rs @@ -567,6 +567,7 @@ impl> Matrix { /// Tests whether `self` and `rhs` are exactly equal. #[inline] #[must_use] + #[allow(clippy::should_implement_trait)] pub fn eq(&self, other: &Matrix) -> bool where T: PartialEq, diff --git a/src/base/ops.rs b/src/base/ops.rs index f0780f7f..852f6490 100644 --- a/src/base/ops.rs +++ b/src/base/ops.rs @@ -529,7 +529,7 @@ macro_rules! left_scalar_mul_impl( // for rhs in res.iter_mut() { for rhs in res.as_mut_slice().iter_mut() { - *rhs = self * *rhs + *rhs *= self } res diff --git a/src/base/unit.rs b/src/base/unit.rs index b5a4096f..32eff82f 100644 --- a/src/base/unit.rs +++ b/src/base/unit.rs @@ -1,6 +1,5 @@ #[cfg(feature = "abomonation-serialize")] use std::io::{Result as IOResult, Write}; -use std::mem; use std::ops::Deref; #[cfg(feature = "serde-serialize-no-std")] @@ -228,8 +227,8 @@ impl Unit { /// Wraps the given reference, assuming it is already normalized. #[inline] - pub fn from_ref_unchecked<'a>(value: &'a T) -> &'a Self { - unsafe { mem::transmute(value) } + pub fn from_ref_unchecked(value: &T) -> &Self { + unsafe { &*(value as *const T as *const Self) } } /// Retrieves the underlying value. @@ -332,7 +331,7 @@ impl Deref for Unit { #[inline] fn deref(&self) -> &T { - unsafe { mem::transmute(self) } + unsafe { &*(self as *const Self as *const T) } } } diff --git a/src/base/vec_storage.rs b/src/base/vec_storage.rs index cc5f0ab3..c312c048 100644 --- a/src/base/vec_storage.rs +++ b/src/base/vec_storage.rs @@ -143,9 +143,9 @@ impl VecStorage { } } -impl Into> for VecStorage { - fn into(self) -> Vec { - self.data +impl From> for Vec { + fn from(vec: VecStorage) -> Self { + vec.data } } diff --git a/src/geometry/dual_quaternion.rs b/src/geometry/dual_quaternion.rs index 83912b9e..63148836 100644 --- a/src/geometry/dual_quaternion.rs +++ b/src/geometry/dual_quaternion.rs @@ -1,3 +1,6 @@ +// The macros break if the references are taken out, for some reason. +#![allow(clippy::op_ref)] + use crate::{ Isometry3, Matrix4, Normed, OVector, Point3, Quaternion, Scalar, SimdRealField, Translation3, Unit, UnitQuaternion, Vector3, Zero, U8, @@ -273,7 +276,7 @@ where impl DualQuaternion { fn to_vector(&self) -> OVector { - self.as_ref().clone().into() + (*self.as_ref()).into() } } @@ -618,9 +621,9 @@ where let other = { let dot_product = self.as_ref().real.coords.dot(&other.as_ref().real.coords); if dot_product < T::zero() { - -other.clone() + -*other } else { - other.clone() + *other } }; diff --git a/src/geometry/dual_quaternion_construction.rs b/src/geometry/dual_quaternion_construction.rs index be274cf4..ea4c7ee2 100644 --- a/src/geometry/dual_quaternion_construction.rs +++ b/src/geometry/dual_quaternion_construction.rs @@ -186,9 +186,9 @@ where pub fn from_parts(translation: Translation3, rotation: UnitQuaternion) -> Self { let half: T = crate::convert(0.5f64); UnitDualQuaternion::new_unchecked(DualQuaternion { - real: rotation.clone().into_inner(), + real: rotation.into_inner(), dual: Quaternion::from_parts(T::zero(), translation.vector) - * rotation.clone().into_inner() + * rotation.into_inner() * half, }) } diff --git a/src/geometry/dual_quaternion_ops.rs b/src/geometry/dual_quaternion_ops.rs index 46bc22b5..2a1527ec 100644 --- a/src/geometry/dual_quaternion_ops.rs +++ b/src/geometry/dual_quaternion_ops.rs @@ -1,3 +1,6 @@ +// The macros break if the references are taken out, for some reason. +#![allow(clippy::op_ref)] + /* * This file provides: * @@ -49,7 +52,6 @@ use crate::{ DualQuaternion, Isometry3, Point, Point3, Quaternion, SimdRealField, Translation3, Unit, UnitDualQuaternion, UnitQuaternion, Vector, Vector3, U3, }; -use std::mem; use std::ops::{ Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign, }; @@ -57,14 +59,14 @@ use std::ops::{ impl AsRef<[T; 8]> for DualQuaternion { #[inline] fn as_ref(&self) -> &[T; 8] { - unsafe { mem::transmute(self) } + unsafe { &*(self as *const Self as *const [T; 8]) } } } impl AsMut<[T; 8]> for DualQuaternion { #[inline] fn as_mut(&mut self) -> &mut [T; 8] { - unsafe { mem::transmute(self) } + unsafe { &mut *(self as *mut Self as *mut [T; 8]) } } } @@ -564,7 +566,7 @@ dual_quaternion_op_impl!( (U4, U1), (U3, U1); self: &'a UnitDualQuaternion, rhs: &'b Translation3, Output = UnitDualQuaternion => U3, U1; - self * UnitDualQuaternion::::from_parts(rhs.clone(), UnitQuaternion::identity()); + self * UnitDualQuaternion::::from_parts(*rhs, UnitQuaternion::identity()); 'a, 'b); dual_quaternion_op_impl!( @@ -580,7 +582,7 @@ dual_quaternion_op_impl!( (U4, U1), (U3, U3); self: UnitDualQuaternion, rhs: &'b Translation3, Output = UnitDualQuaternion => U3, U1; - self * UnitDualQuaternion::::from_parts(rhs.clone(), UnitQuaternion::identity()); + self * UnitDualQuaternion::::from_parts(*rhs, UnitQuaternion::identity()); 'b); dual_quaternion_op_impl!( @@ -632,7 +634,7 @@ dual_quaternion_op_impl!( (U3, U1), (U4, U1); self: &'b Translation3, rhs: &'a UnitDualQuaternion, Output = UnitDualQuaternion => U3, U1; - UnitDualQuaternion::::from_parts(self.clone(), UnitQuaternion::identity()) * rhs; + UnitDualQuaternion::::from_parts(*self, UnitQuaternion::identity()) * rhs; 'a, 'b); dual_quaternion_op_impl!( @@ -640,7 +642,7 @@ dual_quaternion_op_impl!( (U3, U1), (U4, U1); self: &'a Translation3, rhs: UnitDualQuaternion, Output = UnitDualQuaternion => U3, U1; - UnitDualQuaternion::::from_parts(self.clone(), UnitQuaternion::identity()) * rhs; + UnitDualQuaternion::::from_parts(*self, UnitQuaternion::identity()) * rhs; 'a); dual_quaternion_op_impl!( @@ -664,7 +666,7 @@ dual_quaternion_op_impl!( (U3, U1), (U4, U1); self: &'b Translation3, rhs: &'a UnitDualQuaternion, Output = UnitDualQuaternion => U3, U1; - UnitDualQuaternion::::from_parts(self.clone(), UnitQuaternion::identity()) / rhs; + UnitDualQuaternion::::from_parts(*self, UnitQuaternion::identity()) / rhs; 'a, 'b); dual_quaternion_op_impl!( @@ -672,7 +674,7 @@ dual_quaternion_op_impl!( (U3, U1), (U4, U1); self: &'a Translation3, rhs: UnitDualQuaternion, Output = UnitDualQuaternion => U3, U1; - UnitDualQuaternion::::from_parts(self.clone(), UnitQuaternion::identity()) / rhs; + UnitDualQuaternion::::from_parts(*self, UnitQuaternion::identity()) / rhs; 'a); dual_quaternion_op_impl!( @@ -860,7 +862,7 @@ dual_quaternion_op_impl!( Output = Point3 => U3, U1; { let two: T = crate::convert(2.0f64); - let q_point = Quaternion::from_parts(T::zero(), rhs.coords.clone()); + let q_point = Quaternion::from_parts(T::zero(), rhs.coords); Point::from( ((self.as_ref().real * q_point + self.as_ref().dual * two) * self.as_ref().real.conjugate()) .vector() @@ -1115,7 +1117,7 @@ dual_quaternion_op_impl!( MulAssign, mul_assign; (U4, U1), (U4, U1); self: UnitDualQuaternion, rhs: &'b UnitQuaternion; - *self *= rhs.clone(); 'b); + *self *= *rhs; 'b); // UnitDualQuaternion ÷= UnitQuaternion dual_quaternion_op_impl!( @@ -1151,7 +1153,7 @@ dual_quaternion_op_impl!( MulAssign, mul_assign; (U4, U1), (U4, U1); self: UnitDualQuaternion, rhs: &'b Translation3; - *self *= rhs.clone(); 'b); + *self *= *rhs; 'b); // UnitDualQuaternion ÷= Translation3 dual_quaternion_op_impl!( diff --git a/src/geometry/isometry.rs b/src/geometry/isometry.rs index 6d3e9127..7d8c6e95 100755 --- a/src/geometry/isometry.rs +++ b/src/geometry/isometry.rs @@ -270,7 +270,7 @@ where #[must_use] pub fn inv_mul(&self, rhs: &Isometry) -> Self { let inv_rot1 = self.rotation.inverse(); - let tr_12 = rhs.translation.vector.clone() - self.translation.vector.clone(); + let tr_12 = rhs.translation.vector - self.translation.vector; Isometry::from_parts( inv_rot1.transform_vector(&tr_12).into(), inv_rot1 * rhs.rotation.clone(), @@ -435,7 +435,7 @@ where #[must_use] pub fn inverse_transform_point(&self, pt: &Point) -> Point { self.rotation - .inverse_transform_point(&(pt - &self.translation.vector)) + .inverse_transform_point(&(pt - self.translation.vector)) } /// Transform the given vector by the inverse of this isometry, ignoring the diff --git a/src/geometry/isometry_conversion.rs b/src/geometry/isometry_conversion.rs index 75c0d98d..627ea3ee 100644 --- a/src/geometry/isometry_conversion.rs +++ b/src/geometry/isometry_conversion.rs @@ -239,7 +239,7 @@ where { #[inline] fn from(arr: [Isometry; 2]) -> Self { - let tra = Translation::from([arr[0].translation.clone(), arr[1].translation.clone()]); + let tra = Translation::from([arr[0].translation, arr[1].translation]); let rot = R::from([arr[0].rotation, arr[0].rotation]); Self::from_parts(tra, rot) @@ -258,10 +258,10 @@ where #[inline] fn from(arr: [Isometry; 4]) -> Self { let tra = Translation::from([ - arr[0].translation.clone(), - arr[1].translation.clone(), - arr[2].translation.clone(), - arr[3].translation.clone(), + arr[0].translation, + arr[1].translation, + arr[2].translation, + arr[3].translation, ]); let rot = R::from([ arr[0].rotation, @@ -286,14 +286,14 @@ where #[inline] fn from(arr: [Isometry; 8]) -> Self { let tra = Translation::from([ - arr[0].translation.clone(), - arr[1].translation.clone(), - arr[2].translation.clone(), - arr[3].translation.clone(), - arr[4].translation.clone(), - arr[5].translation.clone(), - arr[6].translation.clone(), - arr[7].translation.clone(), + arr[0].translation, + arr[1].translation, + arr[2].translation, + arr[3].translation, + arr[4].translation, + arr[5].translation, + arr[6].translation, + arr[7].translation, ]); let rot = R::from([ arr[0].rotation, @@ -322,22 +322,22 @@ where #[inline] fn from(arr: [Isometry; 16]) -> Self { let tra = Translation::from([ - arr[0].translation.clone(), - arr[1].translation.clone(), - arr[2].translation.clone(), - arr[3].translation.clone(), - arr[4].translation.clone(), - arr[5].translation.clone(), - arr[6].translation.clone(), - arr[7].translation.clone(), - arr[8].translation.clone(), - arr[9].translation.clone(), - arr[10].translation.clone(), - arr[11].translation.clone(), - arr[12].translation.clone(), - arr[13].translation.clone(), - arr[14].translation.clone(), - arr[15].translation.clone(), + arr[0].translation, + arr[1].translation, + arr[2].translation, + arr[3].translation, + arr[4].translation, + arr[5].translation, + arr[6].translation, + arr[7].translation, + arr[8].translation, + arr[9].translation, + arr[10].translation, + arr[11].translation, + arr[12].translation, + arr[13].translation, + arr[14].translation, + arr[15].translation, ]); let rot = R::from([ arr[0].rotation, diff --git a/src/geometry/isometry_ops.rs b/src/geometry/isometry_ops.rs index 2e6477b5..5cf5ec35 100644 --- a/src/geometry/isometry_ops.rs +++ b/src/geometry/isometry_ops.rs @@ -1,3 +1,6 @@ +// The macros break if the references are taken out, for some reason. +#![allow(clippy::op_ref)] + use num::{One, Zero}; use std::ops::{Div, DivAssign, Mul, MulAssign}; @@ -198,7 +201,7 @@ md_assign_impl_all!( const D; for; where; self: Isometry, D>, rhs: Rotation; [val] => self.rotation *= rhs; - [ref] => self.rotation *= rhs.clone(); + [ref] => self.rotation *= *rhs; ); md_assign_impl_all!( @@ -365,9 +368,9 @@ isometry_from_composition_impl_all!( D; self: Rotation, right: Translation, Output = Isometry, D>; [val val] => Isometry::from_parts(Translation::from(&self * right.vector), self); - [ref val] => Isometry::from_parts(Translation::from(self * right.vector), self.clone()); + [ref val] => Isometry::from_parts(Translation::from(self * right.vector), *self); [val ref] => Isometry::from_parts(Translation::from(&self * &right.vector), self); - [ref ref] => Isometry::from_parts(Translation::from(self * &right.vector), self.clone()); + [ref ref] => Isometry::from_parts(Translation::from(self * &right.vector), *self); ); // UnitQuaternion × Translation @@ -389,9 +392,9 @@ isometry_from_composition_impl_all!( self: Isometry, D>, rhs: Rotation, Output = Isometry, D>; [val val] => Isometry::from_parts(self.translation, self.rotation * rhs); - [ref val] => Isometry::from_parts(self.translation.clone(), self.rotation.clone() * rhs); // TODO: do not clone. - [val ref] => Isometry::from_parts(self.translation, self.rotation * rhs.clone()); - [ref ref] => Isometry::from_parts(self.translation.clone(), self.rotation.clone() * rhs.clone()); + [ref val] => Isometry::from_parts(self.translation, self.rotation * rhs); + [val ref] => Isometry::from_parts(self.translation, self.rotation * *rhs); + [ref ref] => Isometry::from_parts(self.translation, self.rotation * *rhs); ); // Rotation × Isometry @@ -416,9 +419,9 @@ isometry_from_composition_impl_all!( self: Isometry, D>, rhs: Rotation, Output = Isometry, D>; [val val] => Isometry::from_parts(self.translation, self.rotation / rhs); - [ref val] => Isometry::from_parts(self.translation.clone(), self.rotation.clone() / rhs); // TODO: do not clone. - [val ref] => Isometry::from_parts(self.translation, self.rotation / rhs.clone()); - [ref ref] => Isometry::from_parts(self.translation.clone(), self.rotation.clone() / rhs.clone()); + [ref val] => Isometry::from_parts(self.translation, self.rotation / rhs); + [val ref] => Isometry::from_parts(self.translation, self.rotation / *rhs); + [ref ref] => Isometry::from_parts(self.translation, self.rotation / *rhs); ); // Rotation ÷ Isometry @@ -441,9 +444,9 @@ isometry_from_composition_impl_all!( self: Isometry, 3>, rhs: UnitQuaternion, Output = Isometry, 3>; [val val] => Isometry::from_parts(self.translation, self.rotation * rhs); - [ref val] => Isometry::from_parts(self.translation.clone(), self.rotation * rhs); // TODO: do not clone. + [ref val] => Isometry::from_parts(self.translation, self.rotation * rhs); [val ref] => Isometry::from_parts(self.translation, self.rotation * *rhs); - [ref ref] => Isometry::from_parts(self.translation.clone(), self.rotation * *rhs); + [ref ref] => Isometry::from_parts(self.translation, self.rotation * *rhs); ); // UnitQuaternion × Isometry @@ -468,9 +471,9 @@ isometry_from_composition_impl_all!( self: Isometry, 3>, rhs: UnitQuaternion, Output = Isometry, 3>; [val val] => Isometry::from_parts(self.translation, self.rotation / rhs); - [ref val] => Isometry::from_parts(self.translation.clone(), self.rotation / rhs); // TODO: do not clone. + [ref val] => Isometry::from_parts(self.translation, self.rotation / rhs); [val ref] => Isometry::from_parts(self.translation, self.rotation / *rhs); - [ref ref] => Isometry::from_parts(self.translation.clone(), self.rotation / *rhs); + [ref ref] => Isometry::from_parts(self.translation, self.rotation / *rhs); ); // UnitQuaternion ÷ Isometry @@ -492,9 +495,9 @@ isometry_from_composition_impl_all!( D; self: Translation, right: Rotation, Output = Isometry, D>; [val val] => Isometry::from_parts(self, right); - [ref val] => Isometry::from_parts(self.clone(), right); - [val ref] => Isometry::from_parts(self, right.clone()); - [ref ref] => Isometry::from_parts(self.clone(), right.clone()); + [ref val] => Isometry::from_parts(*self, right); + [val ref] => Isometry::from_parts(self, *right); + [ref ref] => Isometry::from_parts(*self, *right); ); // Translation × UnitQuaternion @@ -503,9 +506,9 @@ isometry_from_composition_impl_all!( ; self: Translation, right: UnitQuaternion, Output = Isometry, 3>; [val val] => Isometry::from_parts(self, right); - [ref val] => Isometry::from_parts(self.clone(), right); + [ref val] => Isometry::from_parts(*self, right); [val ref] => Isometry::from_parts(self, *right); - [ref ref] => Isometry::from_parts(self.clone(), *right); + [ref ref] => Isometry::from_parts(*self, *right); ); // Isometry × UnitComplex @@ -515,9 +518,9 @@ isometry_from_composition_impl_all!( self: Isometry, 2>, rhs: UnitComplex, Output = Isometry, 2>; [val val] => Isometry::from_parts(self.translation, self.rotation * rhs); - [ref val] => Isometry::from_parts(self.translation.clone(), self.rotation * rhs); // TODO: do not clone. + [ref val] => Isometry::from_parts(self.translation, self.rotation * rhs); [val ref] => Isometry::from_parts(self.translation, self.rotation * *rhs); - [ref ref] => Isometry::from_parts(self.translation.clone(), self.rotation * *rhs); + [ref ref] => Isometry::from_parts(self.translation, self.rotation * *rhs); ); // Isometry ÷ UnitComplex @@ -527,7 +530,7 @@ isometry_from_composition_impl_all!( self: Isometry, 2>, rhs: UnitComplex, Output = Isometry, 2>; [val val] => Isometry::from_parts(self.translation, self.rotation / rhs); - [ref val] => Isometry::from_parts(self.translation.clone(), self.rotation / rhs); // TODO: do not clone. + [ref val] => Isometry::from_parts(self.translation, self.rotation / rhs); [val ref] => Isometry::from_parts(self.translation, self.rotation / *rhs); - [ref ref] => Isometry::from_parts(self.translation.clone(), self.rotation / *rhs); + [ref ref] => Isometry::from_parts(self.translation, self.rotation / *rhs); ); diff --git a/src/geometry/orthographic.rs b/src/geometry/orthographic.rs index 6cc4dacc..17a5b969 100644 --- a/src/geometry/orthographic.rs +++ b/src/geometry/orthographic.rs @@ -8,7 +8,6 @@ use rand::{ #[cfg(feature = "serde-serialize-no-std")] use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::fmt; -use std::mem; use simba::scalar::RealField; @@ -258,7 +257,7 @@ impl Orthographic3 { #[inline] #[must_use] pub fn as_projective(&self) -> &Projective3 { - unsafe { mem::transmute(self) } + unsafe { &*(self as *const Orthographic3 as *const Projective3) } } /// This transformation seen as a `Projective3`. diff --git a/src/geometry/perspective.rs b/src/geometry/perspective.rs index 65aee5fd..6ad9707f 100644 --- a/src/geometry/perspective.rs +++ b/src/geometry/perspective.rs @@ -9,7 +9,6 @@ use rand::{ #[cfg(feature = "serde-serialize-no-std")] use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::fmt; -use std::mem; use simba::scalar::RealField; @@ -140,7 +139,7 @@ impl Perspective3 { #[inline] #[must_use] pub fn as_projective(&self) -> &Projective3 { - unsafe { mem::transmute(self) } + unsafe { &*(self as *const Perspective3 as *const Projective3) } } /// This transformation seen as a `Projective3`. @@ -256,8 +255,9 @@ impl Perspective3 { #[inline] pub fn set_fovy(&mut self, fovy: T) { let old_m22 = self.matrix[(1, 1)]; - self.matrix[(1, 1)] = T::one() / (fovy / crate::convert(2.0)).tan(); - self.matrix[(0, 0)] = self.matrix[(0, 0)] * (self.matrix[(1, 1)] / old_m22); + let new_m22 = T::one() / (fovy / crate::convert(2.0)).tan(); + self.matrix[(1, 1)] = new_m22; + self.matrix[(0, 0)] *= new_m22 / old_m22; } /// Updates this perspective matrix with a new near plane offset of the view frustum. diff --git a/src/geometry/point_conversion.rs b/src/geometry/point_conversion.rs index 91cd62ce..e5ab8272 100644 --- a/src/geometry/point_conversion.rs +++ b/src/geometry/point_conversion.rs @@ -90,10 +90,10 @@ impl From<[T; D]> for Point { } } -impl Into<[T; D]> for Point { +impl From> for [T; D] { #[inline] - fn into(self) -> [T; D] { - self.coords.into() + fn from(p: Point) -> Self { + p.coords.into() } } diff --git a/src/geometry/quaternion_coordinates.rs b/src/geometry/quaternion_coordinates.rs index d9901888..cb16e59e 100644 --- a/src/geometry/quaternion_coordinates.rs +++ b/src/geometry/quaternion_coordinates.rs @@ -1,4 +1,3 @@ -use std::mem; use std::ops::{Deref, DerefMut}; use simba::simd::SimdValue; @@ -13,13 +12,13 @@ impl Deref for Quaternion { #[inline] fn deref(&self) -> &Self::Target { - unsafe { mem::transmute(self) } + unsafe { &*(self as *const Self as *const Self::Target) } } } impl DerefMut for Quaternion { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { - unsafe { mem::transmute(self) } + unsafe { &mut *(self as *mut Self as *mut Self::Target) } } } diff --git a/src/geometry/quaternion_ops.rs b/src/geometry/quaternion_ops.rs index 6a2c87a0..eb7a15cd 100644 --- a/src/geometry/quaternion_ops.rs +++ b/src/geometry/quaternion_ops.rs @@ -1,3 +1,6 @@ +// The macros break if the references are taken out, for some reason. +#![allow(clippy::op_ref)] + /* * This file provides: * =================== diff --git a/src/geometry/rotation_conversion.rs b/src/geometry/rotation_conversion.rs index 0e83d60f..517010a0 100644 --- a/src/geometry/rotation_conversion.rs +++ b/src/geometry/rotation_conversion.rs @@ -267,10 +267,7 @@ where { #[inline] fn from(arr: [Rotation; 2]) -> Self { - Self::from_matrix_unchecked(OMatrix::from([ - arr[0].clone().into_inner(), - arr[1].clone().into_inner(), - ])) + Self::from_matrix_unchecked(OMatrix::from([arr[0].into_inner(), arr[1].into_inner()])) } } @@ -283,10 +280,10 @@ where #[inline] fn from(arr: [Rotation; 4]) -> Self { Self::from_matrix_unchecked(OMatrix::from([ - arr[0].clone().into_inner(), - arr[1].clone().into_inner(), - arr[2].clone().into_inner(), - arr[3].clone().into_inner(), + arr[0].into_inner(), + arr[1].into_inner(), + arr[2].into_inner(), + arr[3].into_inner(), ])) } } @@ -300,14 +297,14 @@ where #[inline] fn from(arr: [Rotation; 8]) -> Self { Self::from_matrix_unchecked(OMatrix::from([ - arr[0].clone().into_inner(), - arr[1].clone().into_inner(), - arr[2].clone().into_inner(), - arr[3].clone().into_inner(), - arr[4].clone().into_inner(), - arr[5].clone().into_inner(), - arr[6].clone().into_inner(), - arr[7].clone().into_inner(), + arr[0].into_inner(), + arr[1].into_inner(), + arr[2].into_inner(), + arr[3].into_inner(), + arr[4].into_inner(), + arr[5].into_inner(), + arr[6].into_inner(), + arr[7].into_inner(), ])) } } @@ -321,22 +318,22 @@ where #[inline] fn from(arr: [Rotation; 16]) -> Self { Self::from_matrix_unchecked(OMatrix::from([ - arr[0].clone().into_inner(), - arr[1].clone().into_inner(), - arr[2].clone().into_inner(), - arr[3].clone().into_inner(), - arr[4].clone().into_inner(), - arr[5].clone().into_inner(), - arr[6].clone().into_inner(), - arr[7].clone().into_inner(), - arr[8].clone().into_inner(), - arr[9].clone().into_inner(), - arr[10].clone().into_inner(), - arr[11].clone().into_inner(), - arr[12].clone().into_inner(), - arr[13].clone().into_inner(), - arr[14].clone().into_inner(), - arr[15].clone().into_inner(), + arr[0].into_inner(), + arr[1].into_inner(), + arr[2].into_inner(), + arr[3].into_inner(), + arr[4].into_inner(), + arr[5].into_inner(), + arr[6].into_inner(), + arr[7].into_inner(), + arr[8].into_inner(), + arr[9].into_inner(), + arr[10].into_inner(), + arr[11].into_inner(), + arr[12].into_inner(), + arr[13].into_inner(), + arr[14].into_inner(), + arr[15].into_inner(), ])) } } diff --git a/src/geometry/rotation_specialization.rs b/src/geometry/rotation_specialization.rs index a89f5845..6c9ecf21 100644 --- a/src/geometry/rotation_specialization.rs +++ b/src/geometry/rotation_specialization.rs @@ -857,11 +857,7 @@ impl Rotation3 { where T: RealField, { - if let Some(axis) = self.axis() { - Some((axis, self.angle())) - } else { - None - } + self.axis().map(|axis| (axis, self.angle())) } /// The rotation angle needed to make `self` and `other` coincide. diff --git a/src/geometry/similarity.rs b/src/geometry/similarity.rs index 516b95c5..48ce6a85 100755 --- a/src/geometry/similarity.rs +++ b/src/geometry/similarity.rs @@ -178,7 +178,7 @@ where ); Self::from_parts( - Translation::from(&self.isometry.translation.vector * scaling), + Translation::from(self.isometry.translation.vector * scaling), self.isometry.rotation.clone(), self.scaling * scaling, ) diff --git a/src/geometry/similarity_conversion.rs b/src/geometry/similarity_conversion.rs index 2a2338b0..6bc12814 100644 --- a/src/geometry/similarity_conversion.rs +++ b/src/geometry/similarity_conversion.rs @@ -197,7 +197,7 @@ where { #[inline] fn from(arr: [Similarity; 2]) -> Self { - let iso = Isometry::from([arr[0].isometry.clone(), arr[1].isometry.clone()]); + let iso = Isometry::from([arr[0].isometry, arr[1].isometry]); let scale = T::from([arr[0].scaling(), arr[1].scaling()]); Self::from_isometry(iso, scale) @@ -216,10 +216,10 @@ where #[inline] fn from(arr: [Similarity; 4]) -> Self { let iso = Isometry::from([ - arr[0].isometry.clone(), - arr[1].isometry.clone(), - arr[2].isometry.clone(), - arr[3].isometry.clone(), + arr[0].isometry, + arr[1].isometry, + arr[2].isometry, + arr[3].isometry, ]); let scale = T::from([ arr[0].scaling(), @@ -244,14 +244,14 @@ where #[inline] fn from(arr: [Similarity; 8]) -> Self { let iso = Isometry::from([ - arr[0].isometry.clone(), - arr[1].isometry.clone(), - arr[2].isometry.clone(), - arr[3].isometry.clone(), - arr[4].isometry.clone(), - arr[5].isometry.clone(), - arr[6].isometry.clone(), - arr[7].isometry.clone(), + arr[0].isometry, + arr[1].isometry, + arr[2].isometry, + arr[3].isometry, + arr[4].isometry, + arr[5].isometry, + arr[6].isometry, + arr[7].isometry, ]); let scale = T::from([ arr[0].scaling(), @@ -280,22 +280,22 @@ where #[inline] fn from(arr: [Similarity; 16]) -> Self { let iso = Isometry::from([ - arr[0].isometry.clone(), - arr[1].isometry.clone(), - arr[2].isometry.clone(), - arr[3].isometry.clone(), - arr[4].isometry.clone(), - arr[5].isometry.clone(), - arr[6].isometry.clone(), - arr[7].isometry.clone(), - arr[8].isometry.clone(), - arr[9].isometry.clone(), - arr[10].isometry.clone(), - arr[11].isometry.clone(), - arr[12].isometry.clone(), - arr[13].isometry.clone(), - arr[14].isometry.clone(), - arr[15].isometry.clone(), + arr[0].isometry, + arr[1].isometry, + arr[2].isometry, + arr[3].isometry, + arr[4].isometry, + arr[5].isometry, + arr[6].isometry, + arr[7].isometry, + arr[8].isometry, + arr[9].isometry, + arr[10].isometry, + arr[11].isometry, + arr[12].isometry, + arr[13].isometry, + arr[14].isometry, + arr[15].isometry, ]); let scale = T::from([ arr[0].scaling(), diff --git a/src/geometry/similarity_ops.rs b/src/geometry/similarity_ops.rs index c164acaa..b88f9442 100644 --- a/src/geometry/similarity_ops.rs +++ b/src/geometry/similarity_ops.rs @@ -1,3 +1,6 @@ +// The macros break if the references are taken out, for some reason. +#![allow(clippy::op_ref)] + use num::{One, Zero}; use std::ops::{Div, DivAssign, Mul, MulAssign}; @@ -219,7 +222,7 @@ md_assign_impl_all!( const D; for; where; self: Similarity, D>, rhs: Rotation; [val] => self.isometry.rotation *= rhs; - [ref] => self.isometry.rotation *= rhs.clone(); + [ref] => self.isometry.rotation *= *rhs; ); md_assign_impl_all!( diff --git a/src/geometry/transform.rs b/src/geometry/transform.rs index 8c294b15..682d2bd6 100755 --- a/src/geometry/transform.rs +++ b/src/geometry/transform.rs @@ -399,11 +399,9 @@ where #[inline] #[must_use = "Did you mean to use try_inverse_mut()?"] pub fn try_inverse(self) -> Option> { - if let Some(m) = self.matrix.try_inverse() { - Some(Transform::from_matrix_unchecked(m)) - } else { - None - } + self.matrix + .try_inverse() + .map(Transform::from_matrix_unchecked) } /// Inverts this transformation. Use `.try_inverse` if this transform has the `TGeneral` diff --git a/src/geometry/transform_ops.rs b/src/geometry/transform_ops.rs index 29781c3c..efbfa67b 100644 --- a/src/geometry/transform_ops.rs +++ b/src/geometry/transform_ops.rs @@ -1,3 +1,6 @@ +// The macros break if the references are taken out, for some reason. +#![allow(clippy::op_ref)] + use num::{One, Zero}; use std::ops::{Div, DivAssign, Index, IndexMut, Mul, MulAssign}; diff --git a/src/geometry/translation.rs b/src/geometry/translation.rs index 1476e75b..18fa7e04 100755 --- a/src/geometry/translation.rs +++ b/src/geometry/translation.rs @@ -38,7 +38,7 @@ where } } -impl Copy for Translation where Owned>: Copy {} +impl Copy for Translation {} impl Clone for Translation where diff --git a/src/geometry/translation_conversion.rs b/src/geometry/translation_conversion.rs index ff8e797f..d443a2f4 100644 --- a/src/geometry/translation_conversion.rs +++ b/src/geometry/translation_conversion.rs @@ -77,7 +77,7 @@ where { #[inline] fn to_superset(&self) -> UnitDualQuaternion { - let dq = UnitDualQuaternion::::from_parts(self.clone(), UnitQuaternion::identity()); + let dq = UnitDualQuaternion::::from_parts(*self, UnitQuaternion::identity()); dq.to_superset() } @@ -212,16 +212,14 @@ impl From<[T; D]> for Translation { impl From> for Translation { #[inline] fn from(pt: Point) -> Self { - Translation { - vector: pt.coords.into(), - } + Translation { vector: pt.coords } } } -impl Into<[T; D]> for Translation { +impl From> for [T; D] { #[inline] - fn into(self) -> [T; D] { - self.vector.into() + fn from(t: Translation) -> Self { + t.vector.into() } } diff --git a/src/geometry/translation_coordinates.rs b/src/geometry/translation_coordinates.rs index 9a9bf44a..80267e06 100644 --- a/src/geometry/translation_coordinates.rs +++ b/src/geometry/translation_coordinates.rs @@ -1,4 +1,3 @@ -use std::mem; use std::ops::{Deref, DerefMut}; use crate::base::coordinates::{X, XY, XYZ, XYZW, XYZWA, XYZWAB}; @@ -19,15 +18,14 @@ macro_rules! deref_impl( #[inline] fn deref(&self) -> &Self::Target { - unsafe { mem::transmute(self) } + unsafe { &*(self as *const Translation as *const Self::Target) } } } - impl DerefMut for Translation - { + impl DerefMut for Translation { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { - unsafe { mem::transmute(self) } + unsafe { &mut *(self as *mut Translation as *mut Self::Target) } } } } diff --git a/src/geometry/unit_complex_ops.rs b/src/geometry/unit_complex_ops.rs index abaa9d4f..efa91a95 100644 --- a/src/geometry/unit_complex_ops.rs +++ b/src/geometry/unit_complex_ops.rs @@ -1,3 +1,6 @@ +// The macros break if the references are taken out, for some reason. +#![allow(clippy::op_ref)] + use std::ops::{Div, DivAssign, Mul, MulAssign}; use crate::base::storage::Storage; @@ -314,10 +317,10 @@ complex_op_impl_all!( ; self: Translation, right: UnitComplex, Output = Isometry, 2>; - [val val] => Isometry::from_parts(self, right); - [ref val] => Isometry::from_parts(self.clone(), right); - [val ref] => Isometry::from_parts(self, *right); - [ref ref] => Isometry::from_parts(self.clone(), *right); + [val val] => Isometry::from_parts(self, right); + [ref val] => Isometry::from_parts(*self, right); + [val ref] => Isometry::from_parts(self, *right); + [ref ref] => Isometry::from_parts(*self, *right); ); // UnitComplex ×= UnitComplex @@ -327,7 +330,7 @@ where { #[inline] fn mul_assign(&mut self, rhs: UnitComplex) { - *self = &*self * rhs + *self = *self * rhs } } @@ -337,7 +340,7 @@ where { #[inline] fn mul_assign(&mut self, rhs: &'b UnitComplex) { - *self = &*self * rhs + *self = *self * rhs } } @@ -348,7 +351,7 @@ where { #[inline] fn div_assign(&mut self, rhs: UnitComplex) { - *self = &*self / rhs + *self = *self / rhs } } @@ -358,7 +361,7 @@ where { #[inline] fn div_assign(&mut self, rhs: &'b UnitComplex) { - *self = &*self / rhs + *self = *self / rhs } } @@ -369,7 +372,7 @@ where { #[inline] fn mul_assign(&mut self, rhs: Rotation) { - *self = &*self * rhs + *self = *self * rhs } } @@ -379,7 +382,7 @@ where { #[inline] fn mul_assign(&mut self, rhs: &'b Rotation) { - *self = &*self * rhs + *self = *self * rhs } } @@ -390,7 +393,7 @@ where { #[inline] fn div_assign(&mut self, rhs: Rotation) { - *self = &*self / rhs + *self = *self / rhs } } @@ -400,7 +403,7 @@ where { #[inline] fn div_assign(&mut self, rhs: &'b Rotation) { - *self = &*self / rhs + *self = *self / rhs } } diff --git a/src/lib.rs b/src/lib.rs index a978d5f5..04bc4002 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +#![allow(clippy::type_complexity)] /*! # nalgebra @@ -199,19 +200,15 @@ where while val < min { val += width } - - val } else if val > max { val -= width; while val > max { val -= width } - - val - } else { - val } + + val } /// Returns a reference to the input value clamped to the interval `[min, max]`. @@ -393,7 +390,7 @@ pub fn center( p1: &Point, p2: &Point, ) -> Point { - ((&p1.coords + &p2.coords) * convert::<_, T>(0.5)).into() + ((p1.coords + p2.coords) * convert::<_, T>(0.5)).into() } /// The distance between two points. @@ -407,7 +404,7 @@ pub fn distance( p1: &Point, p2: &Point, ) -> T::SimdRealField { - (&p2.coords - &p1.coords).norm() + (p2.coords - p1.coords).norm() } /// The squared distance between two points. @@ -421,7 +418,7 @@ pub fn distance_squared( p1: &Point, p2: &Point, ) -> T::SimdRealField { - (&p2.coords - &p1.coords).norm_squared() + (p2.coords - p1.coords).norm_squared() } /* diff --git a/src/linalg/balancing.rs b/src/linalg/balancing.rs index 3b834563..3965caf1 100644 --- a/src/linalg/balancing.rs +++ b/src/linalg/balancing.rs @@ -8,17 +8,17 @@ use crate::base::dimension::Dim; use crate::base::storage::Storage; use crate::base::{Const, DefaultAllocator, OMatrix, OVector}; -/// Applies in-place a modified Parlett and Reinsch matrix balancing with 2-norm to the matrix `m` and returns +/// Applies in-place a modified Parlett and Reinsch matrix balancing with 2-norm to the matrix and returns /// the corresponding diagonal transformation. /// /// See https://arxiv.org/pdf/1401.5766.pdf -pub fn balance_parlett_reinsch(m: &mut OMatrix) -> OVector +pub fn balance_parlett_reinsch(matrix: &mut OMatrix) -> OVector where DefaultAllocator: Allocator + Allocator, { - assert!(m.is_square(), "Unable to balance a non-square matrix."); + assert!(matrix.is_square(), "Unable to balance a non-square matrix."); - let dim = m.data.shape().0; + let dim = matrix.data.shape().0; let radix: T = crate::convert(2.0f64); let mut d = OVector::from_element_generic(dim, Const::<1>, T::one()); @@ -28,36 +28,37 @@ where converged = true; for i in 0..dim.value() { - let mut c = m.column(i).norm_squared(); - let mut r = m.row(i).norm_squared(); + let mut n_col = matrix.column(i).norm_squared(); + let mut n_row = matrix.row(i).norm_squared(); let mut f = T::one(); - let s = c + r; - c = c.sqrt(); - r = r.sqrt(); + let s = n_col + n_row; + n_col = n_col.sqrt(); + n_row = n_row.sqrt(); - if c.is_zero() || r.is_zero() { + if n_col.is_zero() || n_row.is_zero() { continue; } - while c < r / radix { - c *= radix; - r /= radix; + while n_col < n_row / radix { + n_col *= radix; + n_row /= radix; f *= radix; } - while c >= r * radix { - c /= radix; - r *= radix; + while n_col >= n_row * radix { + n_col /= radix; + n_row *= radix; f /= radix; } let eps: T = crate::convert(0.95); - if c * c + r * r < eps * s { + #[allow(clippy::suspicious_operation_groupings)] + if n_col * n_col + n_row * n_row < eps * s { converged = false; d[i] *= f; - m.column_mut(i).mul_assign(f); - m.row_mut(i).div_assign(f); + matrix.column_mut(i).mul_assign(f); + matrix.row_mut(i).div_assign(f); } } } diff --git a/src/linalg/exp.rs b/src/linalg/exp.rs index acb2b9e3..c2816ff0 100644 --- a/src/linalg/exp.rs +++ b/src/linalg/exp.rs @@ -442,31 +442,31 @@ where return self.map(|v| v.exp()); } - let mut h = ExpmPadeHelper::new(self.clone(), true); + let mut helper = ExpmPadeHelper::new(self.clone(), true); - let eta_1 = T::RealField::max(h.d4_loose(), h.d6_loose()); - if eta_1 < convert(1.495_585_217_958_292e-2) && ell(&h.a, 3) == 0 { - let (u, v) = h.pade3(); + let eta_1 = T::RealField::max(helper.d4_loose(), helper.d6_loose()); + if eta_1 < convert(1.495_585_217_958_292e-2) && ell(&helper.a, 3) == 0 { + let (u, v) = helper.pade3(); return solve_p_q(u, v); } - let eta_2 = T::RealField::max(h.d4_tight(), h.d6_loose()); - if eta_2 < convert(2.539_398_330_063_230e-1) && ell(&h.a, 5) == 0 { - let (u, v) = h.pade5(); + let eta_2 = T::RealField::max(helper.d4_tight(), helper.d6_loose()); + if eta_2 < convert(2.539_398_330_063_23e-1) && ell(&helper.a, 5) == 0 { + let (u, v) = helper.pade5(); return solve_p_q(u, v); } - let eta_3 = T::RealField::max(h.d6_tight(), h.d8_loose()); - if eta_3 < convert(9.504_178_996_162_932e-1) && ell(&h.a, 7) == 0 { - let (u, v) = h.pade7(); + let eta_3 = T::RealField::max(helper.d6_tight(), helper.d8_loose()); + if eta_3 < convert(9.504_178_996_162_932e-1) && ell(&helper.a, 7) == 0 { + let (u, v) = helper.pade7(); return solve_p_q(u, v); } - if eta_3 < convert(2.097_847_961_257_068e+0) && ell(&h.a, 9) == 0 { - let (u, v) = h.pade9(); + if eta_3 < convert(2.097_847_961_257_068e0) && ell(&helper.a, 9) == 0 { + let (u, v) = helper.pade9(); return solve_p_q(u, v); } - let eta_4 = T::RealField::max(h.d8_loose(), h.d10_loose()); + let eta_4 = T::RealField::max(helper.d8_loose(), helper.d10_loose()); let eta_5 = T::RealField::min(eta_3, eta_4); let theta_13 = convert(4.25); @@ -482,9 +482,12 @@ where } }; - s += ell(&(&h.a * convert::(2.0_f64.powf(-(s as f64)))), 13); + s += ell( + &(&helper.a * convert::(2.0_f64.powf(-(s as f64)))), + 13, + ); - let (u, v) = h.pade13_scaled(s); + let (u, v) = helper.pade13_scaled(s); let mut x = solve_p_q(u, v); for _ in 0..s { diff --git a/src/linalg/pow.rs b/src/linalg/pow.rs index 74da2cfe..df513643 100644 --- a/src/linalg/pow.rs +++ b/src/linalg/pow.rs @@ -31,10 +31,8 @@ where // If e is negative, we compute the inverse matrix, then raise it to the // power of -e. - if e < zero { - if !self.try_inverse_mut() { - return false; - } + if e < zero && !self.try_inverse_mut() { + return false; } let one = I::one(); diff --git a/src/linalg/schur.rs b/src/linalg/schur.rs index 16b8c66d..c03f6f08 100644 --- a/src/linalg/schur.rs +++ b/src/linalg/schur.rs @@ -1,3 +1,4 @@ +#![allow(clippy::suspicious_operation_groupings)] #[cfg(feature = "serde-serialize-no-std")] use serde::{Deserialize, Serialize}; diff --git a/src/linalg/svd.rs b/src/linalg/svd.rs index f559c9fa..241f00ce 100644 --- a/src/linalg/svd.rs +++ b/src/linalg/svd.rs @@ -121,11 +121,15 @@ where matrix.unscale_mut(m_amax); } - let b = Bidiagonal::new(matrix); - let mut u = if compute_u { Some(b.u()) } else { None }; - let mut v_t = if compute_v { Some(b.v_t()) } else { None }; - let mut diagonal = b.diagonal(); - let mut off_diagonal = b.off_diagonal(); + let bi_matrix = Bidiagonal::new(matrix); + let mut u = if compute_u { Some(bi_matrix.u()) } else { None }; + let mut v_t = if compute_v { + Some(bi_matrix.v_t()) + } else { + None + }; + let mut diagonal = bi_matrix.diagonal(); + let mut off_diagonal = bi_matrix.off_diagonal(); let mut niter = 0; let (mut start, mut end) = Self::delimit_subproblem( @@ -133,7 +137,7 @@ where &mut off_diagonal, &mut u, &mut v_t, - b.is_upper_diagonal(), + bi_matrix.is_upper_diagonal(), dim - 1, eps, ); @@ -142,6 +146,7 @@ where let subdim = end - start + 1; // Solve the subproblem. + #[allow(clippy::comparison_chain)] if subdim > 2 { let m = end - 1; let n = end; @@ -201,7 +206,7 @@ where subm[(0, 0)] = norm2; if let Some(ref mut v_t) = v_t { - if b.is_upper_diagonal() { + if bi_matrix.is_upper_diagonal() { rot1.rotate(&mut v_t.fixed_rows_mut::<2>(k)); } else { rot2.rotate(&mut v_t.fixed_rows_mut::<2>(k)); @@ -209,7 +214,7 @@ where } if let Some(ref mut u) = u { - if b.is_upper_diagonal() { + if bi_matrix.is_upper_diagonal() { rot2.inverse().rotate_rows(&mut u.fixed_columns_mut::<2>(k)); } else { rot1.inverse().rotate_rows(&mut u.fixed_columns_mut::<2>(k)); @@ -236,8 +241,10 @@ where diagonal[start], off_diagonal[start], diagonal[start + 1], - compute_u && b.is_upper_diagonal() || compute_v && !b.is_upper_diagonal(), - compute_v && b.is_upper_diagonal() || compute_u && !b.is_upper_diagonal(), + compute_u && bi_matrix.is_upper_diagonal() + || compute_v && !bi_matrix.is_upper_diagonal(), + compute_v && bi_matrix.is_upper_diagonal() + || compute_u && !bi_matrix.is_upper_diagonal(), ); let u2 = u2.map(|u2| GivensRotation::new_unchecked(u2.c(), T::from_real(u2.s()))); let v2 = v2.map(|v2| GivensRotation::new_unchecked(v2.c(), T::from_real(v2.s()))); @@ -247,7 +254,7 @@ where off_diagonal[start] = T::RealField::zero(); if let Some(ref mut u) = u { - let rot = if b.is_upper_diagonal() { + let rot = if bi_matrix.is_upper_diagonal() { u2.unwrap() } else { v2.unwrap() @@ -256,7 +263,7 @@ where } if let Some(ref mut v_t) = v_t { - let rot = if b.is_upper_diagonal() { + let rot = if bi_matrix.is_upper_diagonal() { v2.unwrap() } else { u2.unwrap() @@ -273,7 +280,7 @@ where &mut off_diagonal, &mut u, &mut v_t, - b.is_upper_diagonal(), + bi_matrix.is_upper_diagonal(), end, eps, ); diff --git a/src/linalg/symmetric_eigen.rs b/src/linalg/symmetric_eigen.rs index 25dab08c..5ac6d5da 100644 --- a/src/linalg/symmetric_eigen.rs +++ b/src/linalg/symmetric_eigen.rs @@ -87,7 +87,7 @@ where } fn do_decompose( - mut m: OMatrix, + mut matrix: OMatrix, eigenvectors: bool, eps: T::RealField, max_niter: usize, @@ -97,33 +97,33 @@ where DefaultAllocator: Allocator> + Allocator>, { assert!( - m.is_square(), + matrix.is_square(), "Unable to compute the eigendecomposition of a non-square matrix." ); - let dim = m.nrows(); - let m_amax = m.camax(); + let dim = matrix.nrows(); + let m_amax = matrix.camax(); if !m_amax.is_zero() { - m.unscale_mut(m_amax); + matrix.unscale_mut(m_amax); } - let (mut q, mut diag, mut off_diag); + let (mut q_mat, mut diag, mut off_diag); if eigenvectors { - let res = SymmetricTridiagonal::new(m).unpack(); - q = Some(res.0); + let res = SymmetricTridiagonal::new(matrix).unpack(); + q_mat = Some(res.0); diag = res.1; off_diag = res.2; } else { - let res = SymmetricTridiagonal::new(m).unpack_tridiagonal(); - q = None; + let res = SymmetricTridiagonal::new(matrix).unpack_tridiagonal(); + q_mat = None; diag = res.0; off_diag = res.1; } if dim == 1 { diag.scale_mut(m_amax); - return Some((diag, q)); + return Some((diag, q_mat)); } let mut niter = 0; @@ -132,11 +132,12 @@ where while end != start { let subdim = end - start + 1; + #[allow(clippy::comparison_chain)] if subdim > 2 { let m = end - 1; let n = end; - let mut v = Vector2::new( + let mut vec = Vector2::new( diag[start] - wilkinson_shift(diag[m], diag[n], off_diag[m]), off_diag[start], ); @@ -144,7 +145,7 @@ where for i in start..n { let j = i + 1; - if let Some((rot, norm)) = GivensRotation::cancel_y(&v) { + if let Some((rot, norm)) = GivensRotation::cancel_y(&vec) { if i > start { // Not the first iteration. off_diag[i - 1] = norm; @@ -165,12 +166,12 @@ where off_diag[i] = cs * (mii - mjj) + mij * (cc - ss); if i != n - 1 { - v.x = off_diag[i]; - v.y = -rot.s() * off_diag[i + 1]; + vec.x = off_diag[i]; + vec.y = -rot.s() * off_diag[i + 1]; off_diag[i + 1] *= rot.c(); } - if let Some(ref mut q) = q { + if let Some(ref mut q) = q_mat { let rot = GivensRotation::new_unchecked(rot.c(), T::from_real(rot.s())); rot.inverse().rotate_rows(&mut q.fixed_columns_mut::<2>(i)); } @@ -195,7 +196,7 @@ where diag[start] = eigvals[0]; diag[start + 1] = eigvals[1]; - if let Some(ref mut q) = q { + if let Some(ref mut q) = q_mat { if let Some((rot, _)) = GivensRotation::try_new(basis.x, basis.y, eps) { let rot = GivensRotation::new_unchecked(rot.c(), T::from_real(rot.s())); rot.rotate_rows(&mut q.fixed_columns_mut::<2>(start)); @@ -219,7 +220,7 @@ where diag.scale_mut(m_amax); - Some((diag, q)) + Some((diag, q_mat)) } fn delimit_subproblem( diff --git a/tests/linalg/convolution.rs b/tests/linalg/convolution.rs index 84f42a6e..b2e151d3 100644 --- a/tests/linalg/convolution.rs +++ b/tests/linalg/convolution.rs @@ -26,18 +26,20 @@ fn convolve_same_check() { // Panic Tests // These really only apply to dynamic sized vectors assert!(panic::catch_unwind(|| { - DVector::from_vec(vec![1.0, 2.0]) + let _ = DVector::from_vec(vec![1.0, 2.0]) .convolve_same(DVector::from_vec(vec![1.0, 2.0, 3.0, 4.0])); }) .is_err()); assert!(panic::catch_unwind(|| { - DVector::::from_vec(vec![]).convolve_same(DVector::from_vec(vec![1.0, 2.0, 3.0, 4.0])); + let _ = DVector::::from_vec(vec![]) + .convolve_same(DVector::from_vec(vec![1.0, 2.0, 3.0, 4.0])); }) .is_err()); assert!(panic::catch_unwind(|| { - DVector::from_vec(vec![1.0, 2.0, 3.0, 4.0]).convolve_same(DVector::::from_vec(vec![])); + let _ = DVector::from_vec(vec![1.0, 2.0, 3.0, 4.0]) + .convolve_same(DVector::::from_vec(vec![])); }) .is_err()); } From 1554c0114e4bfdbcae24ab6bed6e22252b9be424 Mon Sep 17 00:00:00 2001 From: Cryptjar Date: Fri, 18 Jun 2021 13:18:33 +0200 Subject: [PATCH 20/42] 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 21/42] =?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 22/42] 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 23/42] 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 24/42] 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 25/42] 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 26/42] 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 27/42] 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 28/42] 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 29/42] 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 30/42] 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 31/42] 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 32/42] 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 33/42] 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 34/42] 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 35/42] 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 36/42] 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 37/42] 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 38/42] 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 39/42] 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 40/42] 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 41/42] 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 42/42] 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