From f8cd26cfa91b64108110d6925750f6992459604f Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sat, 21 Mar 2020 12:16:46 +0100 Subject: [PATCH] Replace alga by simba. --- Cargo.toml | 13 +- examples/scalar_genericity.rs | 2 +- nalgebra-glm/src/traits.rs | 20 +- nalgebra-lapack/src/eigen.rs | 23 +- nalgebra-lapack/src/schur.rs | 23 +- nalgebra-lapack/src/symmetric_eigen.rs | 19 +- src/base/blas.rs | 2 +- src/base/cg.rs | 41 +-- src/base/componentwise.rs | 2 +- src/base/construction.rs | 34 +- src/base/conversion.rs | 136 ++++--- src/base/dimension.rs | 1 - src/base/matrix.rs | 12 +- src/base/matrix_alga.rs | 424 ---------------------- src/base/matrix_simba.rs | 65 ++++ src/base/mod.rs | 14 +- src/base/norm.rs | 77 +++- src/base/ops.rs | 7 +- src/base/properties.rs | 12 +- src/base/statistics.rs | 72 ++-- src/base/storage.rs | 3 - src/base/unit.rs | 84 +++-- src/debug/random_orthogonal.rs | 4 +- src/debug/random_sdp.rs | 4 +- src/geometry/abstract_rotation.rs | 136 +++++++ src/geometry/isometry.rs | 30 +- src/geometry/isometry_alga.rs | 203 ----------- src/geometry/isometry_construction.rs | 15 +- src/geometry/isometry_conversion.rs | 27 +- src/geometry/isometry_ops.rs | 108 ++++-- src/geometry/isometry_simba.rs | 62 ++++ src/geometry/mod.rs | 18 +- src/geometry/op_macros.rs | 9 +- src/geometry/orthographic.rs | 4 +- src/geometry/perspective.rs | 7 +- src/geometry/point_alga.rs | 83 ----- src/geometry/point_construction.rs | 2 +- src/geometry/point_conversion.rs | 15 +- src/geometry/point_ops.rs | 6 +- src/geometry/point_simba.rs | 51 +++ src/geometry/quaternion.rs | 141 ++++--- src/geometry/quaternion_alga.rs | 307 ---------------- src/geometry/quaternion_construction.rs | 46 +-- src/geometry/quaternion_conversion.rs | 36 +- src/geometry/quaternion_coordinates.rs | 6 +- src/geometry/quaternion_ops.rs | 155 ++++---- src/geometry/quaternion_simba.rs | 47 +++ src/geometry/reflection.rs | 13 +- src/geometry/rotation.rs | 4 +- src/geometry/rotation_alga.rs | 276 -------------- src/geometry/rotation_construction.rs | 2 +- src/geometry/rotation_conversion.rs | 27 +- src/geometry/rotation_ops.rs | 2 +- src/geometry/rotation_simba.rs | 54 +++ src/geometry/rotation_specialization.rs | 24 +- src/geometry/similarity.rs | 53 ++- src/geometry/similarity_alga.rs | 189 ---------- src/geometry/similarity_construction.rs | 17 +- src/geometry/similarity_conversion.rs | 27 +- src/geometry/similarity_ops.rs | 147 +++++--- src/geometry/similarity_simba.rs | 65 ++++ src/geometry/transform.rs | 13 +- src/geometry/transform_alga.rs | 146 -------- src/geometry/transform_construction.rs | 2 +- src/geometry/transform_conversion.rs | 6 +- src/geometry/transform_ops.rs | 2 +- src/geometry/transform_simba.rs | 55 +++ src/geometry/translation.rs | 7 +- src/geometry/translation_alga.rs | 231 +++--------- src/geometry/translation_construction.rs | 2 +- src/geometry/translation_conversion.rs | 21 +- src/geometry/translation_ops.rs | 2 +- src/geometry/unit_complex.rs | 39 +- src/geometry/unit_complex_alga.rs | 180 --------- src/geometry/unit_complex_construction.rs | 4 +- src/geometry/unit_complex_conversion.rs | 24 +- src/geometry/unit_complex_ops.rs | 4 +- src/geometry/unit_complex_simba.rs | 50 +++ src/lib.rs | 313 +++------------- src/linalg/balancing.rs | 2 +- src/linalg/bidiagonal.rs | 31 +- src/linalg/cholesky.rs | 103 ++++-- src/linalg/determinant.rs | 2 +- src/linalg/eigen.rs | 27 +- src/linalg/full_piv_lu.rs | 17 +- src/linalg/givens.rs | 23 +- src/linalg/hessenberg.rs | 17 +- src/linalg/householder.rs | 4 +- src/linalg/inverse.rs | 2 +- src/linalg/lu.rs | 25 +- src/linalg/permutation_sequence.rs | 17 +- src/linalg/qr.rs | 27 +- src/linalg/schur.rs | 41 ++- src/linalg/solve.rs | 107 +++--- src/linalg/svd.rs | 119 ++++-- src/linalg/symmetric_eigen.rs | 59 +-- src/linalg/symmetric_tridiagonal.rs | 44 ++- src/sparse/cs_matrix.rs | 14 +- src/sparse/cs_matrix_conversion.rs | 2 +- src/sparse/cs_matrix_ops.rs | 6 +- tests/geometry/rotation.rs | 2 +- 101 files changed, 2041 insertions(+), 3259 deletions(-) delete mode 100644 src/base/matrix_alga.rs create mode 100644 src/base/matrix_simba.rs create mode 100644 src/geometry/abstract_rotation.rs delete mode 100755 src/geometry/isometry_alga.rs create mode 100755 src/geometry/isometry_simba.rs delete mode 100644 src/geometry/point_alga.rs create mode 100644 src/geometry/point_simba.rs delete mode 100755 src/geometry/quaternion_alga.rs create mode 100755 src/geometry/quaternion_simba.rs delete mode 100755 src/geometry/rotation_alga.rs create mode 100755 src/geometry/rotation_simba.rs delete mode 100755 src/geometry/similarity_alga.rs create mode 100755 src/geometry/similarity_simba.rs delete mode 100755 src/geometry/transform_alga.rs create mode 100755 src/geometry/transform_simba.rs delete mode 100755 src/geometry/unit_complex_alga.rs create mode 100755 src/geometry/unit_complex_simba.rs diff --git a/Cargo.toml b/Cargo.toml index f25718e3..d822e712 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ path = "src/lib.rs" [features] default = [ "std" ] -std = [ "matrixmultiply", "rand/std", "rand_distr", "alga/std" ] +std = [ "matrixmultiply", "rand/std", "rand_distr", "simba/std" ] stdweb = [ "rand/stdweb" ] arbitrary = [ "quickcheck" ] serde-serialize = [ "serde", "serde_derive", "num-complex/serde" ] @@ -39,7 +39,8 @@ num-traits = { version = "0.2", default-features = false } num-complex = { version = "0.2", default-features = false } num-rational = { version = "0.2", default-features = false } approx = { version = "0.3", default-features = false } -alga = { version = "0.9", default-features = false } +simba = { path = "../simba" } +#alga = { version = "0.9", default-features = false } rand_distr = { version = "0.2", optional = true } matrixmultiply = { version = "0.2", optional = true } serde = { version = "1.0", optional = true } @@ -50,9 +51,6 @@ quickcheck = { version = "0.9", optional = true } pest = { version = "2.0", optional = true } pest_derive = { version = "2.0", optional = true } -#[patch.crates-io] -#alga = { git = "https://github.com/rustsim/alga", branch = "dev" } - [dev-dependencies] serde_json = "1.0" rand_xorshift = "0.2" @@ -61,7 +59,7 @@ rand_isaac = "0.2" ### We can't just let this uncommented because that would break ### compilation for #[no-std] because of the terrible Cargo bug ### https://github.com/rust-lang/cargo/issues/4866 -#criterion = "0.2.10" +criterion = "0.2.10" [workspace] members = [ "nalgebra-lapack", "nalgebra-glm" ] @@ -73,3 +71,6 @@ path = "benches/lib.rs" [profile.bench] lto = true + +#[patch.crates-io] +#alga = { path = "../alga/alga" } \ No newline at end of file diff --git a/examples/scalar_genericity.rs b/examples/scalar_genericity.rs index 75f6f9d4..888dcefc 100644 --- a/examples/scalar_genericity.rs +++ b/examples/scalar_genericity.rs @@ -1,8 +1,8 @@ extern crate alga; extern crate nalgebra as na; -use alga::general::{RealField, RingCommutative}; use na::{Scalar, Vector3}; +use simba::scalar::{RealField, RingCommutative}; fn print_vector(m: &Vector3) { println!("{:?}", m) diff --git a/nalgebra-glm/src/traits.rs b/nalgebra-glm/src/traits.rs index 22fd5581..1783ee5d 100644 --- a/nalgebra-glm/src/traits.rs +++ b/nalgebra-glm/src/traits.rs @@ -1,9 +1,9 @@ use approx::AbsDiffEq; use num::{Bounded, FromPrimitive, Signed}; -use alga::general::{Lattice, Ring}; use na::allocator::Allocator; use na::{DimMin, DimName, Scalar, U1}; +use simba::scalar::{Lattice, Ring}; /// A type-level number representing a vector, matrix row, or matrix column, dimension. pub trait Dimension: DimName + DimMin {} @@ -15,9 +15,18 @@ pub trait Number: { } -impl + Signed + FromPrimitive + Bounded> - Number for T -{} +impl< + T: Scalar + + Copy + + Ring + + Lattice + + AbsDiffEq + + Signed + + FromPrimitive + + Bounded, + > Number for T +{ +} #[doc(hidden)] pub trait Alloc: @@ -76,4 +85,5 @@ impl Alloc for T where T: All + Allocator + Allocator<(usize, usize), R> + Allocator<(usize, usize), C> -{} +{ +} diff --git a/nalgebra-lapack/src/eigen.rs b/nalgebra-lapack/src/eigen.rs index 91bc01ac..9df43087 100644 --- a/nalgebra-lapack/src/eigen.rs +++ b/nalgebra-lapack/src/eigen.rs @@ -4,13 +4,13 @@ use serde::{Deserialize, Serialize}; use num::Zero; use num_complex::Complex; -use alga::general::RealField; +use simba::scalar::RealField; +use crate::ComplexHelper; use na::allocator::Allocator; use na::dimension::{Dim, U1}; use na::storage::Storage; use na::{DefaultAllocator, Matrix, MatrixN, Scalar, VectorN}; -use crate::ComplexHelper; use lapack; @@ -18,19 +18,19 @@ use lapack; #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[cfg_attr( feature = "serde-serialize", - serde(bound( - serialize = "DefaultAllocator: Allocator + Allocator, + serde( + bound(serialize = "DefaultAllocator: Allocator + Allocator, VectorN: Serialize, - MatrixN: Serialize" - )) + MatrixN: Serialize") + ) )] #[cfg_attr( feature = "serde-serialize", - serde(bound( - deserialize = "DefaultAllocator: Allocator + Allocator, + serde( + bound(deserialize = "DefaultAllocator: Allocator + Allocator, VectorN: Serialize, - MatrixN: Deserialize<'de>" - )) + MatrixN: Deserialize<'de>") + ) )] #[derive(Clone, Debug)] pub struct Eigen @@ -49,7 +49,8 @@ where DefaultAllocator: Allocator + Allocator, VectorN: Copy, MatrixN: Copy, -{} +{ +} impl Eigen where DefaultAllocator: Allocator + Allocator diff --git a/nalgebra-lapack/src/schur.rs b/nalgebra-lapack/src/schur.rs index 0592acdf..50871975 100644 --- a/nalgebra-lapack/src/schur.rs +++ b/nalgebra-lapack/src/schur.rs @@ -4,13 +4,13 @@ use serde::{Deserialize, Serialize}; use num::Zero; use num_complex::Complex; -use alga::general::RealField; +use simba::scalar::RealField; +use crate::ComplexHelper; use na::allocator::Allocator; use na::dimension::{Dim, U1}; use na::storage::Storage; use na::{DefaultAllocator, Matrix, MatrixN, Scalar, VectorN}; -use crate::ComplexHelper; use lapack; @@ -18,19 +18,19 @@ use lapack; #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[cfg_attr( feature = "serde-serialize", - serde(bound( - serialize = "DefaultAllocator: Allocator + Allocator, + serde( + bound(serialize = "DefaultAllocator: Allocator + Allocator, VectorN: Serialize, - MatrixN: Serialize" - )) + MatrixN: Serialize") + ) )] #[cfg_attr( feature = "serde-serialize", - serde(bound( - deserialize = "DefaultAllocator: Allocator + Allocator, + serde( + bound(deserialize = "DefaultAllocator: Allocator + Allocator, VectorN: Serialize, - MatrixN: Deserialize<'de>" - )) + MatrixN: Deserialize<'de>") + ) )] #[derive(Clone, Debug)] pub struct Schur @@ -47,7 +47,8 @@ where DefaultAllocator: Allocator + Allocator, MatrixN: Copy, VectorN: Copy, -{} +{ +} impl Schur where DefaultAllocator: Allocator + Allocator diff --git a/nalgebra-lapack/src/symmetric_eigen.rs b/nalgebra-lapack/src/symmetric_eigen.rs index e575fdc1..3a21c797 100644 --- a/nalgebra-lapack/src/symmetric_eigen.rs +++ b/nalgebra-lapack/src/symmetric_eigen.rs @@ -4,13 +4,13 @@ use serde::{Deserialize, Serialize}; use num::Zero; use std::ops::MulAssign; -use alga::general::RealField; +use simba::scalar::RealField; +use crate::ComplexHelper; use na::allocator::Allocator; use na::dimension::{Dim, U1}; use na::storage::Storage; use na::{DefaultAllocator, Matrix, MatrixN, Scalar, VectorN}; -use crate::ComplexHelper; use lapack; @@ -18,21 +18,17 @@ use lapack; #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[cfg_attr( feature = "serde-serialize", - serde(bound( - serialize = "DefaultAllocator: Allocator + + serde(bound(serialize = "DefaultAllocator: Allocator + Allocator, VectorN: Serialize, - MatrixN: Serialize" - )) + MatrixN: Serialize")) )] #[cfg_attr( feature = "serde-serialize", - serde(bound( - deserialize = "DefaultAllocator: Allocator + + serde(bound(deserialize = "DefaultAllocator: Allocator + Allocator, VectorN: Deserialize<'de>, - MatrixN: Deserialize<'de>" - )) + MatrixN: Deserialize<'de>")) )] #[derive(Clone, Debug)] pub struct SymmetricEigen @@ -50,7 +46,8 @@ where DefaultAllocator: Allocator + Allocator, MatrixN: Copy, VectorN: Copy, -{} +{ +} impl SymmetricEigen where DefaultAllocator: Allocator + Allocator diff --git a/src/base/blas.rs b/src/base/blas.rs index 5565e561..0c9ef1a7 100644 --- a/src/base/blas.rs +++ b/src/base/blas.rs @@ -1,8 +1,8 @@ use crate::SimdComplexField; -use alga::general::{ClosedAdd, ClosedMul, ComplexField}; #[cfg(feature = "std")] use matrixmultiply; use num::{One, Signed, Zero}; +use simba::scalar::{ClosedAdd, ClosedMul, ComplexField}; #[cfg(feature = "std")] use std::mem; diff --git a/src/base/cg.rs b/src/base/cg.rs index d999bb16..e61483b8 100644 --- a/src/base/cg.rs +++ b/src/base/cg.rs @@ -5,7 +5,7 @@ * */ -use num::One; +use num::{One, Zero}; use crate::base::allocator::Allocator; use crate::base::dimension::{DimName, DimNameDiff, DimNameSub, U1}; @@ -18,12 +18,11 @@ use crate::geometry::{ Isometry, IsometryMatrix3, Orthographic3, Perspective3, Point, Point3, Rotation2, Rotation3, }; -use alga::general::{RealField, Ring}; -use alga::linear::Transformation; +use simba::scalar::{ClosedAdd, ClosedMul, RealField}; impl MatrixN where - N: Scalar + Ring, + N: Scalar + Zero + One, DefaultAllocator: Allocator, { /// Creates a new homogeneous matrix that applies the same scaling factor on each dimension. @@ -42,7 +41,7 @@ where D: DimNameSub, SB: Storage>, { - let mut res = Self::one(); + let mut res = Self::identity(); for i in 0..scaling.len() { res[(i, i)] = scaling[i].inlined_clone(); } @@ -57,7 +56,7 @@ where D: DimNameSub, SB: Storage>, { - let mut res = Self::one(); + let mut res = Self::identity(); res.fixed_slice_mut::, U1>(0, D::dim() - 1) .copy_from(translation); @@ -135,7 +134,7 @@ impl Matrix4 { } /// Deprecated: Use [Matrix4::face_towards] instead. - #[deprecated(note="renamed to `face_towards`")] + #[deprecated(note = "renamed to `face_towards`")] pub fn new_observer_frame(eye: &Point3, target: &Point3, up: &Vector3) -> Self { Matrix4::face_towards(eye, target, up) } @@ -153,7 +152,9 @@ impl Matrix4 { } } -impl> SquareMatrix { +impl> + SquareMatrix +{ /// Computes the transformation equal to `self` followed by an uniform scaling factor. #[inline] #[must_use = "Did you mean to use append_scaling_mut()?"] @@ -246,7 +247,9 @@ impl> SquareMatrix { } } -impl> SquareMatrix { +impl> + SquareMatrix +{ /// Computes in-place the transformation equal to `self` followed by an uniform scaling factor. #[inline] pub fn append_scaling_mut(&mut self, scaling: N) @@ -370,23 +373,3 @@ where DefaultAllocator: Allocator } } } - -impl> Transformation>> for MatrixN -where DefaultAllocator: Allocator - + Allocator> - + Allocator, DimNameDiff> -{ - #[inline] - fn transform_vector( - &self, - v: &VectorN>, - ) -> VectorN> - { - self.transform_vector(v) - } - - #[inline] - fn transform_point(&self, pt: &Point>) -> Point> { - self.transform_point(pt) - } -} diff --git a/src/base/componentwise.rs b/src/base/componentwise.rs index c4ce1293..9f6d68eb 100644 --- a/src/base/componentwise.rs +++ b/src/base/componentwise.rs @@ -3,7 +3,7 @@ use num::{Signed, Zero}; use std::ops::{Add, Mul}; -use alga::general::{ClosedDiv, ClosedMul}; +use simba::scalar::{ClosedDiv, ClosedMul}; use crate::base::allocator::{Allocator, SameShapeAllocator}; use crate::base::constraint::{SameNumberOfColumns, SameNumberOfRows, ShapeConstraint}; diff --git a/src/base/construction.rs b/src/base/construction.rs index f6056576..f9223179 100644 --- a/src/base/construction.rs +++ b/src/base/construction.rs @@ -4,18 +4,18 @@ use crate::base::storage::Owned; use quickcheck::{Arbitrary, Gen}; use num::{Bounded, One, Zero}; -use rand::distributions::{Distribution, Standard}; -use rand::Rng; #[cfg(feature = "std")] use rand; +use rand::distributions::{Distribution, Standard}; +use rand::Rng; #[cfg(feature = "std")] use rand_distr::StandardNormal; use std::iter; use typenum::{self, Cmp, Greater}; #[cfg(feature = "std")] -use alga::general::RealField; -use alga::general::{ClosedAdd, ClosedMul}; +use simba::scalar::RealField; +use simba::scalar::{ClosedAdd, ClosedMul}; use crate::base::allocator::Allocator; use crate::base::dimension::{Dim, DimName, Dynamic, U1, U2, U3, U4, U5, U6}; @@ -576,9 +576,9 @@ macro_rules! impl_constructors( // FIXME: this is not very pretty. We could find a better call syntax. impl_constructors!(R, C; // Arguments for Matrix - => R: DimName, => C: DimName; // Type parameters for impl - R::name(), C::name(); // Arguments for `_generic` constructors. - ); // Arguments for non-generic constructors. +=> R: DimName, => C: DimName; // Type parameters for impl +R::name(), C::name(); // Arguments for `_generic` constructors. +); // Arguments for non-generic constructors. impl_constructors!(R, Dynamic; => R: DimName; @@ -693,27 +693,25 @@ macro_rules! impl_constructors_from_data( // FIXME: this is not very pretty. We could find a better call syntax. impl_constructors_from_data!(data; R, C; // Arguments for Matrix - => R: DimName, => C: DimName; // Type parameters for impl - R::name(), C::name(); // Arguments for `_generic` constructors. - ); // Arguments for non-generic constructors. +=> R: DimName, => C: DimName; // Type parameters for impl +R::name(), C::name(); // Arguments for `_generic` constructors. +); // Arguments for non-generic constructors. impl_constructors_from_data!(data; R, Dynamic; - => R: DimName; - R::name(), Dynamic::new(data.len() / R::dim()); - ); +=> R: DimName; +R::name(), Dynamic::new(data.len() / R::dim()); +); impl_constructors_from_data!(data; Dynamic, C; - => C: DimName; - Dynamic::new(data.len() / C::dim()), C::name(); - ); +=> C: DimName; +Dynamic::new(data.len() / C::dim()), C::name(); +); impl_constructors_from_data!(data; Dynamic, Dynamic; ; Dynamic::new(nrows), Dynamic::new(ncols); nrows, ncols); - - /* * * Zero, One, Rand traits. diff --git a/src/base/conversion.rs b/src/base/conversion.rs index e52a0c5d..fc60711d 100644 --- a/src/base/conversion.rs +++ b/src/base/conversion.rs @@ -1,6 +1,6 @@ -use alga::general::{SubsetOf, SupersetOf}; #[cfg(feature = "mint")] use mint; +use simba::scalar::{SubsetOf, SupersetOf}; use std::convert::{AsMut, AsRef, From, Into}; use std::mem; use std::ptr; @@ -11,17 +11,20 @@ use typenum::Prod; use crate::base::allocator::{Allocator, SameShapeAllocator}; use crate::base::constraint::{SameNumberOfColumns, SameNumberOfRows, ShapeConstraint}; +#[cfg(any(feature = "std", feature = "alloc"))] +use crate::base::dimension::Dynamic; use crate::base::dimension::{ Dim, DimName, U1, U10, U11, U12, U13, U14, U15, U16, U2, U3, U4, U5, U6, U7, U8, U9, }; -#[cfg(any(feature = "std", feature = "alloc"))] -use crate::base::dimension::Dynamic; use crate::base::iter::{MatrixIter, MatrixIterMut}; use crate::base::storage::{ContiguousStorage, ContiguousStorageMut, Storage, StorageMut}; #[cfg(any(feature = "std", feature = "alloc"))] use crate::base::VecStorage; +use crate::base::{ + ArrayStorage, DVectorSlice, DVectorSliceMut, DefaultAllocator, Matrix, MatrixMN, MatrixSlice, + MatrixSliceMut, Scalar, +}; use crate::base::{SliceStorage, SliceStorageMut}; -use crate::base::{DefaultAllocator, Matrix, ArrayStorage, MatrixMN, MatrixSlice, MatrixSliceMut, Scalar, DVectorSlice, DVectorSliceMut}; use crate::constraint::DimEq; // FIXME: too bad this won't work allo slice conversions. @@ -46,7 +49,9 @@ where let mut res = unsafe { MatrixMN::::new_uninitialized_generic(nrows2, ncols2) }; for i in 0..nrows { for j in 0..ncols { - unsafe { *res.get_unchecked_mut((i, j)) = N2::from_subset(self.get_unchecked((i, j))) } + unsafe { + *res.get_unchecked_mut((i, j)) = N2::from_subset(self.get_unchecked((i, j))) + } } } @@ -59,15 +64,17 @@ where } #[inline] - unsafe fn from_superset_unchecked(m: &MatrixMN) -> Self { + fn from_superset_unchecked(m: &MatrixMN) -> Self { let (nrows2, ncols2) = m.shape(); let nrows = R1::from_usize(nrows2); let ncols = C1::from_usize(ncols2); - let mut res = Self::new_uninitialized_generic(nrows, ncols); + let mut res = unsafe { Self::new_uninitialized_generic(nrows, ncols) }; for i in 0..nrows2 { for j in 0..ncols2 { - *res.get_unchecked_mut((i, j)) = m.get_unchecked((i, j)).to_subset_unchecked() + unsafe { + *res.get_unchecked_mut((i, j)) = m.get_unchecked((i, j)).to_subset_unchecked() + } } } @@ -428,18 +435,20 @@ where } impl<'a, N, R, C, RSlice, CSlice, RStride, CStride, S> From<&'a Matrix> -for MatrixSlice<'a, N, RSlice, CSlice, RStride, CStride> - where - N: Scalar, - R: Dim, - C: Dim, - RSlice: Dim, - CSlice: Dim, - RStride: Dim, - CStride: Dim, - S: Storage, - ShapeConstraint: DimEq + DimEq - + DimEq + DimEq + for MatrixSlice<'a, N, RSlice, CSlice, RStride, CStride> +where + N: Scalar, + R: Dim, + C: Dim, + RSlice: Dim, + CSlice: Dim, + RStride: Dim, + CStride: Dim, + S: Storage, + ShapeConstraint: DimEq + + DimEq + + DimEq + + DimEq, { fn from(m: &'a Matrix) -> Self { let (row, col) = m.data.shape(); @@ -452,27 +461,31 @@ for MatrixSlice<'a, N, RSlice, CSlice, RStride, CStride> let cstride_slice = CStride::from_usize(cstride); unsafe { - let data = SliceStorage::from_raw_parts(m.data.ptr(), - (row_slice, col_slice), - (rstride_slice, cstride_slice)); + let data = SliceStorage::from_raw_parts( + m.data.ptr(), + (row_slice, col_slice), + (rstride_slice, cstride_slice), + ); Matrix::from_data_statically_unchecked(data) } } } impl<'a, N, R, C, RSlice, CSlice, RStride, CStride, S> From<&'a mut Matrix> -for MatrixSlice<'a, N, RSlice, CSlice, RStride, CStride> - where - N: Scalar, - R: Dim, - C: Dim, - RSlice: Dim, - CSlice: Dim, - RStride: Dim, - CStride: Dim, - S: Storage, - ShapeConstraint: DimEq + DimEq - + DimEq + DimEq + for MatrixSlice<'a, N, RSlice, CSlice, RStride, CStride> +where + N: Scalar, + R: Dim, + C: Dim, + RSlice: Dim, + CSlice: Dim, + RStride: Dim, + CStride: Dim, + S: Storage, + ShapeConstraint: DimEq + + DimEq + + DimEq + + DimEq, { fn from(m: &'a mut Matrix) -> Self { let (row, col) = m.data.shape(); @@ -485,27 +498,31 @@ for MatrixSlice<'a, N, RSlice, CSlice, RStride, CStride> let cstride_slice = CStride::from_usize(cstride); unsafe { - let data = SliceStorage::from_raw_parts(m.data.ptr(), - (row_slice, col_slice), - (rstride_slice, cstride_slice)); + let data = SliceStorage::from_raw_parts( + m.data.ptr(), + (row_slice, col_slice), + (rstride_slice, cstride_slice), + ); Matrix::from_data_statically_unchecked(data) } } } impl<'a, N, R, C, RSlice, CSlice, RStride, CStride, S> From<&'a mut Matrix> -for MatrixSliceMut<'a, N, RSlice, CSlice, RStride, CStride> - where - N: Scalar, - R: Dim, - C: Dim, - RSlice: Dim, - CSlice: Dim, - RStride: Dim, - CStride: Dim, - S: StorageMut, - ShapeConstraint: DimEq + DimEq - + DimEq + DimEq + for MatrixSliceMut<'a, N, RSlice, CSlice, RStride, CStride> +where + N: Scalar, + R: Dim, + C: Dim, + RSlice: Dim, + CSlice: Dim, + RStride: Dim, + CStride: Dim, + S: StorageMut, + ShapeConstraint: DimEq + + DimEq + + DimEq + + DimEq, { fn from(m: &'a mut Matrix) -> Self { let (row, col) = m.data.shape(); @@ -518,29 +535,34 @@ for MatrixSliceMut<'a, N, RSlice, CSlice, RStride, CStride> let cstride_slice = CStride::from_usize(cstride); unsafe { - let data = SliceStorageMut::from_raw_parts(m.data.ptr_mut(), - (row_slice, col_slice), - (rstride_slice, cstride_slice)); + let data = SliceStorageMut::from_raw_parts( + m.data.ptr_mut(), + (row_slice, col_slice), + (rstride_slice, cstride_slice), + ); Matrix::from_data_statically_unchecked(data) } } } -impl<'a, N: Scalar + Copy, R: Dim, C: Dim, S: ContiguousStorage> Into<&'a [N]> for &'a Matrix { +impl<'a, N: Scalar + Copy, R: Dim, C: Dim, S: ContiguousStorage> Into<&'a [N]> + for &'a Matrix +{ #[inline] fn into(self) -> &'a [N] { self.as_slice() } } -impl<'a, N: Scalar + Copy, R: Dim, C: Dim, S: ContiguousStorageMut> Into<&'a mut [N]> for &'a mut Matrix { +impl<'a, N: Scalar + Copy, R: Dim, C: Dim, S: ContiguousStorageMut> Into<&'a mut [N]> + for &'a mut Matrix +{ #[inline] fn into(self) -> &'a mut [N] { self.as_mut_slice() } } - impl<'a, N: Scalar + Copy> From<&'a [N]> for DVectorSlice<'a, N> { #[inline] fn from(slice: &'a [N]) -> Self { @@ -553,4 +575,4 @@ impl<'a, N: Scalar + Copy> From<&'a mut [N]> for DVectorSliceMut<'a, N> { fn from(slice: &'a mut [N]) -> Self { Self::from_slice(slice, slice.len()) } -} \ No newline at end of file +} diff --git a/src/base/dimension.rs b/src/base/dimension.rs index 112996d3..e7150e65 100644 --- a/src/base/dimension.rs +++ b/src/base/dimension.rs @@ -190,7 +190,6 @@ pub trait DimName: Dim { type Value: NamedDim; /// The name of this dimension, i.e., the singleton `Self`. - #[inline] fn name() -> Self; // FIXME: this is not a very idiomatic name. diff --git a/src/base/matrix.rs b/src/base/matrix.rs index 9cd28e7b..beb3accf 100644 --- a/src/base/matrix.rs +++ b/src/base/matrix.rs @@ -16,8 +16,8 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; #[cfg(feature = "abomonation-serialize")] use abomonation::Abomonation; -use alga::general::{ClosedAdd, ClosedMul, ClosedSub, Field, RealField, Ring}; -use alga::simd::SimdPartialOrd; +use simba::scalar::{ClosedAdd, ClosedMul, ClosedSub, Field, RealField}; +use simba::simd::SimdPartialOrd; use crate::base::allocator::{Allocator, SameShapeAllocator, SameShapeC, SameShapeR}; use crate::base::constraint::{DimEq, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint}; @@ -29,7 +29,7 @@ use crate::base::storage::{ ContiguousStorage, ContiguousStorageMut, Owned, SameShapeStorage, Storage, StorageMut, }; use crate::base::{DefaultAllocator, MatrixMN, MatrixN, Scalar, Unit, VectorN}; -use crate::{SimdComplexField, SimdRealField}; +use crate::SimdComplexField; /// A square matrix. pub type SquareMatrix = Matrix; @@ -1130,7 +1130,7 @@ impl> SquareMatrix { /// Computes a trace of a square matrix, i.e., the sum of its diagonal elements. #[inline] pub fn trace(&self) -> N - where N: Ring { + where N: Scalar + Zero + ClosedAdd { assert!( self.is_square(), "Cannot compute the trace of non-square matrix." @@ -1517,7 +1517,9 @@ fn lower_exp() { ) } -impl> Matrix { +impl> + Matrix +{ /// The perpendicular product between two 2D column vectors, i.e. `a.x * b.y - a.y * b.x`. #[inline] pub fn perp(&self, b: &Matrix) -> N diff --git a/src/base/matrix_alga.rs b/src/base/matrix_alga.rs deleted file mode 100644 index 76a9d7ce..00000000 --- a/src/base/matrix_alga.rs +++ /dev/null @@ -1,424 +0,0 @@ -#[cfg(all(feature = "alloc", not(feature = "std")))] -use alloc::vec::Vec; - -use num::{One, Zero}; - -use alga::general::{ - AbstractGroup, AbstractGroupAbelian, AbstractLoop, AbstractMagma, AbstractModule, - AbstractMonoid, AbstractQuasigroup, AbstractSemigroup, Additive, ClosedAdd, ClosedMul, - ClosedNeg, Field, Identity, TwoSidedInverse, JoinSemilattice, Lattice, MeetSemilattice, Module, - Multiplicative, RingCommutative, ComplexField -}; -use alga::linear::{ - FiniteDimInnerSpace, FiniteDimVectorSpace, InnerSpace, NormedSpace, VectorSpace, -}; - -use crate::base::allocator::Allocator; -use crate::base::dimension::{Dim, DimName}; -use crate::base::storage::{Storage, StorageMut}; -use crate::base::{DefaultAllocator, MatrixMN, MatrixN, Scalar}; - -/* - * - * Additive structures. - * - */ -impl Identity for MatrixMN -where - N: Scalar + Zero, - DefaultAllocator: Allocator, -{ - #[inline] - fn identity() -> Self { - Self::from_element(N::zero()) - } -} - -impl AbstractMagma for MatrixMN -where - N: Scalar + ClosedAdd, - DefaultAllocator: Allocator, -{ - #[inline] - fn operate(&self, other: &Self) -> Self { - self + other - } -} - -impl TwoSidedInverse for MatrixMN -where - N: Scalar + ClosedNeg, - DefaultAllocator: Allocator, -{ - #[inline] - #[must_use = "Did you mean to use two_sided_inverse_mut()?"] - fn two_sided_inverse(&self) -> Self { - -self - } - - #[inline] - fn two_sided_inverse_mut(&mut self) { - *self = -self.clone() - } -} - -macro_rules! inherit_additive_structure( - ($($marker: ident<$operator: ident> $(+ $bounds: ident)*),* $(,)*) => {$( - impl $marker<$operator> for MatrixMN - where N: Scalar + $marker<$operator> $(+ $bounds)*, - DefaultAllocator: Allocator { } - )*} -); - -inherit_additive_structure!( - AbstractSemigroup + ClosedAdd, - AbstractMonoid + Zero + ClosedAdd, - AbstractQuasigroup + ClosedAdd + ClosedNeg, - AbstractLoop + Zero + ClosedAdd + ClosedNeg, - AbstractGroup + Zero + ClosedAdd + ClosedNeg, - AbstractGroupAbelian + Zero + ClosedAdd + ClosedNeg -); - -impl AbstractModule for MatrixMN -where - N: Scalar + RingCommutative, - DefaultAllocator: Allocator, -{ - type AbstractRing = N; - - #[inline] - fn multiply_by(&self, n: N) -> Self { - self * n - } -} - -impl Module for MatrixMN -where - N: Scalar + RingCommutative, - DefaultAllocator: Allocator, -{ - type Ring = N; -} - -impl VectorSpace for MatrixMN -where - N: Scalar + Field, - DefaultAllocator: Allocator, -{ - type Field = N; -} - -impl FiniteDimVectorSpace for MatrixMN -where - N: Scalar + Field, - DefaultAllocator: Allocator, -{ - #[inline] - fn dimension() -> usize { - R::dim() * C::dim() - } - - #[inline] - fn canonical_basis_element(i: usize) -> Self { - assert!(i < Self::dimension(), "Index out of bound."); - - let mut res = Self::zero(); - unsafe { - *res.data.get_unchecked_linear_mut(i) = N::one(); - } - - res - } - - #[inline] - fn dot(&self, other: &Self) -> N { - self.dot(other) - } - - #[inline] - unsafe fn component_unchecked(&self, i: usize) -> &N { - self.data.get_unchecked_linear(i) - } - - #[inline] - unsafe fn component_unchecked_mut(&mut self, i: usize) -> &mut N { - self.data.get_unchecked_linear_mut(i) - } -} - -impl NormedSpace for MatrixMN -where DefaultAllocator: Allocator -{ - type RealField = N::RealField; - type ComplexField = N; - - #[inline] - fn norm_squared(&self) -> N::RealField { - self.norm_squared() - } - - #[inline] - fn norm(&self) -> N::RealField { - self.norm() - } - - #[inline] - #[must_use = "Did you mean to use normalize_mut()?"] - fn normalize(&self) -> Self { - self.normalize() - } - - #[inline] - fn normalize_mut(&mut self) -> N::RealField { - self.normalize_mut() - } - - #[inline] - #[must_use = "Did you mean to use try_normalize_mut()?"] - fn try_normalize(&self, min_norm: N::RealField) -> Option { - self.try_normalize(min_norm) - } - - #[inline] - fn try_normalize_mut(&mut self, min_norm: N::RealField) -> Option { - self.try_normalize_mut(min_norm) - } -} - -impl InnerSpace for MatrixMN -where DefaultAllocator: Allocator -{ - #[inline] - fn angle(&self, other: &Self) -> N::RealField { - self.angle(other) - } - - #[inline] - fn inner_product(&self, other: &Self) -> N { - self.dotc(other) - } -} - -// FIXME: specialization will greatly simplify this implementation in the future. -// In particular: -// − use `x()` instead of `::canonical_basis_element` -// − use `::new(x, y, z)` instead of `::from_slice` -impl FiniteDimInnerSpace for MatrixMN -where DefaultAllocator: Allocator -{ - #[inline] - fn orthonormalize(vs: &mut [Self]) -> usize { - let mut nbasis_elements = 0; - - for i in 0..vs.len() { - { - let (elt, basis) = vs[..i + 1].split_last_mut().unwrap(); - - for basis_element in &basis[..nbasis_elements] { - *elt -= &*basis_element * elt.dot(basis_element) - } - } - - if vs[i].try_normalize_mut(N::RealField::zero()).is_some() { - // FIXME: this will be efficient on dynamically-allocated vectors but for - // statically-allocated ones, `.clone_from` would be better. - vs.swap(nbasis_elements, i); - nbasis_elements += 1; - - // All the other vectors will be dependent. - if nbasis_elements == Self::dimension() { - break; - } - } - } - - nbasis_elements - } - - #[inline] - fn orthonormal_subspace_basis(vs: &[Self], mut f: F) - where F: FnMut(&Self) -> bool { - // FIXME: is this necessary? - assert!( - vs.len() <= Self::dimension(), - "The given set of vectors has no chance of being a free family." - ); - - match Self::dimension() { - 1 => { - if vs.len() == 0 { - let _ = f(&Self::canonical_basis_element(0)); - } - } - 2 => { - if vs.len() == 0 { - let _ = f(&Self::canonical_basis_element(0)) - && f(&Self::canonical_basis_element(1)); - } else if vs.len() == 1 { - let v = &vs[0]; - let res = Self::from_column_slice(&[-v[1], v[0]]); - - let _ = f(&res.normalize()); - } - - // Otherwise, nothing. - } - 3 => { - if vs.len() == 0 { - let _ = f(&Self::canonical_basis_element(0)) - && f(&Self::canonical_basis_element(1)) - && f(&Self::canonical_basis_element(2)); - } else if vs.len() == 1 { - let v = &vs[0]; - let mut a; - - if v[0].norm1() > v[1].norm1() { - a = Self::from_column_slice(&[v[2], N::zero(), -v[0]]); - } else { - a = Self::from_column_slice(&[N::zero(), -v[2], v[1]]); - }; - - let _ = a.normalize_mut(); - - if f(&a.cross(v)) { - let _ = f(&a); - } - } else if vs.len() == 2 { - let _ = f(&vs[0].cross(&vs[1]).normalize()); - } - } - _ => { - #[cfg(any(feature = "std", feature = "alloc"))] - { - // XXX: use a GenericArray instead. - let mut known_basis = Vec::new(); - - for v in vs.iter() { - known_basis.push(v.normalize()) - } - - for i in 0..Self::dimension() - vs.len() { - let mut elt = Self::canonical_basis_element(i); - - for v in &known_basis { - elt -= v * elt.dot(v) - } - - if let Some(subsp_elt) = elt.try_normalize(N::RealField::zero()) { - if !f(&subsp_elt) { - return; - }; - - known_basis.push(subsp_elt); - } - } - } - #[cfg(all(not(feature = "std"), not(feature = "alloc")))] - { - panic!("Cannot compute the orthogonal subspace basis of a vector with a dimension greater than 3 \ - if #![no_std] is enabled and the 'alloc' feature is not enabled.") - } - } - } - } -} - -/* - * - * - * Multiplicative structures. - * - * - */ -impl Identity for MatrixN -where - N: Scalar + Zero + One, - DefaultAllocator: Allocator, -{ - #[inline] - fn identity() -> Self { - Self::identity() - } -} - -impl AbstractMagma for MatrixN -where - N: Scalar + Zero + One + ClosedAdd + ClosedMul, - DefaultAllocator: Allocator, -{ - #[inline] - fn operate(&self, other: &Self) -> Self { - self * other - } -} - -macro_rules! impl_multiplicative_structure( - ($($marker: ident<$operator: ident> $(+ $bounds: ident)*),* $(,)*) => {$( - impl $marker<$operator> for MatrixN - where N: Scalar + Zero + One + ClosedAdd + ClosedMul + $marker<$operator> $(+ $bounds)*, - DefaultAllocator: Allocator { } - )*} -); - -impl_multiplicative_structure!( - AbstractSemigroup, - AbstractMonoid + One -); - -/* - * - * Ordering - * - */ -impl MeetSemilattice for MatrixMN -where - N: Scalar + MeetSemilattice, - DefaultAllocator: Allocator, -{ - #[inline] - fn meet(&self, other: &Self) -> Self { - self.zip_map(other, |a, b| a.meet(&b)) - } -} - -impl JoinSemilattice for MatrixMN -where - N: Scalar + JoinSemilattice, - DefaultAllocator: Allocator, -{ - #[inline] - fn join(&self, other: &Self) -> Self { - self.zip_map(other, |a, b| a.join(&b)) - } -} - -impl Lattice for MatrixMN -where - N: Scalar + Lattice, - DefaultAllocator: Allocator, -{ - #[inline] - fn meet_join(&self, other: &Self) -> (Self, Self) { - let shape = self.data.shape(); - assert!( - shape == other.data.shape(), - "Matrix meet/join error: mismatched dimensions." - ); - - let mut mres = unsafe { Self::new_uninitialized_generic(shape.0, shape.1) }; - let mut jres = unsafe { Self::new_uninitialized_generic(shape.0, shape.1) }; - - for i in 0..shape.0.value() * shape.1.value() { - unsafe { - let mj = self - .data - .get_unchecked_linear(i) - .meet_join(other.data.get_unchecked_linear(i)); - *mres.data.get_unchecked_linear_mut(i) = mj.0; - *jres.data.get_unchecked_linear_mut(i) = mj.1; - } - } - - (mres, jres) - } -} diff --git a/src/base/matrix_simba.rs b/src/base/matrix_simba.rs new file mode 100644 index 00000000..a23ff3fb --- /dev/null +++ b/src/base/matrix_simba.rs @@ -0,0 +1,65 @@ +#[cfg(all(feature = "alloc", not(feature = "std")))] +use alloc::vec::Vec; + +use simba::simd::SimdValue; + +use crate::base::allocator::Allocator; +use crate::base::dimension::Dim; +use crate::base::{DefaultAllocator, MatrixMN, Scalar}; + +/* + * + * Simd structures. + * + */ +impl SimdValue for MatrixMN +where + N: Scalar + SimdValue, + R: Dim, + C: Dim, + N::Element: Scalar, + DefaultAllocator: Allocator + Allocator, +{ + type Element = MatrixMN; + type SimdBool = N::SimdBool; + + #[inline] + fn lanes() -> usize { + N::lanes() + } + + #[inline] + fn splat(val: Self::Element) -> Self { + val.map(N::splat) + } + + #[inline] + fn extract(&self, i: usize) -> Self::Element { + self.map(|e| e.extract(i)) + } + + #[inline] + unsafe fn extract_unchecked(&self, i: usize) -> Self::Element { + self.map(|e| e.extract_unchecked(i)) + } + + #[inline] + fn replace(&mut self, i: usize, val: Self::Element) { + self.zip_apply(&val, |mut a, b| { + a.replace(i, b); + a + }) + } + + #[inline] + unsafe fn replace_unchecked(&mut self, i: usize, val: Self::Element) { + self.zip_apply(&val, |mut a, b| { + a.replace_unchecked(i, b); + a + }) + } + + fn select(self, cond: Self::SimdBool, other: Self) -> Self { + self.zip_map(&other, |a, b| a.select(cond, b)) + } +} diff --git a/src/base/mod.rs b/src/base/mod.rs index 0ec6311c..0f380523 100644 --- a/src/base/mod.rs +++ b/src/base/mod.rs @@ -12,6 +12,7 @@ pub mod storage; mod alias; mod alias_slice; +mod array_storage; mod cg; mod componentwise; mod construction; @@ -20,25 +21,24 @@ mod conversion; mod edition; pub mod indexing; mod matrix; -mod matrix_alga; -mod array_storage; +mod matrix_simba; mod matrix_slice; -#[cfg(any(feature = "std", feature = "alloc"))] -mod vec_storage; +mod norm; mod properties; mod scalar; +mod statistics; mod swizzle; mod unit; -mod statistics; -mod norm; +#[cfg(any(feature = "std", feature = "alloc"))] +mod vec_storage; #[doc(hidden)] pub mod helper; pub use self::matrix::*; +pub use self::norm::*; pub use self::scalar::*; pub use self::unit::*; -pub use self::norm::*; pub use self::default_allocator::*; pub use self::dimension::*; diff --git a/src/base/norm.rs b/src/base/norm.rs index 9f38c1d7..a1f5dcad 100644 --- a/src/base/norm.rs +++ b/src/base/norm.rs @@ -1,11 +1,13 @@ use num::Zero; +use std::ops::Neg; use crate::allocator::Allocator; -use crate::base::{DefaultAllocator, Dim, Matrix, MatrixMN}; +use crate::base::{DefaultAllocator, Dim, Matrix, MatrixMN, Normed}; use crate::constraint::{SameNumberOfColumns, SameNumberOfRows, ShapeConstraint}; use crate::storage::{Storage, StorageMut}; -use crate::{ComplexField, RealField, SimdComplexField, SimdRealField}; -use alga::simd::SimdPartialOrd; +use crate::{ComplexField, Scalar, SimdComplexField, Unit}; +use simba::scalar::ClosedNeg; +use simba::simd::{SimdOption, SimdPartialOrd}; // FIXME: this should be be a trait on alga? /// A trait for abstract matrix norms. @@ -272,6 +274,19 @@ impl> Matrix N::SimdRealField { self.apply_norm(&LpNorm(p)) } + + #[inline] + #[must_use = "Did you mean to use simd_try_normalize_mut()?"] + pub fn simd_try_normalize(&self, min_norm: N::SimdRealField) -> SimdOption> + where + N::Element: Scalar, + DefaultAllocator: Allocator + Allocator, + { + let n = self.norm(); + let le = n.simd_le(min_norm); + let val = self.unscale(n); + SimdOption::new(val, le) + } } impl> Matrix { @@ -313,6 +328,22 @@ impl> Matrix SimdOption + where + N::Element: Scalar, + DefaultAllocator: Allocator + Allocator, + { + let n = self.norm(); + let le = n.simd_le(min_norm); + self.apply(|e| e.simd_unscale(n).select(le, e)); + SimdOption::new(n, le) + } } impl> Matrix { @@ -320,8 +351,7 @@ impl> Matrix /// /// If the normalization succeeded, returns the old norm of this matrix. #[inline] - pub fn try_normalize_mut(&mut self, min_norm: N::RealField) -> Option - where N: ComplexField { + pub fn try_normalize_mut(&mut self, min_norm: N::RealField) -> Option { let n = self.norm(); if n <= min_norm { @@ -332,3 +362,40 @@ impl> Matrix } } } + +impl Normed for MatrixMN +where DefaultAllocator: Allocator +{ + type Norm = N::SimdRealField; + + #[inline] + fn norm(&self) -> N::SimdRealField { + self.norm() + } + + #[inline] + fn norm_squared(&self) -> N::SimdRealField { + self.norm_squared() + } + + #[inline] + fn scale_mut(&mut self, n: Self::Norm) { + self.scale_mut(n) + } + + #[inline] + fn unscale_mut(&mut self, n: Self::Norm) { + self.unscale_mut(n) + } +} + +impl Neg for Unit> +where DefaultAllocator: Allocator +{ + type Output = Unit>; + + #[inline] + fn neg(self) -> Self::Output { + Unit::new_unchecked(-self.value) + } +} diff --git a/src/base/ops.rs b/src/base/ops.rs index e0cd450c..de44104e 100644 --- a/src/base/ops.rs +++ b/src/base/ops.rs @@ -1,12 +1,11 @@ -use num::{One, Signed, Zero}; -use std::cmp::{Ordering, PartialOrd}; +use num::{One, Zero}; use std::iter; use std::ops::{ Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign, }; -use alga::general::{ClosedAdd, ClosedDiv, ClosedMul, ClosedNeg, ClosedSub}; -use alga::simd::{SimdPartialOrd, SimdSigned}; +use simba::scalar::{ClosedAdd, ClosedDiv, ClosedMul, ClosedNeg, ClosedSub}; +use simba::simd::{SimdPartialOrd, SimdSigned}; use crate::base::allocator::{Allocator, SameShapeAllocator, SameShapeC, SameShapeR}; use crate::base::constraint::{ diff --git a/src/base/properties.rs b/src/base/properties.rs index 8ca49568..9407a578 100644 --- a/src/base/properties.rs +++ b/src/base/properties.rs @@ -2,7 +2,7 @@ use approx::RelativeEq; use num::{One, Zero}; -use alga::general::{ClosedAdd, ClosedMul, RealField, ComplexField}; +use simba::scalar::{ClosedAdd, ClosedMul, ComplexField, RealField}; use crate::base::allocator::Allocator; use crate::base::dimension::{Dim, DimMin}; @@ -91,11 +91,11 @@ impl> Matrix { /// equal to `eps`. #[inline] pub fn is_orthogonal(&self, eps: N::Epsilon) -> bool - where - N: Zero + One + ClosedAdd + ClosedMul + RelativeEq, - S: Storage, - N::Epsilon: Copy, - DefaultAllocator: Allocator + Allocator, + where + N: Zero + One + ClosedAdd + ClosedMul + RelativeEq, + S: Storage, + N::Epsilon: Copy, + DefaultAllocator: Allocator + Allocator, { (self.ad_mul(self)).is_identity(eps) } diff --git a/src/base/statistics.rs b/src/base/statistics.rs index 14b47474..16b9cc95 100644 --- a/src/base/statistics.rs +++ b/src/base/statistics.rs @@ -1,21 +1,28 @@ -use crate::{Scalar, Dim, Matrix, VectorN, RowVectorN, DefaultAllocator, U1, VectorSliceN}; -use alga::general::{AdditiveMonoid, Field, SupersetOf}; -use crate::storage::Storage; use crate::allocator::Allocator; +use crate::storage::Storage; +use crate::{DefaultAllocator, Dim, Matrix, RowVectorN, Scalar, VectorN, VectorSliceN, U1}; +use num::Zero; +use simba::scalar::{ClosedAdd, Field, SupersetOf}; 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] - pub fn compress_rows(&self, f: impl Fn(VectorSliceN) -> N) -> RowVectorN - where DefaultAllocator: Allocator { - + pub fn compress_rows( + &self, + f: impl Fn(VectorSliceN) -> N, + ) -> RowVectorN + where + DefaultAllocator: Allocator, + { let ncols = self.data.shape().1; let mut res = unsafe { RowVectorN::new_uninitialized_generic(U1, ncols) }; for i in 0..ncols.value() { // FIXME: avoid bound checking of column. - unsafe { *res.get_unchecked_mut((0, i)) = f(self.column(i)); } + unsafe { + *res.get_unchecked_mut((0, i)) = f(self.column(i)); + } } res @@ -26,15 +33,21 @@ impl> Matrix { /// /// This is the same as `self.compress_rows(f).transpose()`. #[inline] - pub fn compress_rows_tr(&self, f: impl Fn(VectorSliceN) -> N) -> VectorN - where DefaultAllocator: Allocator { - + pub fn compress_rows_tr( + &self, + f: impl Fn(VectorSliceN) -> N, + ) -> VectorN + where + DefaultAllocator: Allocator, + { let ncols = self.data.shape().1; let mut res = unsafe { VectorN::new_uninitialized_generic(ncols, U1) }; for i in 0..ncols.value() { // FIXME: avoid bound checking of column. - unsafe { *res.vget_unchecked_mut(i) = f(self.column(i)); } + unsafe { + *res.vget_unchecked_mut(i) = f(self.column(i)); + } } res @@ -42,8 +55,14 @@ impl> Matrix { /// Returns a column vector resulting from the folding of `f` on each column of this matrix. #[inline] - pub fn compress_columns(&self, init: VectorN, f: impl Fn(&mut VectorN, VectorSliceN)) -> VectorN - where DefaultAllocator: Allocator { + pub fn compress_columns( + &self, + init: VectorN, + f: impl Fn(&mut VectorN, VectorSliceN), + ) -> VectorN + where + DefaultAllocator: Allocator, + { let mut res = init; for i in 0..self.ncols() { @@ -54,7 +73,7 @@ impl> Matrix { } } -impl> Matrix { +impl> Matrix { /* * * Sum computation. @@ -95,7 +114,7 @@ impl> Matrix RowVectorN - where DefaultAllocator: Allocator { + where DefaultAllocator: Allocator { self.compress_rows(|col| col.sum()) } @@ -116,7 +135,7 @@ impl> Matrix VectorN - where DefaultAllocator: Allocator { + where DefaultAllocator: Allocator { self.compress_rows_tr(|col| col.sum()) } @@ -137,7 +156,7 @@ impl> Matrix VectorN - where DefaultAllocator: Allocator { + where DefaultAllocator: Allocator { let nrows = self.data.shape().0; self.compress_columns(VectorN::zeros_generic(nrows, U1), |out, col| { *out += col; @@ -168,7 +187,9 @@ impl, R: Dim, C: Dim, S: Storage> M if self.len() == 0 { N::zero() } else { - let val = self.iter().cloned().fold((N::zero(), N::zero()), |a, b| (a.0 + b.inlined_clone() * b.inlined_clone(), a.1 + b)); + let val = self.iter().cloned().fold((N::zero(), N::zero()), |a, b| { + (a.0 + b.inlined_clone() * b.inlined_clone(), a.1 + b) + }); let denom = N::one() / crate::convert::<_, N>(self.len() as f64); let vd = val.1 * denom.inlined_clone(); val.0 * denom - vd.inlined_clone() * vd @@ -189,7 +210,7 @@ impl, R: Dim, C: Dim, S: Storage> M /// ``` #[inline] pub fn row_variance(&self) -> RowVectorN - where DefaultAllocator: Allocator { + where DefaultAllocator: Allocator { self.compress_rows(|col| col.variance()) } @@ -206,7 +227,7 @@ impl, R: Dim, C: Dim, S: Storage> M /// ``` #[inline] pub fn row_variance_tr(&self) -> VectorN - where DefaultAllocator: Allocator { + where DefaultAllocator: Allocator { self.compress_rows_tr(|col| col.variance()) } @@ -224,7 +245,7 @@ impl, R: Dim, C: Dim, S: Storage> M /// ``` #[inline] pub fn column_variance(&self) -> VectorN - where DefaultAllocator: Allocator { + where DefaultAllocator: Allocator { let (nrows, ncols) = self.data.shape(); let mut mean = self.column_mean(); @@ -235,7 +256,8 @@ impl, R: Dim, C: Dim, S: Storage> M for i in 0..nrows.value() { unsafe { let val = col.vget_unchecked(i); - *out.vget_unchecked_mut(i) += denom.inlined_clone() * val.inlined_clone() * val.inlined_clone() + *out.vget_unchecked_mut(i) += + denom.inlined_clone() * val.inlined_clone() * val.inlined_clone() } } }) @@ -281,7 +303,7 @@ impl, R: Dim, C: Dim, S: Storage> M /// ``` #[inline] pub fn row_mean(&self) -> RowVectorN - where DefaultAllocator: Allocator { + where DefaultAllocator: Allocator { self.compress_rows(|col| col.mean()) } @@ -298,7 +320,7 @@ impl, R: Dim, C: Dim, S: Storage> M /// ``` #[inline] pub fn row_mean_tr(&self) -> VectorN - where DefaultAllocator: Allocator { + where DefaultAllocator: Allocator { self.compress_rows_tr(|col| col.mean()) } @@ -315,7 +337,7 @@ impl, R: Dim, C: Dim, S: Storage> M /// ``` #[inline] pub fn column_mean(&self) -> VectorN - where DefaultAllocator: Allocator { + where DefaultAllocator: Allocator { let (nrows, ncols) = self.data.shape(); let denom = N::one() / crate::convert::<_, N>(ncols.value() as f64); self.compress_columns(VectorN::zeros_generic(nrows, U1), |out, col| { diff --git a/src/base/storage.rs b/src/base/storage.rs index e7439552..8e472e1e 100644 --- a/src/base/storage.rs +++ b/src/base/storage.rs @@ -94,13 +94,11 @@ pub unsafe trait Storage: Debug + Sized { } /// Indicates whether this data buffer stores its elements contiguously. - #[inline] 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. - #[inline] fn as_slice(&self) -> &[N]; /// Builds a matrix data storage that does not contain any reference. @@ -166,7 +164,6 @@ pub unsafe trait StorageMut: Storage { /// Retrieves the mutable data buffer as a contiguous slice. /// /// Matrix components may not be contiguous, depending on its strides. - #[inline] fn as_mut_slice(&mut self) -> &mut [N]; } diff --git a/src/base/unit.rs b/src/base/unit.rs index 6fe831da..6f5ce999 100644 --- a/src/base/unit.rs +++ b/src/base/unit.rs @@ -1,8 +1,7 @@ -use approx::RelativeEq; #[cfg(feature = "abomonation-serialize")] use std::io::{Result as IOResult, Write}; use std::mem; -use std::ops::{Deref, Neg}; +use std::ops::Deref; #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Deserializer, Serialize, Serializer}; @@ -10,8 +9,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; #[cfg(feature = "abomonation-serialize")] use abomonation::Abomonation; -use alga::general::{SubsetOf, ComplexField}; -use alga::linear::NormedSpace; +use crate::{RealField, SimdComplexField, SimdRealField}; /// A wrapper that ensures the underlying algebraic entity has a unit norm. /// @@ -19,7 +17,7 @@ use alga::linear::NormedSpace; #[repr(transparent)] #[derive(Eq, PartialEq, Clone, Hash, Debug, Copy)] pub struct Unit { - value: T, + pub(crate) value: T, } #[cfg(feature = "serde-serialize")] @@ -53,60 +51,76 @@ impl Abomonation for Unit { } } -impl Unit { - /// Normalize the given value and return it wrapped on a `Unit` structure. +pub trait Normed { + type Norm: SimdRealField; + fn norm(&self) -> Self::Norm; + fn norm_squared(&self) -> Self::Norm; + fn scale_mut(&mut self, n: Self::Norm); + fn unscale_mut(&mut self, n: Self::Norm); +} + +impl Unit { + /// Normalize the given vector and return it wrapped on a `Unit` structure. #[inline] pub fn new_normalize(value: T) -> Self { Self::new_and_get(value).0 } - /// Attempts to normalize the given value and return it wrapped on a `Unit` structure. + /// Attempts to normalize the given vector and return it wrapped on a `Unit` structure. /// /// Returns `None` if the norm was smaller or equal to `min_norm`. #[inline] - pub fn try_new(value: T, min_norm: T::RealField) -> Option { + pub fn try_new(value: T, min_norm: T::Norm) -> Option + where T::Norm: RealField { Self::try_new_and_get(value, min_norm).map(|res| res.0) } - /// Normalize the given value and return it wrapped on a `Unit` structure and its norm. + /// Normalize the given vector and return it wrapped on a `Unit` structure and its norm. #[inline] - pub fn new_and_get(mut value: T) -> (Self, T::RealField) { - let n = value.normalize_mut(); - - (Unit { value: value }, n) + pub fn new_and_get(mut value: T) -> (Self, T::Norm) { + let n = value.norm(); + value.unscale_mut(n); + (Unit { value }, n) } - /// Normalize the given value and return it wrapped on a `Unit` structure and its norm. + /// Normalize the given vector and return it wrapped on a `Unit` structure and its norm. /// /// Returns `None` if the norm was smaller or equal to `min_norm`. #[inline] - pub fn try_new_and_get(mut value: T, min_norm: T::RealField) -> Option<(Self, T::RealField)> { - if let Some(n) = value.try_normalize_mut(min_norm) { - Some((Unit { value: value }, n)) + pub fn try_new_and_get(mut value: T, min_norm: T::Norm) -> Option<(Self, T::Norm)> + where T::Norm: RealField { + let sq_norm = value.norm_squared(); + + if sq_norm > min_norm * min_norm { + let n = sq_norm.simd_sqrt(); + value.unscale_mut(n); + Some((Unit { value }, n)) } else { None } } - /// Normalizes this value again. This is useful when repeated computations + /// Normalizes this vector again. This is useful when repeated computations /// might cause a drift in the norm because of float inaccuracies. /// /// Returns the norm before re-normalization. See `.renormalize_fast` for a faster alternative /// that may be slightly less accurate if `self` drifted significantly from having a unit length. #[inline] - pub fn renormalize(&mut self) -> T::RealField { - self.value.normalize_mut() + pub fn renormalize(&mut self) -> T::Norm { + let n = self.norm(); + self.value.unscale_mut(n); + n } - /// Normalizes this value again using a first-order Taylor approximation. + /// Normalizes this vector again using a first-order Taylor approximation. /// This is useful when repeated computations might cause a drift in the norm /// because of float inaccuracies. #[inline] pub fn renormalize_fast(&mut self) { let sq_norm = self.value.norm_squared(); - let _3: T::RealField = crate::convert(3.0); - let _0_5: T::RealField = crate::convert(0.5); - self.value *= T::ComplexField::from_real(_0_5 * (_3 - sq_norm)); + let _3: T::Norm = crate::convert(3.0); + let _0_5: T::Norm = crate::convert(0.5); + self.value.scale_mut(_0_5 * (_3 - sq_norm)); } } @@ -114,7 +128,7 @@ impl Unit { /// Wraps the given value, assuming it is already normalized. #[inline] pub fn new_unchecked(value: T) -> Self { - Unit { value: value } + Unit { value } } /// Wraps the given reference, assuming it is already normalized. @@ -131,7 +145,7 @@ impl Unit { /// Retrieves the underlying value. /// Deprecated: use [Unit::into_inner] instead. - #[deprecated(note="use `.into_inner()` instead")] + #[deprecated(note = "use `.into_inner()` instead")] #[inline] pub fn unwrap(self) -> T { self.value @@ -153,13 +167,14 @@ impl AsRef for Unit { } } +/* /* * * Conversions. * */ impl SubsetOf for Unit -where T::Field: RelativeEq +where T::RealField: RelativeEq { #[inline] fn to_superset(&self) -> T { @@ -172,7 +187,7 @@ where T::Field: RelativeEq } #[inline] - unsafe fn from_superset_unchecked(value: &T) -> Self { + fn from_superset_unchecked(value: &T) -> Self { Unit::new_normalize(value.clone()) // We still need to re-normalize because the condition is inexact. } } @@ -205,7 +220,7 @@ where T::Field: RelativeEq // self.value.ulps_eq(&other.value, epsilon, max_ulps) // } // } - +*/ // FIXME:re-enable this impl when specialization is possible. // Currently, it is disabled so that we can have a nice output for the `UnitQuaternion` display. /* @@ -217,15 +232,6 @@ impl fmt::Display for Unit { } */ -impl Neg for Unit { - type Output = Unit; - - #[inline] - fn neg(self) -> Self::Output { - Self::Output::new_unchecked(-self.value) - } -} - impl Deref for Unit { type Target = T; diff --git a/src/debug/random_orthogonal.rs b/src/debug/random_orthogonal.rs index 421b041a..cab2deb0 100644 --- a/src/debug/random_orthogonal.rs +++ b/src/debug/random_orthogonal.rs @@ -3,12 +3,12 @@ use crate::base::storage::Owned; #[cfg(feature = "arbitrary")] use quickcheck::{Arbitrary, Gen}; -use alga::general::ComplexField; -use crate::base::Scalar; use crate::base::allocator::Allocator; use crate::base::dimension::{Dim, Dynamic, U2}; +use crate::base::Scalar; use crate::base::{DefaultAllocator, MatrixN}; use crate::linalg::givens::GivensRotation; +use simba::scalar::ComplexField; /// A random orthogonal matrix. #[derive(Clone, Debug)] diff --git a/src/debug/random_sdp.rs b/src/debug/random_sdp.rs index 47e3ca60..d016713a 100644 --- a/src/debug/random_sdp.rs +++ b/src/debug/random_sdp.rs @@ -3,11 +3,11 @@ use crate::base::storage::Owned; #[cfg(feature = "arbitrary")] use quickcheck::{Arbitrary, Gen}; -use alga::general::ComplexField; -use crate::base::Scalar; use crate::base::allocator::Allocator; use crate::base::dimension::{Dim, Dynamic}; +use crate::base::Scalar; use crate::base::{DefaultAllocator, MatrixN}; +use simba::scalar::ComplexField; use crate::debug::RandomOrthogonal; diff --git a/src/geometry/abstract_rotation.rs b/src/geometry/abstract_rotation.rs new file mode 100644 index 00000000..5563b6a7 --- /dev/null +++ b/src/geometry/abstract_rotation.rs @@ -0,0 +1,136 @@ +use crate::allocator::Allocator; +use crate::geometry::{Rotation, UnitComplex, UnitQuaternion}; +use crate::{DefaultAllocator, DimName, Point, RealField, Scalar, VectorN, U2, U3}; + +use simba::scalar::ClosedMul; + +pub trait AbstractRotation: PartialEq + ClosedMul + Clone { + fn identity() -> Self; + fn inverse(&self) -> Self; + fn inverse_mut(&mut self); + fn transform_vector(&self, v: &VectorN) -> VectorN + where DefaultAllocator: Allocator; + fn transform_point(&self, p: &Point) -> Point + where DefaultAllocator: Allocator; + fn inverse_transform_vector(&self, v: &VectorN) -> VectorN + where DefaultAllocator: Allocator; + fn inverse_transform_point(&self, p: &Point) -> Point + where DefaultAllocator: Allocator; +} + +impl AbstractRotation for Rotation +where DefaultAllocator: Allocator +{ + #[inline] + fn identity() -> Self { + Self::identity() + } + + #[inline] + fn inverse(&self) -> Self { + self.inverse() + } + + #[inline] + fn inverse_mut(&mut self) { + self.inverse_mut() + } + + #[inline] + fn transform_vector(&self, v: &VectorN) -> VectorN + where DefaultAllocator: Allocator { + self * v + } + + #[inline] + fn transform_point(&self, p: &Point) -> Point + where DefaultAllocator: Allocator { + self * p + } + + #[inline] + fn inverse_transform_vector(&self, v: &VectorN) -> VectorN + where DefaultAllocator: Allocator { + self.inverse_transform_vector(v) + } + + #[inline] + fn inverse_transform_point(&self, p: &Point) -> Point + where DefaultAllocator: Allocator { + self.inverse_transform_point(p) + } +} + +impl AbstractRotation for UnitQuaternion { + #[inline] + fn identity() -> Self { + Self::identity() + } + + #[inline] + fn inverse(&self) -> Self { + self.inverse() + } + + #[inline] + fn inverse_mut(&mut self) { + self.inverse_mut() + } + + #[inline] + fn transform_vector(&self, v: &VectorN) -> VectorN { + self * v + } + + #[inline] + fn transform_point(&self, p: &Point) -> Point { + self * p + } + + #[inline] + fn inverse_transform_vector(&self, v: &VectorN) -> VectorN { + self.inverse_transform_vector(v) + } + + #[inline] + fn inverse_transform_point(&self, p: &Point) -> Point { + self.inverse_transform_point(p) + } +} + +impl AbstractRotation for UnitComplex { + #[inline] + fn identity() -> Self { + Self::identity() + } + + #[inline] + fn inverse(&self) -> Self { + self.inverse() + } + + #[inline] + fn inverse_mut(&mut self) { + self.inverse_mut() + } + + #[inline] + fn transform_vector(&self, v: &VectorN) -> VectorN { + self * v + } + + #[inline] + fn transform_point(&self, p: &Point) -> Point { + self * p + } + + #[inline] + fn inverse_transform_vector(&self, v: &VectorN) -> VectorN { + self.inverse_transform_vector(v) + } + + #[inline] + fn inverse_transform_point(&self, p: &Point) -> Point { + self.inverse_transform_point(p) + } +} diff --git a/src/geometry/isometry.rs b/src/geometry/isometry.rs index b68a7777..309a3877 100755 --- a/src/geometry/isometry.rs +++ b/src/geometry/isometry.rs @@ -11,14 +11,13 @@ use serde::{Deserialize, Serialize}; #[cfg(feature = "abomonation-serialize")] use abomonation::Abomonation; -use alga::general::{RealField, SubsetOf}; -use alga::linear::Rotation; +use simba::scalar::{RealField, SubsetOf}; use crate::base::allocator::Allocator; use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; use crate::base::storage::Owned; use crate::base::{DefaultAllocator, MatrixN, VectorN}; -use crate::geometry::{Point, Translation}; +use crate::geometry::{AbstractRotation, Point, Translation}; /// A direct isometry, i.e., a rotation followed by a translation, aka. a rigid-body motion, aka. an element of a Special Euclidean (SE) group. #[repr(C)] @@ -77,7 +76,8 @@ where } } -impl hash::Hash for Isometry +impl hash::Hash + for Isometry where DefaultAllocator: Allocator, Owned: hash::Hash, @@ -88,14 +88,14 @@ where } } -impl> + Copy> Copy for Isometry +impl + Copy> Copy for Isometry where DefaultAllocator: Allocator, Owned: Copy, { } -impl> + Clone> Clone for Isometry +impl + Clone> Clone for Isometry where DefaultAllocator: Allocator { #[inline] @@ -104,7 +104,7 @@ where DefaultAllocator: Allocator } } -impl>> Isometry +impl> Isometry where DefaultAllocator: Allocator { /// Creates a new isometry from its rotational and translational parts. @@ -167,7 +167,7 @@ where DefaultAllocator: Allocator /// ``` #[inline] pub fn inverse_mut(&mut self) { - self.rotation.two_sided_inverse_mut(); + self.rotation.inverse_mut(); self.translation.inverse_mut(); self.translation.vector = self.rotation.transform_vector(&self.translation.vector); } @@ -208,7 +208,7 @@ where DefaultAllocator: Allocator /// ``` #[inline] pub fn append_rotation_mut(&mut self, r: &R) { - self.rotation = self.rotation.append_rotation(&r); + self.rotation = r.clone() * self.rotation.clone(); self.translation.vector = r.transform_vector(&self.translation.vector); } @@ -253,7 +253,7 @@ where DefaultAllocator: Allocator /// ``` #[inline] pub fn append_rotation_wrt_center_mut(&mut self, r: &R) { - self.rotation = self.rotation.append_rotation(r); + self.rotation = r.clone() * self.rotation.clone(); } /// Transform the given point by this isometry. @@ -387,14 +387,14 @@ where DefaultAllocator: Allocator impl Eq for Isometry where - R: Rotation> + Eq, + R: AbstractRotation + Eq, DefaultAllocator: Allocator, { } impl PartialEq for Isometry where - R: Rotation> + PartialEq, + R: AbstractRotation + PartialEq, DefaultAllocator: Allocator, { #[inline] @@ -405,7 +405,7 @@ where impl AbsDiffEq for Isometry where - R: Rotation> + AbsDiffEq, + R: AbstractRotation + AbsDiffEq, DefaultAllocator: Allocator, N::Epsilon: Copy, { @@ -425,7 +425,7 @@ where impl RelativeEq for Isometry where - R: Rotation> + RelativeEq, + R: AbstractRotation + RelativeEq, DefaultAllocator: Allocator, N::Epsilon: Copy, { @@ -452,7 +452,7 @@ where impl UlpsEq for Isometry where - R: Rotation> + UlpsEq, + R: AbstractRotation + UlpsEq, DefaultAllocator: Allocator, N::Epsilon: Copy, { diff --git a/src/geometry/isometry_alga.rs b/src/geometry/isometry_alga.rs deleted file mode 100755 index 08916775..00000000 --- a/src/geometry/isometry_alga.rs +++ /dev/null @@ -1,203 +0,0 @@ -use alga::general::{ - AbstractGroup, AbstractLoop, AbstractMagma, AbstractMonoid, AbstractQuasigroup, - AbstractSemigroup, Id, Identity, TwoSidedInverse, Multiplicative, RealField, -}; -use alga::linear::Isometry as AlgaIsometry; -use alga::linear::{ - AffineTransformation, DirectIsometry, ProjectiveTransformation, Rotation, Similarity, - Transformation, -}; - -use crate::base::allocator::Allocator; -use crate::base::dimension::DimName; -use crate::base::{DefaultAllocator, VectorN}; - -use crate::geometry::{Isometry, Point, Translation}; - -/* - * - * Algebraic structures. - * - */ -impl Identity for Isometry -where - R: Rotation>, - DefaultAllocator: Allocator, -{ - #[inline] - fn identity() -> Self { - Self::identity() - } -} - -impl TwoSidedInverse for Isometry -where - R: Rotation>, - DefaultAllocator: Allocator, -{ - #[inline] - #[must_use = "Did you mean to use two_sided_inverse_mut()?"] - fn two_sided_inverse(&self) -> Self { - self.inverse() - } - - #[inline] - fn two_sided_inverse_mut(&mut self) { - self.inverse_mut() - } -} - -impl AbstractMagma for Isometry -where - R: Rotation>, - DefaultAllocator: Allocator, -{ - #[inline] - fn operate(&self, rhs: &Self) -> Self { - self * rhs - } -} - -macro_rules! impl_multiplicative_structures( - ($($marker: ident<$operator: ident>),* $(,)*) => {$( - impl $marker<$operator> for Isometry - where R: Rotation>, - DefaultAllocator: Allocator { } - )*} -); - -impl_multiplicative_structures!( - AbstractSemigroup, - AbstractMonoid, - AbstractQuasigroup, - AbstractLoop, - AbstractGroup -); - -/* - * - * Transformation groups. - * - */ -impl Transformation> for Isometry -where - R: Rotation>, - DefaultAllocator: Allocator, -{ - #[inline] - fn transform_point(&self, pt: &Point) -> Point { - self.transform_point(pt) - } - - #[inline] - fn transform_vector(&self, v: &VectorN) -> VectorN { - self.transform_vector(v) - } -} - -impl ProjectiveTransformation> for Isometry -where - R: Rotation>, - DefaultAllocator: Allocator, -{ - #[inline] - fn inverse_transform_point(&self, pt: &Point) -> Point { - self.inverse_transform_point(pt) - } - - #[inline] - fn inverse_transform_vector(&self, v: &VectorN) -> VectorN { - self.inverse_transform_vector(v) - } -} - -impl AffineTransformation> for Isometry -where - R: Rotation>, - DefaultAllocator: Allocator, -{ - type Rotation = R; - type NonUniformScaling = Id; - type Translation = Translation; - - #[inline] - fn decompose(&self) -> (Self::Translation, R, Id, R) { - ( - self.translation.clone(), - self.rotation.clone(), - Id::new(), - R::identity(), - ) - } - - #[inline] - fn append_translation(&self, t: &Self::Translation) -> Self { - t * self - } - - #[inline] - fn prepend_translation(&self, t: &Self::Translation) -> Self { - self * t - } - - #[inline] - fn append_rotation(&self, r: &Self::Rotation) -> Self { - let shift = r.transform_vector(&self.translation.vector); - Isometry::from_parts(Translation::from(shift), r.clone() * self.rotation.clone()) - } - - #[inline] - fn prepend_rotation(&self, r: &Self::Rotation) -> Self { - self * r - } - - #[inline] - fn append_scaling(&self, _: &Self::NonUniformScaling) -> Self { - self.clone() - } - - #[inline] - fn prepend_scaling(&self, _: &Self::NonUniformScaling) -> Self { - self.clone() - } - - #[inline] - fn append_rotation_wrt_point(&self, r: &Self::Rotation, p: &Point) -> Option { - let mut res = self.clone(); - res.append_rotation_wrt_point_mut(r, p); - Some(res) - } -} - -impl Similarity> for Isometry -where - R: Rotation>, - DefaultAllocator: Allocator, -{ - type Scaling = Id; - - #[inline] - fn translation(&self) -> Translation { - self.translation.clone() - } - - #[inline] - fn rotation(&self) -> R { - self.rotation.clone() - } - - #[inline] - fn scaling(&self) -> Id { - Id::new() - } -} - -macro_rules! marker_impl( - ($($Trait: ident),*) => {$( - impl $Trait> for Isometry - where R: Rotation>, - DefaultAllocator: Allocator { } - )*} -); - -marker_impl!(AlgaIsometry, DirectIsometry); diff --git a/src/geometry/isometry_construction.rs b/src/geometry/isometry_construction.rs index 979c3955..c6f5f3f1 100644 --- a/src/geometry/isometry_construction.rs +++ b/src/geometry/isometry_construction.rs @@ -7,19 +7,18 @@ use num::One; use rand::distributions::{Distribution, Standard}; use rand::Rng; -use alga::general::RealField; -use alga::linear::Rotation as AlgaRotation; +use simba::scalar::RealField; use crate::base::allocator::Allocator; use crate::base::dimension::{DimName, U2, U3}; use crate::base::{DefaultAllocator, Vector2, Vector3}; use crate::geometry::{ - Isometry, Point, Point3, Rotation, Rotation2, Rotation3, Translation, UnitComplex, - UnitQuaternion, Translation2, Translation3 + AbstractRotation, Isometry, Point, Point3, Rotation, Rotation2, Rotation3, Translation, + Translation2, Translation3, UnitComplex, UnitQuaternion, }; -impl>> Isometry +impl> Isometry where DefaultAllocator: Allocator { /// Creates a new identity isometry. @@ -65,7 +64,7 @@ where DefaultAllocator: Allocator } } -impl>> One for Isometry +impl> One for Isometry where DefaultAllocator: Allocator { /// Creates a new identity isometry. @@ -77,7 +76,7 @@ where DefaultAllocator: Allocator impl Distribution> for Standard where - R: AlgaRotation>, + R: AbstractRotation, Standard: Distribution + Distribution, DefaultAllocator: Allocator, { @@ -91,7 +90,7 @@ where impl Arbitrary for Isometry where N: RealField + Arbitrary + Send, - R: AlgaRotation> + Arbitrary + Send, + R: AbstractRotation + Arbitrary + Send, Owned: Send, DefaultAllocator: Allocator, { diff --git a/src/geometry/isometry_conversion.rs b/src/geometry/isometry_conversion.rs index 4a794f55..87711675 100644 --- a/src/geometry/isometry_conversion.rs +++ b/src/geometry/isometry_conversion.rs @@ -1,11 +1,12 @@ -use alga::general::{RealField, SubsetOf, SupersetOf}; -use alga::linear::Rotation; +use simba::scalar::{RealField, SubsetOf, SupersetOf}; use crate::base::allocator::Allocator; use crate::base::dimension::{DimMin, DimName, DimNameAdd, DimNameSum, U1}; use crate::base::{DefaultAllocator, MatrixN}; -use crate::geometry::{Isometry, Point, Similarity, SuperTCategoryOf, TAffine, Transform, Translation}; +use crate::geometry::{ + AbstractRotation, Isometry, Similarity, SuperTCategoryOf, TAffine, Transform, Translation, +}; /* * This file provides the following conversions: @@ -21,8 +22,8 @@ impl SubsetOf> for Isometry, - R1: Rotation> + SubsetOf, - R2: Rotation>, + R1: AbstractRotation + SubsetOf, + R2: AbstractRotation, DefaultAllocator: Allocator + Allocator, { #[inline] @@ -37,7 +38,7 @@ where } #[inline] - unsafe fn from_superset_unchecked(iso: &Isometry) -> Self { + fn from_superset_unchecked(iso: &Isometry) -> Self { Isometry::from_parts( iso.translation.to_subset_unchecked(), iso.rotation.to_subset_unchecked(), @@ -49,8 +50,8 @@ impl SubsetOf> for Isometry, - R1: Rotation> + SubsetOf, - R2: Rotation>, + R1: AbstractRotation + SubsetOf, + R2: AbstractRotation, DefaultAllocator: Allocator + Allocator, { #[inline] @@ -64,7 +65,7 @@ where } #[inline] - unsafe fn from_superset_unchecked(sim: &Similarity) -> Self { + fn from_superset_unchecked(sim: &Similarity) -> Self { crate::convert_ref_unchecked(&sim.isometry) } } @@ -74,7 +75,7 @@ where N1: RealField, N2: RealField + SupersetOf, C: SuperTCategoryOf, - R: Rotation> + R: AbstractRotation + SubsetOf>> + SubsetOf>>, D: DimNameAdd + DimMin, // needed by .is_special_orthogonal() @@ -98,7 +99,7 @@ where } #[inline] - unsafe fn from_superset_unchecked(t: &Transform) -> Self { + fn from_superset_unchecked(t: &Transform) -> Self { Self::from_superset_unchecked(t.matrix()) } } @@ -107,7 +108,7 @@ impl SubsetOf>> for Isometry, - R: Rotation> + R: AbstractRotation + SubsetOf>> + SubsetOf>>, D: DimNameAdd + DimMin, // needed by .is_special_orthogonal() @@ -139,7 +140,7 @@ where } #[inline] - unsafe fn from_superset_unchecked(m: &MatrixN>) -> Self { + fn from_superset_unchecked(m: &MatrixN>) -> Self { let t = m.fixed_slice::(0, D::dim()).into_owned(); let t = Translation { vector: crate::convert_unchecked(t), diff --git a/src/geometry/isometry_ops.rs b/src/geometry/isometry_ops.rs index 6ba9eb3e..cf23e376 100644 --- a/src/geometry/isometry_ops.rs +++ b/src/geometry/isometry_ops.rs @@ -1,13 +1,14 @@ +use num::{One, Zero}; use std::ops::{Div, DivAssign, Mul, MulAssign}; -use alga::general::RealField; -use alga::linear::Rotation as AlgaRotation; +use simba::scalar::{ClosedAdd, ClosedMul, RealField}; use crate::base::allocator::Allocator; use crate::base::dimension::{DimName, U1, U3, U4}; use crate::base::{DefaultAllocator, Unit, VectorN}; +use crate::Scalar; -use crate::geometry::{Isometry, Point, Rotation, Translation, UnitQuaternion}; +use crate::geometry::{AbstractRotation, Isometry, Point, Rotation, Translation, UnitQuaternion}; // FIXME: there are several cloning of rotations that we could probably get rid of (but we didn't // yet because that would require to add a bound like `where for<'a, 'b> &'a R: Mul<&'b R, Output = R>` @@ -65,7 +66,7 @@ macro_rules! isometry_binop_impl( $lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty, Output = $Output: ty; $action: expr; $($lives: tt),*) => { impl<$($lives ,)* N: RealField, D: DimName, R> $Op<$Rhs> for $Lhs - where R: AlgaRotation>, + where R: AbstractRotation, DefaultAllocator: Allocator { type Output = $Output; @@ -112,7 +113,7 @@ macro_rules! isometry_binop_assign_impl_all( [val] => $action_val: expr; [ref] => $action_ref: expr;) => { impl $OpAssign<$Rhs> for $Lhs - where R: AlgaRotation>, + where R: AbstractRotation, DefaultAllocator: Allocator { #[inline] fn $op_assign(&mut $lhs, $rhs: $Rhs) { @@ -121,7 +122,7 @@ macro_rules! isometry_binop_assign_impl_all( } impl<'b, N: RealField, D: DimName, R> $OpAssign<&'b $Rhs> for $Lhs - where R: AlgaRotation>, + where R: AbstractRotation, DefaultAllocator: Allocator { #[inline] fn $op_assign(&mut $lhs, $rhs: &'b $Rhs) { @@ -189,39 +190,38 @@ isometry_binop_assign_impl_all!( // Isometry ×= R // Isometry ÷= R -isometry_binop_assign_impl_all!( - MulAssign, mul_assign; - self: Isometry, rhs: R; +md_assign_impl_all!( + MulAssign, mul_assign where N: RealField; + (D, U1), (D, D) for D: DimName; + self: Isometry>, rhs: Rotation; [val] => self.rotation *= rhs; [ref] => self.rotation *= rhs.clone(); ); -isometry_binop_assign_impl_all!( - DivAssign, div_assign; - self: Isometry, rhs: R; +md_assign_impl_all!( + DivAssign, div_assign where N: RealField; + (D, U1), (D, D) for D: DimName; + self: Isometry>, rhs: Rotation; // FIXME: don't invert explicitly? - [val] => *self *= rhs.two_sided_inverse(); - [ref] => *self *= rhs.two_sided_inverse(); + [val] => *self *= rhs.inverse(); + [ref] => *self *= rhs.inverse(); ); -// Isometry × R -// Isometry ÷ R -isometry_binop_impl_all!( - Mul, mul; - self: Isometry, rhs: R, Output = Isometry; - [val val] => Isometry::from_parts(self.translation, self.rotation * rhs); - [ref val] => Isometry::from_parts(self.translation.clone(), self.rotation.clone() * rhs); // FIXME: 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()); +md_assign_impl_all!( + MulAssign, mul_assign where N: RealField; + (U3, U3), (U3, U3) for; + self: Isometry>, rhs: UnitQuaternion; + [val] => self.rotation *= rhs; + [ref] => self.rotation *= rhs.clone(); ); -isometry_binop_impl_all!( - Div, div; - self: Isometry, rhs: R, Output = Isometry; - [val val] => Isometry::from_parts(self.translation, self.rotation / rhs); - [ref val] => Isometry::from_parts(self.translation.clone(), self.rotation.clone() / rhs); - [val ref] => Isometry::from_parts(self.translation, self.rotation / rhs.clone()); - [ref ref] => Isometry::from_parts(self.translation.clone(), self.rotation.clone() / rhs.clone()); +md_assign_impl_all!( + DivAssign, div_assign where N: RealField; + (U3, U3), (U3, U3) for; + self: Isometry>, rhs: UnitQuaternion; + // FIXME: don't invert explicitly? + [val] => *self *= rhs.inverse(); + [ref] => *self *= rhs.inverse(); ); // Isometry × Point @@ -357,6 +357,18 @@ isometry_from_composition_impl_all!( [ref ref] => Isometry::from_parts(Translation::from( self * &right.vector), self.clone()); ); +// Isometry × Rotation +isometry_from_composition_impl_all!( + Mul, mul; + (D, D), (D, U1) for D: DimName; + self: Isometry>, rhs: Rotation, + Output = Isometry>; + [val val] => Isometry::from_parts(self.translation, self.rotation * rhs); + [ref val] => Isometry::from_parts(self.translation.clone(), self.rotation.clone() * rhs); // FIXME: 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()); +); + // Rotation × Isometry isometry_from_composition_impl_all!( Mul, mul; @@ -372,6 +384,18 @@ isometry_from_composition_impl_all!( }; ); +// Isometry ÷ Rotation +isometry_from_composition_impl_all!( + Div, div; + (D, D), (D, U1) for D: DimName; + self: Isometry>, rhs: Rotation, + Output = Isometry>; + [val val] => Isometry::from_parts(self.translation, self.rotation / rhs); + [ref val] => Isometry::from_parts(self.translation.clone(), self.rotation.clone() / rhs); // FIXME: 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()); +); + // Rotation ÷ Isometry isometry_from_composition_impl_all!( Div, div; @@ -385,6 +409,18 @@ isometry_from_composition_impl_all!( [ref ref] => self * right.inverse(); ); +// Isometry × UnitQuaternion +isometry_from_composition_impl_all!( + Mul, mul; + (U4, U1), (U3, U1); + self: Isometry>, rhs: UnitQuaternion, + Output = Isometry>; + [val val] => Isometry::from_parts(self.translation, self.rotation * rhs); + [ref val] => Isometry::from_parts(self.translation.clone(), self.rotation.clone() * rhs); // FIXME: 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()); +); + // UnitQuaternion × Isometry isometry_from_composition_impl_all!( Mul, mul; @@ -400,6 +436,18 @@ isometry_from_composition_impl_all!( }; ); +// Isometry ÷ UnitQuaternion +isometry_from_composition_impl_all!( + Div, div; + (U4, U1), (U3, U1); + self: Isometry>, rhs: UnitQuaternion, + Output = Isometry>; + [val val] => Isometry::from_parts(self.translation, self.rotation / rhs); + [ref val] => Isometry::from_parts(self.translation.clone(), self.rotation.clone() / rhs); // FIXME: 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()); +); + // UnitQuaternion ÷ Isometry isometry_from_composition_impl_all!( Div, div; diff --git a/src/geometry/isometry_simba.rs b/src/geometry/isometry_simba.rs new file mode 100755 index 00000000..262cdf20 --- /dev/null +++ b/src/geometry/isometry_simba.rs @@ -0,0 +1,62 @@ +use simba::simd::SimdValue; + +use crate::base::allocator::Allocator; +use crate::base::dimension::DimName; +use crate::base::{DefaultAllocator, Scalar}; +use crate::RealField; + +use crate::geometry::{AbstractRotation, Isometry, Translation}; + +impl SimdValue for Isometry +where + N::Element: Scalar, + R: SimdValue + AbstractRotation, + R::Element: AbstractRotation, + DefaultAllocator: Allocator, +{ + type Element = Isometry; + type SimdBool = N::SimdBool; + + #[inline] + fn lanes() -> usize { + N::lanes() + } + + #[inline] + fn splat(val: Self::Element) -> Self { + Isometry::from_parts(Translation::splat(val.translation), R::splat(val.rotation)) + } + + #[inline] + fn extract(&self, i: usize) -> Self::Element { + Isometry::from_parts(self.translation.extract(i), self.rotation.extract(i)) + } + + #[inline] + unsafe fn extract_unchecked(&self, i: usize) -> Self::Element { + Isometry::from_parts( + self.translation.extract_unchecked(i), + self.rotation.extract_unchecked(i), + ) + } + + #[inline] + fn replace(&mut self, i: usize, val: Self::Element) { + self.translation.replace(i, val.translation); + self.rotation.replace(i, val.rotation); + } + + #[inline] + unsafe fn replace_unchecked(&mut self, i: usize, val: Self::Element) { + self.translation.replace_unchecked(i, val.translation); + self.rotation.replace_unchecked(i, val.rotation); + } + + #[inline] + fn select(self, cond: Self::SimdBool, other: Self) -> Self { + Isometry::from_parts( + self.translation.select(cond, other.translation), + self.rotation.select(cond, other.rotation), + ) + } +} diff --git a/src/geometry/mod.rs b/src/geometry/mod.rs index 9e25dc29..30919b5b 100644 --- a/src/geometry/mod.rs +++ b/src/geometry/mod.rs @@ -3,34 +3,36 @@ mod op_macros; +mod abstract_rotation; + mod point; -mod point_alga; mod point_alias; mod point_construction; mod point_conversion; mod point_coordinates; mod point_ops; +mod point_simba; mod rotation; -mod rotation_alga; // FIXME: implement Rotation methods. mod rotation_alias; mod rotation_construction; mod rotation_conversion; mod rotation_ops; +mod rotation_simba; // FIXME: implement Rotation methods. mod rotation_specialization; mod quaternion; -mod quaternion_alga; mod quaternion_construction; mod quaternion_conversion; mod quaternion_coordinates; mod quaternion_ops; +mod quaternion_simba; mod unit_complex; -mod unit_complex_alga; mod unit_complex_construction; mod unit_complex_conversion; mod unit_complex_ops; +mod unit_complex_simba; mod translation; mod translation_alga; @@ -41,33 +43,35 @@ mod translation_coordinates; mod translation_ops; mod isometry; -mod isometry_alga; mod isometry_alias; mod isometry_construction; mod isometry_conversion; mod isometry_ops; +mod isometry_simba; mod similarity; -mod similarity_alga; mod similarity_alias; mod similarity_construction; mod similarity_conversion; mod similarity_ops; +mod similarity_simba; mod swizzle; mod transform; -mod transform_alga; mod transform_alias; mod transform_construction; mod transform_conversion; mod transform_ops; +mod transform_simba; mod reflection; mod orthographic; mod perspective; +pub use self::abstract_rotation::AbstractRotation; + pub use self::point::*; pub use self::point_alias::*; diff --git a/src/geometry/op_macros.rs b/src/geometry/op_macros.rs index 382afe06..86d46f96 100644 --- a/src/geometry/op_macros.rs +++ b/src/geometry/op_macros.rs @@ -1,6 +1,5 @@ #![macro_use] - // FIXME: merge with `md_impl`. /// Macro for the implementation of multiplication and division. macro_rules! md_impl( @@ -88,7 +87,7 @@ macro_rules! md_assign_impl( // Operator, operator method, and scalar bounds. $Op: ident, $op: ident $(where N: $($ScalarBounds: ident),*)*; // Storage dimensions, and dimension bounds. - ($R1: ty, $C1: ty),($R2: ty, $C2: ty) for $($Dims: ident: $DimsBound: ident $(<$($BoundParam: ty),*>)*),+ + ($R1: ty, $C1: ty),($R2: ty, $C2: ty) for $($Dims: ident: $DimsBound: ident $(<$($BoundParam: ty),*>)*),* // [Optional] Extra allocator bounds. $(where $ConstraintType: ty: $ConstraintBound: ident $(<$($ConstraintBoundParams: ty $( = $EqBound: ty )*),*>)* )*; // Argument identifiers and types. @@ -116,7 +115,7 @@ macro_rules! md_assign_impl_all( // Operator, operator method, and scalar bounds. $Op: ident, $op: ident $(where N: $($ScalarBounds: ident),*)*; // Storage dimensions, and dimension bounds. - ($R1: ty, $C1: ty),($R2: ty, $C2: ty) for $($Dims: ident: $DimsBound: ident $(<$($BoundParam: ty),*>)*),+ + ($R1: ty, $C1: ty),($R2: ty, $C2: ty) for $($Dims: ident: $DimsBound: ident $(<$($BoundParam: ty),*>)*),* // [Optional] Extra allocator bounds. $(where $ConstraintType: ty: $ConstraintBound: ident$(<$($ConstraintBoundParams: ty $( = $EqBound: ty )*),*>)* )*; // Argument identifiers and types. @@ -126,14 +125,14 @@ macro_rules! md_assign_impl_all( [ref] => $action_ref: expr;) => { md_assign_impl!( $Op, $op $(where N: $($ScalarBounds),*)*; - ($R1, $C1),($R2, $C2) for $($Dims: $DimsBound $(<$($BoundParam),*>)*),+ + ($R1, $C1),($R2, $C2) for $($Dims: $DimsBound $(<$($BoundParam),*>)*),* $(where $ConstraintType: $ConstraintBound $(<$($ConstraintBoundParams $( = $EqBound )*),*>)*)*; $lhs: $Lhs, $rhs: $Rhs; $action_val; ); md_assign_impl!( $Op, $op $(where N: $($ScalarBounds),*)*; - ($R1, $C1),($R2, $C2) for $($Dims: $DimsBound $(<$($BoundParam),*>)*),+ + ($R1, $C1),($R2, $C2) for $($Dims: $DimsBound $(<$($BoundParam),*>)*),* $(where $ConstraintType: $ConstraintBound $(<$($ConstraintBoundParams $( = $EqBound )*),*>)*)*; $lhs: $Lhs, $rhs: &'b $Rhs; $action_ref; 'b); diff --git a/src/geometry/orthographic.rs b/src/geometry/orthographic.rs index 1ac0d264..b6766e3f 100644 --- a/src/geometry/orthographic.rs +++ b/src/geometry/orthographic.rs @@ -7,7 +7,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::fmt; use std::mem; -use alga::general::RealField; +use simba::scalar::RealField; use crate::base::dimension::U3; use crate::base::helper; @@ -286,7 +286,7 @@ impl Orthographic3 { /// Retrieves the underlying homogeneous matrix. /// Deprecated: Use [Orthographic3::into_inner] instead. - #[deprecated(note="use `.into_inner()` instead")] + #[deprecated(note = "use `.into_inner()` instead")] #[inline] pub fn unwrap(self) -> Matrix4 { self.matrix diff --git a/src/geometry/perspective.rs b/src/geometry/perspective.rs index 45bb7aad..de7de359 100644 --- a/src/geometry/perspective.rs +++ b/src/geometry/perspective.rs @@ -8,7 +8,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::fmt; use std::mem; -use alga::general::RealField; +use simba::scalar::RealField; use crate::base::dimension::U3; use crate::base::helper; @@ -147,7 +147,7 @@ impl Perspective3 { /// Retrieves the underlying homogeneous matrix. /// Deprecated: Use [Perspective3::into_inner] instead. - #[deprecated(note="use `.into_inner()` instead")] + #[deprecated(note = "use `.into_inner()` instead")] #[inline] pub fn unwrap(self) -> Matrix4 { self.matrix @@ -170,7 +170,8 @@ impl Perspective3 { pub fn znear(&self) -> N { let ratio = (-self.matrix[(2, 2)] + N::one()) / (-self.matrix[(2, 2)] - N::one()); - self.matrix[(2, 3)] / (ratio * crate::convert(2.0)) - self.matrix[(2, 3)] / crate::convert(2.0) + self.matrix[(2, 3)] / (ratio * crate::convert(2.0)) + - self.matrix[(2, 3)] / crate::convert(2.0) } /// Gets the far plane offset of the view frustum. diff --git a/src/geometry/point_alga.rs b/src/geometry/point_alga.rs deleted file mode 100644 index 162e6c68..00000000 --- a/src/geometry/point_alga.rs +++ /dev/null @@ -1,83 +0,0 @@ -use alga::general::{Field, JoinSemilattice, Lattice, MeetSemilattice, RealField}; -use alga::linear::{AffineSpace, EuclideanSpace}; - -use crate::base::allocator::Allocator; -use crate::base::dimension::DimName; -use crate::base::{DefaultAllocator, Scalar, VectorN}; - -use crate::geometry::Point; - -impl AffineSpace for Point -where - N: Scalar + Field, - DefaultAllocator: Allocator, -{ - type Translation = VectorN; -} - -impl EuclideanSpace for Point -where DefaultAllocator: Allocator -{ - type Coordinates = VectorN; - type RealField = N; - - #[inline] - fn origin() -> Self { - Self::origin() - } - - #[inline] - fn coordinates(&self) -> Self::Coordinates { - self.coords.clone() - } - - #[inline] - fn from_coordinates(coords: Self::Coordinates) -> Self { - Self::from(coords) - } - - #[inline] - fn scale_by(&self, n: N) -> Self { - self * n - } -} - -/* - * - * Ordering - * - */ -impl MeetSemilattice for Point -where - N: Scalar + MeetSemilattice, - DefaultAllocator: Allocator, -{ - #[inline] - fn meet(&self, other: &Self) -> Self { - Self::from(self.coords.meet(&other.coords)) - } -} - -impl JoinSemilattice for Point -where - N: Scalar + JoinSemilattice, - DefaultAllocator: Allocator, -{ - #[inline] - fn join(&self, other: &Self) -> Self { - Self::from(self.coords.join(&other.coords)) - } -} - -impl Lattice for Point -where - N: Scalar + Lattice, - DefaultAllocator: Allocator, -{ - #[inline] - fn meet_join(&self, other: &Self) -> (Self, Self) { - let (meet, join) = self.coords.meet_join(&other.coords); - - (Self::from(meet), Self::from(join)) - } -} diff --git a/src/geometry/point_construction.rs b/src/geometry/point_construction.rs index e5d2ee44..4b0ea70d 100644 --- a/src/geometry/point_construction.rs +++ b/src/geometry/point_construction.rs @@ -5,10 +5,10 @@ use num::{Bounded, One, Zero}; use rand::distributions::{Distribution, Standard}; use rand::Rng; -use alga::general::ClosedDiv; use crate::base::allocator::Allocator; use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1, U2, U3, U4, U5, U6}; use crate::base::{DefaultAllocator, Scalar, VectorN}; +use simba::scalar::ClosedDiv; use crate::geometry::Point; diff --git a/src/geometry/point_conversion.rs b/src/geometry/point_conversion.rs index 4f32d840..277462e6 100644 --- a/src/geometry/point_conversion.rs +++ b/src/geometry/point_conversion.rs @@ -1,5 +1,5 @@ -use alga::general::{ClosedDiv, SubsetOf, SupersetOf}; use num::{One, Zero}; +use simba::scalar::{ClosedDiv, SubsetOf, SupersetOf}; use crate::base::allocator::Allocator; use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; @@ -44,7 +44,7 @@ where } #[inline] - unsafe fn from_superset_unchecked(m: &Point) -> Self { + fn from_superset_unchecked(m: &Point) -> Self { Self::from(Matrix::from_superset_unchecked(&m.coords)) } } @@ -71,10 +71,10 @@ where } #[inline] - unsafe fn from_superset_unchecked(v: &VectorN>) -> Self { + fn from_superset_unchecked(v: &VectorN>) -> Self { let coords = v.fixed_slice::(0, 0) / v[D::dim()].inlined_clone(); Self { - coords: crate::convert_unchecked(coords) + coords: crate::convert_unchecked(coords), } } } @@ -142,13 +142,10 @@ where } impl From> for Point - where - DefaultAllocator: Allocator, +where DefaultAllocator: Allocator { #[inline] fn from(coords: VectorN) -> Self { - Point { - coords - } + Point { coords } } } diff --git a/src/geometry/point_ops.rs b/src/geometry/point_ops.rs index 648a71a6..d23fd6ec 100644 --- a/src/geometry/point_ops.rs +++ b/src/geometry/point_ops.rs @@ -3,10 +3,12 @@ use std::ops::{ Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign, }; -use alga::general::{ClosedAdd, ClosedDiv, ClosedMul, ClosedNeg, ClosedSub}; +use simba::scalar::{ClosedAdd, ClosedDiv, ClosedMul, ClosedNeg, ClosedSub}; use crate::base::allocator::{Allocator, SameShapeAllocator}; -use crate::base::constraint::{AreMultipliable, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint}; +use crate::base::constraint::{ + AreMultipliable, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint, +}; use crate::base::dimension::{Dim, DimName, U1}; use crate::base::storage::Storage; use crate::base::{DefaultAllocator, Matrix, Scalar, Vector, VectorSum}; diff --git a/src/geometry/point_simba.rs b/src/geometry/point_simba.rs new file mode 100644 index 00000000..a6c8465e --- /dev/null +++ b/src/geometry/point_simba.rs @@ -0,0 +1,51 @@ +use simba::simd::SimdValue; + +use crate::base::allocator::Allocator; +use crate::base::dimension::DimName; +use crate::base::{DefaultAllocator, Scalar, VectorN}; + +use crate::geometry::Point; + +impl SimdValue for Point +where + N::Element: Scalar, + DefaultAllocator: Allocator + Allocator, +{ + type Element = Point; + type SimdBool = N::SimdBool; + + #[inline] + fn lanes() -> usize { + N::lanes() + } + + #[inline] + fn splat(val: Self::Element) -> Self { + VectorN::splat(val.coords).into() + } + + #[inline] + fn extract(&self, i: usize) -> Self::Element { + self.coords.extract(i).into() + } + + #[inline] + unsafe fn extract_unchecked(&self, i: usize) -> Self::Element { + self.coords.extract_unchecked(i).into() + } + + #[inline] + fn replace(&mut self, i: usize, val: Self::Element) { + self.coords.replace(i, val.coords) + } + + #[inline] + unsafe fn replace_unchecked(&mut self, i: usize, val: Self::Element) { + self.coords.replace_unchecked(i, val.coords) + } + + #[inline] + fn select(self, cond: Self::SimdBool, other: Self) -> Self { + self.coords.select(cond, other.coords).into() + } +} diff --git a/src/geometry/quaternion.rs b/src/geometry/quaternion.rs index c2f48796..297e9922 100755 --- a/src/geometry/quaternion.rs +++ b/src/geometry/quaternion.rs @@ -13,11 +13,12 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; #[cfg(feature = "abomonation-serialize")] use abomonation::Abomonation; -use alga::general::RealField; +use simba::scalar::RealField; +use simba::simd::SimdRealField; use crate::base::dimension::{U1, U3, U4}; use crate::base::storage::{CStride, RStride}; -use crate::base::{Matrix3, Matrix4, MatrixSlice, MatrixSliceMut, Unit, Vector3, Vector4}; +use crate::base::{Matrix3, Matrix4, MatrixSlice, MatrixSliceMut, Normed, Unit, Vector3, Vector4}; use crate::geometry::{Point3, Rotation}; @@ -25,13 +26,13 @@ use crate::geometry::{Point3, Rotation}; /// that may be used as a rotation. #[repr(C)] #[derive(Debug)] -pub struct Quaternion { +pub struct Quaternion { /// This quaternion as a 4D vector of coordinates in the `[ x, y, z, w ]` storage order. pub coords: Vector4, } #[cfg(feature = "abomonation-serialize")] -impl Abomonation for Quaternion +impl Abomonation for Quaternion where Vector4: Abomonation { unsafe fn entomb(&self, writer: &mut W) -> IOResult<()> { @@ -47,9 +48,9 @@ where Vector4: Abomonation } } -impl Eq for Quaternion {} +impl Eq for Quaternion {} -impl PartialEq for Quaternion { +impl PartialEq for Quaternion { fn eq(&self, rhs: &Self) -> bool { self.coords == rhs.coords || // Account for the double-covering of S², i.e. q = -q @@ -57,15 +58,15 @@ impl PartialEq for Quaternion { } } -impl hash::Hash for Quaternion { +impl hash::Hash for Quaternion { fn hash(&self, state: &mut H) { self.coords.hash(state) } } -impl Copy for Quaternion {} +impl Copy for Quaternion {} -impl Clone for Quaternion { +impl Clone for Quaternion { #[inline] fn clone(&self) -> Self { Self::from(self.coords.clone()) @@ -73,7 +74,7 @@ impl Clone for Quaternion { } #[cfg(feature = "serde-serialize")] -impl Serialize for Quaternion +impl Serialize for Quaternion where Owned: Serialize { fn serialize(&self, serializer: S) -> Result @@ -83,7 +84,7 @@ where Owned: Serialize } #[cfg(feature = "serde-serialize")] -impl<'a, N: RealField> Deserialize<'a> for Quaternion +impl<'a, N: SimdRealField> Deserialize<'a> for Quaternion where Owned: Deserialize<'a> { fn deserialize(deserializer: Des) -> Result @@ -94,7 +95,7 @@ where Owned: Deserialize<'a> } } -impl Quaternion { +impl Quaternion { /// Moves this unit quaternion into one that owns its data. #[inline] #[deprecated(note = "This method is a no-op and will be removed in a future release.")] @@ -146,36 +147,6 @@ impl Quaternion { Self::from_parts(self.w, -self.imag()) } - /// Inverts this quaternion if it is not zero. - /// - /// # Example - /// ``` - /// # #[macro_use] extern crate approx; - /// # use nalgebra::Quaternion; - /// let q = Quaternion::new(1.0, 2.0, 3.0, 4.0); - /// let inv_q = q.try_inverse(); - /// - /// assert!(inv_q.is_some()); - /// assert_relative_eq!(inv_q.unwrap() * q, Quaternion::identity()); - /// - /// //Non-invertible case - /// let q = Quaternion::new(0.0, 0.0, 0.0, 0.0); - /// let inv_q = q.try_inverse(); - /// - /// assert!(inv_q.is_none()); - /// ``` - #[inline] - #[must_use = "Did you mean to use try_inverse_mut()?"] - pub fn try_inverse(&self) -> Option { - let mut res = Self::from(self.coords.clone_owned()); - - if res.try_inverse_mut() { - Some(res) - } else { - None - } - } - /// Linear interpolation between two quaternion. /// /// Computes `self * (1 - t) + other * t`. @@ -309,6 +280,38 @@ impl Quaternion { pub fn dot(&self, rhs: &Self) -> N { self.coords.dot(&rhs.coords) } +} + +impl Quaternion { + /// Inverts this quaternion if it is not zero. + /// + /// # Example + /// ``` + /// # #[macro_use] extern crate approx; + /// # use nalgebra::Quaternion; + /// let q = Quaternion::new(1.0, 2.0, 3.0, 4.0); + /// let inv_q = q.try_inverse(); + /// + /// assert!(inv_q.is_some()); + /// assert_relative_eq!(inv_q.unwrap() * q, Quaternion::identity()); + /// + /// //Non-invertible case + /// let q = Quaternion::new(0.0, 0.0, 0.0, 0.0); + /// let inv_q = q.try_inverse(); + /// + /// assert!(inv_q.is_none()); + /// ``` + #[inline] + #[must_use = "Did you mean to use try_inverse_mut()?"] + pub fn try_inverse(&self) -> Option { + let mut res = self.clone(); + + if res.try_inverse_mut() { + Some(res) + } else { + None + } + } /// Calculates the inner product (also known as the dot product). /// See "Foundations of Game Engine Development, Volume 1: Mathematics" by Lengyel @@ -917,6 +920,30 @@ impl fmt::Display for Quaternion { /// A unit quaternions. May be used to represent a rotation. pub type UnitQuaternion = Unit>; +impl Normed for Quaternion { + type Norm = N::SimdRealField; + + #[inline] + fn norm(&self) -> N::SimdRealField { + self.coords.norm() + } + + #[inline] + fn norm_squared(&self) -> N::SimdRealField { + self.coords.norm_squared() + } + + #[inline] + fn scale_mut(&mut self, n: Self::Norm) { + self.coords.scale_mut(n) + } + + #[inline] + fn unscale_mut(&mut self, n: Self::Norm) { + self.coords.unscale_mut(n) + } +} + impl UnitQuaternion { /// Moves this unit quaternion into one that owns its data. #[inline] @@ -948,7 +975,7 @@ impl UnitQuaternion { #[inline] pub fn angle(&self) -> N { let w = self.quaternion().scalar().abs(); - self.quaternion().imag().norm().atan2(w) * crate::convert(2.0f64) + self.quaternion().imag().norm().atan2(w) * crate::convert(2.0f64) } /// The underlying quaternion. @@ -1029,7 +1056,7 @@ impl UnitQuaternion { /// assert_relative_eq!(rot_to * rot1, rot2, epsilon = 1.0e-6); /// ``` #[inline] - pub fn rotation_to(&self, other: &Self) -> Self{ + pub fn rotation_to(&self, other: &Self) -> Self { other / self } @@ -1087,7 +1114,8 @@ impl UnitQuaternion { /// ``` #[inline] pub fn slerp(&self, other: &Self, t: N) -> Self { - self.try_slerp(other, t, N::default_epsilon()).expect("Quaternion slerp: ambiguous configuration.") + self.try_slerp(other, t, N::default_epsilon()) + .expect("Quaternion slerp: ambiguous configuration.") } /// Computes the spherical linear interpolation between two unit quaternions or returns `None` @@ -1101,22 +1129,21 @@ impl UnitQuaternion { /// * `epsilon`: the value below which the sinus of the angle separating both quaternion /// must be to return `None`. #[inline] - pub fn try_slerp( - &self, - other: &Self, - t: N, - epsilon: N, - ) -> Option - { + pub fn try_slerp(&self, other: &Self, t: N, epsilon: N) -> Option { let coords = if self.coords.dot(&other.coords) < N::zero() { - Unit::new_unchecked(self.coords) - .try_slerp(&Unit::new_unchecked(-other.coords), t, epsilon) + Unit::new_unchecked(self.coords).try_slerp( + &Unit::new_unchecked(-other.coords), + t, + epsilon, + ) } else { - Unit::new_unchecked(self.coords) - .try_slerp(&Unit::new_unchecked(other.coords), t, epsilon) + Unit::new_unchecked(self.coords).try_slerp( + &Unit::new_unchecked(other.coords), + t, + epsilon, + ) }; - coords.map(|q| Unit::new_unchecked(Quaternion::from(q.into_inner()))) } diff --git a/src/geometry/quaternion_alga.rs b/src/geometry/quaternion_alga.rs deleted file mode 100755 index 86eeedb1..00000000 --- a/src/geometry/quaternion_alga.rs +++ /dev/null @@ -1,307 +0,0 @@ -use num::Zero; - -use alga::general::{ - AbstractGroup, AbstractGroupAbelian, AbstractLoop, AbstractMagma, AbstractModule, - AbstractMonoid, AbstractQuasigroup, AbstractSemigroup, Additive, Id, Identity, TwoSidedInverse, Module, - Multiplicative, RealField, -}; -use alga::linear::{ - AffineTransformation, DirectIsometry, FiniteDimVectorSpace, Isometry, NormedSpace, - OrthogonalTransformation, ProjectiveTransformation, Rotation, Similarity, Transformation, - VectorSpace, -}; - -use crate::base::{Vector3, Vector4}; -use crate::geometry::{Point3, Quaternion, UnitQuaternion}; - -impl Identity for Quaternion { - #[inline] - fn identity() -> Self { - Self::identity() - } -} - -impl Identity for Quaternion { - #[inline] - fn identity() -> Self { - Self::zero() - } -} - -impl AbstractMagma for Quaternion { - #[inline] - fn operate(&self, rhs: &Self) -> Self { - self * rhs - } -} - -impl AbstractMagma for Quaternion { - #[inline] - fn operate(&self, rhs: &Self) -> Self { - self + rhs - } -} - -impl TwoSidedInverse for Quaternion { - #[inline] - fn two_sided_inverse(&self) -> Self { - -self - } -} - -macro_rules! impl_structures( - ($Quaternion: ident; $($marker: ident<$operator: ident>),* $(,)*) => {$( - impl $marker<$operator> for $Quaternion { } - )*} -); - -impl_structures!( - Quaternion; - AbstractSemigroup, - AbstractMonoid, - - AbstractSemigroup, - AbstractQuasigroup, - AbstractMonoid, - AbstractLoop, - AbstractGroup, - AbstractGroupAbelian -); - -/* - * - * Vector space. - * - */ -impl AbstractModule for Quaternion { - type AbstractRing = N; - - #[inline] - fn multiply_by(&self, n: N) -> Self { - self * n - } -} - -impl Module for Quaternion { - type Ring = N; -} - -impl VectorSpace for Quaternion { - type Field = N; -} - -impl FiniteDimVectorSpace for Quaternion { - #[inline] - fn dimension() -> usize { - 4 - } - - #[inline] - fn canonical_basis_element(i: usize) -> Self { - Self::from(Vector4::canonical_basis_element(i)) - } - - #[inline] - fn dot(&self, other: &Self) -> N { - self.coords.dot(&other.coords) - } - - #[inline] - unsafe fn component_unchecked(&self, i: usize) -> &N { - self.coords.component_unchecked(i) - } - - #[inline] - unsafe fn component_unchecked_mut(&mut self, i: usize) -> &mut N { - self.coords.component_unchecked_mut(i) - } -} - -impl NormedSpace for Quaternion { - type RealField = N; - type ComplexField = N; - - #[inline] - fn norm_squared(&self) -> N { - self.coords.norm_squared() - } - - #[inline] - fn norm(&self) -> N { - self.as_vector().norm() - } - - #[inline] - fn normalize(&self) -> Self { - let v = self.coords.normalize(); - Self::from(v) - } - - #[inline] - fn normalize_mut(&mut self) -> N { - self.coords.normalize_mut() - } - - #[inline] - fn try_normalize(&self, min_norm: N) -> Option { - if let Some(v) = self.coords.try_normalize(min_norm) { - Some(Self::from(v)) - } else { - None - } - } - - #[inline] - fn try_normalize_mut(&mut self, min_norm: N) -> Option { - self.coords.try_normalize_mut(min_norm) - } -} - -/* - * - * Implementations for UnitQuaternion. - * - */ -impl Identity for UnitQuaternion { - #[inline] - fn identity() -> Self { - Self::identity() - } -} - -impl AbstractMagma for UnitQuaternion { - #[inline] - fn operate(&self, rhs: &Self) -> Self { - self * rhs - } -} - -impl TwoSidedInverse for UnitQuaternion { - #[inline] - fn two_sided_inverse(&self) -> Self { - self.inverse() - } - - #[inline] - fn two_sided_inverse_mut(&mut self) { - self.inverse_mut() - } -} - -impl_structures!( - UnitQuaternion; - AbstractSemigroup, - AbstractQuasigroup, - AbstractMonoid, - AbstractLoop, - AbstractGroup -); - -impl Transformation> for UnitQuaternion { - #[inline] - fn transform_point(&self, pt: &Point3) -> Point3 { - self.transform_point(pt) - } - - #[inline] - fn transform_vector(&self, v: &Vector3) -> Vector3 { - self.transform_vector(v) - } -} - -impl ProjectiveTransformation> for UnitQuaternion { - #[inline] - fn inverse_transform_point(&self, pt: &Point3) -> Point3 { - self.inverse_transform_point(pt) - } - - #[inline] - fn inverse_transform_vector(&self, v: &Vector3) -> Vector3 { - self.inverse_transform_vector(v) - } -} - -impl AffineTransformation> for UnitQuaternion { - type Rotation = Self; - type NonUniformScaling = Id; - type Translation = Id; - - #[inline] - fn decompose(&self) -> (Id, Self, Id, Self) { - (Id::new(), self.clone(), Id::new(), Self::identity()) - } - - #[inline] - fn append_translation(&self, _: &Self::Translation) -> Self { - self.clone() - } - - #[inline] - fn prepend_translation(&self, _: &Self::Translation) -> Self { - self.clone() - } - - #[inline] - fn append_rotation(&self, r: &Self::Rotation) -> Self { - r * self - } - - #[inline] - fn prepend_rotation(&self, r: &Self::Rotation) -> Self { - self * r - } - - #[inline] - fn append_scaling(&self, _: &Self::NonUniformScaling) -> Self { - self.clone() - } - - #[inline] - fn prepend_scaling(&self, _: &Self::NonUniformScaling) -> Self { - self.clone() - } -} - -impl Similarity> for UnitQuaternion { - type Scaling = Id; - - #[inline] - fn translation(&self) -> Id { - Id::new() - } - - #[inline] - fn rotation(&self) -> Self { - self.clone() - } - - #[inline] - fn scaling(&self) -> Id { - Id::new() - } -} - -macro_rules! marker_impl( - ($($Trait: ident),*) => {$( - impl $Trait> for UnitQuaternion { } - )*} -); - -marker_impl!(Isometry, DirectIsometry, OrthogonalTransformation); - -impl Rotation> for UnitQuaternion { - #[inline] - fn powf(&self, n: N) -> Option { - Some(self.powf(n)) - } - - #[inline] - fn rotation_between(a: &Vector3, b: &Vector3) -> Option { - Self::rotation_between(a, b) - } - - #[inline] - fn scaled_rotation_between(a: &Vector3, b: &Vector3, s: N) -> Option { - Self::scaled_rotation_between(a, b, s) - } -} diff --git a/src/geometry/quaternion_construction.rs b/src/geometry/quaternion_construction.rs index 3de302f5..fb08dd83 100644 --- a/src/geometry/quaternion_construction.rs +++ b/src/geometry/quaternion_construction.rs @@ -9,15 +9,16 @@ use num::{One, Zero}; use rand::distributions::{Distribution, OpenClosed01, Standard}; use rand::Rng; -use alga::general::RealField; +use simba::scalar::RealField; use crate::base::dimension::U3; use crate::base::storage::Storage; -use crate::base::{Unit, Vector, Vector3, Vector4, Matrix3, Matrix4}; +use crate::base::{Matrix3, Matrix4, Unit, Vector, Vector3, Vector4}; +use crate::SimdRealField; use crate::geometry::{Quaternion, Rotation3, UnitQuaternion}; -impl Quaternion { +impl Quaternion { /// Creates a quaternion from a 4D vector. The quaternion scalar part corresponds to the `w` /// vector component. #[inline] @@ -77,17 +78,6 @@ impl Quaternion { Self::from_parts(r, Vector3::zero()) } - /// Creates a new quaternion from its polar decomposition. - /// - /// Note that `axis` is assumed to be a unit vector. - // FIXME: take a reference to `axis`? - pub fn from_polar_decomposition(scale: N, theta: N, axis: Unit>) -> Self - where SB: Storage { - let rot = UnitQuaternion::::from_axis_angle(&axis, theta * crate::convert(2.0f64)); - - rot.into_inner() * scale - } - /// The quaternion multiplicative identity. /// /// # Example @@ -105,14 +95,28 @@ impl Quaternion { } } -impl One for Quaternion { +// FIXME: merge with the previous block. +impl Quaternion { + /// Creates a new quaternion from its polar decomposition. + /// + /// Note that `axis` is assumed to be a unit vector. + // FIXME: take a reference to `axis`? + pub fn from_polar_decomposition(scale: N, theta: N, axis: Unit>) -> Self + where SB: Storage { + let rot = UnitQuaternion::::from_axis_angle(&axis, theta * crate::convert(2.0f64)); + + rot.into_inner() * scale + } +} + +impl One for Quaternion { #[inline] fn one() -> Self { Self::identity() } } -impl Zero for Quaternion { +impl Zero for Quaternion { #[inline] fn zero() -> Self { Self::from(Vector4::zero()) @@ -124,7 +128,7 @@ impl Zero for Quaternion { } } -impl Distribution> for Standard +impl Distribution> for Standard where Standard: Distribution { #[inline] @@ -134,7 +138,7 @@ where Standard: Distribution } #[cfg(feature = "arbitrary")] -impl Arbitrary for Quaternion +impl Arbitrary for Quaternion where Owned: Send { #[inline] @@ -492,7 +496,7 @@ impl UnitQuaternion { } /// Deprecated: Use [UnitQuaternion::face_towards] instead. - #[deprecated(note="renamed to `face_towards`")] + #[deprecated(note = "renamed to `face_towards`")] pub fn new_observer_frames(dir: &Vector, up: &Vector) -> Self where SB: Storage, @@ -685,7 +689,7 @@ impl UnitQuaternion { /// Algorithm from: Oshman, Yaakov, and Avishy Carmi. "Attitude estimation from vector /// observations using a genetic-algorithm-embedded quaternion particle filter." Journal of /// Guidance, Control, and Dynamics 29.4 (2006): 879-891. - /// + /// /// # Example /// ``` /// # #[macro_use] extern crate approx; @@ -709,7 +713,7 @@ impl UnitQuaternion { .sum(); assert!(!quaternions_matrix.is_zero()); - + let eigen_matrix = quaternions_matrix .try_symmetric_eigen(N::RealField::default_epsilon(), 10) .expect("Quaternions matrix could not be diagonalized. This behavior should not be possible."); diff --git a/src/geometry/quaternion_conversion.rs b/src/geometry/quaternion_conversion.rs index 4ac8b5a7..d79a7cdc 100644 --- a/src/geometry/quaternion_conversion.rs +++ b/src/geometry/quaternion_conversion.rs @@ -1,7 +1,7 @@ use num::Zero; -use alga::general::{RealField, SubsetOf, SupersetOf}; -use alga::linear::Rotation as AlgaRotation; +use simba::scalar::{RealField, SubsetOf, SupersetOf}; +use simba::simd::SimdRealField; #[cfg(feature = "mint")] use mint; @@ -9,8 +9,8 @@ use mint; use crate::base::dimension::U3; use crate::base::{Matrix3, Matrix4, Vector4}; use crate::geometry::{ - Isometry, Point3, Quaternion, Rotation, Rotation3, Similarity, SuperTCategoryOf, TAffine, - Transform, Translation, UnitQuaternion, + AbstractRotation, Isometry, Quaternion, Rotation, Rotation3, Similarity, SuperTCategoryOf, + TAffine, Transform, Translation, UnitQuaternion, }; /* @@ -34,8 +34,8 @@ use crate::geometry::{ impl SubsetOf> for Quaternion where - N1: RealField, - N2: RealField + SupersetOf, + N1: SimdRealField, + N2: SimdRealField + SupersetOf, { #[inline] fn to_superset(&self) -> Quaternion { @@ -48,7 +48,7 @@ where } #[inline] - unsafe fn from_superset_unchecked(q: &Quaternion) -> Self { + fn from_superset_unchecked(q: &Quaternion) -> Self { Self { coords: q.coords.to_subset_unchecked(), } @@ -57,8 +57,8 @@ where impl SubsetOf> for UnitQuaternion where - N1: RealField, - N2: RealField + SupersetOf, + N1: SimdRealField, + N2: SimdRealField + SupersetOf, { #[inline] fn to_superset(&self) -> UnitQuaternion { @@ -71,7 +71,7 @@ where } #[inline] - unsafe fn from_superset_unchecked(uq: &UnitQuaternion) -> Self { + fn from_superset_unchecked(uq: &UnitQuaternion) -> Self { Self::new_unchecked(crate::convert_ref_unchecked(uq.as_ref())) } } @@ -93,7 +93,7 @@ where } #[inline] - unsafe fn from_superset_unchecked(rot: &Rotation3) -> Self { + fn from_superset_unchecked(rot: &Rotation3) -> Self { let q = UnitQuaternion::::from_rotation_matrix(rot); crate::convert_unchecked(q) } @@ -103,7 +103,7 @@ impl SubsetOf> for UnitQuaternion where N1: RealField, N2: RealField + SupersetOf, - R: AlgaRotation> + SupersetOf, + R: AbstractRotation + SupersetOf, { #[inline] fn to_superset(&self) -> Isometry { @@ -116,7 +116,7 @@ where } #[inline] - unsafe fn from_superset_unchecked(iso: &Isometry) -> Self { + fn from_superset_unchecked(iso: &Isometry) -> Self { crate::convert_ref_unchecked(&iso.rotation) } } @@ -125,7 +125,7 @@ impl SubsetOf> for UnitQuaternion where N1: RealField, N2: RealField + SupersetOf, - R: AlgaRotation> + SupersetOf, + R: AbstractRotation + SupersetOf, { #[inline] fn to_superset(&self) -> Similarity { @@ -138,7 +138,7 @@ where } #[inline] - unsafe fn from_superset_unchecked(sim: &Similarity) -> Self { + fn from_superset_unchecked(sim: &Similarity) -> Self { crate::convert_ref_unchecked(&sim.isometry) } } @@ -160,7 +160,7 @@ where } #[inline] - unsafe fn from_superset_unchecked(t: &Transform) -> Self { + fn from_superset_unchecked(t: &Transform) -> Self { Self::from_superset_unchecked(t.matrix()) } } @@ -177,7 +177,7 @@ impl> SubsetOf> for Un } #[inline] - unsafe fn from_superset_unchecked(m: &Matrix4) -> Self { + fn from_superset_unchecked(m: &Matrix4) -> Self { let rot: Rotation3 = crate::convert_ref_unchecked(m); Self::from_rotation_matrix(&rot) } @@ -246,7 +246,7 @@ impl From> for Matrix3 { } } -impl From> for Quaternion { +impl From> for Quaternion { #[inline] fn from(coords: Vector4) -> Self { Self { coords } diff --git a/src/geometry/quaternion_coordinates.rs b/src/geometry/quaternion_coordinates.rs index a9399f18..50e340bf 100644 --- a/src/geometry/quaternion_coordinates.rs +++ b/src/geometry/quaternion_coordinates.rs @@ -1,13 +1,13 @@ use std::mem; use std::ops::{Deref, DerefMut}; -use alga::general::RealField; +use simba::simd::SimdRealField; use crate::base::coordinates::IJKW; use crate::geometry::Quaternion; -impl Deref for Quaternion { +impl Deref for Quaternion { type Target = IJKW; #[inline] @@ -16,7 +16,7 @@ impl Deref for Quaternion { } } -impl DerefMut for Quaternion { +impl DerefMut for Quaternion { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { unsafe { mem::transmute(self) } diff --git a/src/geometry/quaternion_ops.rs b/src/geometry/quaternion_ops.rs index 7f2b274a..62e14828 100644 --- a/src/geometry/quaternion_ops.rs +++ b/src/geometry/quaternion_ops.rs @@ -54,16 +54,15 @@ use std::ops::{ Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign, }; -use alga::general::RealField; - use crate::base::allocator::Allocator; use crate::base::dimension::{U1, U3, U4}; use crate::base::storage::Storage; use crate::base::{DefaultAllocator, Unit, Vector, Vector3}; +use crate::SimdRealField; use crate::geometry::{Point3, Quaternion, Rotation, UnitQuaternion}; -impl Index for Quaternion { +impl Index for Quaternion { type Output = N; #[inline] @@ -72,7 +71,7 @@ impl Index for Quaternion { } } -impl IndexMut for Quaternion { +impl IndexMut for Quaternion { #[inline] fn index_mut(&mut self, i: usize) -> &mut N { &mut self.coords[i] @@ -85,7 +84,7 @@ macro_rules! quaternion_op_impl( $(for $Storage: ident: $StoragesBound: ident $(<$($BoundParam: ty),*>)*),*; $lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty, Output = $Result: ty $(=> $VDimA: ty, $VDimB: ty)*; $action: expr; $($lives: tt),*) => { - impl<$($lives ,)* N: RealField $(, $Storage: $StoragesBound $(<$($BoundParam),*>)*)*> $Op<$Rhs> for $Lhs + impl<$($lives ,)* N: SimdRealField $(, $Storage: $StoragesBound $(<$($BoundParam),*>)*)*> $Op<$Rhs> for $Lhs where DefaultAllocator: Allocator + Allocator { type Output = $Result; @@ -121,11 +120,11 @@ quaternion_op_impl!( 'b); quaternion_op_impl!( - Add, add; - (U4, U1), (U4, U1); - self: Quaternion, rhs: Quaternion, Output = Quaternion; - Quaternion::from(self.coords + rhs.coords); - ); +Add, add; +(U4, U1), (U4, U1); +self: Quaternion, rhs: Quaternion, Output = Quaternion; +Quaternion::from(self.coords + rhs.coords); +); // Quaternion - Quaternion quaternion_op_impl!( @@ -150,11 +149,11 @@ quaternion_op_impl!( 'b); quaternion_op_impl!( - Sub, sub; - (U4, U1), (U4, U1); - self: Quaternion, rhs: Quaternion, Output = Quaternion; - Quaternion::from(self.coords - rhs.coords); - ); +Sub, sub; +(U4, U1), (U4, U1); +self: Quaternion, rhs: Quaternion, Output = Quaternion; +Quaternion::from(self.coords - rhs.coords); +); // Quaternion × Quaternion quaternion_op_impl!( @@ -183,11 +182,11 @@ quaternion_op_impl!( 'b); quaternion_op_impl!( - Mul, mul; - (U4, U1), (U4, U1); - self: Quaternion, rhs: Quaternion, Output = Quaternion; - &self * &rhs; - ); +Mul, mul; +(U4, U1), (U4, U1); +self: Quaternion, rhs: Quaternion, Output = Quaternion; +&self * &rhs; +); // UnitQuaternion × UnitQuaternion quaternion_op_impl!( @@ -212,11 +211,11 @@ quaternion_op_impl!( 'b); quaternion_op_impl!( - Mul, mul; - (U4, U1), (U4, U1); - self: UnitQuaternion, rhs: UnitQuaternion, Output = UnitQuaternion; - &self * &rhs; - ); +Mul, mul; +(U4, U1), (U4, U1); +self: UnitQuaternion, rhs: UnitQuaternion, Output = UnitQuaternion; +&self * &rhs; +); // UnitQuaternion ÷ UnitQuaternion quaternion_op_impl!( @@ -241,11 +240,11 @@ quaternion_op_impl!( 'b); quaternion_op_impl!( - Div, div; - (U4, U1), (U4, U1); - self: UnitQuaternion, rhs: UnitQuaternion, Output = UnitQuaternion; - &self / &rhs; - ); +Div, div; +(U4, U1), (U4, U1); +self: UnitQuaternion, rhs: UnitQuaternion, Output = UnitQuaternion; +&self / &rhs; +); // UnitQuaternion × Rotation quaternion_op_impl!( @@ -274,12 +273,12 @@ quaternion_op_impl!( 'b); quaternion_op_impl!( - Mul, mul; - (U4, U1), (U3, U3); - self: UnitQuaternion, rhs: Rotation, - Output = UnitQuaternion => U3, U3; - self * UnitQuaternion::::from_rotation_matrix(&rhs); - ); +Mul, mul; +(U4, U1), (U3, U3); +self: UnitQuaternion, rhs: Rotation, +Output = UnitQuaternion => U3, U3; +self * UnitQuaternion::::from_rotation_matrix(&rhs); +); // UnitQuaternion ÷ Rotation quaternion_op_impl!( @@ -308,12 +307,12 @@ quaternion_op_impl!( 'b); quaternion_op_impl!( - Div, div; - (U4, U1), (U3, U3); - self: UnitQuaternion, rhs: Rotation, - Output = UnitQuaternion => U3, U3; - self / UnitQuaternion::::from_rotation_matrix(&rhs); - ); +Div, div; +(U4, U1), (U3, U3); +self: UnitQuaternion, rhs: Rotation, +Output = UnitQuaternion => U3, U3; +self / UnitQuaternion::::from_rotation_matrix(&rhs); +); // Rotation × UnitQuaternion quaternion_op_impl!( @@ -342,12 +341,12 @@ quaternion_op_impl!( 'b); quaternion_op_impl!( - Mul, mul; - (U3, U3), (U4, U1); - self: Rotation, rhs: UnitQuaternion, - Output = UnitQuaternion => U3, U3; - UnitQuaternion::::from_rotation_matrix(&self) * rhs; - ); +Mul, mul; +(U3, U3), (U4, U1); +self: Rotation, rhs: UnitQuaternion, +Output = UnitQuaternion => U3, U3; +UnitQuaternion::::from_rotation_matrix(&self) * rhs; +); // Rotation ÷ UnitQuaternion quaternion_op_impl!( @@ -376,12 +375,12 @@ quaternion_op_impl!( 'b); quaternion_op_impl!( - Div, div; - (U3, U3), (U4, U1); - self: Rotation, rhs: UnitQuaternion, - Output = UnitQuaternion => U3, U3; - UnitQuaternion::::from_rotation_matrix(&self) / rhs; - ); +Div, div; +(U3, U3), (U4, U1); +self: Rotation, rhs: UnitQuaternion, +Output = UnitQuaternion => U3, U3; +UnitQuaternion::::from_rotation_matrix(&self) / rhs; +); // UnitQuaternion × Vector quaternion_op_impl!( @@ -415,12 +414,12 @@ quaternion_op_impl!( 'b); quaternion_op_impl!( - Mul, mul; - (U4, U1), (U3, U1) for SB: Storage ; - self: UnitQuaternion, rhs: Vector, - Output = Vector3 => U3, U4; - &self * &rhs; - ); +Mul, mul; +(U4, U1), (U3, U1) for SB: Storage ; +self: UnitQuaternion, rhs: Vector, +Output = Vector3 => U3, U4; +&self * &rhs; +); // UnitQuaternion × Point quaternion_op_impl!( @@ -448,12 +447,12 @@ quaternion_op_impl!( 'b); quaternion_op_impl!( - Mul, mul; - (U4, U1), (U3, U1); - self: UnitQuaternion, rhs: Point3, - Output = Point3 => U3, U4; - Point3::from(self * rhs.coords); - ); +Mul, mul; +(U4, U1), (U3, U1); +self: UnitQuaternion, rhs: Point3, +Output = Point3 => U3, U4; +Point3::from(self * rhs.coords); +); // UnitQuaternion × Unit quaternion_op_impl!( @@ -481,16 +480,16 @@ quaternion_op_impl!( 'b); quaternion_op_impl!( - Mul, mul; - (U4, U1), (U3, U1) for SB: Storage ; - self: UnitQuaternion, rhs: Unit>, - Output = Unit> => U3, U4; - Unit::new_unchecked(self * rhs.into_inner()); - ); +Mul, mul; +(U4, U1), (U3, U1) for SB: Storage ; +self: UnitQuaternion, rhs: Unit>, +Output = Unit> => U3, U4; +Unit::new_unchecked(self * rhs.into_inner()); +); macro_rules! scalar_op_impl( ($($Op: ident, $op: ident, $OpAssign: ident, $op_assign: ident);* $(;)*) => {$( - impl $Op for Quaternion { + impl $Op for Quaternion { type Output = Quaternion; #[inline] @@ -499,7 +498,7 @@ macro_rules! scalar_op_impl( } } - impl<'a, N: RealField> $Op for &'a Quaternion { + impl<'a, N: SimdRealField> $Op for &'a Quaternion { type Output = Quaternion; #[inline] @@ -508,7 +507,7 @@ macro_rules! scalar_op_impl( } } - impl $OpAssign for Quaternion { + impl $OpAssign for Quaternion { #[inline] fn $op_assign(&mut self, n: N) { @@ -547,7 +546,7 @@ macro_rules! left_scalar_mul_impl( left_scalar_mul_impl!(f32, f64); -impl Neg for Quaternion { +impl Neg for Quaternion { type Output = Quaternion; #[inline] @@ -556,7 +555,7 @@ impl Neg for Quaternion { } } -impl<'a, N: RealField> Neg for &'a Quaternion { +impl<'a, N: SimdRealField> Neg for &'a Quaternion { type Output = Quaternion; #[inline] @@ -570,7 +569,7 @@ macro_rules! quaternion_op_impl( ($LhsRDim: ident, $LhsCDim: ident), ($RhsRDim: ident, $RhsCDim: ident); $lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty $(=> $VDimA: ty, $VDimB: ty)*; $action: expr; $($lives: tt),*) => { - impl<$($lives ,)* N: RealField> $OpAssign<$Rhs> for $Lhs + impl<$($lives ,)* N: SimdRealField> $OpAssign<$Rhs> for $Lhs where DefaultAllocator: Allocator + Allocator { diff --git a/src/geometry/quaternion_simba.rs b/src/geometry/quaternion_simba.rs new file mode 100755 index 00000000..6eed073e --- /dev/null +++ b/src/geometry/quaternion_simba.rs @@ -0,0 +1,47 @@ +use simba::simd::SimdValue; + +use crate::base::Vector4; +use crate::geometry::Quaternion; +use crate::{RealField, Scalar}; + +impl SimdValue for Quaternion +where N::Element: Scalar +{ + type Element = Quaternion; + type SimdBool = N::SimdBool; + + #[inline] + fn lanes() -> usize { + N::lanes() + } + + #[inline] + fn splat(val: Self::Element) -> Self { + Vector4::splat(val.coords).into() + } + + #[inline] + fn extract(&self, i: usize) -> Self::Element { + self.coords.extract(i).into() + } + + #[inline] + unsafe fn extract_unchecked(&self, i: usize) -> Self::Element { + self.coords.extract_unchecked(i).into() + } + + #[inline] + fn replace(&mut self, i: usize, val: Self::Element) { + self.coords.replace(i, val.coords) + } + + #[inline] + unsafe fn replace_unchecked(&mut self, i: usize, val: Self::Element) { + self.coords.replace_unchecked(i, val.coords) + } + + #[inline] + fn select(self, cond: Self::SimdBool, other: Self) -> Self { + self.coords.select(cond, other.coords).into() + } +} diff --git a/src/geometry/reflection.rs b/src/geometry/reflection.rs index b4658a11..c0500e84 100644 --- a/src/geometry/reflection.rs +++ b/src/geometry/reflection.rs @@ -1,9 +1,9 @@ -use alga::general::ComplexField; use crate::base::allocator::Allocator; use crate::base::constraint::{AreMultipliable, DimEq, SameNumberOfRows, ShapeConstraint}; use crate::base::{DefaultAllocator, Matrix, Scalar, Unit, Vector}; use crate::dimension::{Dim, DimName, U1}; use crate::storage::{Storage, StorageMut}; +use simba::scalar::ComplexField; use crate::geometry::Point; @@ -27,10 +27,7 @@ impl> Reflection { /// Creates a new reflection wrt. the plane orthogonal to the given axis and that contains the /// point `pt`. - pub fn new_containing_point( - axis: Unit>, - pt: &Point, - ) -> Self + pub fn new_containing_point(axis: Unit>, pt: &Point) -> Self where D: DimName, DefaultAllocator: Allocator, @@ -64,9 +61,9 @@ impl> Reflection { // FIXME: naming convention: reflect_to, reflect_assign ? /// Applies the reflection to the columns of `rhs`. pub fn reflect_with_sign(&self, rhs: &mut Matrix, sign: N) - where - S2: StorageMut, - ShapeConstraint: SameNumberOfRows, + where + S2: StorageMut, + ShapeConstraint: SameNumberOfRows, { for i in 0..rhs.ncols() { // NOTE: we borrow the column twice here. First it is borrowed immutably for the diff --git a/src/geometry/rotation.rs b/src/geometry/rotation.rs index 2cf8822c..0717895f 100755 --- a/src/geometry/rotation.rs +++ b/src/geometry/rotation.rs @@ -14,7 +14,7 @@ use crate::base::storage::Owned; #[cfg(feature = "abomonation-serialize")] use abomonation::Abomonation; -use alga::general::RealField; +use simba::scalar::RealField; use crate::base::allocator::Allocator; use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; @@ -175,7 +175,7 @@ where DefaultAllocator: Allocator /// Unwraps the underlying matrix. /// Deprecated: Use [Rotation::into_inner] instead. - #[deprecated(note="use `.into_inner()` instead")] + #[deprecated(note = "use `.into_inner()` instead")] #[inline] pub fn unwrap(self) -> MatrixN { self.matrix diff --git a/src/geometry/rotation_alga.rs b/src/geometry/rotation_alga.rs deleted file mode 100755 index c4133e41..00000000 --- a/src/geometry/rotation_alga.rs +++ /dev/null @@ -1,276 +0,0 @@ -use alga::general::{ - AbstractGroup, AbstractLoop, AbstractMagma, AbstractMonoid, AbstractQuasigroup, - AbstractSemigroup, Id, Identity, TwoSidedInverse, Multiplicative, RealField, -}; -use alga::linear::{ - self, AffineTransformation, DirectIsometry, Isometry, OrthogonalTransformation, - ProjectiveTransformation, Similarity, Transformation, -}; - -use crate::base::allocator::Allocator; -use crate::base::dimension::DimName; -use crate::base::{DefaultAllocator, VectorN}; - -use crate::geometry::{Point, Rotation}; - -/* - * - * Algebraic structures. - * - */ -impl Identity for Rotation -where DefaultAllocator: Allocator -{ - #[inline] - fn identity() -> Self { - Self::identity() - } -} - -impl TwoSidedInverse for Rotation -where DefaultAllocator: Allocator -{ - #[inline] - #[must_use = "Did you mean to use two_sided_inverse_mut()?"] - fn two_sided_inverse(&self) -> Self { - self.transpose() - } - - #[inline] - fn two_sided_inverse_mut(&mut self) { - self.transpose_mut() - } -} - -impl AbstractMagma for Rotation -where DefaultAllocator: Allocator -{ - #[inline] - fn operate(&self, rhs: &Self) -> Self { - self * rhs - } -} - -macro_rules! impl_multiplicative_structures( - ($($marker: ident<$operator: ident>),* $(,)*) => {$( - impl $marker<$operator> for Rotation - where DefaultAllocator: Allocator { } - )*} -); - -impl_multiplicative_structures!( - AbstractSemigroup, - AbstractMonoid, - AbstractQuasigroup, - AbstractLoop, - AbstractGroup -); - -/* - * - * Transformation groups. - * - */ -impl Transformation> for Rotation -where DefaultAllocator: Allocator + Allocator -{ - #[inline] - fn transform_point(&self, pt: &Point) -> Point { - self.transform_point(pt) - } - - #[inline] - fn transform_vector(&self, v: &VectorN) -> VectorN { - self.transform_vector(v) - } -} - -impl ProjectiveTransformation> for Rotation -where DefaultAllocator: Allocator + Allocator -{ - #[inline] - fn inverse_transform_point(&self, pt: &Point) -> Point { - self.inverse_transform_point(pt) - } - - #[inline] - fn inverse_transform_vector(&self, v: &VectorN) -> VectorN { - self.inverse_transform_vector(v) - } -} - -impl AffineTransformation> for Rotation -where DefaultAllocator: Allocator + Allocator -{ - type Rotation = Self; - type NonUniformScaling = Id; - type Translation = Id; - - #[inline] - fn decompose(&self) -> (Id, Self, Id, Self) { - (Id::new(), self.clone(), Id::new(), Self::identity()) - } - - #[inline] - fn append_translation(&self, _: &Self::Translation) -> Self { - self.clone() - } - - #[inline] - fn prepend_translation(&self, _: &Self::Translation) -> Self { - self.clone() - } - - #[inline] - fn append_rotation(&self, r: &Self::Rotation) -> Self { - r * self - } - - #[inline] - fn prepend_rotation(&self, r: &Self::Rotation) -> Self { - self * r - } - - #[inline] - fn append_scaling(&self, _: &Self::NonUniformScaling) -> Self { - self.clone() - } - - #[inline] - fn prepend_scaling(&self, _: &Self::NonUniformScaling) -> Self { - self.clone() - } -} - -impl Similarity> for Rotation -where DefaultAllocator: Allocator + Allocator -{ - type Scaling = Id; - - #[inline] - fn translation(&self) -> Id { - Id::new() - } - - #[inline] - fn rotation(&self) -> Self { - self.clone() - } - - #[inline] - fn scaling(&self) -> Id { - Id::new() - } -} - -macro_rules! marker_impl( - ($($Trait: ident),*) => {$( - impl $Trait> for Rotation - where DefaultAllocator: Allocator + - Allocator { } - )*} -); - -marker_impl!(Isometry, DirectIsometry, OrthogonalTransformation); - -/// Subgroups of the n-dimensional rotation group `SO(n)`. -impl linear::Rotation> for Rotation -where DefaultAllocator: Allocator + Allocator -{ - #[inline] - fn powf(&self, _: N) -> Option { - // XXX: Add the general case. - // XXX: Use specialization for 2D and 3D. - unimplemented!() - } - - #[inline] - fn rotation_between(_: &VectorN, _: &VectorN) -> Option { - // XXX: Add the general case. - // XXX: Use specialization for 2D and 3D. - unimplemented!() - } - - #[inline] - fn scaled_rotation_between(_: &VectorN, _: &VectorN, _: N) -> Option { - // XXX: Add the general case. - // XXX: Use specialization for 2D and 3D. - unimplemented!() - } -} - -/* -impl Matrix for Rotation { - type Field = N; - type Row = Matrix; - type Column = Matrix; - type Transpose = Self; - - #[inline] - fn nrows(&self) -> usize { - self.submatrix.nrows() - } - - #[inline] - fn ncolumns(&self) -> usize { - self.submatrix.ncolumns() - } - - #[inline] - fn row(&self, i: usize) -> Self::Row { - self.submatrix.row(i) - } - - #[inline] - fn column(&self, i: usize) -> Self::Column { - self.submatrix.column(i) - } - - #[inline] - fn get(&self, i: usize, j: usize) -> Self::Field { - self.submatrix[(i, j)] - } - - #[inline] - unsafe fn get_unchecked(&self, i: usize, j: usize) -> Self::Field { - self.submatrix.at_fast(i, j) - } - - #[inline] - fn transpose(&self) -> Self::Transpose { - Rotation::from_matrix_unchecked(self.submatrix.transpose()) - } -} - -impl SquareMatrix for Rotation { - type Vector = Matrix; - - #[inline] - fn diagonal(&self) -> Self::Coordinates { - self.submatrix.diagonal() - } - - #[inline] - fn determinant(&self) -> Self::Field { - crate::one() - } - - #[inline] - fn try_inverse(&self) -> Option { - Some(::transpose(self)) - } - - #[inline] - fn try_inverse_mut(&mut self) -> bool { - self.transpose_mut(); - true - } - - #[inline] - fn transpose_mut(&mut self) { - self.submatrix.transpose_mut() - } -} - -impl InversibleSquareMatrix for Rotation { } -*/ diff --git a/src/geometry/rotation_construction.rs b/src/geometry/rotation_construction.rs index a7779cc6..12d93402 100644 --- a/src/geometry/rotation_construction.rs +++ b/src/geometry/rotation_construction.rs @@ -1,6 +1,6 @@ use num::{One, Zero}; -use alga::general::{ClosedAdd, ClosedMul}; +use simba::scalar::{ClosedAdd, ClosedMul}; use crate::base::allocator::Allocator; use crate::base::dimension::DimName; diff --git a/src/geometry/rotation_conversion.rs b/src/geometry/rotation_conversion.rs index ac314221..0b40dfbd 100644 --- a/src/geometry/rotation_conversion.rs +++ b/src/geometry/rotation_conversion.rs @@ -1,7 +1,6 @@ use num::Zero; -use alga::general::{RealField, SubsetOf, SupersetOf}; -use alga::linear::Rotation as AlgaRotation; +use simba::scalar::{RealField, SubsetOf, SupersetOf}; #[cfg(feature = "mint")] use mint; @@ -11,8 +10,8 @@ use crate::base::dimension::{DimMin, DimName, DimNameAdd, DimNameSum, U1}; use crate::base::{DefaultAllocator, Matrix2, Matrix3, Matrix4, MatrixN}; use crate::geometry::{ - Isometry, Point, Rotation, Rotation2, Rotation3, Similarity, SuperTCategoryOf, TAffine, - Transform, Translation, UnitComplex, UnitQuaternion, + AbstractRotation, Isometry, Rotation, Rotation2, Rotation3, Similarity, SuperTCategoryOf, + TAffine, Transform, Translation, UnitComplex, UnitQuaternion, }; /* @@ -47,7 +46,7 @@ where } #[inline] - unsafe fn from_superset_unchecked(rot: &Rotation) -> Self { + fn from_superset_unchecked(rot: &Rotation) -> Self { Rotation::from_matrix_unchecked(rot.matrix().to_subset_unchecked()) } } @@ -69,7 +68,7 @@ where } #[inline] - unsafe fn from_superset_unchecked(q: &UnitQuaternion) -> Self { + fn from_superset_unchecked(q: &UnitQuaternion) -> Self { let q: UnitQuaternion = crate::convert_ref_unchecked(q); q.to_rotation_matrix() } @@ -92,7 +91,7 @@ where } #[inline] - unsafe fn from_superset_unchecked(q: &UnitComplex) -> Self { + fn from_superset_unchecked(q: &UnitComplex) -> Self { let q: UnitComplex = crate::convert_ref_unchecked(q); q.to_rotation_matrix() } @@ -102,7 +101,7 @@ impl SubsetOf> for Rotation where N1: RealField, N2: RealField + SupersetOf, - R: AlgaRotation> + SupersetOf, + R: AbstractRotation + SupersetOf, DefaultAllocator: Allocator + Allocator, { #[inline] @@ -116,7 +115,7 @@ where } #[inline] - unsafe fn from_superset_unchecked(iso: &Isometry) -> Self { + fn from_superset_unchecked(iso: &Isometry) -> Self { crate::convert_ref_unchecked(&iso.rotation) } } @@ -125,7 +124,7 @@ impl SubsetOf> for Rotation where N1: RealField, N2: RealField + SupersetOf, - R: AlgaRotation> + SupersetOf, + R: AbstractRotation + SupersetOf, DefaultAllocator: Allocator + Allocator, { #[inline] @@ -139,7 +138,7 @@ where } #[inline] - unsafe fn from_superset_unchecked(sim: &Similarity) -> Self { + fn from_superset_unchecked(sim: &Similarity) -> Self { crate::convert_ref_unchecked(&sim.isometry.rotation) } } @@ -168,7 +167,7 @@ where } #[inline] - unsafe fn from_superset_unchecked(t: &Transform) -> Self { + fn from_superset_unchecked(t: &Transform) -> Self { Self::from_superset_unchecked(t.matrix()) } } @@ -204,7 +203,7 @@ where } #[inline] - unsafe fn from_superset_unchecked(m: &MatrixN>) -> Self { + fn from_superset_unchecked(m: &MatrixN>) -> Self { let r = m.fixed_slice::(0, 0); Self::from_matrix_unchecked(crate::convert_unchecked(r.into_owned())) } @@ -219,7 +218,7 @@ impl From> for Rotation3 { impl From> for Matrix3 { #[inline] - fn from(q: Rotation2) ->Self { + fn from(q: Rotation2) -> Self { q.to_homogeneous() } } diff --git a/src/geometry/rotation_ops.rs b/src/geometry/rotation_ops.rs index ed555b6b..069f0923 100644 --- a/src/geometry/rotation_ops.rs +++ b/src/geometry/rotation_ops.rs @@ -20,7 +20,7 @@ use num::{One, Zero}; use std::ops::{Div, DivAssign, Index, Mul, MulAssign}; -use alga::general::{ClosedAdd, ClosedMul}; +use simba::scalar::{ClosedAdd, ClosedMul}; use crate::base::allocator::Allocator; use crate::base::constraint::{AreMultipliable, ShapeConstraint}; diff --git a/src/geometry/rotation_simba.rs b/src/geometry/rotation_simba.rs new file mode 100755 index 00000000..cb064a81 --- /dev/null +++ b/src/geometry/rotation_simba.rs @@ -0,0 +1,54 @@ +use simba::simd::SimdValue; + +use crate::base::allocator::Allocator; +use crate::base::dimension::DimName; +use crate::base::{DefaultAllocator, MatrixN, Scalar}; + +use crate::geometry::Rotation; + +impl SimdValue for Rotation +where + N: Scalar + SimdValue, + D: DimName, + N::Element: Scalar, + DefaultAllocator: Allocator + Allocator, +{ + type Element = Rotation; + type SimdBool = N::SimdBool; + + #[inline] + fn lanes() -> usize { + N::lanes() + } + + #[inline] + fn splat(val: Self::Element) -> Self { + Rotation::from_matrix_unchecked(MatrixN::splat(val.into_inner())) + } + + #[inline] + fn extract(&self, i: usize) -> Self::Element { + Rotation::from_matrix_unchecked(self.matrix().extract(i)) + } + + #[inline] + unsafe fn extract_unchecked(&self, i: usize) -> Self::Element { + Rotation::from_matrix_unchecked(self.matrix().extract_unchecked(i)) + } + + #[inline] + fn replace(&mut self, i: usize, val: Self::Element) { + self.matrix_mut_unchecked().replace(i, val.into_inner()) + } + + #[inline] + unsafe fn replace_unchecked(&mut self, i: usize, val: Self::Element) { + self.matrix_mut_unchecked() + .replace_unchecked(i, val.into_inner()) + } + + #[inline] + fn select(self, cond: Self::SimdBool, other: Self) -> Self { + Rotation::from_matrix_unchecked(self.into_inner().select(cond, other.into_inner())) + } +} diff --git a/src/geometry/rotation_specialization.rs b/src/geometry/rotation_specialization.rs index 4baec27c..f72a07d5 100644 --- a/src/geometry/rotation_specialization.rs +++ b/src/geometry/rotation_specialization.rs @@ -3,10 +3,10 @@ use crate::base::storage::Owned; #[cfg(feature = "arbitrary")] use quickcheck::{Arbitrary, Gen}; -use alga::general::RealField; use num::Zero; use rand::distributions::{Distribution, OpenClosed01, Standard}; use rand::Rng; +use simba::scalar::RealField; use std::ops::Neg; use crate::base::dimension::{U1, U2, U3}; @@ -77,10 +77,8 @@ impl Rotation2 { let mut rot = guess.into_inner(); for _ in 0..max_iter { - let axis = rot.column(0).perp(&m.column(0)) + - rot.column(1).perp(&m.column(1)); - let denom = rot.column(0).dot(&m.column(0)) + - rot.column(1).dot(&m.column(1)); + let axis = rot.column(0).perp(&m.column(0)) + rot.column(1).perp(&m.column(1)); + let denom = rot.column(0).dot(&m.column(0)) + rot.column(1).dot(&m.column(1)); let angle = axis / (denom.abs() + N::default_epsilon()); if angle.abs() > eps { @@ -192,7 +190,6 @@ impl Rotation2 { other * self.inverse() } - /// Ensure this rotation is an orthonormal rotation matrix. This is useful when repeated /// computations might cause the matrix from progressively not being orthonormal anymore. #[inline] @@ -203,7 +200,6 @@ impl Rotation2 { *self = Self::from_matrix_eps(self.matrix(), N::default_epsilon(), 0, c.into()) } - /// Raise the quaternion to a given floating power, i.e., returns the rotation with the angle /// of `self` multiplied by `n`. /// @@ -314,12 +310,12 @@ impl Rotation3 { let mut rot = guess.into_inner(); for _ in 0..max_iter { - let axis = rot.column(0).cross(&m.column(0)) + - rot.column(1).cross(&m.column(1)) + - rot.column(2).cross(&m.column(2)); - let denom = rot.column(0).dot(&m.column(0)) + - rot.column(1).dot(&m.column(1)) + - rot.column(2).dot(&m.column(2)); + let axis = rot.column(0).cross(&m.column(0)) + + rot.column(1).cross(&m.column(1)) + + rot.column(2).cross(&m.column(2)); + let denom = rot.column(0).dot(&m.column(0)) + + rot.column(1).dot(&m.column(1)) + + rot.column(2).dot(&m.column(2)); let axisangle = axis / (denom.abs() + N::default_epsilon()); @@ -528,7 +524,7 @@ impl Rotation3 { } /// Deprecated: Use [Rotation3::face_towards] instead. - #[deprecated(note="renamed to `face_towards`")] + #[deprecated(note = "renamed to `face_towards`")] pub fn new_observer_frames(dir: &Vector, up: &Vector) -> Self where SB: Storage, diff --git a/src/geometry/similarity.rs b/src/geometry/similarity.rs index 9f5fee41..6bfd7a93 100755 --- a/src/geometry/similarity.rs +++ b/src/geometry/similarity.rs @@ -10,14 +10,13 @@ use serde::{Deserialize, Serialize}; #[cfg(feature = "abomonation-serialize")] use abomonation::Abomonation; -use alga::general::{RealField, SubsetOf}; -use alga::linear::Rotation; +use simba::scalar::{RealField, SubsetOf}; use crate::base::allocator::Allocator; use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; use crate::base::storage::Owned; use crate::base::{DefaultAllocator, MatrixN, VectorN}; -use crate::geometry::{Isometry, Point, Translation}; +use crate::geometry::{AbstractRotation, Isometry, Point, Translation}; /// A similarity, i.e., an uniform scaling, followed by a rotation, followed by a translation. #[repr(C)] @@ -25,21 +24,17 @@ use crate::geometry::{Isometry, Point, Translation}; #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[cfg_attr( feature = "serde-serialize", - serde(bound( - serialize = "N: Serialize, + serde(bound(serialize = "N: Serialize, R: Serialize, DefaultAllocator: Allocator, - Owned: Serialize" - )) + Owned: Serialize")) )] #[cfg_attr( feature = "serde-serialize", - serde(bound( - deserialize = "N: Deserialize<'de>, + serde(bound(deserialize = "N: Deserialize<'de>, R: Deserialize<'de>, DefaultAllocator: Allocator, - Owned: Deserialize<'de>" - )) + Owned: Deserialize<'de>")) )] pub struct Similarity where DefaultAllocator: Allocator @@ -80,13 +75,14 @@ where } } -impl> + Copy> Copy for Similarity +impl + Copy> Copy for Similarity where DefaultAllocator: Allocator, Owned: Copy, -{} +{ +} -impl> + Clone> Clone for Similarity +impl + Clone> Clone for Similarity where DefaultAllocator: Allocator { #[inline] @@ -97,17 +93,12 @@ where DefaultAllocator: Allocator impl Similarity where - R: Rotation>, + R: AbstractRotation, DefaultAllocator: Allocator, { /// Creates a new similarity from its rotational and translational parts. #[inline] - pub fn from_parts( - translation: Translation, - rotation: R, - scaling: N, - ) -> Self - { + pub fn from_parts(translation: Translation, rotation: R, scaling: N) -> Self { Self::from_isometry(Isometry::from_parts(translation, rotation), scaling) } @@ -119,10 +110,7 @@ where "The scaling factor must not be zero." ); - Self { - isometry: isometry, - scaling: scaling, - } + Self { isometry, scaling } } /// Creates a new similarity that applies only a scaling factor. @@ -351,13 +339,14 @@ where DefaultAllocator: Allocator impl Eq for Similarity where - R: Rotation> + Eq, + R: AbstractRotation + Eq, DefaultAllocator: Allocator, -{} +{ +} impl PartialEq for Similarity where - R: Rotation> + PartialEq, + R: AbstractRotation + PartialEq, DefaultAllocator: Allocator, { #[inline] @@ -368,7 +357,7 @@ where impl AbsDiffEq for Similarity where - R: Rotation> + AbsDiffEq, + R: AbstractRotation + AbsDiffEq, DefaultAllocator: Allocator, N::Epsilon: Copy, { @@ -388,7 +377,7 @@ where impl RelativeEq for Similarity where - R: Rotation> + RelativeEq, + R: AbstractRotation + RelativeEq, DefaultAllocator: Allocator, N::Epsilon: Copy, { @@ -415,7 +404,7 @@ where impl UlpsEq for Similarity where - R: Rotation> + UlpsEq, + R: AbstractRotation + UlpsEq, DefaultAllocator: Allocator, N::Epsilon: Copy, { @@ -439,7 +428,7 @@ where impl fmt::Display for Similarity where N: RealField + fmt::Display, - R: Rotation> + fmt::Display, + R: AbstractRotation + fmt::Display, DefaultAllocator: Allocator + Allocator, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { diff --git a/src/geometry/similarity_alga.rs b/src/geometry/similarity_alga.rs deleted file mode 100755 index c3df94c1..00000000 --- a/src/geometry/similarity_alga.rs +++ /dev/null @@ -1,189 +0,0 @@ -use alga::general::{ - AbstractGroup, AbstractLoop, AbstractMagma, AbstractMonoid, AbstractQuasigroup, - AbstractSemigroup, Identity, TwoSidedInverse, Multiplicative, RealField, -}; -use alga::linear::Similarity as AlgaSimilarity; -use alga::linear::{AffineTransformation, ProjectiveTransformation, Rotation, Transformation}; - -use crate::base::allocator::Allocator; -use crate::base::dimension::DimName; -use crate::base::{DefaultAllocator, VectorN}; - -use crate::geometry::{Point, Similarity, Translation}; - -/* - * - * Algebraic structures. - * - */ -impl Identity for Similarity -where - R: Rotation>, - DefaultAllocator: Allocator, -{ - #[inline] - fn identity() -> Self { - Self::identity() - } -} - -impl TwoSidedInverse for Similarity -where - R: Rotation>, - DefaultAllocator: Allocator, -{ - #[inline] - #[must_use = "Did you mean to use two_sided_inverse_mut()?"] - fn two_sided_inverse(&self) -> Self { - self.inverse() - } - - #[inline] - fn two_sided_inverse_mut(&mut self) { - self.inverse_mut() - } -} - -impl AbstractMagma for Similarity -where - R: Rotation>, - DefaultAllocator: Allocator, -{ - #[inline] - fn operate(&self, rhs: &Self) -> Self { - self * rhs - } -} - -macro_rules! impl_multiplicative_structures( - ($($marker: ident<$operator: ident>),* $(,)*) => {$( - impl $marker<$operator> for Similarity - where R: Rotation>, - DefaultAllocator: Allocator { } - )*} -); - -impl_multiplicative_structures!( - AbstractSemigroup, - AbstractMonoid, - AbstractQuasigroup, - AbstractLoop, - AbstractGroup -); - -/* - * - * Transformation groups. - * - */ -impl Transformation> for Similarity -where - R: Rotation>, - DefaultAllocator: Allocator, -{ - #[inline] - fn transform_point(&self, pt: &Point) -> Point { - self.transform_point(pt) - } - - #[inline] - fn transform_vector(&self, v: &VectorN) -> VectorN { - self.transform_vector(v) - } -} - -impl ProjectiveTransformation> for Similarity -where - R: Rotation>, - DefaultAllocator: Allocator, -{ - #[inline] - fn inverse_transform_point(&self, pt: &Point) -> Point { - self.inverse_transform_point(pt) - } - - #[inline] - fn inverse_transform_vector(&self, v: &VectorN) -> VectorN { - self.inverse_transform_vector(v) - } -} - -impl AffineTransformation> for Similarity -where - R: Rotation>, - DefaultAllocator: Allocator, -{ - type NonUniformScaling = N; - type Rotation = R; - type Translation = Translation; - - #[inline] - fn decompose(&self) -> (Translation, R, N, R) { - ( - self.isometry.translation.clone(), - self.isometry.rotation.clone(), - self.scaling(), - R::identity(), - ) - } - - #[inline] - fn append_translation(&self, t: &Self::Translation) -> Self { - t * self - } - - #[inline] - fn prepend_translation(&self, t: &Self::Translation) -> Self { - self * t - } - - #[inline] - fn append_rotation(&self, r: &Self::Rotation) -> Self { - Similarity::from_isometry(self.isometry.append_rotation(r), self.scaling()) - } - - #[inline] - fn prepend_rotation(&self, r: &Self::Rotation) -> Self { - self * r - } - - #[inline] - fn append_scaling(&self, s: &Self::NonUniformScaling) -> Self { - self.append_scaling(*s) - } - - #[inline] - fn prepend_scaling(&self, s: &Self::NonUniformScaling) -> Self { - self.prepend_scaling(*s) - } - - #[inline] - fn append_rotation_wrt_point(&self, r: &Self::Rotation, p: &Point) -> Option { - let mut res = self.clone(); - res.append_rotation_wrt_point_mut(r, p); - Some(res) - } -} - -impl AlgaSimilarity> for Similarity -where - R: Rotation>, - DefaultAllocator: Allocator, -{ - type Scaling = N; - - #[inline] - fn translation(&self) -> Translation { - self.isometry.translation() - } - - #[inline] - fn rotation(&self) -> R { - self.isometry.rotation() - } - - #[inline] - fn scaling(&self) -> N { - self.scaling() - } -} diff --git a/src/geometry/similarity_construction.rs b/src/geometry/similarity_construction.rs index a3722ba9..f71f60dc 100644 --- a/src/geometry/similarity_construction.rs +++ b/src/geometry/similarity_construction.rs @@ -7,21 +7,20 @@ use num::One; use rand::distributions::{Distribution, Standard}; use rand::Rng; -use alga::general::RealField; -use alga::linear::Rotation as AlgaRotation; +use simba::scalar::RealField; use crate::base::allocator::Allocator; use crate::base::dimension::{DimName, U2, U3}; use crate::base::{DefaultAllocator, Vector2, Vector3}; use crate::geometry::{ - Isometry, Point, Point3, Rotation2, Rotation3, Similarity, Translation, UnitComplex, - UnitQuaternion, + AbstractRotation, Isometry, Point, Point3, Rotation2, Rotation3, Similarity, Translation, + UnitComplex, UnitQuaternion, }; impl Similarity where - R: AlgaRotation>, + R: AbstractRotation, DefaultAllocator: Allocator, { /// Creates a new identity similarity. @@ -47,7 +46,7 @@ where impl One for Similarity where - R: AlgaRotation>, + R: AbstractRotation, DefaultAllocator: Allocator, { /// Creates a new identity similarity. @@ -59,7 +58,7 @@ where impl Distribution> for Standard where - R: AlgaRotation>, + R: AbstractRotation, DefaultAllocator: Allocator, Standard: Distribution + Distribution, { @@ -76,7 +75,7 @@ where impl Similarity where - R: AlgaRotation>, + R: AbstractRotation, DefaultAllocator: Allocator, { /// The similarity that applies the scaling factor `scaling`, followed by the rotation `r` with @@ -105,7 +104,7 @@ where impl Arbitrary for Similarity where N: RealField + Arbitrary + Send, - R: AlgaRotation> + Arbitrary + Send, + R: AbstractRotation + Arbitrary + Send, DefaultAllocator: Allocator, Owned: Send, { diff --git a/src/geometry/similarity_conversion.rs b/src/geometry/similarity_conversion.rs index a0d207e4..6b0adb27 100644 --- a/src/geometry/similarity_conversion.rs +++ b/src/geometry/similarity_conversion.rs @@ -1,11 +1,12 @@ -use alga::general::{RealField, SubsetOf, SupersetOf}; -use alga::linear::Rotation; +use simba::scalar::{RealField, SubsetOf, SupersetOf}; use crate::base::allocator::Allocator; use crate::base::dimension::{DimMin, DimName, DimNameAdd, DimNameSum, U1}; use crate::base::{DefaultAllocator, MatrixN}; -use crate::geometry::{Isometry, Point, Similarity, SuperTCategoryOf, TAffine, Transform, Translation}; +use crate::geometry::{ + AbstractRotation, Isometry, Similarity, SuperTCategoryOf, TAffine, Transform, Translation, +}; /* * This file provides the following conversions: @@ -20,8 +21,8 @@ impl SubsetOf> for Similarity< where N1: RealField + SubsetOf, N2: RealField + SupersetOf, - R1: Rotation> + SubsetOf, - R2: Rotation>, + R1: AbstractRotation + SubsetOf, + R2: AbstractRotation, DefaultAllocator: Allocator + Allocator, { #[inline] @@ -36,7 +37,7 @@ where } #[inline] - unsafe fn from_superset_unchecked(sim: &Similarity) -> Self { + fn from_superset_unchecked(sim: &Similarity) -> Self { Similarity::from_isometry( sim.isometry.to_subset_unchecked(), sim.scaling().to_subset_unchecked(), @@ -49,7 +50,7 @@ where N1: RealField, N2: RealField + SupersetOf, C: SuperTCategoryOf, - R: Rotation> + R: AbstractRotation + SubsetOf>> + SubsetOf>>, D: DimNameAdd + DimMin, // needed by .determinant() @@ -73,7 +74,7 @@ where } #[inline] - unsafe fn from_superset_unchecked(t: &Transform) -> Self { + fn from_superset_unchecked(t: &Transform) -> Self { Self::from_superset_unchecked(t.matrix()) } } @@ -82,7 +83,7 @@ impl SubsetOf>> for Similarity, - R: Rotation> + R: AbstractRotation + SubsetOf>> + SubsetOf>>, D: DimNameAdd + DimMin, // needed by .determinant() @@ -137,7 +138,7 @@ where } #[inline] - unsafe fn from_superset_unchecked(m: &MatrixN>) -> Self { + fn from_superset_unchecked(m: &MatrixN>) -> Self { let mut mm = m.clone_owned(); let na = mm.fixed_slice_mut::(0, 0).normalize_mut(); let nb = mm.fixed_slice_mut::(0, 1).normalize_mut(); @@ -159,7 +160,11 @@ where vector: crate::convert_unchecked(t), }; - Self::from_parts(t, crate::convert_unchecked(mm), crate::convert_unchecked(scale)) + Self::from_parts( + t, + crate::convert_unchecked(mm), + crate::convert_unchecked(scale), + ) } } diff --git a/src/geometry/similarity_ops.rs b/src/geometry/similarity_ops.rs index 80d84b86..f34b13b9 100644 --- a/src/geometry/similarity_ops.rs +++ b/src/geometry/similarity_ops.rs @@ -1,13 +1,15 @@ +use num::{One, Zero}; use std::ops::{Div, DivAssign, Mul, MulAssign}; -use alga::general::RealField; -use alga::linear::Rotation as AlgaRotation; +use simba::scalar::{ClosedAdd, ClosedMul, RealField}; use crate::base::allocator::Allocator; use crate::base::dimension::{DimName, U1, U3, U4}; -use crate::base::{DefaultAllocator, VectorN}; +use crate::base::{DefaultAllocator, Scalar, VectorN}; -use crate::geometry::{Isometry, Point, Rotation, Similarity, Translation, UnitQuaternion}; +use crate::geometry::{ + AbstractRotation, Isometry, Point, Rotation, Similarity, Translation, UnitQuaternion, +}; // FIXME: there are several cloning of rotations that we could probably get rid of (but we didn't // yet because that would require to add a bound like `where for<'a, 'b> &'a R: Mul<&'b R, Output = R>` @@ -67,7 +69,7 @@ macro_rules! similarity_binop_impl( $lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty, Output = $Output: ty; $action: expr; $($lives: tt),*) => { impl<$($lives ,)* N: RealField, D: DimName, R> $Op<$Rhs> for $Lhs - where R: AlgaRotation>, + where R: AbstractRotation, DefaultAllocator: Allocator { type Output = $Output; @@ -114,7 +116,7 @@ macro_rules! similarity_binop_assign_impl_all( [val] => $action_val: expr; [ref] => $action_ref: expr;) => { impl $OpAssign<$Rhs> for $Lhs - where R: AlgaRotation>, + where R: AbstractRotation, DefaultAllocator: Allocator { #[inline] fn $op_assign(&mut $lhs, $rhs: $Rhs) { @@ -123,7 +125,7 @@ macro_rules! similarity_binop_assign_impl_all( } impl<'b, N: RealField, D: DimName, R> $OpAssign<&'b $Rhs> for $Lhs - where R: AlgaRotation>, + where R: AbstractRotation, DefaultAllocator: Allocator { #[inline] fn $op_assign(&mut $lhs, $rhs: &'b $Rhs) { @@ -211,51 +213,38 @@ similarity_binop_assign_impl_all!( // Similarity ×= R // Similarity ÷= R -similarity_binop_assign_impl_all!( - MulAssign, mul_assign; - self: Similarity, rhs: R; +md_assign_impl_all!( + MulAssign, mul_assign where N: RealField; + (D, U1), (D, D) for D: DimName; + self: Similarity>, rhs: Rotation; [val] => self.isometry.rotation *= rhs; [ref] => self.isometry.rotation *= rhs.clone(); ); -similarity_binop_assign_impl_all!( - DivAssign, div_assign; - self: Similarity, rhs: R; +md_assign_impl_all!( + DivAssign, div_assign where N: RealField; + (D, U1), (D, D) for D: DimName; + self: Similarity>, rhs: Rotation; // FIXME: don't invert explicitly? - [val] => *self *= rhs.two_sided_inverse(); - [ref] => *self *= rhs.two_sided_inverse(); + [val] => *self *= rhs.inverse(); + [ref] => *self *= rhs.inverse(); ); -// Similarity × R -// Similarity ÷ R -similarity_binop_impl_all!( - Mul, mul; - self: Similarity, rhs: R, Output = Similarity; - [val val] => { - let scaling = self.scaling(); - Similarity::from_isometry(self.isometry * rhs, scaling) - }; - [ref val] => Similarity::from_isometry(&self.isometry * rhs, self.scaling()); - [val ref] => { - let scaling = self.scaling(); - Similarity::from_isometry(self.isometry * rhs, scaling) - }; - [ref ref] => Similarity::from_isometry(&self.isometry * rhs, self.scaling()); +md_assign_impl_all!( + MulAssign, mul_assign where N: RealField; + (U3, U3), (U3, U3) for; + self: Similarity>, rhs: UnitQuaternion; + [val] => self.isometry.rotation *= rhs; + [ref] => self.isometry.rotation *= rhs.clone(); ); -similarity_binop_impl_all!( - Div, div; - self: Similarity, rhs: R, Output = Similarity; - [val val] => { - let scaling = self.scaling(); - Similarity::from_isometry(self.isometry / rhs, scaling) - }; - [ref val] => Similarity::from_isometry(&self.isometry / rhs, self.scaling()); - [val ref] => { - let scaling = self.scaling(); - Similarity::from_isometry(self.isometry / rhs, scaling) - }; - [ref ref] => Similarity::from_isometry(&self.isometry / rhs, self.scaling()); +md_assign_impl_all!( + DivAssign, div_assign where N: RealField; + (U3, U3), (U3, U3) for; + self: Similarity>, rhs: UnitQuaternion; + // FIXME: don't invert explicitly? + [val] => *self *= rhs.inverse(); + [ref] => *self *= rhs.inverse(); ); // Similarity × Isometry @@ -427,6 +416,24 @@ macro_rules! similarity_from_composition_impl_all( } ); +// Similarity × Rotation +similarity_from_composition_impl_all!( + Mul, mul; + (D, D), (D, U1) for D: DimName; + self: Similarity>, rhs: Rotation, + Output = Similarity>; + [val val] => { + let scaling = self.scaling(); + Similarity::from_isometry(self.isometry * rhs, scaling) + }; + [ref val] => Similarity::from_isometry(&self.isometry * rhs, self.scaling()); + [val ref] => { + let scaling = self.scaling(); + Similarity::from_isometry(self.isometry * rhs, scaling) + }; + [ref ref] => Similarity::from_isometry(&self.isometry * rhs, self.scaling()); +); + // Rotation × Similarity similarity_from_composition_impl_all!( Mul, mul; @@ -439,6 +446,24 @@ similarity_from_composition_impl_all!( [ref ref] => Similarity::from_isometry(self * &right.isometry, right.scaling()); ); +// Similarity ÷ Rotation +similarity_from_composition_impl_all!( + Div, div; + (D, D), (D, U1) for D: DimName; + self: Similarity>, rhs: Rotation, + Output = Similarity>; + [val val] => { + let scaling = self.scaling(); + Similarity::from_isometry(self.isometry / rhs, scaling) + }; + [ref val] => Similarity::from_isometry(&self.isometry / rhs, self.scaling()); + [val ref] => { + let scaling = self.scaling(); + Similarity::from_isometry(self.isometry / rhs, scaling) + }; + [ref ref] => Similarity::from_isometry(&self.isometry / rhs, self.scaling()); +); + // Rotation ÷ Similarity similarity_from_composition_impl_all!( Div, div; @@ -452,6 +477,24 @@ similarity_from_composition_impl_all!( [ref ref] => self * right.inverse(); ); +// Similarity × UnitQuaternion +similarity_from_composition_impl_all!( + Mul, mul; + (U4, U1), (U3, U1); + self: Similarity>, rhs: UnitQuaternion, + Output = Similarity>; + [val val] => { + let scaling = self.scaling(); + Similarity::from_isometry(self.isometry * rhs, scaling) + }; + [ref val] => Similarity::from_isometry(&self.isometry * rhs, self.scaling()); + [val ref] => { + let scaling = self.scaling(); + Similarity::from_isometry(self.isometry * rhs, scaling) + }; + [ref ref] => Similarity::from_isometry(&self.isometry * rhs, self.scaling()); +); + // UnitQuaternion × Similarity similarity_from_composition_impl_all!( Mul, mul; @@ -464,6 +507,24 @@ similarity_from_composition_impl_all!( [ref ref] => Similarity::from_isometry(self * &right.isometry, right.scaling()); ); +// Similarity ÷ Rotation +similarity_from_composition_impl_all!( + Div, div; + (U4, U1), (U3, U1); + self: Similarity>, rhs: UnitQuaternion, + Output = Similarity>; + [val val] => { + let scaling = self.scaling(); + Similarity::from_isometry(self.isometry / rhs, scaling) + }; + [ref val] => Similarity::from_isometry(&self.isometry / rhs, self.scaling()); + [val ref] => { + let scaling = self.scaling(); + Similarity::from_isometry(self.isometry / rhs, scaling) + }; + [ref ref] => Similarity::from_isometry(&self.isometry / rhs, self.scaling()); +); + // UnitQuaternion ÷ Similarity similarity_from_composition_impl_all!( Div, div; diff --git a/src/geometry/similarity_simba.rs b/src/geometry/similarity_simba.rs new file mode 100755 index 00000000..e05ec213 --- /dev/null +++ b/src/geometry/similarity_simba.rs @@ -0,0 +1,65 @@ +use simba::simd::SimdValue; + +use crate::base::allocator::Allocator; +use crate::base::dimension::DimName; +use crate::base::{DefaultAllocator, Scalar}; +use crate::RealField; + +use crate::geometry::{AbstractRotation, Isometry, Similarity}; + +impl SimdValue for Similarity +where + N::Element: Scalar, + R: SimdValue + AbstractRotation, + R::Element: AbstractRotation, + DefaultAllocator: Allocator, +{ + type Element = Similarity; + type SimdBool = N::SimdBool; + + #[inline] + fn lanes() -> usize { + N::lanes() + } + + #[inline] + fn splat(val: Self::Element) -> Self { + let scaling = N::splat(val.scaling()); + Similarity::from_isometry(Isometry::splat(val.isometry), scaling) + } + + #[inline] + fn extract(&self, i: usize) -> Self::Element { + Similarity::from_isometry(self.isometry.extract(i), self.scaling().extract(i)) + } + + #[inline] + unsafe fn extract_unchecked(&self, i: usize) -> Self::Element { + Similarity::from_isometry( + self.isometry.extract_unchecked(i), + self.scaling().extract_unchecked(i), + ) + } + + #[inline] + fn replace(&mut self, i: usize, val: Self::Element) { + let mut s = self.scaling(); + s.replace(i, val.scaling()); + self.set_scaling(s); + self.isometry.replace(i, val.isometry); + } + + #[inline] + unsafe fn replace_unchecked(&mut self, i: usize, val: Self::Element) { + let mut s = self.scaling(); + s.replace_unchecked(i, val.scaling()); + self.set_scaling(s); + self.isometry.replace_unchecked(i, val.isometry); + } + + #[inline] + fn select(self, cond: Self::SimdBool, other: Self) -> Self { + let scaling = self.scaling().select(cond, other.scaling()); + Similarity::from_isometry(self.isometry.select(cond, other.isometry), scaling) + } +} diff --git a/src/geometry/transform.rs b/src/geometry/transform.rs index a8570c9d..b7d47f0a 100755 --- a/src/geometry/transform.rs +++ b/src/geometry/transform.rs @@ -6,7 +6,7 @@ use std::marker::PhantomData; #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use alga::general::{RealField, TwoSidedInverse}; +use simba::scalar::RealField; use crate::base::allocator::Allocator; use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; @@ -259,7 +259,7 @@ where DefaultAllocator: Allocator, DimNameSum> /// Retrieves the underlying matrix. /// Deprecated: Use [Transform::into_inner] instead. - #[deprecated(note="use `.into_inner()` instead")] + #[deprecated(note = "use `.into_inner()` instead")] #[inline] pub fn unwrap(self) -> MatrixN> { self.matrix @@ -484,8 +484,9 @@ where } impl, C: TCategory> Transform -where C: SubTCategoryOf, - DefaultAllocator: Allocator, DimNameSum> +where + C: SubTCategoryOf, + DefaultAllocator: Allocator, DimNameSum> + Allocator> + Allocator + Allocator, @@ -495,7 +496,7 @@ where C: SubTCategoryOf, /// the point. #[inline] pub fn inverse_transform_point(&self, pt: &Point) -> Point { - self.two_sided_inverse() * pt + self.clone().inverse() * pt } /// Transform the given vector by the inverse of this transformation. @@ -503,7 +504,7 @@ where C: SubTCategoryOf, /// the vector. #[inline] pub fn inverse_transform_vector(&self, v: &VectorN) -> VectorN { - self.two_sided_inverse() * v + self.clone().inverse() * v } } diff --git a/src/geometry/transform_alga.rs b/src/geometry/transform_alga.rs deleted file mode 100755 index 65fbb32f..00000000 --- a/src/geometry/transform_alga.rs +++ /dev/null @@ -1,146 +0,0 @@ -use alga::general::{ - AbstractGroup, AbstractLoop, AbstractMagma, AbstractMonoid, AbstractQuasigroup, - AbstractSemigroup, Identity, TwoSidedInverse, Multiplicative, RealField, -}; -use alga::linear::{ProjectiveTransformation, Transformation}; - -use crate::base::allocator::Allocator; -use crate::base::dimension::{DimNameAdd, DimNameSum, U1}; -use crate::base::{DefaultAllocator, VectorN}; - -use crate::geometry::{Point, SubTCategoryOf, TCategory, TProjective, Transform}; - -/* - * - * Algebraic structures. - * - */ -impl, C> Identity for Transform -where - C: TCategory, - DefaultAllocator: Allocator, DimNameSum>, -{ - #[inline] - fn identity() -> Self { - Self::identity() - } -} - -impl, C> TwoSidedInverse for Transform -where - C: SubTCategoryOf, - DefaultAllocator: Allocator, DimNameSum>, -{ - #[inline] - #[must_use = "Did you mean to use two_sided_inverse_mut()?"] - fn two_sided_inverse(&self) -> Self { - self.clone().inverse() - } - - #[inline] - fn two_sided_inverse_mut(&mut self) { - self.inverse_mut() - } -} - -impl, C> AbstractMagma for Transform -where - C: TCategory, - DefaultAllocator: Allocator, DimNameSum>, -{ - #[inline] - fn operate(&self, rhs: &Self) -> Self { - self * rhs - } -} - -macro_rules! impl_multiplicative_structures( - ($($marker: ident<$operator: ident>),* $(,)*) => {$( - impl, C> $marker<$operator> for Transform - where C: TCategory, - DefaultAllocator: Allocator, DimNameSum> { } - )*} -); - -macro_rules! impl_inversible_multiplicative_structures( - ($($marker: ident<$operator: ident>),* $(,)*) => {$( - impl, C> $marker<$operator> for Transform - where C: SubTCategoryOf, - DefaultAllocator: Allocator, DimNameSum> { } - )*} -); - -impl_multiplicative_structures!( - AbstractSemigroup, - AbstractMonoid, -); - -impl_inversible_multiplicative_structures!( - AbstractQuasigroup, - AbstractLoop, - AbstractGroup -); - -/* - * - * Transformation groups. - * - */ -impl, C> Transformation> for Transform -where - N: RealField, - C: TCategory, - DefaultAllocator: Allocator, DimNameSum> - + Allocator> - + Allocator - + Allocator, -{ - #[inline] - fn transform_point(&self, pt: &Point) -> Point { - self.transform_point(pt) - } - - #[inline] - fn transform_vector(&self, v: &VectorN) -> VectorN { - self.transform_vector(v) - } -} - -impl, C> ProjectiveTransformation> for Transform -where - N: RealField, - C: SubTCategoryOf, - DefaultAllocator: Allocator, DimNameSum> - + Allocator> - + Allocator - + Allocator, -{ - #[inline] - fn inverse_transform_point(&self, pt: &Point) -> Point { - self.inverse_transform_point(pt) - } - - #[inline] - fn inverse_transform_vector(&self, v: &VectorN) -> VectorN { - self.inverse_transform_vector(v) - } -} - -// FIXME: we need to implement an SVD for this. -// -// impl, C> AffineTransformation> for Transform -// where N: RealField, -// C: SubTCategoryOf, -// DefaultAllocator: Allocator, DimNameSum> + -// Allocator + -// Allocator { -// type PreRotation = Rotation; -// type NonUniformScaling = VectorN; -// type PostRotation = Rotation; -// type Translation = Translation; -// -// #[inline] -// fn decompose(&self) -> (Self::Translation, Self::PostRotation, Self::NonUniformScaling, Self::PreRotation) { -// unimplemented!() -// } -// } diff --git a/src/geometry/transform_construction.rs b/src/geometry/transform_construction.rs index 1b23daba..85fe6676 100644 --- a/src/geometry/transform_construction.rs +++ b/src/geometry/transform_construction.rs @@ -1,6 +1,6 @@ use num::One; -use alga::general::RealField; +use simba::scalar::RealField; use crate::base::allocator::Allocator; use crate::base::dimension::{DimNameAdd, DimNameSum, U1}; diff --git a/src/geometry/transform_conversion.rs b/src/geometry/transform_conversion.rs index a0e00291..6c531f84 100644 --- a/src/geometry/transform_conversion.rs +++ b/src/geometry/transform_conversion.rs @@ -1,4 +1,4 @@ -use alga::general::{RealField, SubsetOf}; +use simba::scalar::{RealField, SubsetOf}; use crate::base::allocator::Allocator; use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; @@ -29,7 +29,7 @@ where } #[inline] - unsafe fn from_superset_unchecked(t: &Transform) -> Self { + fn from_superset_unchecked(t: &Transform) -> Self { Self::from_superset_unchecked(t.matrix()) } } @@ -56,7 +56,7 @@ where } #[inline] - unsafe fn from_superset_unchecked(m: &MatrixN>) -> Self { + fn from_superset_unchecked(m: &MatrixN>) -> Self { Self::from_matrix_unchecked(crate::convert_ref_unchecked(m)) } } diff --git a/src/geometry/transform_ops.rs b/src/geometry/transform_ops.rs index 4aa943e8..5773782c 100644 --- a/src/geometry/transform_ops.rs +++ b/src/geometry/transform_ops.rs @@ -1,7 +1,7 @@ use num::{One, Zero}; use std::ops::{Div, DivAssign, Index, IndexMut, Mul, MulAssign}; -use alga::general::{ClosedAdd, ClosedMul, RealField, SubsetOf}; +use simba::scalar::{ClosedAdd, ClosedMul, RealField, SubsetOf}; use crate::base::allocator::Allocator; use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1, U3, U4}; diff --git a/src/geometry/transform_simba.rs b/src/geometry/transform_simba.rs new file mode 100755 index 00000000..d50843f4 --- /dev/null +++ b/src/geometry/transform_simba.rs @@ -0,0 +1,55 @@ +use simba::simd::SimdValue; + +use crate::base::allocator::Allocator; +use crate::base::dimension::{DimNameAdd, DimNameSum, U1}; +use crate::base::{DefaultAllocator, MatrixN, Scalar}; +use crate::RealField; + +use crate::geometry::{TCategory, Transform}; + +impl, C> SimdValue for Transform +where + N::Element: Scalar, + C: TCategory, + DefaultAllocator: Allocator, DimNameSum> + + Allocator, DimNameSum>, +{ + type Element = Transform; + type SimdBool = N::SimdBool; + + #[inline] + fn lanes() -> usize { + N::lanes() + } + + #[inline] + fn splat(val: Self::Element) -> Self { + Transform::from_matrix_unchecked(MatrixN::splat(val.into_inner())) + } + + #[inline] + fn extract(&self, i: usize) -> Self::Element { + Transform::from_matrix_unchecked(self.matrix().extract(i)) + } + + #[inline] + unsafe fn extract_unchecked(&self, i: usize) -> Self::Element { + Transform::from_matrix_unchecked(self.matrix().extract_unchecked(i)) + } + + #[inline] + fn replace(&mut self, i: usize, val: Self::Element) { + self.matrix_mut_unchecked().replace(i, val.into_inner()) + } + + #[inline] + unsafe fn replace_unchecked(&mut self, i: usize, val: Self::Element) { + self.matrix_mut_unchecked() + .replace_unchecked(i, val.into_inner()) + } + + #[inline] + fn select(self, cond: Self::SimdBool, other: Self) -> Self { + Transform::from_matrix_unchecked(self.into_inner().select(cond, other.into_inner())) + } +} diff --git a/src/geometry/translation.rs b/src/geometry/translation.rs index 5b907f3a..e82ecaaa 100755 --- a/src/geometry/translation.rs +++ b/src/geometry/translation.rs @@ -11,7 +11,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; #[cfg(feature = "abomonation-serialize")] use abomonation::Abomonation; -use alga::general::{ClosedAdd, ClosedNeg, ClosedSub, RealField}; +use simba::scalar::{ClosedAdd, ClosedNeg, ClosedSub, RealField}; use crate::base::allocator::Allocator; use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; @@ -45,7 +45,8 @@ impl Copy for Translation where DefaultAllocator: Allocator, Owned: Copy, -{} +{ +} impl Clone for Translation where @@ -302,7 +303,7 @@ where * Display * */ -impl fmt::Display for Translation +impl fmt::Display for Translation where DefaultAllocator: Allocator + Allocator { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { diff --git a/src/geometry/translation_alga.rs b/src/geometry/translation_alga.rs index 7add6438..c439a5d2 100755 --- a/src/geometry/translation_alga.rs +++ b/src/geometry/translation_alga.rs @@ -1,199 +1,52 @@ -use alga::general::{ - AbstractGroup, AbstractLoop, AbstractMagma, AbstractMonoid, AbstractQuasigroup, - AbstractSemigroup, Id, Identity, TwoSidedInverse, Multiplicative, RealField, -}; -use alga::linear::Translation as AlgaTranslation; -use alga::linear::{ - AffineTransformation, DirectIsometry, Isometry, ProjectiveTransformation, Similarity, - Transformation, -}; +use simba::simd::SimdValue; use crate::base::allocator::Allocator; use crate::base::dimension::DimName; use crate::base::{DefaultAllocator, VectorN}; +use crate::Scalar; -use crate::geometry::{Point, Translation}; +use crate::geometry::Translation; -/* - * - * Algebraic structures. - * - */ -impl Identity for Translation -where DefaultAllocator: Allocator +impl SimdValue for Translation +where + N::Element: Scalar, + DefaultAllocator: Allocator + Allocator, { + type Element = Translation; + type SimdBool = N::SimdBool; + #[inline] - fn identity() -> Self { - Self::identity() - } -} - -impl TwoSidedInverse for Translation -where DefaultAllocator: Allocator -{ - #[inline] - #[must_use = "Did you mean to use two_sided_inverse_mut()?"] - fn two_sided_inverse(&self) -> Self { - self.inverse() - } - - #[inline] - fn two_sided_inverse_mut(&mut self) { - self.inverse_mut() - } -} - -impl AbstractMagma for Translation -where DefaultAllocator: Allocator -{ - #[inline] - fn operate(&self, rhs: &Self) -> Self { - self * rhs - } -} - -macro_rules! impl_multiplicative_structures( - ($($marker: ident<$operator: ident>),* $(,)*) => {$( - impl $marker<$operator> for Translation - where DefaultAllocator: Allocator { } - )*} -); - -impl_multiplicative_structures!( - AbstractSemigroup, - AbstractMonoid, - AbstractQuasigroup, - AbstractLoop, - AbstractGroup -); - -/* - * - * Transformation groups. - * - */ -impl Transformation> for Translation -where DefaultAllocator: Allocator -{ - #[inline] - fn transform_point(&self, pt: &Point) -> Point { - self.transform_point(pt) - } - - #[inline] - fn transform_vector(&self, v: &VectorN) -> VectorN { - v.clone() - } -} - -impl ProjectiveTransformation> for Translation -where DefaultAllocator: Allocator -{ - #[inline] - fn inverse_transform_point(&self, pt: &Point) -> Point { - self.inverse_transform_point(pt) - } - - #[inline] - fn inverse_transform_vector(&self, v: &VectorN) -> VectorN { - v.clone() - } -} - -impl AffineTransformation> for Translation -where DefaultAllocator: Allocator -{ - type Rotation = Id; - type NonUniformScaling = Id; - type Translation = Self; - - #[inline] - fn decompose(&self) -> (Self, Id, Id, Id) { - (self.clone(), Id::new(), Id::new(), Id::new()) - } - - #[inline] - fn append_translation(&self, t: &Self::Translation) -> Self { - t * self - } - - #[inline] - fn prepend_translation(&self, t: &Self::Translation) -> Self { - self * t - } - - #[inline] - fn append_rotation(&self, _: &Self::Rotation) -> Self { - self.clone() - } - - #[inline] - fn prepend_rotation(&self, _: &Self::Rotation) -> Self { - self.clone() - } - - #[inline] - fn append_scaling(&self, _: &Self::NonUniformScaling) -> Self { - self.clone() - } - - #[inline] - fn prepend_scaling(&self, _: &Self::NonUniformScaling) -> Self { - self.clone() - } -} - -impl Similarity> for Translation -where DefaultAllocator: Allocator -{ - type Scaling = Id; - - #[inline] - fn translation(&self) -> Self { - self.clone() - } - - #[inline] - fn rotation(&self) -> Id { - Id::new() - } - - #[inline] - fn scaling(&self) -> Id { - Id::new() - } -} - -macro_rules! marker_impl( - ($($Trait: ident),*) => {$( - impl $Trait> for Translation - where DefaultAllocator: Allocator { } - )*} -); - -marker_impl!(Isometry, DirectIsometry); - -/// Subgroups of the n-dimensional translation group `T(n)`. -impl AlgaTranslation> for Translation -where DefaultAllocator: Allocator -{ - #[inline] - fn to_vector(&self) -> VectorN { - self.vector.clone() - } - - #[inline] - fn from_vector(v: VectorN) -> Option { - Some(Self::from(v)) - } - - #[inline] - fn powf(&self, n: N) -> Option { - Some(Self::from(&self.vector * n)) - } - - #[inline] - fn translation_between(a: &Point, b: &Point) -> Option { - Some(Self::from(b - a)) + fn lanes() -> usize { + N::lanes() + } + + #[inline] + fn splat(val: Self::Element) -> Self { + VectorN::splat(val.vector).into() + } + + #[inline] + fn extract(&self, i: usize) -> Self::Element { + self.vector.extract(i).into() + } + + #[inline] + unsafe fn extract_unchecked(&self, i: usize) -> Self::Element { + self.vector.extract_unchecked(i).into() + } + + #[inline] + fn replace(&mut self, i: usize, val: Self::Element) { + self.vector.replace(i, val.vector) + } + + #[inline] + unsafe fn replace_unchecked(&mut self, i: usize, val: Self::Element) { + self.vector.replace_unchecked(i, val.vector) + } + + #[inline] + fn select(self, cond: Self::SimdBool, other: Self) -> Self { + self.vector.select(cond, other.vector).into() } } diff --git a/src/geometry/translation_construction.rs b/src/geometry/translation_construction.rs index 339bdd2a..18793721 100644 --- a/src/geometry/translation_construction.rs +++ b/src/geometry/translation_construction.rs @@ -7,7 +7,7 @@ use num::{One, Zero}; use rand::distributions::{Distribution, Standard}; use rand::Rng; -use alga::general::ClosedAdd; +use simba::scalar::ClosedAdd; use crate::base::allocator::Allocator; use crate::base::dimension::{DimName, U1, U2, U3, U4, U5, U6}; diff --git a/src/geometry/translation_conversion.rs b/src/geometry/translation_conversion.rs index b44412e6..a7368ed2 100644 --- a/src/geometry/translation_conversion.rs +++ b/src/geometry/translation_conversion.rs @@ -1,13 +1,14 @@ use num::{One, Zero}; -use alga::general::{RealField, SubsetOf, SupersetOf}; -use alga::linear::Rotation; +use simba::scalar::{RealField, SubsetOf, SupersetOf}; use crate::base::allocator::Allocator; use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; use crate::base::{DefaultAllocator, MatrixN, Scalar, VectorN}; -use crate::geometry::{Isometry, Point, Similarity, SuperTCategoryOf, TAffine, Transform, Translation}; +use crate::geometry::{ + AbstractRotation, Isometry, Similarity, SuperTCategoryOf, TAffine, Transform, Translation, +}; /* * This file provides the following conversions: @@ -37,7 +38,7 @@ where } #[inline] - unsafe fn from_superset_unchecked(rot: &Translation) -> Self { + fn from_superset_unchecked(rot: &Translation) -> Self { Translation { vector: rot.vector.to_subset_unchecked(), } @@ -48,7 +49,7 @@ impl SubsetOf> for Translation where N1: RealField, N2: RealField + SupersetOf, - R: Rotation>, + R: AbstractRotation, DefaultAllocator: Allocator + Allocator, { #[inline] @@ -62,7 +63,7 @@ where } #[inline] - unsafe fn from_superset_unchecked(iso: &Isometry) -> Self { + fn from_superset_unchecked(iso: &Isometry) -> Self { Self::from_superset_unchecked(&iso.translation) } } @@ -71,7 +72,7 @@ impl SubsetOf> for Translation, - R: Rotation>, + R: AbstractRotation, DefaultAllocator: Allocator + Allocator, { #[inline] @@ -85,7 +86,7 @@ where } #[inline] - unsafe fn from_superset_unchecked(sim: &Similarity) -> Self { + fn from_superset_unchecked(sim: &Similarity) -> Self { Self::from_superset_unchecked(&sim.isometry.translation) } } @@ -112,7 +113,7 @@ where } #[inline] - unsafe fn from_superset_unchecked(t: &Transform) -> Self { + fn from_superset_unchecked(t: &Transform) -> Self { Self::from_superset_unchecked(t.matrix()) } } @@ -145,7 +146,7 @@ where } #[inline] - unsafe fn from_superset_unchecked(m: &MatrixN>) -> Self { + fn from_superset_unchecked(m: &MatrixN>) -> Self { let t = m.fixed_slice::(0, D::dim()); Self { vector: crate::convert_unchecked(t.into_owned()), diff --git a/src/geometry/translation_ops.rs b/src/geometry/translation_ops.rs index 55366a05..c00b25bc 100644 --- a/src/geometry/translation_ops.rs +++ b/src/geometry/translation_ops.rs @@ -1,6 +1,6 @@ use std::ops::{Div, DivAssign, Mul, MulAssign}; -use alga::general::{ClosedAdd, ClosedSub}; +use simba::scalar::{ClosedAdd, ClosedSub}; use crate::base::allocator::{Allocator, SameShapeAllocator}; use crate::base::constraint::{SameNumberOfColumns, SameNumberOfRows, ShapeConstraint}; diff --git a/src/geometry/unit_complex.rs b/src/geometry/unit_complex.rs index d411d82a..2ed88378 100755 --- a/src/geometry/unit_complex.rs +++ b/src/geometry/unit_complex.rs @@ -2,13 +2,44 @@ use approx::{AbsDiffEq, RelativeEq, UlpsEq}; use num_complex::Complex; use std::fmt; -use alga::general::RealField; -use crate::base::{Matrix2, Matrix3, Unit, Vector1, Vector2}; -use crate::geometry::{Rotation2, Point2}; +use crate::base::{Matrix2, Matrix3, Normed, Unit, Vector1, Vector2}; +use crate::geometry::{Point2, Rotation2}; +use simba::scalar::RealField; +use simba::simd::SimdRealField; /// A complex number with a norm equal to 1. pub type UnitComplex = Unit>; +impl Normed for Complex { + type Norm = N::SimdRealField; + + #[inline] + fn norm(&self) -> N::SimdRealField { + // We don't use `.norm_sqr()` because it requires + // some very strong Num trait requirements. + (self.re * self.re + self.im * self.im).simd_sqrt() + } + + #[inline] + fn norm_squared(&self) -> N::SimdRealField { + // We don't use `.norm_sqr()` because it requires + // some very strong Num trait requirements. + self.re * self.re + self.im * self.im + } + + #[inline] + fn scale_mut(&mut self, n: Self::Norm) { + self.re *= n; + self.im *= n; + } + + #[inline] + fn unscale_mut(&mut self, n: Self::Norm) { + self.re /= n; + self.im /= n; + } +} + impl UnitComplex { /// The rotation angle in `]-pi; pi]` of this unit complex number. /// @@ -375,4 +406,4 @@ impl UlpsEq for UnitComplex { self.re.ulps_eq(&other.re, epsilon, max_ulps) && self.im.ulps_eq(&other.im, epsilon, max_ulps) } -} \ No newline at end of file +} diff --git a/src/geometry/unit_complex_alga.rs b/src/geometry/unit_complex_alga.rs deleted file mode 100755 index 94cfa6e1..00000000 --- a/src/geometry/unit_complex_alga.rs +++ /dev/null @@ -1,180 +0,0 @@ -use alga::general::{ - AbstractGroup, AbstractLoop, AbstractMagma, AbstractMonoid, AbstractQuasigroup, - AbstractSemigroup, Id, Identity, TwoSidedInverse, Multiplicative, RealField, -}; -use alga::linear::{ - AffineTransformation, DirectIsometry, Isometry, OrthogonalTransformation, - ProjectiveTransformation, Rotation, Similarity, Transformation, -}; - -use crate::base::allocator::Allocator; -use crate::base::dimension::U2; -use crate::base::{DefaultAllocator, Vector2}; -use crate::geometry::{Point2, UnitComplex}; - -/* - * - * Implementations for UnitComplex. - * - */ -impl Identity for UnitComplex { - #[inline] - fn identity() -> Self { - Self::identity() - } -} - -impl AbstractMagma for UnitComplex { - #[inline] - fn operate(&self, rhs: &Self) -> Self { - self * rhs - } -} - -impl TwoSidedInverse for UnitComplex { - #[inline] - #[must_use = "Did you mean to use two_sided_inverse_mut()?"] - fn two_sided_inverse(&self) -> Self { - self.inverse() - } - - #[inline] - fn two_sided_inverse_mut(&mut self) { - self.inverse_mut() - } -} - -macro_rules! impl_structures( - ($($marker: ident<$operator: ident>),* $(,)*) => {$( - impl $marker<$operator> for UnitComplex { - } - )*} -); - -impl_structures!( - AbstractSemigroup, - AbstractQuasigroup, - AbstractMonoid, - AbstractLoop, - AbstractGroup -); - -impl Transformation> for UnitComplex -where DefaultAllocator: Allocator -{ - #[inline] - fn transform_point(&self, pt: &Point2) -> Point2 { - self.transform_point(pt) - } - - #[inline] - fn transform_vector(&self, v: &Vector2) -> Vector2 { - self.transform_vector(v) - } -} - -impl ProjectiveTransformation> for UnitComplex -where DefaultAllocator: Allocator -{ - #[inline] - fn inverse_transform_point(&self, pt: &Point2) -> Point2 { - self.inverse_transform_point(pt) - } - - #[inline] - fn inverse_transform_vector(&self, v: &Vector2) -> Vector2 { - self.inverse_transform_vector(v) - } -} - -impl AffineTransformation> for UnitComplex -where DefaultAllocator: Allocator -{ - type Rotation = Self; - type NonUniformScaling = Id; - type Translation = Id; - - #[inline] - fn decompose(&self) -> (Id, Self, Id, Self) { - (Id::new(), self.clone(), Id::new(), Self::identity()) - } - - #[inline] - fn append_translation(&self, _: &Self::Translation) -> Self { - self.clone() - } - - #[inline] - fn prepend_translation(&self, _: &Self::Translation) -> Self { - self.clone() - } - - #[inline] - fn append_rotation(&self, r: &Self::Rotation) -> Self { - r * self - } - - #[inline] - fn prepend_rotation(&self, r: &Self::Rotation) -> Self { - self * r - } - - #[inline] - fn append_scaling(&self, _: &Self::NonUniformScaling) -> Self { - self.clone() - } - - #[inline] - fn prepend_scaling(&self, _: &Self::NonUniformScaling) -> Self { - self.clone() - } -} - -impl Similarity> for UnitComplex -where DefaultAllocator: Allocator -{ - type Scaling = Id; - - #[inline] - fn translation(&self) -> Id { - Id::new() - } - - #[inline] - fn rotation(&self) -> Self { - self.clone() - } - - #[inline] - fn scaling(&self) -> Id { - Id::new() - } -} - -macro_rules! marker_impl( - ($($Trait: ident),*) => {$( - impl $Trait> for UnitComplex - where DefaultAllocator: Allocator { } - )*} -); - -marker_impl!(Isometry, DirectIsometry, OrthogonalTransformation); - -impl Rotation> for UnitComplex -where DefaultAllocator: Allocator -{ - #[inline] - fn powf(&self, n: N) -> Option { - Some(self.powf(n)) - } - - #[inline] - fn rotation_between(a: &Vector2, b: &Vector2) -> Option { - Some(Self::rotation_between(a, b)) - } - - #[inline] - fn scaled_rotation_between(a: &Vector2, b: &Vector2, s: N) -> Option { - Some(Self::scaled_rotation_between(a, b, s)) - } -} diff --git a/src/geometry/unit_complex_construction.rs b/src/geometry/unit_complex_construction.rs index 046142c8..ce28ea74 100644 --- a/src/geometry/unit_complex_construction.rs +++ b/src/geometry/unit_complex_construction.rs @@ -6,11 +6,11 @@ use num_complex::Complex; use rand::distributions::{Distribution, OpenClosed01, Standard}; use rand::Rng; -use alga::general::RealField; use crate::base::dimension::{U1, U2}; use crate::base::storage::Storage; -use crate::base::{Unit, Vector, Matrix2}; +use crate::base::{Matrix2, Unit, Vector}; use crate::geometry::{Rotation2, UnitComplex}; +use simba::scalar::RealField; impl UnitComplex { /// The unit complex number multiplicative identity. diff --git a/src/geometry/unit_complex_conversion.rs b/src/geometry/unit_complex_conversion.rs index f7fe4532..bd442ee7 100644 --- a/src/geometry/unit_complex_conversion.rs +++ b/src/geometry/unit_complex_conversion.rs @@ -1,14 +1,13 @@ use num::Zero; use num_complex::Complex; -use alga::general::{RealField, SubsetOf, SupersetOf}; -use alga::linear::Rotation as AlgaRotation; +use simba::scalar::{RealField, SubsetOf, SupersetOf}; use crate::base::dimension::U2; use crate::base::{Matrix2, Matrix3}; use crate::geometry::{ - Isometry, Point2, Rotation2, Similarity, SuperTCategoryOf, TAffine, Transform, Translation, - UnitComplex + AbstractRotation, Isometry, Rotation2, Similarity, SuperTCategoryOf, TAffine, Transform, + Translation, UnitComplex, }; /* @@ -42,7 +41,7 @@ where } #[inline] - unsafe fn from_superset_unchecked(uq: &UnitComplex) -> Self { + fn from_superset_unchecked(uq: &UnitComplex) -> Self { Self::new_unchecked(crate::convert_ref_unchecked(uq.as_ref())) } } @@ -64,7 +63,7 @@ where } #[inline] - unsafe fn from_superset_unchecked(rot: &Rotation2) -> Self { + fn from_superset_unchecked(rot: &Rotation2) -> Self { let q = UnitComplex::::from_rotation_matrix(rot); crate::convert_unchecked(q) } @@ -74,7 +73,7 @@ impl SubsetOf> for UnitComplex where N1: RealField, N2: RealField + SupersetOf, - R: AlgaRotation> + SupersetOf, + R: AbstractRotation + SupersetOf, { #[inline] fn to_superset(&self) -> Isometry { @@ -87,7 +86,7 @@ where } #[inline] - unsafe fn from_superset_unchecked(iso: &Isometry) -> Self { + fn from_superset_unchecked(iso: &Isometry) -> Self { crate::convert_ref_unchecked(&iso.rotation) } } @@ -96,7 +95,7 @@ impl SubsetOf> for UnitComplex where N1: RealField, N2: RealField + SupersetOf, - R: AlgaRotation> + SupersetOf, + R: AbstractRotation + SupersetOf, { #[inline] fn to_superset(&self) -> Similarity { @@ -109,7 +108,7 @@ where } #[inline] - unsafe fn from_superset_unchecked(sim: &Similarity) -> Self { + fn from_superset_unchecked(sim: &Similarity) -> Self { crate::convert_ref_unchecked(&sim.isometry) } } @@ -131,7 +130,7 @@ where } #[inline] - unsafe fn from_superset_unchecked(t: &Transform) -> Self { + fn from_superset_unchecked(t: &Transform) -> Self { Self::from_superset_unchecked(t.matrix()) } } @@ -148,13 +147,12 @@ impl> SubsetOf> for Un } #[inline] - unsafe fn from_superset_unchecked(m: &Matrix3) -> Self { + fn from_superset_unchecked(m: &Matrix3) -> Self { let rot: Rotation2 = crate::convert_ref_unchecked(m); Self::from_rotation_matrix(&rot) } } - impl From> for Rotation2 { #[inline] fn from(q: UnitComplex) -> Self { diff --git a/src/geometry/unit_complex_ops.rs b/src/geometry/unit_complex_ops.rs index 11ffdc4a..43c97cd9 100644 --- a/src/geometry/unit_complex_ops.rs +++ b/src/geometry/unit_complex_ops.rs @@ -1,11 +1,11 @@ use std::ops::{Div, DivAssign, Mul, MulAssign}; -use alga::general::RealField; use crate::base::allocator::Allocator; use crate::base::dimension::{U1, U2}; use crate::base::storage::Storage; use crate::base::{DefaultAllocator, Unit, Vector, Vector2}; use crate::geometry::{Isometry, Point2, Rotation, Similarity, Translation, UnitComplex}; +use simba::scalar::RealField; /* * This file provides: @@ -403,4 +403,4 @@ where DefaultAllocator: Allocator fn div_assign(&mut self, rhs: &'b UnitComplex) { self.div_assign(rhs.to_rotation_matrix()) } -} \ No newline at end of file +} diff --git a/src/geometry/unit_complex_simba.rs b/src/geometry/unit_complex_simba.rs new file mode 100755 index 00000000..4784fa15 --- /dev/null +++ b/src/geometry/unit_complex_simba.rs @@ -0,0 +1,50 @@ +use num_complex::Complex; +use simba::simd::SimdValue; +use std::ops::Deref; + +use crate::base::{Scalar, Unit}; +use crate::geometry::UnitComplex; +use crate::RealField; + +impl SimdValue for UnitComplex +where N::Element: Scalar +{ + type Element = UnitComplex; + type SimdBool = N::SimdBool; + + #[inline] + fn lanes() -> usize { + N::lanes() + } + + #[inline] + fn splat(val: Self::Element) -> Self { + Unit::new_unchecked(Complex::splat(val.into_inner())) + } + + #[inline] + fn extract(&self, i: usize) -> Self::Element { + Unit::new_unchecked(self.deref().extract(i)) + } + + #[inline] + unsafe fn extract_unchecked(&self, i: usize) -> Self::Element { + Unit::new_unchecked(self.deref().extract_unchecked(i)) + } + + #[inline] + fn replace(&mut self, i: usize, val: Self::Element) { + self.as_mut_unchecked().replace(i, val.into_inner()) + } + + #[inline] + unsafe fn replace_unchecked(&mut self, i: usize, val: Self::Element) { + self.as_mut_unchecked() + .replace_unchecked(i, val.into_inner()) + } + + #[inline] + fn select(self, cond: Self::SimdBool, other: Self) -> Self { + Unit::new_unchecked(self.into_inner().select(cond, other.into_inner())) + } +} diff --git a/src/lib.rs b/src/lib.rs index 754ccdfb..5ecab6d6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -68,8 +68,6 @@ an optimized set of tools for computer graphics and physics. Those features incl * 3D projections for computer graphics: `Perspective3`, `Orthographic3`. * Matrix factorizations: `Cholesky`, `QR`, `LU`, `FullPivLU`, `SVD`, `Schur`, `Hessenberg`, `SymmetricEigen`. * Insertion and removal of rows of columns of a matrix. -* Implements traits from the [alga](https://crates.io/crates/alga) crate for - generic programming. */ // #![feature(plugin)] @@ -81,7 +79,7 @@ an optimized set of tools for computer graphics and physics. Those features incl #![deny(non_upper_case_globals)] #![deny(unused_qualifications)] #![deny(unused_results)] -#![deny(missing_docs)] +#![allow(missing_docs)] // XXX: deny that #![doc( html_favicon_url = "https://nalgebra.org/img/favicon.ico", html_root_url = "https://nalgebra.org/rustdoc" @@ -106,18 +104,11 @@ extern crate mint; #[macro_use] extern crate approx; -extern crate generic_array; #[cfg(feature = "std")] extern crate matrixmultiply; -extern crate num_complex; -extern crate num_rational; extern crate num_traits as num; -extern crate rand; #[cfg(feature = "std")] extern crate rand_distr; -extern crate typenum; - -extern crate alga; #[cfg(all(feature = "alloc", not(feature = "std")))] extern crate alloc; @@ -152,35 +143,17 @@ pub use crate::sparse::*; )] pub use base as core; +use simba::scalar::SupersetOf; use std::cmp::{self, Ordering, PartialOrd}; -use alga::general::{ - Additive, AdditiveGroup, Identity, JoinSemilattice, Lattice, MeetSemilattice, Multiplicative, - SupersetOf, TwoSidedInverse, -}; -use alga::linear::SquareMatrix as AlgaSquareMatrix; -use alga::linear::{EuclideanSpace, FiniteDimVectorSpace, InnerSpace, NormedSpace}; -use num::Signed; +use num::{One, Signed, Zero}; -#[allow(deprecated)] -pub use alga::general::Real; -pub use alga::general::{ComplexField, Id, RealField}; -pub use alga::simd::{SimdComplexField, SimdRealField}; +use base::allocator::Allocator; pub use num_complex::Complex; - -/* - * - * Multiplicative identity. - * - */ -/// Gets the ubiquitous multiplicative identity element. -/// -/// Same as `Id::new()`. -#[deprecated(note = "use `Id::new()` instead.")] -#[inline] -pub fn id() -> Id { - Id::new() -} +pub use simba::scalar::{ + ClosedAdd, ClosedDiv, ClosedMul, ClosedSub, ComplexField, Field, RealField, +}; +pub use simba::simd::{SimdBool, SimdComplexField, SimdRealField}; /// Gets the multiplicative identity element. /// @@ -189,8 +162,8 @@ pub fn id() -> Id { /// * [`origin`](../nalgebra/fn.origin.html) /// * [`zero`](fn.zero.html) #[inline] -pub fn one>() -> T { - T::identity() +pub fn one() -> T { + T::one() } /// Gets the additive identity element. @@ -200,36 +173,8 @@ pub fn one>() -> T { /// * [`one`](fn.one.html) /// * [`origin`](../nalgebra/fn.origin.html) #[inline] -pub fn zero>() -> T { - T::identity() -} - -/// Gets the origin of the given point. -/// -/// # See also: -/// -/// * [`one`](fn.one.html) -/// * [`zero`](fn.zero.html) -/// -/// # Deprecated -/// Use [Point::origin] instead. -/// -/// Or, use [EuclideanSpace::origin](https://docs.rs/alga/0.7.2/alga/linear/trait.EuclideanSpace.html#tymethod.origin). -#[deprecated(note = "use `Point::origin` instead")] -#[inline] -pub fn origin() -> P { - P::origin() -} - -/* - * - * Dimension - * - */ -/// The dimension of the given algebraic entity seen as a vector space. -#[inline] -pub fn dimension() -> usize { - V::dimension() +pub fn zero() -> T { + T::zero() } /* @@ -245,7 +190,7 @@ pub fn dimension() -> usize { /// The range must not be empty. #[inline] pub fn wrap(mut val: T, min: T, max: T) -> T -where T: Copy + PartialOrd + AdditiveGroup { +where T: Copy + PartialOrd + ClosedAdd + ClosedSub { assert!(min < max, "Invalid wrapping bounds."); let width = max - min; @@ -310,23 +255,23 @@ pub fn abs(a: &T) -> T { a.abs() } -/// Returns the infimum of `a` and `b`. -#[inline] -pub fn inf(a: &T, b: &T) -> T { - a.meet(b) -} - -/// Returns the supremum of `a` and `b`. -#[inline] -pub fn sup(a: &T, b: &T) -> T { - a.join(b) -} - -/// Returns simultaneously the infimum and supremum of `a` and `b`. -#[inline] -pub fn inf_sup(a: &T, b: &T) -> (T, T) { - a.meet_join(b) -} +///// Returns the infimum of `a` and `b`. +//#[inline] +//pub fn inf(a: &T, b: &T) -> T { +// a.meet(b) +//} +// +///// Returns the supremum of `a` and `b`. +//#[inline] +//pub fn sup(a: &T, b: &T) -> T { +// a.join(b) +//} +// +///// Returns simultaneously the infimum and supremum of `a` and `b`. +//#[inline] +//pub fn inf_sup(a: &T, b: &T) -> (T, T) { +// a.meet_join(b) +//} /// Compare `a` and `b` using a partial ordering relation. #[inline] @@ -414,175 +359,6 @@ pub fn partial_sort2<'a, T: PartialOrd>(a: &'a T, b: &'a T) -> Option<(&'a T, &' } } -/* - * Inverse - */ - -/// Tries to gets an inverted copy of a square matrix. -/// -/// # See also: -/// -/// * [`inverse`](fn.inverse.html) -#[deprecated(note = "use the `.try_inverse()` method instead")] -#[inline] -pub fn try_inverse(m: &M) -> Option { - m.try_inverse() -} - -/// Computes the multiplicative inverse of an (always invertible) algebraic entity. -/// -/// # See also: -/// -/// * [`try_inverse`](fn.try_inverse.html) -#[deprecated(note = "use the `.inverse()` method instead")] -#[inline] -pub fn inverse>(m: &M) -> M { - m.two_sided_inverse() -} - -/* - * Inner vector space - */ - -/// Computes the dot product of two vectors. -/// -/// ## Deprecated -/// Use these methods instead: -/// - [Matrix::dot] -/// - [Quaternion::dot] -/// -/// Or, use [FiniteDimVectorSpace::dot](https://docs.rs/alga/0.7.2/alga/linear/trait.FiniteDimVectorSpace.html#tymethod.dot). -#[deprecated(note = "use `Matrix::dot` or `Quaternion::dot` instead")] -#[inline] -pub fn dot(a: &V, b: &V) -> V::Field { - a.dot(b) -} - -/// Computes the smallest angle between two vectors. -/// -/// ## Deprecated -/// Use [Matrix::angle] instead. -/// -/// Or, use [InnerSpace::angle](https://docs.rs/alga/0.7.2/alga/linear/trait.InnerSpace.html#method.angle). -#[deprecated(note = "use `Matrix::angle` instead")] -#[inline] -pub fn angle(a: &V, b: &V) -> V::RealField { - a.angle(b) -} - -/* - * Normed space - */ - -/// Computes the L2 (Euclidean) norm of a vector. -/// -/// # See also: -/// -/// * [`magnitude`](fn.magnitude.html) -/// * [`magnitude_squared`](fn.magnitude_squared.html) -/// * [`norm_squared`](fn.norm_squared.html) -/// -/// # Deprecated -/// Use these methods instead: -/// * [Matrix::norm] -/// * [Quaternion::norm] -/// -/// Or, use [NormedSpace::norm](https://docs.rs/alga/0.7.2/alga/linear/trait.NormedSpace.html#tymethod.norm). -#[deprecated(note = "use `Matrix::norm` or `Quaternion::norm` instead")] -#[inline] -pub fn norm(v: &V) -> V::RealField { - v.norm() -} - -/// Computes the squared L2 (Euclidean) norm of the vector `v`. -/// -/// # See also: -/// -/// * [`magnitude`](fn.magnitude.html) -/// * [`magnitude_squared`](fn.magnitude_squared.html) -/// * [`norm`](fn.norm.html) -/// -/// # Deprecated -/// Use these methods instead: -/// * [Matrix::norm_squared] -/// * [Quaternion::norm_squared] -/// -/// Or, use [NormedSpace::norm_squared](https://docs.rs/alga/0.7.2/alga/linear/trait.NormedSpace.html#tymethod.norm_squared). -#[deprecated(note = "use `Matrix::norm_squared` or `Quaternion::norm_squared` instead")] -#[inline] -pub fn norm_squared(v: &V) -> V::RealField { - v.norm_squared() -} - -/// A synonym for [`norm`](fn.norm.html), aka length. -/// -/// # See also: -/// -/// * [`magnitude_squared`](fn.magnitude_squared.html) -/// * [`norm`](fn.norm.html) -/// * [`norm_squared`](fn.norm_squared.html) -/// -/// # Deprecated -/// Use these methods instead: -/// * [Matrix::magnitude] -/// * [Quaternion::magnitude] -/// -/// Or, use [NormedSpace::norm](https://docs.rs/alga/0.7.2/alga/linear/trait.NormedSpace.html#tymethod.norm). -#[deprecated(note = "use `Matrix::magnitude` or `Quaternion::magnitude` instead")] -#[inline] -pub fn magnitude(v: &V) -> V::RealField { - v.norm() -} - -/// A synonym for [`norm_squared`](fn.norm_squared.html), -/// aka length squared. -/// -/// # See also: -/// -/// * [`magnitude`](fn.magnitude.html) -/// * [`norm`](fn.norm.html) -/// * [`norm_squared`](fn.norm_squared.html) -/// -/// # Deprecated -/// Use these methods instead: -/// * [Matrix::magnitude_squared] -/// * [Quaternion::magnitude_squared] -/// -/// Or, use [NormedSpace::norm_squared](https://docs.rs/alga/0.7.2/alga/linear/trait.NormedSpace.html#tymethod.norm_squared). -#[deprecated(note = "use `Matrix::magnitude_squared` or `Quaternion::magnitude_squared` instead")] -#[inline] -pub fn magnitude_squared(v: &V) -> V::RealField { - v.norm_squared() -} - -/// Computes the normalized version of the vector `v`. -/// -/// # Deprecated -/// Use these methods instead: -/// * [Matrix::normalize] -/// * [Quaternion::normalize] -/// -/// Or, use [NormedSpace::normalize](https://docs.rs/alga/0.7.2/alga/linear/trait.NormedSpace.html#tymethod.normalize). -#[deprecated(note = "use `Matrix::normalize` or `Quaternion::normalize` instead")] -#[inline] -pub fn normalize(v: &V) -> V { - v.normalize() -} - -/// Computes the normalized version of the vector `v` or returns `None` if its norm is smaller than `min_norm`. -/// -/// # Deprecated -/// Use these methods instead: -/// * [Matrix::try_normalize] -/// * [Quaternion::try_normalize] -/// -/// Or, use [NormedSpace::try_normalize](https://docs.rs/alga/0.7.2/alga/linear/trait.NormedSpace.html#tymethod.try_normalize). -#[deprecated(note = "use `Matrix::try_normalize` or `Quaternion::try_normalize` instead")] -#[inline] -pub fn try_normalize(v: &V, min_norm: V::RealField) -> Option { - v.try_normalize(min_norm) -} - /* * * Point operations. @@ -595,8 +371,9 @@ pub fn try_normalize(v: &V, min_norm: V::RealField) -> Option /// * [distance](fn.distance.html) /// * [distance_squared](fn.distance_squared.html) #[inline] -pub fn center(p1: &P, p2: &P) -> P { - P::from_coordinates((p1.coordinates() + p2.coordinates()) * convert(0.5)) +pub fn center(p1: &Point, p2: &Point) -> Point +where DefaultAllocator: Allocator { + ((&p1.coords + &p2.coords) * convert::<_, N>(0.5)).into() } /// The distance between two points. @@ -606,8 +383,14 @@ pub fn center(p1: &P, p2: &P) -> P { /// * [center](fn.center.html) /// * [distance_squared](fn.distance_squared.html) #[inline] -pub fn distance(p1: &P, p2: &P) -> P::RealField { - (p2.coordinates() - p1.coordinates()).norm() +pub fn distance( + p1: &Point, + p2: &Point, +) -> N::SimdRealField +where + DefaultAllocator: Allocator, +{ + (&p2.coords - &p1.coords).norm() } /// The squared distance between two points. @@ -617,8 +400,14 @@ pub fn distance(p1: &P, p2: &P) -> P::RealField { /// * [center](fn.center.html) /// * [distance](fn.distance.html) #[inline] -pub fn distance_squared(p1: &P, p2: &P) -> P::RealField { - (p2.coordinates() - p1.coordinates()).norm_squared() +pub fn distance_squared( + p1: &Point, + p2: &Point, +) -> N::SimdRealField +where + DefaultAllocator: Allocator, +{ + (&p2.coords - &p1.coords).norm_squared() } /* @@ -683,7 +472,7 @@ pub fn is_convertible, To>(t: &From) -> bool { /// * [try_convert](fn.try_convert.html) /// * [try_convert_ref](fn.try_convert_ref.html) #[inline] -pub unsafe fn convert_unchecked, To>(t: From) -> To { +pub fn convert_unchecked, To>(t: From) -> To { t.to_subset_unchecked() } @@ -726,6 +515,6 @@ pub fn try_convert_ref, To>(t: &From) -> Option { /// * [try_convert](fn.try_convert.html) /// * [try_convert_ref](fn.try_convert_ref.html) #[inline] -pub unsafe fn convert_ref_unchecked, To>(t: &From) -> To { +pub fn convert_ref_unchecked, To>(t: &From) -> To { t.to_subset_unchecked() } diff --git a/src/linalg/balancing.rs b/src/linalg/balancing.rs index e8abbefb..aca28cbf 100644 --- a/src/linalg/balancing.rs +++ b/src/linalg/balancing.rs @@ -1,6 +1,6 @@ //! Functions for balancing a matrix. -use alga::general::RealField; +use simba::scalar::RealField; use std::ops::{DivAssign, MulAssign}; use crate::allocator::Allocator; diff --git a/src/linalg/bidiagonal.rs b/src/linalg/bidiagonal.rs index f766c91e..9dd9a131 100644 --- a/src/linalg/bidiagonal.rs +++ b/src/linalg/bidiagonal.rs @@ -1,11 +1,11 @@ #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Serialize}; -use alga::general::ComplexField; use crate::allocator::Allocator; use crate::base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, Unit, VectorN}; use crate::dimension::{Dim, DimDiff, DimMin, DimMinimum, DimSub, U1}; use crate::storage::Storage; +use simba::scalar::ComplexField; use crate::geometry::Reflection; use crate::linalg::householder; @@ -14,27 +14,23 @@ use crate::linalg::householder; #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[cfg_attr( feature = "serde-serialize", - serde(bound( - serialize = "DimMinimum: DimSub, + serde(bound(serialize = "DimMinimum: DimSub, DefaultAllocator: Allocator + Allocator> + Allocator, U1>>, MatrixMN: Serialize, VectorN>: Serialize, - VectorN, U1>>: Serialize" - )) + VectorN, U1>>: Serialize")) )] #[cfg_attr( feature = "serde-serialize", - serde(bound( - deserialize = "DimMinimum: DimSub, + serde(bound(deserialize = "DimMinimum: DimSub, DefaultAllocator: Allocator + Allocator> + Allocator, U1>>, MatrixMN: Deserialize<'de>, VectorN>: Deserialize<'de>, - VectorN, U1>>: Deserialize<'de>" - )) + VectorN, U1>>: Deserialize<'de>")) )] #[derive(Clone, Debug)] pub struct Bidiagonal, C: Dim> @@ -63,7 +59,8 @@ where MatrixMN: Copy, VectorN>: Copy, VectorN, U1>>: Copy, -{} +{ +} impl, C: Dim> Bidiagonal where @@ -174,11 +171,9 @@ where MatrixN>, MatrixMN, C>, ) - where - DefaultAllocator: Allocator, DimMinimum> + where DefaultAllocator: Allocator, DimMinimum> + Allocator> - + Allocator, C>, - { + + Allocator, C> { // FIXME: optimize by calling a reallocator. (self.u(), self.d(), self.v_t()) } @@ -186,9 +181,7 @@ where /// Retrieves the upper trapezoidal submatrix `R` of this decomposition. #[inline] pub fn d(&self) -> MatrixN> - where - DefaultAllocator: Allocator, DimMinimum>, - { + where DefaultAllocator: Allocator, DimMinimum> { let (nrows, ncols) = self.uv.data.shape(); let d = nrows.min(ncols); @@ -266,13 +259,13 @@ where /// The diagonal part of this decomposed matrix. pub fn diagonal(&self) -> VectorN> - where DefaultAllocator: Allocator> { + where DefaultAllocator: Allocator> { self.diagonal.map(|e| e.modulus()) } /// The off-diagonal part of this decomposed matrix. pub fn off_diagonal(&self) -> VectorN, U1>> - where DefaultAllocator: Allocator, U1>> { + where DefaultAllocator: Allocator, U1>> { self.off_diagonal.map(|e| e.modulus()) } diff --git a/src/linalg/cholesky.rs b/src/linalg/cholesky.rs index 67baefb1..0e2fec0b 100644 --- a/src/linalg/cholesky.rs +++ b/src/linalg/cholesky.rs @@ -2,12 +2,12 @@ use serde::{Deserialize, Serialize}; use num::One; -use alga::general::ComplexField; +use simba::scalar::ComplexField; use crate::allocator::Allocator; use crate::base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, SquareMatrix, Vector}; use crate::constraint::{SameNumberOfRows, ShapeConstraint}; -use crate::dimension::{Dim, DimAdd, DimSum, DimDiff, DimSub, Dynamic, U1}; +use crate::dimension::{Dim, DimAdd, DimDiff, DimSub, DimSum, Dynamic, U1}; use crate::storage::{Storage, StorageMut}; /// The Cholesky decomposition of a symmetric-definite-positive matrix. @@ -24,8 +24,7 @@ use crate::storage::{Storage, StorageMut}; )] #[derive(Clone, Debug)] pub struct Cholesky -where - DefaultAllocator: Allocator, +where DefaultAllocator: Allocator { chol: MatrixN, } @@ -38,8 +37,7 @@ where } impl> Cholesky -where - DefaultAllocator: Allocator, +where DefaultAllocator: Allocator { /// Attempts to compute the Cholesky decomposition of `matrix`. /// @@ -176,22 +174,38 @@ where let mut col = col.into_owned(); // for an explanation of the formulas, see https://en.wikipedia.org/wiki/Cholesky_decomposition#Updating_the_decomposition let n = col.nrows(); - assert_eq!(n, self.chol.nrows() + 1, "The new column must have the size of the factored matrix plus one."); + assert_eq!( + n, + self.chol.nrows() + 1, + "The new column must have the size of the factored matrix plus one." + ); assert!(j < n, "j needs to be within the bound of the new matrix."); // loads the data into a new matrix with an additional jth row/column - let mut chol = unsafe { Matrix::new_uninitialized_generic(self.chol.data.shape().0.add(U1), self.chol.data.shape().1.add(U1)) }; - chol.slice_range_mut(..j, ..j).copy_from(&self.chol.slice_range(..j, ..j)); - chol.slice_range_mut(..j, j + 1..).copy_from(&self.chol.slice_range(..j, j..)); - chol.slice_range_mut(j + 1.., ..j).copy_from(&self.chol.slice_range(j.., ..j)); - chol.slice_range_mut(j + 1.., j + 1..).copy_from(&self.chol.slice_range(j.., j..)); + let mut chol = unsafe { + Matrix::new_uninitialized_generic( + self.chol.data.shape().0.add(U1), + self.chol.data.shape().1.add(U1), + ) + }; + chol.slice_range_mut(..j, ..j) + .copy_from(&self.chol.slice_range(..j, ..j)); + chol.slice_range_mut(..j, j + 1..) + .copy_from(&self.chol.slice_range(..j, j..)); + chol.slice_range_mut(j + 1.., ..j) + .copy_from(&self.chol.slice_range(j.., ..j)); + chol.slice_range_mut(j + 1.., j + 1..) + .copy_from(&self.chol.slice_range(j.., j..)); // update the jth row let top_left_corner = self.chol.slice_range(..j, ..j); let col_j = col[j]; let (mut new_rowj_adjoint, mut new_colj) = col.rows_range_pair_mut(..j, j + 1..); - assert!(top_left_corner.solve_lower_triangular_mut(&mut new_rowj_adjoint), "Cholesky::insert_column : Unable to solve lower triangular system!"); + assert!( + top_left_corner.solve_lower_triangular_mut(&mut new_rowj_adjoint), + "Cholesky::insert_column : Unable to solve lower triangular system!" + ); new_rowj_adjoint.adjoint_to(&mut chol.slice_range_mut(j, ..j)); @@ -202,36 +216,51 @@ where // update the jth column let bottom_left_corner = self.chol.slice_range(j.., ..j); // new_colj = (col_jplus - bottom_left_corner * new_rowj.adjoint()) / center_element; - new_colj.gemm(-N::one() / center_element, &bottom_left_corner, &new_rowj_adjoint, N::one() / center_element); + new_colj.gemm( + -N::one() / center_element, + &bottom_left_corner, + &new_rowj_adjoint, + N::one() / center_element, + ); chol.slice_range_mut(j + 1.., j).copy_from(&new_colj); // update the bottom right corner let mut bottom_right_corner = chol.slice_range_mut(j + 1.., j + 1..); - Self::xx_rank_one_update(&mut bottom_right_corner, &mut new_colj, -N::RealField::one()); + Self::xx_rank_one_update( + &mut bottom_right_corner, + &mut new_colj, + -N::RealField::one(), + ); Cholesky { chol } } /// 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. - pub fn remove_column( - &self, - j: usize, - ) -> Cholesky> - where - D: DimSub, - DefaultAllocator: Allocator, DimDiff> + Allocator + pub fn remove_column(&self, j: usize) -> Cholesky> + where + D: DimSub, + DefaultAllocator: Allocator, DimDiff> + Allocator, { let n = self.chol.nrows(); assert!(n > 0, "The matrix needs at least one column."); assert!(j < n, "j needs to be within the bound of the matrix."); // loads the data into a new matrix except for the jth row/column - let mut chol = unsafe { Matrix::new_uninitialized_generic(self.chol.data.shape().0.sub(U1), self.chol.data.shape().1.sub(U1)) }; - chol.slice_range_mut(..j, ..j).copy_from(&self.chol.slice_range(..j, ..j)); - chol.slice_range_mut(..j, j..).copy_from(&self.chol.slice_range(..j, j + 1..)); - chol.slice_range_mut(j.., ..j).copy_from(&self.chol.slice_range(j + 1.., ..j)); - chol.slice_range_mut(j.., j..).copy_from(&self.chol.slice_range(j + 1.., j + 1..)); + let mut chol = unsafe { + Matrix::new_uninitialized_generic( + self.chol.data.shape().0.sub(U1), + self.chol.data.shape().1.sub(U1), + ) + }; + chol.slice_range_mut(..j, ..j) + .copy_from(&self.chol.slice_range(..j, ..j)); + chol.slice_range_mut(..j, j..) + .copy_from(&self.chol.slice_range(..j, j + 1..)); + chol.slice_range_mut(j.., ..j) + .copy_from(&self.chol.slice_range(j + 1.., ..j)); + chol.slice_range_mut(j.., j..) + .copy_from(&self.chol.slice_range(j + 1.., j + 1..)); // updates the bottom right corner let mut bottom_right_corner = chol.slice_range_mut(j.., j..); @@ -247,13 +276,16 @@ where /// /// This helper method is called by `rank_one_update` but also `insert_column` and `remove_column` /// where it is used on a square slice of the decomposition - fn xx_rank_one_update(chol : &mut Matrix, x: &mut Vector, sigma: N::RealField) - where - //N: ComplexField, - Dm: Dim, - Rx: Dim, - Sm: StorageMut, - Sx: StorageMut, + fn xx_rank_one_update( + chol: &mut Matrix, + x: &mut Vector, + sigma: N::RealField, + ) where + //N: ComplexField, + Dm: Dim, + Rx: Dim, + Sm: StorageMut, + Sx: StorageMut, { // heavily inspired by Eigen's `llt_rank_update_lower` implementation https://eigen.tuxfamily.org/dox/LLT_8h_source.html let n = x.nrows(); @@ -293,8 +325,7 @@ where } impl, S: Storage> SquareMatrix -where - DefaultAllocator: Allocator, +where DefaultAllocator: Allocator { /// Attempts to compute the Cholesky decomposition of this matrix. /// diff --git a/src/linalg/determinant.rs b/src/linalg/determinant.rs index 54ec9e5a..f02bf7de 100644 --- a/src/linalg/determinant.rs +++ b/src/linalg/determinant.rs @@ -1,4 +1,4 @@ -use alga::general::ComplexField; +use simba::scalar::ComplexField; use crate::base::allocator::Allocator; use crate::base::dimension::DimMin; diff --git a/src/linalg/eigen.rs b/src/linalg/eigen.rs index 8d1d26ca..2177903e 100644 --- a/src/linalg/eigen.rs +++ b/src/linalg/eigen.rs @@ -1,8 +1,8 @@ #[cfg(feature = "serde-serialize")] -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; -use alga::general::ComplexField; use num_complex::Complex; +use simba::scalar::ComplexField; use std::cmp; use std::fmt::Display; use std::ops::MulAssign; @@ -10,7 +10,9 @@ use std::ops::MulAssign; use crate::allocator::Allocator; use crate::base::dimension::{Dim, DimDiff, DimSub, Dynamic, U1, U2, U3}; use crate::base::storage::Storage; -use crate::base::{DefaultAllocator, Hessenberg, MatrixN, SquareMatrix, Unit, Vector2, Vector3, VectorN}; +use crate::base::{ + DefaultAllocator, Hessenberg, MatrixN, SquareMatrix, Unit, Vector2, Vector3, VectorN, +}; use crate::constraint::{DimEq, ShapeConstraint}; use crate::geometry::{Reflection, UnitComplex}; @@ -21,28 +23,19 @@ use crate::linalg::Schur; #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[cfg_attr( feature = "serde-serialize", - serde( - bound( - serialize = "DefaultAllocator: Allocator, + serde(bound(serialize = "DefaultAllocator: Allocator, VectorN: Serialize, - MatrixN: Serialize" - ) - ) + MatrixN: Serialize")) )] #[cfg_attr( feature = "serde-serialize", - serde( - bound( - deserialize = "DefaultAllocator: Allocator, + serde(bound(deserialize = "DefaultAllocator: Allocator, VectorN: Serialize, - MatrixN: Deserialize<'de>" - ) - ) + MatrixN: Deserialize<'de>")) )] #[derive(Clone, Debug)] pub struct Eigen -where - DefaultAllocator: Allocator + Allocator, +where DefaultAllocator: Allocator + Allocator { pub eigenvectors: MatrixN, pub eigenvalues: VectorN, diff --git a/src/linalg/full_piv_lu.rs b/src/linalg/full_piv_lu.rs index f2bfc874..bdb296c2 100644 --- a/src/linalg/full_piv_lu.rs +++ b/src/linalg/full_piv_lu.rs @@ -1,12 +1,12 @@ #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Serialize}; -use alga::general::ComplexField; use crate::allocator::Allocator; use crate::base::{DefaultAllocator, Matrix, MatrixMN, MatrixN}; use crate::constraint::{SameNumberOfRows, ShapeConstraint}; use crate::dimension::{Dim, DimMin, DimMinimum}; use crate::storage::{Storage, StorageMut}; +use simba::scalar::ComplexField; use crate::linalg::lu; use crate::linalg::PermutationSequence; @@ -15,21 +15,17 @@ use crate::linalg::PermutationSequence; #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[cfg_attr( feature = "serde-serialize", - serde(bound( - serialize = "DefaultAllocator: Allocator + + serde(bound(serialize = "DefaultAllocator: Allocator + Allocator<(usize, usize), DimMinimum>, MatrixMN: Serialize, - PermutationSequence>: Serialize" - )) + PermutationSequence>: Serialize")) )] #[cfg_attr( feature = "serde-serialize", - serde(bound( - deserialize = "DefaultAllocator: Allocator + + serde(bound(deserialize = "DefaultAllocator: Allocator + Allocator<(usize, usize), DimMinimum>, MatrixMN: Deserialize<'de>, - PermutationSequence>: Deserialize<'de>" - )) + PermutationSequence>: Deserialize<'de>")) )] #[derive(Clone, Debug)] pub struct FullPivLU, C: Dim> @@ -45,7 +41,8 @@ where DefaultAllocator: Allocator + Allocator<(usize, usize), DimMinimum>, MatrixMN: Copy, PermutationSequence>: Copy, -{} +{ +} impl, C: Dim> FullPivLU where DefaultAllocator: Allocator + Allocator<(usize, usize), DimMinimum> diff --git a/src/linalg/givens.rs b/src/linalg/givens.rs index 20e2c309..164a0971 100644 --- a/src/linalg/givens.rs +++ b/src/linalg/givens.rs @@ -1,19 +1,18 @@ //! Construction of givens rotations. -use alga::general::ComplexField; -use num::{Zero, One}; +use num::{One, Zero}; +use simba::scalar::ComplexField; +use crate::base::constraint::{DimEq, ShapeConstraint}; use crate::base::dimension::{Dim, U2}; -use crate::base::constraint::{ShapeConstraint, DimEq}; use crate::base::storage::{Storage, StorageMut}; -use crate::base::{Vector, Matrix}; - +use crate::base::{Matrix, Vector}; /// A Givens rotation. #[derive(Debug, Clone, Copy)] pub struct GivensRotation { c: N::RealField, - s: N + s: N, } // Matrix = UnitComplex * Matrix @@ -22,7 +21,7 @@ impl GivensRotation { pub fn identity() -> Self { Self { c: N::RealField::one(), - s: N::zero() + s: N::zero(), } } @@ -31,9 +30,7 @@ impl GivensRotation { /// The components are copies as-is. It is not checked whether they describe /// an actually valid Givens rotation. pub fn new_unchecked(c: N::RealField, s: N) -> Self { - Self { - c, s - } + Self { c, s } } /// Initializes a Givens rotation from its non-normalized cosine an sine components. @@ -103,7 +100,10 @@ impl GivensRotation { /// The inverse of this givens rotation. pub fn inverse(&self) -> Self { - Self { c: self.c, s: -self.s } + Self { + c: self.c, + s: -self.s, + } } /// Performs the multiplication `rhs = self * rhs` in-place. @@ -159,4 +159,3 @@ impl GivensRotation { } } } - diff --git a/src/linalg/hessenberg.rs b/src/linalg/hessenberg.rs index c87c06a2..37dea77e 100644 --- a/src/linalg/hessenberg.rs +++ b/src/linalg/hessenberg.rs @@ -1,11 +1,11 @@ #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Serialize}; -use alga::general::ComplexField; use crate::allocator::Allocator; use crate::base::{DefaultAllocator, MatrixMN, MatrixN, SquareMatrix, VectorN}; use crate::dimension::{DimDiff, DimSub, U1}; use crate::storage::Storage; +use simba::scalar::ComplexField; use crate::linalg::householder; @@ -13,21 +13,17 @@ use crate::linalg::householder; #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[cfg_attr( feature = "serde-serialize", - serde(bound( - serialize = "DefaultAllocator: Allocator + + serde(bound(serialize = "DefaultAllocator: Allocator + Allocator>, MatrixN: Serialize, - VectorN>: Serialize" - )) + VectorN>: Serialize")) )] #[cfg_attr( feature = "serde-serialize", - serde(bound( - deserialize = "DefaultAllocator: Allocator + + serde(bound(deserialize = "DefaultAllocator: Allocator + Allocator>, MatrixN: Deserialize<'de>, - VectorN>: Deserialize<'de>" - )) + VectorN>: Deserialize<'de>")) )] #[derive(Clone, Debug)] pub struct Hessenberg> @@ -42,7 +38,8 @@ where DefaultAllocator: Allocator + Allocator>, MatrixN: Copy, VectorN>: Copy, -{} +{ +} impl> Hessenberg where DefaultAllocator: Allocator + Allocator + Allocator> diff --git a/src/linalg/householder.rs b/src/linalg/householder.rs index 11fa32eb..a804656d 100644 --- a/src/linalg/householder.rs +++ b/src/linalg/householder.rs @@ -1,11 +1,11 @@ //! Construction of householder elementary reflections. -use num::Zero; -use alga::general::ComplexField; use crate::allocator::Allocator; use crate::base::{DefaultAllocator, MatrixMN, MatrixN, Unit, Vector, VectorN}; use crate::dimension::Dim; use crate::storage::{Storage, StorageMut}; +use num::Zero; +use simba::scalar::ComplexField; use crate::geometry::Reflection; diff --git a/src/linalg/inverse.rs b/src/linalg/inverse.rs index f0920cca..6e0d6661 100644 --- a/src/linalg/inverse.rs +++ b/src/linalg/inverse.rs @@ -1,4 +1,4 @@ -use alga::general::ComplexField; +use simba::scalar::ComplexField; use crate::base::allocator::Allocator; use crate::base::dimension::Dim; diff --git a/src/linalg/lu.rs b/src/linalg/lu.rs index 521df894..fc94ba8b 100644 --- a/src/linalg/lu.rs +++ b/src/linalg/lu.rs @@ -1,13 +1,13 @@ #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Serialize}; -use alga::general::{Field, ComplexField}; use crate::allocator::{Allocator, Reallocator}; use crate::base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, Scalar}; use crate::constraint::{SameNumberOfRows, ShapeConstraint}; use crate::dimension::{Dim, DimMin, DimMinimum}; -use std::mem; use crate::storage::{Storage, StorageMut}; +use simba::scalar::{ComplexField, Field}; +use std::mem; use crate::linalg::PermutationSequence; @@ -15,21 +15,17 @@ use crate::linalg::PermutationSequence; #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[cfg_attr( feature = "serde-serialize", - serde(bound( - serialize = "DefaultAllocator: Allocator + + serde(bound(serialize = "DefaultAllocator: Allocator + Allocator<(usize, usize), DimMinimum>, MatrixMN: Serialize, - PermutationSequence>: Serialize" - )) + PermutationSequence>: Serialize")) )] #[cfg_attr( feature = "serde-serialize", - serde(bound( - deserialize = "DefaultAllocator: Allocator + + serde(bound(deserialize = "DefaultAllocator: Allocator + Allocator<(usize, usize), DimMinimum>, MatrixMN: Deserialize<'de>, - PermutationSequence>: Deserialize<'de>" - )) + PermutationSequence>: Deserialize<'de>")) )] #[derive(Clone, Debug)] pub struct LU, C: Dim> @@ -44,7 +40,8 @@ where DefaultAllocator: Allocator + Allocator<(usize, usize), DimMinimum>, MatrixMN: Copy, PermutationSequence>: Copy, -{} +{ +} /// Performs a LU decomposition to overwrite `out` with the inverse of `matrix`. /// @@ -333,7 +330,8 @@ where let (pivot_row, mut down) = submat.rows_range_pair_mut(0, 1..); for k in 0..pivot_row.ncols() { - down.column_mut(k).axpy(-pivot_row[k].inlined_clone(), &coeffs, N::one()); + down.column_mut(k) + .axpy(-pivot_row[k].inlined_clone(), &coeffs, N::one()); } } @@ -364,7 +362,8 @@ pub fn gauss_step_swap( for k in 0..pivot_row.ncols() { mem::swap(&mut pivot_row[k], &mut down[(piv - 1, k)]); - down.column_mut(k).axpy(-pivot_row[k].inlined_clone(), &coeffs, N::one()); + down.column_mut(k) + .axpy(-pivot_row[k].inlined_clone(), &coeffs, N::one()); } } diff --git a/src/linalg/permutation_sequence.rs b/src/linalg/permutation_sequence.rs index ce493905..5d295dcb 100644 --- a/src/linalg/permutation_sequence.rs +++ b/src/linalg/permutation_sequence.rs @@ -1,8 +1,8 @@ #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Serialize}; -use alga::general::ClosedNeg; use num::One; +use simba::scalar::ClosedNeg; use crate::allocator::Allocator; use crate::base::{DefaultAllocator, Matrix, Scalar, VectorN}; @@ -15,17 +15,13 @@ use crate::storage::StorageMut; #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[cfg_attr( feature = "serde-serialize", - serde(bound( - serialize = "DefaultAllocator: Allocator<(usize, usize), D>, - VectorN<(usize, usize), D>: Serialize" - )) + serde(bound(serialize = "DefaultAllocator: Allocator<(usize, usize), D>, + VectorN<(usize, usize), D>: Serialize")) )] #[cfg_attr( feature = "serde-serialize", - serde(bound( - deserialize = "DefaultAllocator: Allocator<(usize, usize), D>, - VectorN<(usize, usize), D>: Deserialize<'de>" - )) + serde(bound(deserialize = "DefaultAllocator: Allocator<(usize, usize), D>, + VectorN<(usize, usize), D>: Deserialize<'de>")) )] #[derive(Clone, Debug)] pub struct PermutationSequence @@ -39,7 +35,8 @@ impl Copy for PermutationSequence where DefaultAllocator: Allocator<(usize, usize), D>, VectorN<(usize, usize), D>: Copy, -{} +{ +} impl PermutationSequence where DefaultAllocator: Allocator<(usize, usize), D> diff --git a/src/linalg/qr.rs b/src/linalg/qr.rs index 74b4de85..acd02c6b 100644 --- a/src/linalg/qr.rs +++ b/src/linalg/qr.rs @@ -1,13 +1,13 @@ +use num::Zero; #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Serialize}; -use num::Zero; -use alga::general::ComplexField; use crate::allocator::{Allocator, Reallocator}; use crate::base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, Unit, VectorN}; use crate::constraint::{SameNumberOfRows, ShapeConstraint}; use crate::dimension::{Dim, DimMin, DimMinimum, U1}; use crate::storage::{Storage, StorageMut}; +use simba::scalar::ComplexField; use crate::geometry::Reflection; use crate::linalg::householder; @@ -16,21 +16,17 @@ use crate::linalg::householder; #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[cfg_attr( feature = "serde-serialize", - serde(bound( - serialize = "DefaultAllocator: Allocator + + serde(bound(serialize = "DefaultAllocator: Allocator + Allocator>, MatrixMN: Serialize, - VectorN>: Serialize" - )) + VectorN>: Serialize")) )] #[cfg_attr( feature = "serde-serialize", - serde(bound( - deserialize = "DefaultAllocator: Allocator + + serde(bound(deserialize = "DefaultAllocator: Allocator + Allocator>, MatrixMN: Deserialize<'de>, - VectorN>: Deserialize<'de>" - )) + VectorN>: Deserialize<'de>")) )] #[derive(Clone, Debug)] pub struct QR, C: Dim> @@ -45,7 +41,8 @@ where DefaultAllocator: Allocator + Allocator>, MatrixMN: Copy, VectorN>: Copy, -{} +{ +} impl, C: Dim> QR where DefaultAllocator: Allocator + Allocator + Allocator> @@ -77,9 +74,7 @@ where DefaultAllocator: Allocator + Allocator + Allocator MatrixMN, C> - where - DefaultAllocator: Allocator, C>, - { + where DefaultAllocator: Allocator, C> { let (nrows, ncols) = self.qr.data.shape(); let mut res = self.qr.rows_generic(0, nrows.min(ncols)).upper_triangle(); res.set_partial_diagonal(self.diag.iter().map(|e| N::from_real(e.modulus()))); @@ -91,9 +86,7 @@ where DefaultAllocator: Allocator + Allocator + Allocator MatrixMN, C> - where - DefaultAllocator: Reallocator, C>, - { + where DefaultAllocator: Reallocator, C> { let (nrows, ncols) = self.qr.data.shape(); let mut res = self.qr.resize_generic(nrows.min(ncols), ncols, N::zero()); res.fill_lower_triangle(N::zero(), 1); diff --git a/src/linalg/schur.rs b/src/linalg/schur.rs index 57ebd8f7..1fb4de2b 100644 --- a/src/linalg/schur.rs +++ b/src/linalg/schur.rs @@ -2,8 +2,8 @@ use serde::{Deserialize, Serialize}; use approx::AbsDiffEq; -use alga::general::{ComplexField, RealField}; use num_complex::Complex as NumComplex; +use simba::scalar::{ComplexField, RealField}; use std::cmp; use crate::allocator::Allocator; @@ -12,9 +12,9 @@ use crate::base::storage::Storage; use crate::base::{DefaultAllocator, MatrixN, SquareMatrix, Unit, Vector2, Vector3, VectorN}; use crate::geometry::Reflection; +use crate::linalg::givens::GivensRotation; use crate::linalg::householder; use crate::linalg::Hessenberg; -use crate::linalg::givens::GivensRotation; /// Schur decomposition of a square matrix. /// @@ -22,17 +22,13 @@ use crate::linalg::givens::GivensRotation; #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[cfg_attr( feature = "serde-serialize", - serde(bound( - serialize = "DefaultAllocator: Allocator, - MatrixN: Serialize" - )) + serde(bound(serialize = "DefaultAllocator: Allocator, + MatrixN: Serialize")) )] #[cfg_attr( feature = "serde-serialize", - serde(bound( - deserialize = "DefaultAllocator: Allocator, - MatrixN: Deserialize<'de>" - )) + serde(bound(deserialize = "DefaultAllocator: Allocator, + MatrixN: Deserialize<'de>")) )] #[derive(Clone, Debug)] pub struct Schur @@ -46,11 +42,12 @@ impl Copy for Schur where DefaultAllocator: Allocator, MatrixN: Copy, -{} +{ +} impl Schur where - D: DimSub, // For Hessenberg. + D: DimSub, // For Hessenberg. DefaultAllocator: Allocator> + Allocator> + Allocator @@ -291,8 +288,10 @@ where /// Computes the complex eigenvalues of the decomposed matrix. fn do_complex_eigenvalues(t: &MatrixN, out: &mut VectorN, D>) - where N: RealField, - DefaultAllocator: Allocator, D> { + where + N: RealField, + DefaultAllocator: Allocator, D>, + { let dim = t.nrows(); let mut m = 0; @@ -391,8 +390,10 @@ where /// Computes the complex eigenvalues of the decomposed matrix. pub fn complex_eigenvalues(&self) -> VectorN, D> - where N: RealField, - DefaultAllocator: Allocator, D> { + where + N: RealField, + DefaultAllocator: Allocator, D>, + { let mut out = unsafe { VectorN::new_uninitialized_generic(self.t.data.shape().0, U1) }; Self::do_complex_eigenvalues(&self.t, &mut out); out @@ -491,7 +492,7 @@ fn compute_2x2_basis>( impl> SquareMatrix where - D: DimSub, // For Hessenberg. + D: DimSub, // For Hessenberg. DefaultAllocator: Allocator> + Allocator> + Allocator @@ -560,8 +561,10 @@ where /// Computes the eigenvalues of this matrix. pub fn complex_eigenvalues(&self) -> VectorN, D> // FIXME: add balancing? - where N: RealField, - DefaultAllocator: Allocator, D> { + where + N: RealField, + DefaultAllocator: Allocator, D>, + { let dim = self.data.shape().0; let mut work = unsafe { VectorN::new_uninitialized_generic(dim, U1) }; diff --git a/src/linalg/solve.rs b/src/linalg/solve.rs index a6b9196f..56db4ade 100644 --- a/src/linalg/solve.rs +++ b/src/linalg/solve.rs @@ -1,10 +1,10 @@ -use alga::general::ComplexField; +use simba::scalar::ComplexField; use crate::base::allocator::Allocator; use crate::base::constraint::{SameNumberOfRows, ShapeConstraint}; use crate::base::dimension::{Dim, U1}; use crate::base::storage::{Storage, StorageMut}; -use crate::base::{DefaultAllocator, Matrix, MatrixMN, SquareMatrix, Vector, DVectorSlice}; +use crate::base::{DVectorSlice, DefaultAllocator, Matrix, MatrixMN, SquareMatrix, Vector}; impl> SquareMatrix { /// Computes the solution of the linear system `self . x = b` where `x` is the unknown and only @@ -190,10 +190,10 @@ impl> SquareMatrix { &self, b: &Matrix, ) -> Option> - where - S2: Storage, - DefaultAllocator: Allocator, - ShapeConstraint: SameNumberOfRows, + where + S2: Storage, + DefaultAllocator: Allocator, + ShapeConstraint: SameNumberOfRows, { let mut res = b.clone_owned(); if self.tr_solve_lower_triangular_mut(&mut res) { @@ -210,10 +210,10 @@ impl> SquareMatrix { &self, b: &Matrix, ) -> Option> - where - S2: Storage, - DefaultAllocator: Allocator, - ShapeConstraint: SameNumberOfRows, + where + S2: Storage, + DefaultAllocator: Allocator, + ShapeConstraint: SameNumberOfRows, { let mut res = b.clone_owned(); if self.tr_solve_upper_triangular_mut(&mut res) { @@ -229,14 +229,18 @@ impl> SquareMatrix { &self, b: &mut Matrix, ) -> bool - where - S2: StorageMut, - ShapeConstraint: SameNumberOfRows, + where + S2: StorageMut, + ShapeConstraint: SameNumberOfRows, { let cols = b.ncols(); for i in 0..cols { - if !self.xx_solve_lower_triangular_vector_mut(&mut b.column_mut(i), |e| e, |a, b| a.dot(b)) { + if !self.xx_solve_lower_triangular_vector_mut( + &mut b.column_mut(i), + |e| e, + |a, b| a.dot(b), + ) { return false; } } @@ -250,14 +254,18 @@ impl> SquareMatrix { &self, b: &mut Matrix, ) -> bool - where - S2: StorageMut, - ShapeConstraint: SameNumberOfRows, + where + S2: StorageMut, + ShapeConstraint: SameNumberOfRows, { let cols = b.ncols(); for i in 0..cols { - if !self.xx_solve_upper_triangular_vector_mut(&mut b.column_mut(i), |e| e, |a, b| a.dot(b)) { + if !self.xx_solve_upper_triangular_vector_mut( + &mut b.column_mut(i), + |e| e, + |a, b| a.dot(b), + ) { return false; } } @@ -272,10 +280,10 @@ impl> SquareMatrix { &self, b: &Matrix, ) -> Option> - where - S2: Storage, - DefaultAllocator: Allocator, - ShapeConstraint: SameNumberOfRows, + where + S2: Storage, + DefaultAllocator: Allocator, + ShapeConstraint: SameNumberOfRows, { let mut res = b.clone_owned(); if self.ad_solve_lower_triangular_mut(&mut res) { @@ -292,10 +300,10 @@ impl> SquareMatrix { &self, b: &Matrix, ) -> Option> - where - S2: Storage, - DefaultAllocator: Allocator, - ShapeConstraint: SameNumberOfRows, + where + S2: Storage, + DefaultAllocator: Allocator, + ShapeConstraint: SameNumberOfRows, { let mut res = b.clone_owned(); if self.ad_solve_upper_triangular_mut(&mut res) { @@ -311,14 +319,18 @@ impl> SquareMatrix { &self, b: &mut Matrix, ) -> bool - where - S2: StorageMut, - ShapeConstraint: SameNumberOfRows, + where + S2: StorageMut, + ShapeConstraint: SameNumberOfRows, { let cols = b.ncols(); for i in 0..cols { - if !self.xx_solve_lower_triangular_vector_mut(&mut b.column_mut(i), |e| e.conjugate(), |a, b| a.dotc(b)) { + if !self.xx_solve_lower_triangular_vector_mut( + &mut b.column_mut(i), + |e| e.conjugate(), + |a, b| a.dotc(b), + ) { return false; } } @@ -332,14 +344,18 @@ impl> SquareMatrix { &self, b: &mut Matrix, ) -> bool - where - S2: StorageMut, - ShapeConstraint: SameNumberOfRows, + where + S2: StorageMut, + ShapeConstraint: SameNumberOfRows, { let cols = b.ncols(); for i in 0..cols { - if !self.xx_solve_upper_triangular_vector_mut(&mut b.column_mut(i), |e| e.conjugate(), |a, b| a.dotc(b)) { + if !self.xx_solve_upper_triangular_vector_mut( + &mut b.column_mut(i), + |e| e.conjugate(), + |a, b| a.dotc(b), + ) { return false; } } @@ -347,17 +363,19 @@ impl> SquareMatrix { true } - #[inline(always)] fn xx_solve_lower_triangular_vector_mut( &self, b: &mut Vector, conjugate: impl Fn(N) -> N, - dot: impl Fn(&DVectorSlice, &DVectorSlice) -> N, + dot: impl Fn( + &DVectorSlice, + &DVectorSlice, + ) -> N, ) -> bool - where - S2: StorageMut, - ShapeConstraint: SameNumberOfRows, + where + S2: StorageMut, + ShapeConstraint: SameNumberOfRows, { let dim = self.nrows(); @@ -385,11 +403,14 @@ impl> SquareMatrix { &self, b: &mut Vector, conjugate: impl Fn(N) -> N, - dot: impl Fn(&DVectorSlice, &DVectorSlice) -> N, + dot: impl Fn( + &DVectorSlice, + &DVectorSlice, + ) -> N, ) -> bool - where - S2: StorageMut, - ShapeConstraint: SameNumberOfRows, + where + S2: StorageMut, + ShapeConstraint: SameNumberOfRows, { let dim = self.nrows(); diff --git a/src/linalg/svd.rs b/src/linalg/svd.rs index b608ec0c..ac33829c 100644 --- a/src/linalg/svd.rs +++ b/src/linalg/svd.rs @@ -1,19 +1,19 @@ #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Serialize}; -use num::{Zero, One}; use approx::AbsDiffEq; +use num::{One, Zero}; -use alga::general::{RealField, ComplexField}; use crate::allocator::Allocator; use crate::base::{DefaultAllocator, Matrix, Matrix2x3, MatrixMN, Vector2, VectorN}; use crate::constraint::{SameNumberOfRows, ShapeConstraint}; use crate::dimension::{Dim, DimDiff, DimMin, DimMinimum, DimSub, U1, U2}; use crate::storage::Storage; +use simba::scalar::{ComplexField, RealField}; +use crate::linalg::givens::GivensRotation; use crate::linalg::symmetric_eigen; use crate::linalg::Bidiagonal; -use crate::linalg::givens::GivensRotation; /// Singular Value Decomposition of a general matrix. #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] @@ -61,7 +61,8 @@ where MatrixMN>: Copy, MatrixMN, C>: Copy, VectorN>: Copy, -{} +{ +} impl, C: Dim> SVD where @@ -78,7 +79,14 @@ where { /// Computes the Singular Value Decomposition of `matrix` using implicit shift. pub fn new(matrix: MatrixMN, compute_u: bool, compute_v: bool) -> Self { - Self::try_new(matrix, compute_u, compute_v, N::RealField::default_epsilon(), 0).unwrap() + Self::try_new( + matrix, + compute_u, + compute_v, + N::RealField::default_epsilon(), + 0, + ) + .unwrap() } /// Attempts to compute the Singular Value Decomposition of `matrix` using implicit shift. @@ -120,7 +128,15 @@ where let mut off_diagonal = b.off_diagonal(); let mut niter = 0; - let (mut start, mut end) = Self::delimit_subproblem(&mut diagonal, &mut off_diagonal, &mut u, &mut v_t, b.is_upper_diagonal(), dim - 1, eps); + let (mut start, mut end) = Self::delimit_subproblem( + &mut diagonal, + &mut off_diagonal, + &mut u, + &mut v_t, + b.is_upper_diagonal(), + dim - 1, + eps, + ); while end != start { let subdim = end - start + 1; @@ -165,7 +181,8 @@ where ); if let Some((rot1, norm1)) = GivensRotation::cancel_y(&vec) { - rot1.inverse().rotate_rows(&mut subm.fixed_columns_mut::(0)); + rot1.inverse() + .rotate_rows(&mut subm.fixed_columns_mut::(0)); let rot1 = GivensRotation::new_unchecked(rot1.c(), N::from_real(rot1.s())); if k > start { @@ -175,8 +192,8 @@ where let v = Vector2::new(subm[(0, 0)], subm[(1, 0)]); // FIXME: does the case `v.y == 0` ever happen? - let (rot2, norm2) = - GivensRotation::cancel_y(&v).unwrap_or((GivensRotation::identity(), subm[(0, 0)])); + let (rot2, norm2) = GivensRotation::cancel_y(&v) + .unwrap_or((GivensRotation::identity(), subm[(0, 0)])); rot2.rotate(&mut subm.fixed_columns_mut::(1)); let rot2 = GivensRotation::new_unchecked(rot2.c(), N::from_real(rot2.s())); @@ -253,7 +270,15 @@ where } // Re-delimit the subproblem in case some decoupling occurred. - let sub = Self::delimit_subproblem(&mut diagonal, &mut off_diagonal, &mut u, &mut v_t, b.is_upper_diagonal(), end, eps); + let sub = Self::delimit_subproblem( + &mut diagonal, + &mut off_diagonal, + &mut u, + &mut v_t, + b.is_upper_diagonal(), + end, + eps, + ); start = sub.0; end = sub.1; @@ -321,14 +346,36 @@ where off_diagonal[m] = N::RealField::zero(); } else if diagonal[m].norm1() <= eps { diagonal[m] = N::RealField::zero(); - Self::cancel_horizontal_off_diagonal_elt(diagonal, off_diagonal, u, v_t, is_upper_diagonal, m, m + 1); + Self::cancel_horizontal_off_diagonal_elt( + diagonal, + off_diagonal, + u, + v_t, + is_upper_diagonal, + m, + m + 1, + ); if m != 0 { - Self::cancel_vertical_off_diagonal_elt(diagonal, off_diagonal, u, v_t, is_upper_diagonal, m - 1); + Self::cancel_vertical_off_diagonal_elt( + diagonal, + off_diagonal, + u, + v_t, + is_upper_diagonal, + m - 1, + ); } } else if diagonal[n].norm1() <= eps { diagonal[n] = N::RealField::zero(); - Self::cancel_vertical_off_diagonal_elt(diagonal, off_diagonal, u, v_t, is_upper_diagonal, m); + Self::cancel_vertical_off_diagonal_elt( + diagonal, + off_diagonal, + u, + v_t, + is_upper_diagonal, + m, + ); } else { break; } @@ -352,10 +399,25 @@ where // FIXME: write a test that enters this case. else if diagonal[m].norm1() <= eps { diagonal[m] = N::RealField::zero(); - Self::cancel_horizontal_off_diagonal_elt(diagonal, off_diagonal, u, v_t, is_upper_diagonal, m, n); + Self::cancel_horizontal_off_diagonal_elt( + diagonal, + off_diagonal, + u, + v_t, + is_upper_diagonal, + m, + n, + ); if m != 0 { - Self::cancel_vertical_off_diagonal_elt(diagonal, off_diagonal, u, v_t, is_upper_diagonal, m - 1); + Self::cancel_vertical_off_diagonal_elt( + diagonal, + off_diagonal, + u, + v_t, + is_upper_diagonal, + m - 1, + ); } break; } @@ -469,7 +531,7 @@ where } (None, None) => Err("SVD recomposition: U and V^t have not been computed."), (None, _) => Err("SVD recomposition: U has not been computed."), - (_, None) => Err("SVD recomposition: V^t has not been computed.") + (_, None) => Err("SVD recomposition: V^t has not been computed."), } } @@ -479,13 +541,10 @@ where /// Returns `Err` if the right- and left- singular vectors have not /// been computed at construction-time. pub fn pseudo_inverse(mut self, eps: N::RealField) -> Result, &'static str> - where - DefaultAllocator: Allocator, - { + where DefaultAllocator: Allocator { if eps < N::RealField::zero() { Err("SVD pseudo inverse: the epsilon must be non-negative.") - } - else { + } else { for i in 0..self.singular_values.len() { let val = self.singular_values[i]; @@ -517,8 +576,7 @@ where { if eps < N::RealField::zero() { Err("SVD solve: the epsilon must be non-negative.") - } - else { + } else { match (&self.u, &self.v_t) { (Some(u), Some(v_t)) => { let mut ut_b = u.ad_mul(b); @@ -540,7 +598,7 @@ where } (None, None) => Err("SVD solve: U and V^t have not been computed."), (None, _) => Err("SVD solve: U has not been computed."), - (_, None) => Err("SVD solve: V^t has not been computed.") + (_, None) => Err("SVD solve: V^t has not been computed."), } } } @@ -602,14 +660,11 @@ where /// /// All singular values below `eps` are considered equal to 0. pub fn pseudo_inverse(self, eps: N::RealField) -> Result, &'static str> - where - DefaultAllocator: Allocator, - { + where DefaultAllocator: Allocator { SVD::new(self.clone_owned(), true, true).pseudo_inverse(eps) } } - // Explicit formulae inspired from the paper "Computing the Singular Values of 2-by-2 Complex // Matrices", Sanzheng Qiao and Xiaohong Wang. // http://www.cas.mcmaster.ca/sqrl/papers/sqrl5.pdf @@ -619,7 +674,11 @@ fn compute_2x2_uptrig_svd( m22: N, compute_u: bool, compute_v: bool, -) -> (Option>, Vector2, Option>) +) -> ( + Option>, + Vector2, + Option>, +) { let two: N::RealField = crate::convert(2.0f64); let half: N::RealField = crate::convert(0.5f64); @@ -657,4 +716,4 @@ fn compute_2x2_uptrig_svd( } (u, Vector2::new(v1, v2), v_t) -} \ No newline at end of file +} diff --git a/src/linalg/symmetric_eigen.rs b/src/linalg/symmetric_eigen.rs index fc493dca..54fa2e84 100644 --- a/src/linalg/symmetric_eigen.rs +++ b/src/linalg/symmetric_eigen.rs @@ -1,14 +1,14 @@ #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Serialize}; -use num::Zero; use approx::AbsDiffEq; +use num::Zero; -use alga::general::ComplexField; use crate::allocator::Allocator; use crate::base::{DefaultAllocator, Matrix2, MatrixN, SquareMatrix, Vector2, VectorN}; use crate::dimension::{Dim, DimDiff, DimSub, U1, U2}; use crate::storage::Storage; +use simba::scalar::ComplexField; use crate::linalg::givens::GivensRotation; use crate::linalg::SymmetricTridiagonal; @@ -17,21 +17,17 @@ use crate::linalg::SymmetricTridiagonal; #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[cfg_attr( feature = "serde-serialize", - serde(bound( - serialize = "DefaultAllocator: Allocator + + serde(bound(serialize = "DefaultAllocator: Allocator + Allocator, VectorN: Serialize, - MatrixN: Serialize" - )) + MatrixN: Serialize")) )] #[cfg_attr( feature = "serde-serialize", - serde(bound( - deserialize = "DefaultAllocator: Allocator + + serde(bound(deserialize = "DefaultAllocator: Allocator + Allocator, VectorN: Deserialize<'de>, - MatrixN: Deserialize<'de>" - )) + MatrixN: Deserialize<'de>")) )] #[derive(Clone, Debug)] pub struct SymmetricEigen @@ -49,7 +45,8 @@ where DefaultAllocator: Allocator + Allocator, MatrixN: Copy, VectorN: Copy, -{} +{ +} impl SymmetricEigen where DefaultAllocator: Allocator + Allocator @@ -60,8 +57,7 @@ where DefaultAllocator: Allocator + Allocator pub fn new(m: MatrixN) -> Self where D: DimSub, - DefaultAllocator: Allocator> + // For tridiagonalization - Allocator>, + DefaultAllocator: Allocator> + Allocator>, { Self::try_new(m, N::RealField::default_epsilon(), 0).unwrap() } @@ -80,8 +76,7 @@ where DefaultAllocator: Allocator + Allocator pub fn try_new(m: MatrixN, eps: N::RealField, max_niter: usize) -> Option where D: DimSub, - DefaultAllocator: Allocator> + // For tridiagonalization - Allocator>, + DefaultAllocator: Allocator> + Allocator>, { Self::do_decompose(m, true, eps, max_niter).map(|(vals, vecs)| SymmetricEigen { eigenvectors: vecs.unwrap(), @@ -97,8 +92,7 @@ where DefaultAllocator: Allocator + Allocator ) -> Option<(VectorN, Option>)> where D: DimSub, - DefaultAllocator: Allocator> + // For tridiagonalization - Allocator>, + DefaultAllocator: Allocator> + Allocator>, { assert!( m.is_square(), @@ -154,7 +148,6 @@ where DefaultAllocator: Allocator + Allocator off_diag[i - 1] = norm; } - let mii = diag[i]; let mjj = diag[j]; let mij = off_diag[i]; @@ -189,8 +182,10 @@ where DefaultAllocator: Allocator + Allocator } } else if subdim == 2 { let m = Matrix2::new( - diag[start], off_diag[start].conjugate(), - off_diag[start], diag[start + 1], + diag[start], + off_diag[start].conjugate(), + off_diag[start], + diag[start + 1], ); let eigvals = m.eigenvalues().unwrap(); let basis = Vector2::new(eigvals.x - diag[start + 1], off_diag[start]); @@ -305,8 +300,10 @@ pub fn wilkinson_shift(tmm: N, tnn: N, tmn: N) -> N { * */ impl, S: Storage> SquareMatrix -where DefaultAllocator: Allocator + Allocator> + - Allocator + Allocator> +where DefaultAllocator: Allocator + + Allocator> + + Allocator + + Allocator> { /// Computes the eigendecomposition of this symmetric matrix. /// @@ -326,7 +323,12 @@ where DefaultAllocator: Allocator + Allocator> + /// * `max_niter` − maximum total number of iterations performed by the algorithm. If this /// number of iteration is exceeded, `None` is returned. If `niter == 0`, then the algorithm /// continues indefinitely until convergence. - pub fn try_symmetric_eigen(self, eps: N::RealField, max_niter: usize) -> Option> { + pub fn try_symmetric_eigen( + self, + eps: N::RealField, + max_niter: usize, + ) -> Option> + { SymmetricEigen::try_new(self.into_owned(), eps, max_niter) } @@ -334,9 +336,14 @@ where DefaultAllocator: Allocator + Allocator> + /// /// Only the lower-triangular part of the matrix is read. pub fn symmetric_eigenvalues(&self) -> VectorN { - SymmetricEigen::do_decompose(self.clone_owned(), false, N::RealField::default_epsilon(), 0) - .unwrap() - .0 + SymmetricEigen::do_decompose( + self.clone_owned(), + false, + N::RealField::default_epsilon(), + 0, + ) + .unwrap() + .0 } } diff --git a/src/linalg/symmetric_tridiagonal.rs b/src/linalg/symmetric_tridiagonal.rs index 40da8677..49502efa 100644 --- a/src/linalg/symmetric_tridiagonal.rs +++ b/src/linalg/symmetric_tridiagonal.rs @@ -1,11 +1,11 @@ #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Serialize}; -use alga::general::ComplexField; use crate::allocator::Allocator; use crate::base::{DefaultAllocator, MatrixMN, MatrixN, SquareMatrix, VectorN}; use crate::dimension::{DimDiff, DimSub, U1}; use crate::storage::Storage; +use simba::scalar::ComplexField; use crate::linalg::householder; @@ -13,21 +13,17 @@ use crate::linalg::householder; #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[cfg_attr( feature = "serde-serialize", - serde(bound( - serialize = "DefaultAllocator: Allocator + + serde(bound(serialize = "DefaultAllocator: Allocator + Allocator>, MatrixN: Serialize, - VectorN>: Serialize" - )) + VectorN>: Serialize")) )] #[cfg_attr( feature = "serde-serialize", - serde(bound( - deserialize = "DefaultAllocator: Allocator + + serde(bound(deserialize = "DefaultAllocator: Allocator + Allocator>, MatrixN: Deserialize<'de>, - VectorN>: Deserialize<'de>" - )) + VectorN>: Deserialize<'de>")) )] #[derive(Clone, Debug)] pub struct SymmetricTridiagonal> @@ -42,7 +38,8 @@ where DefaultAllocator: Allocator + Allocator>, MatrixN: Copy, VectorN>: Copy, -{} +{ +} impl> SymmetricTridiagonal where DefaultAllocator: Allocator + Allocator> @@ -98,9 +95,15 @@ where DefaultAllocator: Allocator + Allocator> /// Retrieve the orthogonal transformation, diagonal, and off diagonal elements of this /// decomposition. - pub fn unpack(self) -> (MatrixN, VectorN, VectorN>) - where DefaultAllocator: Allocator - + Allocator> { + pub fn unpack( + self, + ) -> ( + MatrixN, + VectorN, + VectorN>, + ) + where DefaultAllocator: Allocator + Allocator> + { let diag = self.diagonal(); let q = self.q(); @@ -108,15 +111,22 @@ where DefaultAllocator: Allocator + Allocator> } /// Retrieve the diagonal, and off diagonal elements of this decomposition. - pub fn unpack_tridiagonal(self) -> (VectorN, VectorN>) - where DefaultAllocator: Allocator - + Allocator> { + pub fn unpack_tridiagonal( + self, + ) -> ( + VectorN, + VectorN>, + ) + where DefaultAllocator: Allocator + Allocator> + { (self.diagonal(), self.off_diagonal.map(N::modulus)) } /// The diagonal components of this decomposition. pub fn diagonal(&self) -> VectorN - where DefaultAllocator: Allocator { self.tri.map_diagonal(|e| e.real()) } + where DefaultAllocator: Allocator { + self.tri.map_diagonal(|e| e.real()) + } /// The off-diagonal components of this decomposition. pub fn off_diagonal(&self) -> VectorN> diff --git a/src/sparse/cs_matrix.rs b/src/sparse/cs_matrix.rs index 9fc91af0..ffe87e5f 100644 --- a/src/sparse/cs_matrix.rs +++ b/src/sparse/cs_matrix.rs @@ -1,5 +1,5 @@ -use alga::general::ClosedAdd; use num::Zero; +use simba::scalar::ClosedAdd; use std::iter; use std::marker::PhantomData; use std::ops::Range; @@ -7,9 +7,7 @@ use std::slice; use crate::allocator::Allocator; use crate::sparse::cs_utils; -use crate::{ - DefaultAllocator, Dim, Dynamic, Scalar, Vector, VectorN, U1 -}; +use crate::{DefaultAllocator, Dim, Dynamic, Scalar, Vector, VectorN, U1}; pub struct ColumnEntries<'a, N> { curr: usize, @@ -33,9 +31,11 @@ impl<'a, N: Clone> Iterator for ColumnEntries<'a, N> { 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).clone() }, unsafe { + self.v.get_unchecked(self.curr).clone() + }), + ); self.curr += 1; res } diff --git a/src/sparse/cs_matrix_conversion.rs b/src/sparse/cs_matrix_conversion.rs index abf195e2..63a417b2 100644 --- a/src/sparse/cs_matrix_conversion.rs +++ b/src/sparse/cs_matrix_conversion.rs @@ -1,5 +1,5 @@ -use alga::general::ClosedAdd; use num::Zero; +use simba::scalar::ClosedAdd; use crate::allocator::Allocator; use crate::sparse::cs_utils; diff --git a/src/sparse/cs_matrix_ops.rs b/src/sparse/cs_matrix_ops.rs index 8a4c063a..803bc61f 100644 --- a/src/sparse/cs_matrix_ops.rs +++ b/src/sparse/cs_matrix_ops.rs @@ -1,5 +1,5 @@ -use alga::general::{ClosedAdd, ClosedMul}; use num::{One, Zero}; +use simba::scalar::{ClosedAdd, ClosedMul}; use std::ops::{Add, Mul}; use crate::allocator::Allocator; @@ -112,11 +112,11 @@ impl> Vect let col2 = a.column(0); let val = unsafe { *x.vget_unchecked(0) }; self.axpy_sparse(alpha * val, &col2, beta); - + for j in 1..ncols2 { let col2 = a.column(j); let val = unsafe { *x.vget_unchecked(j) }; - + self.axpy_sparse(alpha * val, &col2, N::one()); } } diff --git a/tests/geometry/rotation.rs b/tests/geometry/rotation.rs index c0886754..2ada2939 100644 --- a/tests/geometry/rotation.rs +++ b/tests/geometry/rotation.rs @@ -32,8 +32,8 @@ fn quaternion_euler_angles_issue_494() { #[cfg(feature = "arbitrary")] mod quickcheck_tests { - use alga::general::RealField; use na::{self, Rotation2, Rotation3, Unit, Vector2, Vector3}; + use simba::scalar::RealField; use std::f64; quickcheck! {