From 7c91f2eeb59684270f4d5f6dff3ead748a3e6021 Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sat, 23 Feb 2019 11:24:07 +0100 Subject: [PATCH 01/28] Use Complex instead of Real whenever possible on the base/ module. --- src/base/blas.rs | 107 +++++++++++++++++++++++++++++++- src/base/matrix.rs | 67 ++++++++++---------- src/base/matrix_alga.rs | 33 +++++----- src/base/norm.rs | 99 ++++++++++++++--------------- src/base/statistics.rs | 7 ++- src/base/unit.rs | 19 +++--- src/geometry/quaternion_alga.rs | 3 + src/lib.rs | 12 ++-- 8 files changed, 228 insertions(+), 119 deletions(-) diff --git a/src/base/blas.rs b/src/base/blas.rs index c16496d4..1b415343 100644 --- a/src/base/blas.rs +++ b/src/base/blas.rs @@ -1,4 +1,4 @@ -use alga::general::{ClosedAdd, ClosedMul}; +use alga::general::{ClosedAdd, ClosedMul, Complex}; #[cfg(feature = "std")] use matrixmultiply; use num::{One, Signed, Zero}; @@ -190,6 +190,111 @@ impl> Matri } } +impl> Matrix { + /// The dot product between two complex or real vectors or matrices (seen as vectors). + /// + /// This is the same as `.dot` except that the conjugate of each component of `self` is taken + /// before performing the products. + #[inline] + pub fn cdot(&self, rhs: &Matrix) -> N + where + SB: Storage, + ShapeConstraint: DimEq + DimEq, + { + assert!( + self.nrows() == rhs.nrows(), + "Dot product dimensions mismatch." + ); + + // So we do some special cases for common fixed-size vectors of dimension lower than 8 + // because the `for` loop below won't be very efficient on those. + if (R::is::() || R2::is::()) && (C::is::() || C2::is::()) { + unsafe { + let a = self.get_unchecked((0, 0)).conjugate() * *rhs.get_unchecked((0, 0)); + let b = self.get_unchecked((1, 0)).conjugate() * *rhs.get_unchecked((1, 0)); + + return a + b; + } + } + if (R::is::() || R2::is::()) && (C::is::() || C2::is::()) { + unsafe { + let a = self.get_unchecked((0, 0)).conjugate() * *rhs.get_unchecked((0, 0)); + let b = self.get_unchecked((1, 0)).conjugate() * *rhs.get_unchecked((1, 0)); + let c = self.get_unchecked((2, 0)).conjugate() * *rhs.get_unchecked((2, 0)); + + return a + b + c; + } + } + if (R::is::() || R2::is::()) && (C::is::() || C2::is::()) { + unsafe { + let mut a = self.get_unchecked((0, 0)).conjugate() * *rhs.get_unchecked((0, 0)); + let mut b = self.get_unchecked((1, 0)).conjugate() * *rhs.get_unchecked((1, 0)); + let c = self.get_unchecked((2, 0)).conjugate() * *rhs.get_unchecked((2, 0)); + let d = self.get_unchecked((3, 0)).conjugate() * *rhs.get_unchecked((3, 0)); + + a += c; + b += d; + + return a + b; + } + } + + // All this is inspired from the "unrolled version" discussed in: + // http://blog.theincredibleholk.org/blog/2012/12/10/optimizing-dot-product/ + // + // And this comment from bluss: + // https://users.rust-lang.org/t/how-to-zip-two-slices-efficiently/2048/12 + let mut res = N::zero(); + + // We have to define them outside of the loop (and not inside at first assignment) + // otherwise vectorization won't kick in for some reason. + let mut acc0; + let mut acc1; + let mut acc2; + let mut acc3; + let mut acc4; + let mut acc5; + let mut acc6; + let mut acc7; + + for j in 0..self.ncols() { + let mut i = 0; + + acc0 = N::zero(); + acc1 = N::zero(); + acc2 = N::zero(); + acc3 = N::zero(); + acc4 = N::zero(); + acc5 = N::zero(); + acc6 = N::zero(); + acc7 = N::zero(); + + while self.nrows() - i >= 8 { + acc0 += unsafe { self.get_unchecked((i + 0, j)).conjugate() * *rhs.get_unchecked((i + 0, j)) }; + acc1 += unsafe { self.get_unchecked((i + 1, j)).conjugate() * *rhs.get_unchecked((i + 1, j)) }; + acc2 += unsafe { self.get_unchecked((i + 2, j)).conjugate() * *rhs.get_unchecked((i + 2, j)) }; + acc3 += unsafe { self.get_unchecked((i + 3, j)).conjugate() * *rhs.get_unchecked((i + 3, j)) }; + acc4 += unsafe { self.get_unchecked((i + 4, j)).conjugate() * *rhs.get_unchecked((i + 4, j)) }; + acc5 += unsafe { self.get_unchecked((i + 5, j)).conjugate() * *rhs.get_unchecked((i + 5, j)) }; + acc6 += unsafe { self.get_unchecked((i + 6, j)).conjugate() * *rhs.get_unchecked((i + 6, j)) }; + acc7 += unsafe { self.get_unchecked((i + 7, j)).conjugate() * *rhs.get_unchecked((i + 7, j)) }; + i += 8; + } + + res += acc0 + acc4; + res += acc1 + acc5; + res += acc2 + acc6; + res += acc3 + acc7; + + for k in i..self.nrows() { + res += unsafe { self.get_unchecked((k, j)).conjugate() * *rhs.get_unchecked((k, j)) } + } + } + + res + } +} + impl> Matrix where N: Scalar + Zero + ClosedAdd + ClosedMul { diff --git a/src/base/matrix.rs b/src/base/matrix.rs index fcd53703..f0b74dd7 100644 --- a/src/base/matrix.rs +++ b/src/base/matrix.rs @@ -1,5 +1,4 @@ use num::{One, Zero}; -use num_complex::Complex; #[cfg(feature = "abomonation-serialize")] use std::io::{Result as IOResult, Write}; @@ -17,7 +16,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; #[cfg(feature = "abomonation-serialize")] use abomonation::Abomonation; -use alga::general::{ClosedAdd, ClosedMul, ClosedSub, Real, Ring}; +use alga::general::{ClosedAdd, ClosedMul, ClosedSub, Real, Ring, Complex, Field}; use base::allocator::{Allocator, SameShapeAllocator, SameShapeC, SameShapeR}; use base::constraint::{DimEq, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint}; @@ -906,14 +905,14 @@ impl> Matrix { } } -impl, R, C>> Matrix, R, C, S> { +impl> Matrix { /// Takes the conjugate and transposes `self` and store the result into `out`. #[inline] - pub fn conjugate_transpose_to(&self, out: &mut Matrix, R2, C2, SB>) + pub fn conjugate_transpose_to(&self, out: &mut Matrix) where R2: Dim, C2: Dim, - SB: StorageMut, R2, C2>, + SB: StorageMut, ShapeConstraint: SameNumberOfRows + SameNumberOfColumns, { let (nrows, ncols) = self.shape(); @@ -926,7 +925,7 @@ impl, R, C>> Matrix, R for i in 0..nrows { for j in 0..ncols { unsafe { - *out.get_unchecked_mut((j, i)) = self.get_unchecked((i, j)).conj(); + *out.get_unchecked_mut((j, i)) = self.get_unchecked((i, j)).conjugate(); } } } @@ -934,8 +933,8 @@ impl, R, C>> Matrix, R /// The conjugate transposition of `self`. #[inline] - pub fn conjugate_transpose(&self) -> MatrixMN, C, R> - where DefaultAllocator: Allocator, C, R> { + pub fn conjugate_transpose(&self) -> MatrixMN + where DefaultAllocator: Allocator { let (nrows, ncols) = self.data.shape(); unsafe { @@ -947,7 +946,7 @@ impl, R, C>> Matrix, R } } -impl, D, D>> Matrix, D, D, S> { +impl> Matrix { /// Sets `self` to its conjugate transpose. pub fn conjugate_transpose_mut(&mut self) { assert!( @@ -960,10 +959,10 @@ impl, D, D>> Matrix, D, D, for i in 1..dim { for j in 0..i { unsafe { - let ref_ij = self.get_unchecked_mut((i, j)) as *mut Complex; - let ref_ji = self.get_unchecked_mut((j, i)) as *mut Complex; - let conj_ij = (*ref_ij).conj(); - let conj_ji = (*ref_ji).conj(); + let ref_ij = self.get_unchecked_mut((i, j)) as *mut N; + let ref_ji = self.get_unchecked_mut((j, i)) as *mut N; + let conj_ij = (*ref_ij).conjugate(); + let conj_ji = (*ref_ji).conjugate(); *ref_ij = conj_ji; *ref_ji = conj_ij; } @@ -1407,7 +1406,7 @@ impl> Matrix { } } -impl> Vector +impl> Vector where DefaultAllocator: Allocator { /// Computes the matrix `M` such that for all vector `v` we have `M * v == self.cross(&v)`. @@ -1427,27 +1426,27 @@ where DefaultAllocator: Allocator } } -impl> Matrix { +impl> Matrix { /// The smallest angle between two vectors. #[inline] - pub fn angle(&self, other: &Matrix) -> N + pub fn angle(&self, other: &Matrix) -> N::Real where SB: Storage, ShapeConstraint: DimEq + DimEq, { - let prod = self.dot(other); + let prod = self.cdot(other); let n1 = self.norm(); let n2 = other.norm(); if n1.is_zero() || n2.is_zero() { - N::zero() + N::Real::zero() } else { - let cang = prod / (n1 * n2); + let cang = prod.real() / (n1 * n2); - if cang > N::one() { - N::zero() - } else if cang < -N::one() { - N::pi() + if cang > N::Real::one() { + N::Real::zero() + } else if cang < -N::Real::one() { + N::Real::pi() } else { cang.acos() } @@ -1478,18 +1477,18 @@ impl> Unit> { +impl> Unit> { /// Computes the spherical linear interpolation between two unit vectors. pub fn slerp>( &self, rhs: &Unit>, - t: N, + t: N::Real, ) -> Unit> where DefaultAllocator: Allocator, { // FIXME: the result is wrong when self and rhs are collinear with opposite direction. - self.try_slerp(rhs, t, N::default_epsilon()) + self.try_slerp(rhs, t, N::Real::default_epsilon()) .unwrap_or(Unit::new_unchecked(self.clone_owned())) } @@ -1500,29 +1499,29 @@ impl> Unit> { pub fn try_slerp>( &self, rhs: &Unit>, - t: N, - epsilon: N, + t: N::Real, + epsilon: N::Real, ) -> Option>> where DefaultAllocator: Allocator, { - let c_hang = self.dot(rhs); + let c_hang = self.cdot(rhs).real(); // self == other - if c_hang.abs() >= N::one() { + if c_hang.abs() >= N::Real::one() { return Some(Unit::new_unchecked(self.clone_owned())); } let hang = c_hang.acos(); - let s_hang = (N::one() - c_hang * c_hang).sqrt(); + let s_hang = (N::Real::one() - c_hang * c_hang).sqrt(); // FIXME: what if s_hang is 0.0 ? The result is not well-defined. - if relative_eq!(s_hang, N::zero(), epsilon = epsilon) { + if relative_eq!(s_hang, N::Real::zero(), epsilon = epsilon) { None } else { - let ta = ((N::one() - t) * hang).sin() / s_hang; + let ta = ((N::Real::one() - t) * hang).sin() / s_hang; let tb = (t * hang).sin() / s_hang; - let res = &**self * ta + &**rhs * tb; + let res = &**self * N::from_real(ta) + &**rhs * N::from_real(tb); Some(Unit::new_unchecked(res)) } diff --git a/src/base/matrix_alga.rs b/src/base/matrix_alga.rs index 6ce60809..35db628b 100644 --- a/src/base/matrix_alga.rs +++ b/src/base/matrix_alga.rs @@ -7,7 +7,7 @@ use alga::general::{ AbstractGroup, AbstractGroupAbelian, AbstractLoop, AbstractMagma, AbstractModule, AbstractMonoid, AbstractQuasigroup, AbstractSemigroup, Additive, ClosedAdd, ClosedMul, ClosedNeg, Field, Identity, TwoSidedInverse, JoinSemilattice, Lattice, MeetSemilattice, Module, - Multiplicative, Real, RingCommutative, + Multiplicative, Real, RingCommutative, Complex }; use alga::linear::{ FiniteDimInnerSpace, FiniteDimVectorSpace, InnerSpace, NormedSpace, VectorSpace, @@ -145,16 +145,19 @@ where } } -impl NormedSpace for MatrixMN +impl NormedSpace for MatrixMN where DefaultAllocator: Allocator { + type Real = N::Real; + type Complex = N; + #[inline] - fn norm_squared(&self) -> N { + fn norm_squared(&self) -> N::Real { self.norm_squared() } #[inline] - fn norm(&self) -> N { + fn norm(&self) -> N::Real { self.norm() } @@ -164,34 +167,32 @@ where DefaultAllocator: Allocator } #[inline] - fn normalize_mut(&mut self) -> N { + fn normalize_mut(&mut self) -> N::Real { self.normalize_mut() } #[inline] - fn try_normalize(&self, min_norm: N) -> Option { + fn try_normalize(&self, min_norm: N::Real) -> Option { self.try_normalize(min_norm) } #[inline] - fn try_normalize_mut(&mut self, min_norm: N) -> Option { + fn try_normalize_mut(&mut self, min_norm: N::Real) -> Option { self.try_normalize_mut(min_norm) } } -impl InnerSpace for MatrixMN +impl InnerSpace for MatrixMN where DefaultAllocator: Allocator { - type Real = N; - #[inline] - fn angle(&self, other: &Self) -> N { + fn angle(&self, other: &Self) -> N::Real { self.angle(other) } #[inline] fn inner_product(&self, other: &Self) -> N { - self.dot(other) + self.cdot(other) } } @@ -199,7 +200,7 @@ where DefaultAllocator: Allocator // In particular: // − use `x()` instead of `::canonical_basis_element` // − use `::new(x, y, z)` instead of `::from_slice` -impl FiniteDimInnerSpace for MatrixMN +impl FiniteDimInnerSpace for MatrixMN where DefaultAllocator: Allocator { #[inline] @@ -215,7 +216,7 @@ where DefaultAllocator: Allocator } } - if vs[i].try_normalize_mut(N::zero()).is_some() { + if vs[i].try_normalize_mut(N::Real::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); @@ -268,7 +269,7 @@ where DefaultAllocator: Allocator let v = &vs[0]; let mut a; - if v[0].abs() > v[1].abs() { + if v[0].modulus() > v[1].modulus() { a = Self::from_column_slice(&[v[2], N::zero(), -v[0]]); } else { a = Self::from_column_slice(&[N::zero(), -v[2], v[1]]); @@ -300,7 +301,7 @@ where DefaultAllocator: Allocator elt -= v * elt.dot(v) } - if let Some(subsp_elt) = elt.try_normalize(N::zero()) { + if let Some(subsp_elt) = elt.try_normalize(N::Real::zero()) { if !f(&subsp_elt) { return; }; diff --git a/src/base/norm.rs b/src/base/norm.rs index 68fb88a1..1b814d74 100644 --- a/src/base/norm.rs +++ b/src/base/norm.rs @@ -1,8 +1,8 @@ -use num::Signed; +use num::{Signed, Zero}; use std::cmp::PartialOrd; use allocator::Allocator; -use ::{Real, Scalar}; +use ::{Real, Complex, Scalar}; use storage::{Storage, StorageMut}; use base::{DefaultAllocator, Matrix, Dim, MatrixMN}; use constraint::{SameNumberOfRows, SameNumberOfColumns, ShapeConstraint}; @@ -12,12 +12,12 @@ use constraint::{SameNumberOfRows, SameNumberOfColumns, ShapeConstraint}; /// A trait for abstract matrix norms. /// /// This may be moved to the alga crate in the future. -pub trait Norm { +pub trait Norm { /// Apply this norm to the given matrix. - fn norm(&self, m: &Matrix) -> N + fn norm(&self, m: &Matrix) -> N::Real where R: Dim, C: Dim, S: Storage; /// Use the metric induced by this norm to compute the metric distance between the two given matrices. - fn metric_distance(&self, m1: &Matrix, m2: &Matrix) -> N + fn metric_distance(&self, m1: &Matrix, m2: &Matrix) -> N::Real where R1: Dim, C1: Dim, S1: Storage, R2: Dim, C2: Dim, S2: Storage, ShapeConstraint: SameNumberOfRows + SameNumberOfColumns; @@ -30,60 +30,60 @@ pub struct LpNorm(pub i32); /// L-infinite norm aka. Chebytchev norm aka. uniform norm aka. suppremum norm. pub struct UniformNorm; -impl Norm for EuclideanNorm { +impl Norm for EuclideanNorm { #[inline] - fn norm(&self, m: &Matrix) -> N + fn norm(&self, m: &Matrix) -> N::Real where R: Dim, C: Dim, S: Storage { - m.norm_squared().sqrt() + m.cdot(m).real().sqrt() } #[inline] - fn metric_distance(&self, m1: &Matrix, m2: &Matrix) -> N + fn metric_distance(&self, m1: &Matrix, m2: &Matrix) -> N::Real where R1: Dim, C1: Dim, S1: Storage, R2: Dim, C2: Dim, S2: Storage, ShapeConstraint: SameNumberOfRows + SameNumberOfColumns { - m1.zip_fold(m2, N::zero(), |acc, a, b| { + m1.zip_fold(m2, N::Real::zero(), |acc, a, b| { let diff = a - b; - acc + diff * diff + acc + (diff.conjugate() * diff).real() }).sqrt() } } -impl Norm for LpNorm { +impl Norm for LpNorm { #[inline] - fn norm(&self, m: &Matrix) -> N + fn norm(&self, m: &Matrix) -> N::Real where R: Dim, C: Dim, S: Storage { - m.fold(N::zero(), |a, b| { - a + b.abs().powi(self.0) + m.fold(N::Real::zero(), |a, b| { + a + b.modulus().powi(self.0) }).powf(::convert(1.0 / (self.0 as f64))) } #[inline] - fn metric_distance(&self, m1: &Matrix, m2: &Matrix) -> N + fn metric_distance(&self, m1: &Matrix, m2: &Matrix) -> N::Real where R1: Dim, C1: Dim, S1: Storage, R2: Dim, C2: Dim, S2: Storage, ShapeConstraint: SameNumberOfRows + SameNumberOfColumns { - m1.zip_fold(m2, N::zero(), |acc, a, b| { + m1.zip_fold(m2, N::Real::zero(), |acc, a, b| { let diff = a - b; - acc + diff.abs().powi(self.0) + acc + diff.modulus().powi(self.0) }).powf(::convert(1.0 / (self.0 as f64))) } } -impl Norm for UniformNorm { +impl Norm for UniformNorm { #[inline] - fn norm(&self, m: &Matrix) -> N + fn norm(&self, m: &Matrix) -> N::Real where R: Dim, C: Dim, S: Storage { - m.amax() + m.fold(N::Real::zero(), |acc, a| acc.max(a.modulus())) } #[inline] - fn metric_distance(&self, m1: &Matrix, m2: &Matrix) -> N + fn metric_distance(&self, m1: &Matrix, m2: &Matrix) -> N::Real where R1: Dim, C1: Dim, S1: Storage, R2: Dim, C2: Dim, S2: Storage, ShapeConstraint: SameNumberOfRows + SameNumberOfColumns { - m1.zip_fold(m2, N::zero(), |acc, a, b| { - let val = (a - b).abs(); + m1.zip_fold(m2, N::Real::zero(), |acc, a, b| { + let val = (a - b).modulus(); if val > acc { val } else { @@ -94,15 +94,15 @@ impl Norm for UniformNorm { } -impl> Matrix { +impl> Matrix { /// The squared L2 norm of this vector. #[inline] - pub fn norm_squared(&self) -> N { - let mut res = N::zero(); + pub fn norm_squared(&self) -> N::Real { + let mut res = N::Real::zero(); for i in 0..self.ncols() { let col = self.column(i); - res += col.dot(&col) + res += col.cdot(&col).real() } res @@ -112,7 +112,7 @@ impl> Matrix { /// /// Use `.apply_norm` to apply a custom norm. #[inline] - pub fn norm(&self) -> N { + pub fn norm(&self) -> N::Real { self.norm_squared().sqrt() } @@ -120,7 +120,7 @@ impl> Matrix { /// /// Use `.apply_metric_distance` to apply a custom norm. #[inline] - pub fn metric_distance(&self, rhs: &Matrix) -> N + pub fn metric_distance(&self, rhs: &Matrix) -> N::Real where R2: Dim, C2: Dim, S2: Storage, ShapeConstraint: SameNumberOfRows + SameNumberOfColumns { self.apply_metric_distance(rhs, &EuclideanNorm) @@ -139,7 +139,7 @@ impl> Matrix { /// assert_eq!(v.apply_norm(&EuclideanNorm), v.norm()); /// ``` #[inline] - pub fn apply_norm(&self, norm: &impl Norm) -> N { + pub fn apply_norm(&self, norm: &impl Norm) -> N::Real { norm.norm(self) } @@ -158,16 +158,10 @@ impl> Matrix { /// assert_eq!(v1.apply_metric_distance(&v2, &EuclideanNorm), (v1 - v2).norm()); /// ``` #[inline] - pub fn apply_metric_distance(&self, rhs: &Matrix, norm: &impl Norm) -> N + pub fn apply_metric_distance(&self, rhs: &Matrix, norm: &impl Norm) -> N::Real where R2: Dim, C2: Dim, S2: Storage, ShapeConstraint: SameNumberOfRows + SameNumberOfColumns { - norm.metric_distance(self,rhs) - } - - /// The Lp norm of this matrix. - #[inline] - pub fn lp_norm(&self, p: i32) -> N { - self.apply_norm(&LpNorm(p)) + norm.metric_distance(self, rhs) } /// A synonym for the norm of this matrix. @@ -176,7 +170,7 @@ impl> Matrix { /// /// This function is simply implemented as a call to `norm()` #[inline] - pub fn magnitude(&self) -> N { + pub fn magnitude(&self) -> N::Real { self.norm() } @@ -186,7 +180,7 @@ impl> Matrix { /// /// This function is simply implemented as a call to `norm_squared()` #[inline] - pub fn magnitude_squared(&self) -> N { + pub fn magnitude_squared(&self) -> N::Real { self.norm_squared() } @@ -194,29 +188,36 @@ impl> Matrix { #[inline] pub fn normalize(&self) -> MatrixMN where DefaultAllocator: Allocator { - self / self.norm() + self.map(|e| e.unscale(self.norm())) } /// Returns a normalized version of this matrix unless its norm as smaller or equal to `eps`. #[inline] - pub fn try_normalize(&self, min_norm: N) -> Option> + pub fn try_normalize(&self, min_norm: N::Real) -> Option> where DefaultAllocator: Allocator { let n = self.norm(); if n <= min_norm { None } else { - Some(self / n) + Some(self.map(|e| e.unscale(n))) } } + + /// The Lp norm of this matrix. + #[inline] + pub fn lp_norm(&self, p: i32) -> N::Real { + self.apply_norm(&LpNorm(p)) + } } -impl> Matrix { + +impl> Matrix { /// Normalizes this matrix in-place and returns its norm. #[inline] - pub fn normalize_mut(&mut self) -> N { + pub fn normalize_mut(&mut self) -> N::Real { let n = self.norm(); - *self /= n; + self.apply(|e| e.unscale(n)); n } @@ -225,13 +226,13 @@ impl> Matrix { /// /// If the normalization succeeded, returns the old normal of this matrix. #[inline] - pub fn try_normalize_mut(&mut self, min_norm: N) -> Option { + pub fn try_normalize_mut(&mut self, min_norm: N::Real) -> Option { let n = self.norm(); if n <= min_norm { None } else { - *self /= n; + self.apply(|e| e.unscale(n)); Some(n) } } diff --git a/src/base/statistics.rs b/src/base/statistics.rs index 11cc9e1c..ce162340 100644 --- a/src/base/statistics.rs +++ b/src/base/statistics.rs @@ -1,8 +1,9 @@ -use ::{Real, Dim, Matrix, VectorN, RowVectorN, DefaultAllocator, U1, VectorSliceN}; +use ::{Scalar, Dim, Matrix, VectorN, RowVectorN, DefaultAllocator, U1, VectorSliceN}; +use alga::general::{Field, SupersetOf}; use storage::Storage; use allocator::Allocator; -impl> Matrix { +impl> Matrix { /// Returns a row vector where each element is the result of the application of `f` on the /// corresponding column of the original matrix. #[inline] @@ -53,7 +54,7 @@ impl> Matrix { } } -impl> Matrix { +impl, R: Dim, C: Dim, S: Storage> Matrix { /* * * Sum computation. diff --git a/src/base/unit.rs b/src/base/unit.rs index 3d0a9c03..b57ca3d3 100644 --- a/src/base/unit.rs +++ b/src/base/unit.rs @@ -10,7 +10,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; #[cfg(feature = "abomonation-serialize")] use abomonation::Abomonation; -use alga::general::SubsetOf; +use alga::general::{SubsetOf, Complex}; use alga::linear::NormedSpace; use ::Real; @@ -66,13 +66,13 @@ impl Unit { /// /// Returns `None` if the norm was smaller or equal to `min_norm`. #[inline] - pub fn try_new(value: T, min_norm: T::Field) -> Option { + pub fn try_new(value: T, min_norm: T::Real) -> Option { 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. #[inline] - pub fn new_and_get(mut value: T) -> (Self, T::Field) { + pub fn new_and_get(mut value: T) -> (Self, T::Real) { let n = value.normalize_mut(); (Unit { value: value }, n) @@ -82,7 +82,7 @@ impl Unit { /// /// 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::Field) -> Option<(Self, T::Field)> { + pub fn try_new_and_get(mut value: T, min_norm: T::Real) -> Option<(Self, T::Real)> { if let Some(n) = value.try_normalize_mut(min_norm) { Some((Unit { value: value }, n)) } else { @@ -96,7 +96,7 @@ impl Unit { /// 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::Field { + pub fn renormalize(&mut self) -> T::Real { self.value.normalize_mut() } @@ -104,12 +104,11 @@ impl Unit { /// This is useful when repeated computations might cause a drift in the norm /// because of float inaccuracies. #[inline] - pub fn renormalize_fast(&mut self) - where T::Field: Real { + pub fn renormalize_fast(&mut self) { let sq_norm = self.value.norm_squared(); - let _3: T::Field = ::convert(3.0); - let _0_5: T::Field = ::convert(0.5); - self.value *= _0_5 * (_3 - sq_norm); + let _3: T::Real = ::convert(3.0); + let _0_5: T::Real = ::convert(0.5); + self.value *= T::Complex::from_real(_0_5 * (_3 - sq_norm)); } } diff --git a/src/geometry/quaternion_alga.rs b/src/geometry/quaternion_alga.rs index 529d27f4..22534b1a 100644 --- a/src/geometry/quaternion_alga.rs +++ b/src/geometry/quaternion_alga.rs @@ -118,6 +118,9 @@ impl FiniteDimVectorSpace for Quaternion { } impl NormedSpace for Quaternion { + type Real = N; + type Complex = N; + #[inline] fn norm_squared(&self) -> N { self.coords.norm_squared() diff --git a/src/lib.rs b/src/lib.rs index 80149c7c..282661b0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -160,7 +160,7 @@ use alga::linear::SquareMatrix as AlgaSquareMatrix; use alga::linear::{EuclideanSpace, FiniteDimVectorSpace, InnerSpace, NormedSpace}; use num::Signed; -pub use alga::general::{Id, Real}; +pub use alga::general::{Id, Real, Complex}; /* * @@ -481,7 +481,7 @@ pub fn angle(a: &V, b: &V) -> V::Real { /// 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::Field { +pub fn norm(v: &V) -> V::Real { v.norm() } @@ -501,7 +501,7 @@ pub fn norm(v: &V) -> V::Field { /// 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::Field { +pub fn norm_squared(v: &V) -> V::Real { v.norm_squared() } @@ -521,7 +521,7 @@ pub fn norm_squared(v: &V) -> V::Field { /// 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::Field { +pub fn magnitude(v: &V) -> V::Real { v.norm() } @@ -542,7 +542,7 @@ pub fn magnitude(v: &V) -> V::Field { /// 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::Field { +pub fn magnitude_squared(v: &V) -> V::Real { v.norm_squared() } @@ -570,7 +570,7 @@ pub fn normalize(v: &V) -> V { /// 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::Field) -> Option { +pub fn try_normalize(v: &V, min_norm: V::Real) -> Option { v.try_normalize(min_norm) } From 77f048b6b9739c905d3a21ca25fc4a92a1175a61 Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sat, 2 Mar 2019 19:33:49 +0100 Subject: [PATCH 02/28] WIP use Complex instead of Real whenever possible on the linalg module. --- Cargo.toml | 5 +- src/base/blas.rs | 118 ++++++++++++++++ src/base/matrix.rs | 73 +++++++++- src/base/ops.rs | 21 ++- src/base/properties.rs | 17 ++- src/geometry/reflection.rs | 13 +- src/linalg/bidiagonal.rs | 12 +- src/linalg/cholesky.rs | 13 +- src/linalg/determinant.rs | 4 +- src/linalg/eigen.rs | 20 +-- src/linalg/full_piv_lu.rs | 14 +- src/linalg/givens.rs | 153 +++++++++++++++++++- src/linalg/hessenberg.rs | 10 +- src/linalg/householder.rs | 36 ++--- src/linalg/inverse.rs | 8 +- src/linalg/lu.rs | 18 +-- src/linalg/qr.rs | 12 +- src/linalg/schur.rs | 91 ++++++------ src/linalg/solve.rs | 4 +- src/linalg/symmetric_eigen.rs | 62 ++++----- src/linalg/symmetric_tridiagonal.rs | 23 ++-- tests/core/helper.rs | 54 ++++++++ tests/core/matrix.rs | 2 +- tests/core/mod.rs | 4 + tests/geometry/isometry.rs | 6 +- tests/geometry/similarity.rs | 8 +- tests/geometry/unit_complex.rs | 2 +- tests/lib.rs | 5 +- tests/linalg/bidiagonal.rs | 16 ++- tests/linalg/eigen.rs | 18 ++- tests/linalg/hessenberg.rs | 9 +- tests/linalg/lu.rs | 186 ++++++++++++++----------- tests/linalg/qr.rs | 207 +++++++++++++++------------- tests/linalg/tridiagonal.rs | 43 +++--- 34 files changed, 878 insertions(+), 409 deletions(-) create mode 100644 tests/core/helper.rs diff --git a/Cargo.toml b/Cargo.toml index 43323c94..d44431c1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,7 @@ arbitrary = [ "quickcheck" ] serde-serialize = [ "serde", "serde_derive", "num-complex/serde" ] abomonation-serialize = [ "abomonation" ] sparse = [ ] -debug = [ ] +debug = [ "approx/num-complex", "rand/std" ] alloc = [ ] io = [ "pest", "pest_derive" ] @@ -53,3 +53,6 @@ rand_xorshift = "0.1" [workspace] members = [ "nalgebra-lapack", "nalgebra-glm" ] + +[patch.crates-io] +alga = { path = "../alga/alga" } diff --git a/src/base/blas.rs b/src/base/blas.rs index 1b415343..6c0c029d 100644 --- a/src/base/blas.rs +++ b/src/base/blas.rs @@ -13,6 +13,39 @@ use base::dimension::{Dim, Dynamic, U1, U2, U3, U4}; use base::storage::{Storage, StorageMut}; use base::{DefaultAllocator, Matrix, Scalar, SquareMatrix, Vector}; + +// FIXME: find a way to avoid code duplication just for complex number support. +impl> Vector { + /// Computes the index of the vector component with the largest complex or real absolute value. + /// + /// # Examples: + /// + /// ``` + /// # use num_complex::Complex; + /// # use nalgebra::Vector3; + /// let vec = Vector3::new(Complex::new(11.0, 3.0), Complex::new(-15.0, 0.0), Complex::new(13.0, 5.0)); + /// assert_eq!(vec.icamax(), 2); + /// ``` + #[inline] + pub fn icamax(&self) -> usize { + assert!(!self.is_empty(), "The input vector must not be empty."); + + let mut the_max = unsafe { self.vget_unchecked(0).asum() }; + let mut the_i = 0; + + for i in 1..self.nrows() { + let val = unsafe { self.vget_unchecked(i).asum() }; + + if val > the_max { + the_max = val; + the_i = i; + } + } + + the_i + } +} + impl> Vector { /// Computes the index and value of the vector component with the largest value. /// @@ -157,6 +190,41 @@ impl> Vector { } } +// FIXME: find a way to avoid code duplication just for complex number support. +impl> Matrix { + /// Computes the index of the matrix component with the largest absolute value. + /// + /// # Examples: + /// + /// ``` + /// # use nalgebra::Matrix2x3; + /// let mat = Matrix2x3::new(Complex::new(11.0, 1.0), Complex::new(-12.0, 2.0), Complex::new(13.0, 3.0), + /// Complex::new(21.0, 43.0), Complex::new(22.0, 5.0), Complex::new(-23.0, 0.0); + /// assert_eq!(mat.iamax_full(), (1, 0)); + /// ``` + #[inline] + pub fn icamax_full(&self) -> (usize, usize) { + assert!(!self.is_empty(), "The input matrix must not be empty."); + + let mut the_max = unsafe { self.get_unchecked((0, 0)).asum() }; + let mut the_ij = (0, 0); + + for j in 0..self.ncols() { + for i in 0..self.nrows() { + let val = unsafe { self.get_unchecked((i, j)).asum() }; + + if val > the_max { + the_max = val; + the_ij = (i, j); + } + } + } + + the_ij + } +} + + impl> Matrix { /// Computes the index of the matrix component with the largest absolute value. /// @@ -705,6 +773,56 @@ where } } +// FIXME: duplicate code +impl> Matrix + where N: Complex + Zero + ClosedAdd + ClosedMul +{ + /// Computes `self = alpha * x * y.transpose() + beta * self`. + /// + /// If `beta` is zero, `self` is never read. + /// + /// # Examples: + /// + /// ``` + /// # use nalgebra::{Matrix2x3, Vector2, Vector3}; + /// let mut mat = Matrix2x3::repeat(4.0); + /// let vec1 = Vector2::new(1.0, 2.0); + /// let vec2 = Vector3::new(0.1, 0.2, 0.3); + /// let expected = vec1 * vec2.transpose() * 10.0 + mat * 5.0; + /// + /// mat.ger(10.0, &vec1, &vec2, 5.0); + /// assert_eq!(mat, expected); + /// ``` + #[inline] + pub fn gerc( + &mut self, + alpha: N, + x: &Vector, + y: &Vector, + beta: N, + ) where + N: One, + SB: Storage, + SC: Storage, + ShapeConstraint: DimEq + DimEq, + { + let (nrows1, ncols1) = self.shape(); + let dim2 = x.nrows(); + let dim3 = y.nrows(); + + assert!( + nrows1 == dim2 && ncols1 == dim3, + "ger: dimensions mismatch." + ); + + for j in 0..ncols1 { + // FIXME: avoid bound checks. + let val = unsafe { y.vget_unchecked(j).conjugate() }; + self.column_mut(j).axpy(alpha * val, x, beta); + } + } +} + impl> Matrix where N: Scalar + Zero + ClosedAdd + ClosedMul { diff --git a/src/base/matrix.rs b/src/base/matrix.rs index f0b74dd7..3fa276f0 100644 --- a/src/base/matrix.rs +++ b/src/base/matrix.rs @@ -944,6 +944,47 @@ impl> Matrix { res } } + + /// The conjugate of `self`. + #[inline] + pub fn conjugate(&self) -> MatrixMN + where DefaultAllocator: Allocator { + self.map(|e| e.conjugate()) + } + + /// Divides each component of `self` by the given real. + #[inline] + pub fn unscale(&self, real: N::Real) -> MatrixMN + where DefaultAllocator: Allocator { + self.map(|e| e.unscale(real)) + } + + /// Multiplies each component of `self` by the given real. + #[inline] + pub fn scale(&self, real: N::Real) -> MatrixMN + where DefaultAllocator: Allocator { + self.map(|e| e.scale(real)) + } +} + +impl> Matrix { + /// The conjugate of `self` computed in-place. + #[inline] + pub fn conjugate_mut(&mut self) { + self.apply(|e| e.conjugate()) + } + + /// Divides each component of `self` by the given real. + #[inline] + pub fn unscale_mut(&mut self, real: N::Real) { + self.apply(|e| e.unscale(real)) + } + + /// Multiplies each component of `self` by the given real. + #[inline] + pub fn scale_mut(&mut self, real: N::Real) { + self.apply(|e| e.scale(real)) + } } impl> Matrix { @@ -975,7 +1016,7 @@ impl> SquareMatrix { /// Creates a square matrix with its diagonal set to `diag` and all other entries set to 0. #[inline] pub fn diagonal(&self) -> VectorN - where DefaultAllocator: Allocator { + where DefaultAllocator: Allocator { assert!( self.is_square(), "Unable to get the diagonal of a non-square matrix." @@ -996,7 +1037,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: Ring { assert!( self.is_square(), "Cannot compute the trace of non-square matrix." @@ -1013,6 +1054,34 @@ impl> SquareMatrix { } } +impl> SquareMatrix { + /// The symmetric part of `self`, i.e., `0.5 * (self + self.transpose())`. + #[inline] + pub fn symmetric_part(&self) -> MatrixMN + where DefaultAllocator: Allocator { + assert!(self.is_square(), "Cannot compute the symmetric part of a non-square matrix."); + let mut tr = self.transpose(); + tr += self; + tr *= ::convert::<_, N>(0.5); + tr + } + + /// The hermitian part of `self`, i.e., `0.5 * (self + self.conjugate_transpose())`. + #[inline] + pub fn hermitian_part(&self) -> MatrixMN + where DefaultAllocator: Allocator { + assert!(self.is_square(), "Cannot compute the hermitian part of a non-square matrix."); + let nrows = self.data.shape().0; + + unsafe { + let mut tr = self.conjugate_transpose(); + tr += self; + tr *= ::convert::<_, N>(0.5); + tr + } + } +} + impl + IsNotStaticOne, S: Storage> Matrix { /// Yields the homogeneous matrix for this matrix, i.e., appending an additional dimension and diff --git a/src/base/ops.rs b/src/base/ops.rs index 96d4626f..bee584b6 100644 --- a/src/base/ops.rs +++ b/src/base/ops.rs @@ -5,7 +5,7 @@ use std::ops::{ Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign, }; -use alga::general::{ClosedAdd, ClosedDiv, ClosedMul, ClosedNeg, ClosedSub}; +use alga::general::{Complex, ClosedAdd, ClosedDiv, ClosedMul, ClosedNeg, ClosedSub}; use base::allocator::{Allocator, SameShapeAllocator, SameShapeC, SameShapeR}; use base::constraint::{ @@ -760,6 +760,25 @@ where } } +// XXX: avoid code duplication. +impl> Matrix { + /// Returns the absolute value of the component with the largest absolute value. + #[inline] + pub fn camax(&self) -> N::Real { + let mut max = N::Real::zero(); + + for e in self.iter() { + let ae = e.asum(); + + if ae > max { + max = ae; + } + } + + max + } +} + impl> Matrix { /// Returns the absolute value of the component with the largest absolute value. #[inline] diff --git a/src/base/properties.rs b/src/base/properties.rs index 7e501575..a511c0f8 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, Real}; +use alga::general::{ClosedAdd, ClosedMul, Real, Complex}; use base::allocator::Allocator; use base::dimension::{Dim, DimMin}; @@ -82,20 +82,23 @@ impl> Matrix { true } +} +impl> Matrix { /// Checks that `Mᵀ × M = Id`. /// /// In this definition `Id` is approximately equal to the identity matrix with a relative error /// 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, + where + N: Zero + One + ClosedAdd + ClosedMul + RelativeEq, + S: Storage, + N::Epsilon: Copy, + DefaultAllocator: Allocator + Allocator, { - (self.tr_mul(self)).is_identity(eps) + // FIXME: add a conjugate-transpose-mul + (self.conjugate().tr_mul(self)).is_identity(eps) } } diff --git a/src/geometry/reflection.rs b/src/geometry/reflection.rs index 6b668c6f..ac63b7da 100644 --- a/src/geometry/reflection.rs +++ b/src/geometry/reflection.rs @@ -1,4 +1,4 @@ -use alga::general::Real; +use alga::general::Complex; use base::allocator::Allocator; use base::constraint::{AreMultipliable, DimEq, SameNumberOfRows, ShapeConstraint}; use base::{DefaultAllocator, Matrix, Scalar, Unit, Vector}; @@ -13,7 +13,7 @@ pub struct Reflection> { bias: N, } -impl> Reflection { +impl> Reflection { /// Creates a new reflection wrt the plane orthogonal to the given axis and bias. /// /// The bias is the position of the plane on the axis. In particular, a bias equal to zero @@ -21,7 +21,7 @@ impl> Reflection { pub fn new(axis: Unit>, bias: N) -> Self { Self { axis: axis.into_inner(), - bias: bias, + bias, } } @@ -35,7 +35,7 @@ impl> Reflection { D: DimName, DefaultAllocator: Allocator, { - let bias = pt.coords.dot(axis.as_ref()); + let bias = axis.cdot(&pt.coords); Self::new(axis, bias) } @@ -56,7 +56,7 @@ impl> Reflection { // dot product, and then mutably. Somehow, this allows significantly // better optimizations of the dot product from the compiler. let m_two: N = ::convert(-2.0f64); - let factor = (rhs.column(i).dot(&self.axis) - self.bias) * m_two; + let factor = (self.axis.cdot(&rhs.column(i)) - self.bias) * m_two; rhs.column_mut(i).axpy(factor, &self.axis, N::one()); } } @@ -70,8 +70,9 @@ impl> Reflection { S2: StorageMut, S3: StorageMut, ShapeConstraint: DimEq + AreMultipliable, + DefaultAllocator: Allocator { - rhs.mul_to(&self.axis, work); + rhs.mul_to(&self.axis.conjugate(), work); if !self.bias.is_zero() { work.add_scalar_mut(-self.bias); diff --git a/src/linalg/bidiagonal.rs b/src/linalg/bidiagonal.rs index 3e73c40f..a44be398 100644 --- a/src/linalg/bidiagonal.rs +++ b/src/linalg/bidiagonal.rs @@ -1,7 +1,7 @@ #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Serialize}; -use alga::general::Real; +use alga::general::Complex; use allocator::Allocator; use base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, Unit, VectorN}; use constraint::{DimEq, ShapeConstraint}; @@ -38,7 +38,7 @@ use linalg::householder; )) )] #[derive(Clone, Debug)] -pub struct Bidiagonal, C: Dim> +pub struct Bidiagonal, C: Dim> where DimMinimum: DimSub, DefaultAllocator: Allocator @@ -55,7 +55,7 @@ where upper_diagonal: bool, } -impl, C: Dim> Copy for Bidiagonal +impl, C: Dim> Copy for Bidiagonal where DimMinimum: DimSub, DefaultAllocator: Allocator @@ -66,7 +66,7 @@ where VectorN, U1>>: Copy, {} -impl, C: Dim> Bidiagonal +impl, C: Dim> Bidiagonal where DimMinimum: DimSub, DefaultAllocator: Allocator @@ -273,7 +273,7 @@ where } } -// impl + DimSub> Bidiagonal +// impl + DimSub> Bidiagonal // where DefaultAllocator: Allocator + // Allocator { // /// Solves the linear system `self * x = b`, where `x` is the unknown to be determined. @@ -346,7 +346,7 @@ where // // } // } -impl, C: Dim, S: Storage> Matrix +impl, C: Dim, S: Storage> Matrix where DimMinimum: DimSub, DefaultAllocator: Allocator diff --git a/src/linalg/cholesky.rs b/src/linalg/cholesky.rs index c1fd7b85..96f533e4 100644 --- a/src/linalg/cholesky.rs +++ b/src/linalg/cholesky.rs @@ -1,7 +1,8 @@ #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Serialize}; -use alga::general::Real; +use num::Zero; +use alga::general::Complex; use allocator::Allocator; use base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, SquareMatrix}; @@ -26,19 +27,19 @@ use storage::{Storage, StorageMut}; )) )] #[derive(Clone, Debug)] -pub struct Cholesky +pub struct Cholesky where DefaultAllocator: Allocator { chol: MatrixN, } -impl Copy for Cholesky +impl Copy for Cholesky where DefaultAllocator: Allocator, MatrixN: Copy, {} -impl> Cholesky +impl> Cholesky where DefaultAllocator: Allocator { /// Attempts to compute the Cholesky decomposition of `matrix`. @@ -62,7 +63,7 @@ where DefaultAllocator: Allocator } let diag = unsafe { *matrix.get_unchecked((j, j)) }; - if diag > N::zero() { + if diag.real() > N::Real::zero() { let denom = diag.sqrt(); unsafe { *matrix.get_unchecked_mut((j, j)) = denom; @@ -144,7 +145,7 @@ where DefaultAllocator: Allocator } } -impl, S: Storage> SquareMatrix +impl, S: Storage> SquareMatrix 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 6229da0e..3b0cb73d 100644 --- a/src/linalg/determinant.rs +++ b/src/linalg/determinant.rs @@ -1,4 +1,4 @@ -use alga::general::Real; +use alga::general::Complex; use base::allocator::Allocator; use base::dimension::DimMin; @@ -7,7 +7,7 @@ use base::{DefaultAllocator, SquareMatrix}; use linalg::LU; -impl, S: Storage> SquareMatrix { +impl, S: Storage> SquareMatrix { /// Computes the matrix determinant. /// /// If the matrix has a dimension larger than 3, an LU decomposition is used. diff --git a/src/linalg/eigen.rs b/src/linalg/eigen.rs index c9fe16e6..dd721f81 100644 --- a/src/linalg/eigen.rs +++ b/src/linalg/eigen.rs @@ -1,7 +1,7 @@ #[cfg(feature = "serde-serialize")] use serde::{Serialize, Deserialize}; -use alga::general::Real; +use alga::general::Complex; use num_complex::Complex; use std::cmp; use std::fmt::Display; @@ -17,7 +17,7 @@ use geometry::{Reflection, UnitComplex}; use linalg::householder; use linalg::RealSchur; -/// Eigendecomposition of a matrix with real eigenvalues. +/// Eigendecomposition of a real matrix with real eigenvalues (or complex eigen values for complex matrices). #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[cfg_attr( feature = "serde-serialize", @@ -40,7 +40,7 @@ use linalg::RealSchur; ) )] #[derive(Clone, Debug)] -pub struct RealEigen +pub struct Eigen where DefaultAllocator: Allocator + Allocator, { @@ -48,7 +48,7 @@ where pub eigenvalues: VectorN, } -impl Copy for RealEigen +impl Copy for Eigen where DefaultAllocator: Allocator + Allocator, MatrixN: Copy, @@ -56,7 +56,7 @@ where { } -impl RealEigen +impl Eigen where D: DimSub, // For Hessenberg. ShapeConstraint: DimEq>, // For Hessenberg. @@ -68,8 +68,8 @@ where DefaultAllocator: Allocator, MatrixN: Display, { - /// Computes the eigendecomposition of a diagonalizable matrix with real eigenvalues. - pub fn new(m: MatrixN) -> Option> { + /// Computes the eigendecomposition of a diagonalizable matrix with Complex eigenvalues. + pub fn new(m: MatrixN) -> Option> { assert!( m.is_square(), "Unable to compute the eigendecomposition of a non-square matrix." @@ -80,7 +80,7 @@ where println!("Schur eigenvalues: {}", eigenvalues); - // Check that the eigenvalues are all real. + // Check that the eigenvalues are all Complex. for i in 0..dim - 1 { if !eigenvalues[(i + 1, i)].is_zero() { return None; @@ -112,8 +112,8 @@ where let _ = eigenvectors.column_mut(i).normalize_mut(); } - Some(RealEigen { - eigenvectors: eigenvectors, + Some(Eigen { + eigenvectors, eigenvalues: eigenvalues.diagonal(), }) } diff --git a/src/linalg/full_piv_lu.rs b/src/linalg/full_piv_lu.rs index 962d4d8b..353a5d1e 100644 --- a/src/linalg/full_piv_lu.rs +++ b/src/linalg/full_piv_lu.rs @@ -1,7 +1,7 @@ #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Serialize}; -use alga::general::Real; +use alga::general::Complex; use allocator::Allocator; use base::{DefaultAllocator, Matrix, MatrixMN, MatrixN}; use constraint::{SameNumberOfRows, ShapeConstraint}; @@ -32,7 +32,7 @@ use linalg::PermutationSequence; )) )] #[derive(Clone, Debug)] -pub struct FullPivLU, C: Dim> +pub struct FullPivLU, C: Dim> where DefaultAllocator: Allocator + Allocator<(usize, usize), DimMinimum> { lu: MatrixMN, @@ -40,14 +40,14 @@ where DefaultAllocator: Allocator + Allocator<(usize, usize), DimMinimu q: PermutationSequence>, } -impl, C: Dim> Copy for FullPivLU +impl, C: Dim> Copy for FullPivLU where DefaultAllocator: Allocator + Allocator<(usize, usize), DimMinimum>, MatrixMN: Copy, PermutationSequence>: Copy, {} -impl, C: Dim> FullPivLU +impl, C: Dim> FullPivLU where DefaultAllocator: Allocator + Allocator<(usize, usize), DimMinimum> { /// Computes the LU decomposition with full pivoting of `matrix`. @@ -69,7 +69,7 @@ where DefaultAllocator: Allocator + Allocator<(usize, usize), DimMinimu } for i in 0..min_nrows_ncols.value() { - let piv = matrix.slice_range(i.., i..).iamax_full(); + let piv = matrix.slice_range(i.., i..).icamax_full(); let row_piv = piv.0 + i; let col_piv = piv.1 + i; let diag = matrix[(row_piv, col_piv)]; @@ -156,7 +156,7 @@ where DefaultAllocator: Allocator + Allocator<(usize, usize), DimMinimu } } -impl> FullPivLU +impl> FullPivLU where DefaultAllocator: Allocator + Allocator<(usize, usize), D> { /// Solves the linear system `self * x = b`, where `x` is the unknown to be determined. @@ -261,7 +261,7 @@ where DefaultAllocator: Allocator + Allocator<(usize, usize), D> } } -impl, C: Dim, S: Storage> Matrix +impl, C: Dim, S: Storage> Matrix where DefaultAllocator: Allocator + Allocator<(usize, usize), DimMinimum> { /// Computes the LU decomposition with full pivoting of `matrix`. diff --git a/src/linalg/givens.rs b/src/linalg/givens.rs index 9175bff9..7e6a881e 100644 --- a/src/linalg/givens.rs +++ b/src/linalg/givens.rs @@ -1,36 +1,175 @@ //! Construction of givens rotations. -use alga::general::Real; -use num_complex::Complex; +use alga::general::{Complex, Real}; +use num_complex::Complex as NumComplex; -use base::dimension::U2; -use base::storage::Storage; -use base::Vector; +use base::dimension::{Dim, U2}; +use base::constraint::{ShapeConstraint, DimEq}; +use base::storage::{Storage, StorageMut}; +use base::{Vector, Matrix}; use geometry::UnitComplex; +/// A Givens rotation. +pub struct GivensRotation { + c: N, + s: N +} + +// XXX: remove this /// Computes the rotation `R` required such that the `y` component of `R * v` is zero. /// /// Returns `None` if no rotation is needed (i.e. if `v.y == 0`). Otherwise, this returns the norm /// of `v` and the rotation `r` such that `R * v = [ |v|, 0.0 ]^t` where `|v|` is the norm of `v`. pub fn cancel_y>(v: &Vector) -> Option<(UnitComplex, N)> { if !v[1].is_zero() { - let c = Complex::new(v[0], -v[1]); + let c = NumComplex::new(v[0], -v[1]); Some(UnitComplex::from_complex_and_get(c)) } else { None } } +// XXX: remove this /// Computes the rotation `R` required such that the `x` component of `R * v` is zero. /// /// Returns `None` if no rotation is needed (i.e. if `v.x == 0`). Otherwise, this returns the norm /// of `v` and the rotation `r` such that `R * v = [ 0.0, |v| ]^t` where `|v|` is the norm of `v`. pub fn cancel_x>(v: &Vector) -> Option<(UnitComplex, N)> { if !v[0].is_zero() { - let c = Complex::new(v[1], v[0]); + let c = NumComplex::new(v[1], v[0]); Some(UnitComplex::from_complex_and_get(c)) } else { None } } + + +// Matrix = UnitComplex * Matrix +impl GivensRotation { + /// Initializes a Givens rotation form its non-normalized cosine an sine components. + pub fn new(c: N, s: N) -> Self { + let denom = (c.modulus_squared() + s.modulus_squared()).sqrt(); + Self { + c: c.unscale(denom), + s: s.unscale(denom) + } + } + + /// Initializes a Givens rotation form its non-normalized cosine an sine components. + pub fn try_new(c: N, s: N, eps: N::Real) -> Option { + let denom = (c.modulus_squared() + s.modulus_squared()).sqrt(); + + if denom > eps { + Some(Self { + c: c.unscale(denom), + s: s.unscale(denom) + }) + } else { + None + } + } + + /// Computes the rotation `R` required such that the `y` component of `R * v` is zero. + /// + /// Returns `None` if no rotation is needed (i.e. if `v.y == 0`). Otherwise, this returns the norm + /// of `v` and the rotation `r` such that `R * v = [ |v|, 0.0 ]^t` where `|v|` is the norm of `v`. + pub fn cancel_y>(v: &Vector) -> Option<(Self, N)> { + if !v[1].is_zero() { + let (mod0, sign0) = v[0].to_exp(); + let denom = (mod0 * mod0 + v[1].modulus_squared()).sqrt(); + let c = N::from_real(mod0 / denom); + let s = (sign0 * v[1].conjugate()).unscale(-denom); + let r = sign0.scale(denom); + Some((Self { c, s }, r)) + } else { + None + } + } + + /// Computes the rotation `R` required such that the `x` component of `R * v` is zero. + /// + /// Returns `None` if no rotation is needed (i.e. if `v.x == 0`). Otherwise, this returns the norm + /// of `v` and the rotation `r` such that `R * v = [ 0.0, |v| ]^t` where `|v|` is the norm of `v`. + pub fn cancel_x>(v: &Vector) -> Option<(Self, N)> { + if !v[0].is_zero() { + let (mod0, sign0) = v[0].to_exp(); + let denom = (mod0 * mod0 + v[1].modulus_squared()).sqrt(); + let c = N::from_real(mod0 / denom); + let s = (sign0 * v[1].conjugate()).unscale(denom); + let r = sign0.scale(denom); + Some((Self { c, s }, r)) + } else { + None + } + } + + /// The cos part of this roration. + pub fn c(&self) -> N { + self.c + } + + /// The sin part of this roration. + pub fn s(&self) -> N { + self.s + } + + /// The inverse of this givens rotation. + pub fn inverse(&self) -> Self { + Self { c: self.c, s: -self.s.conjugate() } + } + + /// Performs the multiplication `rhs = self * rhs` in-place. + pub fn rotate>( + &self, + rhs: &mut Matrix, + ) where + ShapeConstraint: DimEq, + { + assert_eq!( + rhs.nrows(), + 2, + "Unit complex rotation: the input matrix must have exactly two rows." + ); + let s = self.s; + let c = self.c; + + for j in 0..rhs.ncols() { + unsafe { + let a = *rhs.get_unchecked((0, j)); + let b = *rhs.get_unchecked((1, j)); + + *rhs.get_unchecked_mut((0, j)) = c * a - s.conjugate() * b; + *rhs.get_unchecked_mut((1, j)) = s * a + c.conjugate() * b; + } + } + } + + /// Performs the multiplication `lhs = lhs * self` in-place. + pub fn rotate_rows>( + &self, + lhs: &mut Matrix, + ) where + ShapeConstraint: DimEq, + { + assert_eq!( + lhs.ncols(), + 2, + "Unit complex rotation: the input matrix must have exactly two columns." + ); + let s = self.s; + let c = self.c; + + // FIXME: can we optimize that to iterate on one column at a time ? + for j in 0..lhs.nrows() { + unsafe { + let a = *lhs.get_unchecked((j, 0)); + let b = *lhs.get_unchecked((j, 1)); + + *lhs.get_unchecked_mut((j, 0)) = c * a + s * b; + *lhs.get_unchecked_mut((j, 1)) = -s.conjugate() * a + c.conjugate() * b; + } + } + } +} + diff --git a/src/linalg/hessenberg.rs b/src/linalg/hessenberg.rs index 783055a3..25ab445b 100644 --- a/src/linalg/hessenberg.rs +++ b/src/linalg/hessenberg.rs @@ -1,7 +1,7 @@ #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Serialize}; -use alga::general::Real; +use alga::general::Complex; use allocator::Allocator; use base::{DefaultAllocator, MatrixMN, MatrixN, SquareMatrix, VectorN}; use constraint::{DimEq, ShapeConstraint}; @@ -31,21 +31,21 @@ use linalg::householder; )) )] #[derive(Clone, Debug)] -pub struct Hessenberg> +pub struct Hessenberg> where DefaultAllocator: Allocator + Allocator> { hess: MatrixN, subdiag: VectorN>, } -impl> Copy for Hessenberg +impl> Copy for Hessenberg where DefaultAllocator: Allocator + Allocator>, MatrixN: Copy, VectorN>: Copy, {} -impl> Hessenberg +impl> Hessenberg where DefaultAllocator: Allocator + Allocator + Allocator> { /// Computes the Hessenberg decomposition using householder reflections. @@ -137,7 +137,7 @@ where DefaultAllocator: Allocator + Allocator + Allocator, S: Storage> SquareMatrix +impl, S: Storage> SquareMatrix where DefaultAllocator: Allocator + Allocator + Allocator> { /// Computes the Hessenberg decomposition of this matrix using householder reflections. diff --git a/src/linalg/householder.rs b/src/linalg/householder.rs index 09c23091..0fe46499 100644 --- a/src/linalg/householder.rs +++ b/src/linalg/householder.rs @@ -1,6 +1,7 @@ //! Construction of householder elementary reflections. -use alga::general::Real; +use num::Zero; +use alga::general::Complex; use allocator::Allocator; use base::{DefaultAllocator, MatrixMN, MatrixN, Unit, Vector, VectorN}; use dimension::Dim; @@ -15,35 +16,34 @@ use geometry::Reflection; /// `column` after reflection and `false` if no reflection was necessary. #[doc(hidden)] #[inline(always)] -pub fn reflection_axis_mut>( +pub fn reflection_axis_mut>( column: &mut Vector, ) -> (N, bool) { let reflection_sq_norm = column.norm_squared(); - let mut reflection_norm = reflection_sq_norm.sqrt(); + let reflection_norm = reflection_sq_norm.sqrt(); let factor; - unsafe { - if *column.vget_unchecked(0) > N::zero() { - reflection_norm = -reflection_norm; - } + let scaled_norm; - factor = - (reflection_sq_norm - *column.vget_unchecked(0) * reflection_norm) * ::convert(2.0); - *column.vget_unchecked_mut(0) -= reflection_norm; - } + unsafe { + let (modulus, exp) = column.vget_unchecked(0).to_exp(); + scaled_norm = exp.scale(reflection_norm); + factor = (reflection_sq_norm + modulus * reflection_norm) * ::convert(2.0); + *column.vget_unchecked_mut(0) += scaled_norm; + }; if !factor.is_zero() { - *column /= factor.sqrt(); - (reflection_norm, true) + column.unscale_mut(factor.sqrt()); + (-scaled_norm, true) } else { - (reflection_norm, false) + (-scaled_norm, false) } } /// Uses an householder reflection to zero out the `icol`-th column, starting with the `shift + 1`-th /// subdiagonal element. #[doc(hidden)] -pub fn clear_column_unchecked( +pub fn clear_column_unchecked( matrix: &mut MatrixMN, diag_elt: &mut N, icol: usize, @@ -70,7 +70,7 @@ pub fn clear_column_unchecked( /// Uses an hoseholder reflection to zero out the `irow`-th row, ending before the `shift + 1`-th /// superdiagonal element. #[doc(hidden)] -pub fn clear_row_unchecked( +pub fn clear_row_unchecked( matrix: &mut MatrixMN, diag_elt: &mut N, axis_packed: &mut VectorN, @@ -94,7 +94,7 @@ pub fn clear_row_unchecked( &mut work.rows_range_mut(irow + 1..), ); top.columns_range_mut(irow + shift..) - .tr_copy_from(refl.axis()); + .tr_copy_from(&refl.axis()); } else { top.columns_range_mut(irow + shift..).tr_copy_from(&axis); } @@ -104,7 +104,7 @@ pub fn clear_row_unchecked( /// the lower-diagonal element of the given matrix. /// matrices. #[doc(hidden)] -pub fn assemble_q(m: &MatrixN) -> MatrixN +pub fn assemble_q(m: &MatrixN) -> MatrixN where DefaultAllocator: Allocator { assert!(m.is_square()); let dim = m.data.shape().0; diff --git a/src/linalg/inverse.rs b/src/linalg/inverse.rs index 5748900f..f2ccd3e6 100644 --- a/src/linalg/inverse.rs +++ b/src/linalg/inverse.rs @@ -1,4 +1,4 @@ -use alga::general::Real; +use alga::general::Complex; use base::allocator::Allocator; use base::dimension::Dim; @@ -7,7 +7,7 @@ use base::{DefaultAllocator, MatrixN, SquareMatrix}; use linalg::lu; -impl> SquareMatrix { +impl> SquareMatrix { /// Attempts to invert this matrix. #[inline] pub fn try_inverse(self) -> Option> @@ -21,7 +21,7 @@ impl> SquareMatrix { } } -impl> SquareMatrix { +impl> SquareMatrix { /// Attempts to invert this matrix in-place. Returns `false` and leaves `self` untouched if /// inversion fails. #[inline] @@ -115,7 +115,7 @@ impl> SquareMatrix { } // NOTE: this is an extremely efficient, loop-unrolled matrix inverse from MESA (MIT licensed). -fn do_inverse4>( +fn do_inverse4>( m: &MatrixN, out: &mut SquareMatrix, ) -> bool diff --git a/src/linalg/lu.rs b/src/linalg/lu.rs index 67fae23f..7e279227 100644 --- a/src/linalg/lu.rs +++ b/src/linalg/lu.rs @@ -1,7 +1,7 @@ #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Serialize}; -use alga::general::{Field, Real}; +use alga::general::{Field, Complex}; use allocator::{Allocator, Reallocator}; use base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, Scalar}; use constraint::{SameNumberOfRows, ShapeConstraint}; @@ -32,14 +32,14 @@ use linalg::PermutationSequence; )) )] #[derive(Clone, Debug)] -pub struct LU, C: Dim> +pub struct LU, C: Dim> where DefaultAllocator: Allocator + Allocator<(usize, usize), DimMinimum> { lu: MatrixMN, p: PermutationSequence>, } -impl, C: Dim> Copy for LU +impl, C: Dim> Copy for LU where DefaultAllocator: Allocator + Allocator<(usize, usize), DimMinimum>, MatrixMN: Copy, @@ -49,7 +49,7 @@ where /// Performs a LU decomposition to overwrite `out` with the inverse of `matrix`. /// /// If `matrix` is not invertible, `false` is returned and `out` may contain invalid data. -pub fn try_invert_to( +pub fn try_invert_to( mut matrix: MatrixN, out: &mut Matrix, ) -> bool @@ -66,7 +66,7 @@ where out.fill_with_identity(); for i in 0..dim { - let piv = matrix.slice_range(i.., i).iamax() + i; + let piv = matrix.slice_range(i.., i).icamax() + i; let diag = matrix[(piv, i)]; if diag.is_zero() { @@ -86,7 +86,7 @@ where matrix.solve_upper_triangular_mut(out) } -impl, C: Dim> LU +impl, C: Dim> LU where DefaultAllocator: Allocator + Allocator<(usize, usize), DimMinimum> { /// Computes the LU decomposition with partial (row) pivoting of `matrix`. @@ -101,7 +101,7 @@ where DefaultAllocator: Allocator + Allocator<(usize, usize), DimMinimu } for i in 0..min_nrows_ncols.value() { - let piv = matrix.slice_range(i.., i).iamax() + i; + let piv = matrix.slice_range(i.., i).icamax() + i; let diag = matrix[(piv, i)]; if diag.is_zero() { @@ -197,7 +197,7 @@ where DefaultAllocator: Allocator + Allocator<(usize, usize), DimMinimu } } -impl> LU +impl> LU where DefaultAllocator: Allocator + Allocator<(usize, usize), D> { /// Solves the linear system `self * x = b`, where `x` is the unknown to be determined. @@ -368,7 +368,7 @@ pub fn gauss_step_swap( } } -impl, C: Dim, S: Storage> Matrix +impl, C: Dim, S: Storage> Matrix where DefaultAllocator: Allocator + Allocator<(usize, usize), DimMinimum> { /// Computes the LU decomposition with partial (row) pivoting of `matrix`. diff --git a/src/linalg/qr.rs b/src/linalg/qr.rs index 81f72269..023a5042 100644 --- a/src/linalg/qr.rs +++ b/src/linalg/qr.rs @@ -1,7 +1,7 @@ #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Serialize}; -use alga::general::Real; +use alga::general::Complex; use allocator::{Allocator, Reallocator}; use base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, Unit, VectorN}; use constraint::{SameNumberOfRows, ShapeConstraint}; @@ -32,21 +32,21 @@ use linalg::householder; )) )] #[derive(Clone, Debug)] -pub struct QR, C: Dim> +pub struct QR, C: Dim> where DefaultAllocator: Allocator + Allocator> { qr: MatrixMN, diag: VectorN>, } -impl, C: Dim> Copy for QR +impl, C: Dim> Copy for QR where DefaultAllocator: Allocator + Allocator>, MatrixMN: Copy, VectorN>: Copy, {} -impl, C: Dim> QR +impl, C: Dim> QR where DefaultAllocator: Allocator + Allocator + Allocator> { /// Computes the QR decomposition using householder reflections. @@ -162,7 +162,7 @@ where DefaultAllocator: Allocator + Allocator + Allocator> QR +impl> QR where DefaultAllocator: Allocator + Allocator { /// Solves the linear system `self * x = b`, where `x` is the unknown to be determined. @@ -294,7 +294,7 @@ where DefaultAllocator: Allocator + Allocator // } } -impl, C: Dim, S: Storage> Matrix +impl, C: Dim, S: Storage> Matrix where DefaultAllocator: Allocator + Allocator + Allocator> { /// Computes the QR decomposition of this matrix. diff --git a/src/linalg/schur.rs b/src/linalg/schur.rs index 0d425087..fa7e1736 100644 --- a/src/linalg/schur.rs +++ b/src/linalg/schur.rs @@ -1,8 +1,9 @@ #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Serialize}; -use alga::general::Real; -use num_complex::Complex; +use approx::AbsDiffEq; +use alga::general::{Complex, Real}; +use num_complex::Complex as NumComplex; use std::cmp; use allocator::Allocator; @@ -14,6 +15,7 @@ use constraint::{DimEq, ShapeConstraint}; use geometry::{Reflection, UnitComplex}; use linalg::householder; use linalg::Hessenberg; +use linalg::givens::GivensRotation; /// Real Schur decomposition of a square matrix. #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] @@ -32,20 +34,20 @@ use linalg::Hessenberg; )) )] #[derive(Clone, Debug)] -pub struct RealSchur +pub struct RealSchur where DefaultAllocator: Allocator { q: MatrixN, t: MatrixN, } -impl Copy for RealSchur +impl Copy for RealSchur where DefaultAllocator: Allocator, MatrixN: Copy, {} -impl RealSchur +impl RealSchur where D: DimSub, // For Hessenberg. ShapeConstraint: DimEq>, // For Hessenberg. @@ -56,7 +58,7 @@ where { /// Computes the Schur decomposition of a square matrix. pub fn new(m: MatrixN) -> Self { - Self::try_new(m, N::default_epsilon(), 0).unwrap() + Self::try_new(m, N::Real::default_epsilon(), 0).unwrap() } /// Attempts to compute the Schur decomposition of a square matrix. @@ -70,7 +72,7 @@ where /// * `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_new(m: MatrixN, eps: N, max_niter: usize) -> Option { + pub fn try_new(m: MatrixN, eps: N::Real, max_niter: usize) -> Option { let mut work = unsafe { VectorN::new_uninitialized_generic(m.data.shape().0, U1) }; Self::do_decompose(m, &mut work, eps, max_niter, true).map(|(q, t)| RealSchur { @@ -82,7 +84,7 @@ where fn do_decompose( mut m: MatrixN, work: &mut VectorN, - eps: N, + eps: N::Real, max_niter: usize, compute_q: bool, ) -> Option<(Option>, MatrixN)> @@ -111,8 +113,8 @@ where return decompose_2x2(m, compute_q); } - let amax_m = m.amax(); - m /= amax_m; + let amax_m = m.camax(); + m.unscale_mut(amax_m); let hess = Hessenberg::new_with_workspace(m, work); let mut q; @@ -259,7 +261,7 @@ where } } - t *= amax_m; + t.scale_mut(amax_m); Some((q, t)) } @@ -289,8 +291,9 @@ where } /// Computes the complex eigenvalues of the decomposed matrix. - fn do_complex_eigenvalues(t: &MatrixN, out: &mut VectorN, D>) - where DefaultAllocator: Allocator, D> { + fn do_complex_eigenvalues(t: &MatrixN, out: &mut VectorN, D>) + where N: Real, + DefaultAllocator: Allocator, D> { let dim = t.nrows(); let mut m = 0; @@ -298,7 +301,7 @@ where let n = m + 1; if t[(n, m)].is_zero() { - out[m] = Complex::new(t[(m, m)], N::zero()); + out[m] = NumComplex::new(t[(m, m)], N::zero()); m += 1; } else { // Solve the 2x2 eigenvalue subproblem. @@ -313,21 +316,21 @@ where // All 2x2 blocks have negative discriminant because we already decoupled those // with positive eigenvalues.. - let sqrt_discr = Complex::new(N::zero(), (-discr).sqrt()); + let sqrt_discr = NumComplex::new(N::zero(), (-discr).sqrt()); - out[m] = Complex::new(tra * ::convert(0.5), N::zero()) + sqrt_discr; - out[m + 1] = Complex::new(tra * ::convert(0.5), N::zero()) - sqrt_discr; + out[m] = NumComplex::new(tra * ::convert(0.5), N::zero()) + sqrt_discr; + out[m + 1] = NumComplex::new(tra * ::convert(0.5), N::zero()) - sqrt_discr; m += 2; } } if m == dim - 1 { - out[m] = Complex::new(t[(m, m)], N::zero()); + out[m] = NumComplex::new(t[(m, m)], N::zero()); } } - fn delimit_subproblem(t: &mut MatrixN, eps: N, end: usize) -> (usize, usize) + fn delimit_subproblem(t: &mut MatrixN, eps: N::Real, end: usize) -> (usize, usize) where D: DimSub, DefaultAllocator: Allocator>, @@ -337,7 +340,7 @@ where while n > 0 { let m = n - 1; - if t[(n, m)].abs() <= eps * (t[(n, n)].abs() + t[(m, m)].abs()) { + if t[(n, m)].modulus() <= eps * (t[(n, n)].modulus() + t[(m, m)].modulus()) { t[(n, m)] = N::zero(); } else { break; @@ -356,7 +359,7 @@ where let off_diag = t[(new_start, m)]; if off_diag.is_zero() - || off_diag.abs() <= eps * (t[(new_start, new_start)].abs() + t[(m, m)].abs()) + || off_diag.modulus() <= eps * (t[(new_start, new_start)].modulus() + t[(m, m)].modulus()) { t[(new_start, m)] = N::zero(); break; @@ -387,15 +390,16 @@ where } /// Computes the complex eigenvalues of the decomposed matrix. - pub fn complex_eigenvalues(&self) -> VectorN, D> - where DefaultAllocator: Allocator, D> { + pub fn complex_eigenvalues(&self) -> VectorN, D> + where N: Real, + 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 } } -fn decompose_2x2( +fn decompose_2x2( mut m: MatrixN, compute_q: bool, ) -> Option<(Option>, MatrixN)> @@ -412,13 +416,12 @@ where rot.rotate_rows(&mut m); if compute_q { - let c = rot.into_inner(); // XXX: we have to build the matrix manually because // rot.to_rotation_matrix().unwrap() causes an ICE. q = Some(MatrixN::from_column_slice_generic( dim, dim, - &[c.re, c.im, -c.im, c.re], + &[rot.c(), rot.s(), -rot.s().conjugate(), rot.c().conjugate()], )); } } @@ -432,7 +435,7 @@ where Some((q, m)) } -fn compute_2x2_eigvals>( +fn compute_2x2_eigvals>( m: &SquareMatrix, ) -> Option<(N, N)> { // Solve the 2x2 eigenvalue subproblem. @@ -447,13 +450,10 @@ fn compute_2x2_eigvals>( let val = (h00 - h11) * ::convert(0.5); let discr = h10 * h01 + val * val; - if discr >= N::zero() { - let sqrt_discr = discr.sqrt(); + discr.try_sqrt().map(|sqrt_discr| { let half_tra = (h00 + h11) * ::convert(0.5); - Some((half_tra + sqrt_discr, half_tra - sqrt_discr)) - } else { - None - } + (half_tra + sqrt_discr, half_tra - sqrt_discr) + }) } // Computes the 2x2 transformation that upper-triangulates a 2x2 matrix with real eigenvalues. @@ -461,9 +461,9 @@ fn compute_2x2_eigvals>( /// /// Returns `None` if the matrix has complex eigenvalues, or is upper-triangular. In both case, /// the basis is the identity. -fn compute_2x2_basis>( +fn compute_2x2_basis>( m: &SquareMatrix, -) -> Option> { +) -> Option> { let h10 = m[(1, 0)]; if h10.is_zero() { @@ -477,19 +477,17 @@ fn compute_2x2_basis>( // NOTE: Choose the one that yields a larger x component. // This is necessary for numerical stability of the normalization of the complex // number. - let basis = if x1.abs() > x2.abs() { - Complex::new(x1, -h10) + if x1.modulus() > x2.modulus() { + Some(GivensRotation::new(x1, -h10)) } else { - Complex::new(x2, -h10) - }; - - Some(UnitComplex::from_complex(basis)) + Some(GivensRotation::new(x2, -h10)) + } } else { None } } -impl> SquareMatrix +impl> SquareMatrix where D: DimSub, // For Hessenberg. ShapeConstraint: DimEq>, // For Hessenberg. @@ -514,7 +512,7 @@ where /// * `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_real_schur(self, eps: N, max_niter: usize) -> Option> { + pub fn try_real_schur(self, eps: N::Real, max_niter: usize) -> Option> { RealSchur::try_new(self.into_owned(), eps, max_niter) } @@ -546,7 +544,7 @@ where let schur = RealSchur::do_decompose( self.clone_owned(), &mut work, - N::default_epsilon(), + N::Real::default_epsilon(), 0, false, ) @@ -559,9 +557,10 @@ where } /// Computes the eigenvalues of this matrix. - pub fn complex_eigenvalues(&self) -> VectorN, D> + pub fn complex_eigenvalues(&self) -> VectorN, D> // FIXME: add balancing? - where DefaultAllocator: Allocator, D> { + where N: Real, + 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 4d2d103f..b43b44df 100644 --- a/src/linalg/solve.rs +++ b/src/linalg/solve.rs @@ -1,4 +1,4 @@ -use alga::general::Real; +use alga::general::Complex; use base::allocator::Allocator; use base::constraint::{SameNumberOfRows, ShapeConstraint}; @@ -6,7 +6,7 @@ use base::dimension::{Dim, U1}; use base::storage::{Storage, StorageMut}; use base::{DefaultAllocator, Matrix, MatrixMN, SquareMatrix, Vector}; -impl> SquareMatrix { +impl> SquareMatrix { /// Computes the solution of the linear system `self . x = b` where `x` is the unknown and only /// the lower-triangular part of `self` (including the diagonal) is considered not-zero. #[inline] diff --git a/src/linalg/symmetric_eigen.rs b/src/linalg/symmetric_eigen.rs index cd455b7c..8d16232f 100644 --- a/src/linalg/symmetric_eigen.rs +++ b/src/linalg/symmetric_eigen.rs @@ -1,17 +1,19 @@ #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Serialize}; -use num_complex::Complex; +use num::Zero; +use num_complex::Complex as NumComplex; +use approx::AbsDiffEq; use std::ops::MulAssign; -use alga::general::Real; +use alga::general::Complex; use allocator::Allocator; use base::{DefaultAllocator, Matrix2, MatrixN, SquareMatrix, Vector2, VectorN}; use dimension::{Dim, DimDiff, DimSub, U1, U2}; use storage::Storage; use geometry::UnitComplex; -use linalg::givens; +use linalg::givens::GivensRotation; use linalg::SymmetricTridiagonal; /// Eigendecomposition of a symmetric matrix. @@ -35,7 +37,7 @@ use linalg::SymmetricTridiagonal; )) )] #[derive(Clone, Debug)] -pub struct SymmetricEigen +pub struct SymmetricEigen where DefaultAllocator: Allocator + Allocator { /// The eigenvectors of the decomposed matrix. @@ -45,14 +47,14 @@ where DefaultAllocator: Allocator + Allocator pub eigenvalues: VectorN, } -impl Copy for SymmetricEigen +impl Copy for SymmetricEigen where DefaultAllocator: Allocator + Allocator, MatrixN: Copy, VectorN: Copy, {} -impl SymmetricEigen +impl SymmetricEigen where DefaultAllocator: Allocator + Allocator { /// Computes the eigendecomposition of the given symmetric matrix. @@ -63,7 +65,7 @@ where DefaultAllocator: Allocator + Allocator D: DimSub, DefaultAllocator: Allocator>, { - Self::try_new(m, N::default_epsilon(), 0).unwrap() + Self::try_new(m, N::Real::default_epsilon(), 0).unwrap() } /// Computes the eigendecomposition of the given symmetric matrix with user-specified @@ -77,7 +79,7 @@ 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_new(m: MatrixN, eps: N, max_niter: usize) -> Option + pub fn try_new(m: MatrixN, eps: N::Real, max_niter: usize) -> Option where D: DimSub, DefaultAllocator: Allocator>, @@ -91,7 +93,7 @@ where DefaultAllocator: Allocator + Allocator fn do_decompose( mut m: MatrixN, eigenvectors: bool, - eps: N, + eps: N::Real, max_niter: usize, ) -> Option<(VectorN, Option>)> where @@ -103,11 +105,10 @@ where DefaultAllocator: Allocator + Allocator "Unable to compute the eigendecomposition of a non-square matrix." ); let dim = m.nrows(); - - let m_amax = m.amax(); + let m_amax = m.camax(); if !m_amax.is_zero() { - m /= m_amax; + m.unscale_mut(m_amax); } let (mut q, mut diag, mut off_diag); @@ -125,7 +126,7 @@ where DefaultAllocator: Allocator + Allocator } if dim == 1 { - diag *= m_amax; + diag.scale_mut(m_amax); return Some((diag, q)); } @@ -147,7 +148,7 @@ where DefaultAllocator: Allocator + Allocator for i in start..n { let j = i + 1; - if let Some((rot, norm)) = givens::cancel_y(&v) { + if let Some((rot, norm)) = GivensRotation::cancel_y(&v) { if i > start { // Not the first iteration. off_diag[i - 1] = norm; @@ -157,9 +158,9 @@ where DefaultAllocator: Allocator + Allocator let mjj = diag[j]; let mij = off_diag[i]; - let cc = rot.cos_angle() * rot.cos_angle(); - let ss = rot.sin_angle() * rot.sin_angle(); - let cs = rot.cos_angle() * rot.sin_angle(); + let cc = rot.c() * rot.c(); + let ss = rot.s() * rot.s(); + let cs = rot.c() * rot.s(); let b = cs * ::convert(2.0) * mij; @@ -169,8 +170,8 @@ where DefaultAllocator: Allocator + Allocator if i != n - 1 { v.x = off_diag[i]; - v.y = -rot.sin_angle() * off_diag[i + 1]; - off_diag[i + 1] *= rot.cos_angle(); + v.y = -rot.s() * off_diag[i + 1]; + off_diag[i + 1] *= rot.c(); } if let Some(ref mut q) = q { @@ -181,7 +182,7 @@ where DefaultAllocator: Allocator + Allocator } } - if off_diag[m].abs() <= eps * (diag[m].abs() + diag[n].abs()) { + if off_diag[m].modulus() <= eps * (diag[m].modulus() + diag[n].modulus()) { end -= 1; } } else if subdim == 2 { @@ -198,8 +199,7 @@ where DefaultAllocator: Allocator + Allocator diag[start + 1] = eigvals[1]; if let Some(ref mut q) = q { - if let Some(basis) = basis.try_normalize(eps) { - let rot = UnitComplex::new_unchecked(Complex::new(basis.x, basis.y)); + if let Some(rot) = GivensRotation::try_new(basis.x, basis.y, eps) { rot.rotate_rows(&mut q.fixed_columns_mut::(start)); } } @@ -219,7 +219,7 @@ where DefaultAllocator: Allocator + Allocator } } - diag *= m_amax; + diag.scale_mut(m_amax); Some((diag, q)) } @@ -228,7 +228,7 @@ where DefaultAllocator: Allocator + Allocator diag: &VectorN, off_diag: &mut VectorN>, end: usize, - eps: N, + eps: N::Real, ) -> (usize, usize) where D: DimSub, @@ -239,7 +239,7 @@ where DefaultAllocator: Allocator + Allocator while n > 0 { let m = n - 1; - if off_diag[m].abs() > eps * (diag[n].abs() + diag[m].abs()) { + if off_diag[m].modulus() > eps * (diag[n].modulus() + diag[m].modulus()) { break; } @@ -255,7 +255,7 @@ where DefaultAllocator: Allocator + Allocator let m = new_start - 1; if off_diag[m].is_zero() - || off_diag[m].abs() <= eps * (diag[new_start].abs() + diag[m].abs()) + || off_diag[m].modulus() <= eps * (diag[new_start].modulus() + diag[m].modulus()) { off_diag[m] = N::zero(); break; @@ -276,7 +276,7 @@ where DefaultAllocator: Allocator + Allocator let val = self.eigenvalues[i]; u_t.column_mut(i).mul_assign(val); } - u_t.transpose_mut(); + u_t.conjugate_transpose_mut(); &self.eigenvectors * u_t } } @@ -287,7 +287,7 @@ where DefaultAllocator: Allocator + Allocator /// The inputs are interpreted as the 2x2 matrix: /// tmm tmn /// tmn tnn -pub fn wilkinson_shift(tmm: N, tnn: N, tmn: N) -> N { +pub fn wilkinson_shift(tmm: N, tnn: N, tmn: N) -> N { let sq_tmn = tmn * tmn; if !sq_tmn.is_zero() { // We have the guarantee that the denominator won't be zero. @@ -303,7 +303,7 @@ pub fn wilkinson_shift(tmm: N, tnn: N, tmn: N) -> N { * Computations of eigenvalues for symmetric matrices. * */ -impl, S: Storage> SquareMatrix +impl, S: Storage> SquareMatrix where DefaultAllocator: Allocator + Allocator + Allocator> { /// Computes the eigendecomposition of this symmetric matrix. @@ -324,7 +324,7 @@ where DefaultAllocator: Allocator + Allocator + Allocator Option> { + pub fn try_symmetric_eigen(self, eps: N::Real, max_niter: usize) -> Option> { SymmetricEigen::try_new(self.into_owned(), eps, max_niter) } @@ -332,7 +332,7 @@ where DefaultAllocator: Allocator + Allocator + Allocator VectorN { - SymmetricEigen::do_decompose(self.clone_owned(), false, N::default_epsilon(), 0) + SymmetricEigen::do_decompose(self.clone_owned(), false, N::Real::default_epsilon(), 0) .unwrap() .0 } diff --git a/src/linalg/symmetric_tridiagonal.rs b/src/linalg/symmetric_tridiagonal.rs index 2e4108ae..276dc6fb 100644 --- a/src/linalg/symmetric_tridiagonal.rs +++ b/src/linalg/symmetric_tridiagonal.rs @@ -1,7 +1,7 @@ #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Serialize}; -use alga::general::Real; +use alga::general::Complex; use allocator::Allocator; use base::{DefaultAllocator, MatrixMN, MatrixN, SquareMatrix, VectorN}; use dimension::{DimDiff, DimSub, U1}; @@ -30,21 +30,21 @@ use linalg::householder; )) )] #[derive(Clone, Debug)] -pub struct SymmetricTridiagonal> +pub struct SymmetricTridiagonal> where DefaultAllocator: Allocator + Allocator> { tri: MatrixN, off_diagonal: VectorN>, } -impl> Copy for SymmetricTridiagonal +impl> Copy for SymmetricTridiagonal where DefaultAllocator: Allocator + Allocator>, MatrixN: Copy, VectorN>: Copy, {} -impl> SymmetricTridiagonal +impl> SymmetricTridiagonal where DefaultAllocator: Allocator + Allocator> { /// Computes the tridiagonalization of the symmetric matrix `m`. @@ -75,17 +75,18 @@ where DefaultAllocator: Allocator + Allocator> if not_zero { let mut p = p.rows_range_mut(i..); - p.gemv_symm(::convert(2.0), &m, &axis, N::zero()); + p.gemv_symm(::convert(2.0), &m, &axis.conjugate(), N::zero()); let dot = axis.dot(&p); - p.axpy(-dot, &axis, N::one()); - m.ger_symm(-N::one(), &p, &axis, N::one()); +// p.axpy(-dot, &axis.conjugate(), N::one()); + m.ger_symm(-N::one(), &p, &axis.conjugate(), N::one()); m.ger_symm(-N::one(), &axis, &p, N::one()); + m.ger_symm(dot * ::convert(2.0), &axis, &axis.conjugate(), N::one()); } } Self { tri: m, - off_diagonal: off_diagonal, + off_diagonal, } } @@ -138,14 +139,14 @@ where DefaultAllocator: Allocator + Allocator> for i in 0..self.off_diagonal.len() { self.tri[(i + 1, i)] = self.off_diagonal[i]; - self.tri[(i, i + 1)] = self.off_diagonal[i]; + self.tri[(i, i + 1)] = self.off_diagonal[i].conjugate(); } - &q * self.tri * q.transpose() + &q * self.tri * q.conjugate_transpose() } } -impl, S: Storage> SquareMatrix +impl, S: Storage> SquareMatrix where DefaultAllocator: Allocator + Allocator> { /// Computes the tridiagonalization of this symmetric matrix. diff --git a/tests/core/helper.rs b/tests/core/helper.rs new file mode 100644 index 00000000..9b9dfa75 --- /dev/null +++ b/tests/core/helper.rs @@ -0,0 +1,54 @@ +// This module implement several methods to fill some +// missing features of num-complex when it comes to randomness. + +use quickcheck::{Arbitrary, Gen}; +use rand::distributions::{Standard, Distribution}; +use rand::Rng; +use num_complex::Complex; +use na::Real; + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct RandComplex(pub Complex); + +impl Arbitrary for RandComplex { + #[inline] + fn arbitrary(rng: &mut G) -> Self { + let im = Arbitrary::arbitrary(rng); + let re = Arbitrary::arbitrary(rng); + RandComplex(Complex::new(re, im)) + } +} + +impl Distribution> for Standard + where + Standard: Distribution, +{ + #[inline] + fn sample<'a, G: Rng + ?Sized>(&self, rng: &'a mut G) -> RandComplex { + let re = rng.gen(); + let im = rng.gen(); + RandComplex(Complex::new(re, im)) + } +} + +// This is a wrapper similar to RandComplex, but for non-complex. +// This exists only to make generic tests easier to write. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct RandScalar(pub N); + +impl Arbitrary for RandScalar { + #[inline] + fn arbitrary(rng: &mut G) -> Self { + RandScalar(Arbitrary::arbitrary(rng)) + } +} + +impl Distribution> for Standard + where + Standard: Distribution, +{ + #[inline] + fn sample<'a, G: Rng + ?Sized>(&self, rng: &'a mut G) -> RandScalar { + RandScalar(self.sample(rng)) + } +} \ No newline at end of file diff --git a/tests/core/matrix.rs b/tests/core/matrix.rs index 9c6d468a..5ba06f5b 100644 --- a/tests/core/matrix.rs +++ b/tests/core/matrix.rs @@ -1022,7 +1022,7 @@ mod finite_dim_inner_space_tests { * */ #[cfg(feature = "arbitrary")] - fn is_subspace_basis + Display>(vs: &[T]) -> bool { + fn is_subspace_basis + Display>(vs: &[T]) -> bool { for i in 0..vs.len() { // Basis elements must be normalized. if !relative_eq!(vs[i].norm(), 1.0, epsilon = 1.0e-7) { diff --git a/tests/core/mod.rs b/tests/core/mod.rs index 7e1f8591..c53493bd 100644 --- a/tests/core/mod.rs +++ b/tests/core/mod.rs @@ -8,3 +8,7 @@ mod matrix_slice; #[cfg(feature = "mint")] mod mint; mod serde; + + +#[cfg(feature = "arbitrary")] +pub mod helper; \ No newline at end of file diff --git a/tests/geometry/isometry.rs b/tests/geometry/isometry.rs index a0e00272..cf3a4dfa 100644 --- a/tests/geometry/isometry.rs +++ b/tests/geometry/isometry.rs @@ -82,7 +82,7 @@ quickcheck!( r: Rotation2, t: Translation2, v: Vector2, - p: Point2, + p: Point2 ) -> bool { // (rotation × translation) * point = rotation × (translation * point) @@ -120,7 +120,7 @@ quickcheck!( r: Rotation3, t: Translation3, v: Vector3, - p: Point3, + p: Point3 ) -> bool { // (rotation × translation) * point = rotation × (translation * point) @@ -158,7 +158,7 @@ quickcheck!( t: Translation3, v: Vector3, p: Point3, - r: Rotation3, + r: Rotation3 ) -> bool { let iMi = i * i; diff --git a/tests/geometry/similarity.rs b/tests/geometry/similarity.rs index 68b86943..475af976 100644 --- a/tests/geometry/similarity.rs +++ b/tests/geometry/similarity.rs @@ -19,7 +19,7 @@ quickcheck!( fn inverse_is_parts_inversion( t: Translation3, r: UnitQuaternion, - scaling: f64, + scaling: f64 ) -> bool { if relative_eq!(scaling, 0.0) { @@ -33,7 +33,7 @@ quickcheck!( fn multiply_equals_alga_transform( s: Similarity3, v: Vector3, - p: Point3, + p: Point3 ) -> bool { s * v == s.transform_vector(&v) @@ -56,7 +56,7 @@ quickcheck!( t: Translation3, v: Vector3, p: Point3, - scaling: f64, + scaling: f64 ) -> bool { if relative_eq!(scaling, 0.0) { @@ -152,7 +152,7 @@ quickcheck!( uq: UnitQuaternion, t: Translation3, v: Vector3, - p: Point3, + p: Point3 ) -> bool { let sMs = s * s; diff --git a/tests/geometry/unit_complex.rs b/tests/geometry/unit_complex.rs index 88988aa8..46998036 100644 --- a/tests/geometry/unit_complex.rs +++ b/tests/geometry/unit_complex.rs @@ -72,7 +72,7 @@ quickcheck!( uc: UnitComplex, v: Vector2, p: Point2, - r: Rotation2, + r: Rotation2 ) -> bool { let uv = Unit::new_normalize(v); diff --git a/tests/lib.rs b/tests/lib.rs index c32f4066..f6634d0f 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -12,9 +12,10 @@ extern crate num_traits as num; extern crate quickcheck; extern crate rand; extern crate serde_json; +extern crate num_complex; mod core; mod geometry; mod linalg; -#[cfg(feature = "sparse")] -mod sparse; +//#[cfg(feature = "sparse")] +//mod sparse; diff --git a/tests/linalg/bidiagonal.rs b/tests/linalg/bidiagonal.rs index a7d5952f..28b1e3a9 100644 --- a/tests/linalg/bidiagonal.rs +++ b/tests/linalg/bidiagonal.rs @@ -1,9 +1,11 @@ #![cfg(feature = "arbitrary")] use na::{DMatrix, Matrix2, Matrix3x5, Matrix4, Matrix5x3}; +use core::helper::{RandScalar, RandComplex}; quickcheck! { - fn bidiagonal(m: DMatrix) -> bool { + fn bidiagonal(m: DMatrix>) -> bool { + let m = m.map(|e| e.0); if m.len() == 0 { return true; } @@ -17,7 +19,8 @@ quickcheck! { relative_eq!(m, &u * d * &v_t, epsilon = 1.0e-7) } - fn bidiagonal_static_5_3(m: Matrix5x3) -> bool { + fn bidiagonal_static_5_3(m: Matrix5x3>) -> bool { + let m = m.map(|e| e.0); let bidiagonal = m.bidiagonalize(); let (u, d, v_t) = bidiagonal.unpack(); @@ -27,7 +30,8 @@ quickcheck! { relative_eq!(m, &u * d * &v_t, epsilon = 1.0e-7) } - fn bidiagonal_static_3_5(m: Matrix3x5) -> bool { + fn bidiagonal_static_3_5(m: Matrix3x5>) -> bool { + let m = m.map(|e| e.0); let bidiagonal = m.bidiagonalize(); let (u, d, v_t) = bidiagonal.unpack(); @@ -37,7 +41,8 @@ quickcheck! { relative_eq!(m, &u * d * &v_t, epsilon = 1.0e-7) } - fn bidiagonal_static_square(m: Matrix4) -> bool { + fn bidiagonal_static_square(m: Matrix4>) -> bool { + let m = m.map(|e| e.0); let bidiagonal = m.bidiagonalize(); let (u, d, v_t) = bidiagonal.unpack(); @@ -47,7 +52,8 @@ quickcheck! { relative_eq!(m, &u * d * &v_t, epsilon = 1.0e-7) } - fn bidiagonal_static_square_2x2(m: Matrix2) -> bool { + fn bidiagonal_static_square_2x2(m: Matrix2>) -> bool { + let m = m.map(|e| e.0); let bidiagonal = m.bidiagonalize(); let (u, d, v_t) = bidiagonal.unpack(); diff --git a/tests/linalg/eigen.rs b/tests/linalg/eigen.rs index 36855acf..c44bb098 100644 --- a/tests/linalg/eigen.rs +++ b/tests/linalg/eigen.rs @@ -5,12 +5,13 @@ use na::DMatrix; #[cfg(feature = "arbitrary")] mod quickcheck_tests { use na::{DMatrix, Matrix2, Matrix3, Matrix4}; + use core::helper::{RandScalar, RandComplex}; use std::cmp; quickcheck! { fn symmetric_eigen(n: usize) -> bool { let n = cmp::max(1, cmp::min(n, 10)); - let m = DMatrix::::new_random(n, n); + let m = DMatrix::>::new_random(n, n).map(|e| e.0); let eig = m.clone().symmetric_eigen(); let recomp = eig.recompose(); @@ -21,9 +22,9 @@ mod quickcheck_tests { fn symmetric_eigen_singular(n: usize) -> bool { let n = cmp::max(1, cmp::min(n, 10)); - let mut m = DMatrix::::new_random(n, n); - m.row_mut(n / 2).fill(0.0); - m.column_mut(n / 2).fill(0.0); + let mut m = DMatrix::>::new_random(n, n).map(|e| e.0); + m.row_mut(n / 2).fill(na::zero()); + m.column_mut(n / 2).fill(na::zero()); let eig = m.clone().symmetric_eigen(); let recomp = eig.recompose(); @@ -32,7 +33,8 @@ mod quickcheck_tests { relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-5) } - fn symmetric_eigen_static_square_4x4(m: Matrix4) -> bool { + fn symmetric_eigen_static_square_4x4(m: Matrix4>) -> bool { + let m = m.map(|e| e.0); let eig = m.symmetric_eigen(); let recomp = eig.recompose(); @@ -41,7 +43,8 @@ mod quickcheck_tests { relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-5) } - fn symmetric_eigen_static_square_3x3(m: Matrix3) -> bool { + fn symmetric_eigen_static_square_3x3(m: Matrix3>) -> bool { + let m = m.map(|e| e.0); let eig = m.symmetric_eigen(); let recomp = eig.recompose(); @@ -50,7 +53,8 @@ mod quickcheck_tests { relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-5) } - fn symmetric_eigen_static_square_2x2(m: Matrix2) -> bool { + fn symmetric_eigen_static_square_2x2(m: Matrix2>) -> bool { + let m = m.map(|e| e.0); let eig = m.symmetric_eigen(); let recomp = eig.recompose(); diff --git a/tests/linalg/hessenberg.rs b/tests/linalg/hessenberg.rs index 22d62fbf..d9245110 100644 --- a/tests/linalg/hessenberg.rs +++ b/tests/linalg/hessenberg.rs @@ -1,6 +1,7 @@ #![cfg(feature = "arbitrary")] use na::{DMatrix, Matrix2, Matrix4}; +use core::helper::{RandScalar, RandComplex}; use std::cmp; #[test] @@ -14,20 +15,22 @@ fn hessenberg_simple() { quickcheck! { fn hessenberg(n: usize) -> bool { let n = cmp::max(1, cmp::min(n, 50)); - let m = DMatrix::::new_random(n, n); + let m = DMatrix::>::new_random(n, n).map(|e| e.0); let hess = m.clone().hessenberg(); let (p, h) = hess.unpack(); relative_eq!(m, &p * h * p.transpose(), epsilon = 1.0e-7) } - fn hessenberg_static_mat2(m: Matrix2) -> bool { + fn hessenberg_static_mat2(m: Matrix2>) -> bool { + let m = m.map(|e| e.0); let hess = m.hessenberg(); let (p, h) = hess.unpack(); relative_eq!(m, p * h * p.transpose(), epsilon = 1.0e-7) } - fn hessenberg_static(m: Matrix4) -> bool { + fn hessenberg_static(m: Matrix4>) -> bool { + let m = m.map(|e| e.0); let hess = m.hessenberg(); let (p, h) = hess.unpack(); relative_eq!(m, p * h * p.transpose(), epsilon = 1.0e-7) diff --git a/tests/linalg/lu.rs b/tests/linalg/lu.rs index 5069f7e5..cb82731e 100644 --- a/tests/linalg/lu.rs +++ b/tests/linalg/lu.rs @@ -40,114 +40,134 @@ fn lu_simple_with_pivot() { #[cfg(feature = "arbitrary")] mod quickcheck_tests { - use std::cmp; - use na::{DMatrix, Matrix4, Matrix4x3, Matrix5x3, Matrix3x5, DVector, Vector4}; + use core::helper::{RandScalar, RandComplex}; - quickcheck! { - fn lu(m: DMatrix) -> bool { - let mut m = m; - if m.len() == 0 { - m = DMatrix::new_random(1, 1); - } + macro_rules! gen_tests( + ($module: ident, $scalar: ty) => { + mod $module { + use std::cmp; + use na::{DMatrix, Matrix4, Matrix4x3, Matrix5x3, Matrix3x5, DVector, Vector4}; + #[allow(unused_imports)] + use core::helper::{RandScalar, RandComplex}; - let lu = m.clone().lu(); - let (p, l, u) = lu.unpack(); - let mut lu = l * u; - p.inv_permute_rows(&mut lu); + quickcheck! { + fn lu(m: DMatrix<$scalar>) -> bool { + let mut m = m; + if m.len() == 0 { + m = DMatrix::<$scalar>::new_random(1, 1); + } - relative_eq!(m, lu, epsilon = 1.0e-7) - } + let m = m.map(|e| e.0); - fn lu_static_3_5(m: Matrix3x5) -> bool { - let lu = m.lu(); - let (p, l, u) = lu.unpack(); - let mut lu = l * u; - p.inv_permute_rows(&mut lu); + let lu = m.clone().lu(); + let (p, l, u) = lu.unpack(); + let mut lu = l * u; + p.inv_permute_rows(&mut lu); - relative_eq!(m, lu, epsilon = 1.0e-7) - } + relative_eq!(m, lu, epsilon = 1.0e-7) + } - fn lu_static_5_3(m: Matrix5x3) -> bool { - let lu = m.lu(); - let (p, l, u) = lu.unpack(); - let mut lu = l * u; - p.inv_permute_rows(&mut lu); + fn lu_static_3_5(m: Matrix3x5<$scalar>) -> bool { + let m = m.map(|e| e.0); + let lu = m.lu(); + let (p, l, u) = lu.unpack(); + let mut lu = l * u; + p.inv_permute_rows(&mut lu); - relative_eq!(m, lu, epsilon = 1.0e-7) - } + relative_eq!(m, lu, epsilon = 1.0e-7) + } - fn lu_static_square(m: Matrix4) -> bool { - let lu = m.lu(); - let (p, l, u) = lu.unpack(); - let mut lu = l * u; - p.inv_permute_rows(&mut lu); + fn lu_static_5_3(m: Matrix5x3<$scalar>) -> bool { + let m = m.map(|e| e.0); + let lu = m.lu(); + let (p, l, u) = lu.unpack(); + let mut lu = l * u; + p.inv_permute_rows(&mut lu); - relative_eq!(m, lu, epsilon = 1.0e-7) - } + relative_eq!(m, lu, epsilon = 1.0e-7) + } - fn lu_solve(n: usize, nb: usize) -> bool { - if n != 0 && nb != 0 { - let n = cmp::min(n, 50); // To avoid slowing down the test too much. - let nb = cmp::min(nb, 50); // To avoid slowing down the test too much. - let m = DMatrix::::new_random(n, n); + fn lu_static_square(m: Matrix4<$scalar>) -> bool { + let m = m.map(|e| e.0); + let lu = m.lu(); + let (p, l, u) = lu.unpack(); + let mut lu = l * u; + p.inv_permute_rows(&mut lu); - let lu = m.clone().lu(); - let b1 = DVector::new_random(n); - let b2 = DMatrix::new_random(n, nb); + relative_eq!(m, lu, epsilon = 1.0e-7) + } - let sol1 = lu.solve(&b1); - let sol2 = lu.solve(&b2); + fn lu_solve(n: usize, nb: usize) -> bool { + if n != 0 && nb != 0 { + let n = cmp::min(n, 50); // To avoid slowing down the test too much. + let nb = cmp::min(nb, 50); // To avoid slowing down the test too much. + let m = DMatrix::<$scalar>::new_random(n, n).map(|e| e.0); - return (sol1.is_none() || relative_eq!(&m * sol1.unwrap(), b1, epsilon = 1.0e-6)) && - (sol2.is_none() || relative_eq!(&m * sol2.unwrap(), b2, epsilon = 1.0e-6)) - } + let lu = m.clone().lu(); + let b1 = DVector::<$scalar>::new_random(n).map(|e| e.0); + let b2 = DMatrix::<$scalar>::new_random(n, nb).map(|e| e.0); - return true; - } + let sol1 = lu.solve(&b1); + let sol2 = lu.solve(&b2); - fn lu_solve_static(m: Matrix4) -> bool { - let lu = m.lu(); - let b1 = Vector4::new_random(); - let b2 = Matrix4x3::new_random(); + return (sol1.is_none() || relative_eq!(&m * sol1.unwrap(), b1, epsilon = 1.0e-6)) && + (sol2.is_none() || relative_eq!(&m * sol2.unwrap(), b2, epsilon = 1.0e-6)) + } - let sol1 = lu.solve(&b1); - let sol2 = lu.solve(&b2); + return true; + } - return (sol1.is_none() || relative_eq!(&m * sol1.unwrap(), b1, epsilon = 1.0e-6)) && - (sol2.is_none() || relative_eq!(&m * sol2.unwrap(), b2, epsilon = 1.0e-6)) - } + fn lu_solve_static(m: Matrix4<$scalar>) -> bool { + let m = m.map(|e| e.0); + let lu = m.lu(); + let b1 = Vector4::<$scalar>::new_random().map(|e| e.0); + let b2 = Matrix4x3::<$scalar>::new_random().map(|e| e.0); - fn lu_inverse(n: usize) -> bool { - let n = cmp::max(1, cmp::min(n, 15)); // To avoid slowing down the test too much. - let m = DMatrix::::new_random(n, n); + let sol1 = lu.solve(&b1); + let sol2 = lu.solve(&b2); - let mut l = m.lower_triangle(); - let mut u = m.upper_triangle(); + return (sol1.is_none() || relative_eq!(&m * sol1.unwrap(), b1, epsilon = 1.0e-6)) && + (sol2.is_none() || relative_eq!(&m * sol2.unwrap(), b2, epsilon = 1.0e-6)) + } - // Ensure the matrix is well conditioned for inversion. - l.fill_diagonal(1.0); - u.fill_diagonal(1.0); - let m = l * u; + fn lu_inverse(n: usize) -> bool { + let n = cmp::max(1, cmp::min(n, 15)); // To avoid slowing down the test too much. + let m = DMatrix::<$scalar>::new_random(n, n).map(|e| e.0); - let m1 = m.clone().lu().try_inverse().unwrap(); - let id1 = &m * &m1; - let id2 = &m1 * &m; + let mut l = m.lower_triangle(); + let mut u = m.upper_triangle(); - return id1.is_identity(1.0e-5) && id2.is_identity(1.0e-5); - } + // Ensure the matrix is well conditioned for inversion. + l.fill_diagonal(na::one()); + u.fill_diagonal(na::one()); + let m = l * u; - fn lu_inverse_static(m: Matrix4) -> bool { - let lu = m.lu(); + let m1 = m.clone().lu().try_inverse().unwrap(); + let id1 = &m * &m1; + let id2 = &m1 * &m; - if let Some(m1) = lu.try_inverse() { - let id1 = &m * &m1; - let id2 = &m1 * &m; + return id1.is_identity(1.0e-5) && id2.is_identity(1.0e-5); + } - id1.is_identity(1.0e-5) && id2.is_identity(1.0e-5) - } - else { - true + fn lu_inverse_static(m: Matrix4<$scalar>) -> bool { + let m = m.map(|e| e.0); + let lu = m.lu(); + + if let Some(m1) = lu.try_inverse() { + let id1 = &m * &m1; + let id2 = &m1 * &m; + + id1.is_identity(1.0e-5) && id2.is_identity(1.0e-5) + } + else { + true + } + } + } } } - } + ); + + gen_tests!(complex, RandComplex); + gen_tests!(f64, RandScalar); } diff --git a/tests/linalg/qr.rs b/tests/linalg/qr.rs index d7211623..48b0a8f7 100644 --- a/tests/linalg/qr.rs +++ b/tests/linalg/qr.rs @@ -1,112 +1,133 @@ #![cfg(feature = "arbitrary")] -use na::{DMatrix, DVector, Matrix3x5, Matrix4, Matrix4x3, Matrix5x3, Vector4}; -use std::cmp; +use core::helper::{RandScalar, RandComplex}; -quickcheck! { - fn qr(m: DMatrix) -> bool { - let qr = m.clone().qr(); - let q = qr.q(); - let r = qr.r(); +macro_rules! gen_tests( + ($module: ident, $scalar: ty) => { + mod $module { + use na::{DMatrix, DVector, Matrix3x5, Matrix4, Matrix4x3, Matrix5x3, Vector4}; + use std::cmp; + use core::helper::{RandScalar, RandComplex}; - relative_eq!(m, &q * r, epsilon = 1.0e-7) && - q.is_orthogonal(1.0e-7) - } + quickcheck! { + fn qr(m: DMatrix<$scalar>) -> bool { + let m = m.map(|e| e.0); + let qr = m.clone().qr(); + let q = qr.q(); + let r = qr.r(); - fn qr_static_5_3(m: Matrix5x3) -> bool { - let qr = m.qr(); - let q = qr.q(); - let r = qr.r(); + println!("m: {}", m); + println!("qr: {}", &q * &r); - relative_eq!(m, q * r, epsilon = 1.0e-7) && - q.is_orthogonal(1.0e-7) - } + relative_eq!(m, &q * r, epsilon = 1.0e-7) && + q.is_orthogonal(1.0e-7) + } - fn qr_static_3_5(m: Matrix3x5) -> bool { - let qr = m.qr(); - let q = qr.q(); - let r = qr.r(); + fn qr_static_5_3(m: Matrix5x3<$scalar>) -> bool { + let m = m.map(|e| e.0); + let qr = m.qr(); + let q = qr.q(); + let r = qr.r(); - relative_eq!(m, q * r, epsilon = 1.0e-7) && - q.is_orthogonal(1.0e-7) - } + relative_eq!(m, q * r, epsilon = 1.0e-7) && + q.is_orthogonal(1.0e-7) + } - fn qr_static_square(m: Matrix4) -> bool { - let qr = m.qr(); - let q = qr.q(); - let r = qr.r(); + fn qr_static_3_5(m: Matrix3x5<$scalar>) -> bool { + let m = m.map(|e| e.0); + let qr = m.qr(); + let q = qr.q(); + let r = qr.r(); - println!("{}{}{}{}", q, r, q * r, m); + relative_eq!(m, q * r, epsilon = 1.0e-7) && + q.is_orthogonal(1.0e-7) + } - relative_eq!(m, q * r, epsilon = 1.0e-7) && - q.is_orthogonal(1.0e-7) - } + fn qr_static_square(m: Matrix4<$scalar>) -> bool { + let m = m.map(|e| e.0); + let qr = m.qr(); + let q = qr.q(); + let r = qr.r(); - fn qr_solve(n: usize, nb: usize) -> bool { - if n != 0 && nb != 0 { - let n = cmp::min(n, 50); // To avoid slowing down the test too much. - let nb = cmp::min(nb, 50); // To avoid slowing down the test too much. - let m = DMatrix::::new_random(n, n); + println!("{}{}{}{}", q, r, q * r, m); - let qr = m.clone().qr(); - let b1 = DVector::new_random(n); - let b2 = DMatrix::new_random(n, nb); + relative_eq!(m, q * r, epsilon = 1.0e-7) && + q.is_orthogonal(1.0e-7) + } - if qr.is_invertible() { - let sol1 = qr.solve(&b1).unwrap(); - let sol2 = qr.solve(&b2).unwrap(); + fn qr_solve(n: usize, nb: usize) -> bool { + if n != 0 && nb != 0 { + let n = cmp::min(n, 50); // To avoid slowing down the test too much. + let nb = cmp::min(nb, 50); // To avoid slowing down the test too much. + let m = DMatrix::<$scalar>::new_random(n, n).map(|e| e.0); - return relative_eq!(&m * sol1, b1, epsilon = 1.0e-6) && - relative_eq!(&m * sol2, b2, epsilon = 1.0e-6) + let qr = m.clone().qr(); + let b1 = DVector::<$scalar>::new_random(n).map(|e| e.0); + let b2 = DMatrix::<$scalar>::new_random(n, nb).map(|e| e.0); + + if qr.is_invertible() { + let sol1 = qr.solve(&b1).unwrap(); + let sol2 = qr.solve(&b2).unwrap(); + + return relative_eq!(&m * sol1, b1, epsilon = 1.0e-6) && + relative_eq!(&m * sol2, b2, epsilon = 1.0e-6) + } + } + + return true; + } + + fn qr_solve_static(m: Matrix4<$scalar>) -> bool { + let m = m.map(|e| e.0); + let qr = m.qr(); + let b1 = Vector4::<$scalar>::new_random().map(|e| e.0); + let b2 = Matrix4x3::<$scalar>::new_random().map(|e| e.0); + + if qr.is_invertible() { + let sol1 = qr.solve(&b1).unwrap(); + let sol2 = qr.solve(&b2).unwrap(); + + relative_eq!(m * sol1, b1, epsilon = 1.0e-6) && + relative_eq!(m * sol2, b2, epsilon = 1.0e-6) + } + else { + false + } + } + + fn qr_inverse(n: usize) -> bool { + let n = cmp::max(1, cmp::min(n, 15)); // To avoid slowing down the test too much. + let m = DMatrix::<$scalar>::new_random(n, n).map(|e| e.0); + + if let Some(m1) = m.clone().qr().try_inverse() { + let id1 = &m * &m1; + let id2 = &m1 * &m; + + id1.is_identity(1.0e-5) && id2.is_identity(1.0e-5) + } + else { + true + } + } + + fn qr_inverse_static(m: Matrix4<$scalar>) -> bool { + let m = m.map(|e| e.0); + let qr = m.qr(); + + if let Some(m1) = qr.try_inverse() { + let id1 = &m * &m1; + let id2 = &m1 * &m; + + id1.is_identity(1.0e-5) && id2.is_identity(1.0e-5) + } + else { + true + } + } } } - - return true; } +); - fn qr_solve_static(m: Matrix4) -> bool { - let qr = m.qr(); - let b1 = Vector4::new_random(); - let b2 = Matrix4x3::new_random(); - - if qr.is_invertible() { - let sol1 = qr.solve(&b1).unwrap(); - let sol2 = qr.solve(&b2).unwrap(); - - relative_eq!(m * sol1, b1, epsilon = 1.0e-6) && - relative_eq!(m * sol2, b2, epsilon = 1.0e-6) - } - else { - false - } - } - - fn qr_inverse(n: usize) -> bool { - let n = cmp::max(1, cmp::min(n, 15)); // To avoid slowing down the test too much. - let m = DMatrix::::new_random(n, n); - - if let Some(m1) = m.clone().qr().try_inverse() { - let id1 = &m * &m1; - let id2 = &m1 * &m; - - id1.is_identity(1.0e-5) && id2.is_identity(1.0e-5) - } - else { - true - } - } - - fn qr_inverse_static(m: Matrix4) -> bool { - let qr = m.qr(); - - if let Some(m1) = qr.try_inverse() { - let id1 = &m * &m1; - let id2 = &m1 * &m; - - id1.is_identity(1.0e-5) && id2.is_identity(1.0e-5) - } - else { - true - } - } -} +gen_tests!(complex, RandComplex); +gen_tests!(f64, RandScalar); diff --git a/tests/linalg/tridiagonal.rs b/tests/linalg/tridiagonal.rs index 6db86aef..132edba5 100644 --- a/tests/linalg/tridiagonal.rs +++ b/tests/linalg/tridiagonal.rs @@ -3,12 +3,24 @@ use std::cmp; use na::{DMatrix, Matrix2, Matrix4}; +use core::helper::{RandScalar, RandComplex}; quickcheck! { - fn symm_tridiagonal(n: usize) -> bool { - let n = cmp::max(1, cmp::min(n, 50)); - let m = DMatrix::::new_random(n, n); - let tri = m.clone().symmetric_tridiagonalize(); +// fn symm_tridiagonal(n: usize) -> bool { +// let n = cmp::max(1, cmp::min(n, 50)); +// let m = DMatrix::>::new_random(n, n).map(|e| e.0).hermitian_part(); +// let tri = m.clone().symmetric_tridiagonalize(); +// let recomp = tri.recompose(); +// +// println!("{}{}", m.lower_triangle(), recomp.lower_triangle()); +// +// relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-7) +// } + + fn symm_tridiagonal_static_square(m: Matrix4>) -> bool { + let m = m.map(|e| e.0).hermitian_part(); + let tri = m.symmetric_tridiagonalize(); + println!("Internal tri: {}{}", tri.internal_tri(), tri.off_diagonal()); let recomp = tri.recompose(); println!("{}{}", m.lower_triangle(), recomp.lower_triangle()); @@ -16,20 +28,11 @@ quickcheck! { relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-7) } - fn symm_tridiagonal_static_square(m: Matrix4) -> bool { - let tri = m.symmetric_tridiagonalize(); - println!("{}{}", tri.internal_tri(), tri.off_diagonal()); - let recomp = tri.recompose(); - - println!("{}{}", m.lower_triangle(), recomp.lower_triangle()); - - relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-7) - } - - fn symm_tridiagonal_static_square_2x2(m: Matrix2) -> bool { - let tri = m.symmetric_tridiagonalize(); - let recomp = tri.recompose(); - - relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-7) - } +// fn symm_tridiagonal_static_square_2x2(m: Matrix2>) -> bool { +// let m = m.map(|e| e.0).hermitian_part(); +// let tri = m.symmetric_tridiagonalize(); +// let recomp = tri.recompose(); +// +// relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-7) +// } } From 010c009cfffd5ba748e02b32c803bad35ce8fc47 Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Tue, 12 Mar 2019 13:15:02 +0100 Subject: [PATCH 03/28] Fix Schur decomposition. --- src/base/blas.rs | 79 ++++++++++++++++++++++++++++- src/base/matrix.rs | 7 ++- src/geometry/reflection.rs | 4 +- src/linalg/givens.rs | 31 +++++------ src/linalg/schur.rs | 21 ++++---- src/linalg/symmetric_eigen.rs | 17 ++++--- src/linalg/symmetric_tridiagonal.rs | 8 +-- tests/linalg/eigen.rs | 14 +++-- tests/linalg/hessenberg.rs | 7 +-- tests/linalg/real_schur.rs | 34 +++++++------ tests/linalg/tridiagonal.rs | 43 +++++++--------- 11 files changed, 181 insertions(+), 84 deletions(-) diff --git a/src/base/blas.rs b/src/base/blas.rs index 6c0c029d..5eddf2b5 100644 --- a/src/base/blas.rs +++ b/src/base/blas.rs @@ -684,7 +684,7 @@ where assert!( a.is_square(), - "Syetric gemv: the input matrix must be square." + "Symmetric gemv: the input matrix must be square." ); assert!( dim2 == dim3 && dim1 == dim2, @@ -715,6 +715,83 @@ where } } + /// Computes `self = alpha * a * x + beta * self`, where `a` is a **symmetric** matrix, `x` a + /// vector, and `alpha, beta` two scalars. + /// + /// If `beta` is zero, `self` is never read. If `self` is read, only its lower-triangular part + /// (including the diagonal) is actually read. + /// + /// # Examples: + /// + /// ``` + /// # use nalgebra::{Matrix2, Vector2}; + /// let mat = Matrix2::new(1.0, 2.0, + /// 2.0, 4.0); + /// let mut vec1 = Vector2::new(1.0, 2.0); + /// let vec2 = Vector2::new(0.1, 0.2); + /// vec1.gemv_symm(10.0, &mat, &vec2, 5.0); + /// assert_eq!(vec1, Vector2::new(10.0, 20.0)); + /// + /// + /// // The matrix upper-triangular elements can be garbage because it is never + /// // read by this method. Therefore, it is not necessary for the caller to + /// // fill the matrix struct upper-triangle. + /// let mat = Matrix2::new(1.0, 9999999.9999999, + /// 2.0, 4.0); + /// let mut vec1 = Vector2::new(1.0, 2.0); + /// vec1.gemv_symm(10.0, &mat, &vec2, 5.0); + /// assert_eq!(vec1, Vector2::new(10.0, 20.0)); + /// ``` + #[inline] + pub fn cgemv_symm( + &mut self, + alpha: N, + a: &SquareMatrix, + x: &Vector, + beta: N, + ) where + N: Complex, + SB: Storage, + SC: Storage, + ShapeConstraint: DimEq + AreMultipliable, + { + let dim1 = self.nrows(); + let dim2 = a.nrows(); + let dim3 = x.nrows(); + + assert!( + a.is_square(), + "Symmetric cgemv: the input matrix must be square." + ); + assert!( + dim2 == dim3 && dim1 == dim2, + "Symmetric cgemv: dimensions mismatch." + ); + + if dim2 == 0 { + return; + } + + // FIXME: avoid bound checks. + let col2 = a.column(0); + let val = unsafe { *x.vget_unchecked(0) }; + self.axpy(alpha * val, &col2, beta); + self[0] += alpha * a.slice_range(1.., 0).cdot(&x.rows_range(1..)); + + for j in 1..dim2 { + let col2 = a.column(j); + let dot = col2.rows_range(j..).cdot(&x.rows_range(j..)); + + let val; + unsafe { + val = *x.vget_unchecked(j); + *self.vget_unchecked_mut(j) += alpha * dot; + } + self.rows_range_mut(j + 1..) + .axpy(alpha * val, &col2.rows_range(j + 1..), N::one()); + } + } + /// Computes `self = alpha * a.transpose() * x + beta * self`, where `a` is a matrix, `x` a vector, and /// `alpha, beta` two scalars. /// diff --git a/src/base/matrix.rs b/src/base/matrix.rs index 3fa276f0..e7cf0026 100644 --- a/src/base/matrix.rs +++ b/src/base/matrix.rs @@ -997,7 +997,12 @@ impl> Matrix { let dim = self.shape().0; - for i in 1..dim { + for i in 0..dim { + { + let diag = unsafe { self.get_unchecked_mut((i, i)) }; + *diag = diag.conjugate(); + } + for j in 0..i { unsafe { let ref_ij = self.get_unchecked_mut((i, j)) as *mut N; diff --git a/src/geometry/reflection.rs b/src/geometry/reflection.rs index ac63b7da..fca0f548 100644 --- a/src/geometry/reflection.rs +++ b/src/geometry/reflection.rs @@ -72,13 +72,13 @@ impl> Reflection { ShapeConstraint: DimEq + AreMultipliable, DefaultAllocator: Allocator { - rhs.mul_to(&self.axis.conjugate(), work); + rhs.mul_to(&self.axis, work); if !self.bias.is_zero() { work.add_scalar_mut(-self.bias); } let m_two: N = ::convert(-2.0f64); - rhs.ger(m_two, &work, &self.axis, N::one()); + rhs.ger(m_two, &work, &self.axis.conjugate(), N::one()); } } diff --git a/src/linalg/givens.rs b/src/linalg/givens.rs index 7e6a881e..472f3bb3 100644 --- a/src/linalg/givens.rs +++ b/src/linalg/givens.rs @@ -1,6 +1,7 @@ //! Construction of givens rotations. use alga::general::{Complex, Real}; +use num::Zero; use num_complex::Complex as NumComplex; use base::dimension::{Dim, U2}; @@ -11,7 +12,9 @@ use base::{Vector, Matrix}; use geometry::UnitComplex; /// A Givens rotation. +#[derive(Debug)] pub struct GivensRotation { + // FIXME: c should be a `N::Real`. c: N, s: N } @@ -47,24 +50,22 @@ pub fn cancel_x>(v: &Vector) -> Option<(Uni // Matrix = UnitComplex * Matrix impl GivensRotation { - /// Initializes a Givens rotation form its non-normalized cosine an sine components. + /// Initializes a Givens rotation from its non-normalized cosine an sine components. pub fn new(c: N, s: N) -> Self { - let denom = (c.modulus_squared() + s.modulus_squared()).sqrt(); - Self { - c: c.unscale(denom), - s: s.unscale(denom) - } + let res = Self::try_new(c, s, N::Real::zero()).unwrap(); + println!("The rot: {:?}", res); + res } /// Initializes a Givens rotation form its non-normalized cosine an sine components. pub fn try_new(c: N, s: N, eps: N::Real) -> Option { - let denom = (c.modulus_squared() + s.modulus_squared()).sqrt(); + let (mod0, sign0) = c.to_exp(); + let denom = (mod0 * mod0 + s.modulus_squared()).sqrt(); if denom > eps { - Some(Self { - c: c.unscale(denom), - s: s.unscale(denom) - }) + let c = N::from_real(mod0 / denom); + let s = s / sign0.scale(denom); + Some(Self { c, s }) } else { None } @@ -116,7 +117,7 @@ impl GivensRotation { /// The inverse of this givens rotation. pub fn inverse(&self) -> Self { - Self { c: self.c, s: -self.s.conjugate() } + Self { c: self.c, s: -self.s } } /// Performs the multiplication `rhs = self * rhs` in-place. @@ -139,8 +140,8 @@ impl GivensRotation { let a = *rhs.get_unchecked((0, j)); let b = *rhs.get_unchecked((1, j)); - *rhs.get_unchecked_mut((0, j)) = c * a - s.conjugate() * b; - *rhs.get_unchecked_mut((1, j)) = s * a + c.conjugate() * b; + *rhs.get_unchecked_mut((0, j)) = c * a + -s.conjugate() * b; + *rhs.get_unchecked_mut((1, j)) = s * a + c * b; } } } @@ -167,7 +168,7 @@ impl GivensRotation { let b = *lhs.get_unchecked((j, 1)); *lhs.get_unchecked_mut((j, 0)) = c * a + s * b; - *lhs.get_unchecked_mut((j, 1)) = -s.conjugate() * a + c.conjugate() * b; + *lhs.get_unchecked_mut((j, 1)) = -s.conjugate() * a + c * b; } } } diff --git a/src/linalg/schur.rs b/src/linalg/schur.rs index fa7e1736..2eca9843 100644 --- a/src/linalg/schur.rs +++ b/src/linalg/schur.rs @@ -96,6 +96,7 @@ where let dim = m.data.shape().0; + // Specialization would make this easier. if dim.value() == 0 { let vecs = Some(MatrixN::from_element_generic(dim, dim, N::zero())); let vals = MatrixN::from_element_generic(dim, dim, N::zero()); @@ -107,9 +108,7 @@ where } else { return Some((None, m)); } - } - // Specialization would make this easier. - else if dim.value() == 2 { + } else if dim.value() == 2 { return decompose_2x2(m, compute_q); } @@ -421,7 +420,7 @@ where q = Some(MatrixN::from_column_slice_generic( dim, dim, - &[rot.c(), rot.s(), -rot.s().conjugate(), rot.c().conjugate()], + &[rot.c(), rot.s(), -rot.s().conjugate(), rot.c()], )); } } @@ -444,9 +443,9 @@ fn compute_2x2_eigvals>( let h01 = m[(0, 1)]; let h11 = m[(1, 1)]; - // NOTE: this discriminant computation is mor stable than the + // NOTE: this discriminant computation is more stable than the // one based on the trace and determinant: 0.25 * tra * tra - det - // because et ensures positiveness for symmetric matrices. + // because it ensures positiveness for symmetric matrices. let val = (h00 - h11) * ::convert(0.5); let discr = h10 * h01 + val * val; @@ -471,16 +470,18 @@ fn compute_2x2_basis>( } if let Some((eigval1, eigval2)) = compute_2x2_eigvals(m) { - let x1 = m[(1, 1)] - eigval1; - let x2 = m[(1, 1)] - eigval2; + let x1 = eigval1 - m[(1, 1)]; + let x2 = eigval2 - m[(1, 1)]; + + println!("eigval1: {}, eigval2: {}, h10: {}", eigval1, eigval2, h10); // NOTE: Choose the one that yields a larger x component. // This is necessary for numerical stability of the normalization of the complex // number. if x1.modulus() > x2.modulus() { - Some(GivensRotation::new(x1, -h10)) + Some(GivensRotation::new(x1, h10)) } else { - Some(GivensRotation::new(x2, -h10)) + Some(GivensRotation::new(x2, h10)) } } else { None diff --git a/src/linalg/symmetric_eigen.rs b/src/linalg/symmetric_eigen.rs index 8d16232f..6084c1b4 100644 --- a/src/linalg/symmetric_eigen.rs +++ b/src/linalg/symmetric_eigen.rs @@ -43,6 +43,7 @@ where DefaultAllocator: Allocator + Allocator /// The eigenvectors of the decomposed matrix. pub eigenvectors: MatrixN, + // FIXME: this should be a VectorN /// The unsorted eigenvalues of the decomposed matrix. pub eigenvalues: VectorN, } @@ -159,14 +160,14 @@ where DefaultAllocator: Allocator + Allocator let mij = off_diag[i]; let cc = rot.c() * rot.c(); - let ss = rot.s() * rot.s(); + let ss = rot.s() * rot.s().conjugate(); let cs = rot.c() * rot.s(); - let b = cs * ::convert(2.0) * mij; + let b = cs * mij.conjugate() + cs.conjugate() * mij; diag[i] = (cc * mii + ss * mjj) - b; diag[j] = (ss * mii + cc * mjj) + b; - off_diag[i] = cs * (mii - mjj) + mij * (cc - ss); + off_diag[i] = cs * (mii - mjj) + mij * cc - mij.conjugate() * rot.s() * rot.s(); if i != n - 1 { v.x = off_diag[i]; @@ -187,10 +188,8 @@ where DefaultAllocator: Allocator + Allocator } } else if subdim == 2 { let m = Matrix2::new( - diag[start], - off_diag[start], - 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]); @@ -198,6 +197,10 @@ where DefaultAllocator: Allocator + Allocator diag[start + 0] = eigvals[0]; diag[start + 1] = eigvals[1]; + println!("Eigvals: {:?}", eigvals); + println!("m: {}", m); + println!("Curr q: {:?}", q); + if let Some(ref mut q) = q { if let Some(rot) = GivensRotation::try_new(basis.x, basis.y, eps) { rot.rotate_rows(&mut q.fixed_columns_mut::(start)); diff --git a/src/linalg/symmetric_tridiagonal.rs b/src/linalg/symmetric_tridiagonal.rs index 276dc6fb..9b54c596 100644 --- a/src/linalg/symmetric_tridiagonal.rs +++ b/src/linalg/symmetric_tridiagonal.rs @@ -53,6 +53,8 @@ where DefaultAllocator: Allocator + Allocator> pub fn new(mut m: MatrixN) -> Self { let dim = m.data.shape().0; + println!("Input m: {}", m.index((0.., 0..))); + assert!( m.is_square(), "Unable to compute the symmetric tridiagonal decomposition of a non-square matrix." @@ -75,11 +77,11 @@ where DefaultAllocator: Allocator + Allocator> if not_zero { let mut p = p.rows_range_mut(i..); - p.gemv_symm(::convert(2.0), &m, &axis.conjugate(), N::zero()); - let dot = axis.dot(&p); + p.cgemv_symm(::convert(2.0), &m, &axis, N::zero()); + let dot = axis.cdot(&p); // p.axpy(-dot, &axis.conjugate(), N::one()); m.ger_symm(-N::one(), &p, &axis.conjugate(), N::one()); - m.ger_symm(-N::one(), &axis, &p, N::one()); + m.ger_symm(-N::one(), &axis, &p.conjugate(), N::one()); m.ger_symm(dot * ::convert(2.0), &axis, &axis.conjugate(), N::one()); } } diff --git a/tests/linalg/eigen.rs b/tests/linalg/eigen.rs index c44bb098..28a2b0d1 100644 --- a/tests/linalg/eigen.rs +++ b/tests/linalg/eigen.rs @@ -9,6 +9,7 @@ mod quickcheck_tests { use std::cmp; quickcheck! { + /* fn symmetric_eigen(n: usize) -> bool { let n = cmp::max(1, cmp::min(n, 10)); let m = DMatrix::>::new_random(n, n).map(|e| e.0); @@ -42,29 +43,36 @@ mod quickcheck_tests { relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-5) } + */ fn symmetric_eigen_static_square_3x3(m: Matrix3>) -> bool { - let m = m.map(|e| e.0); + let m = m.map(|e| e.0).hermitian_part(); let eig = m.symmetric_eigen(); let recomp = eig.recompose(); + println!("Eigenvectors: {}", eig.eigenvectors); + println!("Eigenvalues: {}", eig.eigenvalues); println!("{}{}", m.lower_triangle(), recomp.lower_triangle()); relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-5) } +/* fn symmetric_eigen_static_square_2x2(m: Matrix2>) -> bool { - let m = m.map(|e| e.0); + let m = m.map(|e| e.0).hermitian_part(); let eig = m.symmetric_eigen(); let recomp = eig.recompose(); + println!("Eigenvectors: {}", eig.eigenvectors); println!("{}{}", m.lower_triangle(), recomp.lower_triangle()); relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-5) } + */ } } +/* // Test proposed on the issue #176 of rulinalg. #[test] fn symmetric_eigen_singular_24x24() { @@ -107,7 +115,7 @@ fn symmetric_eigen_singular_24x24() { recomp.lower_triangle(), epsilon = 1.0e-5 )); -} +}*/ // #[cfg(feature = "arbitrary")] // quickcheck! { diff --git a/tests/linalg/hessenberg.rs b/tests/linalg/hessenberg.rs index d9245110..72c2baab 100644 --- a/tests/linalg/hessenberg.rs +++ b/tests/linalg/hessenberg.rs @@ -4,6 +4,7 @@ use na::{DMatrix, Matrix2, Matrix4}; use core::helper::{RandScalar, RandComplex}; use std::cmp; + #[test] fn hessenberg_simple() { let m = Matrix2::new(1.0, 0.0, 1.0, 3.0); @@ -19,20 +20,20 @@ quickcheck! { let hess = m.clone().hessenberg(); let (p, h) = hess.unpack(); - relative_eq!(m, &p * h * p.transpose(), epsilon = 1.0e-7) + relative_eq!(m, &p * h * p.conjugate_transpose(), epsilon = 1.0e-7) } fn hessenberg_static_mat2(m: Matrix2>) -> bool { let m = m.map(|e| e.0); let hess = m.hessenberg(); let (p, h) = hess.unpack(); - relative_eq!(m, p * h * p.transpose(), epsilon = 1.0e-7) + relative_eq!(m, p * h * p.conjugate_transpose(), epsilon = 1.0e-7) } fn hessenberg_static(m: Matrix4>) -> bool { let m = m.map(|e| e.0); let hess = m.hessenberg(); let (p, h) = hess.unpack(); - relative_eq!(m, p * h * p.transpose(), epsilon = 1.0e-7) + relative_eq!(m, p * h * p.conjugate_transpose(), epsilon = 1.0e-7) } } diff --git a/tests/linalg/real_schur.rs b/tests/linalg/real_schur.rs index 554bbdef..54ad9ce4 100644 --- a/tests/linalg/real_schur.rs +++ b/tests/linalg/real_schur.rs @@ -2,7 +2,6 @@ use na::{DMatrix, Matrix3, Matrix4}; - #[test] fn schur_simpl_mat3() { let m = Matrix3::new(-2.0, -4.0, 2.0, @@ -19,48 +18,53 @@ fn schur_simpl_mat3() { mod quickcheck_tests { use std::cmp; use na::{DMatrix, Matrix2, Matrix3, Matrix4}; + use core::helper::{RandScalar, RandComplex}; quickcheck! { fn schur(n: usize) -> bool { let n = cmp::max(1, cmp::min(n, 10)); - let m = DMatrix::::new_random(n, n); + let m = DMatrix::>::new_random(n, n).map(|e| e.0); let (vecs, vals) = m.clone().real_schur().unpack(); - if !relative_eq!(&vecs * &vals * vecs.transpose(), m, epsilon = 1.0e-7) { - println!("{:.5}{:.5}", m, &vecs * &vals * vecs.transpose()); + if !relative_eq!(&vecs * &vals * vecs.conjugate_transpose(), m, epsilon = 1.0e-7) { + println!("{:.5}{:.5}", m, &vecs * &vals * vecs.conjugate_transpose()); } - relative_eq!(&vecs * vals * vecs.transpose(), m, epsilon = 1.0e-7) + relative_eq!(&vecs * vals * vecs.conjugate_transpose(), m, epsilon = 1.0e-7) } - fn schur_static_mat2(m: Matrix2) -> bool { + fn schur_static_mat2(m: Matrix2>) -> bool { + let m = m.map(|e| e.0); let (vecs, vals) = m.clone().real_schur().unpack(); - let ok = relative_eq!(vecs * vals * vecs.transpose(), m, epsilon = 1.0e-7); + let ok = relative_eq!(vecs * vals * vecs.conjugate_transpose(), m, epsilon = 1.0e-7); if !ok { - println!("{:.5}{:.5}", vecs, vals); - println!("Reconstruction:{}{}", m, &vecs * &vals * vecs.transpose()); + println!("Vecs: {:.5} Vals: {:.5}", vecs, vals); + println!("Reconstruction:{}{}", m, &vecs * &vals * vecs.conjugate_transpose()); } ok } - fn schur_static_mat3(m: Matrix3) -> bool { + fn schur_static_mat3(m: Matrix3>) -> bool { + let m = m.map(|e| e.0); let (vecs, vals) = m.clone().real_schur().unpack(); - let ok = relative_eq!(vecs * vals * vecs.transpose(), m, epsilon = 1.0e-7); + let ok = relative_eq!(vecs * vals * vecs.conjugate_transpose(), m, epsilon = 1.0e-7); if !ok { - println!("{:.5}{:.5}", m, &vecs * &vals * vecs.transpose()); + println!("Vecs: {:.5} Vals: {:.5}", vecs, vals); + println!("{:.5}{:.5}", m, &vecs * &vals * vecs.conjugate_transpose()); } ok } - fn schur_static_mat4(m: Matrix4) -> bool { + fn schur_static_mat4(m: Matrix4>) -> bool { + let m = m.map(|e| e.0); let (vecs, vals) = m.clone().real_schur().unpack(); - let ok = relative_eq!(vecs * vals * vecs.transpose(), m, epsilon = 1.0e-7); + let ok = relative_eq!(vecs * vals * vecs.conjugate_transpose(), m, epsilon = 1.0e-7); if !ok { - println!("{:.5}{:.5}", m, &vecs * &vals * vecs.transpose()); + println!("{:.5}{:.5}", m, &vecs * &vals * vecs.conjugate_transpose()); } ok } diff --git a/tests/linalg/tridiagonal.rs b/tests/linalg/tridiagonal.rs index 132edba5..5ecf32ff 100644 --- a/tests/linalg/tridiagonal.rs +++ b/tests/linalg/tridiagonal.rs @@ -6,33 +6,28 @@ use na::{DMatrix, Matrix2, Matrix4}; use core::helper::{RandScalar, RandComplex}; quickcheck! { -// fn symm_tridiagonal(n: usize) -> bool { -// let n = cmp::max(1, cmp::min(n, 50)); -// let m = DMatrix::>::new_random(n, n).map(|e| e.0).hermitian_part(); -// let tri = m.clone().symmetric_tridiagonalize(); -// let recomp = tri.recompose(); -// -// println!("{}{}", m.lower_triangle(), recomp.lower_triangle()); -// -// relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-7) -// } - - fn symm_tridiagonal_static_square(m: Matrix4>) -> bool { - let m = m.map(|e| e.0).hermitian_part(); - let tri = m.symmetric_tridiagonalize(); - println!("Internal tri: {}{}", tri.internal_tri(), tri.off_diagonal()); + fn symm_tridiagonal(n: usize) -> bool { + let n = cmp::max(1, cmp::min(n, 50)); + let m = DMatrix::>::new_random(n, n).map(|e| e.0).hermitian_part(); + let tri = m.clone().symmetric_tridiagonalize(); let recomp = tri.recompose(); - println!("{}{}", m.lower_triangle(), recomp.lower_triangle()); - relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-7) } -// fn symm_tridiagonal_static_square_2x2(m: Matrix2>) -> bool { -// let m = m.map(|e| e.0).hermitian_part(); -// let tri = m.symmetric_tridiagonalize(); -// let recomp = tri.recompose(); -// -// relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-7) -// } + fn symm_tridiagonal_static_square(m: Matrix4>) -> bool { + let m = m.map(|e| e.0).hermitian_part(); + let tri = m.symmetric_tridiagonalize(); + let recomp = tri.recompose(); + + relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-7) + } + + fn symm_tridiagonal_static_square_2x2(m: Matrix2>) -> bool { + let m = m.map(|e| e.0).hermitian_part(); + let tri = m.symmetric_tridiagonalize(); + let recomp = tri.recompose(); + + relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-7) + } } From e4748c69ce3e5f31cd6e7e2504daa4c6868118f1 Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Mon, 18 Mar 2019 11:23:19 +0100 Subject: [PATCH 04/28] Start fixing SVD. --- src/geometry/reflection.rs | 8 +- src/linalg/bidiagonal.rs | 20 +-- src/linalg/givens.rs | 83 ++++------ src/linalg/householder.rs | 15 +- src/linalg/mod.rs | 2 +- src/linalg/schur.rs | 7 +- src/linalg/svd.rs | 228 +++++++++++++++------------- src/linalg/symmetric_eigen.rs | 41 +++-- src/linalg/symmetric_tridiagonal.rs | 1 + tests/linalg/bidiagonal.rs | 1 + tests/linalg/eigen.rs | 13 +- tests/linalg/svd.rs | 21 ++- tests/linalg/tridiagonal.rs | 14 ++ 13 files changed, 248 insertions(+), 206 deletions(-) diff --git a/src/geometry/reflection.rs b/src/geometry/reflection.rs index fca0f548..237054b6 100644 --- a/src/geometry/reflection.rs +++ b/src/geometry/reflection.rs @@ -61,10 +61,10 @@ impl> Reflection { } } - /// Applies the reflection to the rows of `rhs`. + /// Applies the reflection to the rows of `lhs`. pub fn reflect_rows( &self, - rhs: &mut Matrix, + lhs: &mut Matrix, work: &mut Vector, ) where S2: StorageMut, @@ -72,13 +72,13 @@ impl> Reflection { ShapeConstraint: DimEq + AreMultipliable, DefaultAllocator: Allocator { - rhs.mul_to(&self.axis, work); + lhs.mul_to(&self.axis, work); if !self.bias.is_zero() { work.add_scalar_mut(-self.bias); } let m_two: N = ::convert(-2.0f64); - rhs.ger(m_two, &work, &self.axis.conjugate(), N::one()); + lhs.ger(m_two, &work, &self.axis.conjugate(), N::one()); } } diff --git a/src/linalg/bidiagonal.rs b/src/linalg/bidiagonal.rs index a44be398..e487758c 100644 --- a/src/linalg/bidiagonal.rs +++ b/src/linalg/bidiagonal.rs @@ -49,9 +49,9 @@ where // contiguous. This prevents some useless copies. uv: MatrixMN, /// The diagonal elements of the decomposed matrix. - pub diagonal: VectorN>, + diagonal: VectorN>, /// The off-diagonal elements of the decomposed matrix. - pub off_diagonal: VectorN, U1>>, + off_diagonal: VectorN, U1>>, upper_diagonal: bool, } @@ -143,9 +143,9 @@ where Bidiagonal { uv: matrix, - diagonal: diagonal, - off_diagonal: off_diagonal, - upper_diagonal: upper_diagonal, + diagonal, + off_diagonal, + upper_diagonal, } } @@ -231,7 +231,7 @@ where res } - /// Computes the orthogonal matrix `V` of this `U * D * V` decomposition. + /// Computes the orthogonal matrix `V_t` of this `U * D * V_t` decomposition. pub fn v_t(&self) -> MatrixMN, C> where DefaultAllocator: Allocator, C> { let (nrows, ncols) = self.uv.data.shape(); @@ -258,13 +258,13 @@ where } /// The diagonal part of this decomposed matrix. - pub fn diagonal(&self) -> &VectorN> { - &self.diagonal + pub fn diagonal(&self) -> VectorN> { + self.diagonal.map(|e| N::from_real(e.modulus())) } /// The off-diagonal part of this decomposed matrix. - pub fn off_diagonal(&self) -> &VectorN, U1>> { - &self.off_diagonal + pub fn off_diagonal(&self) -> VectorN, U1>> { + self.off_diagonal.map(|e| N::from_real(e.modulus())) } #[doc(hidden)] diff --git a/src/linalg/givens.rs b/src/linalg/givens.rs index 472f3bb3..72f4a427 100644 --- a/src/linalg/givens.rs +++ b/src/linalg/givens.rs @@ -1,7 +1,7 @@ //! Construction of givens rotations. use alga::general::{Complex, Real}; -use num::Zero; +use num::{Zero, One}; use num_complex::Complex as NumComplex; use base::dimension::{Dim, U2}; @@ -12,60 +12,37 @@ use base::{Vector, Matrix}; use geometry::UnitComplex; /// A Givens rotation. -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] pub struct GivensRotation { - // FIXME: c should be a `N::Real`. - c: N, + c: N::Real, s: N } -// XXX: remove this -/// Computes the rotation `R` required such that the `y` component of `R * v` is zero. -/// -/// Returns `None` if no rotation is needed (i.e. if `v.y == 0`). Otherwise, this returns the norm -/// of `v` and the rotation `r` such that `R * v = [ |v|, 0.0 ]^t` where `|v|` is the norm of `v`. -pub fn cancel_y>(v: &Vector) -> Option<(UnitComplex, N)> { - if !v[1].is_zero() { - let c = NumComplex::new(v[0], -v[1]); - Some(UnitComplex::from_complex_and_get(c)) - } else { - None - } -} - -// XXX: remove this -/// Computes the rotation `R` required such that the `x` component of `R * v` is zero. -/// -/// Returns `None` if no rotation is needed (i.e. if `v.x == 0`). Otherwise, this returns the norm -/// of `v` and the rotation `r` such that `R * v = [ 0.0, |v| ]^t` where `|v|` is the norm of `v`. -pub fn cancel_x>(v: &Vector) -> Option<(UnitComplex, N)> { - if !v[0].is_zero() { - let c = NumComplex::new(v[1], v[0]); - Some(UnitComplex::from_complex_and_get(c)) - } else { - None - } -} - - // Matrix = UnitComplex * Matrix impl GivensRotation { + /// The Givents rotation that does nothing. + pub fn identity() -> Self { + Self { + c: N::Real::one(), + s: N::zero() + } + } + /// Initializes a Givens rotation from its non-normalized cosine an sine components. - pub fn new(c: N, s: N) -> Self { - let res = Self::try_new(c, s, N::Real::zero()).unwrap(); - println!("The rot: {:?}", res); - res + pub fn new(c: N, s: N) -> (Self, N) { + Self::try_new(c, s, N::Real::zero()).unwrap() } /// Initializes a Givens rotation form its non-normalized cosine an sine components. - pub fn try_new(c: N, s: N, eps: N::Real) -> Option { + pub fn try_new(c: N, s: N, eps: N::Real) -> Option<(Self, N)> { let (mod0, sign0) = c.to_exp(); let denom = (mod0 * mod0 + s.modulus_squared()).sqrt(); if denom > eps { - let c = N::from_real(mod0 / denom); - let s = s / sign0.scale(denom); - Some(Self { c, s }) + let norm = sign0.scale(denom); + let c = mod0 / denom; + let s = s / norm; + Some((Self { c, s }, norm)) } else { None } @@ -79,8 +56,8 @@ impl GivensRotation { if !v[1].is_zero() { let (mod0, sign0) = v[0].to_exp(); let denom = (mod0 * mod0 + v[1].modulus_squared()).sqrt(); - let c = N::from_real(mod0 / denom); - let s = (sign0 * v[1].conjugate()).unscale(-denom); + let c = mod0 / denom; + let s = -v[1] / sign0.scale(denom); let r = sign0.scale(denom); Some((Self { c, s }, r)) } else { @@ -94,11 +71,11 @@ impl GivensRotation { /// of `v` and the rotation `r` such that `R * v = [ 0.0, |v| ]^t` where `|v|` is the norm of `v`. pub fn cancel_x>(v: &Vector) -> Option<(Self, N)> { if !v[0].is_zero() { - let (mod0, sign0) = v[0].to_exp(); - let denom = (mod0 * mod0 + v[1].modulus_squared()).sqrt(); - let c = N::from_real(mod0 / denom); - let s = (sign0 * v[1].conjugate()).unscale(denom); - let r = sign0.scale(denom); + let (mod1, sign1) = v[1].to_exp(); + let denom = (mod1 * mod1 + v[0].modulus_squared()).sqrt(); + let c = mod1 / denom; + let s = (v[0].conjugate() * sign1).unscale(denom); + let r = sign1.scale(denom); Some((Self { c, s }, r)) } else { None @@ -106,7 +83,7 @@ impl GivensRotation { } /// The cos part of this roration. - pub fn c(&self) -> N { + pub fn c(&self) -> N::Real { self.c } @@ -140,8 +117,8 @@ impl GivensRotation { let a = *rhs.get_unchecked((0, j)); let b = *rhs.get_unchecked((1, j)); - *rhs.get_unchecked_mut((0, j)) = c * a + -s.conjugate() * b; - *rhs.get_unchecked_mut((1, j)) = s * a + c * b; + *rhs.get_unchecked_mut((0, j)) = a.scale(c) - s.conjugate() * b; + *rhs.get_unchecked_mut((1, j)) = s * a + b.scale(c); } } } @@ -167,8 +144,8 @@ impl GivensRotation { let a = *lhs.get_unchecked((j, 0)); let b = *lhs.get_unchecked((j, 1)); - *lhs.get_unchecked_mut((j, 0)) = c * a + s * b; - *lhs.get_unchecked_mut((j, 1)) = -s.conjugate() * a + c * b; + *lhs.get_unchecked_mut((j, 0)) = a.scale(c) + s * b; + *lhs.get_unchecked_mut((j, 1)) = -s.conjugate() * a + b.scale(c); } } } diff --git a/src/linalg/householder.rs b/src/linalg/householder.rs index 0fe46499..dc97b9b3 100644 --- a/src/linalg/householder.rs +++ b/src/linalg/householder.rs @@ -23,20 +23,20 @@ pub fn reflection_axis_mut>( let reflection_norm = reflection_sq_norm.sqrt(); let factor; - let scaled_norm; + let signed_norm; unsafe { - let (modulus, exp) = column.vget_unchecked(0).to_exp(); - scaled_norm = exp.scale(reflection_norm); + let (modulus, sign) = column.vget_unchecked(0).to_exp(); + signed_norm = sign.scale(reflection_norm); factor = (reflection_sq_norm + modulus * reflection_norm) * ::convert(2.0); - *column.vget_unchecked_mut(0) += scaled_norm; + *column.vget_unchecked_mut(0) += signed_norm; }; if !factor.is_zero() { column.unscale_mut(factor.sqrt()); - (-scaled_norm, true) + (-signed_norm, true) } else { - (-scaled_norm, false) + (-signed_norm, false) } } @@ -67,7 +67,7 @@ pub fn clear_column_unchecked( } } -/// Uses an hoseholder reflection to zero out the `irow`-th row, ending before the `shift + 1`-th +/// Uses an householder reflection to zero out the `irow`-th row, ending before the `shift + 1`-th /// superdiagonal element. #[doc(hidden)] pub fn clear_row_unchecked( @@ -85,6 +85,7 @@ pub fn clear_row_unchecked( axis.tr_copy_from(&top.columns_range(irow + shift..)); let (reflection_norm, not_zero) = reflection_axis_mut(&mut axis); + axis.conjugate_mut(); // So that reflect_rows actually cancels the first row. *diag_elt = reflection_norm; if not_zero { diff --git a/src/linalg/mod.rs b/src/linalg/mod.rs index 4418b283..6c7f7194 100644 --- a/src/linalg/mod.rs +++ b/src/linalg/mod.rs @@ -30,6 +30,6 @@ pub use self::lu::*; pub use self::permutation_sequence::*; pub use self::qr::*; pub use self::schur::*; -pub use self::svd::*; +//pub use self::svd::*; pub use self::symmetric_eigen::*; pub use self::symmetric_tridiagonal::*; diff --git a/src/linalg/schur.rs b/src/linalg/schur.rs index 2eca9843..b815131e 100644 --- a/src/linalg/schur.rs +++ b/src/linalg/schur.rs @@ -417,10 +417,11 @@ where if compute_q { // XXX: we have to build the matrix manually because // rot.to_rotation_matrix().unwrap() causes an ICE. + let c = N::from_real(rot.c()); q = Some(MatrixN::from_column_slice_generic( dim, dim, - &[rot.c(), rot.s(), -rot.s().conjugate(), rot.c()], + &[c, rot.s(), -rot.s().conjugate(), c], )); } } @@ -479,9 +480,9 @@ fn compute_2x2_basis>( // This is necessary for numerical stability of the normalization of the complex // number. if x1.modulus() > x2.modulus() { - Some(GivensRotation::new(x1, h10)) + Some(GivensRotation::new(x1, h10).0) } else { - Some(GivensRotation::new(x2, h10)) + Some(GivensRotation::new(x2, h10).0) } } else { None diff --git a/src/linalg/svd.rs b/src/linalg/svd.rs index 67b49604..bcc93333 100644 --- a/src/linalg/svd.rs +++ b/src/linalg/svd.rs @@ -1,27 +1,29 @@ #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Serialize}; -use num_complex::Complex; +use num_complex::Complex as NumComplex; +use num::Zero; use std::ops::MulAssign; +use approx::AbsDiffEq; -use alga::general::Real; +use alga::general::Complex; use allocator::Allocator; use base::{DefaultAllocator, Matrix, Matrix2x3, MatrixMN, Vector2, VectorN}; use constraint::{SameNumberOfRows, ShapeConstraint}; use dimension::{Dim, DimDiff, DimMin, DimMinimum, DimSub, U1, U2}; use storage::Storage; -use geometry::UnitComplex; use linalg::givens; use linalg::symmetric_eigen; use linalg::Bidiagonal; +use linalg::givens::GivensRotation; /// Singular Value Decomposition of a general matrix. #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[cfg_attr( feature = "serde-serialize", serde(bound( - serialize = "DefaultAllocator: Allocator + + serialize = "DefaultAllocator: Allocator + Allocator> + Allocator, C> + Allocator>, @@ -33,7 +35,7 @@ use linalg::Bidiagonal; #[cfg_attr( feature = "serde-serialize", serde(bound( - deserialize = "DefaultAllocator: Allocator + + deserialize = "DefaultAllocator: Allocator + Allocator> + Allocator, C> + Allocator>, @@ -43,7 +45,7 @@ use linalg::Bidiagonal; )) )] #[derive(Clone, Debug)] -pub struct SVD, C: Dim> +pub struct SVD, C: Dim> where DefaultAllocator: Allocator, C> + Allocator> + Allocator> @@ -52,11 +54,13 @@ where DefaultAllocator: Allocator, C> pub u: Option>>, /// The right-singular vectors `V^t` of this SVD. pub v_t: Option, C>>, + // FIXME: this should a vector of N::Real + // because singular values are necessarily real. /// The singular values of this SVD. pub singular_values: VectorN>, } -impl, C: Dim> Copy for SVD +impl, C: Dim> Copy for SVD where DefaultAllocator: Allocator, C> + Allocator> @@ -66,7 +70,7 @@ where VectorN>: Copy, {} -impl, C: Dim> SVD +impl, C: Dim> SVD where DimMinimum: DimSub, // for Bidiagonal. DefaultAllocator: Allocator @@ -79,7 +83,7 @@ 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::default_epsilon(), 0).unwrap() + Self::try_new(matrix, compute_u, compute_v, N::Real::default_epsilon(), 0).unwrap() } /// Attempts to compute the Singular Value Decomposition of `matrix` using implicit shift. @@ -96,7 +100,7 @@ where mut matrix: MatrixMN, compute_u: bool, compute_v: bool, - eps: N, + eps: N::Real, max_niter: usize, ) -> Option { @@ -108,18 +112,20 @@ where let min_nrows_ncols = nrows.min(ncols); let dim = min_nrows_ncols.value(); - let m_amax = matrix.amax(); + let m_amax = matrix.camax(); if !m_amax.is_zero() { - matrix /= m_amax; + matrix.unscale_mut(m_amax); } let mut b = Bidiagonal::new(matrix); let mut u = if compute_u { Some(b.u()) } else { None }; let mut v_t = if compute_v { Some(b.v_t()) } else { None }; + let mut diagonal = b.diagonal(); + let mut off_diagonal = b.off_diagonal(); let mut niter = 0; - let (mut start, mut end) = Self::delimit_subproblem(&mut b, &mut u, &mut v_t, 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; @@ -131,19 +137,19 @@ where let mut vec; { - let dm = b.diagonal[m]; - let dn = b.diagonal[n]; - let fm = b.off_diagonal[m]; + let dm = diagonal[m]; + let dn = diagonal[n]; + let fm = off_diagonal[m]; - let tmm = dm * dm + b.off_diagonal[m - 1] * b.off_diagonal[m - 1]; + let tmm = dm * dm + off_diagonal[m - 1] * off_diagonal[m - 1]; let tmn = dm * fm; let tnn = dn * dn + fm * fm; let shift = symmetric_eigen::wilkinson_shift(tmm, tnn, tmn); vec = Vector2::new( - b.diagonal[start] * b.diagonal[start] - shift, - b.diagonal[start] * b.off_diagonal[start], + diagonal[start] * diagonal[start] - shift, + diagonal[start] * off_diagonal[start], ); } @@ -151,31 +157,31 @@ where let m12 = if k == n - 1 { N::zero() } else { - b.off_diagonal[k + 1] + off_diagonal[k + 1] }; let mut subm = Matrix2x3::new( - b.diagonal[k], - b.off_diagonal[k], + diagonal[k], + off_diagonal[k], N::zero(), N::zero(), - b.diagonal[k + 1], + diagonal[k + 1], m12, ); - if let Some((rot1, norm1)) = givens::cancel_y(&vec) { - rot1.conjugate() + if let Some((rot1, norm1)) = GivensRotation::cancel_y(&vec) { + rot1.inverse() .rotate_rows(&mut subm.fixed_columns_mut::(0)); if k > start { // This is not the first iteration. - b.off_diagonal[k - 1] = norm1; + off_diagonal[k - 1] = norm1; } let v = Vector2::new(subm[(0, 0)], subm[(1, 0)]); // FIXME: does the case `v.y == 0` ever happen? let (rot2, norm2) = - givens::cancel_y(&v).unwrap_or((UnitComplex::identity(), subm[(0, 0)])); + GivensRotation::cancel_y(&v).unwrap_or((GivensRotation::identity(), subm[(0, 0)])); rot2.rotate(&mut subm.fixed_columns_mut::(1)); subm[(0, 0)] = norm2; @@ -197,12 +203,12 @@ where } } - b.diagonal[k + 0] = subm[(0, 0)]; - b.diagonal[k + 1] = subm[(1, 1)]; - b.off_diagonal[k + 0] = subm[(0, 1)]; + diagonal[k + 0] = subm[(0, 0)]; + diagonal[k + 1] = subm[(1, 1)]; + off_diagonal[k + 0] = subm[(0, 1)]; if k != n - 1 { - b.off_diagonal[k + 1] = subm[(1, 2)]; + off_diagonal[k + 1] = subm[(1, 2)]; } vec.x = subm[(0, 1)]; @@ -214,16 +220,16 @@ where } else if subdim == 2 { // Solve the remaining 2x2 subproblem. let (u2, s, v2) = Self::compute_2x2_uptrig_svd( - b.diagonal[start], - b.off_diagonal[start], - b.diagonal[start + 1], + diagonal[start], + off_diagonal[start], + diagonal[start + 1], compute_u && b.is_upper_diagonal() || compute_v && !b.is_upper_diagonal(), compute_v && b.is_upper_diagonal() || compute_u && !b.is_upper_diagonal(), ); - b.diagonal[start + 0] = s[0]; - b.diagonal[start + 1] = s[1]; - b.off_diagonal[start] = N::zero(); + diagonal[start + 0] = s[0]; + diagonal[start + 1] = s[1]; + off_diagonal[start] = N::zero(); if let Some(ref mut u) = u { let rot = if b.is_upper_diagonal() { @@ -247,7 +253,7 @@ where } // Re-delimit the subproblem in case some decoupling occurred. - let sub = Self::delimit_subproblem(&mut b, &mut u, &mut v_t, 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; @@ -257,24 +263,25 @@ where } } - b.diagonal *= m_amax; + diagonal.scale_mut(m_amax); // Ensure all singular value are non-negative. for i in 0..dim { - let sval = b.diagonal[i]; - if sval < N::zero() { - b.diagonal[i] = -sval; + let sval = diagonal[i]; + let (modulus, sign) = sval.to_exp(); + if modulus != N::Real::zero() { + diagonal[i] = N::from_real(modulus); if let Some(ref mut u) = u { - u.column_mut(i).neg_mut(); + u.column_mut(i).mul_assign(sign); } } } Some(Self { - u: u, - v_t: v_t, - singular_values: b.diagonal, + u, + v_t, + singular_values: diagonal, }) } @@ -287,10 +294,10 @@ where m22: N, compute_u: bool, compute_v: bool, - ) -> (Option>, Vector2, Option>) + ) -> (Option>, Vector2, Option>) { - let two: N = ::convert(2.0f64); - let half: N = ::convert(0.5f64); + let two: N::Real = ::convert(2.0f64); + let half: N::Real = ::convert(0.5f64); let denom = (m11 + m22).hypot(m12) + (m11 - m22).hypot(m12); @@ -298,24 +305,29 @@ where // This prevents cancellation issues when constructing the vector `csv` below. If we chose // otherwise, we would have v1 ~= m11 when m12 is small. This would cause catastrophic // cancellation on `v1 * v1 - m11 * m11` below. - let v1 = two * m11 * m22 / denom; - let v2 = half * denom; + let mut v1 = (m11 * m22).scale(two / denom); + let mut v2 = N::from_real(half * denom); let mut u = None; let mut v_t = None; if compute_u || compute_v { - let csv = Vector2::new(m11 * m12, v1 * v1 - m11 * m11).normalize(); + let (csv, sgn_v) = GivensRotation::new(m11 * m12, v1 * v1 - m11 * m11); + v1 *= sgn_v; + v2 *= sgn_v; if compute_v { - v_t = Some(UnitComplex::new_unchecked(Complex::new(csv.x, csv.y))); + v_t = Some(csv); } if compute_u { - let cu = (m11 * csv.x + m12 * csv.y) / v1; - let su = (m22 * csv.y) / v1; + let cu = (m11.scale(csv.c()) + m12 * csv.s()) / v1; + let su = (m22 * csv.s()) / v1; + let (csu, sgn_u) = GivensRotation::new(cu, su); - u = Some(UnitComplex::new_unchecked(Complex::new(cu, su))); + v1 *= sgn_u; + v2 *= sgn_u; + u = Some(csu); } } @@ -338,11 +350,13 @@ where */ fn delimit_subproblem( - b: &mut Bidiagonal, + diagonal: &mut VectorN>, + off_diagonal: &mut VectorN, U1>>, u: &mut Option>>, v_t: &mut Option, C>>, + is_upper_diagonal: bool, end: usize, - eps: N, + eps: N::Real, ) -> (usize, usize) { let mut n = end; @@ -350,20 +364,20 @@ where while n > 0 { let m = n - 1; - if b.off_diagonal[m].is_zero() - || b.off_diagonal[m].abs() <= eps * (b.diagonal[n].abs() + b.diagonal[m].abs()) + if off_diagonal[m].is_zero() + || off_diagonal[m].modulus() <= eps * (diagonal[n].modulus() + diagonal[m].modulus()) { - b.off_diagonal[m] = N::zero(); - } else if b.diagonal[m].abs() <= eps { - b.diagonal[m] = N::zero(); - Self::cancel_horizontal_off_diagonal_elt(b, u, v_t, m, m + 1); + off_diagonal[m] = N::zero(); + } else if diagonal[m].modulus() <= eps { + diagonal[m] = N::zero(); + 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(b, u, v_t, m - 1); + Self::cancel_vertical_off_diagonal_elt(diagonal, off_diagonal, u, v_t, is_upper_diagonal, m - 1); } - } else if b.diagonal[n].abs() <= eps { - b.diagonal[n] = N::zero(); - Self::cancel_vertical_off_diagonal_elt(b, u, v_t, m); + } else if diagonal[n].modulus() <= eps { + diagonal[n] = N::zero(); + Self::cancel_vertical_off_diagonal_elt(diagonal, off_diagonal, u, v_t, is_upper_diagonal, m); } else { break; } @@ -379,18 +393,18 @@ where while new_start > 0 { let m = new_start - 1; - if b.off_diagonal[m].abs() <= eps * (b.diagonal[new_start].abs() + b.diagonal[m].abs()) + if off_diagonal[m].modulus() <= eps * (diagonal[new_start].modulus() + diagonal[m].modulus()) { - b.off_diagonal[m] = N::zero(); + off_diagonal[m] = N::zero(); break; } // FIXME: write a test that enters this case. - else if b.diagonal[m].abs() <= eps { - b.diagonal[m] = N::zero(); - Self::cancel_horizontal_off_diagonal_elt(b, u, v_t, m, n); + else if diagonal[m].modulus() <= eps { + diagonal[m] = N::zero(); + 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(b, u, v_t, m - 1); + Self::cancel_vertical_off_diagonal_elt(diagonal, off_diagonal, u, v_t, is_upper_diagonal, m - 1); } break; } @@ -403,21 +417,23 @@ where // Cancels the i-th off-diagonal element using givens rotations. fn cancel_horizontal_off_diagonal_elt( - b: &mut Bidiagonal, + diagonal: &mut VectorN>, + off_diagonal: &mut VectorN, U1>>, u: &mut Option>>, v_t: &mut Option, C>>, + is_upper_diagonal: bool, i: usize, end: usize, ) { - let mut v = Vector2::new(b.off_diagonal[i], b.diagonal[i + 1]); - b.off_diagonal[i] = N::zero(); + let mut v = Vector2::new(off_diagonal[i], diagonal[i + 1]); + off_diagonal[i] = N::zero(); for k in i..end { - if let Some((rot, norm)) = givens::cancel_x(&v) { - b.diagonal[k + 1] = norm; + if let Some((rot, norm)) = GivensRotation::cancel_x(&v) { + diagonal[k + 1] = norm; - if b.is_upper_diagonal() { + if is_upper_diagonal { if let Some(ref mut u) = *u { rot.inverse() .rotate_rows(&mut u.fixed_columns_with_step_mut::(i, k - i)); @@ -427,9 +443,9 @@ where } if k + 1 != end { - v.x = -rot.sin_angle() * b.off_diagonal[k + 1]; - v.y = b.diagonal[k + 2]; - b.off_diagonal[k + 1] *= rot.cos_angle(); + v.x = -rot.s() * off_diagonal[k + 1]; + v.y = diagonal[k + 2]; + off_diagonal[k + 1] = off_diagonal[k + 1].scale(rot.c()); } } else { break; @@ -439,20 +455,22 @@ where // Cancels the i-th off-diagonal element using givens rotations. fn cancel_vertical_off_diagonal_elt( - b: &mut Bidiagonal, + diagonal: &mut VectorN>, + off_diagonal: &mut VectorN, U1>>, u: &mut Option>>, v_t: &mut Option, C>>, + is_upper_diagonal: bool, i: usize, ) { - let mut v = Vector2::new(b.diagonal[i], b.off_diagonal[i]); - b.off_diagonal[i] = N::zero(); + let mut v = Vector2::new(diagonal[i], off_diagonal[i]); + off_diagonal[i] = N::zero(); for k in (0..i + 1).rev() { - if let Some((rot, norm)) = givens::cancel_y(&v) { - b.diagonal[k] = norm; + if let Some((rot, norm)) = GivensRotation::cancel_y(&v) { + diagonal[k] = norm; - if b.is_upper_diagonal() { + if is_upper_diagonal { if let Some(ref mut v_t) = *v_t { rot.rotate(&mut v_t.fixed_rows_with_step_mut::(k, i - k)); } @@ -462,9 +480,9 @@ where } if k > 0 { - v.x = b.diagonal[k - 1]; - v.y = rot.sin_angle() * b.off_diagonal[k - 1]; - b.off_diagonal[k - 1] *= rot.cos_angle(); + v.x = diagonal[k - 1]; + v.y = rot.s() * off_diagonal[k - 1]; + off_diagonal[k - 1] = off_diagonal[k - 1].scale(rot.c()); } } else { break; @@ -474,12 +492,12 @@ where /// Computes the rank of the decomposed matrix, i.e., the number of singular values greater /// than `eps`. - pub fn rank(&self, eps: N) -> usize { + pub fn rank(&self, eps: N::Real) -> usize { assert!( - eps >= N::zero(), + eps >= N::Real::zero(), "SVD rank: the epsilon must be non-negative." ); - self.singular_values.iter().filter(|e| **e > eps).count() + self.singular_values.iter().filter(|e| e.asum() > eps).count() } /// Rebuild the original matrix. @@ -507,18 +525,18 @@ where /// Any singular value smaller than `eps` is assumed to be zero. /// Returns `Err` if the right- and left- singular vectors have not /// been computed at construction-time. - pub fn pseudo_inverse(mut self, eps: N) -> Result, &'static str> + pub fn pseudo_inverse(mut self, eps: N::Real) -> Result, &'static str> where DefaultAllocator: Allocator, { - if eps < N::zero() { + if eps < N::Real::zero() { Err("SVD pseudo inverse: the epsilon must be non-negative.") } else { for i in 0..self.singular_values.len() { let val = self.singular_values[i]; - if val > eps { + if val.asum() > eps { self.singular_values[i] = N::one() / val; } else { self.singular_values[i] = N::zero(); @@ -537,14 +555,14 @@ where pub fn solve( &self, b: &Matrix, - eps: N, + eps: N::Real, ) -> Result, &'static str> where S2: Storage, DefaultAllocator: Allocator + Allocator, C2>, ShapeConstraint: SameNumberOfRows, { - if eps < N::zero() { + if eps < N::Real::zero() { Err("SVD solve: the epsilon must be non-negative.") } else { @@ -557,7 +575,7 @@ where for i in 0..self.singular_values.len() { let val = self.singular_values[i]; - if val > eps { + if val.asum() > eps { col[i] /= val; } else { col[i] = N::zero(); @@ -575,7 +593,7 @@ where } } -impl, C: Dim, S: Storage> Matrix +impl, C: Dim, S: Storage> Matrix where DimMinimum: DimSub, // for Bidiagonal. DefaultAllocator: Allocator @@ -605,7 +623,7 @@ where self, compute_u: bool, compute_v: bool, - eps: N, + eps: N::Real, max_niter: usize, ) -> Option> { @@ -620,7 +638,7 @@ where /// Computes the rank of this matrix. /// /// All singular values below `eps` are considered equal to 0. - pub fn rank(&self, eps: N) -> usize { + pub fn rank(&self, eps: N::Real) -> usize { let svd = SVD::new(self.clone_owned(), false, false); svd.rank(eps) } @@ -628,7 +646,7 @@ where /// Computes the pseudo-inverse of this matrix. /// /// All singular values below `eps` are considered equal to 0. - pub fn pseudo_inverse(self, eps: N) -> Result, &'static str> + pub fn pseudo_inverse(self, eps: N::Real) -> Result, &'static str> where DefaultAllocator: Allocator, { diff --git a/src/linalg/symmetric_eigen.rs b/src/linalg/symmetric_eigen.rs index 6084c1b4..b5437d83 100644 --- a/src/linalg/symmetric_eigen.rs +++ b/src/linalg/symmetric_eigen.rs @@ -1,7 +1,7 @@ #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Serialize}; -use num::Zero; +use num::{Zero, One}; use num_complex::Complex as NumComplex; use approx::AbsDiffEq; use std::ops::MulAssign; @@ -119,6 +119,8 @@ where DefaultAllocator: Allocator + Allocator q = Some(res.0); diag = res.1; off_diag = res.2; + + println!("Tridiagonalization q: {:.5?}", q); } else { let res = SymmetricTridiagonal::new(m).unpack_tridiagonal(); q = None; @@ -150,6 +152,7 @@ where DefaultAllocator: Allocator + Allocator let j = i + 1; if let Some((rot, norm)) = GivensRotation::cancel_y(&v) { + println!("Canceling: {:.5?} with norm: {:.5?}", rot, norm); if i > start { // Not the first iteration. off_diag[i - 1] = norm; @@ -160,19 +163,33 @@ where DefaultAllocator: Allocator + Allocator let mij = off_diag[i]; let cc = rot.c() * rot.c(); - let ss = rot.s() * rot.s().conjugate(); - let cs = rot.c() * rot.s(); + let ss = rot.s().modulus_squared(); // rot.s() * rot.s().conjugate() + let cs = rot.s().scale(rot.c()); - let b = cs * mij.conjugate() + cs.conjugate() * mij; + // b = cs * mij.conjugate() + cs.conjugate() * mij + let b = N::from_real((cs * mij.conjugate()).real() * ::convert(2.0)); - diag[i] = (cc * mii + ss * mjj) - b; - diag[j] = (ss * mii + cc * mjj) + b; - off_diag[i] = cs * (mii - mjj) + mij * cc - mij.conjugate() * rot.s() * rot.s(); + diag[i] = (mii.scale(cc) + mjj.scale(ss)) - b; + diag[j] = (mii.scale(ss) + mjj.scale(cc)) + b; + off_diag[i] = cs * (mii - mjj) + mij.scale(cc) - mij.conjugate() * rot.s() * rot.s(); + + let mut mat = Matrix2::new( + mii, mij.conjugate(), + mij, mjj); + println!("The mat before rotate: {:.5}", mat); + println!("The v before rotate: {:.5?}", v); + rot.rotate(&mut mat); + rot.inverse().rotate_rows(&mut mat); + let mut v2 = v.clone(); + rot.rotate(&mut v2); + println!("The v: {:.5?}", v2); + println!("The mat: {:.5}", mat); + println!("Its components: {:.5}, {:.5}, {:.5}", diag[i], diag[j], off_diag[i]); if i != n - 1 { v.x = off_diag[i]; v.y = -rot.s() * off_diag[i + 1]; - off_diag[i + 1] *= rot.c(); + off_diag[i + 1] = off_diag[i + 1].scale(rot.c()); } if let Some(ref mut q) = q { @@ -197,12 +214,12 @@ where DefaultAllocator: Allocator + Allocator diag[start + 0] = eigvals[0]; diag[start + 1] = eigvals[1]; - println!("Eigvals: {:?}", eigvals); - println!("m: {}", m); - println!("Curr q: {:?}", q); + println!("Eigvals: {:.5?}", eigvals); + println!("m: {:.5}", m); + println!("Curr q: {:.5?}", q); if let Some(ref mut q) = q { - if let Some(rot) = GivensRotation::try_new(basis.x, basis.y, eps) { + if let Some((rot, _)) = GivensRotation::try_new(basis.x, basis.y, eps) { rot.rotate_rows(&mut q.fixed_columns_mut::(start)); } } diff --git a/src/linalg/symmetric_tridiagonal.rs b/src/linalg/symmetric_tridiagonal.rs index 9b54c596..cd4f7c3d 100644 --- a/src/linalg/symmetric_tridiagonal.rs +++ b/src/linalg/symmetric_tridiagonal.rs @@ -83,6 +83,7 @@ where DefaultAllocator: Allocator + Allocator> m.ger_symm(-N::one(), &p, &axis.conjugate(), N::one()); m.ger_symm(-N::one(), &axis, &p.conjugate(), N::one()); m.ger_symm(dot * ::convert(2.0), &axis, &axis.conjugate(), N::one()); + println!("The m: {}", m); } } diff --git a/tests/linalg/bidiagonal.rs b/tests/linalg/bidiagonal.rs index 28b1e3a9..dbb0c4fb 100644 --- a/tests/linalg/bidiagonal.rs +++ b/tests/linalg/bidiagonal.rs @@ -41,6 +41,7 @@ quickcheck! { relative_eq!(m, &u * d * &v_t, epsilon = 1.0e-7) } + fn bidiagonal_static_square(m: Matrix4>) -> bool { let m = m.map(|e| e.0); let bidiagonal = m.bidiagonalize(); diff --git a/tests/linalg/eigen.rs b/tests/linalg/eigen.rs index 28a2b0d1..024384ce 100644 --- a/tests/linalg/eigen.rs +++ b/tests/linalg/eigen.rs @@ -9,10 +9,9 @@ mod quickcheck_tests { use std::cmp; quickcheck! { - /* fn symmetric_eigen(n: usize) -> bool { let n = cmp::max(1, cmp::min(n, 10)); - let m = DMatrix::>::new_random(n, n).map(|e| e.0); + let m = DMatrix::>::new_random(n, n).map(|e| e.0).hermitian_part(); let eig = m.clone().symmetric_eigen(); let recomp = eig.recompose(); @@ -23,7 +22,7 @@ mod quickcheck_tests { fn symmetric_eigen_singular(n: usize) -> bool { let n = cmp::max(1, cmp::min(n, 10)); - let mut m = DMatrix::>::new_random(n, n).map(|e| e.0); + let mut m = DMatrix::>::new_random(n, n).map(|e| e.0).hermitian_part(); m.row_mut(n / 2).fill(na::zero()); m.column_mut(n / 2).fill(na::zero()); let eig = m.clone().symmetric_eigen(); @@ -35,7 +34,7 @@ mod quickcheck_tests { } fn symmetric_eigen_static_square_4x4(m: Matrix4>) -> bool { - let m = m.map(|e| e.0); + let m = m.map(|e| e.0).hermitian_part(); let eig = m.symmetric_eigen(); let recomp = eig.recompose(); @@ -43,7 +42,6 @@ mod quickcheck_tests { relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-5) } - */ fn symmetric_eigen_static_square_3x3(m: Matrix3>) -> bool { let m = m.map(|e| e.0).hermitian_part(); @@ -57,7 +55,6 @@ mod quickcheck_tests { relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-5) } -/* fn symmetric_eigen_static_square_2x2(m: Matrix2>) -> bool { let m = m.map(|e| e.0).hermitian_part(); let eig = m.symmetric_eigen(); @@ -68,11 +65,9 @@ mod quickcheck_tests { relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-5) } - */ } } -/* // Test proposed on the issue #176 of rulinalg. #[test] fn symmetric_eigen_singular_24x24() { @@ -115,7 +110,7 @@ fn symmetric_eigen_singular_24x24() { recomp.lower_triangle(), epsilon = 1.0e-5 )); -}*/ +} // #[cfg(feature = "arbitrary")] // quickcheck! { diff --git a/tests/linalg/svd.rs b/tests/linalg/svd.rs index e84108ed..91f2002d 100644 --- a/tests/linalg/svd.rs +++ b/tests/linalg/svd.rs @@ -7,8 +7,11 @@ mod quickcheck_tests { DMatrix, DVector, Matrix2, Matrix2x5, Matrix3, Matrix3x5, Matrix4, Matrix5x2, Matrix5x3, }; use std::cmp; + use core::helper::{RandScalar, RandComplex}; + quickcheck! { + /* fn svd(m: DMatrix) -> bool { if m.len() > 0 { let svd = m.clone().svd(true, true); @@ -68,6 +71,7 @@ mod quickcheck_tests { relative_eq!(m, u * ds * v_t, epsilon = 1.0e-5) } + fn svd_static_square(m: Matrix4) -> bool { let svd = m.svd(true, true); let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); @@ -78,18 +82,27 @@ mod quickcheck_tests { u.is_orthogonal(1.0e-5) && v_t.is_orthogonal(1.0e-5) } + */ - fn svd_static_square_2x2(m: Matrix2) -> bool { + + fn svd_static_square_2x2(m: Matrix2>) -> bool { + let m = m.map(|e| e.0); let svd = m.svd(true, true); let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); let ds = Matrix2::from_diagonal(&s); - s.iter().all(|e| *e >= 0.0) && + println!("u, s, v_t: {}{}{}", u, s, v_t); + println!("m: {}", m); + println!("recomp: {}", u * ds * v_t); + println!("uu_t, vv_t: {}{}", u * u.conjugate_transpose(), v_t.conjugate_transpose() * v_t); + + s.iter().all(|e| e.re >= 0.0) && relative_eq!(m, u * ds * v_t, epsilon = 1.0e-5) && u.is_orthogonal(1.0e-5) && v_t.is_orthogonal(1.0e-5) } +/* fn svd_pseudo_inverse(m: DMatrix) -> bool { if m.len() > 0 { let svd = m.clone().svd(true, true); @@ -140,9 +153,11 @@ mod quickcheck_tests { true } + */ } } +/* // Test proposed on the issue #176 of rulinalg. #[test] fn svd_singular() { @@ -342,3 +357,5 @@ fn svd_err() { assert_eq!(Err("SVD recomposition: U and V^t have not been computed."), svd.clone().recompose()); assert_eq!(Err("SVD pseudo inverse: the epsilon must be non-negative."), svd.clone().pseudo_inverse(-1.0)); } + +*/ \ No newline at end of file diff --git a/tests/linalg/tridiagonal.rs b/tests/linalg/tridiagonal.rs index 5ecf32ff..fee0176a 100644 --- a/tests/linalg/tridiagonal.rs +++ b/tests/linalg/tridiagonal.rs @@ -15,6 +15,20 @@ quickcheck! { relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-7) } + fn symm_tridiagonal_singular(n: usize) -> bool { + let n = cmp::max(1, cmp::min(n, 4)); + let mut m = DMatrix::>::new_random(n, n).map(|e| e.0).hermitian_part(); + m.row_mut(n / 2).fill(na::zero()); + m.column_mut(n / 2).fill(na::zero()); + let tri = m.clone().symmetric_tridiagonalize(); + println!("Tri: {:?}", tri); + let recomp = tri.recompose(); + println!("Recomp: {:?}", recomp); + + + relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-7) + } + fn symm_tridiagonal_static_square(m: Matrix4>) -> bool { let m = m.map(|e| e.0).hermitian_part(); let tri = m.symmetric_tridiagonalize(); From 2f0d95bdbb3ceaa34428e0f6d9d9512f75f92afa Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Tue, 19 Mar 2019 12:00:10 +0100 Subject: [PATCH 05/28] Fix most tests. --- src/base/matrix.rs | 8 +++++ src/geometry/reflection.rs | 39 +++++++++++++++++++++ src/linalg/bidiagonal.rs | 22 +++++++++--- src/linalg/hessenberg.rs | 6 ++-- src/linalg/householder.rs | 14 ++++---- src/linalg/qr.rs | 13 +++---- src/linalg/svd.rs | 6 ++-- src/linalg/symmetric_tridiagonal.rs | 22 ++++++------ tests/linalg/bidiagonal.rs | 1 - tests/linalg/svd.rs | 53 +++++++++++++++-------------- 10 files changed, 124 insertions(+), 60 deletions(-) diff --git a/src/base/matrix.rs b/src/base/matrix.rs index e7cf0026..1e402d29 100644 --- a/src/base/matrix.rs +++ b/src/base/matrix.rs @@ -770,6 +770,14 @@ impl> Matrix { } } + // FIXME: rename `apply` to `apply_mut` and `apply_into` to `apply`? + /// Returns `self` with each of its components replaced by the result of a closure `f` applied on it. + #[inline] + pub fn apply_into N>(mut self, mut f: F) -> Self{ + self.apply(f); + self + } + /// Replaces each component of `self` by the result of a closure `f` applied on it. #[inline] pub fn apply N>(&mut self, mut f: F) { diff --git a/src/geometry/reflection.rs b/src/geometry/reflection.rs index 237054b6..b3c77bd9 100644 --- a/src/geometry/reflection.rs +++ b/src/geometry/reflection.rs @@ -61,6 +61,23 @@ 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, + { + for i in 0..rhs.ncols() { + // NOTE: we borrow the column twice here. First it is borrowed immutably for the + // dot product, and then mutably. Somehow, this allows significantly + // better optimizations of the dot product from the compiler. + let m_two = sign.scale(::convert(-2.0f64)); + let factor = (self.axis.cdot(&rhs.column(i)) - self.bias) * m_two; + rhs.column_mut(i).axpy(factor, &self.axis, sign); + } + } + /// Applies the reflection to the rows of `lhs`. pub fn reflect_rows( &self, @@ -81,4 +98,26 @@ impl> Reflection { let m_two: N = ::convert(-2.0f64); lhs.ger(m_two, &work, &self.axis.conjugate(), N::one()); } + + /// Applies the reflection to the rows of `lhs`. + pub fn reflect_rows_with_sign( + &self, + lhs: &mut Matrix, + work: &mut Vector, + sign: N, + ) where + S2: StorageMut, + S3: StorageMut, + ShapeConstraint: DimEq + AreMultipliable, + DefaultAllocator: Allocator + { + lhs.mul_to(&self.axis, work); + + if !self.bias.is_zero() { + work.add_scalar_mut(-self.bias); + } + + let m_two = sign.scale(::convert(-2.0f64)); + lhs.ger(m_two, &work, &self.axis.conjugate(), sign); + } } diff --git a/src/linalg/bidiagonal.rs b/src/linalg/bidiagonal.rs index e487758c..51087e96 100644 --- a/src/linalg/bidiagonal.rs +++ b/src/linalg/bidiagonal.rs @@ -200,11 +200,11 @@ where let d = nrows.min(ncols); let mut res = MatrixN::identity_generic(d, d); - res.set_diagonal(&self.diagonal); + res.set_diagonal(&self.diagonal.map(|e| N::from_real(e.modulus()))); let start = self.axis_shift(); res.slice_mut(start, (d.value() - 1, d.value() - 1)) - .set_diagonal(&self.off_diagonal); + .set_diagonal(&self.off_diagonal.map(|e| N::from_real(e.modulus()))); res } @@ -225,7 +225,14 @@ where let refl = Reflection::new(Unit::new_unchecked(axis), N::zero()); let mut res_rows = res.slice_range_mut(i + shift.., i..); - refl.reflect(&mut res_rows); + + let sign = if self.upper_diagonal { + self.diagonal[i].signum() + } else { + self.off_diagonal[i].signum() + }; + + refl.reflect_with_sign(&mut res_rows, sign); } res @@ -251,7 +258,14 @@ where let refl = Reflection::new(Unit::new_unchecked(axis_packed), N::zero()); let mut res_rows = res.slice_range_mut(i.., i + shift..); - refl.reflect_rows(&mut res_rows, &mut work.rows_range_mut(i..)); + + let sign = if self.upper_diagonal { + self.off_diagonal[i].signum() + } else { + self.diagonal[i].signum() + }; + + refl.reflect_rows_with_sign(&mut res_rows, &mut work.rows_range_mut(i..), sign); } res diff --git a/src/linalg/hessenberg.rs b/src/linalg/hessenberg.rs index 25ab445b..a73ee5b5 100644 --- a/src/linalg/hessenberg.rs +++ b/src/linalg/hessenberg.rs @@ -107,7 +107,7 @@ where DefaultAllocator: Allocator + Allocator + Allocator + Allocator + Allocator MatrixN { - householder::assemble_q(&self.hess) + householder::assemble_q(&self.hess, self.subdiag.as_slice()) } #[doc(hidden)] diff --git a/src/linalg/householder.rs b/src/linalg/householder.rs index dc97b9b3..d04da188 100644 --- a/src/linalg/householder.rs +++ b/src/linalg/householder.rs @@ -60,10 +60,11 @@ pub fn clear_column_unchecked( if not_zero { let refl = Reflection::new(Unit::new_unchecked(axis), N::zero()); + let sign = reflection_norm.signum(); if let Some(mut work) = bilateral { - refl.reflect_rows(&mut right, &mut work); + refl.reflect_rows_with_sign(&mut right, &mut work, sign); } - refl.reflect(&mut right.rows_range_mut(icol + shift..)); + refl.reflect_with_sign(&mut right.rows_range_mut(icol + shift..), sign.conjugate()); } } @@ -90,9 +91,10 @@ pub fn clear_row_unchecked( if not_zero { let refl = Reflection::new(Unit::new_unchecked(axis), N::zero()); - refl.reflect_rows( + refl.reflect_rows_with_sign( &mut bottom.columns_range_mut(irow + shift..), &mut work.rows_range_mut(irow + 1..), + reflection_norm.signum().conjugate(), ); top.columns_range_mut(irow + shift..) .tr_copy_from(&refl.axis()); @@ -101,11 +103,11 @@ pub fn clear_row_unchecked( } } -/// Computes the orthogonal transformation described by the elementary reflector axices stored on +/// Computes the orthogonal transformation described by the elementary reflector axii stored on /// the lower-diagonal element of the given matrix. /// matrices. #[doc(hidden)] -pub fn assemble_q(m: &MatrixN) -> MatrixN +pub fn assemble_q(m: &MatrixN, signs: &[N]) -> MatrixN where DefaultAllocator: Allocator { assert!(m.is_square()); let dim = m.data.shape().0; @@ -119,7 +121,7 @@ where DefaultAllocator: Allocator { let refl = Reflection::new(Unit::new_unchecked(axis), N::zero()); let mut res_rows = res.slice_range_mut(i + 1.., i..); - refl.reflect(&mut res_rows); + refl.reflect_with_sign(&mut res_rows, signs[i].signum()); } res diff --git a/src/linalg/qr.rs b/src/linalg/qr.rs index 023a5042..e48c057c 100644 --- a/src/linalg/qr.rs +++ b/src/linalg/qr.rs @@ -1,5 +1,6 @@ #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Serialize}; +use num::Zero; use alga::general::Complex; use allocator::{Allocator, Reallocator}; @@ -83,7 +84,7 @@ where DefaultAllocator: Allocator + Allocator + Allocator + Allocator + Allocator + Allocator + Allocator + Allocator + Allocator + Allocator let coeff; unsafe { - let diag = *self.diag.vget_unchecked(i); + let diag = self.diag.vget_unchecked(i).modulus(); if diag.is_zero() { return false; } - coeff = *b.vget_unchecked(i) / diag; + coeff = b.vget_unchecked(i).unscale(diag); *b.vget_unchecked_mut(i) = coeff; } diff --git a/src/linalg/svd.rs b/src/linalg/svd.rs index bcc93333..852878f7 100644 --- a/src/linalg/svd.rs +++ b/src/linalg/svd.rs @@ -543,7 +543,7 @@ where } } - self.recompose().map(|m| m.transpose()) + self.recompose().map(|m| m.conjugate_transpose()) } } @@ -568,7 +568,7 @@ where else { match (&self.u, &self.v_t) { (Some(u), Some(v_t)) => { - let mut ut_b = u.tr_mul(b); + let mut ut_b = u.conjugate().tr_mul(b); for j in 0..ut_b.ncols() { let mut col = ut_b.column_mut(j); @@ -583,7 +583,7 @@ where } } - Ok(v_t.tr_mul(&ut_b)) + Ok(v_t.conjugate().tr_mul(&ut_b)) } (None, None) => Err("SVD solve: U and V^t have not been computed."), (None, _) => Err("SVD solve: U has not been computed."), diff --git a/src/linalg/symmetric_tridiagonal.rs b/src/linalg/symmetric_tridiagonal.rs index cd4f7c3d..8fd36003 100644 --- a/src/linalg/symmetric_tridiagonal.rs +++ b/src/linalg/symmetric_tridiagonal.rs @@ -79,6 +79,7 @@ where DefaultAllocator: Allocator + Allocator> p.cgemv_symm(::convert(2.0), &m, &axis, N::zero()); let dot = axis.cdot(&p); + // p.axpy(-dot, &axis.conjugate(), N::one()); m.ger_symm(-N::one(), &p, &axis.conjugate(), N::one()); m.ger_symm(-N::one(), &axis, &p.conjugate(), N::one()); @@ -106,32 +107,30 @@ where DefaultAllocator: Allocator + Allocator> let diag = self.diagonal(); let q = self.q(); - (q, diag, self.off_diagonal) + (q, diag, self.off_diagonal.apply_into(|e| N::from_real(e.modulus()))) } /// Retrieve the diagonal, and off diagonal elements of this decomposition. - pub fn unpack_tridiagonal(self) -> (VectorN, VectorN>) + pub fn unpack_tridiagonal(mut self) -> (VectorN, VectorN>) where DefaultAllocator: Allocator { let diag = self.diagonal(); - (diag, self.off_diagonal) + (diag, self.off_diagonal.apply_into(|e| N::from_real(e.modulus()))) } /// The diagonal components of this decomposition. pub fn diagonal(&self) -> VectorN - where DefaultAllocator: Allocator { - self.tri.diagonal() - } + where DefaultAllocator: Allocator { self.tri.diagonal() } /// The off-diagonal components of this decomposition. - pub fn off_diagonal(&self) -> &VectorN> + pub fn off_diagonal(&self) -> VectorN> where DefaultAllocator: Allocator { - &self.off_diagonal + self.off_diagonal.map(|e| N::from_real(e.modulus())) } /// Computes the orthogonal matrix `Q` of this decomposition. pub fn q(&self) -> MatrixN { - householder::assemble_q(&self.tri) + householder::assemble_q(&self.tri, self.off_diagonal.as_slice()) } /// Recomputes the original symmetric matrix. @@ -141,8 +140,9 @@ where DefaultAllocator: Allocator + Allocator> self.tri.fill_upper_triangle(N::zero(), 2); for i in 0..self.off_diagonal.len() { - self.tri[(i + 1, i)] = self.off_diagonal[i]; - self.tri[(i, i + 1)] = self.off_diagonal[i].conjugate(); + let val = N::from_real(self.off_diagonal[i].modulus()); + self.tri[(i + 1, i)] = val; + self.tri[(i, i + 1)] = val; } &q * self.tri * q.conjugate_transpose() diff --git a/tests/linalg/bidiagonal.rs b/tests/linalg/bidiagonal.rs index dbb0c4fb..28b1e3a9 100644 --- a/tests/linalg/bidiagonal.rs +++ b/tests/linalg/bidiagonal.rs @@ -41,7 +41,6 @@ quickcheck! { relative_eq!(m, &u * d * &v_t, epsilon = 1.0e-7) } - fn bidiagonal_static_square(m: Matrix4>) -> bool { let m = m.map(|e| e.0); let bidiagonal = m.bidiagonalize(); diff --git a/tests/linalg/svd.rs b/tests/linalg/svd.rs index 91f2002d..860c7ce2 100644 --- a/tests/linalg/svd.rs +++ b/tests/linalg/svd.rs @@ -5,14 +5,15 @@ use na::{DMatrix, Matrix6}; mod quickcheck_tests { use na::{ DMatrix, DVector, Matrix2, Matrix2x5, Matrix3, Matrix3x5, Matrix4, Matrix5x2, Matrix5x3, + Complex }; use std::cmp; use core::helper::{RandScalar, RandComplex}; quickcheck! { - /* - fn svd(m: DMatrix) -> bool { + fn svd(m: DMatrix>) -> bool { + let m = m.map(|e| e.0); if m.len() > 0 { let svd = m.clone().svd(true, true); let recomp_m = svd.clone().recompose().unwrap(); @@ -21,7 +22,7 @@ mod quickcheck_tests { println!("{}{}", &m, &u * &ds * &v_t); - s.iter().all(|e| *e >= 0.0) && + s.iter().all(|e| e.real() >= 0.0) && relative_eq!(&u * ds * &v_t, recomp_m, epsilon = 1.0e-5) && relative_eq!(m, recomp_m, epsilon = 1.0e-5) } @@ -30,60 +31,62 @@ mod quickcheck_tests { } } - fn svd_static_5_3(m: Matrix5x3) -> bool { + fn svd_static_5_3(m: Matrix5x3>) -> bool { + let m = m.map(|e| e.0); let svd = m.svd(true, true); let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); let ds = Matrix3::from_diagonal(&s); - s.iter().all(|e| *e >= 0.0) && + s.iter().all(|e| e.real() >= 0.0) && relative_eq!(m, &u * ds * &v_t, epsilon = 1.0e-5) && u.is_orthogonal(1.0e-5) && v_t.is_orthogonal(1.0e-5) } - fn svd_static_5_2(m: Matrix5x2) -> bool { + fn svd_static_5_2(m: Matrix5x2>) -> bool { + let m = m.map(|e| e.0); let svd = m.svd(true, true); let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); let ds = Matrix2::from_diagonal(&s); - s.iter().all(|e| *e >= 0.0) && + s.iter().all(|e| e.real() >= 0.0) && relative_eq!(m, &u * ds * &v_t, epsilon = 1.0e-5) && u.is_orthogonal(1.0e-5) && v_t.is_orthogonal(1.0e-5) } - fn svd_static_3_5(m: Matrix3x5) -> bool { + fn svd_static_3_5(m: Matrix3x5>) -> bool { + let m = m.map(|e| e.0); let svd = m.svd(true, true); let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); let ds = Matrix3::from_diagonal(&s); - s.iter().all(|e| *e >= 0.0) && + s.iter().all(|e| e.real() >= 0.0) && relative_eq!(m, u * ds * v_t, epsilon = 1.0e-5) } - fn svd_static_2_5(m: Matrix2x5) -> bool { + fn svd_static_2_5(m: Matrix2x5>) -> bool { + let m = m.map(|e| e.0); let svd = m.svd(true, true); let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); let ds = Matrix2::from_diagonal(&s); - s.iter().all(|e| *e >= 0.0) && + s.iter().all(|e| e.real() >= 0.0) && relative_eq!(m, u * ds * v_t, epsilon = 1.0e-5) } - - fn svd_static_square(m: Matrix4) -> bool { + fn svd_static_square(m: Matrix4>) -> bool { + let m = m.map(|e| e.0); let svd = m.svd(true, true); let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); let ds = Matrix4::from_diagonal(&s); - s.iter().all(|e| *e >= 0.0) && + s.iter().all(|e| e.real() >= 0.0) && relative_eq!(m, u * ds * v_t, epsilon = 1.0e-5) && u.is_orthogonal(1.0e-5) && v_t.is_orthogonal(1.0e-5) } - */ - fn svd_static_square_2x2(m: Matrix2>) -> bool { let m = m.map(|e| e.0); @@ -102,8 +105,9 @@ mod quickcheck_tests { v_t.is_orthogonal(1.0e-5) } -/* - fn svd_pseudo_inverse(m: DMatrix) -> bool { + fn svd_pseudo_inverse(m: DMatrix>) -> bool { + let m = m.map(|e| e.0); + if m.len() > 0 { let svd = m.clone().svd(true, true); let pinv = svd.pseudo_inverse(1.0e-10).unwrap(); @@ -125,13 +129,13 @@ mod quickcheck_tests { fn svd_solve(n: usize, nb: usize) -> bool { let n = cmp::max(1, cmp::min(n, 10)); let nb = cmp::min(nb, 10); - let m = DMatrix::::new_random(n, n); + let m = DMatrix::>::new_random(n, n).map(|e| e.0); let svd = m.clone().svd(true, true); if svd.rank(1.0e-7) == n { - let b1 = DVector::new_random(n); - let b2 = DMatrix::new_random(n, nb); + let b1 = DVector::>::new_random(n).map(|e| e.0); + let b2 = DMatrix::>::new_random(n, nb).map(|e| e.0); let sol1 = svd.solve(&b1, 1.0e-7).unwrap(); let sol2 = svd.solve(&b2, 1.0e-7).unwrap(); @@ -153,11 +157,10 @@ mod quickcheck_tests { true } - */ } } -/* + // Test proposed on the issue #176 of rulinalg. #[test] fn svd_singular() { @@ -356,6 +359,4 @@ fn svd_err() { let svd = m.clone().svd(false, false); assert_eq!(Err("SVD recomposition: U and V^t have not been computed."), svd.clone().recompose()); assert_eq!(Err("SVD pseudo inverse: the epsilon must be non-negative."), svd.clone().pseudo_inverse(-1.0)); -} - -*/ \ No newline at end of file +} \ No newline at end of file From 3edef2f006387876ef11988b76dda57c0e20e9aa Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Tue, 19 Mar 2019 14:22:59 +0100 Subject: [PATCH 06/28] Decomposition results: return a real vector whenever applicable. This includes singular values, eigenvalues of hermitian matrices, tridiagonalization and bidiagonalization diagonal and off-diagonal elements. --- src/base/matrix.rs | 13 +- src/linalg/bidiagonal.rs | 10 +- src/linalg/givens.rs | 10 ++ src/linalg/svd.rs | 212 +++++++++++++++------------- src/linalg/symmetric_eigen.rs | 76 +++++----- src/linalg/symmetric_tridiagonal.rs | 26 ++-- tests/linalg/svd.rs | 28 ++-- 7 files changed, 198 insertions(+), 177 deletions(-) diff --git a/src/base/matrix.rs b/src/base/matrix.rs index 1e402d29..73fe3fa4 100644 --- a/src/base/matrix.rs +++ b/src/base/matrix.rs @@ -1026,10 +1026,19 @@ impl> Matrix { } impl> SquareMatrix { - /// Creates a square matrix with its diagonal set to `diag` and all other entries set to 0. + /// The diagonal of this matrix. #[inline] pub fn diagonal(&self) -> VectorN where DefaultAllocator: Allocator { + self.map_diagonal(|e| e) + } + + /// Apply the given function to this matrix's diagonal and returns it. + /// + /// This is a more efficient version of `self.diagonal().map(f)` since this + /// allocates only once. + pub fn map_diagonal(&self, mut f: impl FnMut(N) -> N2) -> VectorN + where DefaultAllocator: Allocator { assert!( self.is_square(), "Unable to get the diagonal of a non-square matrix." @@ -1040,7 +1049,7 @@ impl> SquareMatrix { for i in 0..dim.value() { unsafe { - *res.vget_unchecked_mut(i) = *self.get_unchecked((i, i)); + *res.vget_unchecked_mut(i) = f(*self.get_unchecked((i, i))); } } diff --git a/src/linalg/bidiagonal.rs b/src/linalg/bidiagonal.rs index 51087e96..7de0b887 100644 --- a/src/linalg/bidiagonal.rs +++ b/src/linalg/bidiagonal.rs @@ -272,13 +272,15 @@ where } /// The diagonal part of this decomposed matrix. - pub fn diagonal(&self) -> VectorN> { - self.diagonal.map(|e| N::from_real(e.modulus())) + pub fn diagonal(&self) -> VectorN> + where DefaultAllocator: Allocator> { + self.diagonal.map(|e| e.modulus()) } /// The off-diagonal part of this decomposed matrix. - pub fn off_diagonal(&self) -> VectorN, U1>> { - self.off_diagonal.map(|e| N::from_real(e.modulus())) + pub fn off_diagonal(&self) -> VectorN, U1>> + where DefaultAllocator: Allocator, U1>> { + self.off_diagonal.map(|e| e.modulus()) } #[doc(hidden)] diff --git a/src/linalg/givens.rs b/src/linalg/givens.rs index 72f4a427..5943e0c1 100644 --- a/src/linalg/givens.rs +++ b/src/linalg/givens.rs @@ -28,6 +28,16 @@ impl GivensRotation { } } + /// Initializes a Givens rotation from its components. + /// + /// The components are copies as-is. It is not checked whether they describe + /// an actually valid Givens rotation. + pub fn new_unchecked(c: N::Real, s: N) -> Self { + Self { + c, s + } + } + /// Initializes a Givens rotation from its non-normalized cosine an sine components. pub fn new(c: N, s: N) -> (Self, N) { Self::try_new(c, s, N::Real::zero()).unwrap() diff --git a/src/linalg/svd.rs b/src/linalg/svd.rs index 852878f7..8de75829 100644 --- a/src/linalg/svd.rs +++ b/src/linalg/svd.rs @@ -2,11 +2,11 @@ use serde::{Deserialize, Serialize}; use num_complex::Complex as NumComplex; -use num::Zero; +use num::{Zero, One}; use std::ops::MulAssign; use approx::AbsDiffEq; -use alga::general::Complex; +use alga::general::{Real, Complex}; use allocator::Allocator; use base::{DefaultAllocator, Matrix, Matrix2x3, MatrixMN, Vector2, VectorN}; use constraint::{SameNumberOfRows, ShapeConstraint}; @@ -23,51 +23,47 @@ use linalg::givens::GivensRotation; #[cfg_attr( feature = "serde-serialize", serde(bound( - serialize = "DefaultAllocator: Allocator + - Allocator> + + serialize = "DefaultAllocator: Allocator> + Allocator, C> + Allocator>, MatrixMN>: Serialize, MatrixMN, C>: Serialize, - VectorN>: Serialize" + VectorN>: Serialize" )) )] #[cfg_attr( feature = "serde-serialize", serde(bound( - deserialize = "DefaultAllocator: Allocator + - Allocator> + + deserialize = "DefaultAllocator: Allocator> + Allocator, C> + Allocator>, MatrixMN>: Deserialize<'de>, MatrixMN, C>: Deserialize<'de>, - VectorN>: Deserialize<'de>" + VectorN>: Deserialize<'de>" )) )] #[derive(Clone, Debug)] pub struct SVD, C: Dim> where DefaultAllocator: Allocator, C> + Allocator> - + Allocator> + + Allocator> { /// The left-singular vectors `U` of this SVD. pub u: Option>>, /// The right-singular vectors `V^t` of this SVD. pub v_t: Option, C>>, - // FIXME: this should a vector of N::Real - // because singular values are necessarily real. /// The singular values of this SVD. - pub singular_values: VectorN>, + pub singular_values: VectorN>, } impl, C: Dim> Copy for SVD where DefaultAllocator: Allocator, C> + Allocator> - + Allocator>, + + Allocator>, MatrixMN>: Copy, MatrixMN, C>: Copy, - VectorN>: Copy, + VectorN>: Copy, {} impl, C: Dim> SVD @@ -79,7 +75,9 @@ where + Allocator, U1>> + Allocator, C> + Allocator> - + Allocator>, + + Allocator> + + Allocator> + + Allocator, U1>>, { /// Computes the Singular Value Decomposition of `matrix` using implicit shift. pub fn new(matrix: MatrixMN, compute_u: bool, compute_v: bool) -> Self { @@ -155,7 +153,7 @@ where for k in start..n { let m12 = if k == n - 1 { - N::zero() + N::Real::zero() } else { off_diagonal[k + 1] }; @@ -163,15 +161,15 @@ where let mut subm = Matrix2x3::new( diagonal[k], off_diagonal[k], - N::zero(), - N::zero(), + N::Real::zero(), + N::Real::zero(), diagonal[k + 1], m12, ); 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 { // This is not the first iteration. @@ -182,7 +180,10 @@ where // FIXME: does the case `v.y == 0` ever happen? 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())); + subm[(0, 0)] = norm2; if let Some(ref mut v_t) = v_t { @@ -219,17 +220,19 @@ where } } else if subdim == 2 { // Solve the remaining 2x2 subproblem. - let (u2, s, v2) = Self::compute_2x2_uptrig_svd( + let (u2, s, v2) = compute_2x2_uptrig_svd( diagonal[start], off_diagonal[start], diagonal[start + 1], compute_u && b.is_upper_diagonal() || compute_v && !b.is_upper_diagonal(), compute_v && b.is_upper_diagonal() || compute_u && !b.is_upper_diagonal(), ); + let u2 = u2.map(|u2| GivensRotation::new_unchecked(u2.c(), N::from_real(u2.s()))); + let v2 = v2.map(|v2| GivensRotation::new_unchecked(v2.c(), N::from_real(v2.s()))); diagonal[start + 0] = s[0]; diagonal[start + 1] = s[1]; - off_diagonal[start] = N::zero(); + off_diagonal[start] = N::Real::zero(); if let Some(ref mut u) = u { let rot = if b.is_upper_diagonal() { @@ -263,17 +266,17 @@ where } } - diagonal.scale_mut(m_amax); + diagonal *= m_amax; // Ensure all singular value are non-negative. for i in 0..dim { let sval = diagonal[i]; - let (modulus, sign) = sval.to_exp(); - if modulus != N::Real::zero() { - diagonal[i] = N::from_real(modulus); + + if sval < N::Real::zero() { + diagonal[i] = -sval; if let Some(ref mut u) = u { - u.column_mut(i).mul_assign(sign); + u.column_mut(i).neg_mut(); } } } @@ -285,55 +288,6 @@ where }) } - // Explicit formulaes 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 - fn compute_2x2_uptrig_svd( - m11: N, - m12: N, - m22: N, - compute_u: bool, - compute_v: bool, - ) -> (Option>, Vector2, Option>) - { - let two: N::Real = ::convert(2.0f64); - let half: N::Real = ::convert(0.5f64); - - let denom = (m11 + m22).hypot(m12) + (m11 - m22).hypot(m12); - - // NOTE: v1 is the singular value that is the closest to m22. - // This prevents cancellation issues when constructing the vector `csv` below. If we chose - // otherwise, we would have v1 ~= m11 when m12 is small. This would cause catastrophic - // cancellation on `v1 * v1 - m11 * m11` below. - let mut v1 = (m11 * m22).scale(two / denom); - let mut v2 = N::from_real(half * denom); - - let mut u = None; - let mut v_t = None; - - if compute_u || compute_v { - let (csv, sgn_v) = GivensRotation::new(m11 * m12, v1 * v1 - m11 * m11); - v1 *= sgn_v; - v2 *= sgn_v; - - if compute_v { - v_t = Some(csv); - } - - if compute_u { - let cu = (m11.scale(csv.c()) + m12 * csv.s()) / v1; - let su = (m22 * csv.s()) / v1; - let (csu, sgn_u) = GivensRotation::new(cu, su); - - v1 *= sgn_u; - v2 *= sgn_u; - u = Some(csu); - } - } - - (u, Vector2::new(v1, v2), v_t) - } - /* fn display_bidiag(b: &Bidiagonal, begin: usize, end: usize) { for i in begin .. end { @@ -350,8 +304,8 @@ where */ fn delimit_subproblem( - diagonal: &mut VectorN>, - off_diagonal: &mut VectorN, U1>>, + diagonal: &mut VectorN>, + off_diagonal: &mut VectorN, U1>>, u: &mut Option>>, v_t: &mut Option, C>>, is_upper_diagonal: bool, @@ -367,16 +321,16 @@ where if off_diagonal[m].is_zero() || off_diagonal[m].modulus() <= eps * (diagonal[n].modulus() + diagonal[m].modulus()) { - off_diagonal[m] = N::zero(); + off_diagonal[m] = N::Real::zero(); } else if diagonal[m].modulus() <= eps { - diagonal[m] = N::zero(); + diagonal[m] = N::Real::zero(); 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); } } else if diagonal[n].modulus() <= eps { - diagonal[n] = N::zero(); + diagonal[n] = N::Real::zero(); Self::cancel_vertical_off_diagonal_elt(diagonal, off_diagonal, u, v_t, is_upper_diagonal, m); } else { break; @@ -395,12 +349,12 @@ where if off_diagonal[m].modulus() <= eps * (diagonal[new_start].modulus() + diagonal[m].modulus()) { - off_diagonal[m] = N::zero(); + off_diagonal[m] = N::Real::zero(); break; } // FIXME: write a test that enters this case. else if diagonal[m].modulus() <= eps { - diagonal[m] = N::zero(); + diagonal[m] = N::Real::zero(); Self::cancel_horizontal_off_diagonal_elt(diagonal, off_diagonal, u, v_t, is_upper_diagonal, m, n); if m != 0 { @@ -417,8 +371,8 @@ where // Cancels the i-th off-diagonal element using givens rotations. fn cancel_horizontal_off_diagonal_elt( - diagonal: &mut VectorN>, - off_diagonal: &mut VectorN, U1>>, + diagonal: &mut VectorN>, + off_diagonal: &mut VectorN, U1>>, u: &mut Option>>, v_t: &mut Option, C>>, is_upper_diagonal: bool, @@ -427,10 +381,11 @@ where ) { let mut v = Vector2::new(off_diagonal[i], diagonal[i + 1]); - off_diagonal[i] = N::zero(); + off_diagonal[i] = N::Real::zero(); for k in i..end { if let Some((rot, norm)) = GivensRotation::cancel_x(&v) { + let rot = GivensRotation::new_unchecked(rot.c(), N::from_real(rot.s())); diagonal[k + 1] = norm; if is_upper_diagonal { @@ -443,9 +398,9 @@ where } if k + 1 != end { - v.x = -rot.s() * off_diagonal[k + 1]; + v.x = -rot.s().real() * off_diagonal[k + 1]; v.y = diagonal[k + 2]; - off_diagonal[k + 1] = off_diagonal[k + 1].scale(rot.c()); + off_diagonal[k + 1] *= rot.c(); } } else { break; @@ -455,8 +410,8 @@ where // Cancels the i-th off-diagonal element using givens rotations. fn cancel_vertical_off_diagonal_elt( - diagonal: &mut VectorN>, - off_diagonal: &mut VectorN, U1>>, + diagonal: &mut VectorN>, + off_diagonal: &mut VectorN, U1>>, u: &mut Option>>, v_t: &mut Option, C>>, is_upper_diagonal: bool, @@ -464,10 +419,11 @@ where ) { let mut v = Vector2::new(diagonal[i], off_diagonal[i]); - off_diagonal[i] = N::zero(); + off_diagonal[i] = N::Real::zero(); for k in (0..i + 1).rev() { if let Some((rot, norm)) = GivensRotation::cancel_y(&v) { + let rot = GivensRotation::new_unchecked(rot.c(), N::from_real(rot.s())); diagonal[k] = norm; if is_upper_diagonal { @@ -481,8 +437,8 @@ where if k > 0 { v.x = diagonal[k - 1]; - v.y = rot.s() * off_diagonal[k - 1]; - off_diagonal[k - 1] = off_diagonal[k - 1].scale(rot.c()); + v.y = rot.s().real() * off_diagonal[k - 1]; + off_diagonal[k - 1] *= rot.c(); } } else { break; @@ -497,7 +453,7 @@ where eps >= N::Real::zero(), "SVD rank: the epsilon must be non-negative." ); - self.singular_values.iter().filter(|e| e.asum() > eps).count() + self.singular_values.iter().filter(|e| **e > eps).count() } /// Rebuild the original matrix. @@ -510,7 +466,7 @@ where (Some(mut u), Some(v_t)) => { for i in 0..self.singular_values.len() { let val = self.singular_values[i]; - u.column_mut(i).mul_assign(val); + u.column_mut(i).scale_mut(val); } Ok(u * v_t) } @@ -536,10 +492,10 @@ where for i in 0..self.singular_values.len() { let val = self.singular_values[i]; - if val.asum() > eps { - self.singular_values[i] = N::one() / val; + if val > eps { + self.singular_values[i] = N::Real::one() / val; } else { - self.singular_values[i] = N::zero(); + self.singular_values[i] = N::Real::zero(); } } @@ -575,8 +531,8 @@ where for i in 0..self.singular_values.len() { let val = self.singular_values[i]; - if val.asum() > eps { - col[i] /= val; + if val > eps { + col[i] = col[i].unscale(val); } else { col[i] = N::zero(); } @@ -602,7 +558,9 @@ where + Allocator, U1>> + Allocator, C> + Allocator> - + Allocator>, + + Allocator> + + Allocator> + + Allocator, U1>>, { /// Computes the Singular Value Decomposition using implicit shift. pub fn svd(self, compute_u: bool, compute_v: bool) -> SVD { @@ -631,7 +589,7 @@ where } /// Computes the singular values of this matrix. - pub fn singular_values(&self) -> VectorN> { + pub fn singular_values(&self) -> VectorN> { SVD::new(self.clone_owned(), false, false).singular_values } @@ -653,3 +611,53 @@ where 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 +fn compute_2x2_uptrig_svd( + m11: N, + m12: N, + m22: N, + compute_u: bool, + compute_v: bool, +) -> (Option>, Vector2, Option>) +{ + let two: N::Real = ::convert(2.0f64); + let half: N::Real = ::convert(0.5f64); + + let denom = (m11 + m22).hypot(m12) + (m11 - m22).hypot(m12); + + // NOTE: v1 is the singular value that is the closest to m22. + // This prevents cancellation issues when constructing the vector `csv` below. If we chose + // otherwise, we would have v1 ~= m11 when m12 is small. This would cause catastrophic + // cancellation on `v1 * v1 - m11 * m11` below. + let mut v1 = m11 * m22 * two / denom; + let mut v2 = half * denom; + + let mut u = None; + let mut v_t = None; + + if compute_u || compute_v { + let (csv, sgn_v) = GivensRotation::new(m11 * m12, v1 * v1 - m11 * m11); + v1 *= sgn_v; + v2 *= sgn_v; + + if compute_v { + v_t = Some(csv); + } + + if compute_u { + let cu = (m11.scale(csv.c()) + m12 * csv.s()) / v1; + let su = (m22 * csv.s()) / v1; + let (csu, sgn_u) = GivensRotation::new(cu, su); + + v1 *= sgn_u; + v2 *= sgn_u; + u = Some(csu); + } + } + + (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 b5437d83..a0f614fe 100644 --- a/src/linalg/symmetric_eigen.rs +++ b/src/linalg/symmetric_eigen.rs @@ -22,8 +22,8 @@ use linalg::SymmetricTridiagonal; feature = "serde-serialize", serde(bound( serialize = "DefaultAllocator: Allocator + - Allocator, - VectorN: Serialize, + Allocator, + VectorN: Serialize, MatrixN: Serialize" )) )] @@ -31,32 +31,31 @@ use linalg::SymmetricTridiagonal; feature = "serde-serialize", serde(bound( deserialize = "DefaultAllocator: Allocator + - Allocator, - VectorN: Deserialize<'de>, + Allocator, + VectorN: Deserialize<'de>, MatrixN: Deserialize<'de>" )) )] #[derive(Clone, Debug)] pub struct SymmetricEigen -where DefaultAllocator: Allocator + Allocator +where DefaultAllocator: Allocator + Allocator { /// The eigenvectors of the decomposed matrix. pub eigenvectors: MatrixN, - // FIXME: this should be a VectorN /// The unsorted eigenvalues of the decomposed matrix. - pub eigenvalues: VectorN, + pub eigenvalues: VectorN, } impl Copy for SymmetricEigen where - DefaultAllocator: Allocator + Allocator, + DefaultAllocator: Allocator + Allocator, MatrixN: Copy, - VectorN: Copy, + VectorN: Copy, {} impl SymmetricEigen -where DefaultAllocator: Allocator + Allocator +where DefaultAllocator: Allocator + Allocator { /// Computes the eigendecomposition of the given symmetric matrix. /// @@ -64,7 +63,8 @@ where DefaultAllocator: Allocator + Allocator pub fn new(m: MatrixN) -> Self where D: DimSub, - DefaultAllocator: Allocator>, + DefaultAllocator: Allocator> + // For tridiagonalization + Allocator>, { Self::try_new(m, N::Real::default_epsilon(), 0).unwrap() } @@ -83,7 +83,8 @@ where DefaultAllocator: Allocator + Allocator pub fn try_new(m: MatrixN, eps: N::Real, max_niter: usize) -> Option where D: DimSub, - DefaultAllocator: Allocator>, + DefaultAllocator: Allocator> + // For tridiagonalization + Allocator>, { Self::do_decompose(m, true, eps, max_niter).map(|(vals, vecs)| SymmetricEigen { eigenvectors: vecs.unwrap(), @@ -96,10 +97,11 @@ where DefaultAllocator: Allocator + Allocator eigenvectors: bool, eps: N::Real, max_niter: usize, - ) -> Option<(VectorN, Option>)> + ) -> Option<(VectorN, Option>)> where D: DimSub, - DefaultAllocator: Allocator>, + DefaultAllocator: Allocator> + // For tridiagonalization + Allocator>, { assert!( m.is_square(), @@ -158,41 +160,29 @@ where DefaultAllocator: Allocator + Allocator off_diag[i - 1] = norm; } + let mii = diag[i]; let mjj = diag[j]; let mij = off_diag[i]; let cc = rot.c() * rot.c(); - let ss = rot.s().modulus_squared(); // rot.s() * rot.s().conjugate() - let cs = rot.s().scale(rot.c()); + let ss = rot.s() * rot.s(); + let cs = rot.c() * rot.s(); - // b = cs * mij.conjugate() + cs.conjugate() * mij - let b = N::from_real((cs * mij.conjugate()).real() * ::convert(2.0)); + let b = cs * ::convert(2.0) * mij; - diag[i] = (mii.scale(cc) + mjj.scale(ss)) - b; - diag[j] = (mii.scale(ss) + mjj.scale(cc)) + b; - off_diag[i] = cs * (mii - mjj) + mij.scale(cc) - mij.conjugate() * rot.s() * rot.s(); - - let mut mat = Matrix2::new( - mii, mij.conjugate(), - mij, mjj); - println!("The mat before rotate: {:.5}", mat); - println!("The v before rotate: {:.5?}", v); - rot.rotate(&mut mat); - rot.inverse().rotate_rows(&mut mat); - let mut v2 = v.clone(); - rot.rotate(&mut v2); - println!("The v: {:.5?}", v2); - println!("The mat: {:.5}", mat); - println!("Its components: {:.5}, {:.5}, {:.5}", diag[i], diag[j], off_diag[i]); + diag[i] = (cc * mii + ss * mjj) - b; + diag[j] = (ss * mii + cc * mjj) + b; + off_diag[i] = cs * (mii - mjj) + mij * (cc - ss); if i != n - 1 { v.x = off_diag[i]; v.y = -rot.s() * off_diag[i + 1]; - off_diag[i + 1] = off_diag[i + 1].scale(rot.c()); + off_diag[i + 1] *= rot.c(); } if let Some(ref mut q) = q { + let rot = GivensRotation::new_unchecked(rot.c(), N::from_real(rot.s())); rot.inverse().rotate_rows(&mut q.fixed_columns_mut::(i)); } } else { @@ -220,6 +210,7 @@ where DefaultAllocator: Allocator + Allocator if let Some(ref mut q) = q { if let Some((rot, _)) = GivensRotation::try_new(basis.x, basis.y, eps) { + let rot = GivensRotation::new_unchecked(rot.c(), N::from_real(rot.s())); rot.rotate_rows(&mut q.fixed_columns_mut::(start)); } } @@ -245,14 +236,14 @@ where DefaultAllocator: Allocator + Allocator } fn delimit_subproblem( - diag: &VectorN, - off_diag: &mut VectorN>, + diag: &VectorN, + off_diag: &mut VectorN>, end: usize, eps: N::Real, ) -> (usize, usize) where D: DimSub, - DefaultAllocator: Allocator>, + DefaultAllocator: Allocator>, { let mut n = end; @@ -277,7 +268,7 @@ where DefaultAllocator: Allocator + Allocator if off_diag[m].is_zero() || off_diag[m].modulus() <= eps * (diag[new_start].modulus() + diag[m].modulus()) { - off_diag[m] = N::zero(); + off_diag[m] = N::Real::zero(); break; } @@ -294,7 +285,7 @@ where DefaultAllocator: Allocator + Allocator let mut u_t = self.eigenvectors.clone(); for i in 0..self.eigenvalues.len() { let val = self.eigenvalues[i]; - u_t.column_mut(i).mul_assign(val); + u_t.column_mut(i).scale_mut(val); } u_t.conjugate_transpose_mut(); &self.eigenvectors * u_t @@ -324,7 +315,8 @@ pub fn wilkinson_shift(tmm: N, tnn: N, tmn: N) -> N { * */ impl, S: Storage> SquareMatrix -where DefaultAllocator: Allocator + Allocator + Allocator> +where DefaultAllocator: Allocator + Allocator> + + Allocator + Allocator> { /// Computes the eigendecomposition of this symmetric matrix. /// @@ -351,7 +343,7 @@ where DefaultAllocator: Allocator + Allocator + Allocator VectorN { + pub fn symmetric_eigenvalues(&self) -> VectorN { SymmetricEigen::do_decompose(self.clone_owned(), false, N::Real::default_epsilon(), 0) .unwrap() .0 diff --git a/src/linalg/symmetric_tridiagonal.rs b/src/linalg/symmetric_tridiagonal.rs index 8fd36003..0b8f5675 100644 --- a/src/linalg/symmetric_tridiagonal.rs +++ b/src/linalg/symmetric_tridiagonal.rs @@ -102,30 +102,30 @@ 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 { + pub fn unpack(self) -> (MatrixN, VectorN, VectorN>) + where DefaultAllocator: Allocator + + Allocator> { let diag = self.diagonal(); let q = self.q(); - (q, diag, self.off_diagonal.apply_into(|e| N::from_real(e.modulus()))) + (q, diag, self.off_diagonal.map(N::modulus)) } /// Retrieve the diagonal, and off diagonal elements of this decomposition. - pub fn unpack_tridiagonal(mut self) -> (VectorN, VectorN>) - where DefaultAllocator: Allocator { - let diag = self.diagonal(); - - (diag, self.off_diagonal.apply_into(|e| N::from_real(e.modulus()))) + pub fn unpack_tridiagonal(mut 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.diagonal() } + pub fn diagonal(&self) -> VectorN + where DefaultAllocator: Allocator { self.tri.map_diagonal(|e| e.real()) } /// The off-diagonal components of this decomposition. - pub fn off_diagonal(&self) -> VectorN> - where DefaultAllocator: Allocator { - self.off_diagonal.map(|e| N::from_real(e.modulus())) + pub fn off_diagonal(&self) -> VectorN> + where DefaultAllocator: Allocator> { + self.off_diagonal.map(N::modulus) } /// Computes the orthogonal matrix `Q` of this decomposition. diff --git a/tests/linalg/svd.rs b/tests/linalg/svd.rs index 860c7ce2..8e98b3f7 100644 --- a/tests/linalg/svd.rs +++ b/tests/linalg/svd.rs @@ -18,11 +18,11 @@ mod quickcheck_tests { let svd = m.clone().svd(true, true); let recomp_m = svd.clone().recompose().unwrap(); let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); - let ds = DMatrix::from_diagonal(&s); + let ds = DMatrix::from_diagonal(&s.map(|e| Complex::from_real(e))); println!("{}{}", &m, &u * &ds * &v_t); - s.iter().all(|e| e.real() >= 0.0) && + s.iter().all(|e| *e >= 0.0) && relative_eq!(&u * ds * &v_t, recomp_m, epsilon = 1.0e-5) && relative_eq!(m, recomp_m, epsilon = 1.0e-5) } @@ -35,9 +35,9 @@ mod quickcheck_tests { let m = m.map(|e| e.0); let svd = m.svd(true, true); let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); - let ds = Matrix3::from_diagonal(&s); + let ds = Matrix3::from_diagonal(&s.map(|e| Complex::from_real(e))); - s.iter().all(|e| e.real() >= 0.0) && + s.iter().all(|e| *e >= 0.0) && relative_eq!(m, &u * ds * &v_t, epsilon = 1.0e-5) && u.is_orthogonal(1.0e-5) && v_t.is_orthogonal(1.0e-5) @@ -47,9 +47,9 @@ mod quickcheck_tests { let m = m.map(|e| e.0); let svd = m.svd(true, true); let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); - let ds = Matrix2::from_diagonal(&s); + let ds = Matrix2::from_diagonal(&s.map(|e| Complex::from_real(e))); - s.iter().all(|e| e.real() >= 0.0) && + s.iter().all(|e| *e >= 0.0) && relative_eq!(m, &u * ds * &v_t, epsilon = 1.0e-5) && u.is_orthogonal(1.0e-5) && v_t.is_orthogonal(1.0e-5) @@ -60,9 +60,9 @@ mod quickcheck_tests { let svd = m.svd(true, true); let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); - let ds = Matrix3::from_diagonal(&s); + let ds = Matrix3::from_diagonal(&s.map(|e| Complex::from_real(e))); - s.iter().all(|e| e.real() >= 0.0) && + s.iter().all(|e| *e >= 0.0) && relative_eq!(m, u * ds * v_t, epsilon = 1.0e-5) } @@ -70,9 +70,9 @@ mod quickcheck_tests { let m = m.map(|e| e.0); let svd = m.svd(true, true); let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); - let ds = Matrix2::from_diagonal(&s); + let ds = Matrix2::from_diagonal(&s.map(|e| Complex::from_real(e))); - s.iter().all(|e| e.real() >= 0.0) && + s.iter().all(|e| *e >= 0.0) && relative_eq!(m, u * ds * v_t, epsilon = 1.0e-5) } @@ -80,9 +80,9 @@ mod quickcheck_tests { let m = m.map(|e| e.0); let svd = m.svd(true, true); let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); - let ds = Matrix4::from_diagonal(&s); + let ds = Matrix4::from_diagonal(&s.map(|e| Complex::from_real(e))); - s.iter().all(|e| e.real() >= 0.0) && + s.iter().all(|e| *e >= 0.0) && relative_eq!(m, u * ds * v_t, epsilon = 1.0e-5) && u.is_orthogonal(1.0e-5) && v_t.is_orthogonal(1.0e-5) @@ -92,14 +92,14 @@ mod quickcheck_tests { let m = m.map(|e| e.0); let svd = m.svd(true, true); let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); - let ds = Matrix2::from_diagonal(&s); + let ds = Matrix2::from_diagonal(&s.map(|e| Complex::from_real(e))); println!("u, s, v_t: {}{}{}", u, s, v_t); println!("m: {}", m); println!("recomp: {}", u * ds * v_t); println!("uu_t, vv_t: {}{}", u * u.conjugate_transpose(), v_t.conjugate_transpose() * v_t); - s.iter().all(|e| e.re >= 0.0) && + s.iter().all(|e| *e >= 0.0) && relative_eq!(m, u * ds * v_t, epsilon = 1.0e-5) && u.is_orthogonal(1.0e-5) && v_t.is_orthogonal(1.0e-5) From b0a9eab0b996be6d7c6fdc47bf24f9ef2611f83a Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Tue, 19 Mar 2019 22:52:57 +0100 Subject: [PATCH 07/28] Final SVD fix. --- src/linalg/householder.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/linalg/householder.rs b/src/linalg/householder.rs index d04da188..1dc0f7b6 100644 --- a/src/linalg/householder.rs +++ b/src/linalg/householder.rs @@ -36,7 +36,8 @@ pub fn reflection_axis_mut>( column.unscale_mut(factor.sqrt()); (-signed_norm, true) } else { - (-signed_norm, false) + // FIXME: not sure why we don't have a - sign here. + (signed_norm, false) } } From cb367a645d74b6c8198d5b4d86e30fb3d5a4ba38 Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Tue, 19 Mar 2019 22:53:21 +0100 Subject: [PATCH 08/28] Fix mint tests. --- ci/test.sh | 2 +- src/base/conversion.rs | 4 ++-- tests/linalg/bidiagonal.rs | 24 ++++++++++++++++++++++++ tests/linalg/eigen.rs | 4 ++-- tests/linalg/svd.rs | 14 +++++++------- 5 files changed, 36 insertions(+), 12 deletions(-) diff --git a/ci/test.sh b/ci/test.sh index 88071149..a3a27fb2 100755 --- a/ci/test.sh +++ b/ci/test.sh @@ -6,7 +6,7 @@ if [ -z "$NO_STD" ]; then if [ -z "$LAPACK" ]; then cargo test --verbose; cargo test --verbose "arbitrary"; - cargo test --verbose "debug arbitrary mint serde-serialize abomonation-serialize"; + cargo test --verbose --all-features; cd nalgebra-glm; cargo test --verbose; else cd nalgebra-lapack; cargo test --verbose; diff --git a/src/base/conversion.rs b/src/base/conversion.rs index fcb6907d..750739a6 100644 --- a/src/base/conversion.rs +++ b/src/base/conversion.rs @@ -331,9 +331,9 @@ macro_rules! impl_from_into_mint_2D( #[cfg(feature = "mint")] impl_from_into_mint_2D!( (U2, U2) => ColumnMatrix2{x, y}[2]; - (U2, U3) => ColumnMatrix2x3{x, y}[2]; + (U2, U3) => ColumnMatrix2x3{x, y, z}[2]; (U3, U3) => ColumnMatrix3{x, y, z}[3]; - (U3, U4) => ColumnMatrix3x4{x, y, z}[3]; + (U3, U4) => ColumnMatrix3x4{x, y, z, w}[3]; (U4, U4) => ColumnMatrix4{x, y, z, w}[4]; ); diff --git a/tests/linalg/bidiagonal.rs b/tests/linalg/bidiagonal.rs index 28b1e3a9..d2f21a84 100644 --- a/tests/linalg/bidiagonal.rs +++ b/tests/linalg/bidiagonal.rs @@ -3,6 +3,7 @@ use na::{DMatrix, Matrix2, Matrix3x5, Matrix4, Matrix5x3}; use core::helper::{RandScalar, RandComplex}; + quickcheck! { fn bidiagonal(m: DMatrix>) -> bool { let m = m.map(|e| e.0); @@ -63,3 +64,26 @@ quickcheck! { relative_eq!(m, &u * d * &v_t, epsilon = 1.0e-7) } } + + +#[test] +fn bidiagonal_identity() { + let m = DMatrix::::identity(10, 10); + let bidiagonal = m.clone().bidiagonalize(); + let (u, d, v_t) = bidiagonal.unpack(); + println!("u, s, v_t: {}{}{}", u, d, v_t); + println!("recomp: {}", &u * &d * &v_t); + assert_eq!(m, &u * d * &v_t); + + let m = DMatrix::::identity(10, 15); + let bidiagonal = m.clone().bidiagonalize(); + let (u, d, v_t) = bidiagonal.unpack(); + println!("u, s, v_t: {}{}{}", u, d, v_t); + assert_eq!(m, &u * d * &v_t); + + let m = DMatrix::::identity(15, 10); + let bidiagonal = m.clone().bidiagonalize(); + let (u, d, v_t) = bidiagonal.unpack(); + println!("u, s, v_t: {}{}{}", u, d, v_t); + assert_eq!(m, &u * d * &v_t); +} \ No newline at end of file diff --git a/tests/linalg/eigen.rs b/tests/linalg/eigen.rs index 024384ce..a5dfcf6b 100644 --- a/tests/linalg/eigen.rs +++ b/tests/linalg/eigen.rs @@ -105,11 +105,11 @@ fn symmetric_eigen_singular_24x24() { let eig = m.clone().symmetric_eigen(); let recomp = eig.recompose(); - assert!(relative_eq!( + assert_relative_eq!( m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-5 - )); + ); } // #[cfg(feature = "arbitrary")] diff --git a/tests/linalg/svd.rs b/tests/linalg/svd.rs index 8e98b3f7..efced01a 100644 --- a/tests/linalg/svd.rs +++ b/tests/linalg/svd.rs @@ -199,7 +199,7 @@ fn svd_singular() { assert!(s.iter().all(|e| *e >= 0.0)); assert!(u.is_orthogonal(1.0e-5)); assert!(v_t.is_orthogonal(1.0e-5)); - assert!(relative_eq!(m, &u * ds * &v_t, epsilon = 1.0e-5)); + assert_relative_eq!(m, &u * ds * &v_t, epsilon = 1.0e-5); } // Same as the previous test but with one additional row. @@ -238,7 +238,7 @@ fn svd_singular_vertical() { let ds = DMatrix::from_diagonal(&s); assert!(s.iter().all(|e| *e >= 0.0)); - assert!(relative_eq!(m, &u * ds * &v_t, epsilon = 1.0e-5)); + assert_relative_eq!(m, &u * ds * &v_t, epsilon = 1.0e-5); } // Same as the previous test but with one additional column. @@ -275,7 +275,7 @@ fn svd_singular_horizontal() { let ds = DMatrix::from_diagonal(&s); assert!(s.iter().all(|e| *e >= 0.0)); - assert!(relative_eq!(m, &u * ds * &v_t, epsilon = 1.0e-5)); + assert_relative_eq!(m, &u * ds * &v_t, epsilon = 1.0e-5); } #[test] @@ -314,7 +314,7 @@ fn svd_with_delimited_subproblem() { m[(8,8)] = 16.0; m[(3,9)] = 17.0; m[(9,9)] = 18.0; let svd = m.clone().svd(true, true); - assert!(relative_eq!(m, svd.recompose().unwrap(), epsilon = 1.0e-7)); + assert_relative_eq!(m, svd.recompose().unwrap(), epsilon = 1.0e-7); // Rectangular versions. let mut m = DMatrix::::from_element(15, 10, 0.0); @@ -329,10 +329,10 @@ fn svd_with_delimited_subproblem() { m[(8,8)] = 16.0; m[(3,9)] = 17.0; m[(9,9)] = 18.0; let svd = m.clone().svd(true, true); - assert!(relative_eq!(m, svd.recompose().unwrap(), epsilon = 1.0e-7)); + assert_relative_eq!(m, svd.recompose().unwrap(), epsilon = 1.0e-7); let svd = m.transpose().svd(true, true); - assert!(relative_eq!(m.transpose(), svd.recompose().unwrap(), epsilon = 1.0e-7)); + assert_relative_eq!(m.transpose(), svd.recompose().unwrap(), epsilon = 1.0e-7); } #[test] @@ -350,7 +350,7 @@ fn svd_fail() { println!("v: {:.5}", svd.v_t.unwrap()); let recomp = svd.recompose().unwrap(); println!("{:.5}{:.5}", m, recomp); - assert!(relative_eq!(m, recomp, epsilon = 1.0e-5)); + assert_relative_eq!(m, recomp, epsilon = 1.0e-5); } #[test] From fd6573873893b448045c37e7bc6c9e44cc20c38f Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Tue, 19 Mar 2019 22:56:32 +0100 Subject: [PATCH 09/28] Fix icamax_full doc-test. --- src/base/blas.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/base/blas.rs b/src/base/blas.rs index 5eddf2b5..af20abae 100644 --- a/src/base/blas.rs +++ b/src/base/blas.rs @@ -197,9 +197,10 @@ impl> Matrix { /// # Examples: /// /// ``` + /// # use num_complex::Complex; /// # use nalgebra::Matrix2x3; /// let mat = Matrix2x3::new(Complex::new(11.0, 1.0), Complex::new(-12.0, 2.0), Complex::new(13.0, 3.0), - /// Complex::new(21.0, 43.0), Complex::new(22.0, 5.0), Complex::new(-23.0, 0.0); + /// Complex::new(21.0, 43.0), Complex::new(22.0, 5.0), Complex::new(-23.0, 0.0)); /// assert_eq!(mat.iamax_full(), (1, 0)); /// ``` #[inline] From 1001e8ee0f7500e6274e19d2908a4c3497172d8e Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sat, 23 Mar 2019 11:46:56 +0100 Subject: [PATCH 10/28] Cleanup warnings and rename Schur -> RealSchur --- benches/linalg/schur.rs | 10 +- nalgebra-lapack/src/lib.rs | 2 +- nalgebra-lapack/src/schur.rs | 14 +- nalgebra-lapack/tests/linalg/mod.rs | 2 +- nalgebra-lapack/tests/linalg/real_schur.rs | 6 +- src/base/blas.rs | 6 +- src/base/matrix.rs | 13 +- src/base/matrix_alga.rs | 2 +- src/base/norm.rs | 5 +- src/base/unit.rs | 2 - src/debug/random_orthogonal.rs | 17 +- src/debug/random_sdp.rs | 13 +- src/lib.rs | 2 +- src/linalg/cholesky.rs | 26 +- src/linalg/eigen.rs | 4 +- src/linalg/givens.rs | 4 +- src/linalg/schur.rs | 32 +-- src/linalg/svd.rs | 5 +- src/linalg/symmetric_eigen.rs | 13 +- src/linalg/symmetric_tridiagonal.rs | 5 +- tests/core/abomonation.rs | 2 +- tests/linalg/bidiagonal.rs | 123 +++++----- tests/linalg/cholesky.rs | 148 ++++++------ tests/linalg/eigen.rs | 111 +++++---- tests/linalg/full_piv_lu.rs | 192 ++++++++------- tests/linalg/hessenberg.rs | 59 +++-- tests/linalg/lu.rs | 1 + tests/linalg/mod.rs | 2 +- tests/linalg/qr.rs | 2 +- tests/linalg/{real_schur.rs => schur.rs} | 119 ++++----- tests/linalg/solve.rs | 110 +++++---- tests/linalg/svd.rs | 266 ++++++++++----------- tests/linalg/tridiagonal.rs | 87 ++++--- 33 files changed, 714 insertions(+), 691 deletions(-) rename tests/linalg/{real_schur.rs => schur.rs} (65%) diff --git a/benches/linalg/schur.rs b/benches/linalg/schur.rs index e0e588ac..ce0b741f 100644 --- a/benches/linalg/schur.rs +++ b/benches/linalg/schur.rs @@ -1,28 +1,28 @@ -use na::{Matrix4, RealSchur}; +use na::{Matrix4, Schur}; use test::{self, Bencher}; #[bench] fn schur_decompose_4x4(bh: &mut Bencher) { let m = Matrix4::::new_random(); - bh.iter(|| test::black_box(RealSchur::new(m.clone()))) + bh.iter(|| test::black_box(Schur::new(m.clone()))) } #[bench] fn schur_decompose_10x10(bh: &mut Bencher) { let m = ::reproductible_dmatrix(10, 10); - bh.iter(|| test::black_box(RealSchur::new(m.clone()))) + bh.iter(|| test::black_box(Schur::new(m.clone()))) } #[bench] fn schur_decompose_100x100(bh: &mut Bencher) { let m = ::reproductible_dmatrix(100, 100); - bh.iter(|| test::black_box(RealSchur::new(m.clone()))) + bh.iter(|| test::black_box(Schur::new(m.clone()))) } #[bench] fn schur_decompose_200x200(bh: &mut Bencher) { let m = ::reproductible_dmatrix(200, 200); - bh.iter(|| test::black_box(RealSchur::new(m.clone()))) + bh.iter(|| test::black_box(Schur::new(m.clone()))) } #[bench] diff --git a/nalgebra-lapack/src/lib.rs b/nalgebra-lapack/src/lib.rs index c343ba83..a1a7b7b7 100644 --- a/nalgebra-lapack/src/lib.rs +++ b/nalgebra-lapack/src/lib.rs @@ -98,7 +98,7 @@ pub use self::eigen::Eigen; pub use self::hessenberg::Hessenberg; pub use self::lu::{LUScalar, LU}; pub use self::qr::QR; -pub use self::schur::RealSchur; +pub use self::schur::Schur; pub use self::svd::SVD; pub use self::symmetric_eigen::SymmetricEigen; diff --git a/nalgebra-lapack/src/schur.rs b/nalgebra-lapack/src/schur.rs index a09b31ff..ab2423cb 100644 --- a/nalgebra-lapack/src/schur.rs +++ b/nalgebra-lapack/src/schur.rs @@ -33,7 +33,7 @@ use lapack; )) )] #[derive(Clone, Debug)] -pub struct RealSchur +pub struct Schur where DefaultAllocator: Allocator + Allocator { re: VectorN, @@ -42,21 +42,21 @@ where DefaultAllocator: Allocator + Allocator q: MatrixN, } -impl Copy for RealSchur +impl Copy for Schur where DefaultAllocator: Allocator + Allocator, MatrixN: Copy, VectorN: Copy, {} -impl RealSchur +impl Schur where DefaultAllocator: Allocator + Allocator { /// Computes the eigenvalues and real Schur form of the matrix `m`. /// /// Panics if the method did not converge. pub fn new(m: MatrixN) -> Self { - Self::try_new(m).expect("RealSchur decomposition: convergence failed.") + Self::try_new(m).expect("Schur decomposition: convergence failed.") } /// Computes the eigenvalues and real Schur form of the matrix `m`. @@ -118,7 +118,7 @@ where DefaultAllocator: Allocator + Allocator ); lapack_check!(info); - Some(RealSchur { + Some(Schur { re: wr, im: wi, t: m, @@ -162,7 +162,7 @@ where DefaultAllocator: Allocator + Allocator * */ /// Trait implemented by scalars for which Lapack implements the Real Schur decomposition. -pub trait RealSchurScalar: Scalar { +pub trait SchurScalar: Scalar { #[allow(missing_docs)] fn xgees( jobvs: u8, @@ -202,7 +202,7 @@ pub trait RealSchurScalar: Scalar { macro_rules! real_eigensystem_scalar_impl ( ($N: ty, $xgees: path) => ( - impl RealSchurScalar for $N { + impl SchurScalar for $N { #[inline] fn xgees(jobvs: u8, sort: u8, diff --git a/nalgebra-lapack/tests/linalg/mod.rs b/nalgebra-lapack/tests/linalg/mod.rs index ba228308..a6742217 100644 --- a/nalgebra-lapack/tests/linalg/mod.rs +++ b/nalgebra-lapack/tests/linalg/mod.rs @@ -2,6 +2,6 @@ mod cholesky; mod lu; mod qr; mod real_eigensystem; -mod real_schur; +mod schur; mod svd; mod symmetric_eigen; diff --git a/nalgebra-lapack/tests/linalg/real_schur.rs b/nalgebra-lapack/tests/linalg/real_schur.rs index 127107dd..ccdb0f0b 100644 --- a/nalgebra-lapack/tests/linalg/real_schur.rs +++ b/nalgebra-lapack/tests/linalg/real_schur.rs @@ -1,5 +1,5 @@ use na::{DMatrix, Matrix4}; -use nl::RealSchur; +use nl::Schur; use std::cmp; quickcheck! { @@ -7,13 +7,13 @@ quickcheck! { let n = cmp::max(1, cmp::min(n, 10)); let m = DMatrix::::new_random(n, n); - let (vecs, vals) = RealSchur::new(m.clone()).unpack(); + let (vecs, vals) = Schur::new(m.clone()).unpack(); relative_eq!(&vecs * vals * vecs.transpose(), m, epsilon = 1.0e-7) } fn schur_static(m: Matrix4) -> bool { - let (vecs, vals) = RealSchur::new(m.clone()).unpack(); + let (vecs, vals) = Schur::new(m.clone()).unpack(); relative_eq!(vecs * vals * vecs.transpose(), m, epsilon = 1.0e-7) } diff --git a/src/base/blas.rs b/src/base/blas.rs index af20abae..7dce36b6 100644 --- a/src/base/blas.rs +++ b/src/base/blas.rs @@ -21,6 +21,8 @@ impl> Vector { /// # Examples: /// /// ``` + /// # extern crate num_complex; + /// # extern crate nalgebra; /// # use num_complex::Complex; /// # use nalgebra::Vector3; /// let vec = Vector3::new(Complex::new(11.0, 3.0), Complex::new(-15.0, 0.0), Complex::new(13.0, 5.0)); @@ -197,11 +199,13 @@ impl> Matrix { /// # Examples: /// /// ``` + /// # extern crate num_complex; + /// # extern crate nalgebra; /// # use num_complex::Complex; /// # use nalgebra::Matrix2x3; /// let mat = Matrix2x3::new(Complex::new(11.0, 1.0), Complex::new(-12.0, 2.0), Complex::new(13.0, 3.0), /// Complex::new(21.0, 43.0), Complex::new(22.0, 5.0), Complex::new(-23.0, 0.0)); - /// assert_eq!(mat.iamax_full(), (1, 0)); + /// assert_eq!(mat.icamax_full(), (1, 0)); /// ``` #[inline] pub fn icamax_full(&self) -> (usize, usize) { diff --git a/src/base/matrix.rs b/src/base/matrix.rs index 73fe3fa4..8f6c071a 100644 --- a/src/base/matrix.rs +++ b/src/base/matrix.rs @@ -773,7 +773,7 @@ impl> Matrix { // FIXME: rename `apply` to `apply_mut` and `apply_into` to `apply`? /// Returns `self` with each of its components replaced by the result of a closure `f` applied on it. #[inline] - pub fn apply_into N>(mut self, mut f: F) -> Self{ + pub fn apply_into N>(mut self, f: F) -> Self{ self.apply(f); self } @@ -1093,14 +1093,11 @@ impl> SquareMatrix { pub fn hermitian_part(&self) -> MatrixMN where DefaultAllocator: Allocator { assert!(self.is_square(), "Cannot compute the hermitian part of a non-square matrix."); - let nrows = self.data.shape().0; - unsafe { - let mut tr = self.conjugate_transpose(); - tr += self; - tr *= ::convert::<_, N>(0.5); - tr - } + let mut tr = self.conjugate_transpose(); + tr += self; + tr *= ::convert::<_, N>(0.5); + tr } } diff --git a/src/base/matrix_alga.rs b/src/base/matrix_alga.rs index 35db628b..a2e1dd54 100644 --- a/src/base/matrix_alga.rs +++ b/src/base/matrix_alga.rs @@ -7,7 +7,7 @@ use alga::general::{ AbstractGroup, AbstractGroupAbelian, AbstractLoop, AbstractMagma, AbstractModule, AbstractMonoid, AbstractQuasigroup, AbstractSemigroup, Additive, ClosedAdd, ClosedMul, ClosedNeg, Field, Identity, TwoSidedInverse, JoinSemilattice, Lattice, MeetSemilattice, Module, - Multiplicative, Real, RingCommutative, Complex + Multiplicative, RingCommutative, Complex }; use alga::linear::{ FiniteDimInnerSpace, FiniteDimVectorSpace, InnerSpace, NormedSpace, VectorSpace, diff --git a/src/base/norm.rs b/src/base/norm.rs index 1b814d74..b3056067 100644 --- a/src/base/norm.rs +++ b/src/base/norm.rs @@ -1,8 +1,7 @@ -use num::{Signed, Zero}; -use std::cmp::PartialOrd; +use num::Zero; use allocator::Allocator; -use ::{Real, Complex, Scalar}; +use ::{Real, Complex}; use storage::{Storage, StorageMut}; use base::{DefaultAllocator, Matrix, Dim, MatrixMN}; use constraint::{SameNumberOfRows, SameNumberOfColumns, ShapeConstraint}; diff --git a/src/base/unit.rs b/src/base/unit.rs index b57ca3d3..87a428b5 100644 --- a/src/base/unit.rs +++ b/src/base/unit.rs @@ -13,8 +13,6 @@ use abomonation::Abomonation; use alga::general::{SubsetOf, Complex}; use alga::linear::NormedSpace; -use ::Real; - /// A wrapper that ensures the underlying algebraic entity has a unit norm. /// /// Use `.as_ref()` or `.into_inner()` to obtain the underlying value by-reference or by-move. diff --git a/src/debug/random_orthogonal.rs b/src/debug/random_orthogonal.rs index 6d393a24..94035109 100644 --- a/src/debug/random_orthogonal.rs +++ b/src/debug/random_orthogonal.rs @@ -3,22 +3,22 @@ use base::storage::Owned; #[cfg(feature = "arbitrary")] use quickcheck::{Arbitrary, Gen}; -use alga::general::Real; +use alga::general::Complex; +use base::Scalar; use base::allocator::Allocator; use base::dimension::{Dim, Dynamic, U2}; use base::{DefaultAllocator, MatrixN}; -use geometry::UnitComplex; -use num_complex::Complex; +use linalg::givens::GivensRotation; /// A random orthogonal matrix. #[derive(Clone, Debug)] -pub struct RandomOrthogonal +pub struct RandomOrthogonal where DefaultAllocator: Allocator { m: MatrixN, } -impl RandomOrthogonal +impl RandomOrthogonal where DefaultAllocator: Allocator { /// Retrieve the generated matrix. @@ -30,10 +30,9 @@ where DefaultAllocator: Allocator pub fn new N>(dim: D, mut rand: Rand) -> Self { let mut res = MatrixN::identity_generic(dim, dim); - // Create an orthogonal matrix by compositing planar 2D rotations. + // Create an orthogonal matrix by composing random Givens rotations rotations. for i in 0..dim.value() - 1 { - let c = Complex::new(rand(), rand()); - let rot: UnitComplex = UnitComplex::from_complex(c); + let rot = GivensRotation::new(rand(), rand()).0; rot.rotate(&mut res.fixed_rows_mut::(i)); } @@ -42,7 +41,7 @@ where DefaultAllocator: Allocator } #[cfg(feature = "arbitrary")] -impl Arbitrary for RandomOrthogonal +impl Arbitrary for RandomOrthogonal where DefaultAllocator: Allocator, Owned: Clone + Send, diff --git a/src/debug/random_sdp.rs b/src/debug/random_sdp.rs index 7835c775..772eccc9 100644 --- a/src/debug/random_sdp.rs +++ b/src/debug/random_sdp.rs @@ -3,7 +3,8 @@ use base::storage::Owned; #[cfg(feature = "arbitrary")] use quickcheck::{Arbitrary, Gen}; -use alga::general::Real; +use alga::general::Complex; +use base::Scalar; use base::allocator::Allocator; use base::dimension::{Dim, Dynamic}; use base::{DefaultAllocator, MatrixN}; @@ -12,13 +13,13 @@ use debug::RandomOrthogonal; /// A random, well-conditioned, symmetric definite-positive matrix. #[derive(Clone, Debug)] -pub struct RandomSDP +pub struct RandomSDP where DefaultAllocator: Allocator { m: MatrixN, } -impl RandomSDP +impl RandomSDP where DefaultAllocator: Allocator { /// Retrieve the generated matrix. @@ -30,11 +31,11 @@ where DefaultAllocator: Allocator /// random reals generators. pub fn new N>(dim: D, mut rand: Rand) -> Self { let mut m = RandomOrthogonal::new(dim, || rand()).unwrap(); - let mt = m.transpose(); + let mt = m.conjugate_transpose(); for i in 0..dim.value() { let mut col = m.column_mut(i); - let eigenval = N::one() + rand().abs(); + let eigenval = N::one() + N::from_real(rand().modulus()); col *= eigenval; } @@ -43,7 +44,7 @@ where DefaultAllocator: Allocator } #[cfg(feature = "arbitrary")] -impl Arbitrary for RandomSDP +impl Arbitrary for RandomSDP where DefaultAllocator: Allocator, Owned: Clone + Send, diff --git a/src/lib.rs b/src/lib.rs index 282661b0..a718cf91 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -66,7 +66,7 @@ an optimized set of tools for computer graphics and physics. Those features incl * General transformations that does not have to be invertible, stored as an homogeneous matrix: `Transform2`, `Transform3`. * 3D projections for computer graphics: `Perspective3`, `Orthographic3`. -* Matrix factorizations: `Cholesky`, `QR`, `LU`, `FullPivLU`, `SVD`, `RealSchur`, `Hessenberg`, `SymmetricEigen`. +* 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. diff --git a/src/linalg/cholesky.rs b/src/linalg/cholesky.rs index 96f533e4..682bd990 100644 --- a/src/linalg/cholesky.rs +++ b/src/linalg/cholesky.rs @@ -1,7 +1,6 @@ #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Serialize}; -use num::Zero; use alga::general::Complex; use allocator::Allocator; @@ -59,21 +58,24 @@ where DefaultAllocator: Allocator let mut col_j = col_j.rows_range_mut(j..); let col_k = col_k.rows_range(j..); - col_j.axpy(factor, &col_k, N::one()); + col_j.axpy(factor.conjugate(), &col_k, N::one()); } let diag = unsafe { *matrix.get_unchecked((j, j)) }; - if diag.real() > N::Real::zero() { - let denom = diag.sqrt(); - unsafe { - *matrix.get_unchecked_mut((j, j)) = denom; - } + if !diag.is_zero() { + if let Some(denom) = diag.try_sqrt() { + unsafe { + *matrix.get_unchecked_mut((j, j)) = denom; + } - let mut col = matrix.slice_range_mut(j + 1.., j); - col /= denom; - } else { - return None; + let mut col = matrix.slice_range_mut(j + 1.., j); + col /= denom; + + continue; + } } + + return None; } Some(Cholesky { chol: matrix }) @@ -119,7 +121,7 @@ where DefaultAllocator: Allocator ShapeConstraint: SameNumberOfRows, { let _ = self.chol.solve_lower_triangular_mut(b); - let _ = self.chol.tr_solve_lower_triangular_mut(b); + let _ = self.chol.conjugate().tr_solve_lower_triangular_mut(b); } /// Returns the solution of the system `self * x = b` where `self` is the decomposed matrix and diff --git a/src/linalg/eigen.rs b/src/linalg/eigen.rs index dd721f81..be1812ee 100644 --- a/src/linalg/eigen.rs +++ b/src/linalg/eigen.rs @@ -15,7 +15,7 @@ use constraint::{DimEq, ShapeConstraint}; use geometry::{Reflection, UnitComplex}; use linalg::householder; -use linalg::RealSchur; +use linalg::Schur; /// Eigendecomposition of a real matrix with real eigenvalues (or complex eigen values for complex matrices). #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] @@ -76,7 +76,7 @@ where ); let dim = m.nrows(); - let (mut eigenvectors, mut eigenvalues) = RealSchur::new(m, 0).unwrap().unpack(); + let (mut eigenvectors, mut eigenvalues) = Schur::new(m, 0).unwrap().unpack(); println!("Schur eigenvalues: {}", eigenvalues); diff --git a/src/linalg/givens.rs b/src/linalg/givens.rs index 5943e0c1..ecc9126b 100644 --- a/src/linalg/givens.rs +++ b/src/linalg/givens.rs @@ -1,15 +1,13 @@ //! Construction of givens rotations. -use alga::general::{Complex, Real}; +use alga::general::Complex; use num::{Zero, One}; -use num_complex::Complex as NumComplex; use base::dimension::{Dim, U2}; use base::constraint::{ShapeConstraint, DimEq}; use base::storage::{Storage, StorageMut}; use base::{Vector, Matrix}; -use geometry::UnitComplex; /// A Givens rotation. #[derive(Debug, Clone, Copy)] diff --git a/src/linalg/schur.rs b/src/linalg/schur.rs index b815131e..9c877d92 100644 --- a/src/linalg/schur.rs +++ b/src/linalg/schur.rs @@ -12,12 +12,14 @@ use base::storage::Storage; use base::{DefaultAllocator, MatrixN, SquareMatrix, Unit, Vector2, Vector3, VectorN}; use constraint::{DimEq, ShapeConstraint}; -use geometry::{Reflection, UnitComplex}; +use geometry::Reflection; use linalg::householder; use linalg::Hessenberg; use linalg::givens::GivensRotation; -/// Real Schur decomposition of a square matrix. +/// Schur decomposition of a square matrix. +/// +/// If this is a real matrix, this will be a Real Schur decomposition. #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[cfg_attr( feature = "serde-serialize", @@ -34,20 +36,20 @@ use linalg::givens::GivensRotation; )) )] #[derive(Clone, Debug)] -pub struct RealSchur +pub struct Schur where DefaultAllocator: Allocator { q: MatrixN, t: MatrixN, } -impl Copy for RealSchur +impl Copy for Schur where DefaultAllocator: Allocator, MatrixN: Copy, {} -impl RealSchur +impl Schur where D: DimSub, // For Hessenberg. ShapeConstraint: DimEq>, // For Hessenberg. @@ -75,7 +77,7 @@ where pub fn try_new(m: MatrixN, eps: N::Real, max_niter: usize) -> Option { let mut work = unsafe { VectorN::new_uninitialized_generic(m.data.shape().0, U1) }; - Self::do_decompose(m, &mut work, eps, max_niter, true).map(|(q, t)| RealSchur { + Self::do_decompose(m, &mut work, eps, max_niter, true).map(|(q, t)| Schur { q: q.unwrap(), t: t, }) @@ -474,8 +476,6 @@ fn compute_2x2_basis>( let x1 = eigval1 - m[(1, 1)]; let x2 = eigval2 - m[(1, 1)]; - println!("eigval1: {}, eigval2: {}, h10: {}", eigval1, eigval2, h10); - // NOTE: Choose the one that yields a larger x component. // This is necessary for numerical stability of the normalization of the complex // number. @@ -499,8 +499,8 @@ where + Allocator, { /// Computes the Schur decomposition of a square matrix. - pub fn real_schur(self) -> RealSchur { - RealSchur::new(self.into_owned()) + pub fn schur(self) -> Schur { + Schur::new(self.into_owned()) } /// Attempts to compute the Schur decomposition of a square matrix. @@ -514,8 +514,8 @@ where /// * `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_real_schur(self, eps: N::Real, max_niter: usize) -> Option> { - RealSchur::try_new(self.into_owned(), eps, max_niter) + pub fn try_schur(self, eps: N::Real, max_niter: usize) -> Option> { + Schur::try_new(self.into_owned(), eps, max_niter) } /// Computes the eigenvalues of this matrix. @@ -543,7 +543,7 @@ where } // FIXME: add balancing? - let schur = RealSchur::do_decompose( + let schur = Schur::do_decompose( self.clone_owned(), &mut work, N::Real::default_epsilon(), @@ -551,7 +551,7 @@ where false, ) .unwrap(); - if RealSchur::do_eigenvalues(&schur.1, &mut work) { + if Schur::do_eigenvalues(&schur.1, &mut work) { Some(work) } else { None @@ -566,7 +566,7 @@ where let dim = self.data.shape().0; let mut work = unsafe { VectorN::new_uninitialized_generic(dim, U1) }; - let schur = RealSchur::do_decompose( + let schur = Schur::do_decompose( self.clone_owned(), &mut work, N::default_epsilon(), @@ -575,7 +575,7 @@ where ) .unwrap(); let mut eig = unsafe { VectorN::new_uninitialized_generic(dim, U1) }; - RealSchur::do_complex_eigenvalues(&schur.1, &mut eig); + Schur::do_complex_eigenvalues(&schur.1, &mut eig); eig } } diff --git a/src/linalg/svd.rs b/src/linalg/svd.rs index 8de75829..a455badd 100644 --- a/src/linalg/svd.rs +++ b/src/linalg/svd.rs @@ -1,9 +1,7 @@ #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Serialize}; -use num_complex::Complex as NumComplex; use num::{Zero, One}; -use std::ops::MulAssign; use approx::AbsDiffEq; use alga::general::{Real, Complex}; @@ -13,7 +11,6 @@ use constraint::{SameNumberOfRows, ShapeConstraint}; use dimension::{Dim, DimDiff, DimMin, DimMinimum, DimSub, U1, U2}; use storage::Storage; -use linalg::givens; use linalg::symmetric_eigen; use linalg::Bidiagonal; use linalg::givens::GivensRotation; @@ -116,7 +113,7 @@ where matrix.unscale_mut(m_amax); } - let mut b = Bidiagonal::new(matrix); + let b = Bidiagonal::new(matrix); let mut u = if compute_u { Some(b.u()) } else { None }; let mut v_t = if compute_v { Some(b.v_t()) } else { None }; let mut diagonal = b.diagonal(); diff --git a/src/linalg/symmetric_eigen.rs b/src/linalg/symmetric_eigen.rs index a0f614fe..87b08dc2 100644 --- a/src/linalg/symmetric_eigen.rs +++ b/src/linalg/symmetric_eigen.rs @@ -1,10 +1,8 @@ #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Serialize}; -use num::{Zero, One}; -use num_complex::Complex as NumComplex; +use num::Zero; use approx::AbsDiffEq; -use std::ops::MulAssign; use alga::general::Complex; use allocator::Allocator; @@ -12,7 +10,6 @@ use base::{DefaultAllocator, Matrix2, MatrixN, SquareMatrix, Vector2, VectorN}; use dimension::{Dim, DimDiff, DimSub, U1, U2}; use storage::Storage; -use geometry::UnitComplex; use linalg::givens::GivensRotation; use linalg::SymmetricTridiagonal; @@ -121,8 +118,6 @@ where DefaultAllocator: Allocator + Allocator q = Some(res.0); diag = res.1; off_diag = res.2; - - println!("Tridiagonalization q: {:.5?}", q); } else { let res = SymmetricTridiagonal::new(m).unpack_tridiagonal(); q = None; @@ -154,7 +149,6 @@ where DefaultAllocator: Allocator + Allocator let j = i + 1; if let Some((rot, norm)) = GivensRotation::cancel_y(&v) { - println!("Canceling: {:.5?} with norm: {:.5?}", rot, norm); if i > start { // Not the first iteration. off_diag[i - 1] = norm; @@ -204,10 +198,6 @@ where DefaultAllocator: Allocator + Allocator diag[start + 0] = eigvals[0]; diag[start + 1] = eigvals[1]; - println!("Eigvals: {:.5?}", eigvals); - println!("m: {:.5}", m); - println!("Curr q: {:.5?}", q); - if let Some(ref mut q) = q { if let Some((rot, _)) = GivensRotation::try_new(basis.x, basis.y, eps) { let rot = GivensRotation::new_unchecked(rot.c(), N::from_real(rot.s())); @@ -372,7 +362,6 @@ mod test { let expected = expected_shift(m); let computed = super::wilkinson_shift(m.m11, m.m22, m.m12); - println!("{} {}", expected, computed); assert!(relative_eq!(expected, computed, epsilon = 1.0e-7)); } } diff --git a/src/linalg/symmetric_tridiagonal.rs b/src/linalg/symmetric_tridiagonal.rs index 0b8f5675..29451d31 100644 --- a/src/linalg/symmetric_tridiagonal.rs +++ b/src/linalg/symmetric_tridiagonal.rs @@ -53,8 +53,6 @@ where DefaultAllocator: Allocator + Allocator> pub fn new(mut m: MatrixN) -> Self { let dim = m.data.shape().0; - println!("Input m: {}", m.index((0.., 0..))); - assert!( m.is_square(), "Unable to compute the symmetric tridiagonal decomposition of a non-square matrix." @@ -84,7 +82,6 @@ where DefaultAllocator: Allocator + Allocator> m.ger_symm(-N::one(), &p, &axis.conjugate(), N::one()); m.ger_symm(-N::one(), &axis, &p.conjugate(), N::one()); m.ger_symm(dot * ::convert(2.0), &axis, &axis.conjugate(), N::one()); - println!("The m: {}", m); } } @@ -112,7 +109,7 @@ where DefaultAllocator: Allocator + Allocator> } /// Retrieve the diagonal, and off diagonal elements of this decomposition. - pub fn unpack_tridiagonal(mut self) -> (VectorN, VectorN>) + pub fn unpack_tridiagonal(self) -> (VectorN, VectorN>) where DefaultAllocator: Allocator + Allocator> { (self.diagonal(), self.off_diagonal.map(N::modulus)) diff --git a/tests/core/abomonation.rs b/tests/core/abomonation.rs index be3952cd..01760e14 100644 --- a/tests/core/abomonation.rs +++ b/tests/core/abomonation.rs @@ -40,7 +40,7 @@ fn assert_encode_and_decode(original_data: T // Encode let mut bytes = Vec::new(); unsafe { - encode(&original_data, &mut bytes); + let _ = encode(&original_data, &mut bytes); } // Drop the original, so that dangling pointers are revealed by the test diff --git a/tests/linalg/bidiagonal.rs b/tests/linalg/bidiagonal.rs index d2f21a84..b4c382f3 100644 --- a/tests/linalg/bidiagonal.rs +++ b/tests/linalg/bidiagonal.rs @@ -1,89 +1,78 @@ #![cfg(feature = "arbitrary")] -use na::{DMatrix, Matrix2, Matrix3x5, Matrix4, Matrix5x3}; -use core::helper::{RandScalar, RandComplex}; +macro_rules! gen_tests( + ($module: ident, $scalar: ty) => { + mod $module { + use na::{DMatrix, Matrix2, Matrix3x5, Matrix4, Matrix5x3}; + #[allow(unused_imports)] + use core::helper::{RandScalar, RandComplex}; + quickcheck! { + fn bidiagonal(m: DMatrix<$scalar>) -> bool { + let m = m.map(|e| e.0); + if m.len() == 0 { + return true; + } -quickcheck! { - fn bidiagonal(m: DMatrix>) -> bool { - let m = m.map(|e| e.0); - if m.len() == 0 { - return true; + let bidiagonal = m.clone().bidiagonalize(); + let (u, d, v_t) = bidiagonal.unpack(); + + relative_eq!(m, &u * d * &v_t, epsilon = 1.0e-7) + } + + fn bidiagonal_static_5_3(m: Matrix5x3<$scalar>) -> bool { + let m = m.map(|e| e.0); + let bidiagonal = m.bidiagonalize(); + let (u, d, v_t) = bidiagonal.unpack(); + + relative_eq!(m, &u * d * &v_t, epsilon = 1.0e-7) + } + + fn bidiagonal_static_3_5(m: Matrix3x5<$scalar>) -> bool { + let m = m.map(|e| e.0); + let bidiagonal = m.bidiagonalize(); + let (u, d, v_t) = bidiagonal.unpack(); + + relative_eq!(m, &u * d * &v_t, epsilon = 1.0e-7) + } + + fn bidiagonal_static_square(m: Matrix4<$scalar>) -> bool { + let m = m.map(|e| e.0); + let bidiagonal = m.bidiagonalize(); + let (u, d, v_t) = bidiagonal.unpack(); + + relative_eq!(m, &u * d * &v_t, epsilon = 1.0e-7) + } + + fn bidiagonal_static_square_2x2(m: Matrix2<$scalar>) -> bool { + let m = m.map(|e| e.0); + let bidiagonal = m.bidiagonalize(); + let (u, d, v_t) = bidiagonal.unpack(); + + relative_eq!(m, &u * d * &v_t, epsilon = 1.0e-7) + } + } } - - let bidiagonal = m.clone().bidiagonalize(); - let (u, d, v_t) = bidiagonal.unpack(); - - println!("{}{}{}", &u, &d, &v_t); - println!("{:.7}{:.7}", &u * &d * &v_t, m); - - relative_eq!(m, &u * d * &v_t, epsilon = 1.0e-7) } +); - fn bidiagonal_static_5_3(m: Matrix5x3>) -> bool { - let m = m.map(|e| e.0); - let bidiagonal = m.bidiagonalize(); - let (u, d, v_t) = bidiagonal.unpack(); - - println!("{}{}{}", &u, &d, &v_t); - println!("{:.7}{:.7}", &u * &d * &v_t, m); - - relative_eq!(m, &u * d * &v_t, epsilon = 1.0e-7) - } - - fn bidiagonal_static_3_5(m: Matrix3x5>) -> bool { - let m = m.map(|e| e.0); - let bidiagonal = m.bidiagonalize(); - let (u, d, v_t) = bidiagonal.unpack(); - - println!("{}{}{}", &u, &d, &v_t); - println!("{:.7}{:.7}", &u * &d * &v_t, m); - - relative_eq!(m, &u * d * &v_t, epsilon = 1.0e-7) - } - - fn bidiagonal_static_square(m: Matrix4>) -> bool { - let m = m.map(|e| e.0); - let bidiagonal = m.bidiagonalize(); - let (u, d, v_t) = bidiagonal.unpack(); - - println!("{}{}{}", &u, &d, &v_t); - println!("{:.7}{:.7}", &u * &d * &v_t, m); - - relative_eq!(m, &u * d * &v_t, epsilon = 1.0e-7) - } - - fn bidiagonal_static_square_2x2(m: Matrix2>) -> bool { - let m = m.map(|e| e.0); - let bidiagonal = m.bidiagonalize(); - let (u, d, v_t) = bidiagonal.unpack(); - - println!("{}{}{}", &u, &d, &v_t); - println!("{:.7}{:.7}", &u * &d * &v_t, m); - - relative_eq!(m, &u * d * &v_t, epsilon = 1.0e-7) - } -} - +gen_tests!(complex, RandComplex); +gen_tests!(f64, RandScalar); #[test] fn bidiagonal_identity() { - let m = DMatrix::::identity(10, 10); + let m = na::DMatrix::::identity(10, 10); let bidiagonal = m.clone().bidiagonalize(); let (u, d, v_t) = bidiagonal.unpack(); - println!("u, s, v_t: {}{}{}", u, d, v_t); - println!("recomp: {}", &u * &d * &v_t); assert_eq!(m, &u * d * &v_t); - let m = DMatrix::::identity(10, 15); + let m = na::DMatrix::::identity(10, 15); let bidiagonal = m.clone().bidiagonalize(); let (u, d, v_t) = bidiagonal.unpack(); - println!("u, s, v_t: {}{}{}", u, d, v_t); assert_eq!(m, &u * d * &v_t); - let m = DMatrix::::identity(15, 10); + let m = na::DMatrix::::identity(15, 10); let bidiagonal = m.clone().bidiagonalize(); let (u, d, v_t) = bidiagonal.unpack(); - println!("u, s, v_t: {}{}{}", u, d, v_t); assert_eq!(m, &u * d * &v_t); } \ No newline at end of file diff --git a/tests/linalg/cholesky.rs b/tests/linalg/cholesky.rs index 9fe086ff..5bc91dc2 100644 --- a/tests/linalg/cholesky.rs +++ b/tests/linalg/cholesky.rs @@ -1,81 +1,87 @@ #![cfg(all(feature = "arbitrary", feature = "debug"))] -use na::debug::RandomSDP; -use na::dimension::U4; -use na::{DMatrix, DVector, Matrix4x3, Vector4}; -use std::cmp; -quickcheck! { - fn cholesky(m: RandomSDP) -> bool { - let mut m = m.unwrap(); +macro_rules! gen_tests( + ($module: ident, $scalar: ty) => { + mod $module { + use na::debug::RandomSDP; + use na::dimension::{U4, Dynamic}; + use na::{DMatrix, DVector, Matrix4x3, Vector4}; + use rand::random; + #[allow(unused_imports)] + use core::helper::{RandScalar, RandComplex}; + use std::cmp; - // Put garbage on the upper triangle to make sure it is not read by the decomposition. - m.fill_upper_triangle(23.0, 1); + quickcheck! { + fn cholesky(n: usize) -> bool { + let m = RandomSDP::new(Dynamic::new(n.max(1).min(50)), || random::<$scalar>().0).unwrap(); + let l = m.clone().cholesky().unwrap().unpack(); + relative_eq!(m, &l * l.conjugate_transpose(), epsilon = 1.0e-7) + } - let l = m.clone().cholesky().unwrap().unpack(); - m.fill_upper_triangle_with_lower_triangle(); - relative_eq!(m, &l * l.transpose(), epsilon = 1.0e-7) - } + fn cholesky_static(_m: RandomSDP) -> bool { + let m = RandomSDP::new(U4, || random::<$scalar>().0).unwrap(); + let chol = m.cholesky().unwrap(); + let l = chol.unpack(); - fn cholesky_static(m: RandomSDP) -> bool { - let m = m.unwrap(); - let chol = m.cholesky().unwrap(); - let l = chol.unpack(); + if !relative_eq!(m, &l * l.conjugate_transpose(), epsilon = 1.0e-7) { + false + } + else { + true + } + } - if !relative_eq!(m, &l * l.transpose(), epsilon = 1.0e-7) { - false - } - else { - true + fn cholesky_solve(n: usize, nb: usize) -> bool { + let n = n.max(1).min(50); + let m = RandomSDP::new(Dynamic::new(n), || random::<$scalar>().0).unwrap(); + let nb = cmp::min(nb, 50); // To avoid slowing down the test too much. + + let chol = m.clone().cholesky().unwrap(); + let b1 = DVector::<$scalar>::new_random(n).map(|e| e.0); + let b2 = DMatrix::<$scalar>::new_random(n, nb).map(|e| e.0); + + let sol1 = chol.solve(&b1); + let sol2 = chol.solve(&b2); + + relative_eq!(&m * &sol1, b1, epsilon = 1.0e-7) && + relative_eq!(&m * &sol2, b2, epsilon = 1.0e-7) + } + + fn cholesky_solve_static(_n: usize) -> bool { + let m = RandomSDP::new(U4, || random::<$scalar>().0).unwrap(); + let chol = m.clone().cholesky().unwrap(); + let b1 = Vector4::<$scalar>::new_random().map(|e| e.0); + let b2 = Matrix4x3::<$scalar>::new_random().map(|e| e.0); + + let sol1 = chol.solve(&b1); + let sol2 = chol.solve(&b2); + + relative_eq!(m * sol1, b1, epsilon = 1.0e-7) && + relative_eq!(m * sol2, b2, epsilon = 1.0e-7) + } + + fn cholesky_inverse(n: usize) -> bool { + let m = RandomSDP::new(Dynamic::new(n.max(1).min(50)), || random::<$scalar>().0).unwrap(); + let m1 = m.clone().cholesky().unwrap().inverse(); + let id1 = &m * &m1; + let id2 = &m1 * &m; + + id1.is_identity(1.0e-7) && id2.is_identity(1.0e-7) + } + + fn cholesky_inverse_static(_n: usize) -> bool { + let m = RandomSDP::new(U4, || random::<$scalar>().0).unwrap(); + let m1 = m.clone().cholesky().unwrap().inverse(); + let id1 = &m * &m1; + let id2 = &m1 * &m; + + id1.is_identity(1.0e-7) && id2.is_identity(1.0e-7) + } + } } } +); - - fn cholesky_solve(m: RandomSDP, nb: usize) -> bool { - let m = m.unwrap(); - let n = m.nrows(); - let nb = cmp::min(nb, 50); // To avoid slowing down the test too much. - - let chol = m.clone().cholesky().unwrap(); - let b1 = DVector::new_random(n); - let b2 = DMatrix::new_random(n, nb); - - let sol1 = chol.solve(&b1); - let sol2 = chol.solve(&b2); - - relative_eq!(&m * &sol1, b1, epsilon = 1.0e-7) && - relative_eq!(&m * &sol2, b2, epsilon = 1.0e-7) - } - - fn cholesky_solve_static(m: RandomSDP) -> bool { - let m = m.unwrap(); - let chol = m.clone().cholesky().unwrap(); - let b1 = Vector4::new_random(); - let b2 = Matrix4x3::new_random(); - - let sol1 = chol.solve(&b1); - let sol2 = chol.solve(&b2); - - relative_eq!(m * sol1, b1, epsilon = 1.0e-7) && - relative_eq!(m * sol2, b2, epsilon = 1.0e-7) - } - - fn cholesky_inverse(m: RandomSDP) -> bool { - let m = m.unwrap(); - - let m1 = m.clone().cholesky().unwrap().inverse(); - let id1 = &m * &m1; - let id2 = &m1 * &m; - - id1.is_identity(1.0e-7) && id2.is_identity(1.0e-7) - } - - fn cholesky_inverse_static(m: RandomSDP) -> bool { - let m = m.unwrap(); - let m1 = m.clone().cholesky().unwrap().inverse(); - let id1 = &m * &m1; - let id2 = &m1 * &m; - - id1.is_identity(1.0e-7) && id2.is_identity(1.0e-7) - } -} +gen_tests!(complex, RandComplex); +gen_tests!(f64, RandScalar); diff --git a/tests/linalg/eigen.rs b/tests/linalg/eigen.rs index a5dfcf6b..9a1c3539 100644 --- a/tests/linalg/eigen.rs +++ b/tests/linalg/eigen.rs @@ -4,68 +4,65 @@ use na::DMatrix; #[cfg(feature = "arbitrary")] mod quickcheck_tests { - use na::{DMatrix, Matrix2, Matrix3, Matrix4}; - use core::helper::{RandScalar, RandComplex}; - use std::cmp; + macro_rules! gen_tests( + ($module: ident, $scalar: ty) => { + mod $module { + use na::{DMatrix, Matrix2, Matrix3, Matrix4}; + #[allow(unused_imports)] + use core::helper::{RandScalar, RandComplex}; + use std::cmp; - quickcheck! { - fn symmetric_eigen(n: usize) -> bool { - let n = cmp::max(1, cmp::min(n, 10)); - let m = DMatrix::>::new_random(n, n).map(|e| e.0).hermitian_part(); - let eig = m.clone().symmetric_eigen(); - let recomp = eig.recompose(); + quickcheck! { + fn symmetric_eigen(n: usize) -> bool { + let n = cmp::max(1, cmp::min(n, 10)); + let m = DMatrix::<$scalar>::new_random(n, n).map(|e| e.0).hermitian_part(); + let eig = m.clone().symmetric_eigen(); + let recomp = eig.recompose(); - println!("{}{}", m.lower_triangle(), recomp.lower_triangle()); + relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-5) + } - relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-5) + fn symmetric_eigen_singular(n: usize) -> bool { + let n = cmp::max(1, cmp::min(n, 10)); + let mut m = DMatrix::<$scalar>::new_random(n, n).map(|e| e.0).hermitian_part(); + m.row_mut(n / 2).fill(na::zero()); + m.column_mut(n / 2).fill(na::zero()); + let eig = m.clone().symmetric_eigen(); + let recomp = eig.recompose(); + + relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-5) + } + + fn symmetric_eigen_static_square_4x4(m: Matrix4<$scalar>) -> bool { + let m = m.map(|e| e.0).hermitian_part(); + let eig = m.symmetric_eigen(); + let recomp = eig.recompose(); + + relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-5) + } + + fn symmetric_eigen_static_square_3x3(m: Matrix3<$scalar>) -> bool { + let m = m.map(|e| e.0).hermitian_part(); + let eig = m.symmetric_eigen(); + let recomp = eig.recompose(); + + relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-5) + } + + fn symmetric_eigen_static_square_2x2(m: Matrix2<$scalar>) -> bool { + let m = m.map(|e| e.0).hermitian_part(); + let eig = m.symmetric_eigen(); + let recomp = eig.recompose(); + + relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-5) + } + } + } } + ); - fn symmetric_eigen_singular(n: usize) -> bool { - let n = cmp::max(1, cmp::min(n, 10)); - let mut m = DMatrix::>::new_random(n, n).map(|e| e.0).hermitian_part(); - m.row_mut(n / 2).fill(na::zero()); - m.column_mut(n / 2).fill(na::zero()); - let eig = m.clone().symmetric_eigen(); - let recomp = eig.recompose(); - - println!("{}{}", m.lower_triangle(), recomp.lower_triangle()); - - relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-5) - } - - fn symmetric_eigen_static_square_4x4(m: Matrix4>) -> bool { - let m = m.map(|e| e.0).hermitian_part(); - let eig = m.symmetric_eigen(); - let recomp = eig.recompose(); - - println!("{}{}", m.lower_triangle(), recomp.lower_triangle()); - - relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-5) - } - - fn symmetric_eigen_static_square_3x3(m: Matrix3>) -> bool { - let m = m.map(|e| e.0).hermitian_part(); - let eig = m.symmetric_eigen(); - let recomp = eig.recompose(); - - println!("Eigenvectors: {}", eig.eigenvectors); - println!("Eigenvalues: {}", eig.eigenvalues); - println!("{}{}", m.lower_triangle(), recomp.lower_triangle()); - - relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-5) - } - - fn symmetric_eigen_static_square_2x2(m: Matrix2>) -> bool { - let m = m.map(|e| e.0).hermitian_part(); - let eig = m.symmetric_eigen(); - let recomp = eig.recompose(); - - println!("Eigenvectors: {}", eig.eigenvectors); - println!("{}{}", m.lower_triangle(), recomp.lower_triangle()); - - relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-5) - } - } + gen_tests!(complex, RandComplex); + gen_tests!(f64, RandScalar); } // Test proposed on the issue #176 of rulinalg. diff --git a/tests/linalg/full_piv_lu.rs b/tests/linalg/full_piv_lu.rs index 5a0ad75b..c0e15cde 100644 --- a/tests/linalg/full_piv_lu.rs +++ b/tests/linalg/full_piv_lu.rs @@ -42,122 +42,140 @@ fn full_piv_lu_simple_with_pivot() { #[cfg(feature = "arbitrary")] mod quickcheck_tests { - use std::cmp; - use na::{DMatrix, Matrix4, Matrix4x3, Matrix5x3, Matrix3x5, DVector, Vector4}; + macro_rules! gen_tests( + ($module: ident, $scalar: ty) => { + mod $module { + use std::cmp; + use num::One; + use na::{DMatrix, Matrix4, Matrix4x3, Matrix5x3, Matrix3x5, DVector, Vector4}; + #[allow(unused_imports)] + use core::helper::{RandScalar, RandComplex}; - quickcheck! { - fn full_piv_lu(m: DMatrix) -> bool { - let mut m = m; - if m.len() == 0 { - m = DMatrix::new_random(1, 1); - } + quickcheck! { + fn full_piv_lu(m: DMatrix<$scalar>) -> bool { + let mut m = m.map(|e| e.0); + if m.len() == 0 { + m = DMatrix::<$scalar>::new_random(1, 1).map(|e| e.0); + } - let lu = m.clone().full_piv_lu(); - let (p, l, u, q) = lu.unpack(); - let mut lu = l * u; - p.inv_permute_rows(&mut lu); - q.inv_permute_columns(&mut lu); + let lu = m.clone().full_piv_lu(); + let (p, l, u, q) = lu.unpack(); + let mut lu = l * u; + p.inv_permute_rows(&mut lu); + q.inv_permute_columns(&mut lu); - relative_eq!(m, lu, epsilon = 1.0e-7) - } + relative_eq!(m, lu, epsilon = 1.0e-7) + } - fn full_piv_lu_static_3_5(m: Matrix3x5) -> bool { - let lu = m.full_piv_lu(); - let (p, l, u, q) = lu.unpack(); - let mut lu = l * u; - p.inv_permute_rows(&mut lu); - q.inv_permute_columns(&mut lu); + fn full_piv_lu_static_3_5(m: Matrix3x5<$scalar>) -> bool { + let m = m.map(|e| e.0); + let lu = m.full_piv_lu(); + let (p, l, u, q) = lu.unpack(); + let mut lu = l * u; + p.inv_permute_rows(&mut lu); + q.inv_permute_columns(&mut lu); - relative_eq!(m, lu, epsilon = 1.0e-7) - } + relative_eq!(m, lu, epsilon = 1.0e-7) + } - fn full_piv_lu_static_5_3(m: Matrix5x3) -> bool { - let lu = m.full_piv_lu(); - let (p, l, u, q) = lu.unpack(); - let mut lu = l * u; - p.inv_permute_rows(&mut lu); - q.inv_permute_columns(&mut lu); + fn full_piv_lu_static_5_3(m: Matrix5x3<$scalar>) -> bool { + let m = m.map(|e| e.0); + let lu = m.full_piv_lu(); + let (p, l, u, q) = lu.unpack(); + let mut lu = l * u; + p.inv_permute_rows(&mut lu); + q.inv_permute_columns(&mut lu); - relative_eq!(m, lu, epsilon = 1.0e-7) - } + relative_eq!(m, lu, epsilon = 1.0e-7) + } - fn full_piv_lu_static_square(m: Matrix4) -> bool { - let lu = m.full_piv_lu(); - let (p, l, u, q) = lu.unpack(); - let mut lu = l * u; - p.inv_permute_rows(&mut lu); - q.inv_permute_columns(&mut lu); + fn full_piv_lu_static_square(m: Matrix4<$scalar>) -> bool { + let m = m.map(|e| e.0); + let lu = m.full_piv_lu(); + let (p, l, u, q) = lu.unpack(); + let mut lu = l * u; + p.inv_permute_rows(&mut lu); + q.inv_permute_columns(&mut lu); - relative_eq!(m, lu, epsilon = 1.0e-7) - } + relative_eq!(m, lu, epsilon = 1.0e-7) + } - fn full_piv_lu_solve(n: usize, nb: usize) -> bool { - if n != 0 && nb != 0 { - let n = cmp::min(n, 50); // To avoid slowing down the test too much. - let nb = cmp::min(nb, 50); // To avoid slowing down the test too much. - let m = DMatrix::::new_random(n, n); + fn full_piv_lu_solve(n: usize, nb: usize) -> bool { + if n != 0 && nb != 0 { + let n = cmp::min(n, 50); // To avoid slowing down the test too much. + let nb = cmp::min(nb, 50); // To avoid slowing down the test too much. + let m = DMatrix::<$scalar>::new_random(n, n).map(|e| e.0); - let lu = m.clone().full_piv_lu(); - let b1 = DVector::new_random(n); - let b2 = DMatrix::new_random(n, nb); + let lu = m.clone().full_piv_lu(); + let b1 = DVector::<$scalar>::new_random(n).map(|e| e.0); + let b2 = DMatrix::<$scalar>::new_random(n, nb).map(|e| e.0); - let sol1 = lu.solve(&b1); - let sol2 = lu.solve(&b2); + let sol1 = lu.solve(&b1); + let sol2 = lu.solve(&b2); - return (sol1.is_none() || relative_eq!(&m * sol1.unwrap(), b1, epsilon = 1.0e-6)) && - (sol2.is_none() || relative_eq!(&m * sol2.unwrap(), b2, epsilon = 1.0e-6)) - } + return (sol1.is_none() || relative_eq!(&m * sol1.unwrap(), b1, epsilon = 1.0e-6)) && + (sol2.is_none() || relative_eq!(&m * sol2.unwrap(), b2, epsilon = 1.0e-6)) + } - return true; - } + return true; + } - fn full_piv_lu_solve_static(m: Matrix4) -> bool { - let lu = m.full_piv_lu(); - let b1 = Vector4::new_random(); - let b2 = Matrix4x3::new_random(); + fn full_piv_lu_solve_static(m: Matrix4<$scalar>) -> bool { + let m = m.map(|e| e.0); + let lu = m.full_piv_lu(); + let b1 = Vector4::<$scalar>::new_random().map(|e| e.0); + let b2 = Matrix4x3::<$scalar>::new_random().map(|e| e.0); - let sol1 = lu.solve(&b1); - let sol2 = lu.solve(&b2); + let sol1 = lu.solve(&b1); + let sol2 = lu.solve(&b2); - return (sol1.is_none() || relative_eq!(&m * sol1.unwrap(), b1, epsilon = 1.0e-6)) && - (sol2.is_none() || relative_eq!(&m * sol2.unwrap(), b2, epsilon = 1.0e-6)) - } + return (sol1.is_none() || relative_eq!(&m * sol1.unwrap(), b1, epsilon = 1.0e-6)) && + (sol2.is_none() || relative_eq!(&m * sol2.unwrap(), b2, epsilon = 1.0e-6)) + } - fn full_piv_lu_inverse(n: usize) -> bool { - let n = cmp::max(1, cmp::min(n, 15)); // To avoid slowing down the test too much. - let m = DMatrix::::new_random(n, n); + fn full_piv_lu_inverse(n: usize) -> bool { + let n = cmp::max(1, cmp::min(n, 15)); // To avoid slowing down the test too much. + let m = DMatrix::<$scalar>::new_random(n, n).map(|e| e.0); - let mut l = m.lower_triangle(); - let mut u = m.upper_triangle(); + let mut l = m.lower_triangle(); + let mut u = m.upper_triangle(); - // Ensure the matrix is well conditioned for inversion. - l.fill_diagonal(1.0); - u.fill_diagonal(1.0); - let m = l * u; + // Ensure the matrix is well conditioned for inversion. + l.fill_diagonal(One::one()); + u.fill_diagonal(One::one()); + let m = l * u; - let m1 = m.clone().full_piv_lu().try_inverse().unwrap(); - let id1 = &m * &m1; - let id2 = &m1 * &m; + let m1 = m.clone().full_piv_lu().try_inverse().unwrap(); + let id1 = &m * &m1; + let id2 = &m1 * &m; - return id1.is_identity(1.0e-5) && id2.is_identity(1.0e-5); - } + return id1.is_identity(1.0e-5) && id2.is_identity(1.0e-5); + } - fn full_piv_lu_inverse_static(m: Matrix4) -> bool { - let lu = m.full_piv_lu(); + fn full_piv_lu_inverse_static(m: Matrix4<$scalar>) -> bool { + let m = m.map(|e| e.0); + let lu = m.full_piv_lu(); - if let Some(m1) = lu.try_inverse() { - let id1 = &m * &m1; - let id2 = &m1 * &m; + if let Some(m1) = lu.try_inverse() { + let id1 = &m * &m1; + let id2 = &m1 * &m; - id1.is_identity(1.0e-5) && id2.is_identity(1.0e-5) - } - else { - true + id1.is_identity(1.0e-5) && id2.is_identity(1.0e-5) + } + else { + true + } + } + } } } - } + ); + + gen_tests!(complex, RandComplex); + gen_tests!(f64, RandScalar); } + /* #[test] fn swap_rows() { diff --git a/tests/linalg/hessenberg.rs b/tests/linalg/hessenberg.rs index 72c2baab..dfabd29d 100644 --- a/tests/linalg/hessenberg.rs +++ b/tests/linalg/hessenberg.rs @@ -1,8 +1,6 @@ #![cfg(feature = "arbitrary")] -use na::{DMatrix, Matrix2, Matrix4}; -use core::helper::{RandScalar, RandComplex}; -use std::cmp; +use na::Matrix2; #[test] @@ -13,27 +11,42 @@ fn hessenberg_simple() { assert!(relative_eq!(m, p * h * p.transpose(), epsilon = 1.0e-7)) } -quickcheck! { - fn hessenberg(n: usize) -> bool { - let n = cmp::max(1, cmp::min(n, 50)); - let m = DMatrix::>::new_random(n, n).map(|e| e.0); - let hess = m.clone().hessenberg(); - let (p, h) = hess.unpack(); - relative_eq!(m, &p * h * p.conjugate_transpose(), epsilon = 1.0e-7) - } +macro_rules! gen_tests( + ($module: ident, $scalar: ty) => { + mod $module { + use na::{DMatrix, Matrix2, Matrix4}; + use std::cmp; + #[allow(unused_imports)] + use core::helper::{RandScalar, RandComplex}; - fn hessenberg_static_mat2(m: Matrix2>) -> bool { - let m = m.map(|e| e.0); - let hess = m.hessenberg(); - let (p, h) = hess.unpack(); - relative_eq!(m, p * h * p.conjugate_transpose(), epsilon = 1.0e-7) - } + quickcheck! { + fn hessenberg(n: usize) -> bool { + let n = cmp::max(1, cmp::min(n, 50)); + let m = DMatrix::<$scalar>::new_random(n, n).map(|e| e.0); - fn hessenberg_static(m: Matrix4>) -> bool { - let m = m.map(|e| e.0); - let hess = m.hessenberg(); - let (p, h) = hess.unpack(); - relative_eq!(m, p * h * p.conjugate_transpose(), epsilon = 1.0e-7) + let hess = m.clone().hessenberg(); + let (p, h) = hess.unpack(); + relative_eq!(m, &p * h * p.conjugate_transpose(), epsilon = 1.0e-7) + } + + fn hessenberg_static_mat2(m: Matrix2<$scalar>) -> bool { + let m = m.map(|e| e.0); + let hess = m.hessenberg(); + let (p, h) = hess.unpack(); + relative_eq!(m, p * h * p.conjugate_transpose(), epsilon = 1.0e-7) + } + + fn hessenberg_static(m: Matrix4<$scalar>) -> bool { + let m = m.map(|e| e.0); + let hess = m.hessenberg(); + let (p, h) = hess.unpack(); + relative_eq!(m, p * h * p.conjugate_transpose(), epsilon = 1.0e-7) + } + } + } } -} +); + +gen_tests!(complex, RandComplex); +gen_tests!(f64, RandScalar); \ No newline at end of file diff --git a/tests/linalg/lu.rs b/tests/linalg/lu.rs index cb82731e..02f62c10 100644 --- a/tests/linalg/lu.rs +++ b/tests/linalg/lu.rs @@ -40,6 +40,7 @@ fn lu_simple_with_pivot() { #[cfg(feature = "arbitrary")] mod quickcheck_tests { + #[allow(unused_imports)] use core::helper::{RandScalar, RandComplex}; macro_rules! gen_tests( diff --git a/tests/linalg/mod.rs b/tests/linalg/mod.rs index 74a5e03c..f515b4d6 100644 --- a/tests/linalg/mod.rs +++ b/tests/linalg/mod.rs @@ -7,7 +7,7 @@ mod hessenberg; mod inverse; mod lu; mod qr; -mod real_schur; +mod schur; mod solve; mod svd; mod tridiagonal; diff --git a/tests/linalg/qr.rs b/tests/linalg/qr.rs index 48b0a8f7..76eb00d9 100644 --- a/tests/linalg/qr.rs +++ b/tests/linalg/qr.rs @@ -1,12 +1,12 @@ #![cfg(feature = "arbitrary")] -use core::helper::{RandScalar, RandComplex}; macro_rules! gen_tests( ($module: ident, $scalar: ty) => { mod $module { use na::{DMatrix, DVector, Matrix3x5, Matrix4, Matrix4x3, Matrix5x3, Vector4}; use std::cmp; + #[allow(unused_imports)] use core::helper::{RandScalar, RandComplex}; quickcheck! { diff --git a/tests/linalg/real_schur.rs b/tests/linalg/schur.rs similarity index 65% rename from tests/linalg/real_schur.rs rename to tests/linalg/schur.rs index 54ad9ce4..16767c94 100644 --- a/tests/linalg/real_schur.rs +++ b/tests/linalg/schur.rs @@ -8,7 +8,7 @@ fn schur_simpl_mat3() { -2.0, 1.0, 2.0, 4.0, 2.0, 5.0); - let schur = m.real_schur(); + let schur = m.schur(); let (vecs, vals) = schur.unpack(); assert!(relative_eq!(vecs * vals * vecs.transpose(), m, epsilon = 1.0e-7)); @@ -16,59 +16,70 @@ fn schur_simpl_mat3() { #[cfg(feature = "arbitrary")] mod quickcheck_tests { - use std::cmp; - use na::{DMatrix, Matrix2, Matrix3, Matrix4}; - use core::helper::{RandScalar, RandComplex}; + macro_rules! gen_tests( + ($module: ident, $scalar: ty) => { + mod $module { + use std::cmp; + use na::{DMatrix, Matrix2, Matrix3, Matrix4}; + #[allow(unused_imports)] + use core::helper::{RandScalar, RandComplex}; - quickcheck! { - fn schur(n: usize) -> bool { - let n = cmp::max(1, cmp::min(n, 10)); - let m = DMatrix::>::new_random(n, n).map(|e| e.0); + quickcheck! { + fn schur(n: usize) -> bool { + let n = cmp::max(1, cmp::min(n, 10)); + let m = DMatrix::<$scalar>::new_random(n, n).map(|e| e.0); - let (vecs, vals) = m.clone().real_schur().unpack(); + let (vecs, vals) = m.clone().schur().unpack(); - if !relative_eq!(&vecs * &vals * vecs.conjugate_transpose(), m, epsilon = 1.0e-7) { - println!("{:.5}{:.5}", m, &vecs * &vals * vecs.conjugate_transpose()); + if !relative_eq!(&vecs * &vals * vecs.conjugate_transpose(), m, epsilon = 1.0e-7) { + println!("{:.5}{:.5}", m, &vecs * &vals * vecs.conjugate_transpose()); + } + + relative_eq!(&vecs * vals * vecs.conjugate_transpose(), m, epsilon = 1.0e-7) + } + + fn schur_static_mat2(m: Matrix2<$scalar>) -> bool { + let m = m.map(|e| e.0); + let (vecs, vals) = m.clone().schur().unpack(); + + let ok = relative_eq!(vecs * vals * vecs.conjugate_transpose(), m, epsilon = 1.0e-7); + if !ok { + println!("Vecs: {:.5} Vals: {:.5}", vecs, vals); + println!("Reconstruction:{}{}", m, &vecs * &vals * vecs.conjugate_transpose()); + } + ok + } + + fn schur_static_mat3(m: Matrix3<$scalar>) -> bool { + let m = m.map(|e| e.0); + let (vecs, vals) = m.clone().schur().unpack(); + + let ok = relative_eq!(vecs * vals * vecs.conjugate_transpose(), m, epsilon = 1.0e-7); + if !ok { + println!("Vecs: {:.5} Vals: {:.5}", vecs, vals); + println!("{:.5}{:.5}", m, &vecs * &vals * vecs.conjugate_transpose()); + } + ok + } + + fn schur_static_mat4(m: Matrix4<$scalar>) -> bool { + let m = m.map(|e| e.0); + let (vecs, vals) = m.clone().schur().unpack(); + + let ok = relative_eq!(vecs * vals * vecs.conjugate_transpose(), m, epsilon = 1.0e-7); + if !ok { + println!("{:.5}{:.5}", m, &vecs * &vals * vecs.conjugate_transpose()); + } + + ok + } + } } - - relative_eq!(&vecs * vals * vecs.conjugate_transpose(), m, epsilon = 1.0e-7) } + ); - fn schur_static_mat2(m: Matrix2>) -> bool { - let m = m.map(|e| e.0); - let (vecs, vals) = m.clone().real_schur().unpack(); - - let ok = relative_eq!(vecs * vals * vecs.conjugate_transpose(), m, epsilon = 1.0e-7); - if !ok { - println!("Vecs: {:.5} Vals: {:.5}", vecs, vals); - println!("Reconstruction:{}{}", m, &vecs * &vals * vecs.conjugate_transpose()); - } - ok - } - - fn schur_static_mat3(m: Matrix3>) -> bool { - let m = m.map(|e| e.0); - let (vecs, vals) = m.clone().real_schur().unpack(); - - let ok = relative_eq!(vecs * vals * vecs.conjugate_transpose(), m, epsilon = 1.0e-7); - if !ok { - println!("Vecs: {:.5} Vals: {:.5}", vecs, vals); - println!("{:.5}{:.5}", m, &vecs * &vals * vecs.conjugate_transpose()); - } - ok - } - - fn schur_static_mat4(m: Matrix4>) -> bool { - let m = m.map(|e| e.0); - let (vecs, vals) = m.clone().real_schur().unpack(); - - let ok = relative_eq!(vecs * vals * vecs.conjugate_transpose(), m, epsilon = 1.0e-7); - if !ok { - println!("{:.5}{:.5}", m, &vecs * &vals * vecs.conjugate_transpose()); - } - ok - } - } + gen_tests!(complex, RandComplex); + gen_tests!(f64, RandScalar); } #[test] @@ -79,8 +90,7 @@ fn schur_static_mat4_fail() { -94.61793793643038, -18.64216213611094, 88.32376703241675, -99.30169870309795, 90.62661897246733, 96.74200696130146, 34.7421322611369, 84.86773307198098); - let (vecs, vals) = m.clone().real_schur().unpack(); - println!("{:.6}{:.6}", m, &vecs * &vals * vecs.transpose()); + let (vecs, vals) = m.clone().schur().unpack(); assert!(relative_eq!(vecs * vals * vecs.transpose(), m, epsilon = 1.0e-7)) } @@ -92,8 +102,7 @@ fn schur_static_mat4_fail2() { 27.932377940728202, 82.94220150938, -35.5898884705951, 67.56447552434219, 55.66754906908682, -42.14328890569226, -20.684709585152206, -87.9456949841046); - let (vecs, vals) = m.clone().real_schur().unpack(); - println!("{:.6}{:.6}", m, &vecs * &vals * vecs.transpose()); + let (vecs, vals) = m.clone().schur().unpack(); assert!(relative_eq!(vecs * vals * vecs.transpose(), m, epsilon = 1.0e-7)) } @@ -104,8 +113,7 @@ fn schur_static_mat3_fail() { -7.525423104386547, -17.827350599642287, 11.297377444555849, 38.080736654870464, -84.27428302131528, -95.88198590331922); - let (vecs, vals) = m.clone().real_schur().unpack(); - println!("{:.6}{:.6}", m, &vecs * &vals * vecs.transpose()); + let (vecs, vals) = m.clone().schur().unpack(); assert!(relative_eq!(vecs * vals * vecs.transpose(), m, epsilon = 1.0e-7)) } @@ -138,7 +146,6 @@ fn schur_singular() { 0.0, 0.0, 0.0, 0.0, 0.0, -4.0, 0.0, 0.0, 0.0, 4.0, 0.0, 0.0, 0.0, -4.0, 0.0, 0.0, 0.0, 0.0, 4.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 4.0, 0.0, 0.0, 0.0, -4.0, 0.0, 0.0, 0.0, 0.0, 4.0, 0.0, 0.0, 0.0, 0.0, 0.0]); - let (vecs, vals) = m.clone().real_schur().unpack(); - println!("{:.6}{:.6}", m, &vecs * &vals * vecs.transpose()); + let (vecs, vals) = m.clone().schur().unpack(); assert!(relative_eq!(&vecs * vals * vecs.transpose(), m, epsilon = 1.0e-7)) } diff --git a/tests/linalg/solve.rs b/tests/linalg/solve.rs index 76dc05b5..e2f8a3f8 100644 --- a/tests/linalg/solve.rs +++ b/tests/linalg/solve.rs @@ -1,57 +1,65 @@ #![cfg(feature = "arbitrary")] -use na::{Matrix4, Matrix4x5}; -fn unzero_diagonal(a: &mut Matrix4) { - for i in 0..4 { - if a[(i, i)] < 1.0e-7 { - a[(i, i)] = 1.0; +macro_rules! gen_tests( + ($module: ident, $scalar: ty) => { + mod $module { + use na::{Matrix4, Matrix4x5, Complex}; + #[allow(unused_imports)] + use core::helper::{RandScalar, RandComplex}; + + fn unzero_diagonal(a: &mut Matrix4) { + for i in 0..4 { + if a[(i, i)].asum() < na::convert(1.0e-7) { + a[(i, i)] = N::one(); + } + } + } + + quickcheck! { + fn solve_lower_triangular(a: Matrix4<$scalar>, b: Matrix4x5<$scalar>) -> bool { + let b = b.map(|e| e.0); + let mut a = a.map(|e| e.0); + unzero_diagonal(&mut a); + let tri = a.lower_triangle(); + let x = a.solve_lower_triangular(&b).unwrap(); + + relative_eq!(tri * x, b, epsilon = 1.0e-7) + } + + fn solve_upper_triangular(a: Matrix4<$scalar>, b: Matrix4x5<$scalar>) -> bool { + let b = b.map(|e| e.0); + let mut a = a.map(|e| e.0); + unzero_diagonal(&mut a); + let tri = a.upper_triangle(); + let x = a.solve_upper_triangular(&b).unwrap(); + + relative_eq!(tri * x, b, epsilon = 1.0e-7) + } + + fn tr_solve_lower_triangular(a: Matrix4<$scalar>, b: Matrix4x5<$scalar>) -> bool { + let b = b.map(|e| e.0); + let mut a = a.map(|e| e.0); + unzero_diagonal(&mut a); + let tri = a.lower_triangle(); + let x = a.tr_solve_lower_triangular(&b).unwrap(); + + relative_eq!(tri.transpose() * x, b, epsilon = 1.0e-7) + } + + fn tr_solve_upper_triangular(a: Matrix4<$scalar>, b: Matrix4x5<$scalar>) -> bool { + let b = b.map(|e| e.0); + let mut a = a.map(|e| e.0); + unzero_diagonal(&mut a); + let tri = a.upper_triangle(); + let x = a.tr_solve_upper_triangular(&b).unwrap(); + + relative_eq!(tri.transpose() * x, b, epsilon = 1.0e-7) + } + } } } -} +); -quickcheck! { - fn solve_lower_triangular(a: Matrix4, b: Matrix4x5) -> bool { - let mut a = a; - unzero_diagonal(&mut a); - let tri = a.lower_triangle(); - let x = a.solve_lower_triangular(&b).unwrap(); - - println!("{}\n{}\n{}\n{}", tri, x, tri * x, b); - - relative_eq!(tri * x, b, epsilon = 1.0e-7) - } - - fn solve_upper_triangular(a: Matrix4, b: Matrix4x5) -> bool { - let mut a = a; - unzero_diagonal(&mut a); - let tri = a.upper_triangle(); - let x = a.solve_upper_triangular(&b).unwrap(); - - println!("{}\n{}\n{}\n{}", tri, x, tri * x, b); - - relative_eq!(tri * x, b, epsilon = 1.0e-7) - } - - fn tr_solve_lower_triangular(a: Matrix4, b: Matrix4x5) -> bool { - let mut a = a; - unzero_diagonal(&mut a); - let tri = a.lower_triangle(); - let x = a.tr_solve_lower_triangular(&b).unwrap(); - - println!("{}\n{}\n{}\n{}", tri, x, tri * x, b); - - relative_eq!(tri.transpose() * x, b, epsilon = 1.0e-7) - } - - fn tr_solve_upper_triangular(a: Matrix4, b: Matrix4x5) -> bool { - let mut a = a; - unzero_diagonal(&mut a); - let tri = a.upper_triangle(); - let x = a.tr_solve_upper_triangular(&b).unwrap(); - - println!("{}\n{}\n{}\n{}", tri, x, tri * x, b); - - relative_eq!(tri.transpose() * x, b, epsilon = 1.0e-7) - } -} +gen_tests!(complex, RandComplex); +gen_tests!(f64, RandScalar); diff --git a/tests/linalg/svd.rs b/tests/linalg/svd.rs index efced01a..0eb1d69e 100644 --- a/tests/linalg/svd.rs +++ b/tests/linalg/svd.rs @@ -3,161 +3,161 @@ use na::{DMatrix, Matrix6}; #[cfg(feature = "arbitrary")] mod quickcheck_tests { - use na::{ - DMatrix, DVector, Matrix2, Matrix2x5, Matrix3, Matrix3x5, Matrix4, Matrix5x2, Matrix5x3, - Complex - }; - use std::cmp; - use core::helper::{RandScalar, RandComplex}; + macro_rules! gen_tests( + ($module: ident, $scalar: ty) => { + mod $module { + use na::{ + DMatrix, DVector, Matrix2, Matrix2x5, Matrix3, Matrix3x5, Matrix4, Matrix5x2, Matrix5x3, + Complex + }; + use std::cmp; + #[allow(unused_imports)] + use core::helper::{RandScalar, RandComplex}; + quickcheck! { + fn svd(m: DMatrix<$scalar>) -> bool { + let m = m.map(|e| e.0); + if m.len() > 0 { + let svd = m.clone().svd(true, true); + let recomp_m = svd.clone().recompose().unwrap(); + let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); + let ds = DMatrix::from_diagonal(&s.map(|e| Complex::from_real(e))); - quickcheck! { - fn svd(m: DMatrix>) -> bool { - let m = m.map(|e| e.0); - if m.len() > 0 { - let svd = m.clone().svd(true, true); - let recomp_m = svd.clone().recompose().unwrap(); - let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); - let ds = DMatrix::from_diagonal(&s.map(|e| Complex::from_real(e))); + s.iter().all(|e| *e >= 0.0) && + relative_eq!(&u * ds * &v_t, recomp_m, epsilon = 1.0e-5) && + relative_eq!(m, recomp_m, epsilon = 1.0e-5) + } + else { + true + } + } - println!("{}{}", &m, &u * &ds * &v_t); + fn svd_static_5_3(m: Matrix5x3<$scalar>) -> bool { + let m = m.map(|e| e.0); + let svd = m.svd(true, true); + let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); + let ds = Matrix3::from_diagonal(&s.map(|e| Complex::from_real(e))); - s.iter().all(|e| *e >= 0.0) && - relative_eq!(&u * ds * &v_t, recomp_m, epsilon = 1.0e-5) && - relative_eq!(m, recomp_m, epsilon = 1.0e-5) - } - else { - true - } - } + s.iter().all(|e| *e >= 0.0) && + relative_eq!(m, &u * ds * &v_t, epsilon = 1.0e-5) && + u.is_orthogonal(1.0e-5) && + v_t.is_orthogonal(1.0e-5) + } - fn svd_static_5_3(m: Matrix5x3>) -> bool { - let m = m.map(|e| e.0); - let svd = m.svd(true, true); - let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); - let ds = Matrix3::from_diagonal(&s.map(|e| Complex::from_real(e))); + fn svd_static_5_2(m: Matrix5x2<$scalar>) -> bool { + let m = m.map(|e| e.0); + let svd = m.svd(true, true); + let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); + let ds = Matrix2::from_diagonal(&s.map(|e| Complex::from_real(e))); - s.iter().all(|e| *e >= 0.0) && - relative_eq!(m, &u * ds * &v_t, epsilon = 1.0e-5) && - u.is_orthogonal(1.0e-5) && - v_t.is_orthogonal(1.0e-5) - } + s.iter().all(|e| *e >= 0.0) && + relative_eq!(m, &u * ds * &v_t, epsilon = 1.0e-5) && + u.is_orthogonal(1.0e-5) && + v_t.is_orthogonal(1.0e-5) + } - fn svd_static_5_2(m: Matrix5x2>) -> bool { - let m = m.map(|e| e.0); - let svd = m.svd(true, true); - let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); - let ds = Matrix2::from_diagonal(&s.map(|e| Complex::from_real(e))); + fn svd_static_3_5(m: Matrix3x5<$scalar>) -> bool { + let m = m.map(|e| e.0); + let svd = m.svd(true, true); + let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); - s.iter().all(|e| *e >= 0.0) && - relative_eq!(m, &u * ds * &v_t, epsilon = 1.0e-5) && - u.is_orthogonal(1.0e-5) && - v_t.is_orthogonal(1.0e-5) - } + let ds = Matrix3::from_diagonal(&s.map(|e| Complex::from_real(e))); - fn svd_static_3_5(m: Matrix3x5>) -> bool { - let m = m.map(|e| e.0); - let svd = m.svd(true, true); - let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); + s.iter().all(|e| *e >= 0.0) && + relative_eq!(m, u * ds * v_t, epsilon = 1.0e-5) + } - let ds = Matrix3::from_diagonal(&s.map(|e| Complex::from_real(e))); + fn svd_static_2_5(m: Matrix2x5<$scalar>) -> bool { + let m = m.map(|e| e.0); + let svd = m.svd(true, true); + let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); + let ds = Matrix2::from_diagonal(&s.map(|e| Complex::from_real(e))); - s.iter().all(|e| *e >= 0.0) && - relative_eq!(m, u * ds * v_t, epsilon = 1.0e-5) - } + s.iter().all(|e| *e >= 0.0) && + relative_eq!(m, u * ds * v_t, epsilon = 1.0e-5) + } - fn svd_static_2_5(m: Matrix2x5>) -> bool { - let m = m.map(|e| e.0); - let svd = m.svd(true, true); - let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); - let ds = Matrix2::from_diagonal(&s.map(|e| Complex::from_real(e))); + fn svd_static_square(m: Matrix4<$scalar>) -> bool { + let m = m.map(|e| e.0); + let svd = m.svd(true, true); + let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); + let ds = Matrix4::from_diagonal(&s.map(|e| Complex::from_real(e))); - s.iter().all(|e| *e >= 0.0) && - relative_eq!(m, u * ds * v_t, epsilon = 1.0e-5) - } + s.iter().all(|e| *e >= 0.0) && + relative_eq!(m, u * ds * v_t, epsilon = 1.0e-5) && + u.is_orthogonal(1.0e-5) && + v_t.is_orthogonal(1.0e-5) + } - fn svd_static_square(m: Matrix4>) -> bool { - let m = m.map(|e| e.0); - let svd = m.svd(true, true); - let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); - let ds = Matrix4::from_diagonal(&s.map(|e| Complex::from_real(e))); + fn svd_static_square_2x2(m: Matrix2<$scalar>) -> bool { + let m = m.map(|e| e.0); + let svd = m.svd(true, true); + let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); + let ds = Matrix2::from_diagonal(&s.map(|e| Complex::from_real(e))); - s.iter().all(|e| *e >= 0.0) && - relative_eq!(m, u * ds * v_t, epsilon = 1.0e-5) && - u.is_orthogonal(1.0e-5) && - v_t.is_orthogonal(1.0e-5) - } + s.iter().all(|e| *e >= 0.0) && + relative_eq!(m, u * ds * v_t, epsilon = 1.0e-5) && + u.is_orthogonal(1.0e-5) && + v_t.is_orthogonal(1.0e-5) + } - fn svd_static_square_2x2(m: Matrix2>) -> bool { - let m = m.map(|e| e.0); - let svd = m.svd(true, true); - let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); - let ds = Matrix2::from_diagonal(&s.map(|e| Complex::from_real(e))); + fn svd_pseudo_inverse(m: DMatrix<$scalar>) -> bool { + let m = m.map(|e| e.0); - println!("u, s, v_t: {}{}{}", u, s, v_t); - println!("m: {}", m); - println!("recomp: {}", u * ds * v_t); - println!("uu_t, vv_t: {}{}", u * u.conjugate_transpose(), v_t.conjugate_transpose() * v_t); + if m.len() > 0 { + let svd = m.clone().svd(true, true); + let pinv = svd.pseudo_inverse(1.0e-10).unwrap(); - s.iter().all(|e| *e >= 0.0) && - relative_eq!(m, u * ds * v_t, epsilon = 1.0e-5) && - u.is_orthogonal(1.0e-5) && - v_t.is_orthogonal(1.0e-5) - } + if m.nrows() > m.ncols() { + (pinv * m).is_identity(1.0e-5) + } + else { + (m * pinv).is_identity(1.0e-5) + } + } + else { + true + } + } - fn svd_pseudo_inverse(m: DMatrix>) -> bool { - let m = m.map(|e| e.0); + fn svd_solve(n: usize, nb: usize) -> bool { + let n = cmp::max(1, cmp::min(n, 10)); + let nb = cmp::min(nb, 10); + let m = DMatrix::<$scalar>::new_random(n, n).map(|e| e.0); - if m.len() > 0 { - let svd = m.clone().svd(true, true); - let pinv = svd.pseudo_inverse(1.0e-10).unwrap(); + let svd = m.clone().svd(true, true); - if m.nrows() > m.ncols() { - println!("{}", &pinv * &m); - (pinv * m).is_identity(1.0e-5) - } - else { - println!("{}", &m * &pinv); - (m * pinv).is_identity(1.0e-5) + if svd.rank(1.0e-7) == n { + let b1 = DVector::<$scalar>::new_random(n).map(|e| e.0); + let b2 = DMatrix::<$scalar>::new_random(n, nb).map(|e| e.0); + + let sol1 = svd.solve(&b1, 1.0e-7).unwrap(); + let sol2 = svd.solve(&b2, 1.0e-7).unwrap(); + + let recomp = svd.recompose().unwrap(); + if !relative_eq!(m, recomp, epsilon = 1.0e-6) { + println!("{}{}", m, recomp); + } + + if !relative_eq!(&m * &sol1, b1, epsilon = 1.0e-6) { + println!("Problem 1: {:.6}{:.6}", b1, &m * sol1); + return false; + } + if !relative_eq!(&m * &sol2, b2, epsilon = 1.0e-6) { + println!("Problem 2: {:.6}{:.6}", b2, &m * sol2); + return false; + } + } + + true + } } } - else { - true - } } + ); - fn svd_solve(n: usize, nb: usize) -> bool { - let n = cmp::max(1, cmp::min(n, 10)); - let nb = cmp::min(nb, 10); - let m = DMatrix::>::new_random(n, n).map(|e| e.0); - - let svd = m.clone().svd(true, true); - - if svd.rank(1.0e-7) == n { - let b1 = DVector::>::new_random(n).map(|e| e.0); - let b2 = DMatrix::>::new_random(n, nb).map(|e| e.0); - - let sol1 = svd.solve(&b1, 1.0e-7).unwrap(); - let sol2 = svd.solve(&b2, 1.0e-7).unwrap(); - - let recomp = svd.recompose().unwrap(); - if !relative_eq!(m, recomp, epsilon = 1.0e-6) { - println!("{}{}", m, recomp); - } - - if !relative_eq!(&m * &sol1, b1, epsilon = 1.0e-6) { - println!("Problem 1: {:.6}{:.6}", b1, &m * sol1); - return false; - } - if !relative_eq!(&m * &sol2, b2, epsilon = 1.0e-6) { - println!("Problem 2: {:.6}{:.6}", b2, &m * sol2); - return false; - } - } - - true - } - } + gen_tests!(complex, RandComplex); + gen_tests!(f64, RandScalar); } @@ -194,8 +194,6 @@ fn svd_singular() { let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); let ds = DMatrix::from_diagonal(&s); - println!("{:.5}", &u * &ds * &v_t); - assert!(s.iter().all(|e| *e >= 0.0)); assert!(u.is_orthogonal(1.0e-5)); assert!(v_t.is_orthogonal(1.0e-5)); @@ -345,11 +343,7 @@ fn svd_fail() { 0.12293810556077789, 0.6617084679545999, 0.9002240700227326, 0.027153062135304884, 0.3630189466989524, 0.18207502727558866, 0.843196731466686, 0.08951878746549924, 0.7533450877576973, 0.009558876499740077, 0.9429679490873482, 0.9355764454129878); let svd = m.clone().svd(true, true); - println!("Singular values: {}", svd.singular_values); - println!("u: {:.5}", svd.u.unwrap()); - println!("v: {:.5}", svd.v_t.unwrap()); let recomp = svd.recompose().unwrap(); - println!("{:.5}{:.5}", m, recomp); assert_relative_eq!(m, recomp, epsilon = 1.0e-5); } diff --git a/tests/linalg/tridiagonal.rs b/tests/linalg/tridiagonal.rs index fee0176a..368aba13 100644 --- a/tests/linalg/tridiagonal.rs +++ b/tests/linalg/tridiagonal.rs @@ -1,47 +1,56 @@ #![cfg(feature = "arbitrary")] -use std::cmp; -use na::{DMatrix, Matrix2, Matrix4}; -use core::helper::{RandScalar, RandComplex}; +macro_rules! gen_tests( + ($module: ident, $scalar: ty) => { + mod $module { + use std::cmp; -quickcheck! { - fn symm_tridiagonal(n: usize) -> bool { - let n = cmp::max(1, cmp::min(n, 50)); - let m = DMatrix::>::new_random(n, n).map(|e| e.0).hermitian_part(); - let tri = m.clone().symmetric_tridiagonalize(); - let recomp = tri.recompose(); + use na::{DMatrix, Matrix2, Matrix4}; + #[allow(unused_imports)] + use core::helper::{RandScalar, RandComplex}; - relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-7) + quickcheck! { + fn symm_tridiagonal(n: usize) -> bool { + let n = cmp::max(1, cmp::min(n, 50)); + let m = DMatrix::<$scalar>::new_random(n, n).map(|e| e.0).hermitian_part(); + let tri = m.clone().symmetric_tridiagonalize(); + let recomp = tri.recompose(); + + relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-7) + } + + fn symm_tridiagonal_singular(n: usize) -> bool { + let n = cmp::max(1, cmp::min(n, 4)); + let mut m = DMatrix::<$scalar>::new_random(n, n).map(|e| e.0).hermitian_part(); + m.row_mut(n / 2).fill(na::zero()); + m.column_mut(n / 2).fill(na::zero()); + let tri = m.clone().symmetric_tridiagonalize(); + let recomp = tri.recompose(); + + relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-7) + } + + fn symm_tridiagonal_static_square(m: Matrix4<$scalar>) -> bool { + let m = m.map(|e| e.0).hermitian_part(); + let tri = m.symmetric_tridiagonalize(); + let recomp = tri.recompose(); + + relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-7) + } + + fn symm_tridiagonal_static_square_2x2(m: Matrix2<$scalar>) -> bool { + let m = m.map(|e| e.0).hermitian_part(); + let tri = m.symmetric_tridiagonalize(); + let recomp = tri.recompose(); + + relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-7) + } + } + } } - - fn symm_tridiagonal_singular(n: usize) -> bool { - let n = cmp::max(1, cmp::min(n, 4)); - let mut m = DMatrix::>::new_random(n, n).map(|e| e.0).hermitian_part(); - m.row_mut(n / 2).fill(na::zero()); - m.column_mut(n / 2).fill(na::zero()); - let tri = m.clone().symmetric_tridiagonalize(); - println!("Tri: {:?}", tri); - let recomp = tri.recompose(); - println!("Recomp: {:?}", recomp); +); - relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-7) - } - - fn symm_tridiagonal_static_square(m: Matrix4>) -> bool { - let m = m.map(|e| e.0).hermitian_part(); - let tri = m.symmetric_tridiagonalize(); - let recomp = tri.recompose(); - - relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-7) - } - - fn symm_tridiagonal_static_square_2x2(m: Matrix2>) -> bool { - let m = m.map(|e| e.0).hermitian_part(); - let tri = m.symmetric_tridiagonalize(); - let recomp = tri.recompose(); - - relative_eq!(m.lower_triangle(), recomp.lower_triangle(), epsilon = 1.0e-7) - } -} +gen_tests!(complex, RandComplex); +gen_tests!(f64, RandScalar); From 921a05d523681c18888791c343011398084ede74 Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sat, 23 Mar 2019 11:48:12 +0100 Subject: [PATCH 11/28] Implement some BLAS opertaions involving adjoint. --- nalgebra-lapack/src/lu.rs | 4 +- src/base/blas.rs | 600 +++++++++++++++------------- src/base/matrix.rs | 39 +- src/base/matrix_alga.rs | 2 +- src/base/norm.rs | 4 +- src/base/ops.rs | 163 ++++---- src/base/properties.rs | 3 +- src/debug/random_sdp.rs | 2 +- src/geometry/reflection.rs | 6 +- src/lib.rs | 3 + src/linalg/cholesky.rs | 2 +- src/linalg/mod.rs | 2 +- src/linalg/solve.rs | 196 ++++++--- src/linalg/svd.rs | 6 +- src/linalg/symmetric_tridiagonal.rs | 12 +- tests/core/blas.rs | 8 +- tests/linalg/cholesky.rs | 4 +- tests/linalg/hessenberg.rs | 6 +- tests/linalg/schur.rs | 18 +- tests/linalg/solve.rs | 2 +- 20 files changed, 617 insertions(+), 465 deletions(-) diff --git a/nalgebra-lapack/src/lu.rs b/nalgebra-lapack/src/lu.rs index ad76e245..dc21c12b 100644 --- a/nalgebra-lapack/src/lu.rs +++ b/nalgebra-lapack/src/lu.rs @@ -214,7 +214,7 @@ where } } - /// Solves the linear system `self.conjugate_transpose() * x = b`, where `x` is the unknown to + /// Solves the linear system `self.adjoint() * x = b`, where `x` is the unknown to /// be determined. pub fn solve_conjugate_transpose( &self, @@ -249,7 +249,7 @@ where self.generic_solve_mut(b'T', b) } - /// Solves in-place the linear system `self.conjugate_transpose() * x = b`, where `x` is the unknown to + /// Solves in-place the linear system `self.adjoint() * x = b`, where `x` is the unknown to /// be determined. /// /// Returns `false` if no solution was found (the decomposed matrix is singular). diff --git a/src/base/blas.rs b/src/base/blas.rs index 7dce36b6..210db8cd 100644 --- a/src/base/blas.rs +++ b/src/base/blas.rs @@ -11,7 +11,7 @@ use base::constraint::{ }; use base::dimension::{Dim, Dynamic, U1, U2, U3, U4}; use base::storage::{Storage, StorageMut}; -use base::{DefaultAllocator, Matrix, Scalar, SquareMatrix, Vector}; +use base::{DefaultAllocator, Matrix, Scalar, SquareMatrix, Vector, DVectorSlice}; // FIXME: find a way to avoid code duplication just for complex number support. @@ -32,11 +32,11 @@ impl> Vector { pub fn icamax(&self) -> usize { assert!(!self.is_empty(), "The input vector must not be empty."); - let mut the_max = unsafe { self.vget_unchecked(0).asum() }; + let mut the_max = unsafe { self.vget_unchecked(0).norm1() }; let mut the_i = 0; for i in 1..self.nrows() { - let val = unsafe { self.vget_unchecked(i).asum() }; + let val = unsafe { self.vget_unchecked(i).norm1() }; if val > the_max { the_max = val; @@ -211,12 +211,12 @@ impl> Matrix { pub fn icamax_full(&self) -> (usize, usize) { assert!(!self.is_empty(), "The input matrix must not be empty."); - let mut the_max = unsafe { self.get_unchecked((0, 0)).asum() }; + let mut the_max = unsafe { self.get_unchecked((0, 0)).norm1() }; let mut the_ij = (0, 0); for j in 0..self.ncols() { for i in 0..self.nrows() { - let val = unsafe { self.get_unchecked((i, j)).asum() }; + let val = unsafe { self.get_unchecked((i, j)).norm1() }; if val > the_max { the_max = val; @@ -263,13 +263,11 @@ impl> Matri } } -impl> Matrix { - /// The dot product between two complex or real vectors or matrices (seen as vectors). - /// - /// This is the same as `.dot` except that the conjugate of each component of `self` is taken - /// before performing the products. - #[inline] - pub fn cdot(&self, rhs: &Matrix) -> N +impl> Matrix +where N: Scalar + Zero + ClosedAdd + ClosedMul +{ + #[inline(always)] + fn dotx(&self, rhs: &Matrix, conjugate: impl Fn(N) -> N) -> N where SB: Storage, ShapeConstraint: DimEq + DimEq, @@ -283,27 +281,27 @@ impl> Matrix { // because the `for` loop below won't be very efficient on those. if (R::is::() || R2::is::()) && (C::is::() || C2::is::()) { unsafe { - let a = self.get_unchecked((0, 0)).conjugate() * *rhs.get_unchecked((0, 0)); - let b = self.get_unchecked((1, 0)).conjugate() * *rhs.get_unchecked((1, 0)); + let a = conjugate(*self.get_unchecked((0, 0))) * *rhs.get_unchecked((0, 0)); + let b = conjugate(*self.get_unchecked((1, 0))) * *rhs.get_unchecked((1, 0)); return a + b; } } if (R::is::() || R2::is::()) && (C::is::() || C2::is::()) { unsafe { - let a = self.get_unchecked((0, 0)).conjugate() * *rhs.get_unchecked((0, 0)); - let b = self.get_unchecked((1, 0)).conjugate() * *rhs.get_unchecked((1, 0)); - let c = self.get_unchecked((2, 0)).conjugate() * *rhs.get_unchecked((2, 0)); + let a = conjugate(*self.get_unchecked((0, 0))) * *rhs.get_unchecked((0, 0)); + let b = conjugate(*self.get_unchecked((1, 0))) * *rhs.get_unchecked((1, 0)); + let c = conjugate(*self.get_unchecked((2, 0))) * *rhs.get_unchecked((2, 0)); return a + b + c; } } if (R::is::() || R2::is::()) && (C::is::() || C2::is::()) { unsafe { - let mut a = self.get_unchecked((0, 0)).conjugate() * *rhs.get_unchecked((0, 0)); - let mut b = self.get_unchecked((1, 0)).conjugate() * *rhs.get_unchecked((1, 0)); - let c = self.get_unchecked((2, 0)).conjugate() * *rhs.get_unchecked((2, 0)); - let d = self.get_unchecked((3, 0)).conjugate() * *rhs.get_unchecked((3, 0)); + let mut a = conjugate(*self.get_unchecked((0, 0))) * *rhs.get_unchecked((0, 0)); + let mut b = conjugate(*self.get_unchecked((1, 0))) * *rhs.get_unchecked((1, 0)); + let c = conjugate(*self.get_unchecked((2, 0))) * *rhs.get_unchecked((2, 0)); + let d = conjugate(*self.get_unchecked((3, 0))) * *rhs.get_unchecked((3, 0)); a += c; b += d; @@ -343,14 +341,14 @@ impl> Matrix { acc7 = N::zero(); while self.nrows() - i >= 8 { - acc0 += unsafe { self.get_unchecked((i + 0, j)).conjugate() * *rhs.get_unchecked((i + 0, j)) }; - acc1 += unsafe { self.get_unchecked((i + 1, j)).conjugate() * *rhs.get_unchecked((i + 1, j)) }; - acc2 += unsafe { self.get_unchecked((i + 2, j)).conjugate() * *rhs.get_unchecked((i + 2, j)) }; - acc3 += unsafe { self.get_unchecked((i + 3, j)).conjugate() * *rhs.get_unchecked((i + 3, j)) }; - acc4 += unsafe { self.get_unchecked((i + 4, j)).conjugate() * *rhs.get_unchecked((i + 4, j)) }; - acc5 += unsafe { self.get_unchecked((i + 5, j)).conjugate() * *rhs.get_unchecked((i + 5, j)) }; - acc6 += unsafe { self.get_unchecked((i + 6, j)).conjugate() * *rhs.get_unchecked((i + 6, j)) }; - acc7 += unsafe { self.get_unchecked((i + 7, j)).conjugate() * *rhs.get_unchecked((i + 7, j)) }; + acc0 += unsafe { conjugate(*self.get_unchecked((i + 0, j))) * *rhs.get_unchecked((i + 0, j)) }; + acc1 += unsafe { conjugate(*self.get_unchecked((i + 1, j))) * *rhs.get_unchecked((i + 1, j)) }; + acc2 += unsafe { conjugate(*self.get_unchecked((i + 2, j))) * *rhs.get_unchecked((i + 2, j)) }; + acc3 += unsafe { conjugate(*self.get_unchecked((i + 3, j))) * *rhs.get_unchecked((i + 3, j)) }; + acc4 += unsafe { conjugate(*self.get_unchecked((i + 4, j))) * *rhs.get_unchecked((i + 4, j)) }; + acc5 += unsafe { conjugate(*self.get_unchecked((i + 5, j))) * *rhs.get_unchecked((i + 5, j)) }; + acc6 += unsafe { conjugate(*self.get_unchecked((i + 6, j))) * *rhs.get_unchecked((i + 6, j)) }; + acc7 += unsafe { conjugate(*self.get_unchecked((i + 7, j))) * *rhs.get_unchecked((i + 7, j)) }; i += 8; } @@ -360,17 +358,14 @@ impl> Matrix { res += acc3 + acc7; for k in i..self.nrows() { - res += unsafe { self.get_unchecked((k, j)).conjugate() * *rhs.get_unchecked((k, j)) } + res += unsafe { conjugate(*self.get_unchecked((k, j))) * *rhs.get_unchecked((k, j)) } } } res } -} -impl> Matrix -where N: Scalar + Zero + ClosedAdd + ClosedMul -{ + /// The dot product between two vectors or matrices (seen as vectors). /// /// Note that this is **not** the matrix multiplication as in, e.g., numpy. For matrix @@ -396,97 +391,36 @@ where N: Scalar + Zero + ClosedAdd + ClosedMul SB: Storage, ShapeConstraint: DimEq + DimEq, { - assert!( - self.nrows() == rhs.nrows(), - "Dot product dimensions mismatch." - ); + self.dotx(rhs, |e| e) + } - // So we do some special cases for common fixed-size vectors of dimension lower than 8 - // because the `for` loop below won't be very efficient on those. - if (R::is::() || R2::is::()) && (C::is::() || C2::is::()) { - unsafe { - let a = *self.get_unchecked((0, 0)) * *rhs.get_unchecked((0, 0)); - let b = *self.get_unchecked((1, 0)) * *rhs.get_unchecked((1, 0)); - - return a + b; - } - } - if (R::is::() || R2::is::()) && (C::is::() || C2::is::()) { - unsafe { - let a = *self.get_unchecked((0, 0)) * *rhs.get_unchecked((0, 0)); - let b = *self.get_unchecked((1, 0)) * *rhs.get_unchecked((1, 0)); - let c = *self.get_unchecked((2, 0)) * *rhs.get_unchecked((2, 0)); - - return a + b + c; - } - } - if (R::is::() || R2::is::()) && (C::is::() || C2::is::()) { - unsafe { - let mut a = *self.get_unchecked((0, 0)) * *rhs.get_unchecked((0, 0)); - let mut b = *self.get_unchecked((1, 0)) * *rhs.get_unchecked((1, 0)); - let c = *self.get_unchecked((2, 0)) * *rhs.get_unchecked((2, 0)); - let d = *self.get_unchecked((3, 0)) * *rhs.get_unchecked((3, 0)); - - a += c; - b += d; - - return a + b; - } - } - - // All this is inspired from the "unrolled version" discussed in: - // http://blog.theincredibleholk.org/blog/2012/12/10/optimizing-dot-product/ - // - // And this comment from bluss: - // https://users.rust-lang.org/t/how-to-zip-two-slices-efficiently/2048/12 - let mut res = N::zero(); - - // We have to define them outside of the loop (and not inside at first assignment) - // otherwise vectorization won't kick in for some reason. - let mut acc0; - let mut acc1; - let mut acc2; - let mut acc3; - let mut acc4; - let mut acc5; - let mut acc6; - let mut acc7; - - for j in 0..self.ncols() { - let mut i = 0; - - acc0 = N::zero(); - acc1 = N::zero(); - acc2 = N::zero(); - acc3 = N::zero(); - acc4 = N::zero(); - acc5 = N::zero(); - acc6 = N::zero(); - acc7 = N::zero(); - - while self.nrows() - i >= 8 { - acc0 += unsafe { *self.get_unchecked((i + 0, j)) * *rhs.get_unchecked((i + 0, j)) }; - acc1 += unsafe { *self.get_unchecked((i + 1, j)) * *rhs.get_unchecked((i + 1, j)) }; - acc2 += unsafe { *self.get_unchecked((i + 2, j)) * *rhs.get_unchecked((i + 2, j)) }; - acc3 += unsafe { *self.get_unchecked((i + 3, j)) * *rhs.get_unchecked((i + 3, j)) }; - acc4 += unsafe { *self.get_unchecked((i + 4, j)) * *rhs.get_unchecked((i + 4, j)) }; - acc5 += unsafe { *self.get_unchecked((i + 5, j)) * *rhs.get_unchecked((i + 5, j)) }; - acc6 += unsafe { *self.get_unchecked((i + 6, j)) * *rhs.get_unchecked((i + 6, j)) }; - acc7 += unsafe { *self.get_unchecked((i + 7, j)) * *rhs.get_unchecked((i + 7, j)) }; - i += 8; - } - - res += acc0 + acc4; - res += acc1 + acc5; - res += acc2 + acc6; - res += acc3 + acc7; - - for k in i..self.nrows() { - res += unsafe { *self.get_unchecked((k, j)) * *rhs.get_unchecked((k, j)) } - } - } - - res + /// The dot product between two vectors or matrices (seen as vectors). + /// + /// Note that this is **not** the matrix multiplication as in, e.g., numpy. For matrix + /// multiplication, use one of: `.gemm`, `.mul_to`, `.mul`, the `*` operator. + /// + /// # Examples: + /// + /// ``` + /// # use nalgebra::{Vector3, Matrix2x3}; + /// let vec1 = Vector3::new(1.0, 2.0, 3.0); + /// let vec2 = Vector3::new(0.1, 0.2, 0.3); + /// assert_eq!(vec1.dot(&vec2), 1.4); + /// + /// let mat1 = Matrix2x3::new(1.0, 2.0, 3.0, + /// 4.0, 5.0, 6.0); + /// let mat2 = Matrix2x3::new(0.1, 0.2, 0.3, + /// 0.4, 0.5, 0.6); + /// assert_eq!(mat1.dot(&mat2), 9.1); + /// ``` + #[inline] + pub fn dotc(&self, rhs: &Matrix) -> N + where + N: Complex, + SB: Storage, + ShapeConstraint: DimEq + DimEq, + { + self.dotx(rhs, Complex::conjugate) } /// The dot product between the transpose of `self` and `rhs`. @@ -643,40 +577,15 @@ where } } - /// Computes `self = alpha * a * x + beta * self`, where `a` is a **symmetric** matrix, `x` a - /// vector, and `alpha, beta` two scalars. - /// - /// If `beta` is zero, `self` is never read. If `self` is read, only its lower-triangular part - /// (including the diagonal) is actually read. - /// - /// # Examples: - /// - /// ``` - /// # use nalgebra::{Matrix2, Vector2}; - /// let mat = Matrix2::new(1.0, 2.0, - /// 2.0, 4.0); - /// let mut vec1 = Vector2::new(1.0, 2.0); - /// let vec2 = Vector2::new(0.1, 0.2); - /// vec1.gemv_symm(10.0, &mat, &vec2, 5.0); - /// assert_eq!(vec1, Vector2::new(10.0, 20.0)); - /// - /// - /// // The matrix upper-triangular elements can be garbage because it is never - /// // read by this method. Therefore, it is not necessary for the caller to - /// // fill the matrix struct upper-triangle. - /// let mat = Matrix2::new(1.0, 9999999.9999999, - /// 2.0, 4.0); - /// let mut vec1 = Vector2::new(1.0, 2.0); - /// vec1.gemv_symm(10.0, &mat, &vec2, 5.0); - /// assert_eq!(vec1, Vector2::new(10.0, 20.0)); - /// ``` - #[inline] - pub fn gemv_symm( + + #[inline(always)] + fn xgemv( &mut self, alpha: N, a: &SquareMatrix, x: &Vector, beta: N, + dotc: impl Fn(&DVectorSlice, &DVectorSlice) -> N, ) where N: One, SB: Storage, @@ -687,83 +596,6 @@ where let dim2 = a.nrows(); let dim3 = x.nrows(); - assert!( - a.is_square(), - "Symmetric gemv: the input matrix must be square." - ); - assert!( - dim2 == dim3 && dim1 == dim2, - "Symmetric gemv: dimensions mismatch." - ); - - if dim2 == 0 { - return; - } - - // FIXME: avoid bound checks. - let col2 = a.column(0); - let val = unsafe { *x.vget_unchecked(0) }; - self.axpy(alpha * val, &col2, beta); - self[0] += alpha * x.rows_range(1..).dot(&a.slice_range(1.., 0)); - - for j in 1..dim2 { - let col2 = a.column(j); - let dot = x.rows_range(j..).dot(&col2.rows_range(j..)); - - let val; - unsafe { - val = *x.vget_unchecked(j); - *self.vget_unchecked_mut(j) += alpha * dot; - } - self.rows_range_mut(j + 1..) - .axpy(alpha * val, &col2.rows_range(j + 1..), N::one()); - } - } - - /// Computes `self = alpha * a * x + beta * self`, where `a` is a **symmetric** matrix, `x` a - /// vector, and `alpha, beta` two scalars. - /// - /// If `beta` is zero, `self` is never read. If `self` is read, only its lower-triangular part - /// (including the diagonal) is actually read. - /// - /// # Examples: - /// - /// ``` - /// # use nalgebra::{Matrix2, Vector2}; - /// let mat = Matrix2::new(1.0, 2.0, - /// 2.0, 4.0); - /// let mut vec1 = Vector2::new(1.0, 2.0); - /// let vec2 = Vector2::new(0.1, 0.2); - /// vec1.gemv_symm(10.0, &mat, &vec2, 5.0); - /// assert_eq!(vec1, Vector2::new(10.0, 20.0)); - /// - /// - /// // The matrix upper-triangular elements can be garbage because it is never - /// // read by this method. Therefore, it is not necessary for the caller to - /// // fill the matrix struct upper-triangle. - /// let mat = Matrix2::new(1.0, 9999999.9999999, - /// 2.0, 4.0); - /// let mut vec1 = Vector2::new(1.0, 2.0); - /// vec1.gemv_symm(10.0, &mat, &vec2, 5.0); - /// assert_eq!(vec1, Vector2::new(10.0, 20.0)); - /// ``` - #[inline] - pub fn cgemv_symm( - &mut self, - alpha: N, - a: &SquareMatrix, - x: &Vector, - beta: N, - ) where - N: Complex, - SB: Storage, - SC: Storage, - ShapeConstraint: DimEq + AreMultipliable, - { - let dim1 = self.nrows(); - let dim2 = a.nrows(); - let dim3 = x.nrows(); - assert!( a.is_square(), "Symmetric cgemv: the input matrix must be square." @@ -781,11 +613,11 @@ where let col2 = a.column(0); let val = unsafe { *x.vget_unchecked(0) }; self.axpy(alpha * val, &col2, beta); - self[0] += alpha * a.slice_range(1.., 0).cdot(&x.rows_range(1..)); + self[0] += alpha * dotc(&a.slice_range(1.., 0), &x.rows_range(1..)); for j in 1..dim2 { let col2 = a.column(j); - let dot = col2.rows_range(j..).cdot(&x.rows_range(j..)); + let dot = dotc(&col2.rows_range(j..), &x.rows_range(j..)); let val; unsafe { @@ -797,6 +629,111 @@ where } } + /// Computes `self = alpha * a * x + beta * self`, where `a` is a **symmetric** matrix, `x` a + /// vector, and `alpha, beta` two scalars. DEPRECATED: use `sygemv` instead. + #[inline] + #[deprecated(note = "This is renamed `sygemv` to match the original BLAS terminology.")] + pub fn gemv_symm( + &mut self, + alpha: N, + a: &SquareMatrix, + x: &Vector, + beta: N, + ) where + N: One, + SB: Storage, + SC: Storage, + ShapeConstraint: DimEq + AreMultipliable, + { + self.sygemv(alpha, a, x, beta) + } + + /// Computes `self = alpha * a * x + beta * self`, where `a` is a **symmetric** matrix, `x` a + /// vector, and `alpha, beta` two scalars. + /// + /// If `beta` is zero, `self` is never read. If `self` is read, only its lower-triangular part + /// (including the diagonal) is actually read. + /// + /// # Examples: + /// + /// ``` + /// # use nalgebra::{Matrix2, Vector2}; + /// let mat = Matrix2::new(1.0, 2.0, + /// 2.0, 4.0); + /// let mut vec1 = Vector2::new(1.0, 2.0); + /// let vec2 = Vector2::new(0.1, 0.2); + /// vec1.sygemv(10.0, &mat, &vec2, 5.0); + /// assert_eq!(vec1, Vector2::new(10.0, 20.0)); + /// + /// + /// // The matrix upper-triangular elements can be garbage because it is never + /// // read by this method. Therefore, it is not necessary for the caller to + /// // fill the matrix struct upper-triangle. + /// let mat = Matrix2::new(1.0, 9999999.9999999, + /// 2.0, 4.0); + /// let mut vec1 = Vector2::new(1.0, 2.0); + /// vec1.sygemv(10.0, &mat, &vec2, 5.0); + /// assert_eq!(vec1, Vector2::new(10.0, 20.0)); + /// ``` + #[inline] + pub fn sygemv( + &mut self, + alpha: N, + a: &SquareMatrix, + x: &Vector, + beta: N, + ) where + N: One, + SB: Storage, + SC: Storage, + ShapeConstraint: DimEq + AreMultipliable, + { + self.xgemv(alpha, a, x, beta, |a, b| a.dot(b)) + } + + /// Computes `self = alpha * a * x + beta * self`, where `a` is an **hermitian** matrix, `x` a + /// vector, and `alpha, beta` two scalars. + /// + /// If `beta` is zero, `self` is never read. If `self` is read, only its lower-triangular part + /// (including the diagonal) is actually read. + /// + /// # Examples: + /// + /// ``` + /// # use nalgebra::{Matrix2, Vector2}; + /// let mat = Matrix2::new(1.0, 2.0, + /// 2.0, 4.0); + /// let mut vec1 = Vector2::new(1.0, 2.0); + /// let vec2 = Vector2::new(0.1, 0.2); + /// vec1.sygemv(10.0, &mat, &vec2, 5.0); + /// assert_eq!(vec1, Vector2::new(10.0, 20.0)); + /// + /// + /// // The matrix upper-triangular elements can be garbage because it is never + /// // read by this method. Therefore, it is not necessary for the caller to + /// // fill the matrix struct upper-triangle. + /// let mat = Matrix2::new(1.0, 9999999.9999999, + /// 2.0, 4.0); + /// let mut vec1 = Vector2::new(1.0, 2.0); + /// vec1.sygemv(10.0, &mat, &vec2, 5.0); + /// assert_eq!(vec1, Vector2::new(10.0, 20.0)); + /// ``` + #[inline] + pub fn hegemv( + &mut self, + alpha: N, + a: &SquareMatrix, + x: &Vector, + beta: N, + ) where + N: Complex, + SB: Storage, + SC: Storage, + ShapeConstraint: DimEq + AreMultipliable, + { + self.xgemv(alpha, a, x, beta, |a, b| a.dotc(b)) + } + /// Computes `self = alpha * a.transpose() * x + beta * self`, where `a` is a matrix, `x` a vector, and /// `alpha, beta` two scalars. /// @@ -855,33 +792,17 @@ where } } -// FIXME: duplicate code impl> Matrix - where N: Complex + Zero + ClosedAdd + ClosedMul +where N: Scalar + Zero + ClosedAdd + ClosedMul { - /// Computes `self = alpha * x * y.transpose() + beta * self`. - /// - /// If `beta` is zero, `self` is never read. - /// - /// # Examples: - /// - /// ``` - /// # use nalgebra::{Matrix2x3, Vector2, Vector3}; - /// let mut mat = Matrix2x3::repeat(4.0); - /// let vec1 = Vector2::new(1.0, 2.0); - /// let vec2 = Vector3::new(0.1, 0.2, 0.3); - /// let expected = vec1 * vec2.transpose() * 10.0 + mat * 5.0; - /// - /// mat.ger(10.0, &vec1, &vec2, 5.0); - /// assert_eq!(mat, expected); - /// ``` - #[inline] - pub fn gerc( + #[inline(always)] + fn gerx( &mut self, alpha: N, x: &Vector, y: &Vector, beta: N, + conjugate: impl Fn(N) -> N, ) where N: One, SB: Storage, @@ -899,15 +820,11 @@ impl> Matrix for j in 0..ncols1 { // FIXME: avoid bound checks. - let val = unsafe { y.vget_unchecked(j).conjugate() }; + let val = unsafe { conjugate(*y.vget_unchecked(j)) }; self.column_mut(j).axpy(alpha * val, x, beta); } } -} -impl> Matrix -where N: Scalar + Zero + ClosedAdd + ClosedMul -{ /// Computes `self = alpha * x * y.transpose() + beta * self`. /// /// If `beta` is zero, `self` is never read. @@ -937,20 +854,39 @@ where N: Scalar + Zero + ClosedAdd + ClosedMul SC: Storage, ShapeConstraint: DimEq + DimEq, { - let (nrows1, ncols1) = self.shape(); - let dim2 = x.nrows(); - let dim3 = y.nrows(); + self.gerx(alpha, x, y, beta, |e| e) + } - assert!( - nrows1 == dim2 && ncols1 == dim3, - "ger: dimensions mismatch." - ); - - for j in 0..ncols1 { - // FIXME: avoid bound checks. - let val = unsafe { *y.vget_unchecked(j) }; - self.column_mut(j).axpy(alpha * val, x, beta); - } + /// Computes `self = alpha * x * y.transpose() + beta * self`. + /// + /// If `beta` is zero, `self` is never read. + /// + /// # Examples: + /// + /// ``` + /// # use nalgebra::{Matrix2x3, Vector2, Vector3}; + /// let mut mat = Matrix2x3::repeat(4.0); + /// let vec1 = Vector2::new(1.0, 2.0); + /// let vec2 = Vector3::new(0.1, 0.2, 0.3); + /// let expected = vec1 * vec2.transpose() * 10.0 + mat * 5.0; + /// + /// mat.ger(10.0, &vec1, &vec2, 5.0); + /// assert_eq!(mat, expected); + /// ``` + #[inline] + pub fn gerc( + &mut self, + alpha: N, + x: &Vector, + y: &Vector, + beta: N, + ) where + N: Complex, + SB: Storage, + SC: Storage, + ShapeConstraint: DimEq + DimEq, + { + self.gerx(alpha, x, y, beta, Complex::conjugate) } /// Computes `self = alpha * a * b + beta * self`, where `a, b, self` are matrices. @@ -1146,6 +1082,42 @@ where N: Scalar + Zero + ClosedAdd + ClosedMul impl> Matrix where N: Scalar + Zero + ClosedAdd + ClosedMul { + #[inline(always)] + fn sygerx( + &mut self, + alpha: N, + x: &Vector, + y: &Vector, + beta: N, + conjugate: impl Fn(N) -> N, + ) where + N: One, + SB: Storage, + SC: Storage, + ShapeConstraint: DimEq + DimEq, + { + let dim1 = self.nrows(); + let dim2 = x.nrows(); + let dim3 = y.nrows(); + + assert!( + self.is_square(), + "Symmetric ger: the input matrix must be square." + ); + assert!(dim1 == dim2 && dim1 == dim3, "ger: dimensions mismatch."); + + for j in 0..dim1 { + let val = unsafe { conjugate(*y.vget_unchecked(j)) }; + let subdim = Dynamic::new(dim1 - j); + // FIXME: avoid bound checks. + self.generic_slice_mut((j, j), (subdim, U1)).axpy( + alpha * val, + &x.rows_range(j..), + beta, + ); + } + } + /// Computes `self = alpha * x * y.transpose() + beta * self`, where `self` is a **symmetric** /// matrix. /// @@ -1166,6 +1138,7 @@ where N: Scalar + Zero + ClosedAdd + ClosedMul /// assert_eq!(mat.lower_triangle(), expected.lower_triangle()); /// assert_eq!(mat.m12, 99999.99999); // This was untouched. #[inline] + #[deprecated(note = "This is renamed `syger` to match the original BLAS terminology.")] pub fn ger_symm( &mut self, alpha: N, @@ -1178,26 +1151,77 @@ where N: Scalar + Zero + ClosedAdd + ClosedMul SC: Storage, ShapeConstraint: DimEq + DimEq, { - let dim1 = self.nrows(); - let dim2 = x.nrows(); - let dim3 = y.nrows(); + self.syger(alpha, x, y, beta) + } - assert!( - self.is_square(), - "Symmetric ger: the input matrix must be square." - ); - assert!(dim1 == dim2 && dim1 == dim3, "ger: dimensions mismatch."); + /// Computes `self = alpha * x * y.transpose() + beta * self`, where `self` is a **symmetric** + /// matrix. + /// + /// If `beta` is zero, `self` is never read. The result is symmetric. Only the lower-triangular + /// (including the diagonal) part of `self` is read/written. + /// + /// # Examples: + /// + /// ``` + /// # use nalgebra::{Matrix2, Vector2}; + /// let mut mat = Matrix2::identity(); + /// let vec1 = Vector2::new(1.0, 2.0); + /// let vec2 = Vector2::new(0.1, 0.2); + /// let expected = vec1 * vec2.transpose() * 10.0 + mat * 5.0; + /// mat.m12 = 99999.99999; // This component is on the upper-triangular part and will not be read/written. + /// + /// mat.ger_symm(10.0, &vec1, &vec2, 5.0); + /// assert_eq!(mat.lower_triangle(), expected.lower_triangle()); + /// assert_eq!(mat.m12, 99999.99999); // This was untouched. + #[inline] + pub fn syger( + &mut self, + alpha: N, + x: &Vector, + y: &Vector, + beta: N, + ) where + N: One, + SB: Storage, + SC: Storage, + ShapeConstraint: DimEq + DimEq, + { + self.sygerx(alpha, x, y, beta, |e| e) + } - for j in 0..dim1 { - let val = unsafe { *y.vget_unchecked(j) }; - let subdim = Dynamic::new(dim1 - j); - // FIXME: avoid bound checks. - self.generic_slice_mut((j, j), (subdim, U1)).axpy( - alpha * val, - &x.rows_range(j..), - beta, - ); - } + /// Computes `self = alpha * x * y.transpose() + beta * self`, where `self` is a **symmetric** + /// matrix. + /// + /// If `beta` is zero, `self` is never read. The result is symmetric. Only the lower-triangular + /// (including the diagonal) part of `self` is read/written. + /// + /// # Examples: + /// + /// ``` + /// # use nalgebra::{Matrix2, Vector2}; + /// let mut mat = Matrix2::identity(); + /// let vec1 = Vector2::new(1.0, 2.0); + /// let vec2 = Vector2::new(0.1, 0.2); + /// let expected = vec1 * vec2.transpose() * 10.0 + mat * 5.0; + /// mat.m12 = 99999.99999; // This component is on the upper-triangular part and will not be read/written. + /// + /// mat.ger_symm(10.0, &vec1, &vec2, 5.0); + /// assert_eq!(mat.lower_triangle(), expected.lower_triangle()); + /// assert_eq!(mat.m12, 99999.99999); // This was untouched. + #[inline] + pub fn hegerc( + &mut self, + alpha: N, + x: &Vector, + y: &Vector, + beta: N, + ) where + N: Complex, + SB: Storage, + SC: Storage, + ShapeConstraint: DimEq + DimEq, + { + self.sygerx(alpha, x, y, beta, Complex::conjugate) } } diff --git a/src/base/matrix.rs b/src/base/matrix.rs index 8f6c071a..6a89e945 100644 --- a/src/base/matrix.rs +++ b/src/base/matrix.rs @@ -914,9 +914,9 @@ impl> Matrix { } impl> Matrix { - /// Takes the conjugate and transposes `self` and store the result into `out`. + /// Takes the adjoint (aka. conjugate-transpose) of `self` and store the result into `out`. #[inline] - pub fn conjugate_transpose_to(&self, out: &mut Matrix) + pub fn adjoint_to(&self, out: &mut Matrix) where R2: Dim, C2: Dim, @@ -939,20 +939,41 @@ impl> Matrix { } } - /// The conjugate transposition of `self`. + /// The adjoint (aka. conjugate-transpose) of `self`. #[inline] - pub fn conjugate_transpose(&self) -> MatrixMN + pub fn adjoint(&self) -> MatrixMN where DefaultAllocator: Allocator { let (nrows, ncols) = self.data.shape(); unsafe { let mut res: MatrixMN<_, C, R> = Matrix::new_uninitialized_generic(ncols, nrows); - self.conjugate_transpose_to(&mut res); + self.adjoint_to(&mut res); res } } + /// Takes the conjugate and transposes `self` and store the result into `out`. + #[deprecated(note = "Renamed `self.adjoint_to(out)`.")] + #[inline] + pub fn conjugate_transpose_to(&self, out: &mut Matrix) + where + R2: Dim, + C2: Dim, + SB: StorageMut, + ShapeConstraint: SameNumberOfRows + SameNumberOfColumns, + { + self.adjoint_to(out) + } + + /// The conjugate transposition of `self`. + #[deprecated(note = "Renamed `self.adjoint()`.")] + #[inline] + pub fn conjugate_transpose(&self) -> MatrixMN + where DefaultAllocator: Allocator { + self.adjoint() + } + /// The conjugate of `self`. #[inline] pub fn conjugate(&self) -> MatrixMN @@ -1088,13 +1109,13 @@ impl> SquareMatrix { tr } - /// The hermitian part of `self`, i.e., `0.5 * (self + self.conjugate_transpose())`. + /// The hermitian part of `self`, i.e., `0.5 * (self + self.adjoint())`. #[inline] pub fn hermitian_part(&self) -> MatrixMN where DefaultAllocator: Allocator { assert!(self.is_square(), "Cannot compute the hermitian part of a non-square matrix."); - let mut tr = self.conjugate_transpose(); + let mut tr = self.adjoint(); tr += self; tr *= ::convert::<_, N>(0.5); tr @@ -1522,7 +1543,7 @@ impl> Matrix { SB: Storage, ShapeConstraint: DimEq + DimEq, { - let prod = self.cdot(other); + let prod = self.dotc(other); let n1 = self.norm(); let n2 = other.norm(); @@ -1593,7 +1614,7 @@ impl> Unit> { where DefaultAllocator: Allocator, { - let c_hang = self.cdot(rhs).real(); + let c_hang = self.dotc(rhs).real(); // self == other if c_hang.abs() >= N::Real::one() { diff --git a/src/base/matrix_alga.rs b/src/base/matrix_alga.rs index a2e1dd54..4d540f46 100644 --- a/src/base/matrix_alga.rs +++ b/src/base/matrix_alga.rs @@ -192,7 +192,7 @@ where DefaultAllocator: Allocator #[inline] fn inner_product(&self, other: &Self) -> N { - self.cdot(other) + self.dotc(other) } } diff --git a/src/base/norm.rs b/src/base/norm.rs index b3056067..2a50f4ec 100644 --- a/src/base/norm.rs +++ b/src/base/norm.rs @@ -33,7 +33,7 @@ impl Norm for EuclideanNorm { #[inline] fn norm(&self, m: &Matrix) -> N::Real where R: Dim, C: Dim, S: Storage { - m.cdot(m).real().sqrt() + m.dotc(m).real().sqrt() } #[inline] @@ -101,7 +101,7 @@ impl> Matrix { for i in 0..self.ncols() { let col = self.column(i); - res += col.cdot(&col).real() + res += col.dotc(&col).real() } res diff --git a/src/base/ops.rs b/src/base/ops.rs index bee584b6..f2a683c1 100644 --- a/src/base/ops.rs +++ b/src/base/ops.rs @@ -13,7 +13,7 @@ use base::constraint::{ }; use base::dimension::{Dim, DimMul, DimName, DimProd}; use base::storage::{ContiguousStorageMut, Storage, StorageMut}; -use base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, MatrixSum, Scalar}; +use base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, MatrixSum, Scalar, VectorSliceN}; /* * @@ -629,13 +629,28 @@ where res } - /// Equivalent to `self.transpose() * rhs` but stores the result into `out` to avoid - /// allocations. + /// Equivalent to `self.adjoint() * rhs`. #[inline] - pub fn tr_mul_to( + pub fn ad_mul(&self, rhs: &Matrix) -> MatrixMN + where + N: Complex, + SB: Storage, + DefaultAllocator: Allocator, + ShapeConstraint: SameNumberOfRows, + { + let mut res = + unsafe { Matrix::new_uninitialized_generic(self.data.shape().1, rhs.data.shape().1) }; + + self.ad_mul_to(rhs, &mut res); + res + } + + #[inline(always)] + fn xx_mul_to( &self, rhs: &Matrix, out: &mut Matrix, + dot: impl Fn(&VectorSliceN, &VectorSliceN) -> N, ) where SB: Storage, SC: StorageMut, @@ -656,12 +671,43 @@ where for i in 0..ncols1 { for j in 0..ncols2 { - let dot = self.column(i).dot(&rhs.column(j)); + let dot = dot(&self.column(i), &rhs.column(j)); unsafe { *out.get_unchecked_mut((i, j)) = dot }; } } } + /// Equivalent to `self.transpose() * rhs` but stores the result into `out` to avoid + /// allocations. + #[inline] + pub fn tr_mul_to( + &self, + rhs: &Matrix, + out: &mut Matrix, + ) where + SB: Storage, + SC: StorageMut, + ShapeConstraint: SameNumberOfRows + DimEq + DimEq, + { + self.xx_mul_to(rhs, out, |a, b| a.dot(b)) + } + + /// Equivalent to `self.adjoint() * rhs` but stores the result into `out` to avoid + /// allocations. + #[inline] + pub fn ad_mul_to( + &self, + rhs: &Matrix, + out: &mut Matrix, + ) where + N: Complex, + SB: Storage, + SC: StorageMut, + ShapeConstraint: SameNumberOfRows + DimEq + DimEq, + { + self.xx_mul_to(rhs, out, |a, b| a.dotc(b)) + } + /// Equivalent to `self * rhs` but stores the result into `out` to avoid allocations. #[inline] pub fn mul_to( @@ -760,35 +806,16 @@ where } } -// XXX: avoid code duplication. -impl> Matrix { - /// Returns the absolute value of the component with the largest absolute value. - #[inline] - pub fn camax(&self) -> N::Real { - let mut max = N::Real::zero(); +impl> Matrix { + #[inline(always)] + fn xcmp(&self, abs: impl Fn(N) -> N2, cmp: impl Fn(N2, N2) -> bool) -> N2 + where N2: Scalar + PartialOrd + Zero { + let mut max = N2::zero(); for e in self.iter() { - let ae = e.asum(); + let ae = abs(*e); - if ae > max { - max = ae; - } - } - - max - } -} - -impl> Matrix { - /// Returns the absolute value of the component with the largest absolute value. - #[inline] - pub fn amax(&self) -> N { - let mut max = N::zero(); - - for e in self.iter() { - let ae = e.abs(); - - if ae > max { + if cmp(ae, max) { max = ae; } } @@ -796,61 +823,45 @@ impl> Matri max } - /// Returns the absolute value of the component with the smallest absolute value. + /// Returns the absolute value of the component with the largest absolute value. #[inline] - pub fn amin(&self) -> N { - let mut it = self.iter(); - let mut min = it - .next() - .expect("amin: empty matrices not supported.") - .abs(); + pub fn amax(&self) -> N + where N: PartialOrd + Signed { + self.xcmp(|e| e.abs(), |a, b| a > b) + } - for e in it { - let ae = e.abs(); - - if ae < min { - min = ae; - } - } - - min + /// Returns the the 1-norm of the complex component with the largest 1-norm. + #[inline] + pub fn camax(&self) -> N::Real + where N: Complex { + self.xcmp(|e| e.norm1(), |a, b| a > b) } /// Returns the component with the largest value. #[inline] - pub fn max(&self) -> N { - let mut it = self.iter(); - let mut max = it - .next() - .expect("max: empty matrices not supported."); + pub fn max(&self) -> N + where N: PartialOrd + Signed { + self.xcmp(|e| e, |a, b| a > b) + } - for e in it { - let ae = e; + /// Returns the absolute value of the component with the smallest absolute value. + #[inline] + pub fn amin(&self) -> N + where N: PartialOrd + Signed { + self.xcmp(|e| e.abs(), |a, b| a < b) + } - if ae > max { - max = ae; - } - } - - *max + /// Returns the the 1-norm of the complex component with the smallest 1-norm. + #[inline] + pub fn camin(&self) -> N::Real + where N: Complex { + self.xcmp(|e| e.norm1(), |a, b| a < b) } /// Returns the component with the smallest value. #[inline] - pub fn min(&self) -> N { - let mut it = self.iter(); - let mut min = it - .next() - .expect("min: empty matrices not supported."); - - for e in it { - let ae = e; - - if ae < min { - min = ae; - } - } - - *min + pub fn min(&self) -> N + where N: PartialOrd + Signed { + self.xcmp(|e| e, |a, b| a < b) } -} +} \ No newline at end of file diff --git a/src/base/properties.rs b/src/base/properties.rs index a511c0f8..de6be72a 100644 --- a/src/base/properties.rs +++ b/src/base/properties.rs @@ -97,8 +97,7 @@ impl> Matrix { N::Epsilon: Copy, DefaultAllocator: Allocator + Allocator, { - // FIXME: add a conjugate-transpose-mul - (self.conjugate().tr_mul(self)).is_identity(eps) + (self.ad_mul(self)).is_identity(eps) } } diff --git a/src/debug/random_sdp.rs b/src/debug/random_sdp.rs index 772eccc9..f8ee6d30 100644 --- a/src/debug/random_sdp.rs +++ b/src/debug/random_sdp.rs @@ -31,7 +31,7 @@ where DefaultAllocator: Allocator /// random reals generators. pub fn new N>(dim: D, mut rand: Rand) -> Self { let mut m = RandomOrthogonal::new(dim, || rand()).unwrap(); - let mt = m.conjugate_transpose(); + let mt = m.adjoint(); for i in 0..dim.value() { let mut col = m.column_mut(i); diff --git a/src/geometry/reflection.rs b/src/geometry/reflection.rs index b3c77bd9..653a9bdc 100644 --- a/src/geometry/reflection.rs +++ b/src/geometry/reflection.rs @@ -35,7 +35,7 @@ impl> Reflection { D: DimName, DefaultAllocator: Allocator, { - let bias = axis.cdot(&pt.coords); + let bias = axis.dotc(&pt.coords); Self::new(axis, bias) } @@ -56,7 +56,7 @@ impl> Reflection { // dot product, and then mutably. Somehow, this allows significantly // better optimizations of the dot product from the compiler. let m_two: N = ::convert(-2.0f64); - let factor = (self.axis.cdot(&rhs.column(i)) - self.bias) * m_two; + let factor = (self.axis.dotc(&rhs.column(i)) - self.bias) * m_two; rhs.column_mut(i).axpy(factor, &self.axis, N::one()); } } @@ -73,7 +73,7 @@ impl> Reflection { // dot product, and then mutably. Somehow, this allows significantly // better optimizations of the dot product from the compiler. let m_two = sign.scale(::convert(-2.0f64)); - let factor = (self.axis.cdot(&rhs.column(i)) - self.bias) * m_two; + let factor = (self.axis.dotc(&rhs.column(i)) - self.bias) * m_two; rhs.column_mut(i).axpy(factor, &self.axis, sign); } } diff --git a/src/lib.rs b/src/lib.rs index a718cf91..c2bb04f2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -170,6 +170,7 @@ pub use alga::general::{Id, Real, Complex}; /// Gets the ubiquitous multiplicative identity element. /// /// Same as `Id::new()`. +#[deprecated(note = "use `Id::new()` instead.")] #[inline] pub fn id() -> Id { Id::new() @@ -416,6 +417,7 @@ pub fn partial_sort2<'a, T: PartialOrd>(a: &'a T, b: &'a T) -> Option<(&'a T, &' /// # 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() @@ -426,6 +428,7 @@ pub fn try_inverse(m: &M) -> Option { /// # 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() diff --git a/src/linalg/cholesky.rs b/src/linalg/cholesky.rs index 682bd990..d4973df1 100644 --- a/src/linalg/cholesky.rs +++ b/src/linalg/cholesky.rs @@ -121,7 +121,7 @@ where DefaultAllocator: Allocator ShapeConstraint: SameNumberOfRows, { let _ = self.chol.solve_lower_triangular_mut(b); - let _ = self.chol.conjugate().tr_solve_lower_triangular_mut(b); + let _ = self.chol.ad_solve_lower_triangular_mut(b); } /// Returns the solution of the system `self * x = b` where `self` is the decomposed matrix and diff --git a/src/linalg/mod.rs b/src/linalg/mod.rs index 6c7f7194..4418b283 100644 --- a/src/linalg/mod.rs +++ b/src/linalg/mod.rs @@ -30,6 +30,6 @@ pub use self::lu::*; pub use self::permutation_sequence::*; pub use self::qr::*; pub use self::schur::*; -//pub use self::svd::*; +pub use self::svd::*; pub use self::symmetric_eigen::*; pub use self::symmetric_tridiagonal::*; diff --git a/src/linalg/solve.rs b/src/linalg/solve.rs index b43b44df..fad85a81 100644 --- a/src/linalg/solve.rs +++ b/src/linalg/solve.rs @@ -4,7 +4,7 @@ use base::allocator::Allocator; use base::constraint::{SameNumberOfRows, ShapeConstraint}; use base::dimension::{Dim, U1}; use base::storage::{Storage, StorageMut}; -use base::{DefaultAllocator, Matrix, MatrixMN, SquareMatrix, Vector}; +use base::{DefaultAllocator, Matrix, MatrixMN, SquareMatrix, Vector, DVectorSlice}; impl> SquareMatrix { /// Computes the solution of the linear system `self . x = b` where `x` is the unknown and only @@ -180,10 +180,9 @@ impl> SquareMatrix { /* * - * Transpose versions + * Transpose and adjoint versions * */ - /// Computes the solution of the linear system `self.transpose() . x = b` where `x` is the unknown and only /// the lower-triangular part of `self` (including the diagonal) is considered not-zero. #[inline] @@ -191,10 +190,10 @@ impl> SquareMatrix { &self, b: &Matrix, ) -> Option> - where - S2: StorageMut, - DefaultAllocator: Allocator, - ShapeConstraint: SameNumberOfRows, + where + S2: StorageMut, + DefaultAllocator: Allocator, + ShapeConstraint: SameNumberOfRows, { let mut res = b.clone_owned(); if self.tr_solve_lower_triangular_mut(&mut res) { @@ -211,10 +210,10 @@ impl> SquareMatrix { &self, b: &Matrix, ) -> Option> - where - S2: StorageMut, - DefaultAllocator: Allocator, - ShapeConstraint: SameNumberOfRows, + where + S2: StorageMut, + DefaultAllocator: Allocator, + ShapeConstraint: SameNumberOfRows, { let mut res = b.clone_owned(); if self.tr_solve_upper_triangular_mut(&mut res) { @@ -230,14 +229,14 @@ 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.tr_solve_lower_triangular_vector_mut(&mut b.column_mut(i)) { + if !self.xx_solve_lower_triangular_vector_mut(&mut b.column_mut(i), |e| e, |a, b| a.dot(b)) { return false; } } @@ -245,46 +244,20 @@ impl> SquareMatrix { true } - fn tr_solve_lower_triangular_vector_mut(&self, b: &mut Vector) -> bool - where - S2: StorageMut, - ShapeConstraint: SameNumberOfRows, - { - let dim = self.nrows(); - - for i in (0..dim).rev() { - let dot = self.slice_range(i + 1.., i).dot(&b.slice_range(i + 1.., 0)); - - unsafe { - let b_i = b.vget_unchecked_mut(i); - - let diag = *self.get_unchecked((i, i)); - - if diag.is_zero() { - return false; - } - - *b_i = (*b_i - dot) / diag; - } - } - - true - } - /// Solves the linear system `self.transpose() . x = b` where `x` is the unknown and only the /// upper-triangular part of `self` (including the diagonal) is considered not-zero. pub fn tr_solve_upper_triangular_mut( &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.tr_solve_upper_triangular_vector_mut(&mut b.column_mut(i)) { + if !self.xx_solve_upper_triangular_vector_mut(&mut b.column_mut(i), |e| e, |a, b| a.dot(b)) { return false; } } @@ -292,19 +265,140 @@ impl> SquareMatrix { true } - fn tr_solve_upper_triangular_vector_mut(&self, b: &mut Vector) -> bool - where - S2: StorageMut, - ShapeConstraint: SameNumberOfRows, + /// Computes the solution of the linear system `self.adjoint() . x = b` where `x` is the unknown and only + /// the lower-triangular part of `self` (including the diagonal) is considered not-zero. + #[inline] + pub fn ad_solve_lower_triangular( + &self, + b: &Matrix, + ) -> Option> + where + S2: StorageMut, + DefaultAllocator: Allocator, + ShapeConstraint: SameNumberOfRows, + { + let mut res = b.clone_owned(); + if self.ad_solve_lower_triangular_mut(&mut res) { + Some(res) + } else { + None + } + } + + /// Computes the solution of the linear system `self.adjoint() . x = b` where `x` is the unknown and only + /// the upper-triangular part of `self` (including the diagonal) is considered not-zero. + #[inline] + pub fn ad_solve_upper_triangular( + &self, + b: &Matrix, + ) -> Option> + where + S2: StorageMut, + DefaultAllocator: Allocator, + ShapeConstraint: SameNumberOfRows, + { + let mut res = b.clone_owned(); + if self.ad_solve_upper_triangular_mut(&mut res) { + Some(res) + } else { + None + } + } + + /// Solves the linear system `self.adjoint() . x = b` where `x` is the unknown and only the + /// lower-triangular part of `self` (including the diagonal) is considered not-zero. + pub fn ad_solve_lower_triangular_mut( + &self, + b: &mut Matrix, + ) -> bool + 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)) { + return false; + } + } + + true + } + + /// Solves the linear system `self.adjoint() . x = b` where `x` is the unknown and only the + /// upper-triangular part of `self` (including the diagonal) is considered not-zero. + pub fn ad_solve_upper_triangular_mut( + &self, + b: &mut Matrix, + ) -> bool + 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)) { + return false; + } + } + + 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, + ) -> bool + where + S2: StorageMut, + ShapeConstraint: SameNumberOfRows, + { + let dim = self.nrows(); + + for i in (0..dim).rev() { + let dot = dot(&self.slice_range(i + 1.., i), &b.slice_range(i + 1.., 0)); + + unsafe { + let b_i = b.vget_unchecked_mut(i); + + let diag = conjugate(*self.get_unchecked((i, i))); + + if diag.is_zero() { + return false; + } + + *b_i = (*b_i - dot) / diag; + } + } + + true + } + + #[inline(always)] + fn xx_solve_upper_triangular_vector_mut( + &self, + b: &mut Vector, + conjugate: impl Fn(N) -> N, + dot: impl Fn(&DVectorSlice, &DVectorSlice) -> N, + ) -> bool + where + S2: StorageMut, + ShapeConstraint: SameNumberOfRows, { let dim = self.nrows(); for i in 0..dim { - let dot = self.slice_range(..i, i).dot(&b.slice_range(..i, 0)); + let dot = dot(&self.slice_range(..i, i), &b.slice_range(..i, 0)); unsafe { let b_i = b.vget_unchecked_mut(i); - let diag = *self.get_unchecked((i, i)); + let diag = conjugate(*self.get_unchecked((i, i))); if diag.is_zero() { return false; diff --git a/src/linalg/svd.rs b/src/linalg/svd.rs index a455badd..12ee0469 100644 --- a/src/linalg/svd.rs +++ b/src/linalg/svd.rs @@ -496,7 +496,7 @@ where } } - self.recompose().map(|m| m.conjugate_transpose()) + self.recompose().map(|m| m.adjoint()) } } @@ -521,7 +521,7 @@ where else { match (&self.u, &self.v_t) { (Some(u), Some(v_t)) => { - let mut ut_b = u.conjugate().tr_mul(b); + let mut ut_b = u.ad_mul(b); for j in 0..ut_b.ncols() { let mut col = ut_b.column_mut(j); @@ -536,7 +536,7 @@ where } } - Ok(v_t.conjugate().tr_mul(&ut_b)) + Ok(v_t.ad_mul(&ut_b)) } (None, None) => Err("SVD solve: U and V^t have not been computed."), (None, _) => Err("SVD solve: U has not been computed."), diff --git a/src/linalg/symmetric_tridiagonal.rs b/src/linalg/symmetric_tridiagonal.rs index 29451d31..d652ce4c 100644 --- a/src/linalg/symmetric_tridiagonal.rs +++ b/src/linalg/symmetric_tridiagonal.rs @@ -75,13 +75,13 @@ where DefaultAllocator: Allocator + Allocator> if not_zero { let mut p = p.rows_range_mut(i..); - p.cgemv_symm(::convert(2.0), &m, &axis, N::zero()); - let dot = axis.cdot(&p); + p.hegemv(::convert(2.0), &m, &axis, N::zero()); + let dot = axis.dotc(&p); // p.axpy(-dot, &axis.conjugate(), N::one()); - m.ger_symm(-N::one(), &p, &axis.conjugate(), N::one()); - m.ger_symm(-N::one(), &axis, &p.conjugate(), N::one()); - m.ger_symm(dot * ::convert(2.0), &axis, &axis.conjugate(), N::one()); + m.hegerc(-N::one(), &p, &axis, N::one()); + m.hegerc(-N::one(), &axis, &p, N::one()); + m.hegerc(dot * ::convert(2.0), &axis, &axis, N::one()); } } @@ -142,7 +142,7 @@ where DefaultAllocator: Allocator + Allocator> self.tri[(i, i + 1)] = val; } - &q * self.tri * q.conjugate_transpose() + &q * self.tri * q.adjoint() } } diff --git a/tests/core/blas.rs b/tests/core/blas.rs index 00eac3a3..38113c17 100644 --- a/tests/core/blas.rs +++ b/tests/core/blas.rs @@ -19,14 +19,14 @@ quickcheck! { let mut y2 = y1.clone(); y1.gemv(alpha, &a, &x, beta); - y2.gemv_symm(alpha, &a.lower_triangle(), &x, beta); + y2.sygemv(alpha, &a.lower_triangle(), &x, beta); if !relative_eq!(y1, y2, epsilon = 1.0e-10) { return false; } y1.gemv(alpha, &a, &x, 0.0); - y2.gemv_symm(alpha, &a.lower_triangle(), &x, 0.0); + y2.sygemv(alpha, &a.lower_triangle(), &x, 0.0); relative_eq!(y1, y2, epsilon = 1.0e-10) } @@ -61,14 +61,14 @@ quickcheck! { let y = DVector::new_random(n); a1.ger(alpha, &x, &y, beta); - a2.ger_symm(alpha, &x, &y, beta); + a2.syger(alpha, &x, &y, beta); if !relative_eq!(a1.lower_triangle(), a2) { return false; } a1.ger(alpha, &x, &y, 0.0); - a2.ger_symm(alpha, &x, &y, 0.0); + a2.syger(alpha, &x, &y, 0.0); relative_eq!(a1.lower_triangle(), a2) } diff --git a/tests/linalg/cholesky.rs b/tests/linalg/cholesky.rs index 5bc91dc2..774b76b0 100644 --- a/tests/linalg/cholesky.rs +++ b/tests/linalg/cholesky.rs @@ -16,7 +16,7 @@ macro_rules! gen_tests( fn cholesky(n: usize) -> bool { let m = RandomSDP::new(Dynamic::new(n.max(1).min(50)), || random::<$scalar>().0).unwrap(); let l = m.clone().cholesky().unwrap().unpack(); - relative_eq!(m, &l * l.conjugate_transpose(), epsilon = 1.0e-7) + relative_eq!(m, &l * l.adjoint(), epsilon = 1.0e-7) } fn cholesky_static(_m: RandomSDP) -> bool { @@ -24,7 +24,7 @@ macro_rules! gen_tests( let chol = m.cholesky().unwrap(); let l = chol.unpack(); - if !relative_eq!(m, &l * l.conjugate_transpose(), epsilon = 1.0e-7) { + if !relative_eq!(m, &l * l.adjoint(), epsilon = 1.0e-7) { false } else { diff --git a/tests/linalg/hessenberg.rs b/tests/linalg/hessenberg.rs index dfabd29d..03cba7d1 100644 --- a/tests/linalg/hessenberg.rs +++ b/tests/linalg/hessenberg.rs @@ -27,21 +27,21 @@ macro_rules! gen_tests( let hess = m.clone().hessenberg(); let (p, h) = hess.unpack(); - relative_eq!(m, &p * h * p.conjugate_transpose(), epsilon = 1.0e-7) + relative_eq!(m, &p * h * p.adjoint(), epsilon = 1.0e-7) } fn hessenberg_static_mat2(m: Matrix2<$scalar>) -> bool { let m = m.map(|e| e.0); let hess = m.hessenberg(); let (p, h) = hess.unpack(); - relative_eq!(m, p * h * p.conjugate_transpose(), epsilon = 1.0e-7) + relative_eq!(m, p * h * p.adjoint(), epsilon = 1.0e-7) } fn hessenberg_static(m: Matrix4<$scalar>) -> bool { let m = m.map(|e| e.0); let hess = m.hessenberg(); let (p, h) = hess.unpack(); - relative_eq!(m, p * h * p.conjugate_transpose(), epsilon = 1.0e-7) + relative_eq!(m, p * h * p.adjoint(), epsilon = 1.0e-7) } } } diff --git a/tests/linalg/schur.rs b/tests/linalg/schur.rs index 16767c94..f607ce06 100644 --- a/tests/linalg/schur.rs +++ b/tests/linalg/schur.rs @@ -31,21 +31,21 @@ mod quickcheck_tests { let (vecs, vals) = m.clone().schur().unpack(); - if !relative_eq!(&vecs * &vals * vecs.conjugate_transpose(), m, epsilon = 1.0e-7) { - println!("{:.5}{:.5}", m, &vecs * &vals * vecs.conjugate_transpose()); + if !relative_eq!(&vecs * &vals * vecs.adjoint(), m, epsilon = 1.0e-7) { + println!("{:.5}{:.5}", m, &vecs * &vals * vecs.adjoint()); } - relative_eq!(&vecs * vals * vecs.conjugate_transpose(), m, epsilon = 1.0e-7) + relative_eq!(&vecs * vals * vecs.adjoint(), m, epsilon = 1.0e-7) } fn schur_static_mat2(m: Matrix2<$scalar>) -> bool { let m = m.map(|e| e.0); let (vecs, vals) = m.clone().schur().unpack(); - let ok = relative_eq!(vecs * vals * vecs.conjugate_transpose(), m, epsilon = 1.0e-7); + let ok = relative_eq!(vecs * vals * vecs.adjoint(), m, epsilon = 1.0e-7); if !ok { println!("Vecs: {:.5} Vals: {:.5}", vecs, vals); - println!("Reconstruction:{}{}", m, &vecs * &vals * vecs.conjugate_transpose()); + println!("Reconstruction:{}{}", m, &vecs * &vals * vecs.adjoint()); } ok } @@ -54,10 +54,10 @@ mod quickcheck_tests { let m = m.map(|e| e.0); let (vecs, vals) = m.clone().schur().unpack(); - let ok = relative_eq!(vecs * vals * vecs.conjugate_transpose(), m, epsilon = 1.0e-7); + let ok = relative_eq!(vecs * vals * vecs.adjoint(), m, epsilon = 1.0e-7); if !ok { println!("Vecs: {:.5} Vals: {:.5}", vecs, vals); - println!("{:.5}{:.5}", m, &vecs * &vals * vecs.conjugate_transpose()); + println!("{:.5}{:.5}", m, &vecs * &vals * vecs.adjoint()); } ok } @@ -66,9 +66,9 @@ mod quickcheck_tests { let m = m.map(|e| e.0); let (vecs, vals) = m.clone().schur().unpack(); - let ok = relative_eq!(vecs * vals * vecs.conjugate_transpose(), m, epsilon = 1.0e-7); + let ok = relative_eq!(vecs * vals * vecs.adjoint(), m, epsilon = 1.0e-7); if !ok { - println!("{:.5}{:.5}", m, &vecs * &vals * vecs.conjugate_transpose()); + println!("{:.5}{:.5}", m, &vecs * &vals * vecs.adjoint()); } ok diff --git a/tests/linalg/solve.rs b/tests/linalg/solve.rs index e2f8a3f8..3a9ff143 100644 --- a/tests/linalg/solve.rs +++ b/tests/linalg/solve.rs @@ -10,7 +10,7 @@ macro_rules! gen_tests( fn unzero_diagonal(a: &mut Matrix4) { for i in 0..4 { - if a[(i, i)].asum() < na::convert(1.0e-7) { + if a[(i, i)].norm1() < na::convert(1.0e-7) { a[(i, i)] = N::one(); } } From ce24ea972ef51d0319b3e0b08c39716d8ab4c1f9 Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sat, 23 Mar 2019 14:13:00 +0100 Subject: [PATCH 12/28] Remove all spurious allocation introduced by complex number support on decompositions. --- nalgebra-lapack/src/lu.rs | 2 +- src/base/blas.rs | 12 +++--- src/base/edition.rs | 23 ++++++++-- src/base/matrix.rs | 37 +++++++++------- src/base/matrix_alga.rs | 2 +- src/base/norm.rs | 14 ++++--- src/geometry/reflection.rs | 4 +- src/geometry/unit_complex_ops.rs | 65 ++--------------------------- src/linalg/bidiagonal.rs | 10 +---- src/linalg/cholesky.rs | 3 +- src/linalg/hessenberg.rs | 13 +++--- src/linalg/qr.rs | 8 +--- src/linalg/schur.rs | 8 ++-- src/linalg/svd.rs | 10 ++--- src/linalg/symmetric_eigen.rs | 8 ++-- src/linalg/symmetric_tridiagonal.rs | 3 +- 16 files changed, 87 insertions(+), 135 deletions(-) diff --git a/nalgebra-lapack/src/lu.rs b/nalgebra-lapack/src/lu.rs index dc21c12b..21fdfb41 100644 --- a/nalgebra-lapack/src/lu.rs +++ b/nalgebra-lapack/src/lu.rs @@ -253,7 +253,7 @@ where /// be determined. /// /// Returns `false` if no solution was found (the decomposed matrix is singular). - pub fn solve_conjugate_transpose_mut( + pub fn solve_adjoint_mut( &self, b: &mut MatrixMN, ) -> bool diff --git a/src/base/blas.rs b/src/base/blas.rs index 210db8cd..9f919e11 100644 --- a/src/base/blas.rs +++ b/src/base/blas.rs @@ -585,7 +585,7 @@ where a: &SquareMatrix, x: &Vector, beta: N, - dotc: impl Fn(&DVectorSlice, &DVectorSlice) -> N, + dot: impl Fn(&DVectorSlice, &DVectorSlice) -> N, ) where N: One, SB: Storage, @@ -613,11 +613,11 @@ where let col2 = a.column(0); let val = unsafe { *x.vget_unchecked(0) }; self.axpy(alpha * val, &col2, beta); - self[0] += alpha * dotc(&a.slice_range(1.., 0), &x.rows_range(1..)); + self[0] += alpha * dot(&a.slice_range(1.., 0), &x.rows_range(1..)); for j in 1..dim2 { let col2 = a.column(j); - let dot = dotc(&col2.rows_range(j..), &x.rows_range(j..)); + let dot = dot(&col2.rows_range(j..), &x.rows_range(j..)); let val; unsafe { @@ -1083,7 +1083,7 @@ impl> Matrix where N: Scalar + Zero + ClosedAdd + ClosedMul { #[inline(always)] - fn sygerx( + fn xxgerx( &mut self, alpha: N, x: &Vector, @@ -1186,7 +1186,7 @@ where N: Scalar + Zero + ClosedAdd + ClosedMul SC: Storage, ShapeConstraint: DimEq + DimEq, { - self.sygerx(alpha, x, y, beta, |e| e) + self.xxgerx(alpha, x, y, beta, |e| e) } /// Computes `self = alpha * x * y.transpose() + beta * self`, where `self` is a **symmetric** @@ -1221,7 +1221,7 @@ where N: Scalar + Zero + ClosedAdd + ClosedMul SC: Storage, ShapeConstraint: DimEq + DimEq, { - self.sygerx(alpha, x, y, beta, Complex::conjugate) + self.xxgerx(alpha, x, y, beta, Complex::conjugate) } } diff --git a/src/base/edition.rs b/src/base/edition.rs index 32e2c1aa..b95e0fcf 100644 --- a/src/base/edition.rs +++ b/src/base/edition.rs @@ -137,10 +137,10 @@ impl> Matrix { /// Fills the diagonal of this matrix with the content of the given vector. #[inline] pub fn set_diagonal(&mut self, diag: &Vector) - where - R: DimMin, - S2: Storage, - ShapeConstraint: DimEq, R2>, + where + R: DimMin, + S2: Storage, + ShapeConstraint: DimEq, R2>, { let (nrows, ncols) = self.shape(); let min_nrows_ncols = cmp::min(nrows, ncols); @@ -151,6 +151,21 @@ impl> Matrix { } } + /// Fills the diagonal of this matrix with the content of the given iterator. + /// + /// This will fill as many diagonal elements as the iterator yields, up to the + /// minimum of the number of rows and columns of `self`, and starting with the + /// diagonal element at index (0, 0). + #[inline] + pub fn set_partial_diagonal(&mut self, diag: impl Iterator) { + let (nrows, ncols) = self.shape(); + let min_nrows_ncols = cmp::min(nrows, ncols); + + for (i, val) in diag.enumerate().take(min_nrows_ncols) { + unsafe { *self.get_unchecked_mut((i, i)) = val } + } + } + /// Fills the selected row of this matrix with the content of the given vector. #[inline] pub fn set_row(&mut self, i: usize, row: &RowVector) diff --git a/src/base/matrix.rs b/src/base/matrix.rs index 6a89e945..77d49f42 100644 --- a/src/base/matrix.rs +++ b/src/base/matrix.rs @@ -981,14 +981,14 @@ impl> Matrix { self.map(|e| e.conjugate()) } - /// Divides each component of `self` by the given real. + /// Divides each component of the complex matrix `self` by the given real. #[inline] pub fn unscale(&self, real: N::Real) -> MatrixMN where DefaultAllocator: Allocator { self.map(|e| e.unscale(real)) } - /// Multiplies each component of `self` by the given real. + /// Multiplies each component of the complex matrix `self` by the given real. #[inline] pub fn scale(&self, real: N::Real) -> MatrixMN where DefaultAllocator: Allocator { @@ -997,19 +997,19 @@ impl> Matrix { } impl> Matrix { - /// The conjugate of `self` computed in-place. + /// The conjugate of the complex matrix `self` computed in-place. #[inline] pub fn conjugate_mut(&mut self) { self.apply(|e| e.conjugate()) } - /// Divides each component of `self` by the given real. + /// Divides each component of the complex matrix `self` by the given real. #[inline] pub fn unscale_mut(&mut self, real: N::Real) { self.apply(|e| e.unscale(real)) } - /// Multiplies each component of `self` by the given real. + /// Multiplies each component of the complex matrix `self` by the given real. #[inline] pub fn scale_mut(&mut self, real: N::Real) { self.apply(|e| e.scale(real)) @@ -1017,8 +1017,14 @@ impl> Matrix { } impl> Matrix { - /// Sets `self` to its conjugate transpose. - pub fn conjugate_transpose_mut(&mut self) { + /// Sets `self` to its adjoint. + #[deprecated(note = "Renamed to `self.adjoint_mut()`.")] + pub fn conjugate_transform_mut(&mut self) { + self.adjoint_mut() + } + + /// Sets `self` to its adjoint (aka. conjugate-transpose). + pub fn adjoint_mut(&mut self) { assert!( self.is_square(), "Unable to transpose a non-square matrix in-place." @@ -1027,11 +1033,6 @@ impl> Matrix { let dim = self.shape().0; for i in 0..dim { - { - let diag = unsafe { self.get_unchecked_mut((i, i)) }; - *diag = diag.conjugate(); - } - for j in 0..i { unsafe { let ref_ij = self.get_unchecked_mut((i, j)) as *mut N; @@ -1042,6 +1043,11 @@ impl> Matrix { *ref_ji = conj_ij; } } + + { + let diag = unsafe { self.get_unchecked_mut((i, i)) }; + *diag = diag.conjugate(); + } } } } @@ -1614,10 +1620,10 @@ impl> Unit> { where DefaultAllocator: Allocator, { - let c_hang = self.dotc(rhs).real(); + let (c_hang, c_hang_sign) = self.dotc(rhs).to_exp(); // self == other - if c_hang.abs() >= N::Real::one() { + if c_hang >= N::Real::one() { return Some(Unit::new_unchecked(self.clone_owned())); } @@ -1630,7 +1636,8 @@ impl> Unit> { } else { let ta = ((N::Real::one() - t) * hang).sin() / s_hang; let tb = (t * hang).sin() / s_hang; - let res = &**self * N::from_real(ta) + &**rhs * N::from_real(tb); + let mut res = self.scale(ta); + res.axpy(c_hang_sign.scale(tb), &**rhs, N::one()); Some(Unit::new_unchecked(res)) } diff --git a/src/base/matrix_alga.rs b/src/base/matrix_alga.rs index 4d540f46..43774f17 100644 --- a/src/base/matrix_alga.rs +++ b/src/base/matrix_alga.rs @@ -269,7 +269,7 @@ where DefaultAllocator: Allocator let v = &vs[0]; let mut a; - if v[0].modulus() > v[1].modulus() { + 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]]); diff --git a/src/base/norm.rs b/src/base/norm.rs index 2a50f4ec..b3d695e6 100644 --- a/src/base/norm.rs +++ b/src/base/norm.rs @@ -33,7 +33,7 @@ impl Norm for EuclideanNorm { #[inline] fn norm(&self, m: &Matrix) -> N::Real where R: Dim, C: Dim, S: Storage { - m.dotc(m).real().sqrt() + m.norm_squared().sqrt() } #[inline] @@ -43,7 +43,7 @@ impl Norm for EuclideanNorm { ShapeConstraint: SameNumberOfRows + SameNumberOfColumns { m1.zip_fold(m2, N::Real::zero(), |acc, a, b| { let diff = a - b; - acc + (diff.conjugate() * diff).real() + acc + diff.modulus_squared() }).sqrt() } } @@ -73,6 +73,8 @@ impl Norm for UniformNorm { #[inline] fn norm(&self, m: &Matrix) -> N::Real where R: Dim, C: Dim, S: Storage { + // NOTE: we don't use `m.amax()` here because for the complex + // numbers this will return the max norm1 instead of the modulus. m.fold(N::Real::zero(), |acc, a| acc.max(a.modulus())) } @@ -187,7 +189,7 @@ impl> Matrix { #[inline] pub fn normalize(&self) -> MatrixMN where DefaultAllocator: Allocator { - self.map(|e| e.unscale(self.norm())) + self.unscale(self.norm()) } /// Returns a normalized version of this matrix unless its norm as smaller or equal to `eps`. @@ -199,7 +201,7 @@ impl> Matrix { if n <= min_norm { None } else { - Some(self.map(|e| e.unscale(n))) + Some(self.unscale(n)) } } @@ -216,7 +218,7 @@ impl> Matrix { #[inline] pub fn normalize_mut(&mut self) -> N::Real { let n = self.norm(); - self.apply(|e| e.unscale(n)); + self.unscale_mut(n); n } @@ -231,7 +233,7 @@ impl> Matrix { if n <= min_norm { None } else { - self.apply(|e| e.unscale(n)); + self.unscale_mut(n); Some(n) } } diff --git a/src/geometry/reflection.rs b/src/geometry/reflection.rs index 653a9bdc..45e6381c 100644 --- a/src/geometry/reflection.rs +++ b/src/geometry/reflection.rs @@ -96,7 +96,7 @@ impl> Reflection { } let m_two: N = ::convert(-2.0f64); - lhs.ger(m_two, &work, &self.axis.conjugate(), N::one()); + lhs.gerc(m_two, &work, &self.axis, N::one()); } /// Applies the reflection to the rows of `lhs`. @@ -118,6 +118,6 @@ impl> Reflection { } let m_two = sign.scale(::convert(-2.0f64)); - lhs.ger(m_two, &work, &self.axis.conjugate(), sign); + lhs.gerc(m_two, &work, &self.axis, sign); } } diff --git a/src/geometry/unit_complex_ops.rs b/src/geometry/unit_complex_ops.rs index 75b45eda..28c9a9c3 100644 --- a/src/geometry/unit_complex_ops.rs +++ b/src/geometry/unit_complex_ops.rs @@ -2,10 +2,9 @@ use std::ops::{Div, DivAssign, Mul, MulAssign}; use alga::general::Real; use base::allocator::Allocator; -use base::constraint::{DimEq, ShapeConstraint}; -use base::dimension::{Dim, U1, U2}; -use base::storage::{Storage, StorageMut}; -use base::{DefaultAllocator, Matrix, Unit, Vector, Vector2}; +use base::dimension::{U1, U2}; +use base::storage::Storage; +use base::{DefaultAllocator, Unit, Vector, Vector2}; use geometry::{Isometry, Point2, Rotation, Similarity, Translation, UnitComplex}; /* @@ -404,60 +403,4 @@ where DefaultAllocator: Allocator fn div_assign(&mut self, rhs: &'b UnitComplex) { self.div_assign(rhs.to_rotation_matrix()) } -} - -// Matrix = UnitComplex * Matrix -impl UnitComplex { - /// Performs the multiplication `rhs = self * rhs` in-place. - pub fn rotate>( - &self, - rhs: &mut Matrix, - ) where - ShapeConstraint: DimEq, - { - assert_eq!( - rhs.nrows(), - 2, - "Unit complex rotation: the input matrix must have exactly two rows." - ); - let i = self.as_ref().im; - let r = self.as_ref().re; - - for j in 0..rhs.ncols() { - unsafe { - let a = *rhs.get_unchecked((0, j)); - let b = *rhs.get_unchecked((1, j)); - - *rhs.get_unchecked_mut((0, j)) = r * a - i * b; - *rhs.get_unchecked_mut((1, j)) = i * a + r * b; - } - } - } - - /// Performs the multiplication `lhs = lhs * self` in-place. - pub fn rotate_rows>( - &self, - lhs: &mut Matrix, - ) where - ShapeConstraint: DimEq, - { - assert_eq!( - lhs.ncols(), - 2, - "Unit complex rotation: the input matrix must have exactly two columns." - ); - let i = self.as_ref().im; - let r = self.as_ref().re; - - // FIXME: can we optimize that to iterate on one column at a time ? - for j in 0..lhs.nrows() { - unsafe { - let a = *lhs.get_unchecked((j, 0)); - let b = *lhs.get_unchecked((j, 1)); - - *lhs.get_unchecked_mut((j, 0)) = r * a + i * b; - *lhs.get_unchecked_mut((j, 1)) = -i * a + r * b; - } - } - } -} +} \ No newline at end of file diff --git a/src/linalg/bidiagonal.rs b/src/linalg/bidiagonal.rs index 7de0b887..9bf3cd12 100644 --- a/src/linalg/bidiagonal.rs +++ b/src/linalg/bidiagonal.rs @@ -179,9 +179,6 @@ where DefaultAllocator: Allocator, DimMinimum> + Allocator> + Allocator, C>, - // FIXME: the following bounds are ugly. - DimMinimum: DimMin, Output = DimMinimum>, - ShapeConstraint: DimEq, U1>>, { // FIXME: optimize by calling a reallocator. (self.u(), self.d(), self.v_t()) @@ -192,19 +189,16 @@ where pub fn d(&self) -> MatrixN> where DefaultAllocator: Allocator, DimMinimum>, - // FIXME: the following bounds are ugly. - DimMinimum: DimMin, Output = DimMinimum>, - ShapeConstraint: DimEq, U1>>, { let (nrows, ncols) = self.uv.data.shape(); let d = nrows.min(ncols); let mut res = MatrixN::identity_generic(d, d); - res.set_diagonal(&self.diagonal.map(|e| N::from_real(e.modulus()))); + res.set_partial_diagonal(self.diagonal.iter().map(|e| N::from_real(e.modulus()))); let start = self.axis_shift(); res.slice_mut(start, (d.value() - 1, d.value() - 1)) - .set_diagonal(&self.off_diagonal.map(|e| N::from_real(e.modulus()))); + .set_partial_diagonal(self.off_diagonal.iter().map(|e| N::from_real(e.modulus()))); res } diff --git a/src/linalg/cholesky.rs b/src/linalg/cholesky.rs index d4973df1..4ffacc97 100644 --- a/src/linalg/cholesky.rs +++ b/src/linalg/cholesky.rs @@ -70,11 +70,12 @@ where DefaultAllocator: Allocator let mut col = matrix.slice_range_mut(j + 1.., j); col /= denom; - continue; } } + // The diagonal element is either zero or its square root could not + // be taken (e.g. for negative real numbers). return None; } diff --git a/src/linalg/hessenberg.rs b/src/linalg/hessenberg.rs index a73ee5b5..bde3d325 100644 --- a/src/linalg/hessenberg.rs +++ b/src/linalg/hessenberg.rs @@ -92,8 +92,7 @@ where DefaultAllocator: Allocator + Allocator + Allocator (MatrixN, MatrixN) - where ShapeConstraint: DimEq> { + pub fn unpack(self) -> (MatrixN, MatrixN) { let q = self.q(); (q, self.unpack_h()) @@ -101,13 +100,12 @@ where DefaultAllocator: Allocator + Allocator + Allocator MatrixN - where ShapeConstraint: DimEq> { + pub fn unpack_h(mut self) -> MatrixN { let dim = self.hess.nrows(); self.hess.fill_lower_triangle(N::zero(), 2); self.hess .slice_mut((1, 0), (dim - 1, dim - 1)) - .set_diagonal(&self.subdiag.map(|e| N::from_real(e.modulus()))); + .set_partial_diagonal(self.subdiag.iter().map(|e| N::from_real(e.modulus()))); self.hess } @@ -116,13 +114,12 @@ where DefaultAllocator: Allocator + Allocator + Allocator MatrixN - where ShapeConstraint: DimEq> { + pub fn h(&self) -> MatrixN { let dim = self.hess.nrows(); let mut res = self.hess.clone(); res.fill_lower_triangle(N::zero(), 2); res.slice_mut((1, 0), (dim - 1, dim - 1)) - .set_diagonal(&self.subdiag.map(|e| N::from_real(e.modulus()))); + .set_partial_diagonal(self.subdiag.iter().map(|e| N::from_real(e.modulus()))); res } diff --git a/src/linalg/qr.rs b/src/linalg/qr.rs index e48c057c..12e72463 100644 --- a/src/linalg/qr.rs +++ b/src/linalg/qr.rs @@ -79,12 +79,10 @@ where DefaultAllocator: Allocator + Allocator + Allocator MatrixMN, C> where DefaultAllocator: Allocator, C>, - // FIXME: the following bound is ugly. - DimMinimum: DimMin>, { let (nrows, ncols) = self.qr.data.shape(); let mut res = self.qr.rows_generic(0, nrows.min(ncols)).upper_triangle(); - res.set_diagonal(&self.diag.map(|e| N::from_real(e.modulus()))); + res.set_partial_diagonal(self.diag.iter().map(|e| N::from_real(e.modulus()))); res } @@ -95,13 +93,11 @@ where DefaultAllocator: Allocator + Allocator + Allocator MatrixMN, C> where DefaultAllocator: Reallocator, C>, - // FIXME: the following bound is ugly (needed by `set_diagonal`). - DimMinimum: DimMin>, { 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); - res.set_diagonal(&self.diag.map(|e| N::from_real(e.modulus()))); + res.set_partial_diagonal(self.diag.iter().map(|e| N::from_real(e.modulus()))); res } diff --git a/src/linalg/schur.rs b/src/linalg/schur.rs index 9c877d92..a6521f72 100644 --- a/src/linalg/schur.rs +++ b/src/linalg/schur.rs @@ -52,7 +52,6 @@ where impl Schur where D: DimSub, // For Hessenberg. - ShapeConstraint: DimEq>, // For Hessenberg. DefaultAllocator: Allocator> + Allocator> + Allocator @@ -341,7 +340,7 @@ where while n > 0 { let m = n - 1; - if t[(n, m)].modulus() <= eps * (t[(n, n)].modulus() + t[(m, m)].modulus()) { + if t[(n, m)].norm1() <= eps * (t[(n, n)].norm1() + t[(m, m)].norm1()) { t[(n, m)] = N::zero(); } else { break; @@ -360,7 +359,7 @@ where let off_diag = t[(new_start, m)]; if off_diag.is_zero() - || off_diag.modulus() <= eps * (t[(new_start, new_start)].modulus() + t[(m, m)].modulus()) + || off_diag.norm1() <= eps * (t[(new_start, new_start)].norm1() + t[(m, m)].norm1()) { t[(new_start, m)] = N::zero(); break; @@ -479,7 +478,7 @@ fn compute_2x2_basis>( // NOTE: Choose the one that yields a larger x component. // This is necessary for numerical stability of the normalization of the complex // number. - if x1.modulus() > x2.modulus() { + if x1.norm1() > x2.norm1() { Some(GivensRotation::new(x1, h10).0) } else { Some(GivensRotation::new(x2, h10).0) @@ -492,7 +491,6 @@ fn compute_2x2_basis>( impl> SquareMatrix where D: DimSub, // For Hessenberg. - ShapeConstraint: DimEq>, // For Hessenberg. DefaultAllocator: Allocator> + Allocator> + Allocator diff --git a/src/linalg/svd.rs b/src/linalg/svd.rs index 12ee0469..0b5d0509 100644 --- a/src/linalg/svd.rs +++ b/src/linalg/svd.rs @@ -316,17 +316,17 @@ where let m = n - 1; if off_diagonal[m].is_zero() - || off_diagonal[m].modulus() <= eps * (diagonal[n].modulus() + diagonal[m].modulus()) + || off_diagonal[m].norm1() <= eps * (diagonal[n].norm1() + diagonal[m].norm1()) { off_diagonal[m] = N::Real::zero(); - } else if diagonal[m].modulus() <= eps { + } else if diagonal[m].norm1() <= eps { diagonal[m] = N::Real::zero(); 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); } - } else if diagonal[n].modulus() <= eps { + } else if diagonal[n].norm1() <= eps { diagonal[n] = N::Real::zero(); Self::cancel_vertical_off_diagonal_elt(diagonal, off_diagonal, u, v_t, is_upper_diagonal, m); } else { @@ -344,13 +344,13 @@ where while new_start > 0 { let m = new_start - 1; - if off_diagonal[m].modulus() <= eps * (diagonal[new_start].modulus() + diagonal[m].modulus()) + if off_diagonal[m].norm1() <= eps * (diagonal[new_start].norm1() + diagonal[m].norm1()) { off_diagonal[m] = N::Real::zero(); break; } // FIXME: write a test that enters this case. - else if diagonal[m].modulus() <= eps { + else if diagonal[m].norm1() <= eps { diagonal[m] = N::Real::zero(); Self::cancel_horizontal_off_diagonal_elt(diagonal, off_diagonal, u, v_t, is_upper_diagonal, m, n); diff --git a/src/linalg/symmetric_eigen.rs b/src/linalg/symmetric_eigen.rs index 87b08dc2..acdf956e 100644 --- a/src/linalg/symmetric_eigen.rs +++ b/src/linalg/symmetric_eigen.rs @@ -184,7 +184,7 @@ where DefaultAllocator: Allocator + Allocator } } - if off_diag[m].modulus() <= eps * (diag[m].modulus() + diag[n].modulus()) { + if off_diag[m].norm1() <= eps * (diag[m].norm1() + diag[n].norm1()) { end -= 1; } } else if subdim == 2 { @@ -240,7 +240,7 @@ where DefaultAllocator: Allocator + Allocator while n > 0 { let m = n - 1; - if off_diag[m].modulus() > eps * (diag[n].modulus() + diag[m].modulus()) { + if off_diag[m].norm1() > eps * (diag[n].norm1() + diag[m].norm1()) { break; } @@ -256,7 +256,7 @@ where DefaultAllocator: Allocator + Allocator let m = new_start - 1; if off_diag[m].is_zero() - || off_diag[m].modulus() <= eps * (diag[new_start].modulus() + diag[m].modulus()) + || off_diag[m].norm1() <= eps * (diag[new_start].norm1() + diag[m].norm1()) { off_diag[m] = N::Real::zero(); break; @@ -277,7 +277,7 @@ where DefaultAllocator: Allocator + Allocator let val = self.eigenvalues[i]; u_t.column_mut(i).scale_mut(val); } - u_t.conjugate_transpose_mut(); + u_t.adjoint_mut(); &self.eigenvectors * u_t } } diff --git a/src/linalg/symmetric_tridiagonal.rs b/src/linalg/symmetric_tridiagonal.rs index d652ce4c..76267554 100644 --- a/src/linalg/symmetric_tridiagonal.rs +++ b/src/linalg/symmetric_tridiagonal.rs @@ -76,9 +76,8 @@ where DefaultAllocator: Allocator + Allocator> let mut p = p.rows_range_mut(i..); p.hegemv(::convert(2.0), &m, &axis, N::zero()); - let dot = axis.dotc(&p); -// p.axpy(-dot, &axis.conjugate(), N::one()); + let dot = axis.dotc(&p); m.hegerc(-N::one(), &p, &axis, N::one()); m.hegerc(-N::one(), &axis, &p, N::one()); m.hegerc(dot * ::convert(2.0), &axis, &axis, N::one()); From 3cbe60523a126e6ae3321f8ee1f4ead8f6f1e370 Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sat, 23 Mar 2019 14:29:07 +0100 Subject: [PATCH 13/28] 2018 edition. --- Cargo.toml | 1 + benches/linalg/schur.rs | 12 +++--- benches/linalg/svd.rs | 24 ++++++------ benches/linalg/symmetric_eigen.rs | 6 +-- nalgebra-glm/Cargo.toml | 1 + nalgebra-glm/src/common.rs | 4 +- nalgebra-glm/src/constructors.rs | 2 +- nalgebra-glm/src/exponential.rs | 4 +- nalgebra-glm/src/ext/matrix_clip_space.rs | 30 +++++++-------- nalgebra-glm/src/ext/matrix_projection.rs | 2 +- nalgebra-glm/src/ext/matrix_relationnal.rs | 4 +- nalgebra-glm/src/ext/matrix_transform.rs | 4 +- nalgebra-glm/src/ext/quaternion_common.rs | 2 +- nalgebra-glm/src/ext/quaternion_geometric.rs | 2 +- nalgebra-glm/src/ext/quaternion_relational.rs | 10 ++--- nalgebra-glm/src/ext/quaternion_transform.rs | 2 +- .../src/ext/quaternion_trigonometric.rs | 2 +- nalgebra-glm/src/ext/scalar_common.rs | 2 +- nalgebra-glm/src/ext/vector_common.rs | 4 +- nalgebra-glm/src/ext/vector_relational.rs | 4 +- nalgebra-glm/src/geometric.rs | 4 +- nalgebra-glm/src/gtc/bitfield.rs | 4 +- nalgebra-glm/src/gtc/constants.rs | 2 +- nalgebra-glm/src/gtc/epsilon.rs | 4 +- nalgebra-glm/src/gtc/integer.rs | 4 +- nalgebra-glm/src/gtc/matrix_access.rs | 4 +- nalgebra-glm/src/gtc/matrix_inverse.rs | 4 +- nalgebra-glm/src/gtc/packing.rs | 4 +- nalgebra-glm/src/gtc/quaternion.rs | 12 +++--- nalgebra-glm/src/gtc/round.rs | 4 +- nalgebra-glm/src/gtc/type_ptr.rs | 4 +- nalgebra-glm/src/gtc/ulp.rs | 2 +- nalgebra-glm/src/gtx/component_wise.rs | 4 +- nalgebra-glm/src/gtx/euler_angles.rs | 2 +- nalgebra-glm/src/gtx/exterior_product.rs | 4 +- .../src/gtx/handed_coordinate_space.rs | 4 +- nalgebra-glm/src/gtx/matrix_cross_product.rs | 4 +- nalgebra-glm/src/gtx/matrix_operation.rs | 4 +- nalgebra-glm/src/gtx/norm.rs | 6 +-- nalgebra-glm/src/gtx/normal.rs | 2 +- nalgebra-glm/src/gtx/normalize_dot.rs | 4 +- nalgebra-glm/src/gtx/quaternion.rs | 2 +- .../src/gtx/rotate_normalized_axis.rs | 2 +- nalgebra-glm/src/gtx/rotate_vector.rs | 2 +- nalgebra-glm/src/gtx/transform.rs | 4 +- nalgebra-glm/src/gtx/transform2.rs | 4 +- nalgebra-glm/src/gtx/transform2d.rs | 4 +- nalgebra-glm/src/gtx/vector_angle.rs | 4 +- nalgebra-glm/src/gtx/vector_query.rs | 4 +- nalgebra-glm/src/integer.rs | 4 +- nalgebra-glm/src/lib.rs | 4 +- nalgebra-glm/src/matrix.rs | 4 +- nalgebra-glm/src/packing.rs | 2 +- nalgebra-glm/src/trigonometric.rs | 4 +- nalgebra-glm/src/vector_relational.rs | 4 +- nalgebra-lapack/Cargo.toml | 3 +- nalgebra-lapack/src/eigen.rs | 6 +-- nalgebra-lapack/src/hessenberg.rs | 4 +- nalgebra-lapack/src/lu.rs | 4 +- nalgebra-lapack/src/qr.rs | 4 +- nalgebra-lapack/src/schur.rs | 4 +- nalgebra-lapack/src/svd.rs | 4 +- nalgebra-lapack/src/symmetric_eigen.rs | 4 +- .../tests/linalg/{real_schur.rs => schur.rs} | 0 src/base/alias.rs | 10 ++--- src/base/alias_slice.rs | 6 +-- src/base/allocator.rs | 8 ++-- src/base/array_storage.rs | 12 +++--- src/base/blas.rs | 10 ++--- src/base/cg.rs | 10 ++--- src/base/componentwise.rs | 10 ++--- src/base/constraint.rs | 2 +- src/base/construction.rs | 14 +++---- src/base/construction_slice.rs | 6 +-- src/base/conversion.rs | 16 ++++---- src/base/coordinates.rs | 6 +-- src/base/default_allocator.rs | 14 +++---- src/base/edition.rs | 14 +++---- src/base/indexing.rs | 24 ++++++------ src/base/iter.rs | 6 +-- src/base/matrix.rs | 38 +++++++++---------- src/base/matrix_alga.rs | 8 ++-- src/base/matrix_slice.rs | 12 +++--- src/base/norm.rs | 14 +++---- src/base/ops.rs | 10 ++--- src/base/properties.rs | 8 ++-- src/base/statistics.rs | 14 +++---- src/base/storage.rs | 8 ++-- src/base/swizzle.rs | 4 +- src/base/unit.rs | 6 +-- src/base/vec_storage.rs | 12 +++--- src/debug/random_orthogonal.rs | 12 +++--- src/debug/random_sdp.rs | 12 +++--- src/geometry/isometry.rs | 18 ++++----- src/geometry/isometry_alga.rs | 8 ++-- src/geometry/isometry_alias.rs | 4 +- src/geometry/isometry_construction.rs | 10 ++--- src/geometry/isometry_conversion.rs | 22 +++++------ src/geometry/isometry_ops.rs | 8 ++-- src/geometry/orthographic.rs | 18 ++++----- src/geometry/perspective.rs | 20 +++++----- src/geometry/point.rs | 14 +++---- src/geometry/point_alga.rs | 8 ++-- src/geometry/point_alias.rs | 4 +- src/geometry/point_construction.rs | 10 ++--- src/geometry/point_conversion.rs | 16 ++++---- src/geometry/point_coordinates.rs | 10 ++--- src/geometry/point_ops.rs | 12 +++--- src/geometry/quaternion.rs | 28 +++++++------- src/geometry/quaternion_alga.rs | 4 +- src/geometry/quaternion_construction.rs | 38 +++++++++---------- src/geometry/quaternion_conversion.rs | 28 +++++++------- src/geometry/quaternion_coordinates.rs | 4 +- src/geometry/quaternion_ops.rs | 12 +++--- src/geometry/reflection.rs | 20 +++++----- src/geometry/rotation.rs | 12 +++--- src/geometry/rotation_alga.rs | 10 ++--- src/geometry/rotation_alias.rs | 4 +- src/geometry/rotation_construction.rs | 8 ++-- src/geometry/rotation_conversion.rs | 30 +++++++-------- src/geometry/rotation_ops.rs | 12 +++--- src/geometry/rotation_specialization.rs | 16 ++++---- src/geometry/similarity.rs | 16 ++++---- src/geometry/similarity_alga.rs | 8 ++-- src/geometry/similarity_alias.rs | 4 +- src/geometry/similarity_construction.rs | 10 ++--- src/geometry/similarity_conversion.rs | 18 ++++----- src/geometry/similarity_ops.rs | 8 ++-- src/geometry/swizzle.rs | 6 +-- src/geometry/transform.rs | 10 ++--- src/geometry/transform_alga.rs | 8 ++-- src/geometry/transform_alias.rs | 4 +- src/geometry/transform_construction.rs | 8 ++-- src/geometry/transform_conversion.rs | 10 ++--- src/geometry/transform_ops.rs | 8 ++-- src/geometry/translation.rs | 12 +++--- src/geometry/translation_alga.rs | 8 ++-- src/geometry/translation_alias.rs | 4 +- src/geometry/translation_construction.rs | 10 ++--- src/geometry/translation_conversion.rs | 12 +++--- src/geometry/translation_coordinates.rs | 10 ++--- src/geometry/translation_ops.rs | 10 ++--- src/geometry/unit_complex.rs | 4 +- src/geometry/unit_complex_alga.rs | 8 ++-- src/geometry/unit_complex_construction.rs | 8 ++-- src/geometry/unit_complex_conversion.rs | 26 ++++++------- src/geometry/unit_complex_ops.rs | 10 ++--- src/io/matrix_market.rs | 6 +-- src/lib.rs | 10 ++--- src/linalg/balancing.rs | 12 +++--- src/linalg/bidiagonal.rs | 13 +++---- src/linalg/cholesky.rs | 10 ++--- src/linalg/determinant.rs | 10 ++--- src/linalg/eigen.rs | 16 ++++---- src/linalg/full_piv_lu.rs | 14 +++---- src/linalg/givens.rs | 8 ++-- src/linalg/hessenberg.rs | 11 +++--- src/linalg/householder.rs | 12 +++--- src/linalg/inverse.rs | 10 ++--- src/linalg/lu.rs | 12 +++--- src/linalg/permutation_sequence.rs | 10 ++--- src/linalg/qr.rs | 14 +++---- src/linalg/schur.rs | 27 +++++++------ src/linalg/solve.rs | 10 ++--- src/linalg/svd.rs | 20 +++++----- src/linalg/symmetric_eigen.rs | 18 ++++----- src/linalg/symmetric_tridiagonal.rs | 14 +++---- src/sparse/cs_matrix.rs | 6 +-- src/sparse/cs_matrix_cholesky.rs | 6 +-- src/sparse/cs_matrix_conversion.rs | 10 ++--- src/sparse/cs_matrix_ops.rs | 10 ++--- src/sparse/cs_matrix_solve.rs | 10 ++--- src/sparse/cs_utils.rs | 4 +- tests/linalg/bidiagonal.rs | 2 +- tests/linalg/cholesky.rs | 2 +- tests/linalg/eigen.rs | 2 +- tests/linalg/full_piv_lu.rs | 2 +- tests/linalg/hessenberg.rs | 2 +- tests/linalg/lu.rs | 4 +- tests/linalg/qr.rs | 2 +- tests/linalg/schur.rs | 2 +- tests/linalg/solve.rs | 2 +- tests/linalg/svd.rs | 2 +- tests/linalg/tridiagonal.rs | 2 +- tests/sparse/cs_cholesky.rs | 4 +- 185 files changed, 797 insertions(+), 797 deletions(-) rename nalgebra-lapack/tests/linalg/{real_schur.rs => schur.rs} (100%) diff --git a/Cargo.toml b/Cargo.toml index d44431c1..736b9738 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ readme = "README.md" categories = [ "science" ] keywords = [ "linear", "algebra", "matrix", "vector", "math" ] license = "BSD-3-Clause" +edition = "2018" exclude = ["/ci/*", "/.travis.yml", "/Makefile"] diff --git a/benches/linalg/schur.rs b/benches/linalg/schur.rs index ce0b741f..024e6114 100644 --- a/benches/linalg/schur.rs +++ b/benches/linalg/schur.rs @@ -9,19 +9,19 @@ fn schur_decompose_4x4(bh: &mut Bencher) { #[bench] fn schur_decompose_10x10(bh: &mut Bencher) { - let m = ::reproductible_dmatrix(10, 10); + let m = crate::reproductible_dmatrix(10, 10); bh.iter(|| test::black_box(Schur::new(m.clone()))) } #[bench] fn schur_decompose_100x100(bh: &mut Bencher) { - let m = ::reproductible_dmatrix(100, 100); + let m = crate::reproductible_dmatrix(100, 100); bh.iter(|| test::black_box(Schur::new(m.clone()))) } #[bench] fn schur_decompose_200x200(bh: &mut Bencher) { - let m = ::reproductible_dmatrix(200, 200); + let m = crate::reproductible_dmatrix(200, 200); bh.iter(|| test::black_box(Schur::new(m.clone()))) } @@ -33,18 +33,18 @@ fn eigenvalues_4x4(bh: &mut Bencher) { #[bench] fn eigenvalues_10x10(bh: &mut Bencher) { - let m = ::reproductible_dmatrix(10, 10); + let m = crate::reproductible_dmatrix(10, 10); bh.iter(|| test::black_box(m.complex_eigenvalues())) } #[bench] fn eigenvalues_100x100(bh: &mut Bencher) { - let m = ::reproductible_dmatrix(100, 100); + let m = crate::reproductible_dmatrix(100, 100); bh.iter(|| test::black_box(m.complex_eigenvalues())) } #[bench] fn eigenvalues_200x200(bh: &mut Bencher) { - let m = ::reproductible_dmatrix(200, 200); + let m = crate::reproductible_dmatrix(200, 200); bh.iter(|| test::black_box(m.complex_eigenvalues())) } diff --git a/benches/linalg/svd.rs b/benches/linalg/svd.rs index 47023804..956ba4a7 100644 --- a/benches/linalg/svd.rs +++ b/benches/linalg/svd.rs @@ -9,19 +9,19 @@ fn svd_decompose_4x4(bh: &mut Bencher) { #[bench] fn svd_decompose_10x10(bh: &mut Bencher) { - let m = ::reproductible_dmatrix(10, 10); + let m = crate::reproductible_dmatrix(10, 10); bh.iter(|| test::black_box(SVD::new(m.clone(), true, true))) } #[bench] fn svd_decompose_100x100(bh: &mut Bencher) { - let m = ::reproductible_dmatrix(100, 100); + let m = crate::reproductible_dmatrix(100, 100); bh.iter(|| test::black_box(SVD::new(m.clone(), true, true))) } #[bench] fn svd_decompose_200x200(bh: &mut Bencher) { - let m = ::reproductible_dmatrix(200, 200); + let m = crate::reproductible_dmatrix(200, 200); bh.iter(|| test::black_box(SVD::new(m.clone(), true, true))) } @@ -33,19 +33,19 @@ fn rank_4x4(bh: &mut Bencher) { #[bench] fn rank_10x10(bh: &mut Bencher) { - let m = ::reproductible_dmatrix(10, 10); + let m = crate::reproductible_dmatrix(10, 10); bh.iter(|| test::black_box(m.rank(1.0e-10))) } #[bench] fn rank_100x100(bh: &mut Bencher) { - let m = ::reproductible_dmatrix(100, 100); + let m = crate::reproductible_dmatrix(100, 100); bh.iter(|| test::black_box(m.rank(1.0e-10))) } #[bench] fn rank_200x200(bh: &mut Bencher) { - let m = ::reproductible_dmatrix(200, 200); + let m = crate::reproductible_dmatrix(200, 200); bh.iter(|| test::black_box(m.rank(1.0e-10))) } @@ -57,19 +57,19 @@ fn singular_values_4x4(bh: &mut Bencher) { #[bench] fn singular_values_10x10(bh: &mut Bencher) { - let m = ::reproductible_dmatrix(10, 10); + let m = crate::reproductible_dmatrix(10, 10); bh.iter(|| test::black_box(m.singular_values())) } #[bench] fn singular_values_100x100(bh: &mut Bencher) { - let m = ::reproductible_dmatrix(100, 100); + let m = crate::reproductible_dmatrix(100, 100); bh.iter(|| test::black_box(m.singular_values())) } #[bench] fn singular_values_200x200(bh: &mut Bencher) { - let m = ::reproductible_dmatrix(200, 200); + let m = crate::reproductible_dmatrix(200, 200); bh.iter(|| test::black_box(m.singular_values())) } @@ -81,18 +81,18 @@ fn pseudo_inverse_4x4(bh: &mut Bencher) { #[bench] fn pseudo_inverse_10x10(bh: &mut Bencher) { - let m = ::reproductible_dmatrix(10, 10); + let m = crate::reproductible_dmatrix(10, 10); bh.iter(|| test::black_box(m.clone().pseudo_inverse(1.0e-10))) } #[bench] fn pseudo_inverse_100x100(bh: &mut Bencher) { - let m = ::reproductible_dmatrix(100, 100); + let m = crate::reproductible_dmatrix(100, 100); bh.iter(|| test::black_box(m.clone().pseudo_inverse(1.0e-10))) } #[bench] fn pseudo_inverse_200x200(bh: &mut Bencher) { - let m = ::reproductible_dmatrix(200, 200); + let m = crate::reproductible_dmatrix(200, 200); bh.iter(|| test::black_box(m.clone().pseudo_inverse(1.0e-10))) } diff --git a/benches/linalg/symmetric_eigen.rs b/benches/linalg/symmetric_eigen.rs index 2a9058da..7f19eb78 100644 --- a/benches/linalg/symmetric_eigen.rs +++ b/benches/linalg/symmetric_eigen.rs @@ -9,18 +9,18 @@ fn symmetric_eigen_decompose_4x4(bh: &mut Bencher) { #[bench] fn symmetric_eigen_decompose_10x10(bh: &mut Bencher) { - let m = ::reproductible_dmatrix(10, 10); + let m = crate::reproductible_dmatrix(10, 10); bh.iter(|| test::black_box(SymmetricEigen::new(m.clone()))) } #[bench] fn symmetric_eigen_decompose_100x100(bh: &mut Bencher) { - let m = ::reproductible_dmatrix(100, 100); + let m = crate::reproductible_dmatrix(100, 100); bh.iter(|| test::black_box(SymmetricEigen::new(m.clone()))) } #[bench] fn symmetric_eigen_decompose_200x200(bh: &mut Bencher) { - let m = ::reproductible_dmatrix(200, 200); + let m = crate::reproductible_dmatrix(200, 200); bh.iter(|| test::black_box(SymmetricEigen::new(m.clone()))) } diff --git a/nalgebra-glm/Cargo.toml b/nalgebra-glm/Cargo.toml index 1da1333d..042c75fb 100644 --- a/nalgebra-glm/Cargo.toml +++ b/nalgebra-glm/Cargo.toml @@ -11,6 +11,7 @@ readme = "../README.md" categories = [ "science" ] keywords = [ "linear", "algebra", "matrix", "vector", "math" ] license = "BSD-3-Clause" +edition = "2018" [features] default = [ "std" ] diff --git a/nalgebra-glm/src/common.rs b/nalgebra-glm/src/common.rs index 021ac3ef..23103299 100644 --- a/nalgebra-glm/src/common.rs +++ b/nalgebra-glm/src/common.rs @@ -2,8 +2,8 @@ use na::{self, DefaultAllocator, Real}; use num::FromPrimitive; use std::mem; -use aliases::{TMat, TVec}; -use traits::{Alloc, Dimension, Number}; +use crate::aliases::{TMat, TVec}; +use crate::traits::{Alloc, Dimension, Number}; /// For each matrix or vector component `x` if `x >= 0`; otherwise, it returns `-x`. /// diff --git a/nalgebra-glm/src/constructors.rs b/nalgebra-glm/src/constructors.rs index 1651dd20..fb692d5c 100644 --- a/nalgebra-glm/src/constructors.rs +++ b/nalgebra-glm/src/constructors.rs @@ -1,7 +1,7 @@ #![cfg_attr(rustfmt, rustfmt_skip)] use na::{Scalar, Real, U2, U3, U4}; -use aliases::{TMat, Qua, TVec1, TVec2, TVec3, TVec4, TMat2, TMat2x3, TMat2x4, TMat3, TMat3x2, TMat3x4, +use crate::aliases::{TMat, Qua, TVec1, TVec2, TVec3, TVec4, TMat2, TMat2x3, TMat2x4, TMat3, TMat3x2, TMat3x4, TMat4, TMat4x2, TMat4x3}; diff --git a/nalgebra-glm/src/exponential.rs b/nalgebra-glm/src/exponential.rs index 21b716f2..e080805d 100644 --- a/nalgebra-glm/src/exponential.rs +++ b/nalgebra-glm/src/exponential.rs @@ -1,6 +1,6 @@ -use aliases::TVec; +use crate::aliases::TVec; use na::{DefaultAllocator, Real}; -use traits::{Alloc, Dimension}; +use crate::traits::{Alloc, Dimension}; /// Component-wise exponential. /// diff --git a/nalgebra-glm/src/ext/matrix_clip_space.rs b/nalgebra-glm/src/ext/matrix_clip_space.rs index 02179759..fe7cc973 100644 --- a/nalgebra-glm/src/ext/matrix_clip_space.rs +++ b/nalgebra-glm/src/ext/matrix_clip_space.rs @@ -1,4 +1,4 @@ -use aliases::TMat4; +use crate::aliases::TMat4; use na::{Real}; //pub fn frustum(left: N, right: N, bottom: N, top: N, near: N, far: N) -> TMat4 { @@ -95,7 +95,7 @@ pub fn ortho_lh(left: N, right: N, bottom: N, top: N, znear: N, zfar: N /// * `zfar` - Distance from the viewer to the far clipping plane /// pub fn ortho_lh_no(left: N, right: N, bottom: N, top: N, znear: N, zfar: N) -> TMat4 { - let two : N = ::convert(2.0); + let two : N = crate::convert(2.0); let mut mat : TMat4 = TMat4::::identity(); mat[(0, 0)] = two / (right - left); @@ -121,7 +121,7 @@ pub fn ortho_lh_no(left: N, right: N, bottom: N, top: N, znear: N, zfar /// pub fn ortho_lh_zo(left: N, right: N, bottom: N, top: N, znear: N, zfar: N) -> TMat4 { let one : N = N::one(); - let two : N = ::convert(2.0); + let two : N = crate::convert(2.0); let mut mat : TMat4 = TMat4::::identity(); mat[(0, 0)] = two / (right - left); @@ -176,7 +176,7 @@ pub fn ortho_rh(left: N, right: N, bottom: N, top: N, znear: N, zfar: N /// * `zfar` - Distance from the viewer to the far clipping plane /// pub fn ortho_rh_no(left: N, right: N, bottom: N, top: N, znear: N, zfar: N) -> TMat4 { - let two : N = ::convert(2.0); + let two : N = crate::convert(2.0); let mut mat : TMat4 = TMat4::::identity(); mat[(0, 0)] = two / (right - left); @@ -202,7 +202,7 @@ pub fn ortho_rh_no(left: N, right: N, bottom: N, top: N, znear: N, zfar /// pub fn ortho_rh_zo(left: N, right: N, bottom: N, top: N, znear: N, zfar: N) -> TMat4 { let one : N = N::one(); - let two : N = ::convert(2.0); + let two : N = crate::convert(2.0); let mut mat : TMat4 = TMat4::::identity(); mat[(0, 0)] = two / (right - left); @@ -285,13 +285,13 @@ pub fn perspective_fov_lh_no(fov: N, width: N, height: N, near: N, far: let mut mat = TMat4::zeros(); let rad = fov; - let h = (rad * ::convert(0.5)).cos() / (rad * ::convert(0.5)).sin(); + let h = (rad * crate::convert(0.5)).cos() / (rad * crate::convert(0.5)).sin(); let w = h * height / width; mat[(0, 0)] = w; mat[(1, 1)] = h; mat[(2, 2)] = (far + near) / (far - near); - mat[(2, 3)] = - (far * near * ::convert(2.0)) / (far - near); + mat[(2, 3)] = - (far * near * crate::convert(2.0)) / (far - near); mat[(3, 2)] = N::one(); mat @@ -324,7 +324,7 @@ pub fn perspective_fov_lh_zo(fov: N, width: N, height: N, near: N, far: let mut mat = TMat4::zeros(); let rad = fov; - let h = (rad * ::convert(0.5)).cos() / (rad * ::convert(0.5)).sin(); + let h = (rad * crate::convert(0.5)).cos() / (rad * crate::convert(0.5)).sin(); let w = h * height / width; mat[(0, 0)] = w; @@ -391,13 +391,13 @@ pub fn perspective_fov_rh_no(fov: N, width: N, height: N, near: N, far: let mut mat = TMat4::zeros(); let rad = fov; - let h = (rad * ::convert(0.5)).cos() / (rad * ::convert(0.5)).sin(); + let h = (rad * crate::convert(0.5)).cos() / (rad * crate::convert(0.5)).sin(); let w = h * height / width; mat[(0, 0)] = w; mat[(1, 1)] = h; mat[(2, 2)] = - (far + near) / (far - near); - mat[(2, 3)] = - (far * near * ::convert(2.0)) / (far - near); + mat[(2, 3)] = - (far * near * crate::convert(2.0)) / (far - near); mat[(3, 2)] = -N::one(); mat @@ -430,7 +430,7 @@ pub fn perspective_fov_rh_zo(fov: N, width: N, height: N, near: N, far: let mut mat = TMat4::zeros(); let rad = fov; - let h = (rad * ::convert(0.5)).cos() / (rad * ::convert(0.5)).sin(); + let h = (rad * crate::convert(0.5)).cos() / (rad * crate::convert(0.5)).sin(); let w = h * height / width; mat[(0, 0)] = w; @@ -522,7 +522,7 @@ pub fn perspective_lh_no(aspect: N, fovy: N, near: N, far: N) -> TMat4< ); let one = N::one(); - let two: N = ::convert( 2.0); + let two: N = crate::convert( 2.0); let mut mat : TMat4 = TMat4::zeros(); let tan_half_fovy = (fovy / two).tan(); @@ -558,7 +558,7 @@ pub fn perspective_lh_zo(aspect: N, fovy: N, near: N, far: N) -> TMat4< ); let one = N::one(); - let two: N = ::convert( 2.0); + let two: N = crate::convert( 2.0); let mut mat: TMat4 = TMat4::zeros(); let tan_half_fovy = (fovy / two).tan(); @@ -625,7 +625,7 @@ pub fn perspective_rh_no(aspect: N, fovy: N, near: N, far: N) -> TMat4< let negone = -N::one(); let one = N::one(); - let two: N = ::convert( 2.0); + let two: N = crate::convert( 2.0); let mut mat = TMat4::zeros(); let tan_half_fovy = (fovy / two).tan(); @@ -662,7 +662,7 @@ pub fn perspective_rh_zo(aspect: N, fovy: N, near: N, far: N) -> TMat4< let negone = -N::one(); let one = N::one(); - let two = ::convert( 2.0); + let two = crate::convert( 2.0); let mut mat = TMat4::zeros(); let tan_half_fovy = (fovy / two).tan(); diff --git a/nalgebra-glm/src/ext/matrix_projection.rs b/nalgebra-glm/src/ext/matrix_projection.rs index 4ed23fb3..8083b1eb 100644 --- a/nalgebra-glm/src/ext/matrix_projection.rs +++ b/nalgebra-glm/src/ext/matrix_projection.rs @@ -1,6 +1,6 @@ use na::{self, Real, U3}; -use aliases::{TMat4, TVec2, TVec3, TVec4}; +use crate::aliases::{TMat4, TVec2, TVec3, TVec4}; /// Define a picking region. /// diff --git a/nalgebra-glm/src/ext/matrix_relationnal.rs b/nalgebra-glm/src/ext/matrix_relationnal.rs index 80fb8b6f..7866e72a 100644 --- a/nalgebra-glm/src/ext/matrix_relationnal.rs +++ b/nalgebra-glm/src/ext/matrix_relationnal.rs @@ -1,7 +1,7 @@ use na::DefaultAllocator; -use aliases::{TMat, TVec}; -use traits::{Alloc, Dimension, Number}; +use crate::aliases::{TMat, TVec}; +use crate::traits::{Alloc, Dimension, Number}; /// Perform a component-wise equal-to comparison of two matrices. /// diff --git a/nalgebra-glm/src/ext/matrix_transform.rs b/nalgebra-glm/src/ext/matrix_transform.rs index 82926249..8265cc19 100644 --- a/nalgebra-glm/src/ext/matrix_transform.rs +++ b/nalgebra-glm/src/ext/matrix_transform.rs @@ -1,7 +1,7 @@ use na::{DefaultAllocator, Point3, Real, Rotation3, Unit}; -use aliases::{TMat, TMat4, TVec, TVec3}; -use traits::{Alloc, Dimension, Number}; +use crate::aliases::{TMat, TMat4, TVec, TVec3}; +use crate::traits::{Alloc, Dimension, Number}; /// The identity matrix. pub fn identity() -> TMat diff --git a/nalgebra-glm/src/ext/quaternion_common.rs b/nalgebra-glm/src/ext/quaternion_common.rs index 3a91d0c7..29150bf6 100644 --- a/nalgebra-glm/src/ext/quaternion_common.rs +++ b/nalgebra-glm/src/ext/quaternion_common.rs @@ -1,6 +1,6 @@ use na::{self, Real, Unit}; -use aliases::Qua; +use crate::aliases::Qua; /// The conjugate of `q`. pub fn quat_conjugate(q: &Qua) -> Qua { diff --git a/nalgebra-glm/src/ext/quaternion_geometric.rs b/nalgebra-glm/src/ext/quaternion_geometric.rs index a67de587..29356869 100644 --- a/nalgebra-glm/src/ext/quaternion_geometric.rs +++ b/nalgebra-glm/src/ext/quaternion_geometric.rs @@ -1,6 +1,6 @@ use na::Real; -use aliases::Qua; +use crate::aliases::Qua; /// Multiplies two quaternions. pub fn quat_cross(q1: &Qua, q2: &Qua) -> Qua { diff --git a/nalgebra-glm/src/ext/quaternion_relational.rs b/nalgebra-glm/src/ext/quaternion_relational.rs index e459054f..ff4c6b01 100644 --- a/nalgebra-glm/src/ext/quaternion_relational.rs +++ b/nalgebra-glm/src/ext/quaternion_relational.rs @@ -1,23 +1,23 @@ use na::{Real, U4}; -use aliases::{Qua, TVec}; +use crate::aliases::{Qua, TVec}; /// Component-wise equality comparison between two quaternions. pub fn quat_equal(x: &Qua, y: &Qua) -> TVec { - ::equal(&x.coords, &y.coords) + crate::equal(&x.coords, &y.coords) } /// Component-wise approximate equality comparison between two quaternions. pub fn quat_equal_eps(x: &Qua, y: &Qua, epsilon: N) -> TVec { - ::equal_eps(&x.coords, &y.coords, epsilon) + crate::equal_eps(&x.coords, &y.coords, epsilon) } /// Component-wise non-equality comparison between two quaternions. pub fn quat_not_equal(x: &Qua, y: &Qua) -> TVec { - ::not_equal(&x.coords, &y.coords) + crate::not_equal(&x.coords, &y.coords) } /// Component-wise approximate non-equality comparison between two quaternions. pub fn quat_not_equal_eps(x: &Qua, y: &Qua, epsilon: N) -> TVec { - ::not_equal_eps(&x.coords, &y.coords, epsilon) + crate::not_equal_eps(&x.coords, &y.coords, epsilon) } diff --git a/nalgebra-glm/src/ext/quaternion_transform.rs b/nalgebra-glm/src/ext/quaternion_transform.rs index a4a60210..4f3f4211 100644 --- a/nalgebra-glm/src/ext/quaternion_transform.rs +++ b/nalgebra-glm/src/ext/quaternion_transform.rs @@ -1,6 +1,6 @@ use na::{Real, Unit, UnitQuaternion}; -use aliases::{Qua, TVec3}; +use crate::aliases::{Qua, TVec3}; /// Computes the quaternion exponential. pub fn quat_exp(q: &Qua) -> Qua { diff --git a/nalgebra-glm/src/ext/quaternion_trigonometric.rs b/nalgebra-glm/src/ext/quaternion_trigonometric.rs index 762bd9e9..42833f05 100644 --- a/nalgebra-glm/src/ext/quaternion_trigonometric.rs +++ b/nalgebra-glm/src/ext/quaternion_trigonometric.rs @@ -1,6 +1,6 @@ use na::{Real, Unit, UnitQuaternion}; -use aliases::{Qua, TVec3}; +use crate::aliases::{Qua, TVec3}; /// The rotation angle of this quaternion assumed to be normalized. pub fn quat_angle(x: &Qua) -> N { diff --git a/nalgebra-glm/src/ext/scalar_common.rs b/nalgebra-glm/src/ext/scalar_common.rs index 48d3255d..11104ce2 100644 --- a/nalgebra-glm/src/ext/scalar_common.rs +++ b/nalgebra-glm/src/ext/scalar_common.rs @@ -1,6 +1,6 @@ use na; -use traits::Number; +use crate::traits::Number; /// Returns the maximum among three values. /// diff --git a/nalgebra-glm/src/ext/vector_common.rs b/nalgebra-glm/src/ext/vector_common.rs index c0318067..a6418ef8 100644 --- a/nalgebra-glm/src/ext/vector_common.rs +++ b/nalgebra-glm/src/ext/vector_common.rs @@ -1,7 +1,7 @@ use na::{self, DefaultAllocator}; -use aliases::TVec; -use traits::{Alloc, Dimension, Number}; +use crate::aliases::TVec; +use crate::traits::{Alloc, Dimension, Number}; /// Component-wise maximum between a vector and a scalar. /// diff --git a/nalgebra-glm/src/ext/vector_relational.rs b/nalgebra-glm/src/ext/vector_relational.rs index ee418588..a5071336 100644 --- a/nalgebra-glm/src/ext/vector_relational.rs +++ b/nalgebra-glm/src/ext/vector_relational.rs @@ -1,7 +1,7 @@ use na::DefaultAllocator; -use aliases::TVec; -use traits::{Alloc, Dimension, Number}; +use crate::aliases::TVec; +use crate::traits::{Alloc, Dimension, Number}; /// Component-wise approximate equality of two vectors, using a scalar epsilon. /// diff --git a/nalgebra-glm/src/geometric.rs b/nalgebra-glm/src/geometric.rs index 998709d6..a0706f75 100644 --- a/nalgebra-glm/src/geometric.rs +++ b/nalgebra-glm/src/geometric.rs @@ -1,7 +1,7 @@ use na::{DefaultAllocator, Real}; -use aliases::{TVec, TVec3}; -use traits::{Alloc, Dimension, Number}; +use crate::aliases::{TVec, TVec3}; +use crate::traits::{Alloc, Dimension, Number}; /// The cross product of two vectors. pub fn cross(x: &TVec3, y: &TVec3) -> TVec3 { diff --git a/nalgebra-glm/src/gtc/bitfield.rs b/nalgebra-glm/src/gtc/bitfield.rs index 65fbcce0..bdf18552 100644 --- a/nalgebra-glm/src/gtc/bitfield.rs +++ b/nalgebra-glm/src/gtc/bitfield.rs @@ -1,7 +1,7 @@ use na::{Scalar, DefaultAllocator}; -use traits::{Alloc, Dimension}; -use aliases::*; +use crate::traits::{Alloc, Dimension}; +use crate::aliases::*; pub fn bitfieldDeinterleave(x: u16) -> U8Vec2 { unimplemented!() diff --git a/nalgebra-glm/src/gtc/constants.rs b/nalgebra-glm/src/gtc/constants.rs index 5e2e1b0d..9407cf29 100644 --- a/nalgebra-glm/src/gtc/constants.rs +++ b/nalgebra-glm/src/gtc/constants.rs @@ -227,7 +227,7 @@ pub fn root_three() -> N { /// * [`root_five`](fn.root_five.html) /// * [`root_three`](fn.root_three.html) pub fn root_two() -> N { - // FIXME: there should be a ::sqrt_2() on the Real trait. + // FIXME: there should be a crate::sqrt_2() on the Real trait. na::convert::<_, N>(2.0).sqrt() } diff --git a/nalgebra-glm/src/gtc/epsilon.rs b/nalgebra-glm/src/gtc/epsilon.rs index 4fd7138a..81ac2e6c 100644 --- a/nalgebra-glm/src/gtc/epsilon.rs +++ b/nalgebra-glm/src/gtc/epsilon.rs @@ -4,8 +4,8 @@ use approx::AbsDiffEq; use na::DefaultAllocator; -use traits::{Alloc, Number, Dimension}; -use aliases::TVec; +use crate::traits::{Alloc, Number, Dimension}; +use crate::aliases::TVec; /// Component-wise approximate equality beween two vectors. pub fn epsilon_equal(x: &TVec, y: &TVec, epsilon: N) -> TVec diff --git a/nalgebra-glm/src/gtc/integer.rs b/nalgebra-glm/src/gtc/integer.rs index df65843f..a972a4ab 100644 --- a/nalgebra-glm/src/gtc/integer.rs +++ b/nalgebra-glm/src/gtc/integer.rs @@ -1,7 +1,7 @@ //use na::{Scalar, DefaultAllocator}; // -//use traits::{Alloc, Dimension}; -//use aliases::TVec; +//use crate::traits::{Alloc, Dimension}; +//use crate::aliases::TVec; //pub fn iround(x: &TVec) -> TVec // where DefaultAllocator: Alloc { diff --git a/nalgebra-glm/src/gtc/matrix_access.rs b/nalgebra-glm/src/gtc/matrix_access.rs index 3eabf5e2..f61d9782 100644 --- a/nalgebra-glm/src/gtc/matrix_access.rs +++ b/nalgebra-glm/src/gtc/matrix_access.rs @@ -1,7 +1,7 @@ use na::{DefaultAllocator, Scalar}; -use aliases::{TMat, TVec}; -use traits::{Alloc, Dimension}; +use crate::aliases::{TMat, TVec}; +use crate::traits::{Alloc, Dimension}; /// The `index`-th column of the matrix `m`. /// diff --git a/nalgebra-glm/src/gtc/matrix_inverse.rs b/nalgebra-glm/src/gtc/matrix_inverse.rs index 4fc305e0..ca390bb9 100644 --- a/nalgebra-glm/src/gtc/matrix_inverse.rs +++ b/nalgebra-glm/src/gtc/matrix_inverse.rs @@ -1,7 +1,7 @@ use na::{DefaultAllocator, Real}; -use aliases::TMat; -use traits::{Alloc, Dimension}; +use crate::aliases::TMat; +use crate::traits::{Alloc, Dimension}; /// Fast matrix inverse for affine matrix. pub fn affine_inverse(m: TMat) -> TMat diff --git a/nalgebra-glm/src/gtc/packing.rs b/nalgebra-glm/src/gtc/packing.rs index b0261239..ab6019b3 100644 --- a/nalgebra-glm/src/gtc/packing.rs +++ b/nalgebra-glm/src/gtc/packing.rs @@ -1,7 +1,7 @@ use na::{Scalar, Real, DefaultAllocator, U3, U4}; -use traits::{Alloc, Dimension}; -use aliases::*; +use crate::traits::{Alloc, Dimension}; +use crate::aliases::*; pub fn packF2x11_1x10(v: &Vec3) -> i32 { diff --git a/nalgebra-glm/src/gtc/quaternion.rs b/nalgebra-glm/src/gtc/quaternion.rs index d31a0bcb..9322ec0a 100644 --- a/nalgebra-glm/src/gtc/quaternion.rs +++ b/nalgebra-glm/src/gtc/quaternion.rs @@ -1,6 +1,6 @@ use na::{Real, UnitQuaternion, U4}; -use aliases::{Qua, TMat4, TVec, TVec3}; +use crate::aliases::{Qua, TMat4, TVec, TVec3}; /// Euler angles of the quaternion `q` as (pitch, yaw, roll). pub fn quat_euler_angles(x: &Qua) -> TVec3 { @@ -11,27 +11,27 @@ pub fn quat_euler_angles(x: &Qua) -> TVec3 { /// Component-wise `>` comparison between two quaternions. pub fn quat_greater_than(x: &Qua, y: &Qua) -> TVec { - ::greater_than(&x.coords, &y.coords) + crate::greater_than(&x.coords, &y.coords) } /// Component-wise `>=` comparison between two quaternions. pub fn quat_greater_than_equal(x: &Qua, y: &Qua) -> TVec { - ::greater_than_equal(&x.coords, &y.coords) + crate::greater_than_equal(&x.coords, &y.coords) } /// Component-wise `<` comparison between two quaternions. pub fn quat_less_than(x: &Qua, y: &Qua) -> TVec { - ::less_than(&x.coords, &y.coords) + crate::less_than(&x.coords, &y.coords) } /// Component-wise `<=` comparison between two quaternions. pub fn quat_less_than_equal(x: &Qua, y: &Qua) -> TVec { - ::less_than_equal(&x.coords, &y.coords) + crate::less_than_equal(&x.coords, &y.coords) } /// Convert a quaternion to a rotation matrix in homogeneous coordinates. pub fn quat_cast(x: &Qua) -> TMat4 { - ::quat_to_mat4(x) + crate::quat_to_mat4(x) } /// Computes a right hand look-at quaternion diff --git a/nalgebra-glm/src/gtc/round.rs b/nalgebra-glm/src/gtc/round.rs index 75bd4462..8dde578d 100644 --- a/nalgebra-glm/src/gtc/round.rs +++ b/nalgebra-glm/src/gtc/round.rs @@ -1,7 +1,7 @@ use na::{Scalar, Real, U3, DefaultAllocator}; -use traits::{Number, Alloc, Dimension}; -use aliases::TVec; +use crate::traits::{Number, Alloc, Dimension}; +use crate::aliases::TVec; pub fn ceilMultiple(v: T, Multiple: T) -> T { diff --git a/nalgebra-glm/src/gtc/type_ptr.rs b/nalgebra-glm/src/gtc/type_ptr.rs index ed901f20..48ef9da5 100644 --- a/nalgebra-glm/src/gtc/type_ptr.rs +++ b/nalgebra-glm/src/gtc/type_ptr.rs @@ -1,10 +1,10 @@ use na::{DefaultAllocator, Quaternion, Real, Scalar}; -use aliases::{ +use crate::aliases::{ Qua, TMat, TMat2, TMat2x3, TMat2x4, TMat3, TMat3x2, TMat3x4, TMat4, TMat4x2, TMat4x3, TVec1, TVec2, TVec3, TVec4, }; -use traits::{Alloc, Dimension, Number}; +use crate::traits::{Alloc, Dimension, Number}; /// Creates a 2x2 matrix from a slice arranged in column-major order. pub fn make_mat2(ptr: &[N]) -> TMat2 { diff --git a/nalgebra-glm/src/gtc/ulp.rs b/nalgebra-glm/src/gtc/ulp.rs index 860d73be..8258d0df 100644 --- a/nalgebra-glm/src/gtc/ulp.rs +++ b/nalgebra-glm/src/gtc/ulp.rs @@ -1,6 +1,6 @@ use na::{Scalar, U2}; -use aliases::TVec; +use crate::aliases::TVec; pub fn float_distance(x: T, y: T) -> u64 { diff --git a/nalgebra-glm/src/gtx/component_wise.rs b/nalgebra-glm/src/gtx/component_wise.rs index 338f4380..7c4af7a0 100644 --- a/nalgebra-glm/src/gtx/component_wise.rs +++ b/nalgebra-glm/src/gtx/component_wise.rs @@ -1,7 +1,7 @@ use na::{self, DefaultAllocator}; -use aliases::TMat; -use traits::{Alloc, Dimension, Number}; +use crate::aliases::TMat; +use crate::traits::{Alloc, Dimension, Number}; /// The sum of every component of the given matrix or vector. /// diff --git a/nalgebra-glm/src/gtx/euler_angles.rs b/nalgebra-glm/src/gtx/euler_angles.rs index 2c4940a6..30be40bf 100644 --- a/nalgebra-glm/src/gtx/euler_angles.rs +++ b/nalgebra-glm/src/gtx/euler_angles.rs @@ -1,6 +1,6 @@ use na::{Real, U3, U4}; -use aliases::{TVec, TMat}; +use crate::aliases::{TVec, TMat}; pub fn derivedEulerAngleX(angleX: N, angularVelocityX: N) -> TMat4 { unimplemented!() diff --git a/nalgebra-glm/src/gtx/exterior_product.rs b/nalgebra-glm/src/gtx/exterior_product.rs index cc58597b..a95c557b 100644 --- a/nalgebra-glm/src/gtx/exterior_product.rs +++ b/nalgebra-glm/src/gtx/exterior_product.rs @@ -1,5 +1,5 @@ -use aliases::TVec2; -use traits::Number; +use crate::aliases::TVec2; +use crate::traits::Number; /// The 2D perpendicular product between two vectors. pub fn cross2d(v: &TVec2, u: &TVec2) -> N { diff --git a/nalgebra-glm/src/gtx/handed_coordinate_space.rs b/nalgebra-glm/src/gtx/handed_coordinate_space.rs index ee1979ad..22d25056 100644 --- a/nalgebra-glm/src/gtx/handed_coordinate_space.rs +++ b/nalgebra-glm/src/gtx/handed_coordinate_space.rs @@ -1,5 +1,5 @@ -use aliases::TVec3; -use traits::Number; +use crate::aliases::TVec3; +use crate::traits::Number; /// Returns `true` if `{a, b, c}` forms a left-handed trihedron. /// diff --git a/nalgebra-glm/src/gtx/matrix_cross_product.rs b/nalgebra-glm/src/gtx/matrix_cross_product.rs index 7d70d438..ac113e42 100644 --- a/nalgebra-glm/src/gtx/matrix_cross_product.rs +++ b/nalgebra-glm/src/gtx/matrix_cross_product.rs @@ -1,6 +1,6 @@ use na::Real; -use aliases::{TMat3, TMat4, TVec3}; +use crate::aliases::{TMat3, TMat4, TVec3}; /// Builds a 3x3 matrix `m` such that for any `v`: `m * v == cross(x, v)`. /// @@ -17,5 +17,5 @@ pub fn matrix_cross3(x: &TVec3) -> TMat3 { /// /// * [`matrix_cross3`](fn.matrix_cross3.html) pub fn matrix_cross(x: &TVec3) -> TMat4 { - ::mat3_to_mat4(&x.cross_matrix()) + crate::mat3_to_mat4(&x.cross_matrix()) } diff --git a/nalgebra-glm/src/gtx/matrix_operation.rs b/nalgebra-glm/src/gtx/matrix_operation.rs index 954607ef..cc051273 100644 --- a/nalgebra-glm/src/gtx/matrix_operation.rs +++ b/nalgebra-glm/src/gtx/matrix_operation.rs @@ -1,7 +1,7 @@ -use aliases::{ +use crate::aliases::{ TMat2, TMat2x3, TMat2x4, TMat3, TMat3x2, TMat3x4, TMat4, TMat4x2, TMat4x3, TVec2, TVec3, TVec4, }; -use traits::Number; +use crate::traits::Number; /// Builds a 2x2 diagonal matrix. /// diff --git a/nalgebra-glm/src/gtx/norm.rs b/nalgebra-glm/src/gtx/norm.rs index 0a287530..4450cdff 100644 --- a/nalgebra-glm/src/gtx/norm.rs +++ b/nalgebra-glm/src/gtx/norm.rs @@ -1,7 +1,7 @@ use na::{DefaultAllocator, Real}; -use aliases::TVec; -use traits::{Alloc, Dimension}; +use crate::aliases::TVec; +use crate::traits::{Alloc, Dimension}; /// The squared distance between two points. /// @@ -37,7 +37,7 @@ where DefaultAllocator: Alloc { /// * [`l2_norm`](fn.l2_norm.html) pub fn l1_norm(v: &TVec) -> N where DefaultAllocator: Alloc { - ::comp_add(&v.abs()) + crate::comp_add(&v.abs()) } /// The l2-norm of `x - y`. diff --git a/nalgebra-glm/src/gtx/normal.rs b/nalgebra-glm/src/gtx/normal.rs index 63fc9246..da3287fb 100644 --- a/nalgebra-glm/src/gtx/normal.rs +++ b/nalgebra-glm/src/gtx/normal.rs @@ -1,6 +1,6 @@ use na::Real; -use aliases::TVec3; +use crate::aliases::TVec3; /// The normal vector of the given triangle. /// diff --git a/nalgebra-glm/src/gtx/normalize_dot.rs b/nalgebra-glm/src/gtx/normalize_dot.rs index df52d2c0..6bce441b 100644 --- a/nalgebra-glm/src/gtx/normalize_dot.rs +++ b/nalgebra-glm/src/gtx/normalize_dot.rs @@ -1,7 +1,7 @@ use na::{DefaultAllocator, Real}; -use aliases::TVec; -use traits::{Alloc, Dimension}; +use crate::aliases::TVec; +use crate::traits::{Alloc, Dimension}; /// The dot product of the normalized version of `x` and `y`. /// diff --git a/nalgebra-glm/src/gtx/quaternion.rs b/nalgebra-glm/src/gtx/quaternion.rs index 70005ca8..5c9a783c 100644 --- a/nalgebra-glm/src/gtx/quaternion.rs +++ b/nalgebra-glm/src/gtx/quaternion.rs @@ -1,6 +1,6 @@ use na::{Real, Rotation3, Unit, UnitQuaternion, U3}; -use aliases::{Qua, TMat3, TMat4, TVec3, TVec4}; +use crate::aliases::{Qua, TMat3, TMat4, TVec3, TVec4}; /// Rotate the vector `v` by the quaternion `q` assumed to be normalized. pub fn quat_cross_vec(q: &Qua, v: &TVec3) -> TVec3 { diff --git a/nalgebra-glm/src/gtx/rotate_normalized_axis.rs b/nalgebra-glm/src/gtx/rotate_normalized_axis.rs index 224d7bfe..6767248c 100644 --- a/nalgebra-glm/src/gtx/rotate_normalized_axis.rs +++ b/nalgebra-glm/src/gtx/rotate_normalized_axis.rs @@ -1,6 +1,6 @@ use na::{Real, Rotation3, Unit, UnitQuaternion}; -use aliases::{Qua, TMat4, TVec3}; +use crate::aliases::{Qua, TMat4, TVec3}; /// Builds a rotation 4 * 4 matrix created from a normalized axis and an angle. /// diff --git a/nalgebra-glm/src/gtx/rotate_vector.rs b/nalgebra-glm/src/gtx/rotate_vector.rs index 64ce7244..a8cdd72b 100644 --- a/nalgebra-glm/src/gtx/rotate_vector.rs +++ b/nalgebra-glm/src/gtx/rotate_vector.rs @@ -1,6 +1,6 @@ use na::{Real, Rotation3, Unit, UnitComplex}; -use aliases::{TMat4, TVec2, TVec3, TVec4}; +use crate::aliases::{TMat4, TVec2, TVec3, TVec4}; /// Build the rotation matrix needed to align `normal` and `up`. pub fn orientation(normal: &TVec3, up: &TVec3) -> TMat4 { diff --git a/nalgebra-glm/src/gtx/transform.rs b/nalgebra-glm/src/gtx/transform.rs index 85554fe5..1e3e404d 100644 --- a/nalgebra-glm/src/gtx/transform.rs +++ b/nalgebra-glm/src/gtx/transform.rs @@ -1,7 +1,7 @@ use na::{Real, Rotation2, Rotation3, Unit}; -use aliases::{TMat3, TMat4, TVec2, TVec3}; -use traits::Number; +use crate::aliases::{TMat3, TMat4, TVec2, TVec3}; +use crate::traits::Number; /// A rotation 4 * 4 matrix created from an axis of 3 scalars and an angle expressed in radians. /// diff --git a/nalgebra-glm/src/gtx/transform2.rs b/nalgebra-glm/src/gtx/transform2.rs index fa5533f7..eaa74acb 100644 --- a/nalgebra-glm/src/gtx/transform2.rs +++ b/nalgebra-glm/src/gtx/transform2.rs @@ -1,7 +1,7 @@ use na::{U2, U3}; -use aliases::{TMat3, TMat4, TVec2, TVec3}; -use traits::Number; +use crate::aliases::{TMat3, TMat4, TVec2, TVec3}; +use crate::traits::Number; /// Build planar projection matrix along normal axis and right-multiply it to `m`. pub fn proj2d(m: &TMat3, normal: &TVec2) -> TMat3 { diff --git a/nalgebra-glm/src/gtx/transform2d.rs b/nalgebra-glm/src/gtx/transform2d.rs index 3d401f56..9e80bb52 100644 --- a/nalgebra-glm/src/gtx/transform2d.rs +++ b/nalgebra-glm/src/gtx/transform2d.rs @@ -1,7 +1,7 @@ use na::{Real, UnitComplex}; -use aliases::{TMat3, TVec2}; -use traits::Number; +use crate::aliases::{TMat3, TVec2}; +use crate::traits::Number; /// Builds a 2D rotation matrix from an angle and right-multiply it to `m`. /// diff --git a/nalgebra-glm/src/gtx/vector_angle.rs b/nalgebra-glm/src/gtx/vector_angle.rs index 1ebb39a4..8cfe813b 100644 --- a/nalgebra-glm/src/gtx/vector_angle.rs +++ b/nalgebra-glm/src/gtx/vector_angle.rs @@ -1,7 +1,7 @@ use na::{DefaultAllocator, Real}; -use aliases::TVec; -use traits::{Alloc, Dimension}; +use crate::aliases::TVec; +use crate::traits::{Alloc, Dimension}; /// The angle between two vectors. pub fn angle(x: &TVec, y: &TVec) -> N diff --git a/nalgebra-glm/src/gtx/vector_query.rs b/nalgebra-glm/src/gtx/vector_query.rs index f408a4b3..da23704d 100644 --- a/nalgebra-glm/src/gtx/vector_query.rs +++ b/nalgebra-glm/src/gtx/vector_query.rs @@ -1,7 +1,7 @@ use na::{DefaultAllocator, Real}; -use aliases::{TVec, TVec2, TVec3}; -use traits::{Alloc, Dimension, Number}; +use crate::aliases::{TVec, TVec2, TVec3}; +use crate::traits::{Alloc, Dimension, Number}; /// Returns `true` if two vectors are collinear (up to an epsilon). /// diff --git a/nalgebra-glm/src/integer.rs b/nalgebra-glm/src/integer.rs index 67a0116c..dbf39cb0 100644 --- a/nalgebra-glm/src/integer.rs +++ b/nalgebra-glm/src/integer.rs @@ -1,7 +1,7 @@ use na::{Scalar, Real, U3, DefaultAllocator}; -use traits::{Number, Alloc, Dimension}; -use aliases::TVec; +use crate::traits::{Number, Alloc, Dimension}; +use crate::aliases::TVec; pub fn bitCount(v: T) -> i32 { unimplemented!() diff --git a/nalgebra-glm/src/lib.rs b/nalgebra-glm/src/lib.rs index 53830f2b..b2fe8b8f 100644 --- a/nalgebra-glm/src/lib.rs +++ b/nalgebra-glm/src/lib.rs @@ -119,7 +119,7 @@ extern crate approx; extern crate alga; extern crate nalgebra as na; -pub use aliases::*; +pub use crate::aliases::*; pub use common::{ abs, ceil, clamp, clamp_scalar, clamp_vec, float_bits_to_int, float_bits_to_int_vec, float_bits_to_uint, float_bits_to_uint_vec, floor, fract, int_bits_to_float, @@ -133,7 +133,7 @@ pub use geometric::{ cross, distance, dot, faceforward, length, magnitude, normalize, reflect_vec, refract_vec, }; pub use matrix::{determinant, inverse, matrix_comp_mult, outer_product, transpose}; -pub use traits::{Alloc, Dimension, Number}; +pub use crate::traits::{Alloc, Dimension, Number}; pub use trigonometric::{ acos, acosh, asin, asinh, atan, atan2, atanh, cos, cosh, degrees, radians, sin, sinh, tan, tanh, }; diff --git a/nalgebra-glm/src/matrix.rs b/nalgebra-glm/src/matrix.rs index 81212248..26b2f3ab 100644 --- a/nalgebra-glm/src/matrix.rs +++ b/nalgebra-glm/src/matrix.rs @@ -1,7 +1,7 @@ use na::{DefaultAllocator, Real, Scalar}; -use aliases::{TMat, TVec}; -use traits::{Alloc, Dimension, Number}; +use crate::aliases::{TMat, TVec}; +use crate::traits::{Alloc, Dimension, Number}; /// The determinant of the matrix `m`. pub fn determinant(m: &TMat) -> N diff --git a/nalgebra-glm/src/packing.rs b/nalgebra-glm/src/packing.rs index 71df195c..3273fb26 100644 --- a/nalgebra-glm/src/packing.rs +++ b/nalgebra-glm/src/packing.rs @@ -1,6 +1,6 @@ use na::Scalar; -use aliases::{Vec2, Vec4, UVec2}; +use crate::aliases::{Vec2, Vec4, UVec2}; pub fn packDouble2x32(v: &UVec2) -> f64 { diff --git a/nalgebra-glm/src/trigonometric.rs b/nalgebra-glm/src/trigonometric.rs index cf0b2652..661bd2ae 100644 --- a/nalgebra-glm/src/trigonometric.rs +++ b/nalgebra-glm/src/trigonometric.rs @@ -1,7 +1,7 @@ use na::{self, DefaultAllocator, Real}; -use aliases::TVec; -use traits::{Alloc, Dimension}; +use crate::aliases::TVec; +use crate::traits::{Alloc, Dimension}; /// Component-wise arc-cosinus. pub fn acos(x: &TVec) -> TVec diff --git a/nalgebra-glm/src/vector_relational.rs b/nalgebra-glm/src/vector_relational.rs index c92f69fe..844936fe 100644 --- a/nalgebra-glm/src/vector_relational.rs +++ b/nalgebra-glm/src/vector_relational.rs @@ -1,7 +1,7 @@ use na::DefaultAllocator; -use aliases::TVec; -use traits::{Alloc, Dimension, Number}; +use crate::aliases::TVec; +use crate::traits::{Alloc, Dimension, Number}; /// Checks that all the vector components are `true`. /// diff --git a/nalgebra-lapack/Cargo.toml b/nalgebra-lapack/Cargo.toml index ac54589c..e3b34cd1 100644 --- a/nalgebra-lapack/Cargo.toml +++ b/nalgebra-lapack/Cargo.toml @@ -10,12 +10,13 @@ repository = "https://github.com/rustsim/nalgebra" readme = "README.md" keywords = [ "linear", "algebra", "matrix", "vector" ] license = "BSD-3-Clause" +edition = "2018" [features] serde-serialize = [ "serde", "serde_derive" ] # For BLAS/LAPACK -default = ["openblas"] +default = ["accelerate"] openblas = ["lapack-src/openblas"] netlib = ["lapack-src/netlib"] accelerate = ["lapack-src/accelerate"] diff --git a/nalgebra-lapack/src/eigen.rs b/nalgebra-lapack/src/eigen.rs index fbc49319..628b532f 100644 --- a/nalgebra-lapack/src/eigen.rs +++ b/nalgebra-lapack/src/eigen.rs @@ -10,7 +10,7 @@ use na::allocator::Allocator; use na::dimension::{Dim, U1}; use na::storage::Storage; use na::{DefaultAllocator, Matrix, MatrixN, Scalar, VectorN}; -use ComplexHelper; +use crate::ComplexHelper; use lapack; @@ -101,7 +101,7 @@ where DefaultAllocator: Allocator + Allocator lapack_check!(info); - let mut work = unsafe { ::uninitialized_vec(lwork as usize) }; + let mut work = unsafe { crate::uninitialized_vec(lwork as usize) }; match (left_eigenvectors, eigenvectors) { (true, true) => { @@ -263,7 +263,7 @@ where DefaultAllocator: Allocator + Allocator lapack_panic!(info); - let mut work = unsafe { ::uninitialized_vec(lwork as usize) }; + let mut work = unsafe { crate::uninitialized_vec(lwork as usize) }; N::xgeev( b'N', diff --git a/nalgebra-lapack/src/hessenberg.rs b/nalgebra-lapack/src/hessenberg.rs index 65a27d1e..c9f8d282 100644 --- a/nalgebra-lapack/src/hessenberg.rs +++ b/nalgebra-lapack/src/hessenberg.rs @@ -5,7 +5,7 @@ use na::allocator::Allocator; use na::dimension::{DimDiff, DimSub, U1}; use na::storage::Storage; use na::{DefaultAllocator, Matrix, MatrixN, Scalar, VectorN}; -use ComplexHelper; +use crate::ComplexHelper; use lapack; @@ -66,7 +66,7 @@ where DefaultAllocator: Allocator + Allocator> let mut info = 0; let lwork = N::xgehrd_work_size(n, 1, n, m.as_mut_slice(), n, tau.as_mut_slice(), &mut info); - let mut work = unsafe { ::uninitialized_vec(lwork as usize) }; + let mut work = unsafe { crate::uninitialized_vec(lwork as usize) }; lapack_panic!(info); diff --git a/nalgebra-lapack/src/lu.rs b/nalgebra-lapack/src/lu.rs index 21fdfb41..ada9bb34 100644 --- a/nalgebra-lapack/src/lu.rs +++ b/nalgebra-lapack/src/lu.rs @@ -5,7 +5,7 @@ use na::allocator::Allocator; use na::dimension::{Dim, DimMin, DimMinimum, U1}; use na::storage::Storage; use na::{DefaultAllocator, Matrix, MatrixMN, MatrixN, Scalar, VectorN}; -use ComplexHelper; +use crate::ComplexHelper; use lapack; @@ -283,7 +283,7 @@ where ); lapack_check!(info); - let mut work = unsafe { ::uninitialized_vec(lwork as usize) }; + let mut work = unsafe { crate::uninitialized_vec(lwork as usize) }; N::xgetri( dim, diff --git a/nalgebra-lapack/src/qr.rs b/nalgebra-lapack/src/qr.rs index 1fa9b066..5d4b3108 100644 --- a/nalgebra-lapack/src/qr.rs +++ b/nalgebra-lapack/src/qr.rs @@ -8,7 +8,7 @@ use na::allocator::Allocator; use na::dimension::{Dim, DimMin, DimMinimum, U1}; use na::storage::Storage; use na::{DefaultAllocator, Matrix, MatrixMN, Scalar, VectorN}; -use ComplexHelper; +use crate::ComplexHelper; use lapack; @@ -73,7 +73,7 @@ where DefaultAllocator: Allocator &mut info, ); - let mut work = unsafe { ::uninitialized_vec(lwork as usize) }; + let mut work = unsafe { crate::uninitialized_vec(lwork as usize) }; N::xgeqrf( nrows.value() as i32, diff --git a/nalgebra-lapack/src/schur.rs b/nalgebra-lapack/src/schur.rs index ab2423cb..f928afda 100644 --- a/nalgebra-lapack/src/schur.rs +++ b/nalgebra-lapack/src/schur.rs @@ -10,7 +10,7 @@ use na::allocator::Allocator; use na::dimension::{Dim, U1}; use na::storage::Storage; use na::{DefaultAllocator, Matrix, MatrixN, Scalar, VectorN}; -use ComplexHelper; +use crate::ComplexHelper; use lapack; @@ -98,7 +98,7 @@ where DefaultAllocator: Allocator + Allocator ); lapack_check!(info); - let mut work = unsafe { ::uninitialized_vec(lwork as usize) }; + let mut work = unsafe { crate::uninitialized_vec(lwork as usize) }; N::xgees( b'V', diff --git a/nalgebra-lapack/src/svd.rs b/nalgebra-lapack/src/svd.rs index 2d048bf3..9363fced 100644 --- a/nalgebra-lapack/src/svd.rs +++ b/nalgebra-lapack/src/svd.rs @@ -109,7 +109,7 @@ macro_rules! svd_impl( let mut work = [ 0.0 ]; let mut lwork = -1 as i32; let mut info = 0; - let mut iwork = unsafe { ::uninitialized_vec(8 * cmp::min(nrows.value(), ncols.value())) }; + let mut iwork = unsafe { crate::uninitialized_vec(8 * cmp::min(nrows.value(), ncols.value())) }; unsafe { $lapack_func(job, nrows.value() as i32, ncols.value() as i32, m.as_mut_slice(), @@ -119,7 +119,7 @@ macro_rules! svd_impl( lapack_check!(info); lwork = work[0] as i32; - let mut work = unsafe { ::uninitialized_vec(lwork as usize) }; + let mut work = unsafe { crate::uninitialized_vec(lwork as usize) }; unsafe { $lapack_func(job, nrows.value() as i32, ncols.value() as i32, m.as_mut_slice(), diff --git a/nalgebra-lapack/src/symmetric_eigen.rs b/nalgebra-lapack/src/symmetric_eigen.rs index 48e444ba..af0575fd 100644 --- a/nalgebra-lapack/src/symmetric_eigen.rs +++ b/nalgebra-lapack/src/symmetric_eigen.rs @@ -10,7 +10,7 @@ use na::allocator::Allocator; use na::dimension::{Dim, U1}; use na::storage::Storage; use na::{DefaultAllocator, Matrix, MatrixN, Scalar, VectorN}; -use ComplexHelper; +use crate::ComplexHelper; use lapack; @@ -102,7 +102,7 @@ where DefaultAllocator: Allocator + Allocator let lwork = N::xsyev_work_size(jobz, b'L', n as i32, m.as_mut_slice(), lda, &mut info); lapack_check!(info); - let mut work = unsafe { ::uninitialized_vec(lwork as usize) }; + let mut work = unsafe { crate::uninitialized_vec(lwork as usize) }; N::xsyev( jobz, diff --git a/nalgebra-lapack/tests/linalg/real_schur.rs b/nalgebra-lapack/tests/linalg/schur.rs similarity index 100% rename from nalgebra-lapack/tests/linalg/real_schur.rs rename to nalgebra-lapack/tests/linalg/schur.rs diff --git a/src/base/alias.rs b/src/base/alias.rs index f7ca2b34..a8925cf3 100644 --- a/src/base/alias.rs +++ b/src/base/alias.rs @@ -1,10 +1,10 @@ #[cfg(any(feature = "alloc", feature = "std"))] -use base::dimension::Dynamic; -use base::dimension::{U1, U2, U3, U4, U5, U6}; +use crate::base::dimension::Dynamic; +use crate::base::dimension::{U1, U2, U3, U4, U5, U6}; #[cfg(any(feature = "std", feature = "alloc"))] -use base::vec_storage::VecStorage; -use base::storage::Owned; -use base::Matrix; +use crate::base::vec_storage::VecStorage; +use crate::base::storage::Owned; +use crate::base::Matrix; /* * diff --git a/src/base/alias_slice.rs b/src/base/alias_slice.rs index 790e4e59..3a332def 100644 --- a/src/base/alias_slice.rs +++ b/src/base/alias_slice.rs @@ -1,6 +1,6 @@ -use base::dimension::{Dynamic, U1, U2, U3, U4, U5, U6}; -use base::matrix_slice::{SliceStorage, SliceStorageMut}; -use base::Matrix; +use crate::base::dimension::{Dynamic, U1, U2, U3, U4, U5, U6}; +use crate::base::matrix_slice::{SliceStorage, SliceStorageMut}; +use crate::base::Matrix; /* * diff --git a/src/base/allocator.rs b/src/base/allocator.rs index 5b17c183..0ad30981 100644 --- a/src/base/allocator.rs +++ b/src/base/allocator.rs @@ -2,10 +2,10 @@ use std::any::Any; -use base::constraint::{SameNumberOfColumns, SameNumberOfRows, ShapeConstraint}; -use base::dimension::{Dim, U1}; -use base::storage::ContiguousStorageMut; -use base::{DefaultAllocator, Scalar}; +use crate::base::constraint::{SameNumberOfColumns, SameNumberOfRows, ShapeConstraint}; +use crate::base::dimension::{Dim, U1}; +use crate::base::storage::ContiguousStorageMut; +use crate::base::{DefaultAllocator, Scalar}; /// A matrix allocator of a memory buffer that may contain `R::to_usize() * C::to_usize()` /// elements of type `N`. diff --git a/src/base/array_storage.rs b/src/base/array_storage.rs index 3beab9e1..bebb8740 100644 --- a/src/base/array_storage.rs +++ b/src/base/array_storage.rs @@ -21,11 +21,11 @@ use abomonation::Abomonation; use generic_array::{ArrayLength, GenericArray}; use typenum::Prod; -use base::allocator::Allocator; -use base::default_allocator::DefaultAllocator; -use base::dimension::{DimName, U1}; -use base::storage::{ContiguousStorage, ContiguousStorageMut, Owned, Storage, StorageMut}; -use base::Scalar; +use crate::base::allocator::Allocator; +use crate::base::default_allocator::DefaultAllocator; +use crate::base::dimension::{DimName, U1}; +use crate::base::storage::{ContiguousStorage, ContiguousStorageMut, Owned, Storage, StorageMut}; +use crate::base::Scalar; /* * @@ -330,7 +330,7 @@ where let mut out: Self::Value = unsafe { mem::uninitialized() }; let mut curr = 0; - while let Some(value) = try!(visitor.next_element()) { + while let Some(value) = visitor.next_element()? { *out.get_mut(curr).ok_or_else(|| V::Error::invalid_length(curr, &self))? = value; curr += 1; } diff --git a/src/base/blas.rs b/src/base/blas.rs index 9f919e11..cdfe4f9f 100644 --- a/src/base/blas.rs +++ b/src/base/blas.rs @@ -5,13 +5,13 @@ use num::{One, Signed, Zero}; #[cfg(feature = "std")] use std::mem; -use base::allocator::Allocator; -use base::constraint::{ +use crate::base::allocator::Allocator; +use crate::base::constraint::{ AreMultipliable, DimEq, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint, }; -use base::dimension::{Dim, Dynamic, U1, U2, U3, U4}; -use base::storage::{Storage, StorageMut}; -use base::{DefaultAllocator, Matrix, Scalar, SquareMatrix, Vector, DVectorSlice}; +use crate::base::dimension::{Dim, Dynamic, U1, U2, U3, U4}; +use crate::base::storage::{Storage, StorageMut}; +use crate::base::{DefaultAllocator, Matrix, Scalar, SquareMatrix, Vector, DVectorSlice}; // FIXME: find a way to avoid code duplication just for complex number support. diff --git a/src/base/cg.rs b/src/base/cg.rs index 5883e710..5c1a7c11 100644 --- a/src/base/cg.rs +++ b/src/base/cg.rs @@ -7,14 +7,14 @@ use num::One; -use base::allocator::Allocator; -use base::dimension::{DimName, DimNameDiff, DimNameSub, U1}; -use base::storage::{Storage, StorageMut}; -use base::{ +use crate::base::allocator::Allocator; +use crate::base::dimension::{DimName, DimNameDiff, DimNameSub, U1}; +use crate::base::storage::{Storage, StorageMut}; +use crate::base::{ DefaultAllocator, Matrix3, Matrix4, MatrixN, Scalar, SquareMatrix, Unit, Vector, Vector3, VectorN, }; -use geometry::{ +use crate::geometry::{ Isometry, IsometryMatrix3, Orthographic3, Perspective3, Point, Point3, Rotation2, Rotation3, }; diff --git a/src/base/componentwise.rs b/src/base/componentwise.rs index 9081cf36..e5f4d7ec 100644 --- a/src/base/componentwise.rs +++ b/src/base/componentwise.rs @@ -5,11 +5,11 @@ use std::ops::{Add, Mul}; use alga::general::{ClosedDiv, ClosedMul}; -use base::allocator::{Allocator, SameShapeAllocator}; -use base::constraint::{SameNumberOfColumns, SameNumberOfRows, ShapeConstraint}; -use base::dimension::Dim; -use base::storage::{Storage, StorageMut}; -use base::{DefaultAllocator, Matrix, MatrixMN, MatrixSum, Scalar}; +use crate::base::allocator::{Allocator, SameShapeAllocator}; +use crate::base::constraint::{SameNumberOfColumns, SameNumberOfRows, ShapeConstraint}; +use crate::base::dimension::Dim; +use crate::base::storage::{Storage, StorageMut}; +use crate::base::{DefaultAllocator, Matrix, MatrixMN, MatrixSum, Scalar}; /// The type of the result of a matrix component-wise operation. pub type MatrixComponentOp = MatrixSum; diff --git a/src/base/constraint.rs b/src/base/constraint.rs index 3bd0540b..89226fe3 100644 --- a/src/base/constraint.rs +++ b/src/base/constraint.rs @@ -1,6 +1,6 @@ //! Compatibility constraints between matrix shapes, e.g., for addition or multiplication. -use base::dimension::{Dim, DimName, Dynamic}; +use crate::base::dimension::{Dim, DimName, Dynamic}; /// A type used in `where` clauses for enforcing constraints. pub struct ShapeConstraint; diff --git a/src/base/construction.rs b/src/base/construction.rs index aeee6121..1b05fe61 100644 --- a/src/base/construction.rs +++ b/src/base/construction.rs @@ -1,5 +1,5 @@ #[cfg(feature = "arbitrary")] -use base::storage::Owned; +use crate::base::storage::Owned; #[cfg(feature = "arbitrary")] use quickcheck::{Arbitrary, Gen}; @@ -15,10 +15,10 @@ use typenum::{self, Cmp, Greater}; use alga::general::Real; use alga::general::{ClosedAdd, ClosedMul}; -use base::allocator::Allocator; -use base::dimension::{Dim, DimName, Dynamic, U1, U2, U3, U4, U5, U6}; -use base::storage::Storage; -use base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, Scalar, Unit, Vector, VectorN}; +use crate::base::allocator::Allocator; +use crate::base::dimension::{Dim, DimName, Dynamic, U1, U2, U3, U4, U5, U6}; +use crate::base::storage::Storage; +use crate::base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, Scalar, Unit, Vector, VectorN}; /* * @@ -131,7 +131,7 @@ where DefaultAllocator: Allocator where N: Zero + One { let mut res = Self::zeros_generic(nrows, ncols); - for i in 0..::min(nrows.value(), ncols.value()) { + for i in 0..crate::min(nrows.value(), ncols.value()) { unsafe { *res.get_unchecked_mut((i, i)) = elt } } @@ -147,7 +147,7 @@ where DefaultAllocator: Allocator where N: Zero { let mut res = Self::zeros_generic(nrows, ncols); assert!( - elts.len() <= ::min(nrows.value(), ncols.value()), + elts.len() <= crate::min(nrows.value(), ncols.value()), "Too many diagonal elements provided." ); diff --git a/src/base/construction_slice.rs b/src/base/construction_slice.rs index 419720bf..0946653a 100644 --- a/src/base/construction_slice.rs +++ b/src/base/construction_slice.rs @@ -1,6 +1,6 @@ -use base::dimension::{Dim, DimName, Dynamic, U1}; -use base::matrix_slice::{SliceStorage, SliceStorageMut}; -use base::{MatrixSliceMN, MatrixSliceMutMN, Scalar}; +use crate::base::dimension::{Dim, DimName, Dynamic, U1}; +use crate::base::matrix_slice::{SliceStorage, SliceStorageMut}; +use crate::base::{MatrixSliceMN, MatrixSliceMutMN, Scalar}; /* * diff --git a/src/base/conversion.rs b/src/base/conversion.rs index 750739a6..4c5bb017 100644 --- a/src/base/conversion.rs +++ b/src/base/conversion.rs @@ -9,18 +9,18 @@ use generic_array::ArrayLength; use std::ops::Mul; use typenum::Prod; -use base::allocator::{Allocator, SameShapeAllocator}; -use base::constraint::{SameNumberOfColumns, SameNumberOfRows, ShapeConstraint}; -use base::dimension::{ +use crate::base::allocator::{Allocator, SameShapeAllocator}; +use crate::base::constraint::{SameNumberOfColumns, SameNumberOfRows, ShapeConstraint}; +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 base::dimension::Dynamic; -use base::iter::{MatrixIter, MatrixIterMut}; -use base::storage::{ContiguousStorage, ContiguousStorageMut, Storage, StorageMut}; +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 base::VecStorage; -use base::{DefaultAllocator, Matrix, ArrayStorage, MatrixMN, MatrixSlice, MatrixSliceMut, Scalar}; +use crate::base::VecStorage; +use crate::base::{DefaultAllocator, Matrix, ArrayStorage, MatrixMN, MatrixSlice, MatrixSliceMut, Scalar}; // FIXME: too bad this won't work allo slice conversions. impl SubsetOf> for MatrixMN diff --git a/src/base/coordinates.rs b/src/base/coordinates.rs index 986b8e9d..832723e3 100644 --- a/src/base/coordinates.rs +++ b/src/base/coordinates.rs @@ -7,9 +7,9 @@ use std::mem; use std::ops::{Deref, DerefMut}; -use base::dimension::{U1, U2, U3, U4, U5, U6}; -use base::storage::{ContiguousStorage, ContiguousStorageMut}; -use base::{Matrix, Scalar}; +use crate::base::dimension::{U1, U2, U3, U4, U5, U6}; +use crate::base::storage::{ContiguousStorage, ContiguousStorageMut}; +use crate::base::{Matrix, Scalar}; /* * diff --git a/src/base/default_allocator.rs b/src/base/default_allocator.rs index 5926f39d..c07c8708 100644 --- a/src/base/default_allocator.rs +++ b/src/base/default_allocator.rs @@ -14,15 +14,15 @@ use alloc::vec::Vec; use generic_array::ArrayLength; use typenum::Prod; -use base::allocator::{Allocator, Reallocator}; +use crate::base::allocator::{Allocator, Reallocator}; #[cfg(any(feature = "alloc", feature = "std"))] -use base::dimension::Dynamic; -use base::dimension::{Dim, DimName}; -use base::array_storage::ArrayStorage; +use crate::base::dimension::Dynamic; +use crate::base::dimension::{Dim, DimName}; +use crate::base::array_storage::ArrayStorage; #[cfg(any(feature = "std", feature = "alloc"))] -use base::vec_storage::VecStorage; -use base::storage::{Storage, StorageMut}; -use base::Scalar; +use crate::base::vec_storage::VecStorage; +use crate::base::storage::{Storage, StorageMut}; +use crate::base::Scalar; /* * diff --git a/src/base/edition.rs b/src/base/edition.rs index b95e0fcf..31489f95 100644 --- a/src/base/edition.rs +++ b/src/base/edition.rs @@ -6,17 +6,17 @@ use std::iter::ExactSizeIterator; #[cfg(any(feature = "std", feature = "alloc"))] use std::mem; -use base::allocator::{Allocator, Reallocator}; -use base::constraint::{DimEq, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint}; -use base::dimension::{ +use crate::base::allocator::{Allocator, Reallocator}; +use crate::base::constraint::{DimEq, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint}; +use crate::base::dimension::{ Dim, DimAdd, DimDiff, DimMin, DimMinimum, DimName, DimSub, DimSum, U1, }; #[cfg(any(feature = "std", feature = "alloc"))] -use base::dimension::Dynamic; -use base::storage::{Storage, StorageMut}; +use crate::base::dimension::Dynamic; +use crate::base::storage::{Storage, StorageMut}; #[cfg(any(feature = "std", feature = "alloc"))] -use base::DMatrix; -use base::{DefaultAllocator, Matrix, MatrixMN, RowVector, Scalar, Vector}; +use crate::base::DMatrix; +use crate::base::{DefaultAllocator, Matrix, MatrixMN, RowVector, Scalar, Vector}; impl> Matrix { /// Extracts the upper triangular part of this matrix (including the diagonal). diff --git a/src/base/indexing.rs b/src/base/indexing.rs index 976eef87..ca786530 100644 --- a/src/base/indexing.rs +++ b/src/base/indexing.rs @@ -1,7 +1,7 @@ //! Indexing -use base::{Dim, DimName, DimDiff, DimSub, Dynamic, Matrix, MatrixSlice, MatrixSliceMut, Scalar, U1}; -use base::storage::{Storage, StorageMut}; +use crate::base::{Dim, DimName, DimDiff, DimSub, Dynamic, Matrix, MatrixSlice, MatrixSliceMut, Scalar, U1}; +use crate::base::storage::{Storage, StorageMut}; use std::ops; @@ -42,7 +42,7 @@ impl DimRange for usize { #[test] fn dimrange_usize() { - use base::dimension::U0; + use crate::base::dimension::U0; assert_eq!(DimRange::contained_by(&0, U0), false); assert_eq!(DimRange::contained_by(&0, U1), true); } @@ -69,7 +69,7 @@ impl DimRange for ops::Range { #[test] fn dimrange_range_usize() { use std::usize::MAX; - use base::dimension::U0; + use crate::base::dimension::U0; assert_eq!(DimRange::contained_by(&(0..0), U0), false); assert_eq!(DimRange::contained_by(&(0..1), U0), false); assert_eq!(DimRange::contained_by(&(0..1), U1), true); @@ -101,7 +101,7 @@ impl DimRange for ops::RangeFrom { #[test] fn dimrange_rangefrom_usize() { use std::usize::MAX; - use base::dimension::U0; + use crate::base::dimension::U0; assert_eq!(DimRange::contained_by(&(0..), U0), false); assert_eq!(DimRange::contained_by(&(0..), U0), false); assert_eq!(DimRange::contained_by(&(0..), U1), true); @@ -133,7 +133,7 @@ where D: DimSub #[test] fn dimrange_rangefrom_dimname() { - use base::dimension::{U5, U4}; + use crate::base::dimension::{U5, U4}; assert_eq!(DimRange::length(&(U1..), U5), U4); } @@ -158,7 +158,7 @@ impl DimRange for ops::RangeFull { #[test] fn dimrange_rangefull() { - use base::dimension::U0; + use crate::base::dimension::U0; assert_eq!(DimRange::contained_by(&(..), U0), true); assert_eq!(DimRange::length(&(..), U1), U1); } @@ -190,7 +190,7 @@ impl DimRange for ops::RangeInclusive { #[test] fn dimrange_rangeinclusive_usize() { use std::usize::MAX; - use base::dimension::U0; + use crate::base::dimension::U0; assert_eq!(DimRange::contained_by(&(0..=0), U0), false); assert_eq!(DimRange::contained_by(&(0..=0), U1), true); assert_eq!(DimRange::contained_by(&(MAX..=MAX), Dynamic::new(MAX)), false); @@ -225,7 +225,7 @@ impl DimRange for ops::RangeTo #[test] fn dimrange_rangeto_usize() { use std::usize::MAX; - use base::dimension::U0; + use crate::base::dimension::U0; assert_eq!(DimRange::contained_by(&(..0), U0), true); assert_eq!(DimRange::contained_by(&(..1), U0), false); assert_eq!(DimRange::contained_by(&(..0), U1), true); @@ -257,7 +257,7 @@ impl DimRange for ops::RangeToInclusive #[test] fn dimrange_rangetoinclusive_usize() { use std::usize::MAX; - use base::dimension::U0; + use crate::base::dimension::U0; assert_eq!(DimRange::contained_by(&(..=0), U0), false); assert_eq!(DimRange::contained_by(&(..=1), U0), false); assert_eq!(DimRange::contained_by(&(..=0), U1), true); @@ -627,7 +627,7 @@ macro_rules! impl_index_pair { #[doc(hidden)] #[inline(always)] unsafe fn get_unchecked(self, matrix: &'a Matrix) -> Self::Output { - use base::SliceStorage; + use crate::base::SliceStorage; let (rows, cols) = self; let (nrows, ncols) = matrix.data.shape(); @@ -655,7 +655,7 @@ macro_rules! impl_index_pair { #[doc(hidden)] #[inline(always)] unsafe fn get_unchecked_mut(self, matrix: &'a mut Matrix) -> Self::OutputMut { - use base::SliceStorageMut; + use crate::base::SliceStorageMut; let (rows, cols) = self; let (nrows, ncols) = matrix.data.shape(); diff --git a/src/base/iter.rs b/src/base/iter.rs index 8a5f10ab..74e4f018 100644 --- a/src/base/iter.rs +++ b/src/base/iter.rs @@ -3,9 +3,9 @@ use std::marker::PhantomData; use std::mem; -use base::dimension::{Dim, U1}; -use base::storage::{Storage, StorageMut}; -use base::{Scalar, Matrix, MatrixSlice, MatrixSliceMut}; +use crate::base::dimension::{Dim, U1}; +use crate::base::storage::{Storage, StorageMut}; +use crate::base::{Scalar, Matrix, MatrixSlice, MatrixSliceMut}; macro_rules! iterator { (struct $Name:ident for $Storage:ident.$ptr: ident -> $Ptr:ty, $Ref:ty, $SRef: ty) => { diff --git a/src/base/matrix.rs b/src/base/matrix.rs index 77d49f42..e5060013 100644 --- a/src/base/matrix.rs +++ b/src/base/matrix.rs @@ -18,14 +18,14 @@ use abomonation::Abomonation; use alga::general::{ClosedAdd, ClosedMul, ClosedSub, Real, Ring, Complex, Field}; -use base::allocator::{Allocator, SameShapeAllocator, SameShapeC, SameShapeR}; -use base::constraint::{DimEq, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint}; -use base::dimension::{Dim, DimAdd, DimSum, IsNotStaticOne, U1, U2, U3}; -use base::iter::{MatrixIter, MatrixIterMut, RowIter, RowIterMut, ColumnIter, ColumnIterMut}; -use base::storage::{ +use crate::base::allocator::{Allocator, SameShapeAllocator, SameShapeC, SameShapeR}; +use crate::base::constraint::{DimEq, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint}; +use crate::base::dimension::{Dim, DimAdd, DimSum, IsNotStaticOne, U1, U2, U3}; +use crate::base::iter::{MatrixIter, MatrixIterMut, RowIter, RowIterMut, ColumnIter, ColumnIterMut}; +use crate::base::storage::{ ContiguousStorage, ContiguousStorageMut, Owned, SameShapeStorage, Storage, StorageMut, }; -use base::{DefaultAllocator, MatrixMN, MatrixN, Scalar, Unit, VectorN}; +use crate::base::{DefaultAllocator, MatrixMN, MatrixN, Scalar, Unit, VectorN}; /// A square matrix. pub type SquareMatrix = Matrix; @@ -1111,7 +1111,7 @@ impl> SquareMatrix { assert!(self.is_square(), "Cannot compute the symmetric part of a non-square matrix."); let mut tr = self.transpose(); tr += self; - tr *= ::convert::<_, N>(0.5); + tr *= crate::convert::<_, N>(0.5); tr } @@ -1123,7 +1123,7 @@ impl> SquareMatrix { let mut tr = self.adjoint(); tr += self; - tr *= ::convert::<_, N>(0.5); + tr *= crate::convert::<_, N>(0.5); tr } } @@ -1392,40 +1392,40 @@ where for i in 0..nrows { for j in 0..ncols { lengths[(i, j)] = val_width(self[(i, j)], f); - max_length = ::max(max_length, lengths[(i, j)]); + max_length = crate::max(max_length, lengths[(i, j)]); } } let max_length_with_space = max_length + 1; - try!(writeln!(f)); - try!(writeln!( + writeln!(f)?; + writeln!( f, " ┌ {:>width$} ┐", "", width = max_length_with_space * ncols - 1 - )); + )?; for i in 0..nrows { - try!(write!(f, " │")); + write!(f, " │")?; for j in 0..ncols { let number_length = lengths[(i, j)] + 1; let pad = max_length_with_space - number_length; - try!(write!(f, " {:>thepad$}", "", thepad = pad)); + write!(f, " {:>thepad$}", "", thepad = pad)?; match f.precision() { - Some(precision) => try!(write!(f, "{:.1$}", (*self)[(i, j)], precision)), - None => try!(write!(f, "{}", (*self)[(i, j)])), + Some(precision) => write!(f, "{:.1$}", (*self)[(i, j)], precision)?, + None => write!(f, "{}", (*self)[(i, j)])?, } } - try!(writeln!(f, " │")); + writeln!(f, " │")?; } - try!(writeln!( + writeln!( f, " └ {:>width$} ┘", "", width = max_length_with_space * ncols - 1 - )); + )?; writeln!(f) } } diff --git a/src/base/matrix_alga.rs b/src/base/matrix_alga.rs index 43774f17..87ab584c 100644 --- a/src/base/matrix_alga.rs +++ b/src/base/matrix_alga.rs @@ -13,10 +13,10 @@ use alga::linear::{ FiniteDimInnerSpace, FiniteDimVectorSpace, InnerSpace, NormedSpace, VectorSpace, }; -use base::allocator::Allocator; -use base::dimension::{Dim, DimName}; -use base::storage::{Storage, StorageMut}; -use base::{DefaultAllocator, MatrixMN, MatrixN, Scalar}; +use crate::base::allocator::Allocator; +use crate::base::dimension::{Dim, DimName}; +use crate::base::storage::{Storage, StorageMut}; +use crate::base::{DefaultAllocator, MatrixMN, MatrixN, Scalar}; /* * diff --git a/src/base/matrix_slice.rs b/src/base/matrix_slice.rs index a4ce1533..be53034a 100644 --- a/src/base/matrix_slice.rs +++ b/src/base/matrix_slice.rs @@ -2,12 +2,12 @@ use std::marker::PhantomData; use std::ops::{Range, RangeFrom, RangeFull, RangeTo}; use std::slice; -use base::allocator::Allocator; -use base::default_allocator::DefaultAllocator; -use base::dimension::{Dim, DimName, Dynamic, U1, IsNotStaticOne}; -use base::iter::MatrixIter; -use base::storage::{Owned, Storage, StorageMut, ContiguousStorage, ContiguousStorageMut}; -use base::{Matrix, Scalar}; +use crate::base::allocator::Allocator; +use crate::base::default_allocator::DefaultAllocator; +use crate::base::dimension::{Dim, DimName, Dynamic, U1, IsNotStaticOne}; +use crate::base::iter::MatrixIter; +use crate::base::storage::{Owned, Storage, StorageMut, ContiguousStorage, ContiguousStorageMut}; +use crate::base::{Matrix, Scalar}; macro_rules! slice_storage_impl( ($doc: expr; $Storage: ident as $SRef: ty; $T: ident.$get_addr: ident ($Ptr: ty as $Ref: ty)) => { diff --git a/src/base/norm.rs b/src/base/norm.rs index b3d695e6..91958cec 100644 --- a/src/base/norm.rs +++ b/src/base/norm.rs @@ -1,10 +1,10 @@ use num::Zero; -use allocator::Allocator; -use ::{Real, Complex}; -use storage::{Storage, StorageMut}; -use base::{DefaultAllocator, Matrix, Dim, MatrixMN}; -use constraint::{SameNumberOfRows, SameNumberOfColumns, ShapeConstraint}; +use crate::allocator::Allocator; +use crate::{Real, Complex}; +use crate::storage::{Storage, StorageMut}; +use crate::base::{DefaultAllocator, Matrix, Dim, MatrixMN}; +use crate::constraint::{SameNumberOfRows, SameNumberOfColumns, ShapeConstraint}; // FIXME: this should be be a trait on alga? @@ -54,7 +54,7 @@ impl Norm for LpNorm { where R: Dim, C: Dim, S: Storage { m.fold(N::Real::zero(), |a, b| { a + b.modulus().powi(self.0) - }).powf(::convert(1.0 / (self.0 as f64))) + }).powf(crate::convert(1.0 / (self.0 as f64))) } #[inline] @@ -65,7 +65,7 @@ impl Norm for LpNorm { m1.zip_fold(m2, N::Real::zero(), |acc, a, b| { let diff = a - b; acc + diff.modulus().powi(self.0) - }).powf(::convert(1.0 / (self.0 as f64))) + }).powf(crate::convert(1.0 / (self.0 as f64))) } } diff --git a/src/base/ops.rs b/src/base/ops.rs index f2a683c1..bfc71040 100644 --- a/src/base/ops.rs +++ b/src/base/ops.rs @@ -7,13 +7,13 @@ use std::ops::{ use alga::general::{Complex, ClosedAdd, ClosedDiv, ClosedMul, ClosedNeg, ClosedSub}; -use base::allocator::{Allocator, SameShapeAllocator, SameShapeC, SameShapeR}; -use base::constraint::{ +use crate::base::allocator::{Allocator, SameShapeAllocator, SameShapeC, SameShapeR}; +use crate::base::constraint::{ AreMultipliable, DimEq, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint, }; -use base::dimension::{Dim, DimMul, DimName, DimProd}; -use base::storage::{ContiguousStorageMut, Storage, StorageMut}; -use base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, MatrixSum, Scalar, VectorSliceN}; +use crate::base::dimension::{Dim, DimMul, DimName, DimProd}; +use crate::base::storage::{ContiguousStorageMut, Storage, StorageMut}; +use crate::base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, MatrixSum, Scalar, VectorSliceN}; /* * diff --git a/src/base/properties.rs b/src/base/properties.rs index de6be72a..73019209 100644 --- a/src/base/properties.rs +++ b/src/base/properties.rs @@ -4,10 +4,10 @@ use num::{One, Zero}; use alga::general::{ClosedAdd, ClosedMul, Real, Complex}; -use base::allocator::Allocator; -use base::dimension::{Dim, DimMin}; -use base::storage::Storage; -use base::{DefaultAllocator, Matrix, Scalar, SquareMatrix}; +use crate::base::allocator::Allocator; +use crate::base::dimension::{Dim, DimMin}; +use crate::base::storage::Storage; +use crate::base::{DefaultAllocator, Matrix, Scalar, SquareMatrix}; impl> Matrix { /// Indicates if this is an empty matrix. diff --git a/src/base/statistics.rs b/src/base/statistics.rs index ce162340..0fe18130 100644 --- a/src/base/statistics.rs +++ b/src/base/statistics.rs @@ -1,7 +1,7 @@ -use ::{Scalar, Dim, Matrix, VectorN, RowVectorN, DefaultAllocator, U1, VectorSliceN}; +use crate::{Scalar, Dim, Matrix, VectorN, RowVectorN, DefaultAllocator, U1, VectorSliceN}; use alga::general::{Field, SupersetOf}; -use storage::Storage; -use allocator::Allocator; +use crate::storage::Storage; +use crate::allocator::Allocator; impl> Matrix { /// Returns a row vector where each element is the result of the application of `f` on the @@ -155,7 +155,7 @@ impl, R: Dim, C: Dim, S: Storage> M N::zero() } else { let val = self.iter().cloned().fold((N::zero(), N::zero()), |a, b| (a.0 + b * b, a.1 + b)); - let denom = N::one() / ::convert::<_, N>(self.len() as f64); + let denom = N::one() / crate::convert::<_, N>(self.len() as f64); val.0 * denom - (val.1 * denom) * (val.1 * denom) } } @@ -215,7 +215,7 @@ impl, R: Dim, C: Dim, S: Storage> M let mut mean = self.column_mean(); mean.apply(|e| -(e * e)); - let denom = N::one() / ::convert::<_, N>(ncols.value() as f64); + let denom = N::one() / crate::convert::<_, N>(ncols.value() as f64); self.compress_columns(mean, |out, col| { for i in 0..nrows.value() { unsafe { @@ -247,7 +247,7 @@ impl, R: Dim, C: Dim, S: Storage> M if self.len() == 0 { N::zero() } else { - self.sum() / ::convert(self.len() as f64) + self.sum() / crate::convert(self.len() as f64) } } @@ -302,7 +302,7 @@ impl, R: Dim, C: Dim, S: Storage> M pub fn column_mean(&self) -> VectorN where DefaultAllocator: Allocator { let (nrows, ncols) = self.data.shape(); - let denom = N::one() / ::convert::<_, N>(ncols.value() as f64); + let denom = N::one() / crate::convert::<_, N>(ncols.value() as f64); self.compress_columns(VectorN::zeros_generic(nrows, U1), |out, col| { out.axpy(denom, &col, N::one()) }) diff --git a/src/base/storage.rs b/src/base/storage.rs index 0a07713b..02941e47 100644 --- a/src/base/storage.rs +++ b/src/base/storage.rs @@ -3,10 +3,10 @@ use std::fmt::Debug; use std::mem; -use base::allocator::{Allocator, SameShapeC, SameShapeR}; -use base::default_allocator::DefaultAllocator; -use base::dimension::{Dim, U1}; -use base::Scalar; +use crate::base::allocator::{Allocator, SameShapeC, SameShapeR}; +use crate::base::default_allocator::DefaultAllocator; +use crate::base::dimension::{Dim, U1}; +use crate::base::Scalar; /* * Aliases for allocation results. diff --git a/src/base/swizzle.rs b/src/base/swizzle.rs index b09316d4..4c9b0b63 100644 --- a/src/base/swizzle.rs +++ b/src/base/swizzle.rs @@ -1,5 +1,5 @@ -use base::{DimName, Scalar, Vector, Vector2, Vector3}; -use storage::Storage; +use crate::base::{DimName, Scalar, Vector, Vector2, Vector3}; +use crate::storage::Storage; use typenum::{self, Cmp, Greater}; macro_rules! impl_swizzle { diff --git a/src/base/unit.rs b/src/base/unit.rs index 87a428b5..90b343e1 100644 --- a/src/base/unit.rs +++ b/src/base/unit.rs @@ -104,8 +104,8 @@ impl Unit { #[inline] pub fn renormalize_fast(&mut self) { let sq_norm = self.value.norm_squared(); - let _3: T::Real = ::convert(3.0); - let _0_5: T::Real = ::convert(0.5); + let _3: T::Real = crate::convert(3.0); + let _0_5: T::Real = crate::convert(0.5); self.value *= T::Complex::from_real(_0_5 * (_3 - sq_norm)); } } @@ -168,7 +168,7 @@ where T::Field: RelativeEq #[inline] fn is_in_subset(value: &T) -> bool { - relative_eq!(value.norm_squared(), ::one()) + relative_eq!(value.norm_squared(), crate::one()) } #[inline] diff --git a/src/base/vec_storage.rs b/src/base/vec_storage.rs index afde3677..2b4bf743 100644 --- a/src/base/vec_storage.rs +++ b/src/base/vec_storage.rs @@ -4,12 +4,12 @@ use std::io::{Result as IOResult, Write}; #[cfg(all(feature = "alloc", not(feature = "std")))] use alloc::vec::Vec; -use base::allocator::Allocator; -use base::default_allocator::DefaultAllocator; -use base::dimension::{Dim, DimName, Dynamic, U1}; -use base::storage::{ContiguousStorage, ContiguousStorageMut, Owned, Storage, StorageMut}; -use base::{Scalar, Vector}; -use base::constraint::{SameNumberOfRows, ShapeConstraint}; +use crate::base::allocator::Allocator; +use crate::base::default_allocator::DefaultAllocator; +use crate::base::dimension::{Dim, DimName, Dynamic, U1}; +use crate::base::storage::{ContiguousStorage, ContiguousStorageMut, Owned, Storage, StorageMut}; +use crate::base::{Scalar, Vector}; +use crate::base::constraint::{SameNumberOfRows, ShapeConstraint}; #[cfg(feature = "abomonation-serialize")] use abomonation::Abomonation; diff --git a/src/debug/random_orthogonal.rs b/src/debug/random_orthogonal.rs index 94035109..b14c7da4 100644 --- a/src/debug/random_orthogonal.rs +++ b/src/debug/random_orthogonal.rs @@ -1,14 +1,14 @@ #[cfg(feature = "arbitrary")] -use base::storage::Owned; +use crate::base::storage::Owned; #[cfg(feature = "arbitrary")] use quickcheck::{Arbitrary, Gen}; use alga::general::Complex; -use base::Scalar; -use base::allocator::Allocator; -use base::dimension::{Dim, Dynamic, U2}; -use base::{DefaultAllocator, MatrixN}; -use linalg::givens::GivensRotation; +use crate::base::Scalar; +use crate::base::allocator::Allocator; +use crate::base::dimension::{Dim, Dynamic, U2}; +use crate::base::{DefaultAllocator, MatrixN}; +use crate::linalg::givens::GivensRotation; /// A random orthogonal matrix. #[derive(Clone, Debug)] diff --git a/src/debug/random_sdp.rs b/src/debug/random_sdp.rs index f8ee6d30..ca3f122f 100644 --- a/src/debug/random_sdp.rs +++ b/src/debug/random_sdp.rs @@ -1,15 +1,15 @@ #[cfg(feature = "arbitrary")] -use base::storage::Owned; +use crate::base::storage::Owned; #[cfg(feature = "arbitrary")] use quickcheck::{Arbitrary, Gen}; use alga::general::Complex; -use base::Scalar; -use base::allocator::Allocator; -use base::dimension::{Dim, Dynamic}; -use base::{DefaultAllocator, MatrixN}; +use crate::base::Scalar; +use crate::base::allocator::Allocator; +use crate::base::dimension::{Dim, Dynamic}; +use crate::base::{DefaultAllocator, MatrixN}; -use debug::RandomOrthogonal; +use crate::debug::RandomOrthogonal; /// A random, well-conditioned, symmetric definite-positive matrix. #[derive(Clone, Debug)] diff --git a/src/geometry/isometry.rs b/src/geometry/isometry.rs index 0d3c6619..f77d4d60 100644 --- a/src/geometry/isometry.rs +++ b/src/geometry/isometry.rs @@ -14,11 +14,11 @@ use abomonation::Abomonation; use alga::general::{Real, SubsetOf}; use alga::linear::Rotation; -use base::allocator::Allocator; -use base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; -use base::storage::Owned; -use base::{DefaultAllocator, MatrixN}; -use geometry::{Point, Translation}; +use crate::base::allocator::Allocator; +use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; +use crate::base::storage::Owned; +use crate::base::{DefaultAllocator, MatrixN}; +use crate::geometry::{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)] @@ -285,7 +285,7 @@ where DefaultAllocator: Allocator R: SubsetOf>>, DefaultAllocator: Allocator, DimNameSum>, { - let mut res: MatrixN = ::convert_ref(&self.rotation); + let mut res: MatrixN = crate::convert_ref(&self.rotation); res.fixed_slice_mut::(0, D::dim()) .copy_from(&self.translation.vector); @@ -390,9 +390,9 @@ where fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let precision = f.precision().unwrap_or(3); - try!(writeln!(f, "Isometry {{")); - try!(write!(f, "{:.*}", precision, self.translation)); - try!(write!(f, "{:.*}", precision, self.rotation)); + writeln!(f, "Isometry {{")?; + write!(f, "{:.*}", precision, self.translation)?; + write!(f, "{:.*}", precision, self.rotation)?; writeln!(f, "}}") } } diff --git a/src/geometry/isometry_alga.rs b/src/geometry/isometry_alga.rs index 246947ca..eb9a5cd5 100644 --- a/src/geometry/isometry_alga.rs +++ b/src/geometry/isometry_alga.rs @@ -8,11 +8,11 @@ use alga::linear::{ Transformation, }; -use base::allocator::Allocator; -use base::dimension::DimName; -use base::{DefaultAllocator, VectorN}; +use crate::base::allocator::Allocator; +use crate::base::dimension::DimName; +use crate::base::{DefaultAllocator, VectorN}; -use geometry::{Isometry, Point, Translation}; +use crate::geometry::{Isometry, Point, Translation}; /* * diff --git a/src/geometry/isometry_alias.rs b/src/geometry/isometry_alias.rs index a0804b5c..ba9a69e7 100644 --- a/src/geometry/isometry_alias.rs +++ b/src/geometry/isometry_alias.rs @@ -1,6 +1,6 @@ -use base::dimension::{U2, U3}; +use crate::base::dimension::{U2, U3}; -use geometry::{Isometry, Rotation2, Rotation3, UnitComplex, UnitQuaternion}; +use crate::geometry::{Isometry, Rotation2, Rotation3, UnitComplex, UnitQuaternion}; /// A 2-dimensional direct isometry using a unit complex number for its rotational part. Also known as a rigid-body motion, or as an element of SE(2). pub type Isometry2 = Isometry>; diff --git a/src/geometry/isometry_construction.rs b/src/geometry/isometry_construction.rs index 5a402c0a..3863051c 100644 --- a/src/geometry/isometry_construction.rs +++ b/src/geometry/isometry_construction.rs @@ -1,5 +1,5 @@ #[cfg(feature = "arbitrary")] -use base::storage::Owned; +use crate::base::storage::Owned; #[cfg(feature = "arbitrary")] use quickcheck::{Arbitrary, Gen}; @@ -10,11 +10,11 @@ use rand::Rng; use alga::general::Real; use alga::linear::Rotation as AlgaRotation; -use base::allocator::Allocator; -use base::dimension::{DimName, U2, U3}; -use base::{DefaultAllocator, Vector2, Vector3}; +use crate::base::allocator::Allocator; +use crate::base::dimension::{DimName, U2, U3}; +use crate::base::{DefaultAllocator, Vector2, Vector3}; -use geometry::{ +use crate::geometry::{ Isometry, Point, Point3, Rotation, Rotation2, Rotation3, Translation, UnitComplex, UnitQuaternion, Translation2, Translation3 }; diff --git a/src/geometry/isometry_conversion.rs b/src/geometry/isometry_conversion.rs index 5dc46009..0ce92aca 100644 --- a/src/geometry/isometry_conversion.rs +++ b/src/geometry/isometry_conversion.rs @@ -1,11 +1,11 @@ use alga::general::{Real, SubsetOf, SupersetOf}; use alga::linear::Rotation; -use base::allocator::Allocator; -use base::dimension::{DimMin, DimName, DimNameAdd, DimNameSum, U1}; -use base::{DefaultAllocator, MatrixN}; +use crate::base::allocator::Allocator; +use crate::base::dimension::{DimMin, DimName, DimNameAdd, DimNameSum, U1}; +use crate::base::{DefaultAllocator, MatrixN}; -use geometry::{Isometry, Point, Similarity, SuperTCategoryOf, TAffine, Transform, Translation}; +use crate::geometry::{Isometry, Point, Similarity, SuperTCategoryOf, TAffine, Transform, Translation}; /* * This file provides the following conversions: @@ -32,8 +32,8 @@ where #[inline] fn is_in_subset(iso: &Isometry) -> bool { - ::is_convertible::<_, Translation>(&iso.translation) - && ::is_convertible::<_, R1>(&iso.rotation) + crate::is_convertible::<_, Translation>(&iso.translation) + && crate::is_convertible::<_, R1>(&iso.rotation) } #[inline] @@ -60,12 +60,12 @@ where #[inline] fn is_in_subset(sim: &Similarity) -> bool { - ::is_convertible::<_, Isometry>(&sim.isometry) && sim.scaling() == N2::one() + crate::is_convertible::<_, Isometry>(&sim.isometry) && sim.scaling() == N2::one() } #[inline] unsafe fn from_superset_unchecked(sim: &Similarity) -> Self { - ::convert_ref_unchecked(&sim.isometry) + crate::convert_ref_unchecked(&sim.isometry) } } @@ -133,7 +133,7 @@ where // Scalar types agree. m.iter().all(|e| SupersetOf::::is_in_subset(e)) && // The block part is a rotation. - rot.is_special_orthogonal(N2::default_epsilon() * ::convert(100.0)) && + rot.is_special_orthogonal(N2::default_epsilon() * crate::convert(100.0)) && // The bottom row is (0, 0, ..., 1) bottom.iter().all(|e| e.is_zero()) && m[(D::dim(), D::dim())] == N2::one() } @@ -142,10 +142,10 @@ where unsafe fn from_superset_unchecked(m: &MatrixN>) -> Self { let t = m.fixed_slice::(0, D::dim()).into_owned(); let t = Translation { - vector: ::convert_unchecked(t), + vector: crate::convert_unchecked(t), }; - Self::from_parts(t, ::convert_unchecked(m.clone_owned())) + Self::from_parts(t, crate::convert_unchecked(m.clone_owned())) } } diff --git a/src/geometry/isometry_ops.rs b/src/geometry/isometry_ops.rs index 6a4b921e..b0da4b62 100644 --- a/src/geometry/isometry_ops.rs +++ b/src/geometry/isometry_ops.rs @@ -3,11 +3,11 @@ use std::ops::{Div, DivAssign, Mul, MulAssign}; use alga::general::Real; use alga::linear::Rotation as AlgaRotation; -use base::allocator::Allocator; -use base::dimension::{DimName, U1, U3, U4}; -use base::{DefaultAllocator, Unit, VectorN}; +use crate::base::allocator::Allocator; +use crate::base::dimension::{DimName, U1, U3, U4}; +use crate::base::{DefaultAllocator, Unit, VectorN}; -use geometry::{Isometry, Point, Rotation, Translation, UnitQuaternion}; +use crate::geometry::{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>` diff --git a/src/geometry/orthographic.rs b/src/geometry/orthographic.rs index 3117c1b6..af86a876 100644 --- a/src/geometry/orthographic.rs +++ b/src/geometry/orthographic.rs @@ -9,12 +9,12 @@ use std::mem; use alga::general::Real; -use base::dimension::U3; -use base::helper; -use base::storage::Storage; -use base::{Matrix4, Vector, Vector3}; +use crate::base::dimension::U3; +use crate::base::helper; +use crate::base::storage::Storage; +use crate::base::{Matrix4, Vector, Vector3}; -use geometry::{Point3, Projective3}; +use crate::geometry::{Point3, Projective3}; /// A 3D orthographic projection stored as an homogeneous 4x4 matrix. pub struct Orthographic3 { @@ -150,7 +150,7 @@ impl Orthographic3 { "The apsect ratio must not be zero." ); - let half: N = ::convert(0.5); + let half: N = crate::convert(0.5); let width = zfar * (vfov * half).tan(); let height = width / aspect; @@ -623,7 +623,7 @@ impl Orthographic3 { left != right, "The left corner must not be equal to the right corner." ); - self.matrix[(0, 0)] = ::convert::<_, N>(2.0) / (right - left); + self.matrix[(0, 0)] = crate::convert::<_, N>(2.0) / (right - left); self.matrix[(0, 3)] = -(right + left) / (right - left); } @@ -648,7 +648,7 @@ impl Orthographic3 { bottom != top, "The top corner must not be equal to the bottom corner." ); - self.matrix[(1, 1)] = ::convert::<_, N>(2.0) / (top - bottom); + self.matrix[(1, 1)] = crate::convert::<_, N>(2.0) / (top - bottom); self.matrix[(1, 3)] = -(top + bottom) / (top - bottom); } @@ -673,7 +673,7 @@ impl Orthographic3 { zfar != znear, "The near-plane and far-plane must not be superimposed." ); - self.matrix[(2, 2)] = -::convert::<_, N>(2.0) / (zfar - znear); + self.matrix[(2, 2)] = -crate::convert::<_, N>(2.0) / (zfar - znear); self.matrix[(2, 3)] = -(zfar + znear) / (zfar - znear); } } diff --git a/src/geometry/perspective.rs b/src/geometry/perspective.rs index 550469be..c8125d99 100644 --- a/src/geometry/perspective.rs +++ b/src/geometry/perspective.rs @@ -10,12 +10,12 @@ use std::mem; use alga::general::Real; -use base::dimension::U3; -use base::helper; -use base::storage::Storage; -use base::{Matrix4, Scalar, Vector, Vector3}; +use crate::base::dimension::U3; +use crate::base::helper; +use crate::base::storage::Storage; +use crate::base::{Matrix4, Scalar, Vector, Vector3}; -use geometry::{Point3, Projective3}; +use crate::geometry::{Point3, Projective3}; /// A 3D perspective projection stored as an homogeneous 4x4 matrix. pub struct Perspective3 { @@ -162,7 +162,7 @@ impl Perspective3 { /// Gets the y field of view of the view frustum. #[inline] pub fn fovy(&self) -> N { - (N::one() / self.matrix[(1, 1)]).atan() * ::convert(2.0) + (N::one() / self.matrix[(1, 1)]).atan() * crate::convert(2.0) } /// Gets the near plane offset of the view frustum. @@ -170,7 +170,7 @@ 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 * ::convert(2.0)) - self.matrix[(2, 3)] / ::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. @@ -178,7 +178,7 @@ impl Perspective3 { pub fn zfar(&self) -> N { let ratio = (-self.matrix[(2, 2)] + N::one()) / (-self.matrix[(2, 2)] - N::one()); - (self.matrix[(2, 3)] - ratio * self.matrix[(2, 3)]) / ::convert(2.0) + (self.matrix[(2, 3)] - ratio * self.matrix[(2, 3)]) / crate::convert(2.0) } // FIXME: add a method to retrieve znear and zfar simultaneously? @@ -235,7 +235,7 @@ impl Perspective3 { #[inline] pub fn set_fovy(&mut self, fovy: N) { let old_m22 = self.matrix[(1, 1)]; - self.matrix[(1, 1)] = N::one() / (fovy / ::convert(2.0)).tan(); + self.matrix[(1, 1)] = N::one() / (fovy / crate::convert(2.0)).tan(); self.matrix[(0, 0)] = self.matrix[(0, 0)] * (self.matrix[(1, 1)] / old_m22); } @@ -257,7 +257,7 @@ impl Perspective3 { #[inline] pub fn set_znear_and_zfar(&mut self, znear: N, zfar: N) { self.matrix[(2, 2)] = (zfar + znear) / (znear - zfar); - self.matrix[(2, 3)] = zfar * znear * ::convert(2.0) / (znear - zfar); + self.matrix[(2, 3)] = zfar * znear * crate::convert(2.0) / (znear - zfar); } } diff --git a/src/geometry/point.rs b/src/geometry/point.rs index 14ce7dc2..04338d2a 100644 --- a/src/geometry/point.rs +++ b/src/geometry/point.rs @@ -12,10 +12,10 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; #[cfg(feature = "abomonation-serialize")] use abomonation::Abomonation; -use base::allocator::Allocator; -use base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; -use base::iter::{MatrixIter, MatrixIterMut}; -use base::{DefaultAllocator, Scalar, VectorN}; +use crate::base::allocator::Allocator; +use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; +use crate::base::iter::{MatrixIter, MatrixIterMut}; +use crate::base::{DefaultAllocator, Scalar, VectorN}; /// A point in a n-dimensional euclidean space. #[repr(C)] @@ -316,14 +316,14 @@ impl fmt::Display for Point where DefaultAllocator: Allocator { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "{{")); + write!(f, "{{")?; let mut it = self.coords.iter(); - try!(write!(f, "{}", *it.next().unwrap())); + write!(f, "{}", *it.next().unwrap())?; for comp in it { - try!(write!(f, ", {}", *comp)); + write!(f, ", {}", *comp)?; } write!(f, "}}") diff --git a/src/geometry/point_alga.rs b/src/geometry/point_alga.rs index 2f81ceff..c95cb5b2 100644 --- a/src/geometry/point_alga.rs +++ b/src/geometry/point_alga.rs @@ -1,11 +1,11 @@ use alga::general::{Field, JoinSemilattice, Lattice, MeetSemilattice, Real}; use alga::linear::{AffineSpace, EuclideanSpace}; -use base::allocator::Allocator; -use base::dimension::DimName; -use base::{DefaultAllocator, Scalar, VectorN}; +use crate::base::allocator::Allocator; +use crate::base::dimension::DimName; +use crate::base::{DefaultAllocator, Scalar, VectorN}; -use geometry::Point; +use crate::geometry::Point; impl AffineSpace for Point where diff --git a/src/geometry/point_alias.rs b/src/geometry/point_alias.rs index 42086d04..83f57301 100644 --- a/src/geometry/point_alias.rs +++ b/src/geometry/point_alias.rs @@ -1,6 +1,6 @@ -use base::dimension::{U1, U2, U3, U4, U5, U6}; +use crate::base::dimension::{U1, U2, U3, U4, U5, U6}; -use geometry::Point; +use crate::geometry::Point; /// A statically sized 1-dimensional column point. pub type Point1 = Point; diff --git a/src/geometry/point_construction.rs b/src/geometry/point_construction.rs index b6c46779..2fac11d4 100644 --- a/src/geometry/point_construction.rs +++ b/src/geometry/point_construction.rs @@ -6,11 +6,11 @@ use rand::distributions::{Distribution, Standard}; use rand::Rng; use alga::general::ClosedDiv; -use base::allocator::Allocator; -use base::dimension::{DimName, DimNameAdd, DimNameSum, U1, U2, U3, U4, U5, U6}; -use base::{DefaultAllocator, Scalar, VectorN}; +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 geometry::Point; +use crate::geometry::Point; impl Point where DefaultAllocator: Allocator @@ -28,7 +28,7 @@ where DefaultAllocator: Allocator /// ``` /// # use nalgebra::{Point2, Point3}; /// // This works in any dimension. - /// // The explicit :: type annotation may not always be needed, + /// // The explicit crate:: type annotation may not always be needed, /// // depending on the context of type inference. /// let pt = Point2::::origin(); /// assert!(pt.x == 0.0 && pt.y == 0.0); diff --git a/src/geometry/point_conversion.rs b/src/geometry/point_conversion.rs index 50a3a4d2..10438165 100644 --- a/src/geometry/point_conversion.rs +++ b/src/geometry/point_conversion.rs @@ -1,15 +1,15 @@ use alga::general::{ClosedDiv, SubsetOf, SupersetOf}; use num::{One, Zero}; -use base::allocator::Allocator; -use base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; -use base::{DefaultAllocator, Matrix, Scalar, VectorN}; +use crate::base::allocator::Allocator; +use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; +use crate::base::{DefaultAllocator, Matrix, Scalar, VectorN}; #[cfg(feature = "mint")] -use base::dimension::{U2, U3}; +use crate::base::dimension::{U2, U3}; #[cfg(feature = "mint")] -use base::storage::{Storage, StorageMut}; -use geometry::Point; +use crate::base::storage::{Storage, StorageMut}; +use crate::geometry::Point; #[cfg(feature = "mint")] use mint; #[cfg(feature = "mint")] @@ -67,14 +67,14 @@ where #[inline] fn is_in_subset(v: &VectorN>) -> bool { - ::is_convertible::<_, VectorN>>(v) && !v[D::dim()].is_zero() + crate::is_convertible::<_, VectorN>>(v) && !v[D::dim()].is_zero() } #[inline] unsafe fn from_superset_unchecked(v: &VectorN>) -> Self { let coords = v.fixed_slice::(0, 0) / v[D::dim()]; Self { - coords: ::convert_unchecked(coords) + coords: crate::convert_unchecked(coords) } } } diff --git a/src/geometry/point_coordinates.rs b/src/geometry/point_coordinates.rs index b24ec052..b56e120e 100644 --- a/src/geometry/point_coordinates.rs +++ b/src/geometry/point_coordinates.rs @@ -1,12 +1,12 @@ use std::mem; use std::ops::{Deref, DerefMut}; -use base::allocator::Allocator; -use base::coordinates::{X, XY, XYZ, XYZW, XYZWA, XYZWAB}; -use base::dimension::{U1, U2, U3, U4, U5, U6}; -use base::{DefaultAllocator, Scalar}; +use crate::base::allocator::Allocator; +use crate::base::coordinates::{X, XY, XYZ, XYZW, XYZWA, XYZWAB}; +use crate::base::dimension::{U1, U2, U3, U4, U5, U6}; +use crate::base::{DefaultAllocator, Scalar}; -use geometry::Point; +use crate::geometry::Point; /* * diff --git a/src/geometry/point_ops.rs b/src/geometry/point_ops.rs index 0a20bc90..b49495f8 100644 --- a/src/geometry/point_ops.rs +++ b/src/geometry/point_ops.rs @@ -5,13 +5,13 @@ use std::ops::{ use alga::general::{ClosedAdd, ClosedDiv, ClosedMul, ClosedNeg, ClosedSub}; -use base::allocator::{Allocator, SameShapeAllocator}; -use base::constraint::{AreMultipliable, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint}; -use base::dimension::{Dim, DimName, U1}; -use base::storage::Storage; -use base::{DefaultAllocator, Matrix, Scalar, Vector, VectorSum}; +use crate::base::allocator::{Allocator, SameShapeAllocator}; +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}; -use geometry::Point; +use crate::geometry::Point; /* * diff --git a/src/geometry/quaternion.rs b/src/geometry/quaternion.rs index b58d885c..3beab4bb 100644 --- a/src/geometry/quaternion.rs +++ b/src/geometry/quaternion.rs @@ -6,7 +6,7 @@ use std::hash; use std::io::{Result as IOResult, Write}; #[cfg(feature = "serde-serialize")] -use base::storage::Owned; +use crate::base::storage::Owned; #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Deserializer, Serialize, Serializer}; @@ -15,11 +15,11 @@ use abomonation::Abomonation; use alga::general::Real; -use base::dimension::{U1, U3, U4}; -use base::storage::{CStride, RStride}; -use base::{Matrix3, MatrixN, MatrixSlice, MatrixSliceMut, Unit, Vector3, Vector4}; +use crate::base::dimension::{U1, U3, U4}; +use crate::base::storage::{CStride, RStride}; +use crate::base::{Matrix3, MatrixN, MatrixSlice, MatrixSliceMut, Unit, Vector3, Vector4}; -use geometry::Rotation; +use crate::geometry::Rotation; /// A quaternion. See the type alias `UnitQuaternion = Unit` for a quaternion /// that may be used as a rotation. @@ -225,7 +225,7 @@ impl Quaternion { /// # use nalgebra::{Vector4, Quaternion}; /// let q = Quaternion::new(1.0, 2.0, 3.0, 4.0); /// // Recall that the quaternion is stored internally as (i, j, k, w) - /// // while the ::new constructor takes the arguments as (w, i, j, k). + /// // while the crate::new constructor takes the arguments as (w, i, j, k). /// assert_eq!(*q.as_vector(), Vector4::new(2.0, 3.0, 4.0, 1.0)); /// ``` #[inline] @@ -325,7 +325,7 @@ impl Quaternion { pub fn polar_decomposition(&self) -> (N, N, Option>>) { if let Some((q, n)) = Unit::try_new_and_get(*self, N::zero()) { if let Some(axis) = Unit::try_new(self.vector().clone_owned(), N::zero()) { - let angle = q.angle() / ::convert(2.0f64); + let angle = q.angle() / crate::convert(2.0f64); (n, angle, Some(axis)) } else { @@ -607,7 +607,7 @@ impl UnitQuaternion { if w >= N::one() { N::zero() } else { - w.acos() * ::convert(2.0f64) + w.acos() * crate::convert(2.0f64) } } @@ -937,12 +937,12 @@ impl UnitQuaternion { let ii = i * i; let jj = j * j; let kk = k * k; - let ij = i * j * ::convert(2.0f64); - let wk = w * k * ::convert(2.0f64); - let wj = w * j * ::convert(2.0f64); - let ik = i * k * ::convert(2.0f64); - let jk = j * k * ::convert(2.0f64); - let wi = w * i * ::convert(2.0f64); + let ij = i * j * crate::convert(2.0f64); + let wk = w * k * crate::convert(2.0f64); + let wj = w * j * crate::convert(2.0f64); + let ik = i * k * crate::convert(2.0f64); + let jk = j * k * crate::convert(2.0f64); + let wi = w * i * crate::convert(2.0f64); Rotation::from_matrix_unchecked(Matrix3::new( ww + ii - jj - kk, diff --git a/src/geometry/quaternion_alga.rs b/src/geometry/quaternion_alga.rs index 22534b1a..b1c9a1ba 100644 --- a/src/geometry/quaternion_alga.rs +++ b/src/geometry/quaternion_alga.rs @@ -11,8 +11,8 @@ use alga::linear::{ VectorSpace, }; -use base::{Vector3, Vector4}; -use geometry::{Point3, Quaternion, UnitQuaternion}; +use crate::base::{Vector3, Vector4}; +use crate::geometry::{Point3, Quaternion, UnitQuaternion}; impl Identity for Quaternion { #[inline] diff --git a/src/geometry/quaternion_construction.rs b/src/geometry/quaternion_construction.rs index 0a30fabe..ff72061f 100644 --- a/src/geometry/quaternion_construction.rs +++ b/src/geometry/quaternion_construction.rs @@ -1,7 +1,7 @@ #[cfg(feature = "arbitrary")] -use base::dimension::U4; +use crate::base::dimension::U4; #[cfg(feature = "arbitrary")] -use base::storage::Owned; +use crate::base::storage::Owned; #[cfg(feature = "arbitrary")] use quickcheck::{Arbitrary, Gen}; @@ -11,13 +11,13 @@ use rand::Rng; use alga::general::Real; -use base::dimension::U3; -use base::storage::Storage; +use crate::base::dimension::U3; +use crate::base::storage::Storage; #[cfg(feature = "arbitrary")] -use base::Vector3; -use base::{Unit, Vector, Vector4, Matrix3}; +use crate::base::Vector3; +use crate::base::{Unit, Vector, Vector4, Matrix3}; -use geometry::{Quaternion, Rotation3, UnitQuaternion}; +use crate::geometry::{Quaternion, Rotation3, UnitQuaternion}; impl Quaternion { /// Creates a quaternion from a 4D vector. The quaternion scalar part corresponds to the `w` @@ -74,7 +74,7 @@ impl Quaternion { // 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 * ::convert(2.0f64)); + let rot = UnitQuaternion::::from_axis_angle(&axis, theta * crate::convert(2.0f64)); rot.into_inner() * scale } @@ -186,7 +186,7 @@ impl UnitQuaternion { #[inline] pub fn from_axis_angle(axis: &Unit>, angle: N) -> Self where SB: Storage { - let (sang, cang) = (angle / ::convert(2.0f64)).sin_cos(); + let (sang, cang) = (angle / crate::convert(2.0f64)).sin_cos(); let q = Quaternion::from_parts(cang, axis.as_ref() * sang); Self::new_unchecked(q) @@ -216,9 +216,9 @@ impl UnitQuaternion { /// ``` #[inline] pub fn from_euler_angles(roll: N, pitch: N, yaw: N) -> Self { - let (sr, cr) = (roll * ::convert(0.5f64)).sin_cos(); - let (sp, cp) = (pitch * ::convert(0.5f64)).sin_cos(); - let (sy, cy) = (yaw * ::convert(0.5f64)).sin_cos(); + let (sr, cr) = (roll * crate::convert(0.5f64)).sin_cos(); + let (sp, cp) = (pitch * crate::convert(0.5f64)).sin_cos(); + let (sy, cy) = (yaw * crate::convert(0.5f64)).sin_cos(); let q = Quaternion::new( cr * cp * cy + sr * sp * sy, @@ -251,10 +251,10 @@ impl UnitQuaternion { let tr = rotmat[(0, 0)] + rotmat[(1, 1)] + rotmat[(2, 2)]; let res; - let _0_25: N = ::convert(0.25); + let _0_25: N = crate::convert(0.25); if tr > N::zero() { - let denom = (tr + N::one()).sqrt() * ::convert(2.0); + let denom = (tr + N::one()).sqrt() * crate::convert(2.0); res = Quaternion::new( _0_25 * denom, (rotmat[(2, 1)] - rotmat[(1, 2)]) / denom, @@ -263,7 +263,7 @@ impl UnitQuaternion { ); } else if rotmat[(0, 0)] > rotmat[(1, 1)] && rotmat[(0, 0)] > rotmat[(2, 2)] { let denom = (N::one() + rotmat[(0, 0)] - rotmat[(1, 1)] - rotmat[(2, 2)]).sqrt() - * ::convert(2.0); + * crate::convert(2.0); res = Quaternion::new( (rotmat[(2, 1)] - rotmat[(1, 2)]) / denom, _0_25 * denom, @@ -272,7 +272,7 @@ impl UnitQuaternion { ); } else if rotmat[(1, 1)] > rotmat[(2, 2)] { let denom = (N::one() + rotmat[(1, 1)] - rotmat[(0, 0)] - rotmat[(2, 2)]).sqrt() - * ::convert(2.0); + * crate::convert(2.0); res = Quaternion::new( (rotmat[(0, 2)] - rotmat[(2, 0)]) / denom, (rotmat[(0, 1)] + rotmat[(1, 0)]) / denom, @@ -281,7 +281,7 @@ impl UnitQuaternion { ); } else { let denom = (N::one() + rotmat[(2, 2)] - rotmat[(0, 0)] - rotmat[(1, 1)]).sqrt() - * ::convert(2.0); + * crate::convert(2.0); res = Quaternion::new( (rotmat[(1, 0)] - rotmat[(0, 1)]) / denom, (rotmat[(0, 2)] + rotmat[(2, 0)]) / denom, @@ -578,7 +578,7 @@ impl UnitQuaternion { #[inline] pub fn new(axisangle: Vector) -> Self where SB: Storage { - let two: N = ::convert(2.0f64); + let two: N = crate::convert(2.0f64); let q = Quaternion::::from_parts(N::zero(), axisangle / two).exp(); Self::new_unchecked(q) } @@ -607,7 +607,7 @@ impl UnitQuaternion { #[inline] pub fn new_eps(axisangle: Vector, eps: N) -> Self where SB: Storage { - let two: N = ::convert(2.0f64); + let two: N = crate::convert(2.0f64); let q = Quaternion::::from_parts(N::zero(), axisangle / two).exp_eps(eps); Self::new_unchecked(q) } diff --git a/src/geometry/quaternion_conversion.rs b/src/geometry/quaternion_conversion.rs index a0b44390..cd5d9f0c 100644 --- a/src/geometry/quaternion_conversion.rs +++ b/src/geometry/quaternion_conversion.rs @@ -6,9 +6,9 @@ use alga::linear::Rotation as AlgaRotation; #[cfg(feature = "mint")] use mint; -use base::dimension::U3; -use base::{Matrix3, Matrix4, Vector4}; -use geometry::{ +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, }; @@ -44,7 +44,7 @@ where #[inline] fn is_in_subset(q: &Quaternion) -> bool { - ::is_convertible::<_, Vector4>(&q.coords) + crate::is_convertible::<_, Vector4>(&q.coords) } #[inline] @@ -67,12 +67,12 @@ where #[inline] fn is_in_subset(uq: &UnitQuaternion) -> bool { - ::is_convertible::<_, Quaternion>(uq.as_ref()) + crate::is_convertible::<_, Quaternion>(uq.as_ref()) } #[inline] unsafe fn from_superset_unchecked(uq: &UnitQuaternion) -> Self { - Self::new_unchecked(::convert_ref_unchecked(uq.as_ref())) + Self::new_unchecked(crate::convert_ref_unchecked(uq.as_ref())) } } @@ -89,13 +89,13 @@ where #[inline] fn is_in_subset(rot: &Rotation3) -> bool { - ::is_convertible::<_, Rotation3>(rot) + crate::is_convertible::<_, Rotation3>(rot) } #[inline] unsafe fn from_superset_unchecked(rot: &Rotation3) -> Self { let q = UnitQuaternion::::from_rotation_matrix(rot); - ::convert_unchecked(q) + crate::convert_unchecked(q) } } @@ -107,7 +107,7 @@ where { #[inline] fn to_superset(&self) -> Isometry { - Isometry::from_parts(Translation::identity(), ::convert_ref(self)) + Isometry::from_parts(Translation::identity(), crate::convert_ref(self)) } #[inline] @@ -117,7 +117,7 @@ where #[inline] unsafe fn from_superset_unchecked(iso: &Isometry) -> Self { - ::convert_ref_unchecked(&iso.rotation) + crate::convert_ref_unchecked(&iso.rotation) } } @@ -129,7 +129,7 @@ where { #[inline] fn to_superset(&self) -> Similarity { - Similarity::from_isometry(::convert_ref(self), N2::one()) + Similarity::from_isometry(crate::convert_ref(self), N2::one()) } #[inline] @@ -139,7 +139,7 @@ where #[inline] unsafe fn from_superset_unchecked(sim: &Similarity) -> Self { - ::convert_ref_unchecked(&sim.isometry) + crate::convert_ref_unchecked(&sim.isometry) } } @@ -173,12 +173,12 @@ impl> SubsetOf> for UnitQuaterni #[inline] fn is_in_subset(m: &Matrix4) -> bool { - ::is_convertible::<_, Rotation3>(m) + crate::is_convertible::<_, Rotation3>(m) } #[inline] unsafe fn from_superset_unchecked(m: &Matrix4) -> Self { - let rot: Rotation3 = ::convert_ref_unchecked(m); + let rot: Rotation3 = crate::convert_ref_unchecked(m); Self::from_rotation_matrix(&rot) } } diff --git a/src/geometry/quaternion_coordinates.rs b/src/geometry/quaternion_coordinates.rs index 228f74bf..05d5af13 100644 --- a/src/geometry/quaternion_coordinates.rs +++ b/src/geometry/quaternion_coordinates.rs @@ -3,9 +3,9 @@ use std::ops::{Deref, DerefMut}; use alga::general::Real; -use base::coordinates::IJKW; +use crate::base::coordinates::IJKW; -use geometry::Quaternion; +use crate::geometry::Quaternion; impl Deref for Quaternion { type Target = IJKW; diff --git a/src/geometry/quaternion_ops.rs b/src/geometry/quaternion_ops.rs index 2ed72453..3fc840ff 100644 --- a/src/geometry/quaternion_ops.rs +++ b/src/geometry/quaternion_ops.rs @@ -56,12 +56,12 @@ use std::ops::{ use alga::general::Real; -use base::allocator::Allocator; -use base::dimension::{U1, U3, U4}; -use base::storage::Storage; -use base::{DefaultAllocator, Unit, Vector, Vector3}; +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 geometry::{Point3, Quaternion, Rotation, UnitQuaternion}; +use crate::geometry::{Point3, Quaternion, Rotation, UnitQuaternion}; impl Index for Quaternion { type Output = N; @@ -390,7 +390,7 @@ quaternion_op_impl!( self: &'a UnitQuaternion, rhs: &'b Vector, Output = Vector3 => U3, U4; { - let two: N = ::convert(2.0f64); + let two: N = crate::convert(2.0f64); let t = self.as_ref().vector().cross(rhs) * two; let cross = self.as_ref().vector().cross(&t); diff --git a/src/geometry/reflection.rs b/src/geometry/reflection.rs index 45e6381c..a13e235a 100644 --- a/src/geometry/reflection.rs +++ b/src/geometry/reflection.rs @@ -1,11 +1,11 @@ use alga::general::Complex; -use base::allocator::Allocator; -use base::constraint::{AreMultipliable, DimEq, SameNumberOfRows, ShapeConstraint}; -use base::{DefaultAllocator, Matrix, Scalar, Unit, Vector}; -use dimension::{Dim, DimName, U1}; -use storage::{Storage, StorageMut}; +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 geometry::Point; +use crate::geometry::Point; /// A reflection wrt. a plane. pub struct Reflection> { @@ -55,7 +55,7 @@ impl> Reflection { // NOTE: we borrow the column twice here. First it is borrowed immutably for the // dot product, and then mutably. Somehow, this allows significantly // better optimizations of the dot product from the compiler. - let m_two: N = ::convert(-2.0f64); + let m_two: N = crate::convert(-2.0f64); let factor = (self.axis.dotc(&rhs.column(i)) - self.bias) * m_two; rhs.column_mut(i).axpy(factor, &self.axis, N::one()); } @@ -72,7 +72,7 @@ impl> Reflection { // NOTE: we borrow the column twice here. First it is borrowed immutably for the // dot product, and then mutably. Somehow, this allows significantly // better optimizations of the dot product from the compiler. - let m_two = sign.scale(::convert(-2.0f64)); + let m_two = sign.scale(crate::convert(-2.0f64)); let factor = (self.axis.dotc(&rhs.column(i)) - self.bias) * m_two; rhs.column_mut(i).axpy(factor, &self.axis, sign); } @@ -95,7 +95,7 @@ impl> Reflection { work.add_scalar_mut(-self.bias); } - let m_two: N = ::convert(-2.0f64); + let m_two: N = crate::convert(-2.0f64); lhs.gerc(m_two, &work, &self.axis, N::one()); } @@ -117,7 +117,7 @@ impl> Reflection { work.add_scalar_mut(-self.bias); } - let m_two = sign.scale(::convert(-2.0f64)); + let m_two = sign.scale(crate::convert(-2.0f64)); lhs.gerc(m_two, &work, &self.axis, sign); } } diff --git a/src/geometry/rotation.rs b/src/geometry/rotation.rs index ca9d888f..21e240fe 100644 --- a/src/geometry/rotation.rs +++ b/src/geometry/rotation.rs @@ -9,16 +9,16 @@ use std::io::{Result as IOResult, Write}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; #[cfg(feature = "serde-serialize")] -use base::storage::Owned; +use crate::base::storage::Owned; #[cfg(feature = "abomonation-serialize")] use abomonation::Abomonation; use alga::general::Real; -use base::allocator::Allocator; -use base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; -use base::{DefaultAllocator, MatrixN, Scalar}; +use crate::base::allocator::Allocator; +use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; +use crate::base::{DefaultAllocator, MatrixN, Scalar}; /// A rotation matrix. #[repr(C)] @@ -435,8 +435,8 @@ where fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let precision = f.precision().unwrap_or(3); - try!(writeln!(f, "Rotation matrix {{")); - try!(write!(f, "{:.*}", precision, self.matrix)); + writeln!(f, "Rotation matrix {{")?; + write!(f, "{:.*}", precision, self.matrix)?; writeln!(f, "}}") } } diff --git a/src/geometry/rotation_alga.rs b/src/geometry/rotation_alga.rs index 18c47b41..e5c1edad 100644 --- a/src/geometry/rotation_alga.rs +++ b/src/geometry/rotation_alga.rs @@ -7,11 +7,11 @@ use alga::linear::{ ProjectiveTransformation, Similarity, Transformation, }; -use base::allocator::Allocator; -use base::dimension::DimName; -use base::{DefaultAllocator, VectorN}; +use crate::base::allocator::Allocator; +use crate::base::dimension::DimName; +use crate::base::{DefaultAllocator, VectorN}; -use geometry::{Point, Rotation}; +use crate::geometry::{Point, Rotation}; /* * @@ -251,7 +251,7 @@ impl SquareMatrix for Rotation { #[inline] fn determinant(&self) -> Self::Field { - ::one() + crate::one() } #[inline] diff --git a/src/geometry/rotation_alias.rs b/src/geometry/rotation_alias.rs index a11bba99..9fa5c2d0 100644 --- a/src/geometry/rotation_alias.rs +++ b/src/geometry/rotation_alias.rs @@ -1,6 +1,6 @@ -use base::dimension::{U2, U3}; +use crate::base::dimension::{U2, U3}; -use geometry::Rotation; +use crate::geometry::Rotation; /// A 2-dimensional rotation matrix. pub type Rotation2 = Rotation; diff --git a/src/geometry/rotation_construction.rs b/src/geometry/rotation_construction.rs index 0da2cb29..a7779cc6 100644 --- a/src/geometry/rotation_construction.rs +++ b/src/geometry/rotation_construction.rs @@ -2,11 +2,11 @@ use num::{One, Zero}; use alga::general::{ClosedAdd, ClosedMul}; -use base::allocator::Allocator; -use base::dimension::DimName; -use base::{DefaultAllocator, MatrixN, Scalar}; +use crate::base::allocator::Allocator; +use crate::base::dimension::DimName; +use crate::base::{DefaultAllocator, MatrixN, Scalar}; -use geometry::Rotation; +use crate::geometry::Rotation; impl Rotation where diff --git a/src/geometry/rotation_conversion.rs b/src/geometry/rotation_conversion.rs index 044d85af..6adee2d8 100644 --- a/src/geometry/rotation_conversion.rs +++ b/src/geometry/rotation_conversion.rs @@ -6,11 +6,11 @@ use alga::linear::Rotation as AlgaRotation; #[cfg(feature = "mint")] use mint; -use base::allocator::Allocator; -use base::dimension::{DimMin, DimName, DimNameAdd, DimNameSum, U1}; -use base::{DefaultAllocator, Matrix2, Matrix3, Matrix4, MatrixN}; +use crate::base::allocator::Allocator; +use crate::base::dimension::{DimMin, DimName, DimNameAdd, DimNameSum, U1}; +use crate::base::{DefaultAllocator, Matrix2, Matrix3, Matrix4, MatrixN}; -use geometry::{ +use crate::geometry::{ Isometry, Point, Rotation, Rotation2, Rotation3, Similarity, SuperTCategoryOf, TAffine, Transform, Translation, UnitComplex, UnitQuaternion, }; @@ -43,7 +43,7 @@ where #[inline] fn is_in_subset(rot: &Rotation) -> bool { - ::is_convertible::<_, MatrixN>(rot.matrix()) + crate::is_convertible::<_, MatrixN>(rot.matrix()) } #[inline] @@ -65,12 +65,12 @@ where #[inline] fn is_in_subset(q: &UnitQuaternion) -> bool { - ::is_convertible::<_, UnitQuaternion>(q) + crate::is_convertible::<_, UnitQuaternion>(q) } #[inline] unsafe fn from_superset_unchecked(q: &UnitQuaternion) -> Self { - let q: UnitQuaternion = ::convert_ref_unchecked(q); + let q: UnitQuaternion = crate::convert_ref_unchecked(q); q.to_rotation_matrix() } } @@ -88,12 +88,12 @@ where #[inline] fn is_in_subset(q: &UnitComplex) -> bool { - ::is_convertible::<_, UnitComplex>(q) + crate::is_convertible::<_, UnitComplex>(q) } #[inline] unsafe fn from_superset_unchecked(q: &UnitComplex) -> Self { - let q: UnitComplex = ::convert_ref_unchecked(q); + let q: UnitComplex = crate::convert_ref_unchecked(q); q.to_rotation_matrix() } } @@ -107,7 +107,7 @@ where { #[inline] fn to_superset(&self) -> Isometry { - Isometry::from_parts(Translation::identity(), ::convert_ref(self)) + Isometry::from_parts(Translation::identity(), crate::convert_ref(self)) } #[inline] @@ -117,7 +117,7 @@ where #[inline] unsafe fn from_superset_unchecked(iso: &Isometry) -> Self { - ::convert_ref_unchecked(&iso.rotation) + crate::convert_ref_unchecked(&iso.rotation) } } @@ -130,7 +130,7 @@ where { #[inline] fn to_superset(&self) -> Similarity { - Similarity::from_parts(Translation::identity(), ::convert_ref(self), N2::one()) + Similarity::from_parts(Translation::identity(), crate::convert_ref(self), N2::one()) } #[inline] @@ -140,7 +140,7 @@ where #[inline] unsafe fn from_superset_unchecked(sim: &Similarity) -> Self { - ::convert_ref_unchecked(&sim.isometry.rotation) + crate::convert_ref_unchecked(&sim.isometry.rotation) } } @@ -198,7 +198,7 @@ where // Scalar types agree. m.iter().all(|e| SupersetOf::::is_in_subset(e)) && // The block part is a rotation. - rot.is_special_orthogonal(N2::default_epsilon() * ::convert(100.0)) && + rot.is_special_orthogonal(N2::default_epsilon() * crate::convert(100.0)) && // The bottom row is (0, 0, ..., 1) bottom.iter().all(|e| e.is_zero()) && m[(D::dim(), D::dim())] == N2::one() } @@ -206,7 +206,7 @@ where #[inline] unsafe fn from_superset_unchecked(m: &MatrixN>) -> Self { let r = m.fixed_slice::(0, 0); - Self::from_matrix_unchecked(::convert_unchecked(r.into_owned())) + Self::from_matrix_unchecked(crate::convert_unchecked(r.into_owned())) } } diff --git a/src/geometry/rotation_ops.rs b/src/geometry/rotation_ops.rs index fae70921..ed555b6b 100644 --- a/src/geometry/rotation_ops.rs +++ b/src/geometry/rotation_ops.rs @@ -22,13 +22,13 @@ use std::ops::{Div, DivAssign, Index, Mul, MulAssign}; use alga::general::{ClosedAdd, ClosedMul}; -use base::allocator::Allocator; -use base::constraint::{AreMultipliable, ShapeConstraint}; -use base::dimension::{Dim, DimName, U1}; -use base::storage::Storage; -use base::{DefaultAllocator, Matrix, MatrixMN, Scalar, Unit, Vector, VectorN}; +use crate::base::allocator::Allocator; +use crate::base::constraint::{AreMultipliable, ShapeConstraint}; +use crate::base::dimension::{Dim, DimName, U1}; +use crate::base::storage::Storage; +use crate::base::{DefaultAllocator, Matrix, MatrixMN, Scalar, Unit, Vector, VectorN}; -use geometry::{Point, Rotation}; +use crate::geometry::{Point, Rotation}; impl Index<(usize, usize)> for Rotation where DefaultAllocator: Allocator diff --git a/src/geometry/rotation_specialization.rs b/src/geometry/rotation_specialization.rs index 0aeb3041..95fa3c07 100644 --- a/src/geometry/rotation_specialization.rs +++ b/src/geometry/rotation_specialization.rs @@ -1,5 +1,5 @@ #[cfg(feature = "arbitrary")] -use base::storage::Owned; +use crate::base::storage::Owned; #[cfg(feature = "arbitrary")] use quickcheck::{Arbitrary, Gen}; @@ -9,11 +9,11 @@ use rand::distributions::{Distribution, OpenClosed01, Standard}; use rand::Rng; use std::ops::Neg; -use base::dimension::{U1, U2, U3}; -use base::storage::Storage; -use base::{Matrix2, Matrix3, MatrixN, Unit, Vector, Vector1, Vector3, VectorN}; +use crate::base::dimension::{U1, U2, U3}; +use crate::base::storage::Storage; +use crate::base::{Matrix2, Matrix3, MatrixN, Unit, Vector, Vector1, Vector3, VectorN}; -use geometry::{Rotation2, Rotation3, UnitComplex, UnitQuaternion}; +use crate::geometry::{Rotation2, Rotation3, UnitComplex, UnitQuaternion}; /* * @@ -113,7 +113,7 @@ impl Rotation2 { SB: Storage, SC: Storage, { - ::convert(UnitComplex::rotation_between(a, b).to_rotation_matrix()) + crate::convert(UnitComplex::rotation_between(a, b).to_rotation_matrix()) } /// The smallest rotation needed to make `a` and `b` collinear and point toward the same @@ -140,7 +140,7 @@ impl Rotation2 { SB: Storage, SC: Storage, { - ::convert(UnitComplex::scaled_rotation_between(a, b, s).to_rotation_matrix()) + crate::convert(UnitComplex::scaled_rotation_between(a, b, s).to_rotation_matrix()) } /// The rotation angle. @@ -682,7 +682,7 @@ impl Rotation3 { #[inline] pub fn angle(&self) -> N { ((self.matrix()[(0, 0)] + self.matrix()[(1, 1)] + self.matrix()[(2, 2)] - N::one()) - / ::convert(2.0)) + / crate::convert(2.0)) .acos() } diff --git a/src/geometry/similarity.rs b/src/geometry/similarity.rs index 1d2f50b4..f0bc6d2e 100644 --- a/src/geometry/similarity.rs +++ b/src/geometry/similarity.rs @@ -13,11 +13,11 @@ use abomonation::Abomonation; use alga::general::{Real, SubsetOf}; use alga::linear::Rotation; -use base::allocator::Allocator; -use base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; -use base::storage::Owned; -use base::{DefaultAllocator, MatrixN}; -use geometry::{Isometry, Point, Translation}; +use crate::base::allocator::Allocator; +use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; +use crate::base::storage::Owned; +use crate::base::{DefaultAllocator, MatrixN}; +use crate::geometry::{Isometry, Point, Translation}; /// A similarity, i.e., an uniform scaling, followed by a rotation, followed by a translation. #[repr(C)] @@ -361,9 +361,9 @@ where fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let precision = f.precision().unwrap_or(3); - try!(writeln!(f, "Similarity {{")); - try!(write!(f, "{:.*}", precision, self.isometry)); - try!(write!(f, "Scaling: {:.*}", precision, self.scaling)); + writeln!(f, "Similarity {{")?; + write!(f, "{:.*}", precision, self.isometry)?; + write!(f, "Scaling: {:.*}", precision, self.scaling)?; writeln!(f, "}}") } } diff --git a/src/geometry/similarity_alga.rs b/src/geometry/similarity_alga.rs index e8a6b154..9aaefe48 100644 --- a/src/geometry/similarity_alga.rs +++ b/src/geometry/similarity_alga.rs @@ -5,11 +5,11 @@ use alga::general::{ use alga::linear::Similarity as AlgaSimilarity; use alga::linear::{AffineTransformation, ProjectiveTransformation, Rotation, Transformation}; -use base::allocator::Allocator; -use base::dimension::DimName; -use base::{DefaultAllocator, VectorN}; +use crate::base::allocator::Allocator; +use crate::base::dimension::DimName; +use crate::base::{DefaultAllocator, VectorN}; -use geometry::{Point, Similarity, Translation}; +use crate::geometry::{Point, Similarity, Translation}; /* * diff --git a/src/geometry/similarity_alias.rs b/src/geometry/similarity_alias.rs index 9d3a2f45..c2c887ac 100644 --- a/src/geometry/similarity_alias.rs +++ b/src/geometry/similarity_alias.rs @@ -1,6 +1,6 @@ -use base::dimension::{U2, U3}; +use crate::base::dimension::{U2, U3}; -use geometry::{Rotation2, Rotation3, Similarity, UnitComplex, UnitQuaternion}; +use crate::geometry::{Rotation2, Rotation3, Similarity, UnitComplex, UnitQuaternion}; /// A 2-dimensional similarity. pub type Similarity2 = Similarity>; diff --git a/src/geometry/similarity_construction.rs b/src/geometry/similarity_construction.rs index 47bb46c7..0875c189 100644 --- a/src/geometry/similarity_construction.rs +++ b/src/geometry/similarity_construction.rs @@ -1,5 +1,5 @@ #[cfg(feature = "arbitrary")] -use base::storage::Owned; +use crate::base::storage::Owned; #[cfg(feature = "arbitrary")] use quickcheck::{Arbitrary, Gen}; @@ -10,11 +10,11 @@ use rand::Rng; use alga::general::Real; use alga::linear::Rotation as AlgaRotation; -use base::allocator::Allocator; -use base::dimension::{DimName, U2, U3}; -use base::{DefaultAllocator, Vector2, Vector3}; +use crate::base::allocator::Allocator; +use crate::base::dimension::{DimName, U2, U3}; +use crate::base::{DefaultAllocator, Vector2, Vector3}; -use geometry::{ +use crate::geometry::{ Isometry, Point, Point3, Rotation2, Rotation3, Similarity, Translation, UnitComplex, UnitQuaternion, }; diff --git a/src/geometry/similarity_conversion.rs b/src/geometry/similarity_conversion.rs index 34943fee..a040def3 100644 --- a/src/geometry/similarity_conversion.rs +++ b/src/geometry/similarity_conversion.rs @@ -1,11 +1,11 @@ use alga::general::{Real, SubsetOf, SupersetOf}; use alga::linear::Rotation; -use base::allocator::Allocator; -use base::dimension::{DimMin, DimName, DimNameAdd, DimNameSum, U1}; -use base::{DefaultAllocator, MatrixN}; +use crate::base::allocator::Allocator; +use crate::base::dimension::{DimMin, DimName, DimNameAdd, DimNameSum, U1}; +use crate::base::{DefaultAllocator, MatrixN}; -use geometry::{Isometry, Point, Similarity, SuperTCategoryOf, TAffine, Transform, Translation}; +use crate::geometry::{Isometry, Point, Similarity, SuperTCategoryOf, TAffine, Transform, Translation}; /* * This file provides the following conversions: @@ -31,8 +31,8 @@ where #[inline] fn is_in_subset(sim: &Similarity) -> bool { - ::is_convertible::<_, Isometry>(&sim.isometry) - && ::is_convertible::<_, N1>(&sim.scaling()) + crate::is_convertible::<_, Isometry>(&sim.isometry) + && crate::is_convertible::<_, N1>(&sim.scaling()) } #[inline] @@ -143,7 +143,7 @@ where let nb = mm.fixed_slice_mut::(0, 1).normalize_mut(); let nc = mm.fixed_slice_mut::(0, 2).normalize_mut(); - let mut scale = (na + nb + nc) / ::convert(3.0); // We take the mean, for robustness. + let mut scale = (na + nb + nc) / crate::convert(3.0); // We take the mean, for robustness. // FIXME: could we avoid the explicit computation of the determinant? // (its sign is needed to see if the scaling factor is negative). @@ -156,10 +156,10 @@ where let t = m.fixed_slice::(0, D::dim()).into_owned(); let t = Translation { - vector: ::convert_unchecked(t), + vector: crate::convert_unchecked(t), }; - Self::from_parts(t, ::convert_unchecked(mm), ::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 081e5133..fec4bdeb 100644 --- a/src/geometry/similarity_ops.rs +++ b/src/geometry/similarity_ops.rs @@ -3,11 +3,11 @@ use std::ops::{Div, DivAssign, Mul, MulAssign}; use alga::general::Real; use alga::linear::Rotation as AlgaRotation; -use base::allocator::Allocator; -use base::dimension::{DimName, U1, U3, U4}; -use base::{DefaultAllocator, VectorN}; +use crate::base::allocator::Allocator; +use crate::base::dimension::{DimName, U1, U3, U4}; +use crate::base::{DefaultAllocator, VectorN}; -use geometry::{Isometry, Point, Rotation, Similarity, Translation, UnitQuaternion}; +use crate::geometry::{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>` diff --git a/src/geometry/swizzle.rs b/src/geometry/swizzle.rs index 20c8dffd..d5740016 100644 --- a/src/geometry/swizzle.rs +++ b/src/geometry/swizzle.rs @@ -1,6 +1,6 @@ -use base::allocator::Allocator; -use base::{DefaultAllocator, DimName, Scalar}; -use geometry::{Point, Point2, Point3}; +use crate::base::allocator::Allocator; +use crate::base::{DefaultAllocator, DimName, Scalar}; +use crate::geometry::{Point, Point2, Point3}; use typenum::{self, Cmp, Greater}; macro_rules! impl_swizzle { diff --git a/src/geometry/transform.rs b/src/geometry/transform.rs index 0d5d9c4a..9b62d531 100644 --- a/src/geometry/transform.rs +++ b/src/geometry/transform.rs @@ -8,10 +8,10 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; use alga::general::Real; -use base::allocator::Allocator; -use base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; -use base::storage::Owned; -use base::{DefaultAllocator, MatrixN}; +use crate::base::allocator::Allocator; +use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; +use crate::base::storage::Owned; +use crate::base::{DefaultAllocator, MatrixN}; /// Trait implemented by phantom types identifying the projective transformation type. /// @@ -523,7 +523,7 @@ where #[cfg(test)] mod tests { use super::*; - use base::Matrix4; + use crate::base::Matrix4; #[test] fn checks_homogeneous_invariants_of_square_identity_matrix() { diff --git a/src/geometry/transform_alga.rs b/src/geometry/transform_alga.rs index c5ba675b..0ece3862 100644 --- a/src/geometry/transform_alga.rs +++ b/src/geometry/transform_alga.rs @@ -4,11 +4,11 @@ use alga::general::{ }; use alga::linear::{ProjectiveTransformation, Transformation}; -use base::allocator::Allocator; -use base::dimension::{DimNameAdd, DimNameSum, U1}; -use base::{DefaultAllocator, VectorN}; +use crate::base::allocator::Allocator; +use crate::base::dimension::{DimNameAdd, DimNameSum, U1}; +use crate::base::{DefaultAllocator, VectorN}; -use geometry::{Point, SubTCategoryOf, TCategory, TProjective, Transform}; +use crate::geometry::{Point, SubTCategoryOf, TCategory, TProjective, Transform}; /* * diff --git a/src/geometry/transform_alias.rs b/src/geometry/transform_alias.rs index 6f529966..1ccc5f95 100644 --- a/src/geometry/transform_alias.rs +++ b/src/geometry/transform_alias.rs @@ -1,6 +1,6 @@ -use base::dimension::{U2, U3}; +use crate::base::dimension::{U2, U3}; -use geometry::{TAffine, TGeneral, TProjective, Transform}; +use crate::geometry::{TAffine, TGeneral, TProjective, Transform}; /// A 2D general transformation that may not be invertible. Stored as an homogeneous 3x3 matrix. pub type Transform2 = Transform; diff --git a/src/geometry/transform_construction.rs b/src/geometry/transform_construction.rs index 3244ad8a..55733a90 100644 --- a/src/geometry/transform_construction.rs +++ b/src/geometry/transform_construction.rs @@ -2,11 +2,11 @@ use num::One; use alga::general::Real; -use base::allocator::Allocator; -use base::dimension::{DimNameAdd, DimNameSum, U1}; -use base::{DefaultAllocator, MatrixN}; +use crate::base::allocator::Allocator; +use crate::base::dimension::{DimNameAdd, DimNameSum, U1}; +use crate::base::{DefaultAllocator, MatrixN}; -use geometry::{TCategory, Transform}; +use crate::geometry::{TCategory, Transform}; impl, C: TCategory> Transform where DefaultAllocator: Allocator, DimNameSum> diff --git a/src/geometry/transform_conversion.rs b/src/geometry/transform_conversion.rs index ab5ad5df..651ab69b 100644 --- a/src/geometry/transform_conversion.rs +++ b/src/geometry/transform_conversion.rs @@ -1,10 +1,10 @@ use alga::general::{Real, SubsetOf}; -use base::allocator::Allocator; -use base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; -use base::{DefaultAllocator, MatrixN}; +use crate::base::allocator::Allocator; +use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; +use crate::base::{DefaultAllocator, MatrixN}; -use geometry::{SuperTCategoryOf, TCategory, Transform}; +use crate::geometry::{SuperTCategoryOf, TCategory, Transform}; impl SubsetOf> for Transform where @@ -57,7 +57,7 @@ where #[inline] unsafe fn from_superset_unchecked(m: &MatrixN>) -> Self { - Self::from_matrix_unchecked(::convert_ref_unchecked(m)) + Self::from_matrix_unchecked(crate::convert_ref_unchecked(m)) } } diff --git a/src/geometry/transform_ops.rs b/src/geometry/transform_ops.rs index 2ede5c60..9d03038d 100644 --- a/src/geometry/transform_ops.rs +++ b/src/geometry/transform_ops.rs @@ -3,11 +3,11 @@ use std::ops::{Div, DivAssign, Index, IndexMut, Mul, MulAssign}; use alga::general::{ClosedAdd, ClosedMul, Real, SubsetOf}; -use base::allocator::Allocator; -use base::dimension::{DimName, DimNameAdd, DimNameSum, U1, U3, U4}; -use base::{DefaultAllocator, MatrixN, Scalar, VectorN}; +use crate::base::allocator::Allocator; +use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1, U3, U4}; +use crate::base::{DefaultAllocator, MatrixN, Scalar, VectorN}; -use geometry::{ +use crate::geometry::{ Isometry, Point, Rotation, Similarity, SubTCategoryOf, SuperTCategoryOf, TAffine, TCategory, TCategoryMul, TGeneral, TProjective, Transform, Translation, UnitQuaternion, }; diff --git a/src/geometry/translation.rs b/src/geometry/translation.rs index 7b1a8957..3b620b20 100644 --- a/src/geometry/translation.rs +++ b/src/geometry/translation.rs @@ -13,10 +13,10 @@ use abomonation::Abomonation; use alga::general::{ClosedNeg, Real}; -use base::allocator::Allocator; -use base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; -use base::storage::Owned; -use base::{DefaultAllocator, MatrixN, Scalar, VectorN}; +use crate::base::allocator::Allocator; +use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; +use crate::base::storage::Owned; +use crate::base::{DefaultAllocator, MatrixN, Scalar, VectorN}; /// A translation. #[repr(C)] @@ -269,8 +269,8 @@ where DefaultAllocator: Allocator + Allocator fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let precision = f.precision().unwrap_or(3); - try!(writeln!(f, "Translation {{")); - try!(write!(f, "{:.*}", precision, self.vector)); + writeln!(f, "Translation {{")?; + write!(f, "{:.*}", precision, self.vector)?; writeln!(f, "}}") } } diff --git a/src/geometry/translation_alga.rs b/src/geometry/translation_alga.rs index fdd24014..00b54421 100644 --- a/src/geometry/translation_alga.rs +++ b/src/geometry/translation_alga.rs @@ -8,11 +8,11 @@ use alga::linear::{ Transformation, }; -use base::allocator::Allocator; -use base::dimension::DimName; -use base::{DefaultAllocator, VectorN}; +use crate::base::allocator::Allocator; +use crate::base::dimension::DimName; +use crate::base::{DefaultAllocator, VectorN}; -use geometry::{Point, Translation}; +use crate::geometry::{Point, Translation}; /* * diff --git a/src/geometry/translation_alias.rs b/src/geometry/translation_alias.rs index 41885db7..13db0495 100644 --- a/src/geometry/translation_alias.rs +++ b/src/geometry/translation_alias.rs @@ -1,6 +1,6 @@ -use base::dimension::{U1, U2, U3, U4, U5, U6}; +use crate::base::dimension::{U1, U2, U3, U4, U5, U6}; -use geometry::Translation; +use crate::geometry::Translation; /// A 1-dimensional translation. pub type Translation1 = Translation; diff --git a/src/geometry/translation_construction.rs b/src/geometry/translation_construction.rs index a973603d..339bdd2a 100644 --- a/src/geometry/translation_construction.rs +++ b/src/geometry/translation_construction.rs @@ -1,5 +1,5 @@ #[cfg(feature = "arbitrary")] -use base::storage::Owned; +use crate::base::storage::Owned; #[cfg(feature = "arbitrary")] use quickcheck::{Arbitrary, Gen}; @@ -9,11 +9,11 @@ use rand::Rng; use alga::general::ClosedAdd; -use base::allocator::Allocator; -use base::dimension::{DimName, U1, U2, U3, U4, U5, U6}; -use base::{DefaultAllocator, Scalar, VectorN}; +use crate::base::allocator::Allocator; +use crate::base::dimension::{DimName, U1, U2, U3, U4, U5, U6}; +use crate::base::{DefaultAllocator, Scalar, VectorN}; -use geometry::Translation; +use crate::geometry::Translation; impl Translation where DefaultAllocator: Allocator diff --git a/src/geometry/translation_conversion.rs b/src/geometry/translation_conversion.rs index d4fd9df2..9f0e9a25 100644 --- a/src/geometry/translation_conversion.rs +++ b/src/geometry/translation_conversion.rs @@ -3,11 +3,11 @@ use num::{One, Zero}; use alga::general::{Real, SubsetOf, SupersetOf}; use alga::linear::Rotation; -use base::allocator::Allocator; -use base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; -use base::{DefaultAllocator, MatrixN, Scalar, VectorN}; +use crate::base::allocator::Allocator; +use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; +use crate::base::{DefaultAllocator, MatrixN, Scalar, VectorN}; -use geometry::{Isometry, Point, Similarity, SuperTCategoryOf, TAffine, Transform, Translation}; +use crate::geometry::{Isometry, Point, Similarity, SuperTCategoryOf, TAffine, Transform, Translation}; /* * This file provides the following conversions: @@ -33,7 +33,7 @@ where #[inline] fn is_in_subset(rot: &Translation) -> bool { - ::is_convertible::<_, VectorN>(&rot.vector) + crate::is_convertible::<_, VectorN>(&rot.vector) } #[inline] @@ -148,7 +148,7 @@ where unsafe fn from_superset_unchecked(m: &MatrixN>) -> Self { let t = m.fixed_slice::(0, D::dim()); Self { - vector: ::convert_unchecked(t.into_owned()), + vector: crate::convert_unchecked(t.into_owned()), } } } diff --git a/src/geometry/translation_coordinates.rs b/src/geometry/translation_coordinates.rs index 01207a32..c422415c 100644 --- a/src/geometry/translation_coordinates.rs +++ b/src/geometry/translation_coordinates.rs @@ -1,12 +1,12 @@ use std::mem; use std::ops::{Deref, DerefMut}; -use base::allocator::Allocator; -use base::coordinates::{X, XY, XYZ, XYZW, XYZWA, XYZWAB}; -use base::dimension::{U1, U2, U3, U4, U5, U6}; -use base::{DefaultAllocator, Scalar}; +use crate::base::allocator::Allocator; +use crate::base::coordinates::{X, XY, XYZ, XYZW, XYZWA, XYZWAB}; +use crate::base::dimension::{U1, U2, U3, U4, U5, U6}; +use crate::base::{DefaultAllocator, Scalar}; -use geometry::Translation; +use crate::geometry::Translation; /* * diff --git a/src/geometry/translation_ops.rs b/src/geometry/translation_ops.rs index 57b8d6d1..55366a05 100644 --- a/src/geometry/translation_ops.rs +++ b/src/geometry/translation_ops.rs @@ -2,12 +2,12 @@ use std::ops::{Div, DivAssign, Mul, MulAssign}; use alga::general::{ClosedAdd, ClosedSub}; -use base::allocator::{Allocator, SameShapeAllocator}; -use base::constraint::{SameNumberOfColumns, SameNumberOfRows, ShapeConstraint}; -use base::dimension::{DimName, U1}; -use base::{DefaultAllocator, Scalar}; +use crate::base::allocator::{Allocator, SameShapeAllocator}; +use crate::base::constraint::{SameNumberOfColumns, SameNumberOfRows, ShapeConstraint}; +use crate::base::dimension::{DimName, U1}; +use crate::base::{DefaultAllocator, Scalar}; -use geometry::{Point, Translation}; +use crate::geometry::{Point, Translation}; // Translation × Translation add_sub_impl!(Mul, mul, ClosedAdd; diff --git a/src/geometry/unit_complex.rs b/src/geometry/unit_complex.rs index fe1058af..d02b46b6 100644 --- a/src/geometry/unit_complex.rs +++ b/src/geometry/unit_complex.rs @@ -3,8 +3,8 @@ use num_complex::Complex; use std::fmt; use alga::general::Real; -use base::{Matrix2, Matrix3, Unit, Vector1}; -use geometry::Rotation2; +use crate::base::{Matrix2, Matrix3, Unit, Vector1}; +use crate::geometry::Rotation2; /// A complex number with a norm equal to 1. pub type UnitComplex = Unit>; diff --git a/src/geometry/unit_complex_alga.rs b/src/geometry/unit_complex_alga.rs index 21b956d9..d49a3e57 100644 --- a/src/geometry/unit_complex_alga.rs +++ b/src/geometry/unit_complex_alga.rs @@ -7,10 +7,10 @@ use alga::linear::{ ProjectiveTransformation, Rotation, Similarity, Transformation, }; -use base::allocator::Allocator; -use base::dimension::U2; -use base::{DefaultAllocator, Vector2}; -use geometry::{Point2, UnitComplex}; +use crate::base::allocator::Allocator; +use crate::base::dimension::U2; +use crate::base::{DefaultAllocator, Vector2}; +use crate::geometry::{Point2, UnitComplex}; /* * diff --git a/src/geometry/unit_complex_construction.rs b/src/geometry/unit_complex_construction.rs index ba1d6694..7e24559c 100644 --- a/src/geometry/unit_complex_construction.rs +++ b/src/geometry/unit_complex_construction.rs @@ -7,10 +7,10 @@ use rand::distributions::{Distribution, OpenClosed01, Standard}; use rand::Rng; use alga::general::Real; -use base::dimension::{U1, U2}; -use base::storage::Storage; -use base::{Unit, Vector, Matrix2}; -use geometry::{Rotation2, UnitComplex}; +use crate::base::dimension::{U1, U2}; +use crate::base::storage::Storage; +use crate::base::{Unit, Vector, Matrix2}; +use crate::geometry::{Rotation2, UnitComplex}; 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 1751a67c..3adb372c 100644 --- a/src/geometry/unit_complex_conversion.rs +++ b/src/geometry/unit_complex_conversion.rs @@ -4,9 +4,9 @@ use num_complex::Complex; use alga::general::{Real, SubsetOf, SupersetOf}; use alga::linear::Rotation as AlgaRotation; -use base::dimension::U2; -use base::{Matrix2, Matrix3}; -use geometry::{ +use crate::base::dimension::U2; +use crate::base::{Matrix2, Matrix3}; +use crate::geometry::{ Isometry, Point2, Rotation2, Similarity, SuperTCategoryOf, TAffine, Transform, Translation, UnitComplex }; @@ -38,12 +38,12 @@ where #[inline] fn is_in_subset(uq: &UnitComplex) -> bool { - ::is_convertible::<_, Complex>(uq.as_ref()) + crate::is_convertible::<_, Complex>(uq.as_ref()) } #[inline] unsafe fn from_superset_unchecked(uq: &UnitComplex) -> Self { - Self::new_unchecked(::convert_ref_unchecked(uq.as_ref())) + Self::new_unchecked(crate::convert_ref_unchecked(uq.as_ref())) } } @@ -60,13 +60,13 @@ where #[inline] fn is_in_subset(rot: &Rotation2) -> bool { - ::is_convertible::<_, Rotation2>(rot) + crate::is_convertible::<_, Rotation2>(rot) } #[inline] unsafe fn from_superset_unchecked(rot: &Rotation2) -> Self { let q = UnitComplex::::from_rotation_matrix(rot); - ::convert_unchecked(q) + crate::convert_unchecked(q) } } @@ -78,7 +78,7 @@ where { #[inline] fn to_superset(&self) -> Isometry { - Isometry::from_parts(Translation::identity(), ::convert_ref(self)) + Isometry::from_parts(Translation::identity(), crate::convert_ref(self)) } #[inline] @@ -88,7 +88,7 @@ where #[inline] unsafe fn from_superset_unchecked(iso: &Isometry) -> Self { - ::convert_ref_unchecked(&iso.rotation) + crate::convert_ref_unchecked(&iso.rotation) } } @@ -100,7 +100,7 @@ where { #[inline] fn to_superset(&self) -> Similarity { - Similarity::from_isometry(::convert_ref(self), N2::one()) + Similarity::from_isometry(crate::convert_ref(self), N2::one()) } #[inline] @@ -110,7 +110,7 @@ where #[inline] unsafe fn from_superset_unchecked(sim: &Similarity) -> Self { - ::convert_ref_unchecked(&sim.isometry) + crate::convert_ref_unchecked(&sim.isometry) } } @@ -144,12 +144,12 @@ impl> SubsetOf> for UnitComplex< #[inline] fn is_in_subset(m: &Matrix3) -> bool { - ::is_convertible::<_, Rotation2>(m) + crate::is_convertible::<_, Rotation2>(m) } #[inline] unsafe fn from_superset_unchecked(m: &Matrix3) -> Self { - let rot: Rotation2 = ::convert_ref_unchecked(m); + let rot: Rotation2 = crate::convert_ref_unchecked(m); Self::from_rotation_matrix(&rot) } } diff --git a/src/geometry/unit_complex_ops.rs b/src/geometry/unit_complex_ops.rs index 28c9a9c3..ee8eca64 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::Real; -use base::allocator::Allocator; -use base::dimension::{U1, U2}; -use base::storage::Storage; -use base::{DefaultAllocator, Unit, Vector, Vector2}; -use geometry::{Isometry, Point2, Rotation, Similarity, Translation, UnitComplex}; +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}; /* * This file provides: diff --git a/src/io/matrix_market.rs b/src/io/matrix_market.rs index f4919cd4..c2653c16 100644 --- a/src/io/matrix_market.rs +++ b/src/io/matrix_market.rs @@ -2,8 +2,8 @@ use std::fs; use std::path::Path; use pest::Parser; -use sparse::CsMatrix; -use Real; +use crate::sparse::CsMatrix; +use crate::Real; #[derive(Parser)] #[grammar = "io/matrix_market.pest"] @@ -41,7 +41,7 @@ pub fn cs_matrix_from_matrix_market_str(data: &str) -> Option().ok()? - 1); cols.push(inner.next()?.as_str().parse::().ok()? - 1); - data.push(::convert(inner.next()?.as_str().parse::().ok()?)); + data.push(crate::convert(inner.next()?.as_str().parse::().ok()?)); } _ => return None, // FIXME: return an Err instead. } diff --git a/src/lib.rs b/src/lib.rs index c2bb04f2..feae7b22 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -51,7 +51,7 @@ an optimized set of tools for computer graphics and physics. Those features incl allocated on the heap. * Convenient aliases for low-dimensional matrices and vectors: `Vector1` to `Vector6` and `Matrix1x1` to `Matrix6x6`, including rectangular matrices like `Matrix2x5`. -* Points sizes known at compile time, and convenience aliases: `Point1` to `Point6`. +* Points sizes known at compile time, and convenience aliases:: `Point1` to `Point6`. * Translation (seen as a transformation that composes by multiplication): `Translation2`, `Translation3`. * Rotation matrices: `Rotation2`, `Rotation3`. @@ -144,11 +144,11 @@ pub mod sparse; note = "The 'core' module is being renamed to 'base' to avoid conflicts with the 'core' crate." )] pub use base as core; -pub use base::*; -pub use geometry::*; -pub use linalg::*; +pub use crate::base::*; +pub use crate::geometry::*; +pub use crate::linalg::*; #[cfg(feature = "sparse")] -pub use sparse::*; +pub use crate::sparse::*; use std::cmp::{self, Ordering, PartialOrd}; diff --git a/src/linalg/balancing.rs b/src/linalg/balancing.rs index 5db113ba..33dcbff6 100644 --- a/src/linalg/balancing.rs +++ b/src/linalg/balancing.rs @@ -3,10 +3,10 @@ use alga::general::Real; use std::ops::{DivAssign, MulAssign}; -use allocator::Allocator; -use base::dimension::{Dim, U1}; -use base::storage::Storage; -use base::{DefaultAllocator, MatrixN, VectorN}; +use crate::allocator::Allocator; +use crate::base::dimension::{Dim, U1}; +use crate::base::storage::Storage; +use crate::base::{DefaultAllocator, MatrixN, VectorN}; /// Applies in-place a modified Parlett and Reinsch matrix balancing with 2-norm to the matrix `m` and returns /// the corresponding diagonal transformation. @@ -17,7 +17,7 @@ where DefaultAllocator: Allocator + Allocator { assert!(m.is_square(), "Unable to balance a non-square matrix."); let dim = m.data.shape().0; - let radix: N = ::convert(2.0f64); + let radix: N = crate::convert(2.0f64); let mut d = VectorN::from_element_generic(dim, U1, N::one()); let mut converged = false; @@ -50,7 +50,7 @@ where DefaultAllocator: Allocator + Allocator { f /= radix; } - let eps: N = ::convert(0.95); + let eps: N = crate::convert(0.95); if c * c + r * r < eps * s { converged = false; d[i] *= f; diff --git a/src/linalg/bidiagonal.rs b/src/linalg/bidiagonal.rs index 9bf3cd12..09031e28 100644 --- a/src/linalg/bidiagonal.rs +++ b/src/linalg/bidiagonal.rs @@ -2,14 +2,13 @@ use serde::{Deserialize, Serialize}; use alga::general::Complex; -use allocator::Allocator; -use base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, Unit, VectorN}; -use constraint::{DimEq, ShapeConstraint}; -use dimension::{Dim, DimDiff, DimMin, DimMinimum, DimSub, Dynamic, U1}; -use storage::Storage; +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 geometry::Reflection; -use linalg::householder; +use crate::geometry::Reflection; +use crate::linalg::householder; /// The bidiagonalization of a general matrix. #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] diff --git a/src/linalg/cholesky.rs b/src/linalg/cholesky.rs index 4ffacc97..985abddc 100644 --- a/src/linalg/cholesky.rs +++ b/src/linalg/cholesky.rs @@ -3,11 +3,11 @@ use serde::{Deserialize, Serialize}; use alga::general::Complex; -use allocator::Allocator; -use base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, SquareMatrix}; -use constraint::{SameNumberOfRows, ShapeConstraint}; -use dimension::{Dim, DimSub, Dynamic}; -use storage::{Storage, StorageMut}; +use crate::allocator::Allocator; +use crate::base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, SquareMatrix}; +use crate::constraint::{SameNumberOfRows, ShapeConstraint}; +use crate::dimension::{Dim, DimSub, Dynamic}; +use crate::storage::{Storage, StorageMut}; /// The Cholesky decomposition of a symmetric-definite-positive matrix. #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] diff --git a/src/linalg/determinant.rs b/src/linalg/determinant.rs index 3b0cb73d..4d265164 100644 --- a/src/linalg/determinant.rs +++ b/src/linalg/determinant.rs @@ -1,11 +1,11 @@ use alga::general::Complex; -use base::allocator::Allocator; -use base::dimension::DimMin; -use base::storage::Storage; -use base::{DefaultAllocator, SquareMatrix}; +use crate::base::allocator::Allocator; +use crate::base::dimension::DimMin; +use crate::base::storage::Storage; +use crate::base::{DefaultAllocator, SquareMatrix}; -use linalg::LU; +use crate::linalg::LU; impl, S: Storage> SquareMatrix { /// Computes the matrix determinant. diff --git a/src/linalg/eigen.rs b/src/linalg/eigen.rs index be1812ee..970e990d 100644 --- a/src/linalg/eigen.rs +++ b/src/linalg/eigen.rs @@ -7,15 +7,15 @@ use std::cmp; use std::fmt::Display; use std::ops::MulAssign; -use allocator::Allocator; -use base::dimension::{Dim, DimDiff, DimSub, Dynamic, U1, U2, U3}; -use base::storage::Storage; -use base::{DefaultAllocator, Hessenberg, MatrixN, SquareMatrix, Unit, Vector2, Vector3, VectorN}; -use constraint::{DimEq, ShapeConstraint}; +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::constraint::{DimEq, ShapeConstraint}; -use geometry::{Reflection, UnitComplex}; -use linalg::householder; -use linalg::Schur; +use crate::geometry::{Reflection, UnitComplex}; +use crate::linalg::householder; +use crate::linalg::Schur; /// Eigendecomposition of a real matrix with real eigenvalues (or complex eigen values for complex matrices). #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] diff --git a/src/linalg/full_piv_lu.rs b/src/linalg/full_piv_lu.rs index 353a5d1e..61bc227c 100644 --- a/src/linalg/full_piv_lu.rs +++ b/src/linalg/full_piv_lu.rs @@ -2,14 +2,14 @@ use serde::{Deserialize, Serialize}; use alga::general::Complex; -use allocator::Allocator; -use base::{DefaultAllocator, Matrix, MatrixMN, MatrixN}; -use constraint::{SameNumberOfRows, ShapeConstraint}; -use dimension::{Dim, DimMin, DimMinimum}; -use storage::{Storage, StorageMut}; +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 linalg::lu; -use linalg::PermutationSequence; +use crate::linalg::lu; +use crate::linalg::PermutationSequence; /// LU decomposition with full row and column pivoting. #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] diff --git a/src/linalg/givens.rs b/src/linalg/givens.rs index ecc9126b..0927dd26 100644 --- a/src/linalg/givens.rs +++ b/src/linalg/givens.rs @@ -3,10 +3,10 @@ use alga::general::Complex; use num::{Zero, One}; -use base::dimension::{Dim, U2}; -use base::constraint::{ShapeConstraint, DimEq}; -use base::storage::{Storage, StorageMut}; -use base::{Vector, Matrix}; +use crate::base::dimension::{Dim, U2}; +use crate::base::constraint::{ShapeConstraint, DimEq}; +use crate::base::storage::{Storage, StorageMut}; +use crate::base::{Vector, Matrix}; /// A Givens rotation. diff --git a/src/linalg/hessenberg.rs b/src/linalg/hessenberg.rs index bde3d325..56e2ace4 100644 --- a/src/linalg/hessenberg.rs +++ b/src/linalg/hessenberg.rs @@ -2,13 +2,12 @@ use serde::{Deserialize, Serialize}; use alga::general::Complex; -use allocator::Allocator; -use base::{DefaultAllocator, MatrixMN, MatrixN, SquareMatrix, VectorN}; -use constraint::{DimEq, ShapeConstraint}; -use dimension::{DimDiff, DimSub, Dynamic, U1}; -use storage::Storage; +use crate::allocator::Allocator; +use crate::base::{DefaultAllocator, MatrixMN, MatrixN, SquareMatrix, VectorN}; +use crate::dimension::{DimDiff, DimSub, U1}; +use crate::storage::Storage; -use linalg::householder; +use crate::linalg::householder; /// Hessenberg decomposition of a general matrix. #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] diff --git a/src/linalg/householder.rs b/src/linalg/householder.rs index 1dc0f7b6..3bd8f801 100644 --- a/src/linalg/householder.rs +++ b/src/linalg/householder.rs @@ -2,12 +2,12 @@ use num::Zero; use alga::general::Complex; -use allocator::Allocator; -use base::{DefaultAllocator, MatrixMN, MatrixN, Unit, Vector, VectorN}; -use dimension::Dim; -use storage::{Storage, StorageMut}; +use crate::allocator::Allocator; +use crate::base::{DefaultAllocator, MatrixMN, MatrixN, Unit, Vector, VectorN}; +use crate::dimension::Dim; +use crate::storage::{Storage, StorageMut}; -use geometry::Reflection; +use crate::geometry::Reflection; /// Replaces `column` by the axis of the householder reflection that transforms `column` into /// `(+/-|column|, 0, ..., 0)`. @@ -28,7 +28,7 @@ pub fn reflection_axis_mut>( unsafe { let (modulus, sign) = column.vget_unchecked(0).to_exp(); signed_norm = sign.scale(reflection_norm); - factor = (reflection_sq_norm + modulus * reflection_norm) * ::convert(2.0); + factor = (reflection_sq_norm + modulus * reflection_norm) * crate::convert(2.0); *column.vget_unchecked_mut(0) += signed_norm; }; diff --git a/src/linalg/inverse.rs b/src/linalg/inverse.rs index f2ccd3e6..3d6a0681 100644 --- a/src/linalg/inverse.rs +++ b/src/linalg/inverse.rs @@ -1,11 +1,11 @@ use alga::general::Complex; -use base::allocator::Allocator; -use base::dimension::Dim; -use base::storage::{Storage, StorageMut}; -use base::{DefaultAllocator, MatrixN, SquareMatrix}; +use crate::base::allocator::Allocator; +use crate::base::dimension::Dim; +use crate::base::storage::{Storage, StorageMut}; +use crate::base::{DefaultAllocator, MatrixN, SquareMatrix}; -use linalg::lu; +use crate::linalg::lu; impl> SquareMatrix { /// Attempts to invert this matrix. diff --git a/src/linalg/lu.rs b/src/linalg/lu.rs index 7e279227..fffe7148 100644 --- a/src/linalg/lu.rs +++ b/src/linalg/lu.rs @@ -2,14 +2,14 @@ use serde::{Deserialize, Serialize}; use alga::general::{Field, Complex}; -use allocator::{Allocator, Reallocator}; -use base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, Scalar}; -use constraint::{SameNumberOfRows, ShapeConstraint}; -use dimension::{Dim, DimMin, DimMinimum}; +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 storage::{Storage, StorageMut}; +use crate::storage::{Storage, StorageMut}; -use linalg::PermutationSequence; +use crate::linalg::PermutationSequence; /// LU decomposition with partial (row) pivoting. #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] diff --git a/src/linalg/permutation_sequence.rs b/src/linalg/permutation_sequence.rs index 3aef1be6..ce493905 100644 --- a/src/linalg/permutation_sequence.rs +++ b/src/linalg/permutation_sequence.rs @@ -4,12 +4,12 @@ use serde::{Deserialize, Serialize}; use alga::general::ClosedNeg; use num::One; -use allocator::Allocator; -use base::{DefaultAllocator, Matrix, Scalar, VectorN}; +use crate::allocator::Allocator; +use crate::base::{DefaultAllocator, Matrix, Scalar, VectorN}; #[cfg(any(feature = "std", feature = "alloc"))] -use dimension::Dynamic; -use dimension::{Dim, DimName, U1}; -use storage::StorageMut; +use crate::dimension::Dynamic; +use crate::dimension::{Dim, DimName, U1}; +use crate::storage::StorageMut; /// A sequence of row or column permutations. #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] diff --git a/src/linalg/qr.rs b/src/linalg/qr.rs index 12e72463..7c02d140 100644 --- a/src/linalg/qr.rs +++ b/src/linalg/qr.rs @@ -3,14 +3,14 @@ use serde::{Deserialize, Serialize}; use num::Zero; use alga::general::Complex; -use allocator::{Allocator, Reallocator}; -use base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, Unit, VectorN}; -use constraint::{SameNumberOfRows, ShapeConstraint}; -use dimension::{Dim, DimMin, DimMinimum, U1}; -use storage::{Storage, StorageMut}; +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 geometry::Reflection; -use linalg::householder; +use crate::geometry::Reflection; +use crate::linalg::householder; /// The QR decomposition of a general matrix. #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] diff --git a/src/linalg/schur.rs b/src/linalg/schur.rs index a6521f72..ade4b2dc 100644 --- a/src/linalg/schur.rs +++ b/src/linalg/schur.rs @@ -6,16 +6,15 @@ use alga::general::{Complex, Real}; use num_complex::Complex as NumComplex; use std::cmp; -use allocator::Allocator; -use base::dimension::{Dim, DimDiff, DimSub, Dynamic, U1, U2, U3}; -use base::storage::Storage; -use base::{DefaultAllocator, MatrixN, SquareMatrix, Unit, Vector2, Vector3, VectorN}; -use constraint::{DimEq, ShapeConstraint}; +use crate::allocator::Allocator; +use crate::base::dimension::{Dim, DimDiff, DimSub, Dynamic, U1, U2, U3}; +use crate::base::storage::Storage; +use crate::base::{DefaultAllocator, MatrixN, SquareMatrix, Unit, Vector2, Vector3, VectorN}; -use geometry::Reflection; -use linalg::householder; -use linalg::Hessenberg; -use linalg::givens::GivensRotation; +use crate::geometry::Reflection; +use crate::linalg::householder; +use crate::linalg::Hessenberg; +use crate::linalg::givens::GivensRotation; /// Schur decomposition of a square matrix. /// @@ -312,14 +311,14 @@ where let tra = hnn + hmm; let det = hnn * hmm - hnm * hmn; - let discr = tra * tra * ::convert(0.25) - det; + let discr = tra * tra * crate::convert(0.25) - det; // All 2x2 blocks have negative discriminant because we already decoupled those // with positive eigenvalues.. let sqrt_discr = NumComplex::new(N::zero(), (-discr).sqrt()); - out[m] = NumComplex::new(tra * ::convert(0.5), N::zero()) + sqrt_discr; - out[m + 1] = NumComplex::new(tra * ::convert(0.5), N::zero()) - sqrt_discr; + out[m] = NumComplex::new(tra * crate::convert(0.5), N::zero()) + sqrt_discr; + out[m + 1] = NumComplex::new(tra * crate::convert(0.5), N::zero()) - sqrt_discr; m += 2; } @@ -448,11 +447,11 @@ fn compute_2x2_eigvals>( // NOTE: this discriminant computation is more stable than the // one based on the trace and determinant: 0.25 * tra * tra - det // because it ensures positiveness for symmetric matrices. - let val = (h00 - h11) * ::convert(0.5); + let val = (h00 - h11) * crate::convert(0.5); let discr = h10 * h01 + val * val; discr.try_sqrt().map(|sqrt_discr| { - let half_tra = (h00 + h11) * ::convert(0.5); + let half_tra = (h00 + h11) * crate::convert(0.5); (half_tra + sqrt_discr, half_tra - sqrt_discr) }) } diff --git a/src/linalg/solve.rs b/src/linalg/solve.rs index fad85a81..0c2bb684 100644 --- a/src/linalg/solve.rs +++ b/src/linalg/solve.rs @@ -1,10 +1,10 @@ use alga::general::Complex; -use base::allocator::Allocator; -use base::constraint::{SameNumberOfRows, ShapeConstraint}; -use base::dimension::{Dim, U1}; -use base::storage::{Storage, StorageMut}; -use base::{DefaultAllocator, Matrix, MatrixMN, SquareMatrix, Vector, DVectorSlice}; +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}; impl> SquareMatrix { /// Computes the solution of the linear system `self . x = b` where `x` is the unknown and only diff --git a/src/linalg/svd.rs b/src/linalg/svd.rs index 0b5d0509..779bcff0 100644 --- a/src/linalg/svd.rs +++ b/src/linalg/svd.rs @@ -5,15 +5,15 @@ use num::{Zero, One}; use approx::AbsDiffEq; use alga::general::{Real, Complex}; -use allocator::Allocator; -use base::{DefaultAllocator, Matrix, Matrix2x3, MatrixMN, Vector2, VectorN}; -use constraint::{SameNumberOfRows, ShapeConstraint}; -use dimension::{Dim, DimDiff, DimMin, DimMinimum, DimSub, U1, U2}; -use storage::Storage; +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 linalg::symmetric_eigen; -use linalg::Bidiagonal; -use 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))] @@ -621,8 +621,8 @@ fn compute_2x2_uptrig_svd( compute_v: bool, ) -> (Option>, Vector2, Option>) { - let two: N::Real = ::convert(2.0f64); - let half: N::Real = ::convert(0.5f64); + let two: N::Real = crate::convert(2.0f64); + let half: N::Real = crate::convert(0.5f64); let denom = (m11 + m22).hypot(m12) + (m11 - m22).hypot(m12); diff --git a/src/linalg/symmetric_eigen.rs b/src/linalg/symmetric_eigen.rs index acdf956e..6fd1fea5 100644 --- a/src/linalg/symmetric_eigen.rs +++ b/src/linalg/symmetric_eigen.rs @@ -5,13 +5,13 @@ use num::Zero; use approx::AbsDiffEq; use alga::general::Complex; -use allocator::Allocator; -use base::{DefaultAllocator, Matrix2, MatrixN, SquareMatrix, Vector2, VectorN}; -use dimension::{Dim, DimDiff, DimSub, U1, U2}; -use storage::Storage; +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 linalg::givens::GivensRotation; -use linalg::SymmetricTridiagonal; +use crate::linalg::givens::GivensRotation; +use crate::linalg::SymmetricTridiagonal; /// Eigendecomposition of a symmetric matrix. #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] @@ -163,7 +163,7 @@ where DefaultAllocator: Allocator + Allocator let ss = rot.s() * rot.s(); let cs = rot.c() * rot.s(); - let b = cs * ::convert(2.0) * mij; + let b = cs * crate::convert(2.0) * mij; diag[i] = (cc * mii + ss * mjj) - b; diag[j] = (ss * mii + cc * mjj) + b; @@ -292,7 +292,7 @@ pub fn wilkinson_shift(tmm: N, tnn: N, tmn: N) -> N { let sq_tmn = tmn * tmn; if !sq_tmn.is_zero() { // We have the guarantee that the denominator won't be zero. - let d = (tmm - tnn) * ::convert(0.5); + let d = (tmm - tnn) * crate::convert(0.5); tnn - sq_tmn / (d + d.signum() * (d * d + sq_tmn).sqrt()) } else { tnn @@ -342,7 +342,7 @@ where DefaultAllocator: Allocator + Allocator> + #[cfg(test)] mod test { - use base::Matrix2; + use crate::base::Matrix2; fn expected_shift(m: Matrix2) -> f64 { let vals = m.eigenvalues().unwrap(); diff --git a/src/linalg/symmetric_tridiagonal.rs b/src/linalg/symmetric_tridiagonal.rs index 76267554..386c0a6f 100644 --- a/src/linalg/symmetric_tridiagonal.rs +++ b/src/linalg/symmetric_tridiagonal.rs @@ -2,12 +2,12 @@ use serde::{Deserialize, Serialize}; use alga::general::Complex; -use allocator::Allocator; -use base::{DefaultAllocator, MatrixMN, MatrixN, SquareMatrix, VectorN}; -use dimension::{DimDiff, DimSub, U1}; -use storage::Storage; +use crate::allocator::Allocator; +use crate::base::{DefaultAllocator, MatrixMN, MatrixN, SquareMatrix, VectorN}; +use crate::dimension::{DimDiff, DimSub, U1}; +use crate::storage::Storage; -use linalg::householder; +use crate::linalg::householder; /// Tridiagonalization of a symmetric matrix. #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] @@ -75,12 +75,12 @@ where DefaultAllocator: Allocator + Allocator> if not_zero { let mut p = p.rows_range_mut(i..); - p.hegemv(::convert(2.0), &m, &axis, N::zero()); + p.hegemv(crate::convert(2.0), &m, &axis, N::zero()); let dot = axis.dotc(&p); m.hegerc(-N::one(), &p, &axis, N::one()); m.hegerc(-N::one(), &axis, &p, N::one()); - m.hegerc(dot * ::convert(2.0), &axis, &axis, N::one()); + m.hegerc(dot * crate::convert(2.0), &axis, &axis, N::one()); } } diff --git a/src/sparse/cs_matrix.rs b/src/sparse/cs_matrix.rs index 4c2983eb..2fc571c7 100644 --- a/src/sparse/cs_matrix.rs +++ b/src/sparse/cs_matrix.rs @@ -5,9 +5,9 @@ use std::marker::PhantomData; use std::ops::Range; use std::slice; -use allocator::Allocator; -use sparse::cs_utils; -use { +use crate::allocator::Allocator; +use crate::sparse::cs_utils; +use crate::{ DefaultAllocator, Dim, Dynamic, Scalar, Vector, VectorN, U1 }; diff --git a/src/sparse/cs_matrix_cholesky.rs b/src/sparse/cs_matrix_cholesky.rs index 5d834ef2..fc7e97f9 100644 --- a/src/sparse/cs_matrix_cholesky.rs +++ b/src/sparse/cs_matrix_cholesky.rs @@ -1,9 +1,9 @@ use std::iter; use std::mem; -use allocator::Allocator; -use sparse::{CsMatrix, CsStorage, CsStorageIter, CsStorageIterMut, CsVecStorage}; -use {DefaultAllocator, Dim, Real, VectorN, U1}; +use crate::allocator::Allocator; +use crate::sparse::{CsMatrix, CsStorage, CsStorageIter, CsStorageIterMut, CsVecStorage}; +use crate::{DefaultAllocator, Dim, Real, VectorN, U1}; /// The cholesky decomposition of a column compressed sparse matrix. pub struct CsCholesky diff --git a/src/sparse/cs_matrix_conversion.rs b/src/sparse/cs_matrix_conversion.rs index 0017340f..31e53796 100644 --- a/src/sparse/cs_matrix_conversion.rs +++ b/src/sparse/cs_matrix_conversion.rs @@ -1,11 +1,11 @@ use alga::general::ClosedAdd; use num::Zero; -use allocator::Allocator; -use sparse::cs_utils; -use sparse::{CsMatrix, CsStorage}; -use storage::Storage; -use {DefaultAllocator, Dim, Dynamic, Matrix, MatrixMN, Scalar}; +use crate::allocator::Allocator; +use crate::sparse::cs_utils; +use crate::sparse::{CsMatrix, CsStorage}; +use crate::storage::Storage; +use crate::{DefaultAllocator, Dim, Dynamic, Matrix, MatrixMN, Scalar}; impl<'a, N: Scalar + Zero + ClosedAdd> CsMatrix { /// Creates a column-compressed sparse matrix from a sparse matrix in triplet form. diff --git a/src/sparse/cs_matrix_ops.rs b/src/sparse/cs_matrix_ops.rs index b944c4e2..322ebb34 100644 --- a/src/sparse/cs_matrix_ops.rs +++ b/src/sparse/cs_matrix_ops.rs @@ -2,11 +2,11 @@ use alga::general::{ClosedAdd, ClosedMul}; use num::{One, Zero}; use std::ops::{Add, Mul}; -use allocator::Allocator; -use constraint::{AreMultipliable, DimEq, ShapeConstraint}; -use sparse::{CsMatrix, CsStorage, CsStorageMut, CsVector}; -use storage::StorageMut; -use {DefaultAllocator, Dim, Scalar, Vector, VectorN, U1}; +use crate::allocator::Allocator; +use crate::constraint::{AreMultipliable, DimEq, ShapeConstraint}; +use crate::sparse::{CsMatrix, CsStorage, CsStorageMut, CsVector}; +use crate::storage::StorageMut; +use crate::{DefaultAllocator, Dim, Scalar, Vector, VectorN, U1}; impl> CsMatrix { fn scatter( diff --git a/src/sparse/cs_matrix_solve.rs b/src/sparse/cs_matrix_solve.rs index 2a13188e..a6bb628d 100644 --- a/src/sparse/cs_matrix_solve.rs +++ b/src/sparse/cs_matrix_solve.rs @@ -1,8 +1,8 @@ -use allocator::Allocator; -use constraint::{SameNumberOfRows, ShapeConstraint}; -use sparse::{CsMatrix, CsStorage, CsVector}; -use storage::{Storage, StorageMut}; -use {DefaultAllocator, Dim, Matrix, MatrixMN, Real, VectorN, U1}; +use crate::allocator::Allocator; +use crate::constraint::{SameNumberOfRows, ShapeConstraint}; +use crate::sparse::{CsMatrix, CsStorage, CsVector}; +use crate::storage::{Storage, StorageMut}; +use crate::{DefaultAllocator, Dim, Matrix, MatrixMN, Real, VectorN, U1}; impl> CsMatrix { /// Solve a lower-triangular system with a dense right-hand-side. diff --git a/src/sparse/cs_utils.rs b/src/sparse/cs_utils.rs index 3c5db43e..a8a454eb 100644 --- a/src/sparse/cs_utils.rs +++ b/src/sparse/cs_utils.rs @@ -1,5 +1,5 @@ -use allocator::Allocator; -use {DefaultAllocator, Dim, VectorN}; +use crate::allocator::Allocator; +use crate::{DefaultAllocator, Dim, VectorN}; pub fn cumsum(a: &mut VectorN, b: &mut VectorN) -> usize where DefaultAllocator: Allocator { diff --git a/tests/linalg/bidiagonal.rs b/tests/linalg/bidiagonal.rs index b4c382f3..9778eea3 100644 --- a/tests/linalg/bidiagonal.rs +++ b/tests/linalg/bidiagonal.rs @@ -5,7 +5,7 @@ macro_rules! gen_tests( mod $module { use na::{DMatrix, Matrix2, Matrix3x5, Matrix4, Matrix5x3}; #[allow(unused_imports)] - use core::helper::{RandScalar, RandComplex}; + use crate::core::helper::{RandScalar, RandComplex}; quickcheck! { fn bidiagonal(m: DMatrix<$scalar>) -> bool { diff --git a/tests/linalg/cholesky.rs b/tests/linalg/cholesky.rs index 774b76b0..cefc2630 100644 --- a/tests/linalg/cholesky.rs +++ b/tests/linalg/cholesky.rs @@ -9,7 +9,7 @@ macro_rules! gen_tests( use na::{DMatrix, DVector, Matrix4x3, Vector4}; use rand::random; #[allow(unused_imports)] - use core::helper::{RandScalar, RandComplex}; + use crate::core::helper::{RandScalar, RandComplex}; use std::cmp; quickcheck! { diff --git a/tests/linalg/eigen.rs b/tests/linalg/eigen.rs index 9a1c3539..8b2f8ed1 100644 --- a/tests/linalg/eigen.rs +++ b/tests/linalg/eigen.rs @@ -9,7 +9,7 @@ mod quickcheck_tests { mod $module { use na::{DMatrix, Matrix2, Matrix3, Matrix4}; #[allow(unused_imports)] - use core::helper::{RandScalar, RandComplex}; + use crate::core::helper::{RandScalar, RandComplex}; use std::cmp; quickcheck! { diff --git a/tests/linalg/full_piv_lu.rs b/tests/linalg/full_piv_lu.rs index c0e15cde..320fe241 100644 --- a/tests/linalg/full_piv_lu.rs +++ b/tests/linalg/full_piv_lu.rs @@ -49,7 +49,7 @@ mod quickcheck_tests { use num::One; use na::{DMatrix, Matrix4, Matrix4x3, Matrix5x3, Matrix3x5, DVector, Vector4}; #[allow(unused_imports)] - use core::helper::{RandScalar, RandComplex}; + use crate::core::helper::{RandScalar, RandComplex}; quickcheck! { fn full_piv_lu(m: DMatrix<$scalar>) -> bool { diff --git a/tests/linalg/hessenberg.rs b/tests/linalg/hessenberg.rs index 03cba7d1..378fbd87 100644 --- a/tests/linalg/hessenberg.rs +++ b/tests/linalg/hessenberg.rs @@ -18,7 +18,7 @@ macro_rules! gen_tests( use na::{DMatrix, Matrix2, Matrix4}; use std::cmp; #[allow(unused_imports)] - use core::helper::{RandScalar, RandComplex}; + use crate::core::helper::{RandScalar, RandComplex}; quickcheck! { fn hessenberg(n: usize) -> bool { diff --git a/tests/linalg/lu.rs b/tests/linalg/lu.rs index 02f62c10..69c387d2 100644 --- a/tests/linalg/lu.rs +++ b/tests/linalg/lu.rs @@ -41,7 +41,7 @@ fn lu_simple_with_pivot() { #[cfg(feature = "arbitrary")] mod quickcheck_tests { #[allow(unused_imports)] - use core::helper::{RandScalar, RandComplex}; + use crate::core::helper::{RandScalar, RandComplex}; macro_rules! gen_tests( ($module: ident, $scalar: ty) => { @@ -49,7 +49,7 @@ mod quickcheck_tests { use std::cmp; use na::{DMatrix, Matrix4, Matrix4x3, Matrix5x3, Matrix3x5, DVector, Vector4}; #[allow(unused_imports)] - use core::helper::{RandScalar, RandComplex}; + use crate::core::helper::{RandScalar, RandComplex}; quickcheck! { fn lu(m: DMatrix<$scalar>) -> bool { diff --git a/tests/linalg/qr.rs b/tests/linalg/qr.rs index 76eb00d9..93cb4973 100644 --- a/tests/linalg/qr.rs +++ b/tests/linalg/qr.rs @@ -7,7 +7,7 @@ macro_rules! gen_tests( use na::{DMatrix, DVector, Matrix3x5, Matrix4, Matrix4x3, Matrix5x3, Vector4}; use std::cmp; #[allow(unused_imports)] - use core::helper::{RandScalar, RandComplex}; + use crate::core::helper::{RandScalar, RandComplex}; quickcheck! { fn qr(m: DMatrix<$scalar>) -> bool { diff --git a/tests/linalg/schur.rs b/tests/linalg/schur.rs index f607ce06..f9c923a2 100644 --- a/tests/linalg/schur.rs +++ b/tests/linalg/schur.rs @@ -22,7 +22,7 @@ mod quickcheck_tests { use std::cmp; use na::{DMatrix, Matrix2, Matrix3, Matrix4}; #[allow(unused_imports)] - use core::helper::{RandScalar, RandComplex}; + use crate::core::helper::{RandScalar, RandComplex}; quickcheck! { fn schur(n: usize) -> bool { diff --git a/tests/linalg/solve.rs b/tests/linalg/solve.rs index 3a9ff143..90b76585 100644 --- a/tests/linalg/solve.rs +++ b/tests/linalg/solve.rs @@ -6,7 +6,7 @@ macro_rules! gen_tests( mod $module { use na::{Matrix4, Matrix4x5, Complex}; #[allow(unused_imports)] - use core::helper::{RandScalar, RandComplex}; + use crate::core::helper::{RandScalar, RandComplex}; fn unzero_diagonal(a: &mut Matrix4) { for i in 0..4 { diff --git a/tests/linalg/svd.rs b/tests/linalg/svd.rs index 0eb1d69e..a9b1d1cf 100644 --- a/tests/linalg/svd.rs +++ b/tests/linalg/svd.rs @@ -12,7 +12,7 @@ mod quickcheck_tests { }; use std::cmp; #[allow(unused_imports)] - use core::helper::{RandScalar, RandComplex}; + use crate::core::helper::{RandScalar, RandComplex}; quickcheck! { fn svd(m: DMatrix<$scalar>) -> bool { diff --git a/tests/linalg/tridiagonal.rs b/tests/linalg/tridiagonal.rs index 368aba13..5d04587e 100644 --- a/tests/linalg/tridiagonal.rs +++ b/tests/linalg/tridiagonal.rs @@ -8,7 +8,7 @@ macro_rules! gen_tests( use na::{DMatrix, Matrix2, Matrix4}; #[allow(unused_imports)] - use core::helper::{RandScalar, RandComplex}; + use crate::core::helper::{RandScalar, RandComplex}; quickcheck! { fn symm_tridiagonal(n: usize) -> bool { diff --git a/tests/sparse/cs_cholesky.rs b/tests/sparse/cs_cholesky.rs index 72a9a08f..314e34f6 100644 --- a/tests/sparse/cs_cholesky.rs +++ b/tests/sparse/cs_cholesky.rs @@ -35,12 +35,12 @@ fn cs_cholesky() { 1.0, 1.0, 0.0, 0.0, 2.0 ); a.fill_upper_triangle_with_lower_triangle(); - // Test ::new, left_looking, and up_looking implementations. + // Test crate::new, left_looking, and up_looking implementations. test_cholesky(a); } fn test_cholesky(a: Matrix5) { - // Test ::new + // Test crate::new test_cholesky_variant(a, 0); // Test up-looking test_cholesky_variant(a, 1); From 6d76249d74783a25c6a370863ddf0e4b062f992f Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sat, 23 Mar 2019 18:01:04 +0100 Subject: [PATCH 14/28] Start switching benchmarks to criterion. --- Cargo.toml | 9 +++++++++ benches/common/macros.rs | 42 +++++++++++++++++----------------------- benches/core/matrix.rs | 2 ++ benches/core/mod.rs | 4 ++-- benches/core/vector.rs | 35 ++++++++++++++------------------- benches/lib.rs | 11 ++++++++--- 6 files changed, 54 insertions(+), 49 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 736b9738..fe87f723 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,9 +51,18 @@ pest_derive = { version = "2.0", optional = true } [dev-dependencies] serde_json = "1.0" rand_xorshift = "0.1" +criterion = "0.2" [workspace] members = [ "nalgebra-lapack", "nalgebra-glm" ] +[[bench]] +name = "nalgebra_bench" +harness = false +path = "benches/lib.rs" + [patch.crates-io] alga = { path = "../alga/alga" } + +[profile.bench] +lto = true diff --git a/benches/common/macros.rs b/benches/common/macros.rs index 758336a8..43bcf59d 100644 --- a/benches/common/macros.rs +++ b/benches/common/macros.rs @@ -2,56 +2,52 @@ macro_rules! bench_binop( ($name: ident, $t1: ty, $t2: ty, $binop: ident) => { - #[bench] - fn $name(bh: &mut Bencher) { + fn $name(bh: &mut criterion::Criterion) { use rand::SeedableRng; let mut rng = IsaacRng::seed_from_u64(0); let a = rng.gen::<$t1>(); let b = rng.gen::<$t2>(); - bh.iter(|| { + bh.bench_function(stringify!($name), move |bh| bh.iter(|| { a.$binop(b) - }) + })); } } ); macro_rules! bench_binop_ref( ($name: ident, $t1: ty, $t2: ty, $binop: ident) => { - #[bench] - fn $name(bh: &mut Bencher) { + fn $name(bh: &mut criterion::Criterion) { use rand::SeedableRng; let mut rng = IsaacRng::seed_from_u64(0); let a = rng.gen::<$t1>(); let b = rng.gen::<$t2>(); - bh.iter(|| { + bh.bench_function(stringify!($name), move |bh| bh.iter(|| { a.$binop(&b) - }) + })); } } ); macro_rules! bench_binop_fn( ($name: ident, $t1: ty, $t2: ty, $binop: path) => { - #[bench] - fn $name(bh: &mut Bencher) { + fn $name(bh: &mut criterion::Criterion) { use rand::SeedableRng; let mut rng = IsaacRng::seed_from_u64(0); let a = rng.gen::<$t1>(); let b = rng.gen::<$t2>(); - bh.iter(|| { + bh.bench_function(stringify!($name), move |bh| bh.iter(|| { $binop(&a, &b) - }) + })); } } ); macro_rules! bench_unop_na( ($name: ident, $t: ty, $unop: ident) => { - #[bench] - fn $name(bh: &mut Bencher) { + fn $name(bh: &mut criterion::Criterion) { const LEN: usize = 1 << 13; use rand::SeedableRng; @@ -60,21 +56,20 @@ macro_rules! bench_unop_na( let elems: Vec<$t> = (0usize .. LEN).map(|_| rng.gen::<$t>()).collect(); let mut i = 0; - bh.iter(|| { + bh.bench_function(stringify!($name), move |bh| bh.iter(|| { i = (i + 1) & (LEN - 1); unsafe { test::black_box(na::$unop(elems.get_unchecked(i))) } - }) + })); } } ); macro_rules! bench_unop( ($name: ident, $t: ty, $unop: ident) => { - #[bench] - fn $name(bh: &mut Bencher) { + fn $name(bh: &mut criterion::Criterion) { const LEN: usize = 1 << 13; use rand::SeedableRng; @@ -83,21 +78,20 @@ macro_rules! bench_unop( let mut elems: Vec<$t> = (0usize .. LEN).map(|_| rng.gen::<$t>()).collect(); let mut i = 0; - bh.iter(|| { + bh.bench_function(stringify!($name), move |bh| bh.iter(|| { i = (i + 1) & (LEN - 1); unsafe { test::black_box(elems.get_unchecked_mut(i).$unop()) } - }) + })); } } ); macro_rules! bench_construction( ($name: ident, $constructor: path, $( $args: ident: $types: ty),*) => { - #[bench] - fn $name(bh: &mut Bencher) { + fn $name(bh: &mut criterion::Criterion) { const LEN: usize = 1 << 13; use rand::SeedableRng; @@ -106,14 +100,14 @@ macro_rules! bench_construction( $(let $args: Vec<$types> = (0usize .. LEN).map(|_| rng.gen::<$types>()).collect();)* let mut i = 0; - bh.iter(|| { + bh.bench_function(stringify!($name), move |bh| bh.iter(|| { i = (i + 1) & (LEN - 1); unsafe { let res = $constructor($(*$args.get_unchecked(i),)*); test::black_box(res) } - }) + })); } } ); diff --git a/benches/core/matrix.rs b/benches/core/matrix.rs index c323cd6e..896f2c97 100644 --- a/benches/core/matrix.rs +++ b/benches/core/matrix.rs @@ -196,3 +196,5 @@ fn mat100_from_fn(bench: &mut Bencher) { fn mat500_from_fn(bench: &mut Bencher) { bench.iter(|| DMatrix::from_fn(500, 500, |a, b| a + b)) } + +criterion_group!(matrix, mat2_transpose); \ No newline at end of file diff --git a/benches/core/mod.rs b/benches/core/mod.rs index 9699a728..f3e633a8 100644 --- a/benches/core/mod.rs +++ b/benches/core/mod.rs @@ -1,2 +1,2 @@ -mod matrix; -mod vector; +pub mod matrix; +pub mod vector; diff --git a/benches/core/vector.rs b/benches/core/vector.rs index 837eb7ca..814f50e7 100644 --- a/benches/core/vector.rs +++ b/benches/core/vector.rs @@ -1,7 +1,6 @@ use na::{DVector, Vector2, Vector3, Vector4, VectorN}; use rand::{IsaacRng, Rng}; use std::ops::{Add, Div, Mul, Sub}; -use test::{self, Bencher}; use typenum::U10000; #[path = "../common/macros.rs"] @@ -48,19 +47,17 @@ bench_unop!(vec4_normalize, Vector4, normalize); bench_binop_ref!(vec10000_dot_f64, VectorN, VectorN, dot); bench_binop_ref!(vec10000_dot_f32, VectorN, VectorN, dot); -#[bench] -fn vec10000_axpy_f64(bh: &mut Bencher) { +fn vec10000_axpy_f64(bh: &mut criterion::Criterion) { use rand::SeedableRng; let mut rng = IsaacRng::seed_from_u64(0); let mut a = DVector::new_random(10000); let b = DVector::new_random(10000); let n = rng.gen::(); - bh.iter(|| a.axpy(n, &b, 1.0)) + bh.bench_function("", move |bh| bh.iter(|| a.axpy(n, &b, 1.0))); } -#[bench] -fn vec10000_axpy_beta_f64(bh: &mut Bencher) { +fn vec10000_axpy_beta_f64(bh: &mut criterion::Criterion) { use rand::SeedableRng; let mut rng = IsaacRng::seed_from_u64(0); let mut a = DVector::new_random(10000); @@ -68,27 +65,25 @@ fn vec10000_axpy_beta_f64(bh: &mut Bencher) { let n = rng.gen::(); let beta = rng.gen::(); - bh.iter(|| a.axpy(n, &b, beta)) + bh.bench_function("", move |bh| bh.iter(|| a.axpy(n, &b, beta))); } -#[bench] -fn vec10000_axpy_f64_slice(bh: &mut Bencher) { +fn vec10000_axpy_f64_slice(bh: &mut criterion::Criterion) { use rand::SeedableRng; let mut rng = IsaacRng::seed_from_u64(0); let mut a = DVector::new_random(10000); let b = DVector::new_random(10000); let n = rng.gen::(); - bh.iter(|| { + bh.bench_function("", move |bh| bh.iter(|| { let mut a = a.fixed_rows_mut::(0); let b = b.fixed_rows::(0); a.axpy(n, &b, 1.0) - }) + })); } -#[bench] -fn vec10000_axpy_f64_static(bh: &mut Bencher) { +fn vec10000_axpy_f64_static(bh: &mut criterion::Criterion) { use rand::SeedableRng; let mut rng = IsaacRng::seed_from_u64(0); let mut a = VectorN::::new_random(); @@ -96,22 +91,20 @@ fn vec10000_axpy_f64_static(bh: &mut Bencher) { let n = rng.gen::(); // NOTE: for some reasons, it is much faster if the arument are boxed (Box::new(VectorN...)). - bh.iter(|| a.axpy(n, &b, 1.0)) + bh.bench_function("", move |bh| bh.iter(|| a.axpy(n, &b, 1.0))); } -#[bench] -fn vec10000_axpy_f32(bh: &mut Bencher) { +fn vec10000_axpy_f32(bh: &mut criterion::Criterion) { use rand::SeedableRng; let mut rng = IsaacRng::seed_from_u64(0); let mut a = DVector::new_random(10000); let b = DVector::new_random(10000); let n = rng.gen::(); - bh.iter(|| a.axpy(n, &b, 1.0)) + bh.bench_function("", move |bh| bh.iter(|| a.axpy(n, &b, 1.0))); } -#[bench] -fn vec10000_axpy_beta_f32(bh: &mut Bencher) { +fn vec10000_axpy_beta_f32(bh: &mut criterion::Criterion) { use rand::SeedableRng; let mut rng = IsaacRng::seed_from_u64(0); let mut a = DVector::new_random(10000); @@ -119,5 +112,7 @@ fn vec10000_axpy_beta_f32(bh: &mut Bencher) { let n = rng.gen::(); let beta = rng.gen::(); - bh.iter(|| a.axpy(n, &b, beta)) + bh.bench_function("", move |bh| bh.iter(|| a.axpy(n, &b, beta))); } + +criterion_group!(vector, vec10000_axpy_f64_static); diff --git a/benches/lib.rs b/benches/lib.rs index f788c998..7c8cdc70 100644 --- a/benches/lib.rs +++ b/benches/lib.rs @@ -6,15 +6,20 @@ extern crate rand; extern crate test; extern crate typenum; +#[macro_use] +extern crate criterion; + use na::DMatrix; use rand::{IsaacRng, Rng}; -mod core; -mod geometry; -mod linalg; +pub mod core; +pub mod geometry; +pub mod linalg; fn reproductible_dmatrix(nrows: usize, ncols: usize) -> DMatrix { use rand::SeedableRng; let mut rng = IsaacRng::seed_from_u64(0); DMatrix::::from_fn(nrows, ncols, |_, _| rng.gen()) } + +criterion_main!(core::matrix::matrix, core::vector::vector); \ No newline at end of file From dabff333e7a9d89e038b1ce2ede3b31d9aca5d27 Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sat, 23 Mar 2019 18:15:15 +0100 Subject: [PATCH 15/28] Port bidiagonalization benchmark to criterion. --- benches/lib.rs | 2 +- benches/linalg/bidiagonal.rs | 66 +++++++++++++++++++----------------- benches/linalg/mod.rs | 4 ++- 3 files changed, 38 insertions(+), 34 deletions(-) diff --git a/benches/lib.rs b/benches/lib.rs index 7c8cdc70..e500e82c 100644 --- a/benches/lib.rs +++ b/benches/lib.rs @@ -22,4 +22,4 @@ fn reproductible_dmatrix(nrows: usize, ncols: usize) -> DMatrix { DMatrix::::from_fn(nrows, ncols, |_, _| rng.gen()) } -criterion_main!(core::matrix::matrix, core::vector::vector); \ No newline at end of file +criterion_main!(core::matrix::matrix, core::vector::vector, linalg::bidiagonal); \ No newline at end of file diff --git a/benches/linalg/bidiagonal.rs b/benches/linalg/bidiagonal.rs index 9e5a723e..3cb9e666 100644 --- a/benches/linalg/bidiagonal.rs +++ b/benches/linalg/bidiagonal.rs @@ -1,73 +1,75 @@ use na::{Bidiagonal, DMatrix, Matrix4}; -use test::{self, Bencher}; #[path = "../common/macros.rs"] mod macros; // Without unpack. -#[bench] -fn bidiagonalize_100x100(bh: &mut Bencher) { +fn bidiagonalize_100x100(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(100, 100); - bh.iter(|| test::black_box(Bidiagonal::new(m.clone()))) + bh.bench_function("bidiagonalize_100x100", move |bh| bh.iter(|| test::black_box(Bidiagonal::new(m.clone())))); } -#[bench] -fn bidiagonalize_100x500(bh: &mut Bencher) { +fn bidiagonalize_100x500(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(100, 500); - bh.iter(|| test::black_box(Bidiagonal::new(m.clone()))) + bh.bench_function("bidiagonalize_100x500", move |bh| bh.iter(|| test::black_box(Bidiagonal::new(m.clone())))); } -#[bench] -fn bidiagonalize_4x4(bh: &mut Bencher) { +fn bidiagonalize_4x4(bh: &mut criterion::Criterion) { let m = Matrix4::::new_random(); - bh.iter(|| test::black_box(Bidiagonal::new(m.clone()))) + bh.bench_function("bidiagonalize_4x4", move |bh| bh.iter(|| test::black_box(Bidiagonal::new(m.clone())))); } -#[bench] -fn bidiagonalize_500x100(bh: &mut Bencher) { +fn bidiagonalize_500x100(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(500, 100); - bh.iter(|| test::black_box(Bidiagonal::new(m.clone()))) + bh.bench_function("bidiagonalize_500x100", move |bh| bh.iter(|| test::black_box(Bidiagonal::new(m.clone())))); } -#[bench] -fn bidiagonalize_500x500(bh: &mut Bencher) { +fn bidiagonalize_500x500(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(500, 500); - bh.iter(|| test::black_box(Bidiagonal::new(m.clone()))) + bh.bench_function("bidiagonalize_500x500", move |bh| bh.iter(|| test::black_box(Bidiagonal::new(m.clone())))); } // With unpack. -#[bench] -fn bidiagonalize_unpack_100x100(bh: &mut Bencher) { +fn bidiagonalize_unpack_100x100(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(100, 100); - bh.iter(|| { + bh.bench_function("bidiagonalize_unpack_100x100", move |bh| bh.iter(|| { let bidiag = Bidiagonal::new(m.clone()); let _ = bidiag.unpack(); - }) + })); } -#[bench] -fn bidiagonalize_unpack_100x500(bh: &mut Bencher) { +fn bidiagonalize_unpack_100x500(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(100, 500); - bh.iter(|| { + bh.bench_function("bidiagonalize_unpack_100x500", move |bh| bh.iter(|| { let bidiag = Bidiagonal::new(m.clone()); let _ = bidiag.unpack(); - }) + })); } -#[bench] -fn bidiagonalize_unpack_500x100(bh: &mut Bencher) { +fn bidiagonalize_unpack_500x100(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(500, 100); - bh.iter(|| { + bh.bench_function("bidiagonalize_unpack_500x100", move |bh| bh.iter(|| { let bidiag = Bidiagonal::new(m.clone()); let _ = bidiag.unpack(); - }) + })); } -#[bench] -fn bidiagonalize_unpack_500x500(bh: &mut Bencher) { +fn bidiagonalize_unpack_500x500(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(500, 500); - bh.iter(|| { + bh.bench_function("bidiagonalize_unpack_500x500", move |bh| bh.iter(|| { let bidiag = Bidiagonal::new(m.clone()); let _ = bidiag.unpack(); - }) + })); } + +criterion_group!(bidiagonal, + bidiagonalize_100x100, + bidiagonalize_100x500, + bidiagonalize_4x4, + bidiagonalize_500x100, + bidiagonalize_500x500, + bidiagonalize_unpack_100x100, + bidiagonalize_unpack_100x500, + bidiagonalize_unpack_500x100, + bidiagonalize_unpack_500x500 +); \ No newline at end of file diff --git a/benches/linalg/mod.rs b/benches/linalg/mod.rs index 526b32ea..fb38835b 100644 --- a/benches/linalg/mod.rs +++ b/benches/linalg/mod.rs @@ -1,3 +1,5 @@ +pub use self::bidiagonal::bidiagonal; + mod bidiagonal; mod cholesky; mod full_piv_lu; @@ -8,4 +10,4 @@ mod schur; mod solve; mod svd; mod symmetric_eigen; -// mod eigen; +// mod eigen; \ No newline at end of file From 1e60bc822ba20c417dc54ecb9b5a539a33291e12 Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sat, 23 Mar 2019 19:07:16 +0100 Subject: [PATCH 16/28] Port all remaining benchmarks to criterion. --- benches/core/matrix.rs | 166 ++++++++++++++++++------------ benches/core/mod.rs | 7 +- benches/core/vector.rs | 62 +++++++++-- benches/geometry/mod.rs | 2 + benches/geometry/quaternion.rs | 12 ++- benches/lib.rs | 16 ++- benches/linalg/bidiagonal.rs | 4 +- benches/linalg/cholesky.rs | 81 ++++++++------- benches/linalg/eigen.rs | 27 ++--- benches/linalg/full_piv_lu.rs | 83 ++++++++------- benches/linalg/hessenberg.rs | 52 +++++----- benches/linalg/lu.rs | 80 +++++++------- benches/linalg/mod.rs | 9 ++ benches/linalg/qr.rs | 109 ++++++++++---------- benches/linalg/schur.rs | 52 +++++----- benches/linalg/solve.rs | 69 +++++++------ benches/linalg/svd.rs | 101 +++++++++--------- benches/linalg/symmetric_eigen.rs | 28 ++--- 18 files changed, 555 insertions(+), 405 deletions(-) diff --git a/benches/core/matrix.rs b/benches/core/matrix.rs index 896f2c97..12fb836d 100644 --- a/benches/core/matrix.rs +++ b/benches/core/matrix.rs @@ -1,7 +1,6 @@ use na::{DMatrix, DVector, Matrix2, Matrix3, Matrix4, MatrixN, Vector2, Vector3, Vector4, U10}; use rand::{IsaacRng, Rng}; use std::ops::{Add, Div, Mul, Sub}; -use test::{self, Bencher}; #[path = "../common/macros.rs"] mod macros; @@ -46,155 +45,196 @@ bench_unop!(mat2_transpose, Matrix2, transpose); bench_unop!(mat3_transpose, Matrix3, transpose); bench_unop!(mat4_transpose, Matrix4, transpose); -#[bench] -fn mat_div_scalar(b: &mut Bencher) { +fn mat_div_scalar(b: &mut criterion::Criterion) { let a = DMatrix::from_row_slice(1000, 1000, &vec![2.0; 1000000]); let n = 42.0; - b.iter(|| { + b.bench_function("mat_div_scalar", move |bh| bh.iter(|| { let mut aa = a.clone(); let mut b = aa.slice_mut((0, 0), (1000, 1000)); b /= n - }) + })); } -#[bench] -fn mat100_add_mat100(bench: &mut Bencher) { +fn mat100_add_mat100(bench: &mut criterion::Criterion) { let a = DMatrix::::new_random(100, 100); let b = DMatrix::::new_random(100, 100); - bench.iter(|| &a + &b) + bench.bench_function("mat100_add_mat100", move |bh| bh.iter(|| &a + &b)); } -#[bench] -fn mat4_mul_mat4(bench: &mut Bencher) { +fn mat4_mul_mat4(bench: &mut criterion::Criterion) { let a = DMatrix::::new_random(4, 4); let b = DMatrix::::new_random(4, 4); - bench.iter(|| &a * &b) + bench.bench_function("mat4_mul_mat4", move |bh| bh.iter(|| &a * &b)); } -#[bench] -fn mat5_mul_mat5(bench: &mut Bencher) { +fn mat5_mul_mat5(bench: &mut criterion::Criterion) { let a = DMatrix::::new_random(5, 5); let b = DMatrix::::new_random(5, 5); - bench.iter(|| &a * &b) + bench.bench_function("mat5_mul_mat5", move |bh| bh.iter(|| &a * &b)); } -#[bench] -fn mat6_mul_mat6(bench: &mut Bencher) { +fn mat6_mul_mat6(bench: &mut criterion::Criterion) { let a = DMatrix::::new_random(6, 6); let b = DMatrix::::new_random(6, 6); - bench.iter(|| &a * &b) + bench.bench_function("mat6_mul_mat6", move |bh| bh.iter(|| &a * &b)); } -#[bench] -fn mat7_mul_mat7(bench: &mut Bencher) { +fn mat7_mul_mat7(bench: &mut criterion::Criterion) { let a = DMatrix::::new_random(7, 7); let b = DMatrix::::new_random(7, 7); - bench.iter(|| &a * &b) + bench.bench_function("mat7_mul_mat7", move |bh| bh.iter(|| &a * &b)); } -#[bench] -fn mat8_mul_mat8(bench: &mut Bencher) { +fn mat8_mul_mat8(bench: &mut criterion::Criterion) { let a = DMatrix::::new_random(8, 8); let b = DMatrix::::new_random(8, 8); - bench.iter(|| &a * &b) + bench.bench_function("mat8_mul_mat8", move |bh| bh.iter(|| &a * &b)); } -#[bench] -fn mat9_mul_mat9(bench: &mut Bencher) { +fn mat9_mul_mat9(bench: &mut criterion::Criterion) { let a = DMatrix::::new_random(9, 9); let b = DMatrix::::new_random(9, 9); - bench.iter(|| &a * &b) + bench.bench_function("mat9_mul_mat9", move |bh| bh.iter(|| &a * &b)); } -#[bench] -fn mat10_mul_mat10(bench: &mut Bencher) { +fn mat10_mul_mat10(bench: &mut criterion::Criterion) { let a = DMatrix::::new_random(10, 10); let b = DMatrix::::new_random(10, 10); - bench.iter(|| &a * &b) + bench.bench_function("mat10_mul_mat10", move |bh| bh.iter(|| &a * &b)); } -#[bench] -fn mat10_mul_mat10_static(bench: &mut Bencher) { +fn mat10_mul_mat10_static(bench: &mut criterion::Criterion) { let a = MatrixN::::new_random(); let b = MatrixN::::new_random(); - bench.iter(|| &a * &b) + bench.bench_function("mat10_mul_mat10_static", move |bh| bh.iter(|| &a * &b)); } -#[bench] -fn mat100_mul_mat100(bench: &mut Bencher) { +fn mat100_mul_mat100(bench: &mut criterion::Criterion) { let a = DMatrix::::new_random(100, 100); let b = DMatrix::::new_random(100, 100); - bench.iter(|| &a * &b) + bench.bench_function("mat100_mul_mat100", move |bh| bh.iter(|| &a * &b)); } -#[bench] -fn mat500_mul_mat500(bench: &mut Bencher) { +fn mat500_mul_mat500(bench: &mut criterion::Criterion) { let a = DMatrix::::from_element(500, 500, 5f64); let b = DMatrix::::from_element(500, 500, 6f64); - bench.iter(|| &a * &b) + bench.bench_function("mat500_mul_mat500", move |bh| bh.iter(|| &a * &b)); } -#[bench] -fn copy_from(bench: &mut Bencher) { +fn copy_from(bench: &mut criterion::Criterion) { let a = DMatrix::::new_random(1000, 1000); let mut b = DMatrix::::new_random(1000, 1000); - bench.iter(|| { - b.copy_from(&a); - }) + bench.bench_function("copy_from", move |bh| bh.iter(|| { + b.copy_from(&a); + })); } -#[bench] -fn axpy(bench: &mut Bencher) { +fn axpy(bench: &mut criterion::Criterion) { let x = DVector::::from_element(100000, 2.0); let mut y = DVector::::from_element(100000, 3.0); let a = 42.0; - bench.iter(|| { - y.axpy(a, &x, 1.0); - }) + bench.bench_function("axpy", move |bh| bh.iter(|| { + y.axpy(a, &x, 1.0); + })); } -#[bench] -fn tr_mul_to(bench: &mut Bencher) { +fn tr_mul_to(bench: &mut criterion::Criterion) { let a = DMatrix::::new_random(1000, 1000); let b = DVector::::new_random(1000); let mut c = DVector::from_element(1000, 0.0); - bench.iter(|| a.tr_mul_to(&b, &mut c)) + bench.bench_function("", move |bh| bh.iter(|| a.tr_mul_to(&b, &mut c))); } -#[bench] -fn mat_mul_mat(bench: &mut Bencher) { +fn mat_mul_mat(bench: &mut criterion::Criterion) { let a = DMatrix::::new_random(100, 100); let b = DMatrix::::new_random(100, 100); let mut ab = DMatrix::::from_element(100, 100, 0.0); - bench.iter(|| { - test::black_box(a.mul_to(&b, &mut ab)); - }) + bench.bench_function("mat_mul_mat", move |bh| bh.iter(|| { + test::black_box(a.mul_to(&b, &mut ab)); + })); } -#[bench] -fn mat100_from_fn(bench: &mut Bencher) { - bench.iter(|| DMatrix::from_fn(100, 100, |a, b| a + b)) +fn mat100_from_fn(bench: &mut criterion::Criterion) { + bench.bench_function("mat100_from_fn", move |bh| bh.iter(|| DMatrix::from_fn(100, 100, |a, b| a + b))); } -#[bench] -fn mat500_from_fn(bench: &mut Bencher) { - bench.iter(|| DMatrix::from_fn(500, 500, |a, b| a + b)) +fn mat500_from_fn(bench: &mut criterion::Criterion) { + bench.bench_function("mat500_from_fn", move |bh| bh.iter(|| DMatrix::from_fn(500, 500, |a, b| a + b))); } -criterion_group!(matrix, mat2_transpose); \ No newline at end of file +criterion_group!(matrix, + mat2_mul_m, + mat3_mul_m, + mat4_mul_m, + + mat2_tr_mul_m, + mat3_tr_mul_m, + mat4_tr_mul_m, + + mat2_add_m, + mat3_add_m, + mat4_add_m, + + mat2_sub_m, + mat3_sub_m, + mat4_sub_m, + + mat2_mul_v, + mat3_mul_v, + mat4_mul_v, + + mat2_tr_mul_v, + mat3_tr_mul_v, + mat4_tr_mul_v, + + mat2_mul_s, + mat3_mul_s, + mat4_mul_s, + + mat2_div_s, + mat3_div_s, + mat4_div_s, + + mat2_inv, + mat3_inv, + mat4_inv, + + mat2_transpose, + mat3_transpose, + mat4_transpose, + + mat_div_scalar, + mat100_add_mat100, + mat4_mul_mat4, + mat5_mul_mat5, + mat6_mul_mat6, + mat7_mul_mat7, + mat8_mul_mat8, + mat9_mul_mat9, + mat10_mul_mat10, + mat10_mul_mat10_static, + mat100_mul_mat100, + mat500_mul_mat500, + copy_from, + axpy, + tr_mul_to, + mat_mul_mat, + mat100_from_fn, + mat500_from_fn, +); \ No newline at end of file diff --git a/benches/core/mod.rs b/benches/core/mod.rs index f3e633a8..eda9ddaa 100644 --- a/benches/core/mod.rs +++ b/benches/core/mod.rs @@ -1,2 +1,5 @@ -pub mod matrix; -pub mod vector; +pub use self::matrix::matrix; +pub use self::vector::vector; + +mod matrix; +mod vector; diff --git a/benches/core/vector.rs b/benches/core/vector.rs index 814f50e7..7d3237e8 100644 --- a/benches/core/vector.rs +++ b/benches/core/vector.rs @@ -54,7 +54,7 @@ fn vec10000_axpy_f64(bh: &mut criterion::Criterion) { let b = DVector::new_random(10000); let n = rng.gen::(); - bh.bench_function("", move |bh| bh.iter(|| a.axpy(n, &b, 1.0))); + bh.bench_function("vec10000_axpy_f64", move |bh| bh.iter(|| a.axpy(n, &b, 1.0))); } fn vec10000_axpy_beta_f64(bh: &mut criterion::Criterion) { @@ -65,7 +65,7 @@ fn vec10000_axpy_beta_f64(bh: &mut criterion::Criterion) { let n = rng.gen::(); let beta = rng.gen::(); - bh.bench_function("", move |bh| bh.iter(|| a.axpy(n, &b, beta))); + bh.bench_function("vec10000_axpy_beta_f64", move |bh| bh.iter(|| a.axpy(n, &b, beta))); } fn vec10000_axpy_f64_slice(bh: &mut criterion::Criterion) { @@ -75,7 +75,7 @@ fn vec10000_axpy_f64_slice(bh: &mut criterion::Criterion) { let b = DVector::new_random(10000); let n = rng.gen::(); - bh.bench_function("", move |bh| bh.iter(|| { + bh.bench_function("vec10000_axpy_f64_slice", move |bh| bh.iter(|| { let mut a = a.fixed_rows_mut::(0); let b = b.fixed_rows::(0); @@ -91,7 +91,7 @@ fn vec10000_axpy_f64_static(bh: &mut criterion::Criterion) { let n = rng.gen::(); // NOTE: for some reasons, it is much faster if the arument are boxed (Box::new(VectorN...)). - bh.bench_function("", move |bh| bh.iter(|| a.axpy(n, &b, 1.0))); + bh.bench_function("vec10000_axpy_f64_static", move |bh| bh.iter(|| a.axpy(n, &b, 1.0))); } fn vec10000_axpy_f32(bh: &mut criterion::Criterion) { @@ -101,7 +101,7 @@ fn vec10000_axpy_f32(bh: &mut criterion::Criterion) { let b = DVector::new_random(10000); let n = rng.gen::(); - bh.bench_function("", move |bh| bh.iter(|| a.axpy(n, &b, 1.0))); + bh.bench_function("vec10000_axpy_f32", move |bh| bh.iter(|| a.axpy(n, &b, 1.0))); } fn vec10000_axpy_beta_f32(bh: &mut criterion::Criterion) { @@ -112,7 +112,55 @@ fn vec10000_axpy_beta_f32(bh: &mut criterion::Criterion) { let n = rng.gen::(); let beta = rng.gen::(); - bh.bench_function("", move |bh| bh.iter(|| a.axpy(n, &b, beta))); + bh.bench_function("vec10000_axpy_beta_f32", move |bh| bh.iter(|| a.axpy(n, &b, beta))); } -criterion_group!(vector, vec10000_axpy_f64_static); +criterion_group!(vector, + vec2_add_v_f32, + vec3_add_v_f32, + vec4_add_v_f32, + + vec2_add_v_f64, + vec3_add_v_f64, + vec4_add_v_f64, + + vec2_sub_v, + vec3_sub_v, + vec4_sub_v, + + vec2_mul_s, + vec3_mul_s, + vec4_mul_s, + + vec2_div_s, + vec3_div_s, + vec4_div_s, + + vec2_dot_f32, + vec3_dot_f32, + vec4_dot_f32, + + vec2_dot_f64, + vec3_dot_f64, + vec4_dot_f64, + + vec3_cross, + + vec2_norm, + vec3_norm, + vec4_norm, + + vec2_normalize, + vec3_normalize, + vec4_normalize, + + vec10000_dot_f64, + vec10000_dot_f32, + + vec10000_axpy_f64, + vec10000_axpy_beta_f64, + vec10000_axpy_f64_slice, + vec10000_axpy_f64_static, + vec10000_axpy_f32, + vec10000_axpy_beta_f32 +); diff --git a/benches/geometry/mod.rs b/benches/geometry/mod.rs index 0f9eb371..d0d0e948 100644 --- a/benches/geometry/mod.rs +++ b/benches/geometry/mod.rs @@ -1 +1,3 @@ +pub use quaternion::quaternion; + mod quaternion; diff --git a/benches/geometry/quaternion.rs b/benches/geometry/quaternion.rs index bc94c054..dd079aac 100644 --- a/benches/geometry/quaternion.rs +++ b/benches/geometry/quaternion.rs @@ -1,7 +1,6 @@ use na::{Quaternion, UnitQuaternion, Vector3}; use rand::{IsaacRng, Rng}; use std::ops::{Add, Div, Mul, Sub}; -use test::{self, Bencher}; #[path = "../common/macros.rs"] mod macros; @@ -25,3 +24,14 @@ bench_unop!(unit_quaternion_inv, UnitQuaternion, inverse); // bench_unop_self!(quaternion_conjugate, Quaternion, conjugate); // bench_unop!(quaternion_normalize, Quaternion, normalize); + +criterion_group!(quaternion, + quaternion_add_q, + quaternion_sub_q, + quaternion_mul_q, + unit_quaternion_mul_v, + quaternion_mul_s, + quaternion_div_s, + quaternion_inv, + unit_quaternion_inv +); \ No newline at end of file diff --git a/benches/lib.rs b/benches/lib.rs index e500e82c..d5333542 100644 --- a/benches/lib.rs +++ b/benches/lib.rs @@ -22,4 +22,18 @@ fn reproductible_dmatrix(nrows: usize, ncols: usize) -> DMatrix { DMatrix::::from_fn(nrows, ncols, |_, _| rng.gen()) } -criterion_main!(core::matrix::matrix, core::vector::vector, linalg::bidiagonal); \ No newline at end of file +criterion_main!( + core::matrix, + core::vector, + geometry::quaternion, + linalg::bidiagonal, + linalg::cholesky, + linalg::full_piv_lu, + linalg::hessenberg, + linalg::lu, + linalg::qr, + linalg::schur, + linalg::solve, + linalg::svd, + linalg::symmetric_eigen, +); \ No newline at end of file diff --git a/benches/linalg/bidiagonal.rs b/benches/linalg/bidiagonal.rs index 3cb9e666..ed126205 100644 --- a/benches/linalg/bidiagonal.rs +++ b/benches/linalg/bidiagonal.rs @@ -67,9 +67,9 @@ criterion_group!(bidiagonal, bidiagonalize_100x500, bidiagonalize_4x4, bidiagonalize_500x100, - bidiagonalize_500x500, +// bidiagonalize_500x500, // too long bidiagonalize_unpack_100x100, bidiagonalize_unpack_100x500, bidiagonalize_unpack_500x100, - bidiagonalize_unpack_500x500 +// bidiagonalize_unpack_500x500 // too long ); \ No newline at end of file diff --git a/benches/linalg/cholesky.rs b/benches/linalg/cholesky.rs index 73c028cb..40ca9821 100644 --- a/benches/linalg/cholesky.rs +++ b/benches/linalg/cholesky.rs @@ -1,109 +1,112 @@ use na::{Cholesky, DMatrix, DVector}; -use test::{self, Bencher}; -#[bench] -fn cholesky_100x100(bh: &mut Bencher) { +fn cholesky_100x100(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(100, 100); let m = &m * m.transpose(); - bh.iter(|| test::black_box(Cholesky::new(m.clone()))) + bh.bench_function("cholesky_100x100", move |bh| bh.iter(|| test::black_box(Cholesky::new(m.clone())))); } -#[bench] -fn cholesky_500x500(bh: &mut Bencher) { +fn cholesky_500x500(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(500, 500); let m = &m * m.transpose(); - bh.iter(|| test::black_box(Cholesky::new(m.clone()))) + bh.bench_function("cholesky_500x500", move |bh| bh.iter(|| test::black_box(Cholesky::new(m.clone())))); } // With unpack. -#[bench] -fn cholesky_decompose_unpack_100x100(bh: &mut Bencher) { +fn cholesky_decompose_unpack_100x100(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(100, 100); let m = &m * m.transpose(); - bh.iter(|| { + bh.bench_function("cholesky_decompose_unpack_100x100", move |bh| bh.iter(|| { let chol = Cholesky::new(m.clone()).unwrap(); let _ = chol.unpack(); - }) + })); } -#[bench] -fn cholesky_decompose_unpack_500x500(bh: &mut Bencher) { +fn cholesky_decompose_unpack_500x500(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(500, 500); let m = &m * m.transpose(); - bh.iter(|| { + bh.bench_function("cholesky_decompose_unpack_500x500", move |bh| bh.iter(|| { let chol = Cholesky::new(m.clone()).unwrap(); let _ = chol.unpack(); - }) + })); } -#[bench] -fn cholesky_solve_10x10(bh: &mut Bencher) { +fn cholesky_solve_10x10(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(10, 10); let m = &m * m.transpose(); let v = DVector::::new_random(10); let chol = Cholesky::new(m.clone()).unwrap(); - bh.iter(|| { + bh.bench_function("cholesky_solve_10x10", move |bh| bh.iter(|| { let _ = chol.solve(&v); - }) + })); } -#[bench] -fn cholesky_solve_100x100(bh: &mut Bencher) { +fn cholesky_solve_100x100(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(100, 100); let m = &m * m.transpose(); let v = DVector::::new_random(100); let chol = Cholesky::new(m.clone()).unwrap(); - bh.iter(|| { + bh.bench_function("cholesky_solve_100x100", move |bh| bh.iter(|| { let _ = chol.solve(&v); - }) + })); } -#[bench] -fn cholesky_solve_500x500(bh: &mut Bencher) { +fn cholesky_solve_500x500(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(500, 500); let m = &m * m.transpose(); let v = DVector::::new_random(500); let chol = Cholesky::new(m.clone()).unwrap(); - bh.iter(|| { + bh.bench_function("cholesky_solve_500x500", move |bh| bh.iter(|| { let _ = chol.solve(&v); - }) + })); } -#[bench] -fn cholesky_inverse_10x10(bh: &mut Bencher) { + +fn cholesky_inverse_10x10(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(10, 10); let m = &m * m.transpose(); let chol = Cholesky::new(m.clone()).unwrap(); - bh.iter(|| { + bh.bench_function("cholesky_inverse_10x10", move |bh| bh.iter(|| { let _ = chol.inverse(); - }) + })); } -#[bench] -fn cholesky_inverse_100x100(bh: &mut Bencher) { +fn cholesky_inverse_100x100(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(100, 100); let m = &m * m.transpose(); let chol = Cholesky::new(m.clone()).unwrap(); - bh.iter(|| { + bh.bench_function("cholesky_inverse_100x100", move |bh| bh.iter(|| { let _ = chol.inverse(); - }) + })); } -#[bench] -fn cholesky_inverse_500x500(bh: &mut Bencher) { +fn cholesky_inverse_500x500(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(500, 500); let m = &m * m.transpose(); let chol = Cholesky::new(m.clone()).unwrap(); - bh.iter(|| { + bh.bench_function("cholesky_inverse_500x500", move |bh| bh.iter(|| { let _ = chol.inverse(); - }) + })); } + +criterion_group!(cholesky, + cholesky_100x100, + cholesky_500x500, + cholesky_decompose_unpack_100x100, + cholesky_decompose_unpack_500x500, + cholesky_solve_10x10, + cholesky_solve_100x100, + cholesky_solve_500x500, + cholesky_inverse_10x10, + cholesky_inverse_100x100, + cholesky_inverse_500x500 +); \ No newline at end of file diff --git a/benches/linalg/eigen.rs b/benches/linalg/eigen.rs index 54aa77a5..0b1e6b26 100644 --- a/benches/linalg/eigen.rs +++ b/benches/linalg/eigen.rs @@ -1,30 +1,33 @@ use test::Bencher; use na::{DMatrix, Eigen}; -#[bench] -fn eigen_100x100(bh: &mut Bencher) { +fn eigen_100x100(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(100, 100); - bh.iter(|| Eigen::new(m.clone(), 1.0e-7, 0)) + bh.bench_function("eigen_100x100", move |bh| bh.iter(|| Eigen::new(m.clone(), 1.0e-7, 0))); } -#[bench] -fn eigen_500x500(bh: &mut Bencher) { +fn eigen_500x500(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(500, 500); - bh.iter(|| Eigen::new(m.clone(), 1.0e-7, 0)) + bh.bench_function("eigen_500x500", move |bh| bh.iter(|| Eigen::new(m.clone(), 1.0e-7, 0))); } -#[bench] -fn eigenvalues_100x100(bh: &mut Bencher) { +fn eigenvalues_100x100(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(100, 100); - bh.iter(|| m.clone().eigenvalues(1.0e-7, 0)) + bh.bench_function("eigenvalues_100x100", move |bh| bh.iter(|| m.clone().eigenvalues(1.0e-7, 0))); } -#[bench] -fn eigenvalues_500x500(bh: &mut Bencher) { +fn eigenvalues_500x500(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(500, 500); - bh.iter(|| m.clone().eigenvalues(1.0e-7, 0)) + bh.bench_function("eigenvalues_500x500", move |bh| bh.iter(|| m.clone().eigenvalues(1.0e-7, 0))); } + +criterion_group!(eigen, + eigen_100x100, +// eigen_500x500, + eigenvalues_100x100, +// eigenvalues_500x500 +); diff --git a/benches/linalg/full_piv_lu.rs b/benches/linalg/full_piv_lu.rs index ad82b069..6c7b1fa6 100644 --- a/benches/linalg/full_piv_lu.rs +++ b/benches/linalg/full_piv_lu.rs @@ -1,102 +1,105 @@ use na::{DMatrix, DVector, FullPivLU}; -use test::{self, Bencher}; // Without unpack. -#[bench] -fn full_piv_lu_decompose_10x10(bh: &mut Bencher) { +fn full_piv_lu_decompose_10x10(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(10, 10); - bh.iter(|| test::black_box(FullPivLU::new(m.clone()))) + bh.bench_function("full_piv_lu_decompose_10x10", move |bh| bh.iter(|| test::black_box(FullPivLU::new(m.clone())))); } -#[bench] -fn full_piv_lu_decompose_100x100(bh: &mut Bencher) { +fn full_piv_lu_decompose_100x100(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(100, 100); - bh.iter(|| test::black_box(FullPivLU::new(m.clone()))) + bh.bench_function("full_piv_lu_decompose_100x100", move |bh| bh.iter(|| test::black_box(FullPivLU::new(m.clone())))); } -#[bench] -fn full_piv_lu_decompose_500x500(bh: &mut Bencher) { +fn full_piv_lu_decompose_500x500(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(500, 500); - bh.iter(|| test::black_box(FullPivLU::new(m.clone()))) + bh.bench_function("full_piv_lu_decompose_500x500", move |bh| bh.iter(|| test::black_box(FullPivLU::new(m.clone())))); } -#[bench] -fn full_piv_lu_solve_10x10(bh: &mut Bencher) { +fn full_piv_lu_solve_10x10(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(10, 10); let lu = FullPivLU::new(m.clone()); - bh.iter(|| { + bh.bench_function("full_piv_lu_solve_10x10", move |bh| bh.iter(|| { let mut b = DVector::::from_element(10, 1.0); lu.solve(&mut b); - }) + })); } -#[bench] -fn full_piv_lu_solve_100x100(bh: &mut Bencher) { +fn full_piv_lu_solve_100x100(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(100, 100); let lu = FullPivLU::new(m.clone()); - bh.iter(|| { + bh.bench_function("full_piv_lu_solve_100x100", move |bh| bh.iter(|| { let mut b = DVector::::from_element(100, 1.0); lu.solve(&mut b); - }) + })); } -#[bench] -fn full_piv_lu_solve_500x500(bh: &mut Bencher) { +fn full_piv_lu_solve_500x500(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(500, 500); let lu = FullPivLU::new(m.clone()); - bh.iter(|| { + bh.bench_function("full_piv_lu_solve_500x500", move |bh| bh.iter(|| { let mut b = DVector::::from_element(500, 1.0); lu.solve(&mut b); - }) + })); } -#[bench] -fn full_piv_lu_inverse_10x10(bh: &mut Bencher) { +fn full_piv_lu_inverse_10x10(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(10, 10); let lu = FullPivLU::new(m.clone()); - bh.iter(|| test::black_box(lu.try_inverse())) + bh.bench_function("full_piv_lu_inverse_10x10", move |bh| bh.iter(|| test::black_box(lu.try_inverse()))); } -#[bench] -fn full_piv_lu_inverse_100x100(bh: &mut Bencher) { +fn full_piv_lu_inverse_100x100(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(100, 100); let lu = FullPivLU::new(m.clone()); - bh.iter(|| test::black_box(lu.try_inverse())) + bh.bench_function("full_piv_lu_inverse_100x100", move |bh| bh.iter(|| test::black_box(lu.try_inverse()))); } -#[bench] -fn full_piv_lu_inverse_500x500(bh: &mut Bencher) { +fn full_piv_lu_inverse_500x500(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(500, 500); let lu = FullPivLU::new(m.clone()); - bh.iter(|| test::black_box(lu.try_inverse())) + bh.bench_function("full_piv_lu_inverse_500x500", move |bh| bh.iter(|| test::black_box(lu.try_inverse()))); } -#[bench] -fn full_piv_lu_determinant_10x10(bh: &mut Bencher) { +fn full_piv_lu_determinant_10x10(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(10, 10); let lu = FullPivLU::new(m.clone()); - bh.iter(|| test::black_box(lu.determinant())) + bh.bench_function("full_piv_lu_determinant_10x10", move |bh| bh.iter(|| test::black_box(lu.determinant()))); } -#[bench] -fn full_piv_lu_determinant_100x100(bh: &mut Bencher) { + +fn full_piv_lu_determinant_100x100(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(100, 100); let lu = FullPivLU::new(m.clone()); - bh.iter(|| test::black_box(lu.determinant())) + bh.bench_function("full_piv_lu_determinant_100x100", move |bh| bh.iter(|| test::black_box(lu.determinant()))); } -#[bench] -fn full_piv_lu_determinant_500x500(bh: &mut Bencher) { +fn full_piv_lu_determinant_500x500(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(500, 500); let lu = FullPivLU::new(m.clone()); - bh.iter(|| test::black_box(lu.determinant())) + bh.bench_function("full_piv_lu_determinant_500x500", move |bh| bh.iter(|| test::black_box(lu.determinant()))); } + +criterion_group!(full_piv_lu, + full_piv_lu_decompose_10x10, + full_piv_lu_decompose_100x100, +// full_piv_lu_decompose_500x500, + full_piv_lu_solve_10x10, + full_piv_lu_solve_100x100, +// full_piv_lu_solve_500x500, + full_piv_lu_inverse_10x10, + full_piv_lu_inverse_100x100, +// full_piv_lu_inverse_500x500, + full_piv_lu_determinant_10x10, + full_piv_lu_determinant_100x100, +// full_piv_lu_determinant_500x500 +); \ No newline at end of file diff --git a/benches/linalg/hessenberg.rs b/benches/linalg/hessenberg.rs index 427aa1fe..3340c3ef 100644 --- a/benches/linalg/hessenberg.rs +++ b/benches/linalg/hessenberg.rs @@ -1,58 +1,60 @@ use na::{DMatrix, Hessenberg, Matrix4}; -use test::{self, Bencher}; #[path = "../common/macros.rs"] mod macros; // Without unpack. -#[bench] -fn hessenberg_decompose_4x4(bh: &mut Bencher) { +fn hessenberg_decompose_4x4(bh: &mut criterion::Criterion) { let m = Matrix4::::new_random(); - bh.iter(|| test::black_box(Hessenberg::new(m.clone()))) + bh.bench_function("hessenberg_decompose_4x4", move |bh| bh.iter(|| test::black_box(Hessenberg::new(m.clone())))); } -#[bench] -fn hessenberg_decompose_100x100(bh: &mut Bencher) { +fn hessenberg_decompose_100x100(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(100, 100); - bh.iter(|| test::black_box(Hessenberg::new(m.clone()))) + bh.bench_function("hessenberg_decompose_100x100", move |bh| bh.iter(|| test::black_box(Hessenberg::new(m.clone())))); } -#[bench] -fn hessenberg_decompose_200x200(bh: &mut Bencher) { +fn hessenberg_decompose_200x200(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(200, 200); - bh.iter(|| test::black_box(Hessenberg::new(m.clone()))) + bh.bench_function("hessenberg_decompose_200x200", move |bh| bh.iter(|| test::black_box(Hessenberg::new(m.clone())))); } -#[bench] -fn hessenberg_decompose_500x500(bh: &mut Bencher) { +fn hessenberg_decompose_500x500(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(500, 500); - bh.iter(|| test::black_box(Hessenberg::new(m.clone()))) + bh.bench_function("hessenberg_decompose_500x500", move |bh| bh.iter(|| test::black_box(Hessenberg::new(m.clone())))); } // With unpack. -#[bench] -fn hessenberg_decompose_unpack_100x100(bh: &mut Bencher) { +fn hessenberg_decompose_unpack_100x100(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(100, 100); - bh.iter(|| { + bh.bench_function("hessenberg_decompose_unpack_100x100", move |bh| bh.iter(|| { let hess = Hessenberg::new(m.clone()); let _ = hess.unpack(); - }) + })); } -#[bench] -fn hessenberg_decompose_unpack_200x200(bh: &mut Bencher) { +fn hessenberg_decompose_unpack_200x200(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(200, 200); - bh.iter(|| { + bh.bench_function("hessenberg_decompose_unpack_200x200", move |bh| bh.iter(|| { let hess = Hessenberg::new(m.clone()); let _ = hess.unpack(); - }) + })); } -#[bench] -fn hessenberg_decompose_unpack_500x500(bh: &mut Bencher) { +fn hessenberg_decompose_unpack_500x500(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(500, 500); - bh.iter(|| { + bh.bench_function("hessenberg_decompose_unpack_500x500", move |bh| bh.iter(|| { let hess = Hessenberg::new(m.clone()); let _ = hess.unpack(); - }) + })); } + +criterion_group!(hessenberg, + hessenberg_decompose_4x4, + hessenberg_decompose_100x100, + hessenberg_decompose_200x200, +// hessenberg_decompose_500x500, + hessenberg_decompose_unpack_100x100, + hessenberg_decompose_unpack_200x200, +// hessenberg_decompose_unpack_500x500 +); \ No newline at end of file diff --git a/benches/linalg/lu.rs b/benches/linalg/lu.rs index 2428cf9c..e37cfe75 100644 --- a/benches/linalg/lu.rs +++ b/benches/linalg/lu.rs @@ -1,102 +1,102 @@ use na::{DMatrix, DVector, LU}; -use test::{self, Bencher}; // Without unpack. -#[bench] -fn lu_decompose_10x10(bh: &mut Bencher) { +fn lu_decompose_10x10(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(10, 10); - bh.iter(|| test::black_box(LU::new(m.clone()))) + bh.bench_function("lu_decompose_10x10", move |bh| bh.iter(|| test::black_box(LU::new(m.clone())))); } -#[bench] -fn lu_decompose_100x100(bh: &mut Bencher) { +fn lu_decompose_100x100(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(100, 100); - bh.iter(|| test::black_box(LU::new(m.clone()))) + bh.bench_function("lu_decompose_100x100", move |bh| bh.iter(|| test::black_box(LU::new(m.clone())))); } -#[bench] -fn lu_decompose_500x500(bh: &mut Bencher) { +fn lu_decompose_500x500(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(500, 500); - bh.iter(|| test::black_box(LU::new(m.clone()))) + bh.bench_function("lu_decompose_500x500", move |bh| bh.iter(|| test::black_box(LU::new(m.clone())))); } -#[bench] -fn lu_solve_10x10(bh: &mut Bencher) { +fn lu_solve_10x10(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(10, 10); let lu = LU::new(m.clone()); - bh.iter(|| { + bh.bench_function("lu_solve_10x10", move |bh| bh.iter(|| { let mut b = DVector::::from_element(10, 1.0); lu.solve(&mut b); - }) + })); } -#[bench] -fn lu_solve_100x100(bh: &mut Bencher) { +fn lu_solve_100x100(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(100, 100); let lu = LU::new(m.clone()); - bh.iter(|| { + bh.bench_function("lu_solve_100x100", move |bh| bh.iter(|| { let mut b = DVector::::from_element(100, 1.0); lu.solve(&mut b); - }) + })); } -#[bench] -fn lu_solve_500x500(bh: &mut Bencher) { +fn lu_solve_500x500(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(500, 500); let lu = LU::new(m.clone()); - bh.iter(|| { + bh.bench_function("", move |bh| bh.iter(|| { let mut b = DVector::::from_element(500, 1.0); lu.solve(&mut b); - }) + })); } -#[bench] -fn lu_inverse_10x10(bh: &mut Bencher) { +fn lu_inverse_10x10(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(10, 10); let lu = LU::new(m.clone()); - bh.iter(|| test::black_box(lu.try_inverse())) + bh.bench_function("lu_inverse_10x10", move |bh| bh.iter(|| test::black_box(lu.try_inverse()))); } -#[bench] -fn lu_inverse_100x100(bh: &mut Bencher) { +fn lu_inverse_100x100(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(100, 100); let lu = LU::new(m.clone()); - bh.iter(|| test::black_box(lu.try_inverse())) + bh.bench_function("lu_inverse_100x100", move |bh| bh.iter(|| test::black_box(lu.try_inverse()))); } -#[bench] -fn lu_inverse_500x500(bh: &mut Bencher) { +fn lu_inverse_500x500(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(500, 500); let lu = LU::new(m.clone()); - bh.iter(|| test::black_box(lu.try_inverse())) + bh.bench_function("lu_inverse_500x500", move |bh| bh.iter(|| test::black_box(lu.try_inverse()))); } -#[bench] -fn lu_determinant_10x10(bh: &mut Bencher) { +fn lu_determinant_10x10(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(10, 10); let lu = LU::new(m.clone()); - bh.iter(|| test::black_box(lu.determinant())) + bh.bench_function("lu_determinant_10x10", move |bh| bh.iter(|| test::black_box(lu.determinant()))); } -#[bench] -fn lu_determinant_100x100(bh: &mut Bencher) { +fn lu_determinant_100x100(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(100, 100); let lu = LU::new(m.clone()); - bh.iter(|| test::black_box(lu.determinant())) + bh.bench_function("lu_determinant_100x100", move |bh| bh.iter(|| test::black_box(lu.determinant()))); } -#[bench] -fn lu_determinant_500x500(bh: &mut Bencher) { +fn lu_determinant_500x500(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(500, 500); let lu = LU::new(m.clone()); - bh.iter(|| test::black_box(lu.determinant())) + bh.bench_function("", move |bh| bh.iter(|| test::black_box(lu.determinant()))); } + +criterion_group!(lu, + lu_decompose_10x10, + lu_decompose_100x100, +// lu_decompose_500x500, + lu_solve_10x10, + lu_solve_100x100, + lu_inverse_10x10, + lu_inverse_100x100, +// lu_inverse_500x500, + lu_determinant_10x10, + lu_determinant_100x100 +); \ No newline at end of file diff --git a/benches/linalg/mod.rs b/benches/linalg/mod.rs index fb38835b..a6e7a8ef 100644 --- a/benches/linalg/mod.rs +++ b/benches/linalg/mod.rs @@ -1,4 +1,13 @@ pub use self::bidiagonal::bidiagonal; +pub use self::cholesky::cholesky; +pub use self::full_piv_lu::full_piv_lu; +pub use self::hessenberg::hessenberg; +pub use self::lu::lu; +pub use self::qr::qr; +pub use self::schur::schur; +pub use self::solve::solve; +pub use self::svd::svd; +pub use self::symmetric_eigen::symmetric_eigen; mod bidiagonal; mod cholesky; diff --git a/benches/linalg/qr.rs b/benches/linalg/qr.rs index 41a814ff..8283c5e9 100644 --- a/benches/linalg/qr.rs +++ b/benches/linalg/qr.rs @@ -1,130 +1,133 @@ use na::{DMatrix, DVector, Matrix4, QR}; -use test::{self, Bencher}; #[path = "../common/macros.rs"] mod macros; // Without unpack. -#[bench] -fn qr_decompose_100x100(bh: &mut Bencher) { +fn qr_decompose_100x100(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(100, 100); - bh.iter(|| test::black_box(QR::new(m.clone()))) + bh.bench_function("qr_decompose_100x100", move |bh| bh.iter(|| test::black_box(QR::new(m.clone())))); } -#[bench] -fn qr_decompose_100x500(bh: &mut Bencher) { +fn qr_decompose_100x500(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(100, 500); - bh.iter(|| test::black_box(QR::new(m.clone()))) + bh.bench_function("qr_decompose_100x500", move |bh| bh.iter(|| test::black_box(QR::new(m.clone())))); } -#[bench] -fn qr_decompose_4x4(bh: &mut Bencher) { +fn qr_decompose_4x4(bh: &mut criterion::Criterion) { let m = Matrix4::::new_random(); - bh.iter(|| test::black_box(QR::new(m.clone()))) + bh.bench_function("qr_decompose_4x4", move |bh| bh.iter(|| test::black_box(QR::new(m.clone())))); } -#[bench] -fn qr_decompose_500x100(bh: &mut Bencher) { +fn qr_decompose_500x100(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(500, 100); - bh.iter(|| test::black_box(QR::new(m.clone()))) + bh.bench_function("qr_decompose_500x100", move |bh| bh.iter(|| test::black_box(QR::new(m.clone())))); } -#[bench] -fn qr_decompose_500x500(bh: &mut Bencher) { +fn qr_decompose_500x500(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(500, 500); - bh.iter(|| test::black_box(QR::new(m.clone()))) + bh.bench_function("qr_decompose_500x500", move |bh| bh.iter(|| test::black_box(QR::new(m.clone())))); } // With unpack. -#[bench] -fn qr_decompose_unpack_100x100(bh: &mut Bencher) { +fn qr_decompose_unpack_100x100(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(100, 100); - bh.iter(|| { + bh.bench_function("qr_decompose_unpack_100x100", move |bh| bh.iter(|| { let qr = QR::new(m.clone()); let _ = qr.unpack(); - }) + })); } -#[bench] -fn qr_decompose_unpack_100x500(bh: &mut Bencher) { +fn qr_decompose_unpack_100x500(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(100, 500); - bh.iter(|| { + bh.bench_function("qr_decompose_unpack_100x500", move |bh| bh.iter(|| { let qr = QR::new(m.clone()); let _ = qr.unpack(); - }) + })); } -#[bench] -fn qr_decompose_unpack_500x100(bh: &mut Bencher) { +fn qr_decompose_unpack_500x100(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(500, 100); - bh.iter(|| { + bh.bench_function("qr_decompose_unpack_500x100", move |bh| bh.iter(|| { let qr = QR::new(m.clone()); let _ = qr.unpack(); - }) + })); } -#[bench] -fn qr_decompose_unpack_500x500(bh: &mut Bencher) { +fn qr_decompose_unpack_500x500(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(500, 500); - bh.iter(|| { + bh.bench_function("qr_decompose_unpack_500x500", move |bh| bh.iter(|| { let qr = QR::new(m.clone()); let _ = qr.unpack(); - }) + })); } -#[bench] -fn qr_solve_10x10(bh: &mut Bencher) { +fn qr_solve_10x10(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(10, 10); let qr = QR::new(m.clone()); - bh.iter(|| { + bh.bench_function("qr_solve_10x10", move |bh| bh.iter(|| { let mut b = DVector::::from_element(10, 1.0); qr.solve(&mut b); - }) + })); } -#[bench] -fn qr_solve_100x100(bh: &mut Bencher) { +fn qr_solve_100x100(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(100, 100); let qr = QR::new(m.clone()); - bh.iter(|| { + bh.bench_function("qr_solve_100x100", move |bh| bh.iter(|| { let mut b = DVector::::from_element(100, 1.0); qr.solve(&mut b); - }) + })); } -#[bench] -fn qr_solve_500x500(bh: &mut Bencher) { +fn qr_solve_500x500(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(500, 500); let qr = QR::new(m.clone()); - bh.iter(|| { + bh.bench_function("qr_solve_500x500", move |bh| bh.iter(|| { let mut b = DVector::::from_element(500, 1.0); qr.solve(&mut b); - }) + })); } -#[bench] -fn qr_inverse_10x10(bh: &mut Bencher) { +fn qr_inverse_10x10(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(10, 10); let qr = QR::new(m.clone()); - bh.iter(|| test::black_box(qr.try_inverse())) + bh.bench_function("qr_inverse_10x10", move |bh| bh.iter(|| test::black_box(qr.try_inverse()))); } -#[bench] -fn qr_inverse_100x100(bh: &mut Bencher) { +fn qr_inverse_100x100(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(100, 100); let qr = QR::new(m.clone()); - bh.iter(|| test::black_box(qr.try_inverse())) + bh.bench_function("qr_inverse_100x100", move |bh| bh.iter(|| test::black_box(qr.try_inverse()))); } -#[bench] -fn qr_inverse_500x500(bh: &mut Bencher) { +fn qr_inverse_500x500(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(500, 500); let qr = QR::new(m.clone()); - bh.iter(|| test::black_box(qr.try_inverse())) + bh.bench_function("qr_inverse_500x500", move |bh| bh.iter(|| test::black_box(qr.try_inverse()))); } + + +criterion_group!(qr, + qr_decompose_100x100, + qr_decompose_100x500, + qr_decompose_4x4, + qr_decompose_500x100, +// qr_decompose_500x500, + qr_decompose_unpack_100x100, + qr_decompose_unpack_100x500, + qr_decompose_unpack_500x100, +// qr_decompose_unpack_500x500, + qr_solve_10x10, + qr_solve_100x100, +// qr_solve_500x500, + qr_inverse_10x10, + qr_inverse_100x100, +// qr_inverse_500x500 +); \ No newline at end of file diff --git a/benches/linalg/schur.rs b/benches/linalg/schur.rs index 024e6114..ffabc539 100644 --- a/benches/linalg/schur.rs +++ b/benches/linalg/schur.rs @@ -1,50 +1,52 @@ use na::{Matrix4, Schur}; -use test::{self, Bencher}; -#[bench] -fn schur_decompose_4x4(bh: &mut Bencher) { +fn schur_decompose_4x4(bh: &mut criterion::Criterion) { let m = Matrix4::::new_random(); - bh.iter(|| test::black_box(Schur::new(m.clone()))) + bh.bench_function("schur_decompose_4x4", move |bh| bh.iter(|| test::black_box(Schur::new(m.clone())))); } -#[bench] -fn schur_decompose_10x10(bh: &mut Bencher) { +fn schur_decompose_10x10(bh: &mut criterion::Criterion) { let m = crate::reproductible_dmatrix(10, 10); - bh.iter(|| test::black_box(Schur::new(m.clone()))) + bh.bench_function("schur_decompose_10x10", move |bh| bh.iter(|| test::black_box(Schur::new(m.clone())))); } -#[bench] -fn schur_decompose_100x100(bh: &mut Bencher) { +fn schur_decompose_100x100(bh: &mut criterion::Criterion) { let m = crate::reproductible_dmatrix(100, 100); - bh.iter(|| test::black_box(Schur::new(m.clone()))) + bh.bench_function("schur_decompose_100x100", move |bh| bh.iter(|| test::black_box(Schur::new(m.clone())))); } -#[bench] -fn schur_decompose_200x200(bh: &mut Bencher) { +fn schur_decompose_200x200(bh: &mut criterion::Criterion) { let m = crate::reproductible_dmatrix(200, 200); - bh.iter(|| test::black_box(Schur::new(m.clone()))) + bh.bench_function("schur_decompose_200x200", move |bh| bh.iter(|| test::black_box(Schur::new(m.clone())))); } -#[bench] -fn eigenvalues_4x4(bh: &mut Bencher) { +fn eigenvalues_4x4(bh: &mut criterion::Criterion) { let m = Matrix4::::new_random(); - bh.iter(|| test::black_box(m.complex_eigenvalues())) + bh.bench_function("eigenvalues_4x4", move |bh| bh.iter(|| test::black_box(m.complex_eigenvalues()))); } -#[bench] -fn eigenvalues_10x10(bh: &mut Bencher) { +fn eigenvalues_10x10(bh: &mut criterion::Criterion) { let m = crate::reproductible_dmatrix(10, 10); - bh.iter(|| test::black_box(m.complex_eigenvalues())) + bh.bench_function("eigenvalues_10x10", move |bh| bh.iter(|| test::black_box(m.complex_eigenvalues()))); } -#[bench] -fn eigenvalues_100x100(bh: &mut Bencher) { +fn eigenvalues_100x100(bh: &mut criterion::Criterion) { let m = crate::reproductible_dmatrix(100, 100); - bh.iter(|| test::black_box(m.complex_eigenvalues())) + bh.bench_function("eigenvalues_100x100", move |bh| bh.iter(|| test::black_box(m.complex_eigenvalues()))); } -#[bench] -fn eigenvalues_200x200(bh: &mut Bencher) { +fn eigenvalues_200x200(bh: &mut criterion::Criterion) { let m = crate::reproductible_dmatrix(200, 200); - bh.iter(|| test::black_box(m.complex_eigenvalues())) + bh.bench_function("eigenvalues_200x200", move |bh| bh.iter(|| test::black_box(m.complex_eigenvalues()))); } + +criterion_group!(schur, + schur_decompose_4x4, + schur_decompose_10x10, + schur_decompose_100x100, + schur_decompose_200x200, + eigenvalues_4x4, + eigenvalues_10x10, + eigenvalues_100x100, + eigenvalues_200x200 +); \ No newline at end of file diff --git a/benches/linalg/solve.rs b/benches/linalg/solve.rs index 03ec71e5..51c6db59 100644 --- a/benches/linalg/solve.rs +++ b/benches/linalg/solve.rs @@ -1,82 +1,85 @@ use na::{DMatrix, DVector}; -use test::Bencher; -#[bench] -fn solve_l_triangular_100x100(bh: &mut Bencher) { +fn solve_l_triangular_100x100(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(100, 100); let v = DVector::::new_random(100); - bh.iter(|| { + bh.bench_function("solve_l_triangular_100x100", move |bh| bh.iter(|| { let _ = m.solve_lower_triangular(&v); - }) + })); } -#[bench] -fn solve_l_triangular_1000x1000(bh: &mut Bencher) { +fn solve_l_triangular_1000x1000(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(1000, 1000); let v = DVector::::new_random(1000); - bh.iter(|| { + bh.bench_function("solve_l_triangular_1000x1000", move |bh| bh.iter(|| { let _ = m.solve_lower_triangular(&v); - }) + })); } -#[bench] -fn tr_solve_l_triangular_100x100(bh: &mut Bencher) { +fn tr_solve_l_triangular_100x100(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(100, 100); let v = DVector::::new_random(100); - bh.iter(|| { + bh.bench_function("tr_solve_l_triangular_100x100", move |bh| bh.iter(|| { let _ = m.tr_solve_lower_triangular(&v); - }) + })); } -#[bench] -fn tr_solve_l_triangular_1000x1000(bh: &mut Bencher) { +fn tr_solve_l_triangular_1000x1000(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(1000, 1000); let v = DVector::::new_random(1000); - bh.iter(|| { + bh.bench_function("tr_solve_l_triangular_1000x1000", move |bh| bh.iter(|| { let _ = m.tr_solve_lower_triangular(&v); - }) + })); } -#[bench] -fn solve_u_triangular_100x100(bh: &mut Bencher) { +fn solve_u_triangular_100x100(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(100, 100); let v = DVector::::new_random(100); - bh.iter(|| { + bh.bench_function("solve_u_triangular_100x100", move |bh| bh.iter(|| { let _ = m.solve_upper_triangular(&v); - }) + })); } -#[bench] -fn solve_u_triangular_1000x1000(bh: &mut Bencher) { +fn solve_u_triangular_1000x1000(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(1000, 1000); let v = DVector::::new_random(1000); - bh.iter(|| { + bh.bench_function("solve_u_triangular_1000x1000", move |bh| bh.iter(|| { let _ = m.solve_upper_triangular(&v); - }) + })); } -#[bench] -fn tr_solve_u_triangular_100x100(bh: &mut Bencher) { +fn tr_solve_u_triangular_100x100(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(100, 100); let v = DVector::::new_random(100); - bh.iter(|| { + bh.bench_function("tr_solve_u_triangular_100x100", move |bh| bh.iter(|| { let _ = m.tr_solve_upper_triangular(&v); - }) + })); } -#[bench] -fn tr_solve_u_triangular_1000x1000(bh: &mut Bencher) { +fn tr_solve_u_triangular_1000x1000(bh: &mut criterion::Criterion) { let m = DMatrix::::new_random(1000, 1000); let v = DVector::::new_random(1000); - bh.iter(|| { + bh.bench_function("tr_solve_u_triangular_1000x1000", move |bh| bh.iter(|| { let _ = m.tr_solve_upper_triangular(&v); - }) + })); } + + +criterion_group!(solve, + solve_l_triangular_100x100, + solve_l_triangular_1000x1000, + tr_solve_l_triangular_100x100, + tr_solve_l_triangular_1000x1000, + solve_u_triangular_100x100, + solve_u_triangular_1000x1000, + tr_solve_u_triangular_100x100, + tr_solve_u_triangular_1000x1000 +); \ No newline at end of file diff --git a/benches/linalg/svd.rs b/benches/linalg/svd.rs index 956ba4a7..6804147c 100644 --- a/benches/linalg/svd.rs +++ b/benches/linalg/svd.rs @@ -1,98 +1,101 @@ use na::{Matrix4, SVD}; -use test::{self, Bencher}; -#[bench] -fn svd_decompose_4x4(bh: &mut Bencher) { +fn svd_decompose_4x4(bh: &mut criterion::Criterion) { let m = Matrix4::::new_random(); - bh.iter(|| test::black_box(SVD::new(m.clone(), true, true))) + bh.bench_function("svd_decompose_4x4", move |bh| bh.iter(|| test::black_box(SVD::new(m.clone(), true, true)))); } -#[bench] -fn svd_decompose_10x10(bh: &mut Bencher) { +fn svd_decompose_10x10(bh: &mut criterion::Criterion) { let m = crate::reproductible_dmatrix(10, 10); - bh.iter(|| test::black_box(SVD::new(m.clone(), true, true))) + bh.bench_function("svd_decompose_10x10", move |bh| bh.iter(|| test::black_box(SVD::new(m.clone(), true, true)))); } -#[bench] -fn svd_decompose_100x100(bh: &mut Bencher) { +fn svd_decompose_100x100(bh: &mut criterion::Criterion) { let m = crate::reproductible_dmatrix(100, 100); - bh.iter(|| test::black_box(SVD::new(m.clone(), true, true))) + bh.bench_function("svd_decompose_100x100", move |bh| bh.iter(|| test::black_box(SVD::new(m.clone(), true, true)))); } -#[bench] -fn svd_decompose_200x200(bh: &mut Bencher) { +fn svd_decompose_200x200(bh: &mut criterion::Criterion) { let m = crate::reproductible_dmatrix(200, 200); - bh.iter(|| test::black_box(SVD::new(m.clone(), true, true))) + bh.bench_function("svd_decompose_200x200", move |bh| bh.iter(|| test::black_box(SVD::new(m.clone(), true, true)))); } -#[bench] -fn rank_4x4(bh: &mut Bencher) { +fn rank_4x4(bh: &mut criterion::Criterion) { let m = Matrix4::::new_random(); - bh.iter(|| test::black_box(m.rank(1.0e-10))) + bh.bench_function("rank_4x4", move |bh| bh.iter(|| test::black_box(m.rank(1.0e-10)))); } -#[bench] -fn rank_10x10(bh: &mut Bencher) { +fn rank_10x10(bh: &mut criterion::Criterion) { let m = crate::reproductible_dmatrix(10, 10); - bh.iter(|| test::black_box(m.rank(1.0e-10))) + bh.bench_function("rank_10x10", move |bh| bh.iter(|| test::black_box(m.rank(1.0e-10)))); } -#[bench] -fn rank_100x100(bh: &mut Bencher) { +fn rank_100x100(bh: &mut criterion::Criterion) { let m = crate::reproductible_dmatrix(100, 100); - bh.iter(|| test::black_box(m.rank(1.0e-10))) + bh.bench_function("rank_100x100", move |bh| bh.iter(|| test::black_box(m.rank(1.0e-10)))); } -#[bench] -fn rank_200x200(bh: &mut Bencher) { +fn rank_200x200(bh: &mut criterion::Criterion) { let m = crate::reproductible_dmatrix(200, 200); - bh.iter(|| test::black_box(m.rank(1.0e-10))) + bh.bench_function("rank_200x200", move |bh| bh.iter(|| test::black_box(m.rank(1.0e-10)))); } -#[bench] -fn singular_values_4x4(bh: &mut Bencher) { +fn singular_values_4x4(bh: &mut criterion::Criterion) { let m = Matrix4::::new_random(); - bh.iter(|| test::black_box(m.singular_values())) + bh.bench_function("singular_values_4x4", move |bh| bh.iter(|| test::black_box(m.singular_values()))); } -#[bench] -fn singular_values_10x10(bh: &mut Bencher) { +fn singular_values_10x10(bh: &mut criterion::Criterion) { let m = crate::reproductible_dmatrix(10, 10); - bh.iter(|| test::black_box(m.singular_values())) + bh.bench_function("singular_values_10x10", move |bh| bh.iter(|| test::black_box(m.singular_values()))); } -#[bench] -fn singular_values_100x100(bh: &mut Bencher) { +fn singular_values_100x100(bh: &mut criterion::Criterion) { let m = crate::reproductible_dmatrix(100, 100); - bh.iter(|| test::black_box(m.singular_values())) + bh.bench_function("singular_values_100x100", move |bh| bh.iter(|| test::black_box(m.singular_values()))); } -#[bench] -fn singular_values_200x200(bh: &mut Bencher) { +fn singular_values_200x200(bh: &mut criterion::Criterion) { let m = crate::reproductible_dmatrix(200, 200); - bh.iter(|| test::black_box(m.singular_values())) + bh.bench_function("singular_values_200x200", move |bh| bh.iter(|| test::black_box(m.singular_values()))); } -#[bench] -fn pseudo_inverse_4x4(bh: &mut Bencher) { +fn pseudo_inverse_4x4(bh: &mut criterion::Criterion) { let m = Matrix4::::new_random(); - bh.iter(|| test::black_box(m.clone().pseudo_inverse(1.0e-10))) + bh.bench_function("pseudo_inverse_4x4", move |bh| bh.iter(|| test::black_box(m.clone().pseudo_inverse(1.0e-10)))); } -#[bench] -fn pseudo_inverse_10x10(bh: &mut Bencher) { +fn pseudo_inverse_10x10(bh: &mut criterion::Criterion) { let m = crate::reproductible_dmatrix(10, 10); - bh.iter(|| test::black_box(m.clone().pseudo_inverse(1.0e-10))) + bh.bench_function("pseudo_inverse_10x10", move |bh| bh.iter(|| test::black_box(m.clone().pseudo_inverse(1.0e-10)))); } -#[bench] -fn pseudo_inverse_100x100(bh: &mut Bencher) { +fn pseudo_inverse_100x100(bh: &mut criterion::Criterion) { let m = crate::reproductible_dmatrix(100, 100); - bh.iter(|| test::black_box(m.clone().pseudo_inverse(1.0e-10))) + bh.bench_function("pseudo_inverse_100x100", move |bh| bh.iter(|| test::black_box(m.clone().pseudo_inverse(1.0e-10)))); } -#[bench] -fn pseudo_inverse_200x200(bh: &mut Bencher) { +fn pseudo_inverse_200x200(bh: &mut criterion::Criterion) { let m = crate::reproductible_dmatrix(200, 200); - bh.iter(|| test::black_box(m.clone().pseudo_inverse(1.0e-10))) + bh.bench_function("pseudo_inverse_200x200", move |bh| bh.iter(|| test::black_box(m.clone().pseudo_inverse(1.0e-10)))); } + + +criterion_group!(svd, + svd_decompose_4x4, + svd_decompose_10x10, + svd_decompose_100x100, + svd_decompose_200x200, + rank_4x4, + rank_10x10, + rank_100x100, + rank_200x200, + singular_values_4x4, + singular_values_10x10, + singular_values_100x100, + singular_values_200x200, + pseudo_inverse_4x4, + pseudo_inverse_10x10, + pseudo_inverse_100x100, + pseudo_inverse_200x200 +); \ No newline at end of file diff --git a/benches/linalg/symmetric_eigen.rs b/benches/linalg/symmetric_eigen.rs index 7f19eb78..822ea30e 100644 --- a/benches/linalg/symmetric_eigen.rs +++ b/benches/linalg/symmetric_eigen.rs @@ -1,26 +1,28 @@ use na::{Matrix4, SymmetricEigen}; -use test::{self, Bencher}; -#[bench] -fn symmetric_eigen_decompose_4x4(bh: &mut Bencher) { +fn symmetric_eigen_decompose_4x4(bh: &mut criterion::Criterion) { let m = Matrix4::::new_random(); - bh.iter(|| test::black_box(SymmetricEigen::new(m.clone()))) + bh.bench_function("symmetric_eigen_decompose_4x4", move |bh| bh.iter(|| test::black_box(SymmetricEigen::new(m.clone())))); } -#[bench] -fn symmetric_eigen_decompose_10x10(bh: &mut Bencher) { +fn symmetric_eigen_decompose_10x10(bh: &mut criterion::Criterion) { let m = crate::reproductible_dmatrix(10, 10); - bh.iter(|| test::black_box(SymmetricEigen::new(m.clone()))) + bh.bench_function("symmetric_eigen_decompose_10x10", move |bh| bh.iter(|| test::black_box(SymmetricEigen::new(m.clone())))); } -#[bench] -fn symmetric_eigen_decompose_100x100(bh: &mut Bencher) { +fn symmetric_eigen_decompose_100x100(bh: &mut criterion::Criterion) { let m = crate::reproductible_dmatrix(100, 100); - bh.iter(|| test::black_box(SymmetricEigen::new(m.clone()))) + bh.bench_function("symmetric_eigen_decompose_100x100", move |bh| bh.iter(|| test::black_box(SymmetricEigen::new(m.clone())))); } -#[bench] -fn symmetric_eigen_decompose_200x200(bh: &mut Bencher) { +fn symmetric_eigen_decompose_200x200(bh: &mut criterion::Criterion) { let m = crate::reproductible_dmatrix(200, 200); - bh.iter(|| test::black_box(SymmetricEigen::new(m.clone()))) + bh.bench_function("symmetric_eigen_decompose_200x200", move |bh| bh.iter(|| test::black_box(SymmetricEigen::new(m.clone())))); } + +criterion_group!(symmetric_eigen, + symmetric_eigen_decompose_4x4, + symmetric_eigen_decompose_10x10, + symmetric_eigen_decompose_100x100, + symmetric_eigen_decompose_200x200 +); From 5b28c39fa7fa22f91d4be479a963a4e0560eb8e8 Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Mon, 25 Mar 2019 11:19:36 +0100 Subject: [PATCH 17/28] Rename Complex to ComplexField. --- benches/geometry/mod.rs | 2 +- examples/identity.rs | 2 +- src/base/blas.rs | 20 ++++++++++---------- src/base/matrix.rs | 14 +++++++------- src/base/matrix_alga.rs | 10 +++++----- src/base/norm.rs | 14 +++++++------- src/base/ops.rs | 10 +++++----- src/base/properties.rs | 4 ++-- src/base/unit.rs | 4 ++-- src/debug/random_orthogonal.rs | 6 +++--- src/debug/random_sdp.rs | 6 +++--- src/geometry/quaternion_alga.rs | 2 +- src/geometry/reflection.rs | 4 ++-- src/lib.rs | 2 +- src/linalg/bidiagonal.rs | 12 ++++++------ src/linalg/cholesky.rs | 10 +++++----- src/linalg/determinant.rs | 4 ++-- src/linalg/eigen.rs | 8 ++++---- src/linalg/full_piv_lu.rs | 12 ++++++------ src/linalg/givens.rs | 6 +++--- src/linalg/hessenberg.rs | 10 +++++----- src/linalg/householder.rs | 10 +++++----- src/linalg/inverse.rs | 8 ++++---- src/linalg/lu.rs | 14 +++++++------- src/linalg/qr.rs | 12 ++++++------ src/linalg/schur.rs | 16 ++++++++-------- src/linalg/solve.rs | 4 ++-- src/linalg/svd.rs | 10 +++++----- src/linalg/symmetric_eigen.rs | 12 ++++++------ src/linalg/symmetric_tridiagonal.rs | 10 +++++----- tests/core/matrix.rs | 2 +- tests/linalg/solve.rs | 4 ++-- tests/linalg/svd.rs | 16 ++++++++-------- 33 files changed, 140 insertions(+), 140 deletions(-) diff --git a/benches/geometry/mod.rs b/benches/geometry/mod.rs index d0d0e948..cb23cbf9 100644 --- a/benches/geometry/mod.rs +++ b/benches/geometry/mod.rs @@ -1,3 +1,3 @@ -pub use quaternion::quaternion; +pub use self::quaternion::quaternion; mod quaternion; diff --git a/examples/identity.rs b/examples/identity.rs index 06d69f70..c20c5616 100644 --- a/examples/identity.rs +++ b/examples/identity.rs @@ -36,4 +36,4 @@ fn main() { // They both return the same result. assert!(result1 == Vector3::new(100001.0, 200002.0, 300003.0)); assert!(result2 == Vector3::new(100001.0, 200002.0, 300003.0)); -} +} \ No newline at end of file diff --git a/src/base/blas.rs b/src/base/blas.rs index cdfe4f9f..55a20216 100644 --- a/src/base/blas.rs +++ b/src/base/blas.rs @@ -1,4 +1,4 @@ -use alga::general::{ClosedAdd, ClosedMul, Complex}; +use alga::general::{ClosedAdd, ClosedMul, ComplexField}; #[cfg(feature = "std")] use matrixmultiply; use num::{One, Signed, Zero}; @@ -15,7 +15,7 @@ use crate::base::{DefaultAllocator, Matrix, Scalar, SquareMatrix, Vector, DVecto // FIXME: find a way to avoid code duplication just for complex number support. -impl> Vector { +impl> Vector { /// Computes the index of the vector component with the largest complex or real absolute value. /// /// # Examples: @@ -193,7 +193,7 @@ impl> Vector { } // FIXME: find a way to avoid code duplication just for complex number support. -impl> Matrix { +impl> Matrix { /// Computes the index of the matrix component with the largest absolute value. /// /// # Examples: @@ -416,11 +416,11 @@ where N: Scalar + Zero + ClosedAdd + ClosedMul #[inline] pub fn dotc(&self, rhs: &Matrix) -> N where - N: Complex, + N: ComplexField, SB: Storage, ShapeConstraint: DimEq + DimEq, { - self.dotx(rhs, Complex::conjugate) + self.dotx(rhs, ComplexField::conjugate) } /// The dot product between the transpose of `self` and `rhs`. @@ -726,7 +726,7 @@ where x: &Vector, beta: N, ) where - N: Complex, + N: ComplexField, SB: Storage, SC: Storage, ShapeConstraint: DimEq + AreMultipliable, @@ -881,12 +881,12 @@ where N: Scalar + Zero + ClosedAdd + ClosedMul y: &Vector, beta: N, ) where - N: Complex, + N: ComplexField, SB: Storage, SC: Storage, ShapeConstraint: DimEq + DimEq, { - self.gerx(alpha, x, y, beta, Complex::conjugate) + self.gerx(alpha, x, y, beta, ComplexField::conjugate) } /// Computes `self = alpha * a * b + beta * self`, where `a, b, self` are matrices. @@ -1216,12 +1216,12 @@ where N: Scalar + Zero + ClosedAdd + ClosedMul y: &Vector, beta: N, ) where - N: Complex, + N: ComplexField, SB: Storage, SC: Storage, ShapeConstraint: DimEq + DimEq, { - self.xxgerx(alpha, x, y, beta, Complex::conjugate) + self.xxgerx(alpha, x, y, beta, ComplexField::conjugate) } } diff --git a/src/base/matrix.rs b/src/base/matrix.rs index e5060013..ad188a26 100644 --- a/src/base/matrix.rs +++ b/src/base/matrix.rs @@ -16,7 +16,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; #[cfg(feature = "abomonation-serialize")] use abomonation::Abomonation; -use alga::general::{ClosedAdd, ClosedMul, ClosedSub, Real, Ring, Complex, Field}; +use alga::general::{ClosedAdd, ClosedMul, ClosedSub, Real, Ring, ComplexField, Field}; use crate::base::allocator::{Allocator, SameShapeAllocator, SameShapeC, SameShapeR}; use crate::base::constraint::{DimEq, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint}; @@ -913,7 +913,7 @@ impl> Matrix { } } -impl> Matrix { +impl> Matrix { /// Takes the adjoint (aka. conjugate-transpose) of `self` and store the result into `out`. #[inline] pub fn adjoint_to(&self, out: &mut Matrix) @@ -996,7 +996,7 @@ impl> Matrix { } } -impl> Matrix { +impl> Matrix { /// The conjugate of the complex matrix `self` computed in-place. #[inline] pub fn conjugate_mut(&mut self) { @@ -1016,7 +1016,7 @@ impl> Matrix { } } -impl> Matrix { +impl> Matrix { /// Sets `self` to its adjoint. #[deprecated(note = "Renamed to `self.adjoint_mut()`.")] pub fn conjugate_transform_mut(&mut self) { @@ -1103,7 +1103,7 @@ impl> SquareMatrix { } } -impl> SquareMatrix { +impl> SquareMatrix { /// The symmetric part of `self`, i.e., `0.5 * (self + self.transpose())`. #[inline] pub fn symmetric_part(&self) -> MatrixMN @@ -1541,7 +1541,7 @@ where DefaultAllocator: Allocator } } -impl> Matrix { +impl> Matrix { /// The smallest angle between two vectors. #[inline] pub fn angle(&self, other: &Matrix) -> N::Real @@ -1592,7 +1592,7 @@ impl> Unit> { +impl> Unit> { /// Computes the spherical linear interpolation between two unit vectors. pub fn slerp>( &self, diff --git a/src/base/matrix_alga.rs b/src/base/matrix_alga.rs index 87ab584c..790d60d3 100644 --- a/src/base/matrix_alga.rs +++ b/src/base/matrix_alga.rs @@ -7,7 +7,7 @@ use alga::general::{ AbstractGroup, AbstractGroupAbelian, AbstractLoop, AbstractMagma, AbstractModule, AbstractMonoid, AbstractQuasigroup, AbstractSemigroup, Additive, ClosedAdd, ClosedMul, ClosedNeg, Field, Identity, TwoSidedInverse, JoinSemilattice, Lattice, MeetSemilattice, Module, - Multiplicative, RingCommutative, Complex + Multiplicative, RingCommutative, ComplexField }; use alga::linear::{ FiniteDimInnerSpace, FiniteDimVectorSpace, InnerSpace, NormedSpace, VectorSpace, @@ -145,11 +145,11 @@ where } } -impl NormedSpace for MatrixMN +impl NormedSpace for MatrixMN where DefaultAllocator: Allocator { type Real = N::Real; - type Complex = N; + type ComplexField = N; #[inline] fn norm_squared(&self) -> N::Real { @@ -182,7 +182,7 @@ where DefaultAllocator: Allocator } } -impl InnerSpace for MatrixMN +impl InnerSpace for MatrixMN where DefaultAllocator: Allocator { #[inline] @@ -200,7 +200,7 @@ where DefaultAllocator: Allocator // In particular: // − use `x()` instead of `::canonical_basis_element` // − use `::new(x, y, z)` instead of `::from_slice` -impl FiniteDimInnerSpace for MatrixMN +impl FiniteDimInnerSpace for MatrixMN where DefaultAllocator: Allocator { #[inline] diff --git a/src/base/norm.rs b/src/base/norm.rs index 91958cec..06bca851 100644 --- a/src/base/norm.rs +++ b/src/base/norm.rs @@ -1,7 +1,7 @@ use num::Zero; use crate::allocator::Allocator; -use crate::{Real, Complex}; +use crate::{Real, ComplexField}; use crate::storage::{Storage, StorageMut}; use crate::base::{DefaultAllocator, Matrix, Dim, MatrixMN}; use crate::constraint::{SameNumberOfRows, SameNumberOfColumns, ShapeConstraint}; @@ -11,7 +11,7 @@ use crate::constraint::{SameNumberOfRows, SameNumberOfColumns, ShapeConstraint}; /// A trait for abstract matrix norms. /// /// This may be moved to the alga crate in the future. -pub trait Norm { +pub trait Norm { /// Apply this norm to the given matrix. fn norm(&self, m: &Matrix) -> N::Real where R: Dim, C: Dim, S: Storage; @@ -29,7 +29,7 @@ pub struct LpNorm(pub i32); /// L-infinite norm aka. Chebytchev norm aka. uniform norm aka. suppremum norm. pub struct UniformNorm; -impl Norm for EuclideanNorm { +impl Norm for EuclideanNorm { #[inline] fn norm(&self, m: &Matrix) -> N::Real where R: Dim, C: Dim, S: Storage { @@ -48,7 +48,7 @@ impl Norm for EuclideanNorm { } } -impl Norm for LpNorm { +impl Norm for LpNorm { #[inline] fn norm(&self, m: &Matrix) -> N::Real where R: Dim, C: Dim, S: Storage { @@ -69,7 +69,7 @@ impl Norm for LpNorm { } } -impl Norm for UniformNorm { +impl Norm for UniformNorm { #[inline] fn norm(&self, m: &Matrix) -> N::Real where R: Dim, C: Dim, S: Storage { @@ -95,7 +95,7 @@ impl Norm for UniformNorm { } -impl> Matrix { +impl> Matrix { /// The squared L2 norm of this vector. #[inline] pub fn norm_squared(&self) -> N::Real { @@ -213,7 +213,7 @@ impl> Matrix { } -impl> Matrix { +impl> Matrix { /// Normalizes this matrix in-place and returns its norm. #[inline] pub fn normalize_mut(&mut self) -> N::Real { diff --git a/src/base/ops.rs b/src/base/ops.rs index bfc71040..8a6fe5a1 100644 --- a/src/base/ops.rs +++ b/src/base/ops.rs @@ -5,7 +5,7 @@ use std::ops::{ Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign, }; -use alga::general::{Complex, ClosedAdd, ClosedDiv, ClosedMul, ClosedNeg, ClosedSub}; +use alga::general::{ComplexField, ClosedAdd, ClosedDiv, ClosedMul, ClosedNeg, ClosedSub}; use crate::base::allocator::{Allocator, SameShapeAllocator, SameShapeC, SameShapeR}; use crate::base::constraint::{ @@ -633,7 +633,7 @@ where #[inline] pub fn ad_mul(&self, rhs: &Matrix) -> MatrixMN where - N: Complex, + N: ComplexField, SB: Storage, DefaultAllocator: Allocator, ShapeConstraint: SameNumberOfRows, @@ -700,7 +700,7 @@ where rhs: &Matrix, out: &mut Matrix, ) where - N: Complex, + N: ComplexField, SB: Storage, SC: StorageMut, ShapeConstraint: SameNumberOfRows + DimEq + DimEq, @@ -833,7 +833,7 @@ impl> Matrix { /// Returns the the 1-norm of the complex component with the largest 1-norm. #[inline] pub fn camax(&self) -> N::Real - where N: Complex { + where N: ComplexField { self.xcmp(|e| e.norm1(), |a, b| a > b) } @@ -854,7 +854,7 @@ impl> Matrix { /// Returns the the 1-norm of the complex component with the smallest 1-norm. #[inline] pub fn camin(&self) -> N::Real - where N: Complex { + where N: ComplexField { self.xcmp(|e| e.norm1(), |a, b| a < b) } diff --git a/src/base/properties.rs b/src/base/properties.rs index 73019209..acb7dfb4 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, Real, Complex}; +use alga::general::{ClosedAdd, ClosedMul, Real, ComplexField}; use crate::base::allocator::Allocator; use crate::base::dimension::{Dim, DimMin}; @@ -84,7 +84,7 @@ impl> Matrix { } } -impl> Matrix { +impl> Matrix { /// Checks that `Mᵀ × M = Id`. /// /// In this definition `Id` is approximately equal to the identity matrix with a relative error diff --git a/src/base/unit.rs b/src/base/unit.rs index 90b343e1..60aa1ae2 100644 --- a/src/base/unit.rs +++ b/src/base/unit.rs @@ -10,7 +10,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; #[cfg(feature = "abomonation-serialize")] use abomonation::Abomonation; -use alga::general::{SubsetOf, Complex}; +use alga::general::{SubsetOf, ComplexField}; use alga::linear::NormedSpace; /// A wrapper that ensures the underlying algebraic entity has a unit norm. @@ -106,7 +106,7 @@ impl Unit { let sq_norm = self.value.norm_squared(); let _3: T::Real = crate::convert(3.0); let _0_5: T::Real = crate::convert(0.5); - self.value *= T::Complex::from_real(_0_5 * (_3 - sq_norm)); + self.value *= T::ComplexField::from_real(_0_5 * (_3 - sq_norm)); } } diff --git a/src/debug/random_orthogonal.rs b/src/debug/random_orthogonal.rs index b14c7da4..421b041a 100644 --- a/src/debug/random_orthogonal.rs +++ b/src/debug/random_orthogonal.rs @@ -3,7 +3,7 @@ use crate::base::storage::Owned; #[cfg(feature = "arbitrary")] use quickcheck::{Arbitrary, Gen}; -use alga::general::Complex; +use alga::general::ComplexField; use crate::base::Scalar; use crate::base::allocator::Allocator; use crate::base::dimension::{Dim, Dynamic, U2}; @@ -18,7 +18,7 @@ where DefaultAllocator: Allocator m: MatrixN, } -impl RandomOrthogonal +impl RandomOrthogonal where DefaultAllocator: Allocator { /// Retrieve the generated matrix. @@ -41,7 +41,7 @@ where DefaultAllocator: Allocator } #[cfg(feature = "arbitrary")] -impl Arbitrary for RandomOrthogonal +impl Arbitrary for RandomOrthogonal where DefaultAllocator: Allocator, Owned: Clone + Send, diff --git a/src/debug/random_sdp.rs b/src/debug/random_sdp.rs index ca3f122f..47e3ca60 100644 --- a/src/debug/random_sdp.rs +++ b/src/debug/random_sdp.rs @@ -3,7 +3,7 @@ use crate::base::storage::Owned; #[cfg(feature = "arbitrary")] use quickcheck::{Arbitrary, Gen}; -use alga::general::Complex; +use alga::general::ComplexField; use crate::base::Scalar; use crate::base::allocator::Allocator; use crate::base::dimension::{Dim, Dynamic}; @@ -19,7 +19,7 @@ where DefaultAllocator: Allocator m: MatrixN, } -impl RandomSDP +impl RandomSDP where DefaultAllocator: Allocator { /// Retrieve the generated matrix. @@ -44,7 +44,7 @@ where DefaultAllocator: Allocator } #[cfg(feature = "arbitrary")] -impl Arbitrary for RandomSDP +impl Arbitrary for RandomSDP where DefaultAllocator: Allocator, Owned: Clone + Send, diff --git a/src/geometry/quaternion_alga.rs b/src/geometry/quaternion_alga.rs index b1c9a1ba..a73beff7 100644 --- a/src/geometry/quaternion_alga.rs +++ b/src/geometry/quaternion_alga.rs @@ -119,7 +119,7 @@ impl FiniteDimVectorSpace for Quaternion { impl NormedSpace for Quaternion { type Real = N; - type Complex = N; + type ComplexField = N; #[inline] fn norm_squared(&self) -> N { diff --git a/src/geometry/reflection.rs b/src/geometry/reflection.rs index a13e235a..b36924d2 100644 --- a/src/geometry/reflection.rs +++ b/src/geometry/reflection.rs @@ -1,4 +1,4 @@ -use alga::general::Complex; +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}; @@ -13,7 +13,7 @@ pub struct Reflection> { bias: N, } -impl> Reflection { +impl> Reflection { /// Creates a new reflection wrt the plane orthogonal to the given axis and bias. /// /// The bias is the position of the plane on the axis. In particular, a bias equal to zero diff --git a/src/lib.rs b/src/lib.rs index feae7b22..f66ae4f0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -160,7 +160,7 @@ use alga::linear::SquareMatrix as AlgaSquareMatrix; use alga::linear::{EuclideanSpace, FiniteDimVectorSpace, InnerSpace, NormedSpace}; use num::Signed; -pub use alga::general::{Id, Real, Complex}; +pub use alga::general::{Id, Real, ComplexField}; /* * diff --git a/src/linalg/bidiagonal.rs b/src/linalg/bidiagonal.rs index 09031e28..e61c98ec 100644 --- a/src/linalg/bidiagonal.rs +++ b/src/linalg/bidiagonal.rs @@ -1,7 +1,7 @@ #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Serialize}; -use alga::general::Complex; +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}; @@ -37,7 +37,7 @@ use crate::linalg::householder; )) )] #[derive(Clone, Debug)] -pub struct Bidiagonal, C: Dim> +pub struct Bidiagonal, C: Dim> where DimMinimum: DimSub, DefaultAllocator: Allocator @@ -54,7 +54,7 @@ where upper_diagonal: bool, } -impl, C: Dim> Copy for Bidiagonal +impl, C: Dim> Copy for Bidiagonal where DimMinimum: DimSub, DefaultAllocator: Allocator @@ -65,7 +65,7 @@ where VectorN, U1>>: Copy, {} -impl, C: Dim> Bidiagonal +impl, C: Dim> Bidiagonal where DimMinimum: DimSub, DefaultAllocator: Allocator @@ -282,7 +282,7 @@ where } } -// impl + DimSub> Bidiagonal +// impl + DimSub> Bidiagonal // where DefaultAllocator: Allocator + // Allocator { // /// Solves the linear system `self * x = b`, where `x` is the unknown to be determined. @@ -355,7 +355,7 @@ where // // } // } -impl, C: Dim, S: Storage> Matrix +impl, C: Dim, S: Storage> Matrix where DimMinimum: DimSub, DefaultAllocator: Allocator diff --git a/src/linalg/cholesky.rs b/src/linalg/cholesky.rs index 985abddc..0b6e6db5 100644 --- a/src/linalg/cholesky.rs +++ b/src/linalg/cholesky.rs @@ -1,7 +1,7 @@ #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Serialize}; -use alga::general::Complex; +use alga::general::ComplexField; use crate::allocator::Allocator; use crate::base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, SquareMatrix}; @@ -26,19 +26,19 @@ use crate::storage::{Storage, StorageMut}; )) )] #[derive(Clone, Debug)] -pub struct Cholesky +pub struct Cholesky where DefaultAllocator: Allocator { chol: MatrixN, } -impl Copy for Cholesky +impl Copy for Cholesky where DefaultAllocator: Allocator, MatrixN: Copy, {} -impl> Cholesky +impl> Cholesky where DefaultAllocator: Allocator { /// Attempts to compute the Cholesky decomposition of `matrix`. @@ -148,7 +148,7 @@ where DefaultAllocator: Allocator } } -impl, S: Storage> SquareMatrix +impl, S: Storage> SquareMatrix 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 4d265164..54ec9e5a 100644 --- a/src/linalg/determinant.rs +++ b/src/linalg/determinant.rs @@ -1,4 +1,4 @@ -use alga::general::Complex; +use alga::general::ComplexField; use crate::base::allocator::Allocator; use crate::base::dimension::DimMin; @@ -7,7 +7,7 @@ use crate::base::{DefaultAllocator, SquareMatrix}; use crate::linalg::LU; -impl, S: Storage> SquareMatrix { +impl, S: Storage> SquareMatrix { /// Computes the matrix determinant. /// /// If the matrix has a dimension larger than 3, an LU decomposition is used. diff --git a/src/linalg/eigen.rs b/src/linalg/eigen.rs index 970e990d..8d1d26ca 100644 --- a/src/linalg/eigen.rs +++ b/src/linalg/eigen.rs @@ -1,7 +1,7 @@ #[cfg(feature = "serde-serialize")] use serde::{Serialize, Deserialize}; -use alga::general::Complex; +use alga::general::ComplexField; use num_complex::Complex; use std::cmp; use std::fmt::Display; @@ -40,7 +40,7 @@ use crate::linalg::Schur; ) )] #[derive(Clone, Debug)] -pub struct Eigen +pub struct Eigen where DefaultAllocator: Allocator + Allocator, { @@ -48,7 +48,7 @@ where pub eigenvalues: VectorN, } -impl Copy for Eigen +impl Copy for Eigen where DefaultAllocator: Allocator + Allocator, MatrixN: Copy, @@ -56,7 +56,7 @@ where { } -impl Eigen +impl Eigen where D: DimSub, // For Hessenberg. ShapeConstraint: DimEq>, // For Hessenberg. diff --git a/src/linalg/full_piv_lu.rs b/src/linalg/full_piv_lu.rs index 61bc227c..04f61faf 100644 --- a/src/linalg/full_piv_lu.rs +++ b/src/linalg/full_piv_lu.rs @@ -1,7 +1,7 @@ #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Serialize}; -use alga::general::Complex; +use alga::general::ComplexField; use crate::allocator::Allocator; use crate::base::{DefaultAllocator, Matrix, MatrixMN, MatrixN}; use crate::constraint::{SameNumberOfRows, ShapeConstraint}; @@ -32,7 +32,7 @@ use crate::linalg::PermutationSequence; )) )] #[derive(Clone, Debug)] -pub struct FullPivLU, C: Dim> +pub struct FullPivLU, C: Dim> where DefaultAllocator: Allocator + Allocator<(usize, usize), DimMinimum> { lu: MatrixMN, @@ -40,14 +40,14 @@ where DefaultAllocator: Allocator + Allocator<(usize, usize), DimMinimu q: PermutationSequence>, } -impl, C: Dim> Copy for FullPivLU +impl, C: Dim> Copy for FullPivLU where DefaultAllocator: Allocator + Allocator<(usize, usize), DimMinimum>, MatrixMN: Copy, PermutationSequence>: Copy, {} -impl, C: Dim> FullPivLU +impl, C: Dim> FullPivLU where DefaultAllocator: Allocator + Allocator<(usize, usize), DimMinimum> { /// Computes the LU decomposition with full pivoting of `matrix`. @@ -156,7 +156,7 @@ where DefaultAllocator: Allocator + Allocator<(usize, usize), DimMinimu } } -impl> FullPivLU +impl> FullPivLU where DefaultAllocator: Allocator + Allocator<(usize, usize), D> { /// Solves the linear system `self * x = b`, where `x` is the unknown to be determined. @@ -261,7 +261,7 @@ where DefaultAllocator: Allocator + Allocator<(usize, usize), D> } } -impl, C: Dim, S: Storage> Matrix +impl, C: Dim, S: Storage> Matrix where DefaultAllocator: Allocator + Allocator<(usize, usize), DimMinimum> { /// Computes the LU decomposition with full pivoting of `matrix`. diff --git a/src/linalg/givens.rs b/src/linalg/givens.rs index 0927dd26..3dd56ee3 100644 --- a/src/linalg/givens.rs +++ b/src/linalg/givens.rs @@ -1,6 +1,6 @@ //! Construction of givens rotations. -use alga::general::Complex; +use alga::general::ComplexField; use num::{Zero, One}; use crate::base::dimension::{Dim, U2}; @@ -11,13 +11,13 @@ use crate::base::{Vector, Matrix}; /// A Givens rotation. #[derive(Debug, Clone, Copy)] -pub struct GivensRotation { +pub struct GivensRotation { c: N::Real, s: N } // Matrix = UnitComplex * Matrix -impl GivensRotation { +impl GivensRotation { /// The Givents rotation that does nothing. pub fn identity() -> Self { Self { diff --git a/src/linalg/hessenberg.rs b/src/linalg/hessenberg.rs index 56e2ace4..c87c06a2 100644 --- a/src/linalg/hessenberg.rs +++ b/src/linalg/hessenberg.rs @@ -1,7 +1,7 @@ #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Serialize}; -use alga::general::Complex; +use alga::general::ComplexField; use crate::allocator::Allocator; use crate::base::{DefaultAllocator, MatrixMN, MatrixN, SquareMatrix, VectorN}; use crate::dimension::{DimDiff, DimSub, U1}; @@ -30,21 +30,21 @@ use crate::linalg::householder; )) )] #[derive(Clone, Debug)] -pub struct Hessenberg> +pub struct Hessenberg> where DefaultAllocator: Allocator + Allocator> { hess: MatrixN, subdiag: VectorN>, } -impl> Copy for Hessenberg +impl> Copy for Hessenberg where DefaultAllocator: Allocator + Allocator>, MatrixN: Copy, VectorN>: Copy, {} -impl> Hessenberg +impl> Hessenberg where DefaultAllocator: Allocator + Allocator + Allocator> { /// Computes the Hessenberg decomposition using householder reflections. @@ -133,7 +133,7 @@ where DefaultAllocator: Allocator + Allocator + Allocator, S: Storage> SquareMatrix +impl, S: Storage> SquareMatrix where DefaultAllocator: Allocator + Allocator + Allocator> { /// Computes the Hessenberg decomposition of this matrix using householder reflections. diff --git a/src/linalg/householder.rs b/src/linalg/householder.rs index 3bd8f801..11fa32eb 100644 --- a/src/linalg/householder.rs +++ b/src/linalg/householder.rs @@ -1,7 +1,7 @@ //! Construction of householder elementary reflections. use num::Zero; -use alga::general::Complex; +use alga::general::ComplexField; use crate::allocator::Allocator; use crate::base::{DefaultAllocator, MatrixMN, MatrixN, Unit, Vector, VectorN}; use crate::dimension::Dim; @@ -16,7 +16,7 @@ use crate::geometry::Reflection; /// `column` after reflection and `false` if no reflection was necessary. #[doc(hidden)] #[inline(always)] -pub fn reflection_axis_mut>( +pub fn reflection_axis_mut>( column: &mut Vector, ) -> (N, bool) { let reflection_sq_norm = column.norm_squared(); @@ -44,7 +44,7 @@ pub fn reflection_axis_mut>( /// Uses an householder reflection to zero out the `icol`-th column, starting with the `shift + 1`-th /// subdiagonal element. #[doc(hidden)] -pub fn clear_column_unchecked( +pub fn clear_column_unchecked( matrix: &mut MatrixMN, diag_elt: &mut N, icol: usize, @@ -72,7 +72,7 @@ pub fn clear_column_unchecked( /// Uses an householder reflection to zero out the `irow`-th row, ending before the `shift + 1`-th /// superdiagonal element. #[doc(hidden)] -pub fn clear_row_unchecked( +pub fn clear_row_unchecked( matrix: &mut MatrixMN, diag_elt: &mut N, axis_packed: &mut VectorN, @@ -108,7 +108,7 @@ pub fn clear_row_unchecked( /// the lower-diagonal element of the given matrix. /// matrices. #[doc(hidden)] -pub fn assemble_q(m: &MatrixN, signs: &[N]) -> MatrixN +pub fn assemble_q(m: &MatrixN, signs: &[N]) -> MatrixN where DefaultAllocator: Allocator { assert!(m.is_square()); let dim = m.data.shape().0; diff --git a/src/linalg/inverse.rs b/src/linalg/inverse.rs index 3d6a0681..2d3b18ad 100644 --- a/src/linalg/inverse.rs +++ b/src/linalg/inverse.rs @@ -1,4 +1,4 @@ -use alga::general::Complex; +use alga::general::ComplexField; use crate::base::allocator::Allocator; use crate::base::dimension::Dim; @@ -7,7 +7,7 @@ use crate::base::{DefaultAllocator, MatrixN, SquareMatrix}; use crate::linalg::lu; -impl> SquareMatrix { +impl> SquareMatrix { /// Attempts to invert this matrix. #[inline] pub fn try_inverse(self) -> Option> @@ -21,7 +21,7 @@ impl> SquareMatrix { } } -impl> SquareMatrix { +impl> SquareMatrix { /// Attempts to invert this matrix in-place. Returns `false` and leaves `self` untouched if /// inversion fails. #[inline] @@ -115,7 +115,7 @@ impl> SquareMatrix { } // NOTE: this is an extremely efficient, loop-unrolled matrix inverse from MESA (MIT licensed). -fn do_inverse4>( +fn do_inverse4>( m: &MatrixN, out: &mut SquareMatrix, ) -> bool diff --git a/src/linalg/lu.rs b/src/linalg/lu.rs index fffe7148..2c3beee3 100644 --- a/src/linalg/lu.rs +++ b/src/linalg/lu.rs @@ -1,7 +1,7 @@ #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Serialize}; -use alga::general::{Field, Complex}; +use alga::general::{Field, ComplexField}; use crate::allocator::{Allocator, Reallocator}; use crate::base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, Scalar}; use crate::constraint::{SameNumberOfRows, ShapeConstraint}; @@ -32,14 +32,14 @@ use crate::linalg::PermutationSequence; )) )] #[derive(Clone, Debug)] -pub struct LU, C: Dim> +pub struct LU, C: Dim> where DefaultAllocator: Allocator + Allocator<(usize, usize), DimMinimum> { lu: MatrixMN, p: PermutationSequence>, } -impl, C: Dim> Copy for LU +impl, C: Dim> Copy for LU where DefaultAllocator: Allocator + Allocator<(usize, usize), DimMinimum>, MatrixMN: Copy, @@ -49,7 +49,7 @@ where /// Performs a LU decomposition to overwrite `out` with the inverse of `matrix`. /// /// If `matrix` is not invertible, `false` is returned and `out` may contain invalid data. -pub fn try_invert_to( +pub fn try_invert_to( mut matrix: MatrixN, out: &mut Matrix, ) -> bool @@ -86,7 +86,7 @@ where matrix.solve_upper_triangular_mut(out) } -impl, C: Dim> LU +impl, C: Dim> LU where DefaultAllocator: Allocator + Allocator<(usize, usize), DimMinimum> { /// Computes the LU decomposition with partial (row) pivoting of `matrix`. @@ -197,7 +197,7 @@ where DefaultAllocator: Allocator + Allocator<(usize, usize), DimMinimu } } -impl> LU +impl> LU where DefaultAllocator: Allocator + Allocator<(usize, usize), D> { /// Solves the linear system `self * x = b`, where `x` is the unknown to be determined. @@ -368,7 +368,7 @@ pub fn gauss_step_swap( } } -impl, C: Dim, S: Storage> Matrix +impl, C: Dim, S: Storage> Matrix where DefaultAllocator: Allocator + Allocator<(usize, usize), DimMinimum> { /// Computes the LU decomposition with partial (row) pivoting of `matrix`. diff --git a/src/linalg/qr.rs b/src/linalg/qr.rs index 7c02d140..683c11b8 100644 --- a/src/linalg/qr.rs +++ b/src/linalg/qr.rs @@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize}; use num::Zero; -use alga::general::Complex; +use alga::general::ComplexField; use crate::allocator::{Allocator, Reallocator}; use crate::base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, Unit, VectorN}; use crate::constraint::{SameNumberOfRows, ShapeConstraint}; @@ -33,21 +33,21 @@ use crate::linalg::householder; )) )] #[derive(Clone, Debug)] -pub struct QR, C: Dim> +pub struct QR, C: Dim> where DefaultAllocator: Allocator + Allocator> { qr: MatrixMN, diag: VectorN>, } -impl, C: Dim> Copy for QR +impl, C: Dim> Copy for QR where DefaultAllocator: Allocator + Allocator>, MatrixMN: Copy, VectorN>: Copy, {} -impl, C: Dim> QR +impl, C: Dim> QR where DefaultAllocator: Allocator + Allocator + Allocator> { /// Computes the QR decomposition using householder reflections. @@ -159,7 +159,7 @@ where DefaultAllocator: Allocator + Allocator + Allocator> QR +impl> QR where DefaultAllocator: Allocator + Allocator { /// Solves the linear system `self * x = b`, where `x` is the unknown to be determined. @@ -291,7 +291,7 @@ where DefaultAllocator: Allocator + Allocator // } } -impl, C: Dim, S: Storage> Matrix +impl, C: Dim, S: Storage> Matrix where DefaultAllocator: Allocator + Allocator + Allocator> { /// Computes the QR decomposition of this matrix. diff --git a/src/linalg/schur.rs b/src/linalg/schur.rs index ade4b2dc..9407cf7f 100644 --- a/src/linalg/schur.rs +++ b/src/linalg/schur.rs @@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize}; use approx::AbsDiffEq; -use alga::general::{Complex, Real}; +use alga::general::{ComplexField, Real}; use num_complex::Complex as NumComplex; use std::cmp; @@ -35,20 +35,20 @@ use crate::linalg::givens::GivensRotation; )) )] #[derive(Clone, Debug)] -pub struct Schur +pub struct Schur where DefaultAllocator: Allocator { q: MatrixN, t: MatrixN, } -impl Copy for Schur +impl Copy for Schur where DefaultAllocator: Allocator, MatrixN: Copy, {} -impl Schur +impl Schur where D: DimSub, // For Hessenberg. DefaultAllocator: Allocator> @@ -398,7 +398,7 @@ where } } -fn decompose_2x2( +fn decompose_2x2( mut m: MatrixN, compute_q: bool, ) -> Option<(Option>, MatrixN)> @@ -435,7 +435,7 @@ where Some((q, m)) } -fn compute_2x2_eigvals>( +fn compute_2x2_eigvals>( m: &SquareMatrix, ) -> Option<(N, N)> { // Solve the 2x2 eigenvalue subproblem. @@ -461,7 +461,7 @@ fn compute_2x2_eigvals>( /// /// Returns `None` if the matrix has complex eigenvalues, or is upper-triangular. In both case, /// the basis is the identity. -fn compute_2x2_basis>( +fn compute_2x2_basis>( m: &SquareMatrix, ) -> Option> { let h10 = m[(1, 0)]; @@ -487,7 +487,7 @@ fn compute_2x2_basis>( } } -impl> SquareMatrix +impl> SquareMatrix where D: DimSub, // For Hessenberg. DefaultAllocator: Allocator> diff --git a/src/linalg/solve.rs b/src/linalg/solve.rs index 0c2bb684..f10b1d00 100644 --- a/src/linalg/solve.rs +++ b/src/linalg/solve.rs @@ -1,4 +1,4 @@ -use alga::general::Complex; +use alga::general::ComplexField; use crate::base::allocator::Allocator; use crate::base::constraint::{SameNumberOfRows, ShapeConstraint}; @@ -6,7 +6,7 @@ use crate::base::dimension::{Dim, U1}; use crate::base::storage::{Storage, StorageMut}; use crate::base::{DefaultAllocator, Matrix, MatrixMN, SquareMatrix, Vector, DVectorSlice}; -impl> SquareMatrix { +impl> SquareMatrix { /// Computes the solution of the linear system `self . x = b` where `x` is the unknown and only /// the lower-triangular part of `self` (including the diagonal) is considered not-zero. #[inline] diff --git a/src/linalg/svd.rs b/src/linalg/svd.rs index 779bcff0..714f398f 100644 --- a/src/linalg/svd.rs +++ b/src/linalg/svd.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; use num::{Zero, One}; use approx::AbsDiffEq; -use alga::general::{Real, Complex}; +use alga::general::{Real, ComplexField}; use crate::allocator::Allocator; use crate::base::{DefaultAllocator, Matrix, Matrix2x3, MatrixMN, Vector2, VectorN}; use crate::constraint::{SameNumberOfRows, ShapeConstraint}; @@ -40,7 +40,7 @@ use crate::linalg::givens::GivensRotation; )) )] #[derive(Clone, Debug)] -pub struct SVD, C: Dim> +pub struct SVD, C: Dim> where DefaultAllocator: Allocator, C> + Allocator> + Allocator> @@ -53,7 +53,7 @@ where DefaultAllocator: Allocator, C> pub singular_values: VectorN>, } -impl, C: Dim> Copy for SVD +impl, C: Dim> Copy for SVD where DefaultAllocator: Allocator, C> + Allocator> @@ -63,7 +63,7 @@ where VectorN>: Copy, {} -impl, C: Dim> SVD +impl, C: Dim> SVD where DimMinimum: DimSub, // for Bidiagonal. DefaultAllocator: Allocator @@ -546,7 +546,7 @@ where } } -impl, C: Dim, S: Storage> Matrix +impl, C: Dim, S: Storage> Matrix where DimMinimum: DimSub, // for Bidiagonal. DefaultAllocator: Allocator diff --git a/src/linalg/symmetric_eigen.rs b/src/linalg/symmetric_eigen.rs index 6fd1fea5..78e00509 100644 --- a/src/linalg/symmetric_eigen.rs +++ b/src/linalg/symmetric_eigen.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; use num::Zero; use approx::AbsDiffEq; -use alga::general::Complex; +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}; @@ -34,7 +34,7 @@ use crate::linalg::SymmetricTridiagonal; )) )] #[derive(Clone, Debug)] -pub struct SymmetricEigen +pub struct SymmetricEigen where DefaultAllocator: Allocator + Allocator { /// The eigenvectors of the decomposed matrix. @@ -44,14 +44,14 @@ where DefaultAllocator: Allocator + Allocator pub eigenvalues: VectorN, } -impl Copy for SymmetricEigen +impl Copy for SymmetricEigen where DefaultAllocator: Allocator + Allocator, MatrixN: Copy, VectorN: Copy, {} -impl SymmetricEigen +impl SymmetricEigen where DefaultAllocator: Allocator + Allocator { /// Computes the eigendecomposition of the given symmetric matrix. @@ -288,7 +288,7 @@ where DefaultAllocator: Allocator + Allocator /// The inputs are interpreted as the 2x2 matrix: /// tmm tmn /// tmn tnn -pub fn wilkinson_shift(tmm: N, tnn: N, tmn: N) -> N { +pub fn wilkinson_shift(tmm: N, tnn: N, tmn: N) -> N { let sq_tmn = tmn * tmn; if !sq_tmn.is_zero() { // We have the guarantee that the denominator won't be zero. @@ -304,7 +304,7 @@ pub fn wilkinson_shift(tmm: N, tnn: N, tmn: N) -> N { * Computations of eigenvalues for symmetric matrices. * */ -impl, S: Storage> SquareMatrix +impl, S: Storage> SquareMatrix where DefaultAllocator: Allocator + Allocator> + Allocator + Allocator> { diff --git a/src/linalg/symmetric_tridiagonal.rs b/src/linalg/symmetric_tridiagonal.rs index 386c0a6f..0a04dae8 100644 --- a/src/linalg/symmetric_tridiagonal.rs +++ b/src/linalg/symmetric_tridiagonal.rs @@ -1,7 +1,7 @@ #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Serialize}; -use alga::general::Complex; +use alga::general::ComplexField; use crate::allocator::Allocator; use crate::base::{DefaultAllocator, MatrixMN, MatrixN, SquareMatrix, VectorN}; use crate::dimension::{DimDiff, DimSub, U1}; @@ -30,21 +30,21 @@ use crate::linalg::householder; )) )] #[derive(Clone, Debug)] -pub struct SymmetricTridiagonal> +pub struct SymmetricTridiagonal> where DefaultAllocator: Allocator + Allocator> { tri: MatrixN, off_diagonal: VectorN>, } -impl> Copy for SymmetricTridiagonal +impl> Copy for SymmetricTridiagonal where DefaultAllocator: Allocator + Allocator>, MatrixN: Copy, VectorN>: Copy, {} -impl> SymmetricTridiagonal +impl> SymmetricTridiagonal where DefaultAllocator: Allocator + Allocator> { /// Computes the tridiagonalization of the symmetric matrix `m`. @@ -145,7 +145,7 @@ where DefaultAllocator: Allocator + Allocator> } } -impl, S: Storage> SquareMatrix +impl, S: Storage> SquareMatrix where DefaultAllocator: Allocator + Allocator> { /// Computes the tridiagonalization of this symmetric matrix. diff --git a/tests/core/matrix.rs b/tests/core/matrix.rs index 5ba06f5b..81de11b0 100644 --- a/tests/core/matrix.rs +++ b/tests/core/matrix.rs @@ -1022,7 +1022,7 @@ mod finite_dim_inner_space_tests { * */ #[cfg(feature = "arbitrary")] - fn is_subspace_basis + Display>(vs: &[T]) -> bool { + fn is_subspace_basis + Display>(vs: &[T]) -> bool { for i in 0..vs.len() { // Basis elements must be normalized. if !relative_eq!(vs[i].norm(), 1.0, epsilon = 1.0e-7) { diff --git a/tests/linalg/solve.rs b/tests/linalg/solve.rs index 90b76585..e917cfc5 100644 --- a/tests/linalg/solve.rs +++ b/tests/linalg/solve.rs @@ -4,11 +4,11 @@ macro_rules! gen_tests( ($module: ident, $scalar: ty) => { mod $module { - use na::{Matrix4, Matrix4x5, Complex}; + use na::{Matrix4, Matrix4x5, ComplexField}; #[allow(unused_imports)] use crate::core::helper::{RandScalar, RandComplex}; - fn unzero_diagonal(a: &mut Matrix4) { + fn unzero_diagonal(a: &mut Matrix4) { for i in 0..4 { if a[(i, i)].norm1() < na::convert(1.0e-7) { a[(i, i)] = N::one(); diff --git a/tests/linalg/svd.rs b/tests/linalg/svd.rs index a9b1d1cf..ca7bab4c 100644 --- a/tests/linalg/svd.rs +++ b/tests/linalg/svd.rs @@ -8,7 +8,7 @@ mod quickcheck_tests { mod $module { use na::{ DMatrix, DVector, Matrix2, Matrix2x5, Matrix3, Matrix3x5, Matrix4, Matrix5x2, Matrix5x3, - Complex + ComplexField }; use std::cmp; #[allow(unused_imports)] @@ -21,7 +21,7 @@ mod quickcheck_tests { let svd = m.clone().svd(true, true); let recomp_m = svd.clone().recompose().unwrap(); let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); - let ds = DMatrix::from_diagonal(&s.map(|e| Complex::from_real(e))); + let ds = DMatrix::from_diagonal(&s.map(|e| ComplexField::from_real(e))); s.iter().all(|e| *e >= 0.0) && relative_eq!(&u * ds * &v_t, recomp_m, epsilon = 1.0e-5) && @@ -36,7 +36,7 @@ mod quickcheck_tests { let m = m.map(|e| e.0); let svd = m.svd(true, true); let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); - let ds = Matrix3::from_diagonal(&s.map(|e| Complex::from_real(e))); + let ds = Matrix3::from_diagonal(&s.map(|e| ComplexField::from_real(e))); s.iter().all(|e| *e >= 0.0) && relative_eq!(m, &u * ds * &v_t, epsilon = 1.0e-5) && @@ -48,7 +48,7 @@ mod quickcheck_tests { let m = m.map(|e| e.0); let svd = m.svd(true, true); let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); - let ds = Matrix2::from_diagonal(&s.map(|e| Complex::from_real(e))); + let ds = Matrix2::from_diagonal(&s.map(|e| ComplexField::from_real(e))); s.iter().all(|e| *e >= 0.0) && relative_eq!(m, &u * ds * &v_t, epsilon = 1.0e-5) && @@ -61,7 +61,7 @@ mod quickcheck_tests { let svd = m.svd(true, true); let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); - let ds = Matrix3::from_diagonal(&s.map(|e| Complex::from_real(e))); + let ds = Matrix3::from_diagonal(&s.map(|e| ComplexField::from_real(e))); s.iter().all(|e| *e >= 0.0) && relative_eq!(m, u * ds * v_t, epsilon = 1.0e-5) @@ -71,7 +71,7 @@ mod quickcheck_tests { let m = m.map(|e| e.0); let svd = m.svd(true, true); let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); - let ds = Matrix2::from_diagonal(&s.map(|e| Complex::from_real(e))); + let ds = Matrix2::from_diagonal(&s.map(|e| ComplexField::from_real(e))); s.iter().all(|e| *e >= 0.0) && relative_eq!(m, u * ds * v_t, epsilon = 1.0e-5) @@ -81,7 +81,7 @@ mod quickcheck_tests { let m = m.map(|e| e.0); let svd = m.svd(true, true); let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); - let ds = Matrix4::from_diagonal(&s.map(|e| Complex::from_real(e))); + let ds = Matrix4::from_diagonal(&s.map(|e| ComplexField::from_real(e))); s.iter().all(|e| *e >= 0.0) && relative_eq!(m, u * ds * v_t, epsilon = 1.0e-5) && @@ -93,7 +93,7 @@ mod quickcheck_tests { let m = m.map(|e| e.0); let svd = m.svd(true, true); let (u, s, v_t) = (svd.u.unwrap(), svd.singular_values, svd.v_t.unwrap()); - let ds = Matrix2::from_diagonal(&s.map(|e| Complex::from_real(e))); + let ds = Matrix2::from_diagonal(&s.map(|e| ComplexField::from_real(e))); s.iter().all(|e| *e >= 0.0) && relative_eq!(m, u * ds * v_t, epsilon = 1.0e-5) && From 4ef40018368f12a44da4cf65a1da5c9d91f0fee0 Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Mon, 25 Mar 2019 11:21:41 +0100 Subject: [PATCH 18/28] Rename Real to RealField. --- examples/dimensional_genericity.rs | 10 +- examples/scalar_genericity.rs | 6 +- nalgebra-glm/src/common.rs | 16 +-- nalgebra-glm/src/constructors.rs | 4 +- nalgebra-glm/src/exponential.rs | 16 +-- nalgebra-glm/src/ext/matrix_clip_space.rs | 86 ++++++++-------- nalgebra-glm/src/ext/matrix_projection.rs | 16 +-- nalgebra-glm/src/ext/matrix_transform.rs | 16 +-- nalgebra-glm/src/ext/quaternion_common.rs | 16 +-- nalgebra-glm/src/ext/quaternion_geometric.rs | 12 +-- nalgebra-glm/src/ext/quaternion_relational.rs | 10 +- nalgebra-glm/src/ext/quaternion_transform.rs | 12 +-- .../src/ext/quaternion_trigonometric.rs | 8 +- nalgebra-glm/src/ext/scalar_constants.rs | 4 +- nalgebra-glm/src/geometric.rs | 12 +-- nalgebra-glm/src/gtc/constants.rs | 54 +++++----- nalgebra-glm/src/gtc/matrix_inverse.rs | 6 +- nalgebra-glm/src/gtc/packing.rs | 10 +- nalgebra-glm/src/gtc/quaternion.rs | 26 ++--- nalgebra-glm/src/gtc/round.rs | 2 +- nalgebra-glm/src/gtc/type_ptr.rs | 4 +- nalgebra-glm/src/gtx/euler_angles.rs | 82 ++++++++-------- nalgebra-glm/src/gtx/matrix_cross_product.rs | 6 +- nalgebra-glm/src/gtx/norm.rs | 20 ++-- nalgebra-glm/src/gtx/normal.rs | 4 +- nalgebra-glm/src/gtx/normalize_dot.rs | 6 +- nalgebra-glm/src/gtx/quaternion.rs | 36 +++---- .../src/gtx/rotate_normalized_axis.rs | 6 +- nalgebra-glm/src/gtx/rotate_vector.rs | 24 ++--- nalgebra-glm/src/gtx/transform.rs | 6 +- nalgebra-glm/src/gtx/transform2d.rs | 4 +- nalgebra-glm/src/gtx/vector_angle.rs | 8 +- nalgebra-glm/src/gtx/vector_query.rs | 4 +- nalgebra-glm/src/integer.rs | 2 +- nalgebra-glm/src/lib.rs | 2 +- nalgebra-glm/src/matrix.rs | 6 +- nalgebra-glm/src/trigonometric.rs | 32 +++--- nalgebra-lapack/src/eigen.rs | 4 +- nalgebra-lapack/src/schur.rs | 6 +- nalgebra-lapack/src/symmetric_eigen.rs | 4 +- src/base/cg.rs | 10 +- src/base/construction.rs | 4 +- src/base/matrix.rs | 38 +++---- src/base/matrix_alga.rs | 18 ++-- src/base/norm.rs | 52 +++++----- src/base/ops.rs | 4 +- src/base/properties.rs | 4 +- src/base/unit.rs | 12 +-- src/geometry/isometry.rs | 28 +++--- src/geometry/isometry_alga.rs | 20 ++-- src/geometry/isometry_construction.rs | 16 +-- src/geometry/isometry_conversion.rs | 20 ++-- src/geometry/isometry_ops.rs | 10 +- src/geometry/orthographic.rs | 24 ++--- src/geometry/perspective.rs | 22 ++--- src/geometry/point_alga.rs | 6 +- src/geometry/quaternion.rs | 40 ++++---- src/geometry/quaternion_alga.rs | 44 ++++----- src/geometry/quaternion_construction.rs | 20 ++-- src/geometry/quaternion_conversion.rs | 44 ++++----- src/geometry/quaternion_coordinates.rs | 6 +- src/geometry/quaternion_ops.rs | 20 ++-- src/geometry/rotation.rs | 4 +- src/geometry/rotation_alga.rs | 28 +++--- src/geometry/rotation_conversion.rs | 40 ++++---- src/geometry/rotation_specialization.rs | 14 +-- src/geometry/similarity.rs | 28 +++--- src/geometry/similarity_alga.rs | 18 ++-- src/geometry/similarity_construction.rs | 18 ++-- src/geometry/similarity_conversion.rs | 16 +-- src/geometry/similarity_ops.rs | 10 +- src/geometry/transform.rs | 36 +++---- src/geometry/transform_alga.rs | 18 ++-- src/geometry/transform_construction.rs | 6 +- src/geometry/transform_conversion.rs | 12 +-- src/geometry/transform_ops.rs | 74 +++++++------- src/geometry/translation.rs | 4 +- src/geometry/translation_alga.rs | 22 ++--- src/geometry/translation_conversion.rs | 18 ++-- src/geometry/unit_complex.rs | 12 +-- src/geometry/unit_complex_alga.rs | 22 ++--- src/geometry/unit_complex_construction.rs | 10 +- src/geometry/unit_complex_conversion.rs | 32 +++--- src/geometry/unit_complex_ops.rs | 44 ++++----- src/io/matrix_market.rs | 6 +- src/lib.rs | 26 ++--- src/linalg/balancing.rs | 6 +- src/linalg/bidiagonal.rs | 8 +- src/linalg/givens.rs | 12 +-- src/linalg/schur.rs | 22 ++--- src/linalg/svd.rs | 98 +++++++++---------- src/linalg/symmetric_eigen.rs | 50 +++++----- src/linalg/symmetric_tridiagonal.rs | 20 ++-- src/sparse/cs_matrix_cholesky.rs | 6 +- src/sparse/cs_matrix_solve.rs | 4 +- tests/core/helper.rs | 8 +- tests/core/matrix.rs | 4 +- tests/geometry/rotation.rs | 4 +- 98 files changed, 915 insertions(+), 915 deletions(-) diff --git a/examples/dimensional_genericity.rs b/examples/dimensional_genericity.rs index ca653d57..411a0666 100644 --- a/examples/dimensional_genericity.rs +++ b/examples/dimensional_genericity.rs @@ -4,7 +4,7 @@ extern crate nalgebra as na; use alga::linear::FiniteDimInnerSpace; use na::allocator::Allocator; use na::dimension::Dim; -use na::{DefaultAllocator, Real, Unit, Vector2, Vector3, VectorN}; +use na::{DefaultAllocator, RealField, Unit, Vector2, Vector3, VectorN}; /// Reflects a vector wrt. the hyperplane with normal `plane_normal`. fn reflect_wrt_hyperplane_with_algebraic_genericity(plane_normal: &Unit, vector: &V) -> V @@ -14,12 +14,12 @@ where V: FiniteDimInnerSpace + Copy { } /// Reflects a vector wrt. the hyperplane with normal `plane_normal`. -fn reflect_wrt_hyperplane_with_dimensional_genericity( +fn reflect_wrt_hyperplane_with_dimensional_genericity( plane_normal: &Unit>, vector: &VectorN, ) -> VectorN where - N: Real, + N: RealField, D: Dim, DefaultAllocator: Allocator, { @@ -29,7 +29,7 @@ where /// Reflects a 2D vector wrt. the 2D line with normal `plane_normal`. fn reflect_wrt_hyperplane2(plane_normal: &Unit>, vector: &Vector2) -> Vector2 -where N: Real { +where N: RealField { let n = plane_normal.as_ref(); // Get the underlying Vector2 vector - n * (n.dot(vector) * na::convert(2.0)) } @@ -37,7 +37,7 @@ where N: Real { /// Reflects a 3D vector wrt. the 3D plane with normal `plane_normal`. /// /!\ This is an exact replicate of `reflect_wrt_hyperplane2, but for 3D. fn reflect_wrt_hyperplane3(plane_normal: &Unit>, vector: &Vector3) -> Vector3 -where N: Real { +where N: RealField { let n = plane_normal.as_ref(); // Get the underlying Vector3 vector - n * (n.dot(vector) * na::convert(2.0)) } diff --git a/examples/scalar_genericity.rs b/examples/scalar_genericity.rs index 246d1efd..75f6f9d4 100644 --- a/examples/scalar_genericity.rs +++ b/examples/scalar_genericity.rs @@ -1,7 +1,7 @@ extern crate alga; extern crate nalgebra as na; -use alga::general::{Real, RingCommutative}; +use alga::general::{RealField, RingCommutative}; use na::{Scalar, Vector3}; fn print_vector(m: &Vector3) { @@ -14,11 +14,11 @@ fn print_squared_norm(v: &Vector3) { println!("{:?}", sqnorm); } -fn print_norm(v: &Vector3) { +fn print_norm(v: &Vector3) { // NOTE: alternatively, nalgebra already defines `v.norm()`. let norm = v.dot(v).sqrt(); - // The Real bound implies that N is Display so we can + // The RealField bound implies that N is Display so we can // use "{}" instead of "{:?}" for the format string. println!("{}", norm) } diff --git a/nalgebra-glm/src/common.rs b/nalgebra-glm/src/common.rs index 23103299..c9f9c265 100644 --- a/nalgebra-glm/src/common.rs +++ b/nalgebra-glm/src/common.rs @@ -1,4 +1,4 @@ -use na::{self, DefaultAllocator, Real}; +use na::{self, DefaultAllocator, RealField}; use num::FromPrimitive; use std::mem; @@ -43,7 +43,7 @@ where DefaultAllocator: Alloc { /// * [`fract`](fn.fract.html) /// * [`round`](fn.round.html) /// * [`trunc`](fn.trunc.html) -pub fn ceil(x: &TVec) -> TVec +pub fn ceil(x: &TVec) -> TVec where DefaultAllocator: Alloc { x.map(|x| x.ceil()) } @@ -222,7 +222,7 @@ where DefaultAllocator: Alloc { /// * [`fract`](fn.fract.html) /// * [`round`](fn.round.html) /// * [`trunc`](fn.trunc.html) -pub fn floor(x: &TVec) -> TVec +pub fn floor(x: &TVec) -> TVec where DefaultAllocator: Alloc { x.map(|x| x.floor()) } @@ -249,14 +249,14 @@ where DefaultAllocator: Alloc { /// * [`floor`](fn.floor.html) /// * [`round`](fn.round.html) /// * [`trunc`](fn.trunc.html) -pub fn fract(x: &TVec) -> TVec +pub fn fract(x: &TVec) -> TVec where DefaultAllocator: Alloc { x.map(|x| x.fract()) } //// FIXME: should be implemented for TVec/TMat? ///// Returns the (significant, exponent) of this float number. -//pub fn frexp(x: N, exp: N) -> (N, N) { +//pub fn frexp(x: N, exp: N) -> (N, N) { // // FIXME: is there a better approach? // let e = x.log2().ceil(); // (x * (-e).exp2(), e) @@ -310,7 +310,7 @@ where DefaultAllocator: Alloc { //} ///// Returns the (significant, exponent) of this float number. -//pub fn ldexp(x: N, exp: N) -> N { +//pub fn ldexp(x: N, exp: N) -> N { // // FIXME: is there a better approach? // x * (exp).exp2() //} @@ -499,7 +499,7 @@ pub fn modf(x: N, i: N) -> N { /// * [`floor`](fn.floor.html) /// * [`fract`](fn.fract.html) /// * [`trunc`](fn.trunc.html) -pub fn round(x: &TVec) -> TVec +pub fn round(x: &TVec) -> TVec where DefaultAllocator: Alloc { x.map(|x| x.round()) } @@ -576,7 +576,7 @@ where DefaultAllocator: Alloc { /// * [`floor`](fn.floor.html) /// * [`fract`](fn.fract.html) /// * [`round`](fn.round.html) -pub fn trunc(x: &TVec) -> TVec +pub fn trunc(x: &TVec) -> TVec where DefaultAllocator: Alloc { x.map(|x| x.trunc()) } diff --git a/nalgebra-glm/src/constructors.rs b/nalgebra-glm/src/constructors.rs index fb692d5c..949ea9e4 100644 --- a/nalgebra-glm/src/constructors.rs +++ b/nalgebra-glm/src/constructors.rs @@ -1,6 +1,6 @@ #![cfg_attr(rustfmt, rustfmt_skip)] -use na::{Scalar, Real, U2, U3, U4}; +use na::{Scalar, RealField, U2, U3, U4}; use crate::aliases::{TMat, Qua, TVec1, TVec2, TVec3, TVec4, TMat2, TMat2x3, TMat2x4, TMat3, TMat3x2, TMat3x4, TMat4, TMat4x2, TMat4x3}; @@ -168,6 +168,6 @@ pub fn mat4(m11: N, m12: N, m13: N, m14: N, } /// Creates a new quaternion. -pub fn quat(x: N, y: N, z: N, w: N) -> Qua { +pub fn quat(x: N, y: N, z: N, w: N) -> Qua { Qua::new(w, x, y, z) } diff --git a/nalgebra-glm/src/exponential.rs b/nalgebra-glm/src/exponential.rs index e080805d..fd54fb34 100644 --- a/nalgebra-glm/src/exponential.rs +++ b/nalgebra-glm/src/exponential.rs @@ -1,5 +1,5 @@ use crate::aliases::TVec; -use na::{DefaultAllocator, Real}; +use na::{DefaultAllocator, RealField}; use crate::traits::{Alloc, Dimension}; /// Component-wise exponential. @@ -7,7 +7,7 @@ use crate::traits::{Alloc, Dimension}; /// # See also: /// /// * [`exp2`](fn.exp2.html) -pub fn exp(v: &TVec) -> TVec +pub fn exp(v: &TVec) -> TVec where DefaultAllocator: Alloc { v.map(|x| x.exp()) } @@ -17,7 +17,7 @@ where DefaultAllocator: Alloc { /// # See also: /// /// * [`exp`](fn.exp.html) -pub fn exp2(v: &TVec) -> TVec +pub fn exp2(v: &TVec) -> TVec where DefaultAllocator: Alloc { v.map(|x| x.exp2()) } @@ -27,7 +27,7 @@ where DefaultAllocator: Alloc { /// # See also: /// /// * [`sqrt`](fn.sqrt.html) -pub fn inversesqrt(v: &TVec) -> TVec +pub fn inversesqrt(v: &TVec) -> TVec where DefaultAllocator: Alloc { v.map(|x| N::one() / x.sqrt()) } @@ -37,7 +37,7 @@ where DefaultAllocator: Alloc { /// # See also: /// /// * [`log2`](fn.log2.html) -pub fn log(v: &TVec) -> TVec +pub fn log(v: &TVec) -> TVec where DefaultAllocator: Alloc { v.map(|x| x.ln()) } @@ -47,13 +47,13 @@ where DefaultAllocator: Alloc { /// # See also: /// /// * [`log`](fn.log.html) -pub fn log2(v: &TVec) -> TVec +pub fn log2(v: &TVec) -> TVec where DefaultAllocator: Alloc { v.map(|x| x.log2()) } /// Component-wise power. -pub fn pow(base: &TVec, exponent: &TVec) -> TVec +pub fn pow(base: &TVec, exponent: &TVec) -> TVec where DefaultAllocator: Alloc { base.zip_map(exponent, |b, e| b.powf(e)) } @@ -66,7 +66,7 @@ where DefaultAllocator: Alloc { /// * [`exp2`](fn.exp2.html) /// * [`inversesqrt`](fn.inversesqrt.html) /// * [`pow`](fn.pow.html) -pub fn sqrt(v: &TVec) -> TVec +pub fn sqrt(v: &TVec) -> TVec where DefaultAllocator: Alloc { v.map(|x| x.sqrt()) } diff --git a/nalgebra-glm/src/ext/matrix_clip_space.rs b/nalgebra-glm/src/ext/matrix_clip_space.rs index fe7cc973..6ef1404b 100644 --- a/nalgebra-glm/src/ext/matrix_clip_space.rs +++ b/nalgebra-glm/src/ext/matrix_clip_space.rs @@ -1,55 +1,55 @@ use crate::aliases::TMat4; -use na::{Real}; +use na::{RealField}; -//pub fn frustum(left: N, right: N, bottom: N, top: N, near: N, far: N) -> TMat4 { +//pub fn frustum(left: N, right: N, bottom: N, top: N, near: N, far: N) -> TMat4 { // unimplemented!() //} -//pub fn frustum_lh(left: N, right: N, bottom: N, top: N, near: N, far: N) -> TMat4 { +//pub fn frustum_lh(left: N, right: N, bottom: N, top: N, near: N, far: N) -> TMat4 { // unimplemented!() //} // -//pub fn frustum_lr_no(left: N, right: N, bottom: N, top: N, near: N, far: N) -> TMat4 { +//pub fn frustum_lr_no(left: N, right: N, bottom: N, top: N, near: N, far: N) -> TMat4 { // unimplemented!() //} // -//pub fn frustum_lh_zo(left: N, right: N, bottom: N, top: N, near: N, far: N) -> TMat4 { +//pub fn frustum_lh_zo(left: N, right: N, bottom: N, top: N, near: N, far: N) -> TMat4 { // unimplemented!() //} // -//pub fn frustum_no(left: N, right: N, bottom: N, top: N, near: N, far: N) -> TMat4 { +//pub fn frustum_no(left: N, right: N, bottom: N, top: N, near: N, far: N) -> TMat4 { // unimplemented!() //} // -//pub fn frustum_rh(left: N, right: N, bottom: N, top: N, near: N, far: N) -> TMat4 { +//pub fn frustum_rh(left: N, right: N, bottom: N, top: N, near: N, far: N) -> TMat4 { // unimplemented!() //} // -//pub fn frustum_rh_no(left: N, right: N, bottom: N, top: N, near: N, far: N) -> TMat4 { +//pub fn frustum_rh_no(left: N, right: N, bottom: N, top: N, near: N, far: N) -> TMat4 { // unimplemented!() //} // -//pub fn frustum_rh_zo(left: N, right: N, bottom: N, top: N, near: N, far: N) -> TMat4 { +//pub fn frustum_rh_zo(left: N, right: N, bottom: N, top: N, near: N, far: N) -> TMat4 { // unimplemented!() //} // -//pub fn frustum_zo(left: N, right: N, bottom: N, top: N, near: N, far: N) -> TMat4 { +//pub fn frustum_zo(left: N, right: N, bottom: N, top: N, near: N, far: N) -> TMat4 { // unimplemented!() //} -//pub fn infinite_perspective(fovy: N, aspect: N, near: N) -> TMat4 { +//pub fn infinite_perspective(fovy: N, aspect: N, near: N) -> TMat4 { // unimplemented!() //} // -//pub fn infinite_perspective_lh(fovy: N, aspect: N, near: N) -> TMat4 { +//pub fn infinite_perspective_lh(fovy: N, aspect: N, near: N) -> TMat4 { // unimplemented!() //} // -//pub fn infinite_perspective_rh(fovy: N, aspect: N, near: N) -> TMat4 { +//pub fn infinite_perspective_rh(fovy: N, aspect: N, near: N) -> TMat4 { // unimplemented!() //} // -//pub fn infinite_ortho(left: N, right: N, bottom: N, top: N) -> TMat4 { +//pub fn infinite_ortho(left: N, right: N, bottom: N, top: N) -> TMat4 { // unimplemented!() //} @@ -64,7 +64,7 @@ use na::{Real}; /// * `znear` - Distance from the viewer to the near clipping plane /// * `zfar` - Distance from the viewer to the far clipping plane /// -pub fn ortho(left: N, right: N, bottom: N, top: N, znear: N, zfar: N) -> TMat4 { +pub fn ortho(left: N, right: N, bottom: N, top: N, znear: N, zfar: N) -> TMat4 { ortho_rh_no(left, right, bottom, top, znear, zfar) } @@ -79,7 +79,7 @@ pub fn ortho(left: N, right: N, bottom: N, top: N, znear: N, zfar: N) - /// * `znear` - Distance from the viewer to the near clipping plane /// * `zfar` - Distance from the viewer to the far clipping plane /// -pub fn ortho_lh(left: N, right: N, bottom: N, top: N, znear: N, zfar: N) -> TMat4 { +pub fn ortho_lh(left: N, right: N, bottom: N, top: N, znear: N, zfar: N) -> TMat4 { ortho_lh_no(left, right, bottom, top, znear, zfar) } @@ -94,7 +94,7 @@ pub fn ortho_lh(left: N, right: N, bottom: N, top: N, znear: N, zfar: N /// * `znear` - Distance from the viewer to the near clipping plane /// * `zfar` - Distance from the viewer to the far clipping plane /// -pub fn ortho_lh_no(left: N, right: N, bottom: N, top: N, znear: N, zfar: N) -> TMat4 { +pub fn ortho_lh_no(left: N, right: N, bottom: N, top: N, znear: N, zfar: N) -> TMat4 { let two : N = crate::convert(2.0); let mut mat : TMat4 = TMat4::::identity(); @@ -119,7 +119,7 @@ pub fn ortho_lh_no(left: N, right: N, bottom: N, top: N, znear: N, zfar /// * `znear` - Distance from the viewer to the near clipping plane /// * `zfar` - Distance from the viewer to the far clipping plane /// -pub fn ortho_lh_zo(left: N, right: N, bottom: N, top: N, znear: N, zfar: N) -> TMat4 { +pub fn ortho_lh_zo(left: N, right: N, bottom: N, top: N, znear: N, zfar: N) -> TMat4 { let one : N = N::one(); let two : N = crate::convert(2.0); let mut mat : TMat4 = TMat4::::identity(); @@ -145,7 +145,7 @@ pub fn ortho_lh_zo(left: N, right: N, bottom: N, top: N, znear: N, zfar /// * `znear` - Distance from the viewer to the near clipping plane /// * `zfar` - Distance from the viewer to the far clipping plane /// -pub fn ortho_no(left: N, right: N, bottom: N, top: N, znear: N, zfar: N) -> TMat4 { +pub fn ortho_no(left: N, right: N, bottom: N, top: N, znear: N, zfar: N) -> TMat4 { ortho_rh_no(left, right, bottom, top, znear, zfar) } @@ -160,7 +160,7 @@ pub fn ortho_no(left: N, right: N, bottom: N, top: N, znear: N, zfar: N /// * `znear` - Distance from the viewer to the near clipping plane /// * `zfar` - Distance from the viewer to the far clipping plane /// -pub fn ortho_rh(left: N, right: N, bottom: N, top: N, znear: N, zfar: N) -> TMat4 { +pub fn ortho_rh(left: N, right: N, bottom: N, top: N, znear: N, zfar: N) -> TMat4 { ortho_rh_no(left, right, bottom, top, znear, zfar) } @@ -175,7 +175,7 @@ pub fn ortho_rh(left: N, right: N, bottom: N, top: N, znear: N, zfar: N /// * `znear` - Distance from the viewer to the near clipping plane /// * `zfar` - Distance from the viewer to the far clipping plane /// -pub fn ortho_rh_no(left: N, right: N, bottom: N, top: N, znear: N, zfar: N) -> TMat4 { +pub fn ortho_rh_no(left: N, right: N, bottom: N, top: N, znear: N, zfar: N) -> TMat4 { let two : N = crate::convert(2.0); let mut mat : TMat4 = TMat4::::identity(); @@ -200,7 +200,7 @@ pub fn ortho_rh_no(left: N, right: N, bottom: N, top: N, znear: N, zfar /// * `znear` - Distance from the viewer to the near clipping plane /// * `zfar` - Distance from the viewer to the far clipping plane /// -pub fn ortho_rh_zo(left: N, right: N, bottom: N, top: N, znear: N, zfar: N) -> TMat4 { +pub fn ortho_rh_zo(left: N, right: N, bottom: N, top: N, znear: N, zfar: N) -> TMat4 { let one : N = N::one(); let two : N = crate::convert(2.0); let mut mat : TMat4 = TMat4::::identity(); @@ -226,7 +226,7 @@ pub fn ortho_rh_zo(left: N, right: N, bottom: N, top: N, znear: N, zfar /// * `znear` - Distance from the viewer to the near clipping plane /// * `zfar` - Distance from the viewer to the far clipping plane /// -pub fn ortho_zo(left: N, right: N, bottom: N, top: N, znear: N, zfar: N) -> TMat4 { +pub fn ortho_zo(left: N, right: N, bottom: N, top: N, znear: N, zfar: N) -> TMat4 { ortho_rh_zo(left, right, bottom, top, znear, zfar) } @@ -240,7 +240,7 @@ pub fn ortho_zo(left: N, right: N, bottom: N, top: N, znear: N, zfar: N /// * `near` - Distance from the viewer to the near clipping plane /// * `far` - Distance from the viewer to the far clipping plane /// -pub fn perspective_fov(fov: N, width: N, height: N, near: N, far: N) -> TMat4 { +pub fn perspective_fov(fov: N, width: N, height: N, near: N, far: N) -> TMat4 { perspective_fov_rh_no(fov, width, height, near, far) } @@ -254,7 +254,7 @@ pub fn perspective_fov(fov: N, width: N, height: N, near: N, far: N) -> /// * `near` - Distance from the viewer to the near clipping plane /// * `far` - Distance from the viewer to the far clipping plane /// -pub fn perspective_fov_lh(fov: N, width: N, height: N, near: N, far: N) -> TMat4 { +pub fn perspective_fov_lh(fov: N, width: N, height: N, near: N, far: N) -> TMat4 { perspective_fov_lh_no(fov, width, height, near, far) } @@ -268,7 +268,7 @@ pub fn perspective_fov_lh(fov: N, width: N, height: N, near: N, far: N) /// * `near` - Distance from the viewer to the near clipping plane /// * `far` - Distance from the viewer to the far clipping plane /// -pub fn perspective_fov_lh_no(fov: N, width: N, height: N, near: N, far: N) -> TMat4 { +pub fn perspective_fov_lh_no(fov: N, width: N, height: N, near: N, far: N) -> TMat4 { assert!( width > N::zero(), "The width must be greater than zero" @@ -307,7 +307,7 @@ pub fn perspective_fov_lh_no(fov: N, width: N, height: N, near: N, far: /// * `near` - Distance from the viewer to the near clipping plane /// * `far` - Distance from the viewer to the far clipping plane /// -pub fn perspective_fov_lh_zo(fov: N, width: N, height: N, near: N, far: N) -> TMat4 { +pub fn perspective_fov_lh_zo(fov: N, width: N, height: N, near: N, far: N) -> TMat4 { assert!( width > N::zero(), "The width must be greater than zero" @@ -346,7 +346,7 @@ pub fn perspective_fov_lh_zo(fov: N, width: N, height: N, near: N, far: /// * `near` - Distance from the viewer to the near clipping plane /// * `far` - Distance from the viewer to the far clipping plane /// -pub fn perspective_fov_no(fov: N, width: N, height: N, near: N, far: N) -> TMat4 { +pub fn perspective_fov_no(fov: N, width: N, height: N, near: N, far: N) -> TMat4 { perspective_fov_rh_no(fov, width, height, near, far) } @@ -360,7 +360,7 @@ pub fn perspective_fov_no(fov: N, width: N, height: N, near: N, far: N) /// * `near` - Distance from the viewer to the near clipping plane /// * `far` - Distance from the viewer to the far clipping plane /// -pub fn perspective_fov_rh(fov: N, width: N, height: N, near: N, far: N) -> TMat4 { +pub fn perspective_fov_rh(fov: N, width: N, height: N, near: N, far: N) -> TMat4 { perspective_fov_rh_no(fov, width, height, near, far) } @@ -374,7 +374,7 @@ pub fn perspective_fov_rh(fov: N, width: N, height: N, near: N, far: N) /// * `near` - Distance from the viewer to the near clipping plane /// * `far` - Distance from the viewer to the far clipping plane /// -pub fn perspective_fov_rh_no(fov: N, width: N, height: N, near: N, far: N) -> TMat4 { +pub fn perspective_fov_rh_no(fov: N, width: N, height: N, near: N, far: N) -> TMat4 { assert!( width > N::zero(), "The width must be greater than zero" @@ -413,7 +413,7 @@ pub fn perspective_fov_rh_no(fov: N, width: N, height: N, near: N, far: /// * `near` - Distance from the viewer to the near clipping plane /// * `far` - Distance from the viewer to the far clipping plane /// -pub fn perspective_fov_rh_zo(fov: N, width: N, height: N, near: N, far: N) -> TMat4 { +pub fn perspective_fov_rh_zo(fov: N, width: N, height: N, near: N, far: N) -> TMat4 { assert!( width > N::zero(), "The width must be greater than zero" @@ -452,7 +452,7 @@ pub fn perspective_fov_rh_zo(fov: N, width: N, height: N, near: N, far: /// * `near` - Distance from the viewer to the near clipping plane /// * `far` - Distance from the viewer to the far clipping plane /// -pub fn perspective_fov_zo(fov: N, width: N, height: N, near: N, far: N) -> TMat4 { +pub fn perspective_fov_zo(fov: N, width: N, height: N, near: N, far: N) -> TMat4 { perspective_fov_rh_zo(fov, width, height, near, far) } @@ -467,7 +467,7 @@ pub fn perspective_fov_zo(fov: N, width: N, height: N, near: N, far: N) /// /// # Important note /// The `aspect` and `fovy` argument are interchanged compared to the original GLM API. -pub fn perspective(aspect: N, fovy: N, near: N, far: N) -> TMat4 { +pub fn perspective(aspect: N, fovy: N, near: N, far: N) -> TMat4 { // TODO: Breaking change - revert back to proper glm conventions? // // Prior to changes to support configuring the behaviour of this function it was simply @@ -496,7 +496,7 @@ pub fn perspective(aspect: N, fovy: N, near: N, far: N) -> TMat4 { /// /// # Important note /// The `aspect` and `fovy` argument are interchanged compared to the original GLM API. -pub fn perspective_lh(aspect: N, fovy: N, near: N, far: N) -> TMat4 { +pub fn perspective_lh(aspect: N, fovy: N, near: N, far: N) -> TMat4 { perspective_lh_no(aspect, fovy, near, far) } @@ -511,7 +511,7 @@ pub fn perspective_lh(aspect: N, fovy: N, near: N, far: N) -> TMat4 /// /// # Important note /// The `aspect` and `fovy` argument are interchanged compared to the original GLM API. -pub fn perspective_lh_no(aspect: N, fovy: N, near: N, far: N) -> TMat4 { +pub fn perspective_lh_no(aspect: N, fovy: N, near: N, far: N) -> TMat4 { assert!( !relative_eq!(far - near, N::zero()), "The near-plane and far-plane must not be superimposed." @@ -547,7 +547,7 @@ pub fn perspective_lh_no(aspect: N, fovy: N, near: N, far: N) -> TMat4< /// /// # Important note /// The `aspect` and `fovy` argument are interchanged compared to the original GLM API. -pub fn perspective_lh_zo(aspect: N, fovy: N, near: N, far: N) -> TMat4 { +pub fn perspective_lh_zo(aspect: N, fovy: N, near: N, far: N) -> TMat4 { assert!( !relative_eq!(far - near, N::zero()), "The near-plane and far-plane must not be superimposed." @@ -583,7 +583,7 @@ pub fn perspective_lh_zo(aspect: N, fovy: N, near: N, far: N) -> TMat4< /// /// # Important note /// The `aspect` and `fovy` argument are interchanged compared to the original GLM API. -pub fn perspective_no(aspect: N, fovy: N, near: N, far: N) -> TMat4 { +pub fn perspective_no(aspect: N, fovy: N, near: N, far: N) -> TMat4 { perspective_rh_no(aspect, fovy, near, far) } @@ -598,7 +598,7 @@ pub fn perspective_no(aspect: N, fovy: N, near: N, far: N) -> TMat4 /// /// # Important note /// The `aspect` and `fovy` argument are interchanged compared to the original GLM API. -pub fn perspective_rh(aspect: N, fovy: N, near: N, far: N) -> TMat4 { +pub fn perspective_rh(aspect: N, fovy: N, near: N, far: N) -> TMat4 { perspective_rh_no(aspect, fovy, near, far) } @@ -613,7 +613,7 @@ pub fn perspective_rh(aspect: N, fovy: N, near: N, far: N) -> TMat4 /// /// # Important note /// The `aspect` and `fovy` argument are interchanged compared to the original GLM API. -pub fn perspective_rh_no(aspect: N, fovy: N, near: N, far: N) -> TMat4 { +pub fn perspective_rh_no(aspect: N, fovy: N, near: N, far: N) -> TMat4 { assert!( !relative_eq!(far - near, N::zero()), "The near-plane and far-plane must not be superimposed." @@ -650,7 +650,7 @@ pub fn perspective_rh_no(aspect: N, fovy: N, near: N, far: N) -> TMat4< /// /// # Important note /// The `aspect` and `fovy` argument are interchanged compared to the original GLM API. -pub fn perspective_rh_zo(aspect: N, fovy: N, near: N, far: N) -> TMat4 { +pub fn perspective_rh_zo(aspect: N, fovy: N, near: N, far: N) -> TMat4 { assert!( !relative_eq!(far - near, N::zero()), "The near-plane and far-plane must not be superimposed." @@ -687,14 +687,14 @@ pub fn perspective_rh_zo(aspect: N, fovy: N, near: N, far: N) -> TMat4< /// /// # Important note /// The `aspect` and `fovy` argument are interchanged compared to the original GLM API. -pub fn perspective_zo(aspect: N, fovy: N, near: N, far: N) -> TMat4 { +pub fn perspective_zo(aspect: N, fovy: N, near: N, far: N) -> TMat4 { perspective_rh_zo(aspect, fovy, near, far) } -//pub fn tweaked_infinite_perspective(fovy: N, aspect: N, near: N) -> TMat4 { +//pub fn tweaked_infinite_perspective(fovy: N, aspect: N, near: N) -> TMat4 { // unimplemented!() //} // -//pub fn tweaked_infinite_perspective_ep(fovy: N, aspect: N, near: N, ep: N) -> TMat4 { +//pub fn tweaked_infinite_perspective_ep(fovy: N, aspect: N, near: N, ep: N) -> TMat4 { // unimplemented!() //} diff --git a/nalgebra-glm/src/ext/matrix_projection.rs b/nalgebra-glm/src/ext/matrix_projection.rs index 8083b1eb..3048b77c 100644 --- a/nalgebra-glm/src/ext/matrix_projection.rs +++ b/nalgebra-glm/src/ext/matrix_projection.rs @@ -1,4 +1,4 @@ -use na::{self, Real, U3}; +use na::{self, RealField, U3}; use crate::aliases::{TMat4, TVec2, TVec3, TVec4}; @@ -9,7 +9,7 @@ use crate::aliases::{TMat4, TVec2, TVec3, TVec4}; /// * `center` - Specify the center of a picking region in window coordinates. /// * `delta` - Specify the width and height, respectively, of the picking region in window coordinates. /// * `viewport` - Rendering viewport. -pub fn pick_matrix(center: &TVec2, delta: &TVec2, viewport: &TVec4) -> TMat4 { +pub fn pick_matrix(center: &TVec2, delta: &TVec2, viewport: &TVec4) -> TMat4 { let shift = TVec3::new( (viewport.z - (center.x - viewport.x) * na::convert(2.0)) / delta.x, (viewport.w - (center.y - viewport.y) * na::convert(2.0)) / delta.y, @@ -41,7 +41,7 @@ pub fn pick_matrix(center: &TVec2, delta: &TVec2, viewport: &TVec /// * [`unproject`](fn.unproject.html) /// * [`unproject_no`](fn.unproject_no.html) /// * [`unproject_zo`](fn.unproject_zo.html) -pub fn project( +pub fn project( obj: &TVec3, model: &TMat4, proj: &TMat4, @@ -69,7 +69,7 @@ pub fn project( /// * [`unproject`](fn.unproject.html) /// * [`unproject_no`](fn.unproject_no.html) /// * [`unproject_zo`](fn.unproject_zo.html) -pub fn project_no( +pub fn project_no( obj: &TVec3, model: &TMat4, proj: &TMat4, @@ -98,7 +98,7 @@ pub fn project_no( /// * [`unproject`](fn.unproject.html) /// * [`unproject_no`](fn.unproject_no.html) /// * [`unproject_zo`](fn.unproject_zo.html) -pub fn project_zo( +pub fn project_zo( obj: &TVec3, model: &TMat4, proj: &TMat4, @@ -132,7 +132,7 @@ pub fn project_zo( /// * [`project_zo`](fn.project_zo.html) /// * [`unproject_no`](fn.unproject_no.html) /// * [`unproject_zo`](fn.unproject_zo.html) -pub fn unproject( +pub fn unproject( win: &TVec3, model: &TMat4, proj: &TMat4, @@ -160,7 +160,7 @@ pub fn unproject( /// * [`project_zo`](fn.project_zo.html) /// * [`unproject`](fn.unproject.html) /// * [`unproject_zo`](fn.unproject_zo.html) -pub fn unproject_no( +pub fn unproject_no( win: &TVec3, model: &TMat4, proj: &TMat4, @@ -198,7 +198,7 @@ pub fn unproject_no( /// * [`project_zo`](fn.project_zo.html) /// * [`unproject`](fn.unproject.html) /// * [`unproject_no`](fn.unproject_no.html) -pub fn unproject_zo( +pub fn unproject_zo( win: &TVec3, model: &TMat4, proj: &TMat4, diff --git a/nalgebra-glm/src/ext/matrix_transform.rs b/nalgebra-glm/src/ext/matrix_transform.rs index 8265cc19..c7f6b72d 100644 --- a/nalgebra-glm/src/ext/matrix_transform.rs +++ b/nalgebra-glm/src/ext/matrix_transform.rs @@ -1,4 +1,4 @@ -use na::{DefaultAllocator, Point3, Real, Rotation3, Unit}; +use na::{DefaultAllocator, Point3, RealField, Rotation3, Unit}; use crate::aliases::{TMat, TMat4, TVec, TVec3}; use crate::traits::{Alloc, Dimension, Number}; @@ -21,7 +21,7 @@ where DefaultAllocator: Alloc { /// /// * [`look_at_lh`](fn.look_at_lh.html) /// * [`look_at_rh`](fn.look_at_rh.html) -pub fn look_at(eye: &TVec3, center: &TVec3, up: &TVec3) -> TMat4 { +pub fn look_at(eye: &TVec3, center: &TVec3, up: &TVec3) -> TMat4 { look_at_rh(eye, center, up) } @@ -37,7 +37,7 @@ pub fn look_at(eye: &TVec3, center: &TVec3, up: &TVec3) -> TMa /// /// * [`look_at`](fn.look_at.html) /// * [`look_at_rh`](fn.look_at_rh.html) -pub fn look_at_lh(eye: &TVec3, center: &TVec3, up: &TVec3) -> TMat4 { +pub fn look_at_lh(eye: &TVec3, center: &TVec3, up: &TVec3) -> TMat4 { TMat::look_at_lh(&Point3::from(*eye), &Point3::from(*center), up) } @@ -53,7 +53,7 @@ pub fn look_at_lh(eye: &TVec3, center: &TVec3, up: &TVec3) -> /// /// * [`look_at`](fn.look_at.html) /// * [`look_at_lh`](fn.look_at_lh.html) -pub fn look_at_rh(eye: &TVec3, center: &TVec3, up: &TVec3) -> TMat4 { +pub fn look_at_rh(eye: &TVec3, center: &TVec3, up: &TVec3) -> TMat4 { TMat::look_at_rh(&Point3::from(*eye), &Point3::from(*center), up) } @@ -72,7 +72,7 @@ pub fn look_at_rh(eye: &TVec3, center: &TVec3, up: &TVec3) -> /// * [`rotate_z`](fn.rotate_z.html) /// * [`scale`](fn.scale.html) /// * [`translate`](fn.translate.html) -pub fn rotate(m: &TMat4, angle: N, axis: &TVec3) -> TMat4 { +pub fn rotate(m: &TMat4, angle: N, axis: &TVec3) -> TMat4 { m * Rotation3::from_axis_angle(&Unit::new_normalize(*axis), angle).to_homogeneous() } @@ -90,7 +90,7 @@ pub fn rotate(m: &TMat4, angle: N, axis: &TVec3) -> TMat4 { /// * [`rotate_z`](fn.rotate_z.html) /// * [`scale`](fn.scale.html) /// * [`translate`](fn.translate.html) -pub fn rotate_x(m: &TMat4, angle: N) -> TMat4 { +pub fn rotate_x(m: &TMat4, angle: N) -> TMat4 { rotate(m, angle, &TVec::x()) } @@ -108,7 +108,7 @@ pub fn rotate_x(m: &TMat4, angle: N) -> TMat4 { /// * [`rotate_z`](fn.rotate_z.html) /// * [`scale`](fn.scale.html) /// * [`translate`](fn.translate.html) -pub fn rotate_y(m: &TMat4, angle: N) -> TMat4 { +pub fn rotate_y(m: &TMat4, angle: N) -> TMat4 { rotate(m, angle, &TVec::y()) } @@ -126,7 +126,7 @@ pub fn rotate_y(m: &TMat4, angle: N) -> TMat4 { /// * [`rotate_y`](fn.rotate_y.html) /// * [`scale`](fn.scale.html) /// * [`translate`](fn.translate.html) -pub fn rotate_z(m: &TMat4, angle: N) -> TMat4 { +pub fn rotate_z(m: &TMat4, angle: N) -> TMat4 { rotate(m, angle, &TVec::z()) } diff --git a/nalgebra-glm/src/ext/quaternion_common.rs b/nalgebra-glm/src/ext/quaternion_common.rs index 29150bf6..072b57e2 100644 --- a/nalgebra-glm/src/ext/quaternion_common.rs +++ b/nalgebra-glm/src/ext/quaternion_common.rs @@ -1,36 +1,36 @@ -use na::{self, Real, Unit}; +use na::{self, RealField, Unit}; use crate::aliases::Qua; /// The conjugate of `q`. -pub fn quat_conjugate(q: &Qua) -> Qua { +pub fn quat_conjugate(q: &Qua) -> Qua { q.conjugate() } /// The inverse of `q`. -pub fn quat_inverse(q: &Qua) -> Qua { +pub fn quat_inverse(q: &Qua) -> Qua { q.try_inverse().unwrap_or_else(na::zero) } -//pub fn quat_isinf(x: &Qua) -> TVec { +//pub fn quat_isinf(x: &Qua) -> TVec { // x.coords.map(|e| e.is_inf()) //} -//pub fn quat_isnan(x: &Qua) -> TVec { +//pub fn quat_isnan(x: &Qua) -> TVec { // x.coords.map(|e| e.is_nan()) //} /// Interpolate linearly between `x` and `y`. -pub fn quat_lerp(x: &Qua, y: &Qua, a: N) -> Qua { +pub fn quat_lerp(x: &Qua, y: &Qua, a: N) -> Qua { x.lerp(y, a) } -//pub fn quat_mix(x: &Qua, y: &Qua, a: N) -> Qua { +//pub fn quat_mix(x: &Qua, y: &Qua, a: N) -> Qua { // x * (N::one() - a) + y * a //} /// Interpolate spherically between `x` and `y`. -pub fn quat_slerp(x: &Qua, y: &Qua, a: N) -> Qua { +pub fn quat_slerp(x: &Qua, y: &Qua, a: N) -> Qua { Unit::new_normalize(*x) .slerp(&Unit::new_normalize(*y), a) .into_inner() diff --git a/nalgebra-glm/src/ext/quaternion_geometric.rs b/nalgebra-glm/src/ext/quaternion_geometric.rs index 29356869..24d9310d 100644 --- a/nalgebra-glm/src/ext/quaternion_geometric.rs +++ b/nalgebra-glm/src/ext/quaternion_geometric.rs @@ -1,28 +1,28 @@ -use na::Real; +use na::RealField; use crate::aliases::Qua; /// Multiplies two quaternions. -pub fn quat_cross(q1: &Qua, q2: &Qua) -> Qua { +pub fn quat_cross(q1: &Qua, q2: &Qua) -> Qua { q1 * q2 } /// The scalar product of two quaternions. -pub fn quat_dot(x: &Qua, y: &Qua) -> N { +pub fn quat_dot(x: &Qua, y: &Qua) -> N { x.dot(y) } /// The magnitude of the quaternion `q`. -pub fn quat_length(q: &Qua) -> N { +pub fn quat_length(q: &Qua) -> N { q.norm() } /// The magnitude of the quaternion `q`. -pub fn quat_magnitude(q: &Qua) -> N { +pub fn quat_magnitude(q: &Qua) -> N { q.norm() } /// Normalizes the quaternion `q`. -pub fn quat_normalize(q: &Qua) -> Qua { +pub fn quat_normalize(q: &Qua) -> Qua { q.normalize() } diff --git a/nalgebra-glm/src/ext/quaternion_relational.rs b/nalgebra-glm/src/ext/quaternion_relational.rs index ff4c6b01..bd24edbe 100644 --- a/nalgebra-glm/src/ext/quaternion_relational.rs +++ b/nalgebra-glm/src/ext/quaternion_relational.rs @@ -1,23 +1,23 @@ -use na::{Real, U4}; +use na::{RealField, U4}; use crate::aliases::{Qua, TVec}; /// Component-wise equality comparison between two quaternions. -pub fn quat_equal(x: &Qua, y: &Qua) -> TVec { +pub fn quat_equal(x: &Qua, y: &Qua) -> TVec { crate::equal(&x.coords, &y.coords) } /// Component-wise approximate equality comparison between two quaternions. -pub fn quat_equal_eps(x: &Qua, y: &Qua, epsilon: N) -> TVec { +pub fn quat_equal_eps(x: &Qua, y: &Qua, epsilon: N) -> TVec { crate::equal_eps(&x.coords, &y.coords, epsilon) } /// Component-wise non-equality comparison between two quaternions. -pub fn quat_not_equal(x: &Qua, y: &Qua) -> TVec { +pub fn quat_not_equal(x: &Qua, y: &Qua) -> TVec { crate::not_equal(&x.coords, &y.coords) } /// Component-wise approximate non-equality comparison between two quaternions. -pub fn quat_not_equal_eps(x: &Qua, y: &Qua, epsilon: N) -> TVec { +pub fn quat_not_equal_eps(x: &Qua, y: &Qua, epsilon: N) -> TVec { crate::not_equal_eps(&x.coords, &y.coords, epsilon) } diff --git a/nalgebra-glm/src/ext/quaternion_transform.rs b/nalgebra-glm/src/ext/quaternion_transform.rs index 4f3f4211..1e4e9771 100644 --- a/nalgebra-glm/src/ext/quaternion_transform.rs +++ b/nalgebra-glm/src/ext/quaternion_transform.rs @@ -1,27 +1,27 @@ -use na::{Real, Unit, UnitQuaternion}; +use na::{RealField, Unit, UnitQuaternion}; use crate::aliases::{Qua, TVec3}; /// Computes the quaternion exponential. -pub fn quat_exp(q: &Qua) -> Qua { +pub fn quat_exp(q: &Qua) -> Qua { q.exp() } /// Computes the quaternion logarithm. -pub fn quat_log(q: &Qua) -> Qua { +pub fn quat_log(q: &Qua) -> Qua { q.ln() } /// Raises the quaternion `q` to the power `y`. -pub fn quat_pow(q: &Qua, y: N) -> Qua { +pub fn quat_pow(q: &Qua, y: N) -> Qua { q.powf(y) } /// Builds a quaternion from an axis and an angle, and right-multiply it to the quaternion `q`. -pub fn quat_rotate(q: &Qua, angle: N, axis: &TVec3) -> Qua { +pub fn quat_rotate(q: &Qua, angle: N, axis: &TVec3) -> Qua { q * UnitQuaternion::from_axis_angle(&Unit::new_normalize(*axis), angle).into_inner() } -//pub fn quat_sqrt(q: &Qua) -> Qua { +//pub fn quat_sqrt(q: &Qua) -> Qua { // unimplemented!() //} diff --git a/nalgebra-glm/src/ext/quaternion_trigonometric.rs b/nalgebra-glm/src/ext/quaternion_trigonometric.rs index 42833f05..a711e69a 100644 --- a/nalgebra-glm/src/ext/quaternion_trigonometric.rs +++ b/nalgebra-glm/src/ext/quaternion_trigonometric.rs @@ -1,19 +1,19 @@ -use na::{Real, Unit, UnitQuaternion}; +use na::{RealField, Unit, UnitQuaternion}; use crate::aliases::{Qua, TVec3}; /// The rotation angle of this quaternion assumed to be normalized. -pub fn quat_angle(x: &Qua) -> N { +pub fn quat_angle(x: &Qua) -> N { UnitQuaternion::from_quaternion(*x).angle() } /// Creates a quaternion from an axis and an angle. -pub fn quat_angle_axis(angle: N, axis: &TVec3) -> Qua { +pub fn quat_angle_axis(angle: N, axis: &TVec3) -> Qua { UnitQuaternion::from_axis_angle(&Unit::new_normalize(*axis), angle).into_inner() } /// The rotation axis of a quaternion assumed to be normalized. -pub fn quat_axis(x: &Qua) -> TVec3 { +pub fn quat_axis(x: &Qua) -> TVec3 { if let Some(a) = UnitQuaternion::from_quaternion(*x).axis() { a.into_inner() } else { diff --git a/nalgebra-glm/src/ext/scalar_constants.rs b/nalgebra-glm/src/ext/scalar_constants.rs index 2b9ed14d..e0741465 100644 --- a/nalgebra-glm/src/ext/scalar_constants.rs +++ b/nalgebra-glm/src/ext/scalar_constants.rs @@ -1,5 +1,5 @@ use approx::AbsDiffEq; -use na::Real; +use na::RealField; /// Default epsilon value used for approximate comparison. pub fn epsilon>() -> N { @@ -22,6 +22,6 @@ pub fn epsilon>() -> N { /// * [`two_over_pi`](fn.two_over_pi.html) /// * [`two_over_root_pi`](fn.two_over_root_pi.html) /// * [`two_pi`](fn.two_pi.html) -pub fn pi() -> N { +pub fn pi() -> N { N::pi() } diff --git a/nalgebra-glm/src/geometric.rs b/nalgebra-glm/src/geometric.rs index a0706f75..ffdc825a 100644 --- a/nalgebra-glm/src/geometric.rs +++ b/nalgebra-glm/src/geometric.rs @@ -1,4 +1,4 @@ -use na::{DefaultAllocator, Real}; +use na::{DefaultAllocator, RealField}; use crate::aliases::{TVec, TVec3}; use crate::traits::{Alloc, Dimension, Number}; @@ -13,7 +13,7 @@ pub fn cross(x: &TVec3, y: &TVec3) -> TVec3 { /// # See also: /// /// * [`distance2`](fn.distance2.html) -pub fn distance(p0: &TVec, p1: &TVec) -> N +pub fn distance(p0: &TVec, p1: &TVec) -> N where DefaultAllocator: Alloc { (p1 - p0).norm() } @@ -49,7 +49,7 @@ where /// * [`length2`](fn.length2.html) /// * [`magnitude`](fn.magnitude.html) /// * [`magnitude2`](fn.magnitude2.html) -pub fn length(x: &TVec) -> N +pub fn length(x: &TVec) -> N where DefaultAllocator: Alloc { x.norm() } @@ -63,13 +63,13 @@ where DefaultAllocator: Alloc { /// * [`length`](fn.length.html) /// * [`magnitude2`](fn.magnitude2.html) /// * [`nalgebra::norm`](../nalgebra/fn.norm.html) -pub fn magnitude(x: &TVec) -> N +pub fn magnitude(x: &TVec) -> N where DefaultAllocator: Alloc { x.norm() } /// Normalizes a vector. -pub fn normalize(x: &TVec) -> TVec +pub fn normalize(x: &TVec) -> TVec where DefaultAllocator: Alloc { x.normalize() } @@ -82,7 +82,7 @@ where DefaultAllocator: Alloc { } /// For the incident vector `i` and surface normal `n`, and the ratio of indices of refraction `eta`, return the refraction vector. -pub fn refract_vec(i: &TVec, n: &TVec, eta: N) -> TVec +pub fn refract_vec(i: &TVec, n: &TVec, eta: N) -> TVec where DefaultAllocator: Alloc { let ni = n.dot(i); let k = N::one() - eta * eta * (N::one() - ni * ni); diff --git a/nalgebra-glm/src/gtc/constants.rs b/nalgebra-glm/src/gtc/constants.rs index 9407cf29..4112d65e 100644 --- a/nalgebra-glm/src/gtc/constants.rs +++ b/nalgebra-glm/src/gtc/constants.rs @@ -1,14 +1,14 @@ -use na::{self, Real}; +use na::{self, RealField}; /// The Euler constant. /// /// This is a shorthand alias for [`euler`](fn.euler.html). -pub fn e() -> N { +pub fn e() -> N { N::e() } /// The Euler constant. -pub fn euler() -> N { +pub fn euler() -> N { N::e() } @@ -28,12 +28,12 @@ pub fn euler() -> N { /// * [`two_over_pi`](fn.two_over_pi.html) /// * [`two_over_root_pi`](fn.two_over_root_pi.html) /// * [`two_pi`](fn.two_pi.html) -pub fn four_over_pi() -> N { +pub fn four_over_pi() -> N { na::convert::<_, N>(4.0) / N::pi() } /// Returns the golden ratio. -pub fn golden_ratio() -> N { +pub fn golden_ratio() -> N { (N::one() + root_five()) / na::convert(2.0) } @@ -53,7 +53,7 @@ pub fn golden_ratio() -> N { /// * [`two_over_pi`](fn.two_over_pi.html) /// * [`two_over_root_pi`](fn.two_over_root_pi.html) /// * [`two_pi`](fn.two_pi.html) -pub fn half_pi() -> N { +pub fn half_pi() -> N { N::frac_pi_2() } @@ -63,7 +63,7 @@ pub fn half_pi() -> N { /// /// * [`ln_ten`](fn.ln_ten.html) /// * [`ln_two`](fn.ln_two.html) -pub fn ln_ln_two() -> N { +pub fn ln_ln_two() -> N { N::ln_2().ln() } @@ -73,7 +73,7 @@ pub fn ln_ln_two() -> N { /// /// * [`ln_ln_two`](fn.ln_ln_two.html) /// * [`ln_two`](fn.ln_two.html) -pub fn ln_ten() -> N { +pub fn ln_ten() -> N { N::ln_10() } @@ -83,7 +83,7 @@ pub fn ln_ten() -> N { /// /// * [`ln_ln_two`](fn.ln_ln_two.html) /// * [`ln_ten`](fn.ln_ten.html) -pub fn ln_two() -> N { +pub fn ln_two() -> N { N::ln_2() } @@ -106,12 +106,12 @@ pub use na::one; /// * [`two_over_pi`](fn.two_over_pi.html) /// * [`two_over_root_pi`](fn.two_over_root_pi.html) /// * [`two_pi`](fn.two_pi.html) -pub fn one_over_pi() -> N { +pub fn one_over_pi() -> N { N::frac_1_pi() } /// Returns `1 / sqrt(2)`. -pub fn one_over_root_two() -> N { +pub fn one_over_root_two() -> N { N::one() / root_two() } @@ -131,7 +131,7 @@ pub fn one_over_root_two() -> N { /// * [`two_over_pi`](fn.two_over_pi.html) /// * [`two_over_root_pi`](fn.two_over_root_pi.html) /// * [`two_pi`](fn.two_pi.html) -pub fn one_over_two_pi() -> N { +pub fn one_over_two_pi() -> N { N::frac_1_pi() * na::convert(0.5) } @@ -151,7 +151,7 @@ pub fn one_over_two_pi() -> N { /// * [`two_over_pi`](fn.two_over_pi.html) /// * [`two_over_root_pi`](fn.two_over_root_pi.html) /// * [`two_pi`](fn.two_pi.html) -pub fn quarter_pi() -> N { +pub fn quarter_pi() -> N { N::frac_pi_4() } @@ -161,7 +161,7 @@ pub fn quarter_pi() -> N { /// /// * [`root_three`](fn.root_three.html) /// * [`root_two`](fn.root_two.html) -pub fn root_five() -> N { +pub fn root_five() -> N { na::convert::<_, N>(5.0).sqrt() } @@ -181,12 +181,12 @@ pub fn root_five() -> N { /// * [`two_over_pi`](fn.two_over_pi.html) /// * [`two_over_root_pi`](fn.two_over_root_pi.html) /// * [`two_pi`](fn.two_pi.html) -pub fn root_half_pi() -> N { +pub fn root_half_pi() -> N { (N::pi() / na::convert(2.0)).sqrt() } /// Returns `sqrt(ln(4))`. -pub fn root_ln_four() -> N { +pub fn root_ln_four() -> N { na::convert::<_, N>(4.0).ln().sqrt() } @@ -206,7 +206,7 @@ pub fn root_ln_four() -> N { /// * [`two_over_pi`](fn.two_over_pi.html) /// * [`two_over_root_pi`](fn.two_over_root_pi.html) /// * [`two_pi`](fn.two_pi.html) -pub fn root_pi() -> N { +pub fn root_pi() -> N { N::pi().sqrt() } @@ -216,7 +216,7 @@ pub fn root_pi() -> N { /// /// * [`root_five`](fn.root_five.html) /// * [`root_two`](fn.root_two.html) -pub fn root_three() -> N { +pub fn root_three() -> N { na::convert::<_, N>(3.0).sqrt() } @@ -226,8 +226,8 @@ pub fn root_three() -> N { /// /// * [`root_five`](fn.root_five.html) /// * [`root_three`](fn.root_three.html) -pub fn root_two() -> N { - // FIXME: there should be a crate::sqrt_2() on the Real trait. +pub fn root_two() -> N { + // FIXME: there should be a crate::sqrt_2() on the RealField trait. na::convert::<_, N>(2.0).sqrt() } @@ -247,7 +247,7 @@ pub fn root_two() -> N { /// * [`two_over_pi`](fn.two_over_pi.html) /// * [`two_over_root_pi`](fn.two_over_root_pi.html) /// * [`two_pi`](fn.two_pi.html) -pub fn root_two_pi() -> N { +pub fn root_two_pi() -> N { N::two_pi().sqrt() } @@ -256,7 +256,7 @@ pub fn root_two_pi() -> N { /// # See also: /// /// * [`two_thirds`](fn.two_thirds.html) -pub fn third() -> N { +pub fn third() -> N { na::convert(1.0 / 3.0) } @@ -276,7 +276,7 @@ pub fn third() -> N { /// * [`two_over_pi`](fn.two_over_pi.html) /// * [`two_over_root_pi`](fn.two_over_root_pi.html) /// * [`two_pi`](fn.two_pi.html) -pub fn three_over_two_pi() -> N { +pub fn three_over_two_pi() -> N { na::convert::<_, N>(3.0) / N::two_pi() } @@ -295,7 +295,7 @@ pub fn three_over_two_pi() -> N { /// * [`three_over_two_pi`](fn.three_over_two_pi.html) /// * [`two_over_root_pi`](fn.two_over_root_pi.html) /// * [`two_pi`](fn.two_pi.html) -pub fn two_over_pi() -> N { +pub fn two_over_pi() -> N { N::frac_2_pi() } @@ -315,7 +315,7 @@ pub fn two_over_pi() -> N { /// * [`three_over_two_pi`](fn.three_over_two_pi.html) /// * [`two_over_pi`](fn.two_over_pi.html) /// * [`two_pi`](fn.two_pi.html) -pub fn two_over_root_pi() -> N { +pub fn two_over_root_pi() -> N { N::frac_2_sqrt_pi() } @@ -335,7 +335,7 @@ pub fn two_over_root_pi() -> N { /// * [`three_over_two_pi`](fn.three_over_two_pi.html) /// * [`two_over_pi`](fn.two_over_pi.html) /// * [`two_over_root_pi`](fn.two_over_root_pi.html) -pub fn two_pi() -> N { +pub fn two_pi() -> N { N::two_pi() } @@ -344,7 +344,7 @@ pub fn two_pi() -> N { /// # See also: /// /// * [`third`](fn.third.html) -pub fn two_thirds() -> N { +pub fn two_thirds() -> N { na::convert(2.0 / 3.0) } diff --git a/nalgebra-glm/src/gtc/matrix_inverse.rs b/nalgebra-glm/src/gtc/matrix_inverse.rs index ca390bb9..eab0b995 100644 --- a/nalgebra-glm/src/gtc/matrix_inverse.rs +++ b/nalgebra-glm/src/gtc/matrix_inverse.rs @@ -1,17 +1,17 @@ -use na::{DefaultAllocator, Real}; +use na::{DefaultAllocator, RealField}; use crate::aliases::TMat; use crate::traits::{Alloc, Dimension}; /// Fast matrix inverse for affine matrix. -pub fn affine_inverse(m: TMat) -> TMat +pub fn affine_inverse(m: TMat) -> TMat where DefaultAllocator: Alloc { // FIXME: this should be optimized. m.try_inverse().unwrap_or_else(TMat::<_, D, D>::zeros) } /// Compute the transpose of the inverse of a matrix. -pub fn inverse_transpose(m: TMat) -> TMat +pub fn inverse_transpose(m: TMat) -> TMat where DefaultAllocator: Alloc { m.try_inverse() .unwrap_or_else(TMat::<_, D, D>::zeros) diff --git a/nalgebra-glm/src/gtc/packing.rs b/nalgebra-glm/src/gtc/packing.rs index ab6019b3..ea5acac4 100644 --- a/nalgebra-glm/src/gtc/packing.rs +++ b/nalgebra-glm/src/gtc/packing.rs @@ -1,4 +1,4 @@ -use na::{Scalar, Real, DefaultAllocator, U3, U4}; +use na::{Scalar, RealField, DefaultAllocator, U3, U4}; use crate::traits::{Alloc, Dimension}; use crate::aliases::*; @@ -53,7 +53,7 @@ pub fn packRGBM(rgb: &TVec3) -> TVec4 { unimplemented!() } -pub fn packSnorm(v: TVec) -> TVec +pub fn packSnorm(v: TVec) -> TVec where DefaultAllocator: Alloc + Alloc { unimplemented!() } @@ -102,7 +102,7 @@ pub fn packUint4x8(v: &U8Vec4) -> i32 { unimplemented!() } -pub fn packUnorm(v: &TVec) -> TVec +pub fn packUnorm(v: &TVec) -> TVec where DefaultAllocator: Alloc + Alloc { unimplemented!() } @@ -196,7 +196,7 @@ pub fn unpackRGBM(rgbm: &TVec4) -> TVec3 { unimplemented!() } -pub fn unpackSnorm(v: &TVec) -> TVec +pub fn unpackSnorm(v: &TVec) -> TVec where DefaultAllocator: Alloc + Alloc { unimplemented!() } @@ -245,7 +245,7 @@ pub fn unpackUint4x8(p: i32) -> U8Vec4 { unimplemented!() } -pub fn unpackUnorm(v: &TVec) -> TVec +pub fn unpackUnorm(v: &TVec) -> TVec where DefaultAllocator: Alloc + Alloc { unimplemented!() } diff --git a/nalgebra-glm/src/gtc/quaternion.rs b/nalgebra-glm/src/gtc/quaternion.rs index 9322ec0a..36977e96 100644 --- a/nalgebra-glm/src/gtc/quaternion.rs +++ b/nalgebra-glm/src/gtc/quaternion.rs @@ -1,36 +1,36 @@ -use na::{Real, UnitQuaternion, U4}; +use na::{RealField, UnitQuaternion, U4}; use crate::aliases::{Qua, TMat4, TVec, TVec3}; /// Euler angles of the quaternion `q` as (pitch, yaw, roll). -pub fn quat_euler_angles(x: &Qua) -> TVec3 { +pub fn quat_euler_angles(x: &Qua) -> TVec3 { let q = UnitQuaternion::new_unchecked(*x); let a = q.euler_angles(); TVec3::new(a.2, a.1, a.0) } /// Component-wise `>` comparison between two quaternions. -pub fn quat_greater_than(x: &Qua, y: &Qua) -> TVec { +pub fn quat_greater_than(x: &Qua, y: &Qua) -> TVec { crate::greater_than(&x.coords, &y.coords) } /// Component-wise `>=` comparison between two quaternions. -pub fn quat_greater_than_equal(x: &Qua, y: &Qua) -> TVec { +pub fn quat_greater_than_equal(x: &Qua, y: &Qua) -> TVec { crate::greater_than_equal(&x.coords, &y.coords) } /// Component-wise `<` comparison between two quaternions. -pub fn quat_less_than(x: &Qua, y: &Qua) -> TVec { +pub fn quat_less_than(x: &Qua, y: &Qua) -> TVec { crate::less_than(&x.coords, &y.coords) } /// Component-wise `<=` comparison between two quaternions. -pub fn quat_less_than_equal(x: &Qua, y: &Qua) -> TVec { +pub fn quat_less_than_equal(x: &Qua, y: &Qua) -> TVec { crate::less_than_equal(&x.coords, &y.coords) } /// Convert a quaternion to a rotation matrix in homogeneous coordinates. -pub fn quat_cast(x: &Qua) -> TMat4 { +pub fn quat_cast(x: &Qua) -> TMat4 { crate::quat_to_mat4(x) } @@ -41,34 +41,34 @@ pub fn quat_cast(x: &Qua) -> TMat4 { /// * `direction` - Direction vector point at where to look /// * `up` - Object up vector /// -pub fn quat_look_at(direction: &TVec3, up: &TVec3) -> Qua { +pub fn quat_look_at(direction: &TVec3, up: &TVec3) -> Qua { quat_look_at_rh(direction, up) } /// Computes a left-handed look-at quaternion (equivalent to a left-handed look-at matrix). -pub fn quat_look_at_lh(direction: &TVec3, up: &TVec3) -> Qua { +pub fn quat_look_at_lh(direction: &TVec3, up: &TVec3) -> Qua { UnitQuaternion::look_at_lh(direction, up).into_inner() } /// Computes a right-handed look-at quaternion (equivalent to a right-handed look-at matrix). -pub fn quat_look_at_rh(direction: &TVec3, up: &TVec3) -> Qua { +pub fn quat_look_at_rh(direction: &TVec3, up: &TVec3) -> Qua { UnitQuaternion::look_at_rh(direction, up).into_inner() } /// The "roll" Euler angle of the quaternion `x` assumed to be normalized. -pub fn quat_roll(x: &Qua) -> N { +pub fn quat_roll(x: &Qua) -> N { // FIXME: optimize this. quat_euler_angles(x).z } /// The "yaw" Euler angle of the quaternion `x` assumed to be normalized. -pub fn quat_yaw(x: &Qua) -> N { +pub fn quat_yaw(x: &Qua) -> N { // FIXME: optimize this. quat_euler_angles(x).y } /// The "pitch" Euler angle of the quaternion `x` assumed to be normalized. -pub fn quat_pitch(x: &Qua) -> N { +pub fn quat_pitch(x: &Qua) -> N { // FIXME: optimize this. quat_euler_angles(x).x } diff --git a/nalgebra-glm/src/gtc/round.rs b/nalgebra-glm/src/gtc/round.rs index 8dde578d..5ad95780 100644 --- a/nalgebra-glm/src/gtc/round.rs +++ b/nalgebra-glm/src/gtc/round.rs @@ -1,4 +1,4 @@ -use na::{Scalar, Real, U3, DefaultAllocator}; +use na::{Scalar, RealField, U3, DefaultAllocator}; use crate::traits::{Number, Alloc, Dimension}; use crate::aliases::TVec; diff --git a/nalgebra-glm/src/gtc/type_ptr.rs b/nalgebra-glm/src/gtc/type_ptr.rs index 48ef9da5..4029bf01 100644 --- a/nalgebra-glm/src/gtc/type_ptr.rs +++ b/nalgebra-glm/src/gtc/type_ptr.rs @@ -1,4 +1,4 @@ -use na::{DefaultAllocator, Quaternion, Real, Scalar}; +use na::{DefaultAllocator, Quaternion, RealField, Scalar}; use crate::aliases::{ Qua, TMat, TMat2, TMat2x3, TMat2x4, TMat3, TMat3x2, TMat3x4, TMat4, TMat4x2, TMat4x3, TVec1, @@ -112,7 +112,7 @@ pub fn mat4_to_mat2(m: &TMat4) -> TMat2 { } /// Creates a quaternion from a slice arranged as `[x, y, z, w]`. -pub fn make_quat(ptr: &[N]) -> Qua { +pub fn make_quat(ptr: &[N]) -> Qua { Quaternion::from(TVec4::from_column_slice(ptr)) } diff --git a/nalgebra-glm/src/gtx/euler_angles.rs b/nalgebra-glm/src/gtx/euler_angles.rs index 30be40bf..c9d16738 100644 --- a/nalgebra-glm/src/gtx/euler_angles.rs +++ b/nalgebra-glm/src/gtx/euler_angles.rs @@ -1,163 +1,163 @@ -use na::{Real, U3, U4}; +use na::{RealField, U3, U4}; use crate::aliases::{TVec, TMat}; -pub fn derivedEulerAngleX(angleX: N, angularVelocityX: N) -> TMat4 { +pub fn derivedEulerAngleX(angleX: N, angularVelocityX: N) -> TMat4 { unimplemented!() } -pub fn derivedEulerAngleY(angleY: N, angularVelocityY: N) -> TMat4 { +pub fn derivedEulerAngleY(angleY: N, angularVelocityY: N) -> TMat4 { unimplemented!() } -pub fn derivedEulerAngleZ(angleZ: N, angularVelocityZ: N) -> TMat4 { +pub fn derivedEulerAngleZ(angleZ: N, angularVelocityZ: N) -> TMat4 { unimplemented!() } -pub fn eulerAngleX(angleX: N) -> TMat4 { +pub fn eulerAngleX(angleX: N) -> TMat4 { unimplemented!() } -pub fn eulerAngleXY(angleX: N, angleY: N) -> TMat4 { +pub fn eulerAngleXY(angleX: N, angleY: N) -> TMat4 { unimplemented!() } -pub fn eulerAngleXYX(t1: N, t2: N, t3: N) -> TMat4 { +pub fn eulerAngleXYX(t1: N, t2: N, t3: N) -> TMat4 { unimplemented!() } -pub fn eulerAngleXYZ(t1: N, t2: N, t3: N) -> TMat4 { +pub fn eulerAngleXYZ(t1: N, t2: N, t3: N) -> TMat4 { unimplemented!() } -pub fn eulerAngleXZ(angleX: N, angleZ: N) -> TMat4 { +pub fn eulerAngleXZ(angleX: N, angleZ: N) -> TMat4 { unimplemented!() } -pub fn eulerAngleXZX(t1: N, t2: N, t3: N) -> TMat4 { +pub fn eulerAngleXZX(t1: N, t2: N, t3: N) -> TMat4 { unimplemented!() } -pub fn eulerAngleXZY(t1: N, t2: N, t3: N) -> TMat4 { +pub fn eulerAngleXZY(t1: N, t2: N, t3: N) -> TMat4 { unimplemented!() } -pub fn eulerAngleY(angleY: N) -> TMat4 { +pub fn eulerAngleY(angleY: N) -> TMat4 { unimplemented!() } -pub fn eulerAngleYX(angleY: N, angleX: N) -> TMat4 { +pub fn eulerAngleYX(angleY: N, angleX: N) -> TMat4 { unimplemented!() } -pub fn eulerAngleYXY(t1: N, t2: N, t3: N) -> TMat4 { +pub fn eulerAngleYXY(t1: N, t2: N, t3: N) -> TMat4 { unimplemented!() } -pub fn eulerAngleYXZ(yaw: N, pitch: N, roll: N) -> TMat4 { +pub fn eulerAngleYXZ(yaw: N, pitch: N, roll: N) -> TMat4 { unimplemented!() } -pub fn eulerAngleYZ(angleY: N, angleZ: N) -> TMat4 { +pub fn eulerAngleYZ(angleY: N, angleZ: N) -> TMat4 { unimplemented!() } -pub fn eulerAngleYZX(t1: N, t2: N, t3: N) -> TMat4 { +pub fn eulerAngleYZX(t1: N, t2: N, t3: N) -> TMat4 { unimplemented!() } -pub fn eulerAngleYZY(t1: N, t2: N, t3: N) -> TMat4 { +pub fn eulerAngleYZY(t1: N, t2: N, t3: N) -> TMat4 { unimplemented!() } -pub fn eulerAngleZ(angleZ: N) -> TMat4 { +pub fn eulerAngleZ(angleZ: N) -> TMat4 { unimplemented!() } -pub fn eulerAngleZX(angle: N, angleX: N) -> TMat4 { +pub fn eulerAngleZX(angle: N, angleX: N) -> TMat4 { unimplemented!() } -pub fn eulerAngleZXY(t1: N, t2: N, t3: N) -> TMat4 { +pub fn eulerAngleZXY(t1: N, t2: N, t3: N) -> TMat4 { unimplemented!() } -pub fn eulerAngleZXZ(t1: N, t2: N, t3: N) -> TMat4 { +pub fn eulerAngleZXZ(t1: N, t2: N, t3: N) -> TMat4 { unimplemented!() } -pub fn eulerAngleZY(angleZ: N, angleY: N) -> TMat4 { +pub fn eulerAngleZY(angleZ: N, angleY: N) -> TMat4 { unimplemented!() } -pub fn eulerAngleZYX(t1: N, t2: N, t3: N) -> TMat4 { +pub fn eulerAngleZYX(t1: N, t2: N, t3: N) -> TMat4 { unimplemented!() } -pub fn eulerAngleZYZ(t1: N, t2: N, t3: N) -> TMat4 { +pub fn eulerAngleZYZ(t1: N, t2: N, t3: N) -> TMat4 { unimplemented!() } -pub fn extractEulerAngleXYX(M: &TMat4) -> (N, N, N) { +pub fn extractEulerAngleXYX(M: &TMat4) -> (N, N, N) { unimplemented!() } -pub fn extractEulerAngleXYZ(M: &TMat4) -> (N, N, N) { +pub fn extractEulerAngleXYZ(M: &TMat4) -> (N, N, N) { unimplemented!() } -pub fn extractEulerAngleXZX(M: &TMat4) -> (N, N, N) { +pub fn extractEulerAngleXZX(M: &TMat4) -> (N, N, N) { unimplemented!() } -pub fn extractEulerAngleXZY(M: &TMat4) -> (N, N, N) { +pub fn extractEulerAngleXZY(M: &TMat4) -> (N, N, N) { unimplemented!() } -pub fn extractEulerAngleYXY(M: &TMat4) -> (N, N, N) { +pub fn extractEulerAngleYXY(M: &TMat4) -> (N, N, N) { unimplemented!() } -pub fn extractEulerAngleYXZ(M: &TMat4) -> (N, N, N) { +pub fn extractEulerAngleYXZ(M: &TMat4) -> (N, N, N) { unimplemented!() } -pub fn extractEulerAngleYZX(M: &TMat4) -> (N, N, N) { +pub fn extractEulerAngleYZX(M: &TMat4) -> (N, N, N) { unimplemented!() } -pub fn extractEulerAngleYZY(M: &TMat4) -> (N, N, N) { +pub fn extractEulerAngleYZY(M: &TMat4) -> (N, N, N) { unimplemented!() } -pub fn extractEulerAngleZXY(M: &TMat4) -> (N, N, N) { +pub fn extractEulerAngleZXY(M: &TMat4) -> (N, N, N) { unimplemented!() } -pub fn extractEulerAngleZXZ(M: &TMat4) -> (N, N, N) { +pub fn extractEulerAngleZXZ(M: &TMat4) -> (N, N, N) { unimplemented!() } -pub fn extractEulerAngleZYX(M: &TMat4) -> (N, N, N) { +pub fn extractEulerAngleZYX(M: &TMat4) -> (N, N, N) { unimplemented!() } -pub fn extractEulerAngleZYZ(M: &TMat4) -> (N, N, N) { +pub fn extractEulerAngleZYZ(M: &TMat4) -> (N, N, N) { unimplemented!() } -pub fn orientate2(angle: N) -> TMat3x3 { +pub fn orientate2(angle: N) -> TMat3x3 { unimplemented!() } -pub fn orientate3(angles: TVec3) -> TMat3x3 { +pub fn orientate3(angles: TVec3) -> TMat3x3 { unimplemented!() } -pub fn orientate4(angles: TVec3) -> TMat4 { +pub fn orientate4(angles: TVec3) -> TMat4 { unimplemented!() } -pub fn yawPitchRoll(yaw: N, pitch: N, roll: N) -> TMat4 { +pub fn yawPitchRoll(yaw: N, pitch: N, roll: N) -> TMat4 { unimplemented!() } diff --git a/nalgebra-glm/src/gtx/matrix_cross_product.rs b/nalgebra-glm/src/gtx/matrix_cross_product.rs index ac113e42..40aa03e8 100644 --- a/nalgebra-glm/src/gtx/matrix_cross_product.rs +++ b/nalgebra-glm/src/gtx/matrix_cross_product.rs @@ -1,4 +1,4 @@ -use na::Real; +use na::RealField; use crate::aliases::{TMat3, TMat4, TVec3}; @@ -7,7 +7,7 @@ use crate::aliases::{TMat3, TMat4, TVec3}; /// # See also: /// /// * [`matrix_cross`](fn.matrix_cross.html) -pub fn matrix_cross3(x: &TVec3) -> TMat3 { +pub fn matrix_cross3(x: &TVec3) -> TMat3 { x.cross_matrix() } @@ -16,6 +16,6 @@ pub fn matrix_cross3(x: &TVec3) -> TMat3 { /// # See also: /// /// * [`matrix_cross3`](fn.matrix_cross3.html) -pub fn matrix_cross(x: &TVec3) -> TMat4 { +pub fn matrix_cross(x: &TVec3) -> TMat4 { crate::mat3_to_mat4(&x.cross_matrix()) } diff --git a/nalgebra-glm/src/gtx/norm.rs b/nalgebra-glm/src/gtx/norm.rs index 4450cdff..9332c010 100644 --- a/nalgebra-glm/src/gtx/norm.rs +++ b/nalgebra-glm/src/gtx/norm.rs @@ -1,4 +1,4 @@ -use na::{DefaultAllocator, Real}; +use na::{DefaultAllocator, RealField}; use crate::aliases::TVec; use crate::traits::{Alloc, Dimension}; @@ -8,7 +8,7 @@ use crate::traits::{Alloc, Dimension}; /// # See also: /// /// * [`distance`](fn.distance.html) -pub fn distance2(p0: &TVec, p1: &TVec) -> N +pub fn distance2(p0: &TVec, p1: &TVec) -> N where DefaultAllocator: Alloc { (p1 - p0).norm_squared() } @@ -20,7 +20,7 @@ where DefaultAllocator: Alloc { /// * [`l1_norm`](fn.l1_norm.html) /// * [`l2_distance`](fn.l2_distance.html) /// * [`l2_norm`](fn.l2_norm.html) -pub fn l1_distance(x: &TVec, y: &TVec) -> N +pub fn l1_distance(x: &TVec, y: &TVec) -> N where DefaultAllocator: Alloc { l1_norm(&(y - x)) } @@ -35,7 +35,7 @@ where DefaultAllocator: Alloc { /// * [`l1_distance`](fn.l1_distance.html) /// * [`l2_distance`](fn.l2_distance.html) /// * [`l2_norm`](fn.l2_norm.html) -pub fn l1_norm(v: &TVec) -> N +pub fn l1_norm(v: &TVec) -> N where DefaultAllocator: Alloc { crate::comp_add(&v.abs()) } @@ -54,7 +54,7 @@ where DefaultAllocator: Alloc { /// * [`length2`](fn.length2.html) /// * [`magnitude`](fn.magnitude.html) /// * [`magnitude2`](fn.magnitude2.html) -pub fn l2_distance(x: &TVec, y: &TVec) -> N +pub fn l2_distance(x: &TVec, y: &TVec) -> N where DefaultAllocator: Alloc { l2_norm(&(y - x)) } @@ -75,7 +75,7 @@ where DefaultAllocator: Alloc { /// * [`length2`](fn.length2.html) /// * [`magnitude`](fn.magnitude.html) /// * [`magnitude2`](fn.magnitude2.html) -pub fn l2_norm(x: &TVec) -> N +pub fn l2_norm(x: &TVec) -> N where DefaultAllocator: Alloc { x.norm() } @@ -91,7 +91,7 @@ where DefaultAllocator: Alloc { /// * [`length`](fn.length.html) /// * [`magnitude`](fn.magnitude.html) /// * [`magnitude2`](fn.magnitude2.html) -pub fn length2(x: &TVec) -> N +pub fn length2(x: &TVec) -> N where DefaultAllocator: Alloc { x.norm_squared() } @@ -107,17 +107,17 @@ where DefaultAllocator: Alloc { /// * [`length2`](fn.length2.html) /// * [`magnitude`](fn.magnitude.html) /// * [`nalgebra::norm_squared`](../nalgebra/fn.norm_squared.html) -pub fn magnitude2(x: &TVec) -> N +pub fn magnitude2(x: &TVec) -> N where DefaultAllocator: Alloc { x.norm_squared() } -//pub fn lxNorm(x: &TVec, y: &TVec, unsigned int Depth) -> N +//pub fn lxNorm(x: &TVec, y: &TVec, unsigned int Depth) -> N // where DefaultAllocator: Alloc { // unimplemented!() //} // -//pub fn lxNorm(x: &TVec, unsigned int Depth) -> N +//pub fn lxNorm(x: &TVec, unsigned int Depth) -> N // where DefaultAllocator: Alloc { // unimplemented!() //} diff --git a/nalgebra-glm/src/gtx/normal.rs b/nalgebra-glm/src/gtx/normal.rs index da3287fb..d9f48034 100644 --- a/nalgebra-glm/src/gtx/normal.rs +++ b/nalgebra-glm/src/gtx/normal.rs @@ -1,10 +1,10 @@ -use na::Real; +use na::RealField; use crate::aliases::TVec3; /// The normal vector of the given triangle. /// /// The normal is computed as the normalized vector `cross(p2 - p1, p3 - p1)`. -pub fn triangle_normal(p1: &TVec3, p2: &TVec3, p3: &TVec3) -> TVec3 { +pub fn triangle_normal(p1: &TVec3, p2: &TVec3, p3: &TVec3) -> TVec3 { (p2 - p1).cross(&(p3 - p1)).normalize() } diff --git a/nalgebra-glm/src/gtx/normalize_dot.rs b/nalgebra-glm/src/gtx/normalize_dot.rs index 6bce441b..06ce6978 100644 --- a/nalgebra-glm/src/gtx/normalize_dot.rs +++ b/nalgebra-glm/src/gtx/normalize_dot.rs @@ -1,4 +1,4 @@ -use na::{DefaultAllocator, Real}; +use na::{DefaultAllocator, RealField}; use crate::aliases::TVec; use crate::traits::{Alloc, Dimension}; @@ -10,7 +10,7 @@ use crate::traits::{Alloc, Dimension}; /// # See also: /// /// * [`normalize_dot`](fn.normalize_dot.html`) -pub fn fast_normalize_dot(x: &TVec, y: &TVec) -> N +pub fn fast_normalize_dot(x: &TVec, y: &TVec) -> N where DefaultAllocator: Alloc { // XXX: improve those. x.normalize().dot(&y.normalize()) @@ -21,7 +21,7 @@ where DefaultAllocator: Alloc { /// # See also: /// /// * [`fast_normalize_dot`](fn.fast_normalize_dot.html`) -pub fn normalize_dot(x: &TVec, y: &TVec) -> N +pub fn normalize_dot(x: &TVec, y: &TVec) -> N where DefaultAllocator: Alloc { // XXX: improve those. x.normalize().dot(&y.normalize()) diff --git a/nalgebra-glm/src/gtx/quaternion.rs b/nalgebra-glm/src/gtx/quaternion.rs index 5c9a783c..a90760d4 100644 --- a/nalgebra-glm/src/gtx/quaternion.rs +++ b/nalgebra-glm/src/gtx/quaternion.rs @@ -1,97 +1,97 @@ -use na::{Real, Rotation3, Unit, UnitQuaternion, U3}; +use na::{RealField, Rotation3, Unit, UnitQuaternion, U3}; use crate::aliases::{Qua, TMat3, TMat4, TVec3, TVec4}; /// Rotate the vector `v` by the quaternion `q` assumed to be normalized. -pub fn quat_cross_vec(q: &Qua, v: &TVec3) -> TVec3 { +pub fn quat_cross_vec(q: &Qua, v: &TVec3) -> TVec3 { UnitQuaternion::new_unchecked(*q) * v } /// Rotate the vector `v` by the inverse of the quaternion `q` assumed to be normalized. -pub fn quat_inv_cross_vec(v: &TVec3, q: &Qua) -> TVec3 { +pub fn quat_inv_cross_vec(v: &TVec3, q: &Qua) -> TVec3 { UnitQuaternion::new_unchecked(*q).inverse() * v } /// The quaternion `w` component. -pub fn quat_extract_real_component(q: &Qua) -> N { +pub fn quat_extract_real_component(q: &Qua) -> N { q.w } /// Normalized linear interpolation between two quaternions. -pub fn quat_fast_mix(x: &Qua, y: &Qua, a: N) -> Qua { +pub fn quat_fast_mix(x: &Qua, y: &Qua, a: N) -> Qua { Unit::new_unchecked(*x) .nlerp(&Unit::new_unchecked(*y), a) .into_inner() } -//pub fn quat_intermediate(prev: &Qua, curr: &Qua, next: &Qua) -> Qua { +//pub fn quat_intermediate(prev: &Qua, curr: &Qua, next: &Qua) -> Qua { // unimplemented!() //} /// The squared magnitude of a quaternion `q`. -pub fn quat_length2(q: &Qua) -> N { +pub fn quat_length2(q: &Qua) -> N { q.norm_squared() } /// The squared magnitude of a quaternion `q`. -pub fn quat_magnitude2(q: &Qua) -> N { +pub fn quat_magnitude2(q: &Qua) -> N { q.norm_squared() } /// The quaternion representing the identity rotation. -pub fn quat_identity() -> Qua { +pub fn quat_identity() -> Qua { UnitQuaternion::identity().into_inner() } /// Rotates a vector by a quaternion assumed to be normalized. -pub fn quat_rotate_vec3(q: &Qua, v: &TVec3) -> TVec3 { +pub fn quat_rotate_vec3(q: &Qua, v: &TVec3) -> TVec3 { UnitQuaternion::new_unchecked(*q) * v } /// Rotates a vector in homogeneous coordinates by a quaternion assumed to be normalized. -pub fn quat_rotate_vec(q: &Qua, v: &TVec4) -> TVec4 { +pub fn quat_rotate_vec(q: &Qua, v: &TVec4) -> TVec4 { let rotated = Unit::new_unchecked(*q) * v.fixed_rows::(0); TVec4::new(rotated.x, rotated.y, rotated.z, v.w) } /// The rotation required to align `orig` to `dest`. -pub fn quat_rotation(orig: &TVec3, dest: &TVec3) -> Qua { +pub fn quat_rotation(orig: &TVec3, dest: &TVec3) -> Qua { UnitQuaternion::rotation_between(orig, dest) .unwrap_or_else(UnitQuaternion::identity) .into_inner() } /// The spherical linear interpolation between two quaternions. -pub fn quat_short_mix(x: &Qua, y: &Qua, a: N) -> Qua { +pub fn quat_short_mix(x: &Qua, y: &Qua, a: N) -> Qua { Unit::new_normalize(*x) .slerp(&Unit::new_normalize(*y), a) .into_inner() } -//pub fn quat_squad(q1: &Qua, q2: &Qua, s1: &Qua, s2: &Qua, h: N) -> Qua { +//pub fn quat_squad(q1: &Qua, q2: &Qua, s1: &Qua, s2: &Qua, h: N) -> Qua { // unimplemented!() //} /// Converts a quaternion to a rotation matrix. -pub fn quat_to_mat3(x: &Qua) -> TMat3 { +pub fn quat_to_mat3(x: &Qua) -> TMat3 { UnitQuaternion::new_unchecked(*x) .to_rotation_matrix() .into_inner() } /// Converts a quaternion to a rotation matrix in homogenous coordinates. -pub fn quat_to_mat4(x: &Qua) -> TMat4 { +pub fn quat_to_mat4(x: &Qua) -> TMat4 { UnitQuaternion::new_unchecked(*x).to_homogeneous() } /// Converts a rotation matrix to a quaternion. -pub fn mat3_to_quat(x: &TMat3) -> Qua { +pub fn mat3_to_quat(x: &TMat3) -> Qua { let r = Rotation3::from_matrix_unchecked(*x); UnitQuaternion::from_rotation_matrix(&r).into_inner() } /// Converts a rotation matrix in homogeneous coordinates to a quaternion. -pub fn to_quat(x: &TMat4) -> Qua { +pub fn to_quat(x: &TMat4) -> Qua { let rot = x.fixed_slice::(0, 0).into_owned(); mat3_to_quat(&rot) } diff --git a/nalgebra-glm/src/gtx/rotate_normalized_axis.rs b/nalgebra-glm/src/gtx/rotate_normalized_axis.rs index 6767248c..1672b978 100644 --- a/nalgebra-glm/src/gtx/rotate_normalized_axis.rs +++ b/nalgebra-glm/src/gtx/rotate_normalized_axis.rs @@ -1,4 +1,4 @@ -use na::{Real, Rotation3, Unit, UnitQuaternion}; +use na::{RealField, Rotation3, Unit, UnitQuaternion}; use crate::aliases::{Qua, TMat4, TVec3}; @@ -9,7 +9,7 @@ use crate::aliases::{Qua, TMat4, TVec3}; /// * `m` - Input matrix multiplied by this rotation matrix. /// * `angle` - Rotation angle expressed in radians. /// * `axis` - Rotation axis, must be normalized. -pub fn rotate_normalized_axis(m: &TMat4, angle: N, axis: &TVec3) -> TMat4 { +pub fn rotate_normalized_axis(m: &TMat4, angle: N, axis: &TVec3) -> TMat4 { m * Rotation3::from_axis_angle(&Unit::new_unchecked(*axis), angle).to_homogeneous() } @@ -20,6 +20,6 @@ pub fn rotate_normalized_axis(m: &TMat4, angle: N, axis: &TVec3) /// * `q` - Source orientation. /// * `angle` - Angle expressed in radians. /// * `axis` - Normalized axis of the rotation, must be normalized. -pub fn quat_rotate_normalized_axis(q: &Qua, angle: N, axis: &TVec3) -> Qua { +pub fn quat_rotate_normalized_axis(q: &Qua, angle: N, axis: &TVec3) -> Qua { q * UnitQuaternion::from_axis_angle(&Unit::new_unchecked(*axis), angle).into_inner() } diff --git a/nalgebra-glm/src/gtx/rotate_vector.rs b/nalgebra-glm/src/gtx/rotate_vector.rs index a8cdd72b..30abc767 100644 --- a/nalgebra-glm/src/gtx/rotate_vector.rs +++ b/nalgebra-glm/src/gtx/rotate_vector.rs @@ -1,9 +1,9 @@ -use na::{Real, Rotation3, Unit, UnitComplex}; +use na::{RealField, Rotation3, Unit, UnitComplex}; use crate::aliases::{TMat4, TVec2, TVec3, TVec4}; /// Build the rotation matrix needed to align `normal` and `up`. -pub fn orientation(normal: &TVec3, up: &TVec3) -> TMat4 { +pub fn orientation(normal: &TVec3, up: &TVec3) -> TMat4 { if let Some(r) = Rotation3::rotation_between(normal, up) { r.to_homogeneous() } else { @@ -12,52 +12,52 @@ pub fn orientation(normal: &TVec3, up: &TVec3) -> TMat4 { } /// Rotate a two dimensional vector. -pub fn rotate_vec2(v: &TVec2, angle: N) -> TVec2 { +pub fn rotate_vec2(v: &TVec2, angle: N) -> TVec2 { UnitComplex::new(angle) * v } /// Rotate a three dimensional vector around an axis. -pub fn rotate_vec3(v: &TVec3, angle: N, normal: &TVec3) -> TVec3 { +pub fn rotate_vec3(v: &TVec3, angle: N, normal: &TVec3) -> TVec3 { Rotation3::from_axis_angle(&Unit::new_normalize(*normal), angle) * v } /// Rotate a thee dimensional vector in homogeneous coordinates around an axis. -pub fn rotate_vec4(v: &TVec4, angle: N, normal: &TVec3) -> TVec4 { +pub fn rotate_vec4(v: &TVec4, angle: N, normal: &TVec3) -> TVec4 { Rotation3::from_axis_angle(&Unit::new_normalize(*normal), angle).to_homogeneous() * v } /// Rotate a three dimensional vector around the `X` axis. -pub fn rotate_x_vec3(v: &TVec3, angle: N) -> TVec3 { +pub fn rotate_x_vec3(v: &TVec3, angle: N) -> TVec3 { Rotation3::from_axis_angle(&TVec3::x_axis(), angle) * v } /// Rotate a three dimensional vector in homogeneous coordinates around the `X` axis. -pub fn rotate_x_vec4(v: &TVec4, angle: N) -> TVec4 { +pub fn rotate_x_vec4(v: &TVec4, angle: N) -> TVec4 { Rotation3::from_axis_angle(&TVec3::x_axis(), angle).to_homogeneous() * v } /// Rotate a three dimensional vector around the `Y` axis. -pub fn rotate_y_vec3(v: &TVec3, angle: N) -> TVec3 { +pub fn rotate_y_vec3(v: &TVec3, angle: N) -> TVec3 { Rotation3::from_axis_angle(&TVec3::y_axis(), angle) * v } /// Rotate a three dimensional vector in homogeneous coordinates around the `Y` axis. -pub fn rotate_y_vec4(v: &TVec4, angle: N) -> TVec4 { +pub fn rotate_y_vec4(v: &TVec4, angle: N) -> TVec4 { Rotation3::from_axis_angle(&TVec3::y_axis(), angle).to_homogeneous() * v } /// Rotate a three dimensional vector around the `Z` axis. -pub fn rotate_z_vec3(v: &TVec3, angle: N) -> TVec3 { +pub fn rotate_z_vec3(v: &TVec3, angle: N) -> TVec3 { Rotation3::from_axis_angle(&TVec3::z_axis(), angle) * v } /// Rotate a three dimensional vector in homogeneous coordinates around the `Z` axis. -pub fn rotate_z_vec4(v: &TVec4, angle: N) -> TVec4 { +pub fn rotate_z_vec4(v: &TVec4, angle: N) -> TVec4 { Rotation3::from_axis_angle(&TVec3::z_axis(), angle).to_homogeneous() * v } /// Computes a spherical linear interpolation between the vectors `x` and `y` assumed to be normalized. -pub fn slerp(x: &TVec3, y: &TVec3, a: N) -> TVec3 { +pub fn slerp(x: &TVec3, y: &TVec3, a: N) -> TVec3 { Unit::new_unchecked(*x) .slerp(&Unit::new_unchecked(*y), a) .into_inner() diff --git a/nalgebra-glm/src/gtx/transform.rs b/nalgebra-glm/src/gtx/transform.rs index 1e3e404d..17a853c1 100644 --- a/nalgebra-glm/src/gtx/transform.rs +++ b/nalgebra-glm/src/gtx/transform.rs @@ -1,4 +1,4 @@ -use na::{Real, Rotation2, Rotation3, Unit}; +use na::{RealField, Rotation2, Rotation3, Unit}; use crate::aliases::{TMat3, TMat4, TVec2, TVec3}; use crate::traits::Number; @@ -12,7 +12,7 @@ use crate::traits::Number; /// * [`rotation2d`](fn.rotation2d.html) /// * [`scaling2d`](fn.scaling2d.html) /// * [`translation2d`](fn.translation2d.html) -pub fn rotation(angle: N, v: &TVec3) -> TMat4 { +pub fn rotation(angle: N, v: &TVec3) -> TMat4 { Rotation3::from_axis_angle(&Unit::new_normalize(*v), angle).to_homogeneous() } @@ -51,7 +51,7 @@ pub fn translation(v: &TVec3) -> TMat4 { /// * [`translation`](fn.translation.html) /// * [`scaling2d`](fn.scaling2d.html) /// * [`translation2d`](fn.translation2d.html) -pub fn rotation2d(angle: N) -> TMat3 { +pub fn rotation2d(angle: N) -> TMat3 { Rotation2::new(angle).to_homogeneous() } diff --git a/nalgebra-glm/src/gtx/transform2d.rs b/nalgebra-glm/src/gtx/transform2d.rs index 9e80bb52..0c7deb18 100644 --- a/nalgebra-glm/src/gtx/transform2d.rs +++ b/nalgebra-glm/src/gtx/transform2d.rs @@ -1,4 +1,4 @@ -use na::{Real, UnitComplex}; +use na::{RealField, UnitComplex}; use crate::aliases::{TMat3, TVec2}; use crate::traits::Number; @@ -12,7 +12,7 @@ use crate::traits::Number; /// * [`scaling2d`](fn.scaling2d.html) /// * [`translate2d`](fn.translate2d.html) /// * [`translation2d`](fn.translation2d.html) -pub fn rotate2d(m: &TMat3, angle: N) -> TMat3 { +pub fn rotate2d(m: &TMat3, angle: N) -> TMat3 { m * UnitComplex::new(angle).to_homogeneous() } diff --git a/nalgebra-glm/src/gtx/vector_angle.rs b/nalgebra-glm/src/gtx/vector_angle.rs index 8cfe813b..8753ccd0 100644 --- a/nalgebra-glm/src/gtx/vector_angle.rs +++ b/nalgebra-glm/src/gtx/vector_angle.rs @@ -1,18 +1,18 @@ -use na::{DefaultAllocator, Real}; +use na::{DefaultAllocator, RealField}; use crate::aliases::TVec; use crate::traits::{Alloc, Dimension}; /// The angle between two vectors. -pub fn angle(x: &TVec, y: &TVec) -> N +pub fn angle(x: &TVec, y: &TVec) -> N where DefaultAllocator: Alloc { x.angle(y) } -//pub fn oriented_angle(x: &TVec2, y: &TVec2) -> N { +//pub fn oriented_angle(x: &TVec2, y: &TVec2) -> N { // unimplemented!() //} // -//pub fn oriented_angle_ref(x: &TVec3, y: &TVec3, refv: &TVec3) -> N { +//pub fn oriented_angle_ref(x: &TVec3, y: &TVec3, refv: &TVec3) -> N { // unimplemented!() //} diff --git a/nalgebra-glm/src/gtx/vector_query.rs b/nalgebra-glm/src/gtx/vector_query.rs index da23704d..2a127f00 100644 --- a/nalgebra-glm/src/gtx/vector_query.rs +++ b/nalgebra-glm/src/gtx/vector_query.rs @@ -1,4 +1,4 @@ -use na::{DefaultAllocator, Real}; +use na::{DefaultAllocator, RealField}; use crate::aliases::{TVec, TVec2, TVec3}; use crate::traits::{Alloc, Dimension, Number}; @@ -45,7 +45,7 @@ where DefaultAllocator: Alloc { } /// Returns `true` if `v` has a magnitude of 1 (up to an epsilon). -pub fn is_normalized(v: &TVec, epsilon: N) -> bool +pub fn is_normalized(v: &TVec, epsilon: N) -> bool where DefaultAllocator: Alloc { abs_diff_eq!(v.norm_squared(), N::one(), epsilon = epsilon * epsilon) } diff --git a/nalgebra-glm/src/integer.rs b/nalgebra-glm/src/integer.rs index dbf39cb0..198d737a 100644 --- a/nalgebra-glm/src/integer.rs +++ b/nalgebra-glm/src/integer.rs @@ -1,4 +1,4 @@ -use na::{Scalar, Real, U3, DefaultAllocator}; +use na::{Scalar, RealField, U3, DefaultAllocator}; use crate::traits::{Number, Alloc, Dimension}; use crate::aliases::TVec; diff --git a/nalgebra-glm/src/lib.rs b/nalgebra-glm/src/lib.rs index b2fe8b8f..66502e73 100644 --- a/nalgebra-glm/src/lib.rs +++ b/nalgebra-glm/src/lib.rs @@ -191,7 +191,7 @@ pub use gtx::{ pub use na::{ convert, convert_ref, convert_ref_unchecked, convert_unchecked, try_convert, try_convert_ref, }; -pub use na::{DefaultAllocator, Real, Scalar, U1, U2, U3, U4}; +pub use na::{DefaultAllocator, RealField, Scalar, U1, U2, U3, U4}; mod aliases; mod common; diff --git a/nalgebra-glm/src/matrix.rs b/nalgebra-glm/src/matrix.rs index 26b2f3ab..a4c4efe9 100644 --- a/nalgebra-glm/src/matrix.rs +++ b/nalgebra-glm/src/matrix.rs @@ -1,16 +1,16 @@ -use na::{DefaultAllocator, Real, Scalar}; +use na::{DefaultAllocator, RealField, Scalar}; use crate::aliases::{TMat, TVec}; use crate::traits::{Alloc, Dimension, Number}; /// The determinant of the matrix `m`. -pub fn determinant(m: &TMat) -> N +pub fn determinant(m: &TMat) -> N where DefaultAllocator: Alloc { m.determinant() } /// The inverse of the matrix `m`. -pub fn inverse(m: &TMat) -> TMat +pub fn inverse(m: &TMat) -> TMat where DefaultAllocator: Alloc { m.clone() .try_inverse() diff --git a/nalgebra-glm/src/trigonometric.rs b/nalgebra-glm/src/trigonometric.rs index 661bd2ae..139a48da 100644 --- a/nalgebra-glm/src/trigonometric.rs +++ b/nalgebra-glm/src/trigonometric.rs @@ -1,94 +1,94 @@ -use na::{self, DefaultAllocator, Real}; +use na::{self, DefaultAllocator, RealField}; use crate::aliases::TVec; use crate::traits::{Alloc, Dimension}; /// Component-wise arc-cosinus. -pub fn acos(x: &TVec) -> TVec +pub fn acos(x: &TVec) -> TVec where DefaultAllocator: Alloc { x.map(|e| e.acos()) } /// Component-wise hyperbolic arc-cosinus. -pub fn acosh(x: &TVec) -> TVec +pub fn acosh(x: &TVec) -> TVec where DefaultAllocator: Alloc { x.map(|e| e.acosh()) } /// Component-wise arc-sinus. -pub fn asin(x: &TVec) -> TVec +pub fn asin(x: &TVec) -> TVec where DefaultAllocator: Alloc { x.map(|e| e.asin()) } /// Component-wise hyperbolic arc-sinus. -pub fn asinh(x: &TVec) -> TVec +pub fn asinh(x: &TVec) -> TVec where DefaultAllocator: Alloc { x.map(|e| e.asinh()) } /// Component-wise arc-tangent of `y / x`. -pub fn atan2(y: &TVec, x: &TVec) -> TVec +pub fn atan2(y: &TVec, x: &TVec) -> TVec where DefaultAllocator: Alloc { y.zip_map(x, |y, x| y.atan2(x)) } /// Component-wise arc-tangent. -pub fn atan(y_over_x: &TVec) -> TVec +pub fn atan(y_over_x: &TVec) -> TVec where DefaultAllocator: Alloc { y_over_x.map(|e| e.atan()) } /// Component-wise hyperbolic arc-tangent. -pub fn atanh(x: &TVec) -> TVec +pub fn atanh(x: &TVec) -> TVec where DefaultAllocator: Alloc { x.map(|e| e.atanh()) } /// Component-wise cosinus. -pub fn cos(angle: &TVec) -> TVec +pub fn cos(angle: &TVec) -> TVec where DefaultAllocator: Alloc { angle.map(|e| e.cos()) } /// Component-wise hyperbolic cosinus. -pub fn cosh(angle: &TVec) -> TVec +pub fn cosh(angle: &TVec) -> TVec where DefaultAllocator: Alloc { angle.map(|e| e.cosh()) } /// Component-wise conversion from radians to degrees. -pub fn degrees(radians: &TVec) -> TVec +pub fn degrees(radians: &TVec) -> TVec where DefaultAllocator: Alloc { radians.map(|e| e * na::convert(180.0) / N::pi()) } /// Component-wise conversion fro degrees to radians. -pub fn radians(degrees: &TVec) -> TVec +pub fn radians(degrees: &TVec) -> TVec where DefaultAllocator: Alloc { degrees.map(|e| e * N::pi() / na::convert(180.0)) } /// Component-wise sinus. -pub fn sin(angle: &TVec) -> TVec +pub fn sin(angle: &TVec) -> TVec where DefaultAllocator: Alloc { angle.map(|e| e.sin()) } /// Component-wise hyperbolic sinus. -pub fn sinh(angle: &TVec) -> TVec +pub fn sinh(angle: &TVec) -> TVec where DefaultAllocator: Alloc { angle.map(|e| e.sinh()) } /// Component-wise tangent. -pub fn tan(angle: &TVec) -> TVec +pub fn tan(angle: &TVec) -> TVec where DefaultAllocator: Alloc { angle.map(|e| e.tan()) } /// Component-wise hyperbolic tangent. -pub fn tanh(angle: &TVec) -> TVec +pub fn tanh(angle: &TVec) -> TVec where DefaultAllocator: Alloc { angle.map(|e| e.tanh()) } diff --git a/nalgebra-lapack/src/eigen.rs b/nalgebra-lapack/src/eigen.rs index 628b532f..d5397841 100644 --- a/nalgebra-lapack/src/eigen.rs +++ b/nalgebra-lapack/src/eigen.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; use num::Zero; use num_complex::Complex; -use alga::general::Real; +use alga::general::RealField; use na::allocator::Allocator; use na::dimension::{Dim, U1}; @@ -51,7 +51,7 @@ where MatrixN: Copy, {} -impl Eigen +impl Eigen where DefaultAllocator: Allocator + Allocator { /// Computes the eigenvalues and eigenvectors of the square matrix `m`. diff --git a/nalgebra-lapack/src/schur.rs b/nalgebra-lapack/src/schur.rs index f928afda..eb618fe9 100644 --- a/nalgebra-lapack/src/schur.rs +++ b/nalgebra-lapack/src/schur.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; use num::Zero; use num_complex::Complex; -use alga::general::Real; +use alga::general::RealField; use na::allocator::Allocator; use na::dimension::{Dim, U1}; @@ -49,7 +49,7 @@ where VectorN: Copy, {} -impl Schur +impl Schur where DefaultAllocator: Allocator + Allocator { /// Computes the eigenvalues and real Schur form of the matrix `m`. @@ -161,7 +161,7 @@ where DefaultAllocator: Allocator + Allocator * Lapack functions dispatch. * */ -/// Trait implemented by scalars for which Lapack implements the Real Schur decomposition. +/// Trait implemented by scalars for which Lapack implements the RealField Schur decomposition. pub trait SchurScalar: Scalar { #[allow(missing_docs)] fn xgees( diff --git a/nalgebra-lapack/src/symmetric_eigen.rs b/nalgebra-lapack/src/symmetric_eigen.rs index af0575fd..d34b3fce 100644 --- a/nalgebra-lapack/src/symmetric_eigen.rs +++ b/nalgebra-lapack/src/symmetric_eigen.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; use num::Zero; use std::ops::MulAssign; -use alga::general::Real; +use alga::general::RealField; use na::allocator::Allocator; use na::dimension::{Dim, U1}; @@ -52,7 +52,7 @@ where VectorN: Copy, {} -impl SymmetricEigen +impl SymmetricEigen where DefaultAllocator: Allocator + Allocator { /// Computes the eigenvalues and eigenvectors of the symmetric matrix `m`. diff --git a/src/base/cg.rs b/src/base/cg.rs index 5c1a7c11..4029dbc3 100644 --- a/src/base/cg.rs +++ b/src/base/cg.rs @@ -18,7 +18,7 @@ use crate::geometry::{ Isometry, IsometryMatrix3, Orthographic3, Perspective3, Point, Point3, Rotation2, Rotation3, }; -use alga::general::{Real, Ring}; +use alga::general::{RealField, Ring}; use alga::linear::Transformation; impl MatrixN @@ -65,7 +65,7 @@ where } } -impl Matrix3 { +impl Matrix3 { /// Builds a 2 dimensional homogeneous rotation matrix from an angle in radian. #[inline] pub fn new_rotation(angle: N) -> Self { @@ -73,7 +73,7 @@ impl Matrix3 { } } -impl Matrix4 { +impl Matrix4 { /// Builds a 3D homogeneous rotation matrix from an axis and an angle (multiplied together). /// /// Returns the identity matrix if the given argument is zero. @@ -320,7 +320,7 @@ impl> SquareMatrix } } -impl, S: Storage> SquareMatrix +impl, S: Storage> SquareMatrix where DefaultAllocator: Allocator + Allocator> + Allocator, DimNameDiff> @@ -364,7 +364,7 @@ where DefaultAllocator: Allocator } } -impl> Transformation>> for MatrixN +impl> Transformation>> for MatrixN where DefaultAllocator: Allocator + Allocator> + Allocator, DimNameDiff> diff --git a/src/base/construction.rs b/src/base/construction.rs index 1b05fe61..5eace4bb 100644 --- a/src/base/construction.rs +++ b/src/base/construction.rs @@ -12,7 +12,7 @@ use std::iter; use typenum::{self, Cmp, Greater}; #[cfg(feature = "std")] -use alga::general::Real; +use alga::general::RealField; use alga::general::{ClosedAdd, ClosedMul}; use crate::base::allocator::Allocator; @@ -795,7 +795,7 @@ where } #[cfg(feature = "std")] -impl Distribution>> for Standard +impl Distribution>> for Standard where DefaultAllocator: Allocator, StandardNormal: Distribution, diff --git a/src/base/matrix.rs b/src/base/matrix.rs index ad188a26..6c1db1d6 100644 --- a/src/base/matrix.rs +++ b/src/base/matrix.rs @@ -16,7 +16,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; #[cfg(feature = "abomonation-serialize")] use abomonation::Abomonation; -use alga::general::{ClosedAdd, ClosedMul, ClosedSub, Real, Ring, ComplexField, Field}; +use alga::general::{ClosedAdd, ClosedMul, ClosedSub, RealField, Ring, ComplexField, Field}; use crate::base::allocator::{Allocator, SameShapeAllocator, SameShapeC, SameShapeR}; use crate::base::constraint::{DimEq, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint}; @@ -983,14 +983,14 @@ impl> Matrix { /// Divides each component of the complex matrix `self` by the given real. #[inline] - pub fn unscale(&self, real: N::Real) -> MatrixMN + pub fn unscale(&self, real: N::RealField) -> MatrixMN where DefaultAllocator: Allocator { self.map(|e| e.unscale(real)) } /// Multiplies each component of the complex matrix `self` by the given real. #[inline] - pub fn scale(&self, real: N::Real) -> MatrixMN + pub fn scale(&self, real: N::RealField) -> MatrixMN where DefaultAllocator: Allocator { self.map(|e| e.scale(real)) } @@ -1005,13 +1005,13 @@ impl> Matrix /// Divides each component of the complex matrix `self` by the given real. #[inline] - pub fn unscale_mut(&mut self, real: N::Real) { + pub fn unscale_mut(&mut self, real: N::RealField) { self.apply(|e| e.unscale(real)) } /// Multiplies each component of the complex matrix `self` by the given real. #[inline] - pub fn scale_mut(&mut self, real: N::Real) { + pub fn scale_mut(&mut self, real: N::RealField) { self.apply(|e| e.scale(real)) } } @@ -1544,7 +1544,7 @@ where DefaultAllocator: Allocator impl> Matrix { /// The smallest angle between two vectors. #[inline] - pub fn angle(&self, other: &Matrix) -> N::Real + pub fn angle(&self, other: &Matrix) -> N::RealField where SB: Storage, ShapeConstraint: DimEq + DimEq, @@ -1554,14 +1554,14 @@ impl> Matrix { let n2 = other.norm(); if n1.is_zero() || n2.is_zero() { - N::Real::zero() + N::RealField::zero() } else { let cang = prod.real() / (n1 * n2); - if cang > N::Real::one() { - N::Real::zero() - } else if cang < -N::Real::one() { - N::Real::pi() + if cang > N::RealField::one() { + N::RealField::zero() + } else if cang < -N::RealField::one() { + N::RealField::pi() } else { cang.acos() } @@ -1597,13 +1597,13 @@ impl> Unit> { pub fn slerp>( &self, rhs: &Unit>, - t: N::Real, + t: N::RealField, ) -> Unit> where DefaultAllocator: Allocator, { // FIXME: the result is wrong when self and rhs are collinear with opposite direction. - self.try_slerp(rhs, t, N::Real::default_epsilon()) + self.try_slerp(rhs, t, N::RealField::default_epsilon()) .unwrap_or(Unit::new_unchecked(self.clone_owned())) } @@ -1614,8 +1614,8 @@ impl> Unit> { pub fn try_slerp>( &self, rhs: &Unit>, - t: N::Real, - epsilon: N::Real, + t: N::RealField, + epsilon: N::RealField, ) -> Option>> where DefaultAllocator: Allocator, @@ -1623,18 +1623,18 @@ impl> Unit> { let (c_hang, c_hang_sign) = self.dotc(rhs).to_exp(); // self == other - if c_hang >= N::Real::one() { + if c_hang >= N::RealField::one() { return Some(Unit::new_unchecked(self.clone_owned())); } let hang = c_hang.acos(); - let s_hang = (N::Real::one() - c_hang * c_hang).sqrt(); + let s_hang = (N::RealField::one() - c_hang * c_hang).sqrt(); // FIXME: what if s_hang is 0.0 ? The result is not well-defined. - if relative_eq!(s_hang, N::Real::zero(), epsilon = epsilon) { + if relative_eq!(s_hang, N::RealField::zero(), epsilon = epsilon) { None } else { - let ta = ((N::Real::one() - t) * hang).sin() / s_hang; + let ta = ((N::RealField::one() - t) * hang).sin() / s_hang; let tb = (t * hang).sin() / s_hang; let mut res = self.scale(ta); res.axpy(c_hang_sign.scale(tb), &**rhs, N::one()); diff --git a/src/base/matrix_alga.rs b/src/base/matrix_alga.rs index 790d60d3..ac6aced7 100644 --- a/src/base/matrix_alga.rs +++ b/src/base/matrix_alga.rs @@ -148,16 +148,16 @@ where impl NormedSpace for MatrixMN where DefaultAllocator: Allocator { - type Real = N::Real; + type RealField = N::RealField; type ComplexField = N; #[inline] - fn norm_squared(&self) -> N::Real { + fn norm_squared(&self) -> N::RealField { self.norm_squared() } #[inline] - fn norm(&self) -> N::Real { + fn norm(&self) -> N::RealField { self.norm() } @@ -167,17 +167,17 @@ where DefaultAllocator: Allocator } #[inline] - fn normalize_mut(&mut self) -> N::Real { + fn normalize_mut(&mut self) -> N::RealField { self.normalize_mut() } #[inline] - fn try_normalize(&self, min_norm: N::Real) -> Option { + fn try_normalize(&self, min_norm: N::RealField) -> Option { self.try_normalize(min_norm) } #[inline] - fn try_normalize_mut(&mut self, min_norm: N::Real) -> Option { + fn try_normalize_mut(&mut self, min_norm: N::RealField) -> Option { self.try_normalize_mut(min_norm) } } @@ -186,7 +186,7 @@ impl InnerSpace for MatrixMN where DefaultAllocator: Allocator { #[inline] - fn angle(&self, other: &Self) -> N::Real { + fn angle(&self, other: &Self) -> N::RealField { self.angle(other) } @@ -216,7 +216,7 @@ where DefaultAllocator: Allocator } } - if vs[i].try_normalize_mut(N::Real::zero()).is_some() { + 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); @@ -301,7 +301,7 @@ where DefaultAllocator: Allocator elt -= v * elt.dot(v) } - if let Some(subsp_elt) = elt.try_normalize(N::Real::zero()) { + if let Some(subsp_elt) = elt.try_normalize(N::RealField::zero()) { if !f(&subsp_elt) { return; }; diff --git a/src/base/norm.rs b/src/base/norm.rs index 06bca851..93319ddc 100644 --- a/src/base/norm.rs +++ b/src/base/norm.rs @@ -1,7 +1,7 @@ use num::Zero; use crate::allocator::Allocator; -use crate::{Real, ComplexField}; +use crate::{RealField, ComplexField}; use crate::storage::{Storage, StorageMut}; use crate::base::{DefaultAllocator, Matrix, Dim, MatrixMN}; use crate::constraint::{SameNumberOfRows, SameNumberOfColumns, ShapeConstraint}; @@ -13,10 +13,10 @@ use crate::constraint::{SameNumberOfRows, SameNumberOfColumns, ShapeConstraint}; /// This may be moved to the alga crate in the future. pub trait Norm { /// Apply this norm to the given matrix. - fn norm(&self, m: &Matrix) -> N::Real + fn norm(&self, m: &Matrix) -> N::RealField where R: Dim, C: Dim, S: Storage; /// Use the metric induced by this norm to compute the metric distance between the two given matrices. - fn metric_distance(&self, m1: &Matrix, m2: &Matrix) -> N::Real + fn metric_distance(&self, m1: &Matrix, m2: &Matrix) -> N::RealField where R1: Dim, C1: Dim, S1: Storage, R2: Dim, C2: Dim, S2: Storage, ShapeConstraint: SameNumberOfRows + SameNumberOfColumns; @@ -31,17 +31,17 @@ pub struct UniformNorm; impl Norm for EuclideanNorm { #[inline] - fn norm(&self, m: &Matrix) -> N::Real + fn norm(&self, m: &Matrix) -> N::RealField where R: Dim, C: Dim, S: Storage { m.norm_squared().sqrt() } #[inline] - fn metric_distance(&self, m1: &Matrix, m2: &Matrix) -> N::Real + fn metric_distance(&self, m1: &Matrix, m2: &Matrix) -> N::RealField where R1: Dim, C1: Dim, S1: Storage, R2: Dim, C2: Dim, S2: Storage, ShapeConstraint: SameNumberOfRows + SameNumberOfColumns { - m1.zip_fold(m2, N::Real::zero(), |acc, a, b| { + m1.zip_fold(m2, N::RealField::zero(), |acc, a, b| { let diff = a - b; acc + diff.modulus_squared() }).sqrt() @@ -50,19 +50,19 @@ impl Norm for EuclideanNorm { impl Norm for LpNorm { #[inline] - fn norm(&self, m: &Matrix) -> N::Real + fn norm(&self, m: &Matrix) -> N::RealField where R: Dim, C: Dim, S: Storage { - m.fold(N::Real::zero(), |a, b| { + m.fold(N::RealField::zero(), |a, b| { a + b.modulus().powi(self.0) }).powf(crate::convert(1.0 / (self.0 as f64))) } #[inline] - fn metric_distance(&self, m1: &Matrix, m2: &Matrix) -> N::Real + fn metric_distance(&self, m1: &Matrix, m2: &Matrix) -> N::RealField where R1: Dim, C1: Dim, S1: Storage, R2: Dim, C2: Dim, S2: Storage, ShapeConstraint: SameNumberOfRows + SameNumberOfColumns { - m1.zip_fold(m2, N::Real::zero(), |acc, a, b| { + m1.zip_fold(m2, N::RealField::zero(), |acc, a, b| { let diff = a - b; acc + diff.modulus().powi(self.0) }).powf(crate::convert(1.0 / (self.0 as f64))) @@ -71,19 +71,19 @@ impl Norm for LpNorm { impl Norm for UniformNorm { #[inline] - fn norm(&self, m: &Matrix) -> N::Real + fn norm(&self, m: &Matrix) -> N::RealField where R: Dim, C: Dim, S: Storage { // NOTE: we don't use `m.amax()` here because for the complex // numbers this will return the max norm1 instead of the modulus. - m.fold(N::Real::zero(), |acc, a| acc.max(a.modulus())) + m.fold(N::RealField::zero(), |acc, a| acc.max(a.modulus())) } #[inline] - fn metric_distance(&self, m1: &Matrix, m2: &Matrix) -> N::Real + fn metric_distance(&self, m1: &Matrix, m2: &Matrix) -> N::RealField where R1: Dim, C1: Dim, S1: Storage, R2: Dim, C2: Dim, S2: Storage, ShapeConstraint: SameNumberOfRows + SameNumberOfColumns { - m1.zip_fold(m2, N::Real::zero(), |acc, a, b| { + m1.zip_fold(m2, N::RealField::zero(), |acc, a, b| { let val = (a - b).modulus(); if val > acc { val @@ -98,8 +98,8 @@ impl Norm for UniformNorm { impl> Matrix { /// The squared L2 norm of this vector. #[inline] - pub fn norm_squared(&self) -> N::Real { - let mut res = N::Real::zero(); + pub fn norm_squared(&self) -> N::RealField { + let mut res = N::RealField::zero(); for i in 0..self.ncols() { let col = self.column(i); @@ -113,7 +113,7 @@ impl> Matrix { /// /// Use `.apply_norm` to apply a custom norm. #[inline] - pub fn norm(&self) -> N::Real { + pub fn norm(&self) -> N::RealField { self.norm_squared().sqrt() } @@ -121,7 +121,7 @@ impl> Matrix { /// /// Use `.apply_metric_distance` to apply a custom norm. #[inline] - pub fn metric_distance(&self, rhs: &Matrix) -> N::Real + pub fn metric_distance(&self, rhs: &Matrix) -> N::RealField where R2: Dim, C2: Dim, S2: Storage, ShapeConstraint: SameNumberOfRows + SameNumberOfColumns { self.apply_metric_distance(rhs, &EuclideanNorm) @@ -140,7 +140,7 @@ impl> Matrix { /// assert_eq!(v.apply_norm(&EuclideanNorm), v.norm()); /// ``` #[inline] - pub fn apply_norm(&self, norm: &impl Norm) -> N::Real { + pub fn apply_norm(&self, norm: &impl Norm) -> N::RealField { norm.norm(self) } @@ -159,7 +159,7 @@ impl> Matrix { /// assert_eq!(v1.apply_metric_distance(&v2, &EuclideanNorm), (v1 - v2).norm()); /// ``` #[inline] - pub fn apply_metric_distance(&self, rhs: &Matrix, norm: &impl Norm) -> N::Real + pub fn apply_metric_distance(&self, rhs: &Matrix, norm: &impl Norm) -> N::RealField where R2: Dim, C2: Dim, S2: Storage, ShapeConstraint: SameNumberOfRows + SameNumberOfColumns { norm.metric_distance(self, rhs) @@ -171,7 +171,7 @@ impl> Matrix { /// /// This function is simply implemented as a call to `norm()` #[inline] - pub fn magnitude(&self) -> N::Real { + pub fn magnitude(&self) -> N::RealField { self.norm() } @@ -181,7 +181,7 @@ impl> Matrix { /// /// This function is simply implemented as a call to `norm_squared()` #[inline] - pub fn magnitude_squared(&self) -> N::Real { + pub fn magnitude_squared(&self) -> N::RealField { self.norm_squared() } @@ -194,7 +194,7 @@ impl> Matrix { /// Returns a normalized version of this matrix unless its norm as smaller or equal to `eps`. #[inline] - pub fn try_normalize(&self, min_norm: N::Real) -> Option> + pub fn try_normalize(&self, min_norm: N::RealField) -> Option> where DefaultAllocator: Allocator { let n = self.norm(); @@ -207,7 +207,7 @@ impl> Matrix { /// The Lp norm of this matrix. #[inline] - pub fn lp_norm(&self, p: i32) -> N::Real { + pub fn lp_norm(&self, p: i32) -> N::RealField { self.apply_norm(&LpNorm(p)) } } @@ -216,7 +216,7 @@ impl> Matrix { impl> Matrix { /// Normalizes this matrix in-place and returns its norm. #[inline] - pub fn normalize_mut(&mut self) -> N::Real { + pub fn normalize_mut(&mut self) -> N::RealField { let n = self.norm(); self.unscale_mut(n); @@ -227,7 +227,7 @@ impl> Matrix /// /// If the normalization succeeded, returns the old normal of this matrix. #[inline] - pub fn try_normalize_mut(&mut self, min_norm: N::Real) -> Option { + pub fn try_normalize_mut(&mut self, min_norm: N::RealField) -> Option { let n = self.norm(); if n <= min_norm { diff --git a/src/base/ops.rs b/src/base/ops.rs index 8a6fe5a1..9f3d44c3 100644 --- a/src/base/ops.rs +++ b/src/base/ops.rs @@ -832,7 +832,7 @@ impl> Matrix { /// Returns the the 1-norm of the complex component with the largest 1-norm. #[inline] - pub fn camax(&self) -> N::Real + pub fn camax(&self) -> N::RealField where N: ComplexField { self.xcmp(|e| e.norm1(), |a, b| a > b) } @@ -853,7 +853,7 @@ impl> Matrix { /// Returns the the 1-norm of the complex component with the smallest 1-norm. #[inline] - pub fn camin(&self) -> N::Real + pub fn camin(&self) -> N::RealField where N: ComplexField { self.xcmp(|e| e.norm1(), |a, b| a < b) } diff --git a/src/base/properties.rs b/src/base/properties.rs index acb7dfb4..8ca49568 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, Real, ComplexField}; +use alga::general::{ClosedAdd, ClosedMul, RealField, ComplexField}; use crate::base::allocator::Allocator; use crate::base::dimension::{Dim, DimMin}; @@ -101,7 +101,7 @@ impl> Matrix { } } -impl> SquareMatrix +impl> SquareMatrix where DefaultAllocator: Allocator { /// Checks that this matrix is orthogonal and has a determinant equal to 1. diff --git a/src/base/unit.rs b/src/base/unit.rs index 60aa1ae2..0c397e52 100644 --- a/src/base/unit.rs +++ b/src/base/unit.rs @@ -64,13 +64,13 @@ impl Unit { /// /// Returns `None` if the norm was smaller or equal to `min_norm`. #[inline] - pub fn try_new(value: T, min_norm: T::Real) -> Option { + pub fn try_new(value: T, min_norm: T::RealField) -> Option { 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. #[inline] - pub fn new_and_get(mut value: T) -> (Self, T::Real) { + pub fn new_and_get(mut value: T) -> (Self, T::RealField) { let n = value.normalize_mut(); (Unit { value: value }, n) @@ -80,7 +80,7 @@ impl Unit { /// /// 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::Real) -> Option<(Self, T::Real)> { + 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)) } else { @@ -94,7 +94,7 @@ impl Unit { /// 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::Real { + pub fn renormalize(&mut self) -> T::RealField { self.value.normalize_mut() } @@ -104,8 +104,8 @@ impl Unit { #[inline] pub fn renormalize_fast(&mut self) { let sq_norm = self.value.norm_squared(); - let _3: T::Real = crate::convert(3.0); - let _0_5: T::Real = crate::convert(0.5); + 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)); } } diff --git a/src/geometry/isometry.rs b/src/geometry/isometry.rs index f77d4d60..6df20039 100644 --- a/src/geometry/isometry.rs +++ b/src/geometry/isometry.rs @@ -11,7 +11,7 @@ use serde::{Deserialize, Serialize}; #[cfg(feature = "abomonation-serialize")] use abomonation::Abomonation; -use alga::general::{Real, SubsetOf}; +use alga::general::{RealField, SubsetOf}; use alga::linear::Rotation; use crate::base::allocator::Allocator; @@ -36,7 +36,7 @@ use crate::geometry::{Point, Translation}; DefaultAllocator: Allocator, Owned: Deserialize<'de>")) )] -pub struct Isometry +pub struct Isometry where DefaultAllocator: Allocator { /// The pure rotational part of this isometry. @@ -55,7 +55,7 @@ where DefaultAllocator: Allocator #[cfg(feature = "abomonation-serialize")] impl Abomonation for Isometry where - N: Real, + N: RealField, D: DimName, R: Abomonation, Translation: Abomonation, @@ -77,7 +77,7 @@ 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. @@ -260,7 +260,7 @@ where DefaultAllocator: Allocator // and makes it hard to use it, e.g., for Transform × Isometry implementation. // This is OK since all constructors of the isometry enforce the Rotation bound already (and // explicit struct construction is prevented by the dummy ZST field). -impl Isometry +impl Isometry where DefaultAllocator: Allocator { /// Converts this isometry into its equivalent homogeneous transformation matrix. @@ -293,14 +293,14 @@ where DefaultAllocator: Allocator } } -impl Eq for Isometry +impl Eq for Isometry where R: Rotation> + Eq, DefaultAllocator: Allocator, { } -impl PartialEq for Isometry +impl PartialEq for Isometry where R: Rotation> + PartialEq, DefaultAllocator: Allocator, @@ -311,7 +311,7 @@ where } } -impl AbsDiffEq for Isometry +impl AbsDiffEq for Isometry where R: Rotation> + AbsDiffEq, DefaultAllocator: Allocator, @@ -331,7 +331,7 @@ where } } -impl RelativeEq for Isometry +impl RelativeEq for Isometry where R: Rotation> + RelativeEq, DefaultAllocator: Allocator, @@ -358,7 +358,7 @@ where } } -impl UlpsEq for Isometry +impl UlpsEq for Isometry where R: Rotation> + UlpsEq, DefaultAllocator: Allocator, @@ -382,7 +382,7 @@ where * Display * */ -impl fmt::Display for Isometry +impl fmt::Display for Isometry where R: fmt::Display, DefaultAllocator: Allocator + Allocator, diff --git a/src/geometry/isometry_alga.rs b/src/geometry/isometry_alga.rs index eb9a5cd5..8402c5cb 100644 --- a/src/geometry/isometry_alga.rs +++ b/src/geometry/isometry_alga.rs @@ -1,6 +1,6 @@ use alga::general::{ AbstractGroup, AbstractLoop, AbstractMagma, AbstractMonoid, AbstractQuasigroup, - AbstractSemigroup, Id, Identity, TwoSidedInverse, Multiplicative, Real, + AbstractSemigroup, Id, Identity, TwoSidedInverse, Multiplicative, RealField, }; use alga::linear::Isometry as AlgaIsometry; use alga::linear::{ @@ -19,7 +19,7 @@ use crate::geometry::{Isometry, Point, Translation}; * Algebraic structures. * */ -impl Identity for Isometry +impl Identity for Isometry where R: Rotation>, DefaultAllocator: Allocator, @@ -30,7 +30,7 @@ where } } -impl TwoSidedInverse for Isometry +impl TwoSidedInverse for Isometry where R: Rotation>, DefaultAllocator: Allocator, @@ -46,7 +46,7 @@ where } } -impl AbstractMagma for Isometry +impl AbstractMagma for Isometry where R: Rotation>, DefaultAllocator: Allocator, @@ -59,7 +59,7 @@ where macro_rules! impl_multiplicative_structures( ($($marker: ident<$operator: ident>),* $(,)*) => {$( - impl $marker<$operator> for Isometry + impl $marker<$operator> for Isometry where R: Rotation>, DefaultAllocator: Allocator { } )*} @@ -78,7 +78,7 @@ impl_multiplicative_structures!( * Transformation groups. * */ -impl Transformation> for Isometry +impl Transformation> for Isometry where R: Rotation>, DefaultAllocator: Allocator, @@ -94,7 +94,7 @@ where } } -impl ProjectiveTransformation> for Isometry +impl ProjectiveTransformation> for Isometry where R: Rotation>, DefaultAllocator: Allocator, @@ -111,7 +111,7 @@ where } } -impl AffineTransformation> for Isometry +impl AffineTransformation> for Isometry where R: Rotation>, DefaultAllocator: Allocator, @@ -169,7 +169,7 @@ where } } -impl Similarity> for Isometry +impl Similarity> for Isometry where R: Rotation>, DefaultAllocator: Allocator, @@ -194,7 +194,7 @@ where macro_rules! marker_impl( ($($Trait: ident),*) => {$( - impl $Trait> for Isometry + impl $Trait> for Isometry where R: Rotation>, DefaultAllocator: Allocator { } )*} diff --git a/src/geometry/isometry_construction.rs b/src/geometry/isometry_construction.rs index 3863051c..979c3955 100644 --- a/src/geometry/isometry_construction.rs +++ b/src/geometry/isometry_construction.rs @@ -7,7 +7,7 @@ use num::One; use rand::distributions::{Distribution, Standard}; use rand::Rng; -use alga::general::Real; +use alga::general::RealField; use alga::linear::Rotation as AlgaRotation; use crate::base::allocator::Allocator; @@ -19,7 +19,7 @@ use crate::geometry::{ UnitQuaternion, Translation2, Translation3 }; -impl>> Isometry +impl>> Isometry where DefaultAllocator: Allocator { /// Creates a new identity isometry. @@ -65,7 +65,7 @@ where DefaultAllocator: Allocator } } -impl>> One for Isometry +impl>> One for Isometry where DefaultAllocator: Allocator { /// Creates a new identity isometry. @@ -75,7 +75,7 @@ where DefaultAllocator: Allocator } } -impl Distribution> for Standard +impl Distribution> for Standard where R: AlgaRotation>, Standard: Distribution + Distribution, @@ -90,7 +90,7 @@ where #[cfg(feature = "arbitrary")] impl Arbitrary for Isometry where - N: Real + Arbitrary + Send, + N: RealField + Arbitrary + Send, R: AlgaRotation> + Arbitrary + Send, Owned: Send, DefaultAllocator: Allocator, @@ -108,7 +108,7 @@ where */ // 2D rotation. -impl Isometry> { +impl Isometry> { /// Creates a new 2D isometry from a translation and a rotation angle. /// /// Its rotational part is represented as a 2x2 rotation matrix. @@ -143,7 +143,7 @@ impl Isometry> { } } -impl Isometry> { +impl Isometry> { /// Creates a new 2D isometry from a translation and a rotation angle. /// /// Its rotational part is represented as an unit complex number. @@ -181,7 +181,7 @@ impl Isometry> { // 3D rotation. macro_rules! isometry_construction_impl( ($RotId: ident < $($RotParams: ident),*>, $RRDim: ty, $RCDim: ty) => { - impl Isometry> { + impl Isometry> { /// Creates a new isometry from a translation and a rotation axis-angle. /// /// # Example diff --git a/src/geometry/isometry_conversion.rs b/src/geometry/isometry_conversion.rs index 0ce92aca..4a794f55 100644 --- a/src/geometry/isometry_conversion.rs +++ b/src/geometry/isometry_conversion.rs @@ -1,4 +1,4 @@ -use alga::general::{Real, SubsetOf, SupersetOf}; +use alga::general::{RealField, SubsetOf, SupersetOf}; use alga::linear::Rotation; use crate::base::allocator::Allocator; @@ -19,8 +19,8 @@ use crate::geometry::{Isometry, Point, Similarity, SuperTCategoryOf, TAffine, Tr impl SubsetOf> for Isometry where - N1: Real, - N2: Real + SupersetOf, + N1: RealField, + N2: RealField + SupersetOf, R1: Rotation> + SubsetOf, R2: Rotation>, DefaultAllocator: Allocator + Allocator, @@ -47,8 +47,8 @@ where impl SubsetOf> for Isometry where - N1: Real, - N2: Real + SupersetOf, + N1: RealField, + N2: RealField + SupersetOf, R1: Rotation> + SubsetOf, R2: Rotation>, DefaultAllocator: Allocator + Allocator, @@ -71,8 +71,8 @@ where impl SubsetOf> for Isometry where - N1: Real, - N2: Real + SupersetOf, + N1: RealField, + N2: RealField + SupersetOf, C: SuperTCategoryOf, R: Rotation> + SubsetOf>> @@ -105,8 +105,8 @@ where impl SubsetOf>> for Isometry where - N1: Real, - N2: Real + SupersetOf, + N1: RealField, + N2: RealField + SupersetOf, R: Rotation> + SubsetOf>> + SubsetOf>>, @@ -149,7 +149,7 @@ where } } -impl From> for MatrixN> +impl From> for MatrixN> where D: DimNameAdd, R: SubsetOf>>, diff --git a/src/geometry/isometry_ops.rs b/src/geometry/isometry_ops.rs index b0da4b62..6ba9eb3e 100644 --- a/src/geometry/isometry_ops.rs +++ b/src/geometry/isometry_ops.rs @@ -1,6 +1,6 @@ use std::ops::{Div, DivAssign, Mul, MulAssign}; -use alga::general::Real; +use alga::general::RealField; use alga::linear::Rotation as AlgaRotation; use crate::base::allocator::Allocator; @@ -64,7 +64,7 @@ macro_rules! isometry_binop_impl( ($Op: ident, $op: ident; $lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty, Output = $Output: ty; $action: expr; $($lives: tt),*) => { - impl<$($lives ,)* N: Real, D: DimName, R> $Op<$Rhs> for $Lhs + impl<$($lives ,)* N: RealField, D: DimName, R> $Op<$Rhs> for $Lhs where R: AlgaRotation>, DefaultAllocator: Allocator { type Output = $Output; @@ -111,7 +111,7 @@ macro_rules! isometry_binop_assign_impl_all( $lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty; [val] => $action_val: expr; [ref] => $action_ref: expr;) => { - impl $OpAssign<$Rhs> for $Lhs + impl $OpAssign<$Rhs> for $Lhs where R: AlgaRotation>, DefaultAllocator: Allocator { #[inline] @@ -120,7 +120,7 @@ macro_rules! isometry_binop_assign_impl_all( } } - impl<'b, N: Real, D: DimName, R> $OpAssign<&'b $Rhs> for $Lhs + impl<'b, N: RealField, D: DimName, R> $OpAssign<&'b $Rhs> for $Lhs where R: AlgaRotation>, DefaultAllocator: Allocator { #[inline] @@ -286,7 +286,7 @@ macro_rules! isometry_from_composition_impl( ($R1: ty, $C1: ty),($R2: ty, $C2: ty) $(for $Dims: ident: $DimsBound: ident),*; $lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty, Output = $Output: ty; $action: expr; $($lives: tt),*) => { - impl<$($lives ,)* N: Real $(, $Dims: $DimsBound)*> $Op<$Rhs> for $Lhs + impl<$($lives ,)* N: RealField $(, $Dims: $DimsBound)*> $Op<$Rhs> for $Lhs where DefaultAllocator: Allocator + Allocator { type Output = $Output; diff --git a/src/geometry/orthographic.rs b/src/geometry/orthographic.rs index af86a876..2c713118 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::Real; +use alga::general::RealField; use crate::base::dimension::U3; use crate::base::helper; @@ -17,26 +17,26 @@ use crate::base::{Matrix4, Vector, Vector3}; use crate::geometry::{Point3, Projective3}; /// A 3D orthographic projection stored as an homogeneous 4x4 matrix. -pub struct Orthographic3 { +pub struct Orthographic3 { matrix: Matrix4, } -impl Copy for Orthographic3 {} +impl Copy for Orthographic3 {} -impl Clone for Orthographic3 { +impl Clone for Orthographic3 { #[inline] fn clone(&self) -> Self { Self::from_matrix_unchecked(self.matrix.clone()) } } -impl fmt::Debug for Orthographic3 { +impl fmt::Debug for Orthographic3 { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { self.matrix.fmt(f) } } -impl PartialEq for Orthographic3 { +impl PartialEq for Orthographic3 { #[inline] fn eq(&self, right: &Self) -> bool { self.matrix == right.matrix @@ -44,7 +44,7 @@ impl PartialEq for Orthographic3 { } #[cfg(feature = "serde-serialize")] -impl Serialize for Orthographic3 { +impl Serialize for Orthographic3 { fn serialize(&self, serializer: S) -> Result where S: Serializer { self.matrix.serialize(serializer) @@ -52,7 +52,7 @@ impl Serialize for Orthographic3 { } #[cfg(feature = "serde-serialize")] -impl<'a, N: Real + Deserialize<'a>> Deserialize<'a> for Orthographic3 { +impl<'a, N: RealField + Deserialize<'a>> Deserialize<'a> for Orthographic3 { fn deserialize(deserializer: Des) -> Result where Des: Deserializer<'a> { let matrix = Matrix4::::deserialize(deserializer)?; @@ -61,7 +61,7 @@ impl<'a, N: Real + Deserialize<'a>> Deserialize<'a> for Orthographic3 { } } -impl Orthographic3 { +impl Orthographic3 { /// Creates a new orthographic projection matrix. /// /// This follows the OpenGL convention, so this will flip the `z` axis. @@ -678,7 +678,7 @@ impl Orthographic3 { } } -impl Distribution> for Standard +impl Distribution> for Standard where Standard: Distribution { fn sample(&self, r: &mut R) -> Orthographic3 { @@ -694,7 +694,7 @@ where Standard: Distribution } #[cfg(feature = "arbitrary")] -impl Arbitrary for Orthographic3 +impl Arbitrary for Orthographic3 where Matrix4: Send { fn arbitrary(g: &mut G) -> Self { @@ -709,7 +709,7 @@ where Matrix4: Send } } -impl From> for Matrix4 { +impl From> for Matrix4 { #[inline] fn from(orth: Orthographic3) -> Self { orth.into_inner() diff --git a/src/geometry/perspective.rs b/src/geometry/perspective.rs index c8125d99..8020c0cf 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::Real; +use alga::general::RealField; use crate::base::dimension::U3; use crate::base::helper; @@ -22,22 +22,22 @@ pub struct Perspective3 { matrix: Matrix4, } -impl Copy for Perspective3 {} +impl Copy for Perspective3 {} -impl Clone for Perspective3 { +impl Clone for Perspective3 { #[inline] fn clone(&self) -> Self { Self::from_matrix_unchecked(self.matrix.clone()) } } -impl fmt::Debug for Perspective3 { +impl fmt::Debug for Perspective3 { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { self.matrix.fmt(f) } } -impl PartialEq for Perspective3 { +impl PartialEq for Perspective3 { #[inline] fn eq(&self, right: &Self) -> bool { self.matrix == right.matrix @@ -45,7 +45,7 @@ impl PartialEq for Perspective3 { } #[cfg(feature = "serde-serialize")] -impl Serialize for Perspective3 { +impl Serialize for Perspective3 { fn serialize(&self, serializer: S) -> Result where S: Serializer { self.matrix.serialize(serializer) @@ -53,7 +53,7 @@ impl Serialize for Perspective3 { } #[cfg(feature = "serde-serialize")] -impl<'a, N: Real + Deserialize<'a>> Deserialize<'a> for Perspective3 { +impl<'a, N: RealField + Deserialize<'a>> Deserialize<'a> for Perspective3 { fn deserialize(deserializer: Des) -> Result where Des: Deserializer<'a> { let matrix = Matrix4::::deserialize(deserializer)?; @@ -62,7 +62,7 @@ impl<'a, N: Real + Deserialize<'a>> Deserialize<'a> for Perspective3 { } } -impl Perspective3 { +impl Perspective3 { /// Creates a new perspective matrix from the aspect ratio, y field of view, and near/far planes. pub fn new(aspect: N, fovy: N, znear: N, zfar: N) -> Self { assert!( @@ -261,7 +261,7 @@ impl Perspective3 { } } -impl Distribution> for Standard +impl Distribution> for Standard where Standard: Distribution { fn sample<'a, R: Rng + ?Sized>(&self, r: &'a mut R) -> Perspective3 { @@ -274,7 +274,7 @@ where Standard: Distribution } #[cfg(feature = "arbitrary")] -impl Arbitrary for Perspective3 { +impl Arbitrary for Perspective3 { fn arbitrary(g: &mut G) -> Self { let znear = Arbitrary::arbitrary(g); let zfar = helper::reject(g, |&x: &N| !(x - znear).is_zero()); @@ -284,7 +284,7 @@ impl Arbitrary for Perspective3 { } } -impl From> for Matrix4 { +impl From> for Matrix4 { #[inline] fn from(orth: Perspective3) -> Self { orth.into_inner() diff --git a/src/geometry/point_alga.rs b/src/geometry/point_alga.rs index c95cb5b2..162e6c68 100644 --- a/src/geometry/point_alga.rs +++ b/src/geometry/point_alga.rs @@ -1,4 +1,4 @@ -use alga::general::{Field, JoinSemilattice, Lattice, MeetSemilattice, Real}; +use alga::general::{Field, JoinSemilattice, Lattice, MeetSemilattice, RealField}; use alga::linear::{AffineSpace, EuclideanSpace}; use crate::base::allocator::Allocator; @@ -15,11 +15,11 @@ where type Translation = VectorN; } -impl EuclideanSpace for Point +impl EuclideanSpace for Point where DefaultAllocator: Allocator { type Coordinates = VectorN; - type Real = N; + type RealField = N; #[inline] fn origin() -> Self { diff --git a/src/geometry/quaternion.rs b/src/geometry/quaternion.rs index 3beab4bb..5306f9c1 100644 --- a/src/geometry/quaternion.rs +++ b/src/geometry/quaternion.rs @@ -13,7 +13,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; #[cfg(feature = "abomonation-serialize")] use abomonation::Abomonation; -use alga::general::Real; +use alga::general::RealField; use crate::base::dimension::{U1, U3, U4}; use crate::base::storage::{CStride, RStride}; @@ -25,13 +25,13 @@ use crate::geometry::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 +47,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 +57,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 +73,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 +83,7 @@ where Owned: Serialize } #[cfg(feature = "serde-serialize")] -impl<'a, N: Real> Deserialize<'a> for Quaternion +impl<'a, N: RealField> Deserialize<'a> for Quaternion where Owned: Deserialize<'a> { fn deserialize(deserializer: Des) -> Result @@ -94,7 +94,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.")] @@ -508,7 +508,7 @@ impl Quaternion { } } -impl> AbsDiffEq for Quaternion { +impl> AbsDiffEq for Quaternion { type Epsilon = N; #[inline] @@ -524,7 +524,7 @@ impl> AbsDiffEq for Quaternion { } } -impl> RelativeEq for Quaternion { +impl> RelativeEq for Quaternion { #[inline] fn default_max_relative() -> Self::Epsilon { N::default_max_relative() @@ -544,7 +544,7 @@ impl> RelativeEq for Quaternion { } } -impl> UlpsEq for Quaternion { +impl> UlpsEq for Quaternion { #[inline] fn default_max_ulps() -> u32 { N::default_max_ulps() @@ -558,7 +558,7 @@ impl> UlpsEq for Quaternion { } } -impl fmt::Display for Quaternion { +impl fmt::Display for Quaternion { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, @@ -571,7 +571,7 @@ impl fmt::Display for Quaternion { /// A unit quaternions. May be used to represent a rotation. pub type UnitQuaternion = Unit>; -impl UnitQuaternion { +impl UnitQuaternion { /// Moves this unit quaternion into one that owns its data. #[inline] #[deprecated( @@ -1007,7 +1007,7 @@ impl UnitQuaternion { } } -impl fmt::Display for UnitQuaternion { +impl fmt::Display for UnitQuaternion { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if let Some(axis) = self.axis() { let axis = axis.into_inner(); @@ -1029,7 +1029,7 @@ impl fmt::Display for UnitQuaternion { } } -impl> AbsDiffEq for UnitQuaternion { +impl> AbsDiffEq for UnitQuaternion { type Epsilon = N; #[inline] @@ -1043,7 +1043,7 @@ impl> AbsDiffEq for UnitQuaternion { } } -impl> RelativeEq for UnitQuaternion { +impl> RelativeEq for UnitQuaternion { #[inline] fn default_max_relative() -> Self::Epsilon { N::default_max_relative() @@ -1062,7 +1062,7 @@ impl> RelativeEq for UnitQuaternion { } } -impl> UlpsEq for UnitQuaternion { +impl> UlpsEq for UnitQuaternion { #[inline] fn default_max_ulps() -> u32 { N::default_max_ulps() diff --git a/src/geometry/quaternion_alga.rs b/src/geometry/quaternion_alga.rs index a73beff7..d9864cb1 100644 --- a/src/geometry/quaternion_alga.rs +++ b/src/geometry/quaternion_alga.rs @@ -3,7 +3,7 @@ use num::Zero; use alga::general::{ AbstractGroup, AbstractGroupAbelian, AbstractLoop, AbstractMagma, AbstractModule, AbstractMonoid, AbstractQuasigroup, AbstractSemigroup, Additive, Id, Identity, TwoSidedInverse, Module, - Multiplicative, Real, + Multiplicative, RealField, }; use alga::linear::{ AffineTransformation, DirectIsometry, FiniteDimVectorSpace, Isometry, NormedSpace, @@ -14,35 +14,35 @@ use alga::linear::{ use crate::base::{Vector3, Vector4}; use crate::geometry::{Point3, Quaternion, UnitQuaternion}; -impl Identity for Quaternion { +impl Identity for Quaternion { #[inline] fn identity() -> Self { Self::identity() } } -impl Identity for Quaternion { +impl Identity for Quaternion { #[inline] fn identity() -> Self { Self::zero() } } -impl AbstractMagma for Quaternion { +impl AbstractMagma for Quaternion { #[inline] fn operate(&self, rhs: &Self) -> Self { self * rhs } } -impl AbstractMagma for Quaternion { +impl AbstractMagma for Quaternion { #[inline] fn operate(&self, rhs: &Self) -> Self { self + rhs } } -impl TwoSidedInverse for Quaternion { +impl TwoSidedInverse for Quaternion { #[inline] fn two_sided_inverse(&self) -> Self { -self @@ -51,7 +51,7 @@ impl TwoSidedInverse for Quaternion { macro_rules! impl_structures( ($Quaternion: ident; $($marker: ident<$operator: ident>),* $(,)*) => {$( - impl $marker<$operator> for $Quaternion { } + impl $marker<$operator> for $Quaternion { } )*} ); @@ -73,7 +73,7 @@ impl_structures!( * Vector space. * */ -impl AbstractModule for Quaternion { +impl AbstractModule for Quaternion { type AbstractRing = N; #[inline] @@ -82,15 +82,15 @@ impl AbstractModule for Quaternion { } } -impl Module for Quaternion { +impl Module for Quaternion { type Ring = N; } -impl VectorSpace for Quaternion { +impl VectorSpace for Quaternion { type Field = N; } -impl FiniteDimVectorSpace for Quaternion { +impl FiniteDimVectorSpace for Quaternion { #[inline] fn dimension() -> usize { 4 @@ -117,8 +117,8 @@ impl FiniteDimVectorSpace for Quaternion { } } -impl NormedSpace for Quaternion { - type Real = N; +impl NormedSpace for Quaternion { + type RealField = N; type ComplexField = N; #[inline] @@ -162,21 +162,21 @@ impl NormedSpace for Quaternion { * Implementations for UnitQuaternion. * */ -impl Identity for UnitQuaternion { +impl Identity for UnitQuaternion { #[inline] fn identity() -> Self { Self::identity() } } -impl AbstractMagma for UnitQuaternion { +impl AbstractMagma for UnitQuaternion { #[inline] fn operate(&self, rhs: &Self) -> Self { self * rhs } } -impl TwoSidedInverse for UnitQuaternion { +impl TwoSidedInverse for UnitQuaternion { #[inline] fn two_sided_inverse(&self) -> Self { self.inverse() @@ -197,7 +197,7 @@ impl_structures!( AbstractGroup ); -impl Transformation> for UnitQuaternion { +impl Transformation> for UnitQuaternion { #[inline] fn transform_point(&self, pt: &Point3) -> Point3 { self * pt @@ -209,7 +209,7 @@ impl Transformation> for UnitQuaternion { } } -impl ProjectiveTransformation> for UnitQuaternion { +impl ProjectiveTransformation> for UnitQuaternion { #[inline] fn inverse_transform_point(&self, pt: &Point3) -> Point3 { // FIXME: would it be useful performancewise not to call inverse explicitly (i-e. implement @@ -223,7 +223,7 @@ impl ProjectiveTransformation> for UnitQuaternion { } } -impl AffineTransformation> for UnitQuaternion { +impl AffineTransformation> for UnitQuaternion { type Rotation = Self; type NonUniformScaling = Id; type Translation = Id; @@ -264,7 +264,7 @@ impl AffineTransformation> for UnitQuaternion { } } -impl Similarity> for UnitQuaternion { +impl Similarity> for UnitQuaternion { type Scaling = Id; #[inline] @@ -285,13 +285,13 @@ impl Similarity> for UnitQuaternion { macro_rules! marker_impl( ($($Trait: ident),*) => {$( - impl $Trait> for UnitQuaternion { } + impl $Trait> for UnitQuaternion { } )*} ); marker_impl!(Isometry, DirectIsometry, OrthogonalTransformation); -impl Rotation> for UnitQuaternion { +impl Rotation> for UnitQuaternion { #[inline] fn powf(&self, n: N) -> Option { Some(self.powf(n)) diff --git a/src/geometry/quaternion_construction.rs b/src/geometry/quaternion_construction.rs index ff72061f..132ede13 100644 --- a/src/geometry/quaternion_construction.rs +++ b/src/geometry/quaternion_construction.rs @@ -9,7 +9,7 @@ use num::{One, Zero}; use rand::distributions::{Distribution, OpenClosed01, Standard}; use rand::Rng; -use alga::general::Real; +use alga::general::RealField; use crate::base::dimension::U3; use crate::base::storage::Storage; @@ -19,7 +19,7 @@ use crate::base::{Unit, Vector, Vector4, Matrix3}; 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] @@ -96,14 +96,14 @@ impl Quaternion { } } -impl One for Quaternion { +impl One for Quaternion { #[inline] fn one() -> Self { Self::identity() } } -impl Zero for Quaternion { +impl Zero for Quaternion { #[inline] fn zero() -> Self { Self::new(N::zero(), N::zero(), N::zero(), N::zero()) @@ -115,7 +115,7 @@ impl Zero for Quaternion { } } -impl Distribution> for Standard +impl Distribution> for Standard where Standard: Distribution { #[inline] @@ -125,7 +125,7 @@ where Standard: Distribution } #[cfg(feature = "arbitrary")] -impl Arbitrary for Quaternion +impl Arbitrary for Quaternion where Owned: Send { #[inline] @@ -139,7 +139,7 @@ where Owned: Send } } -impl UnitQuaternion { +impl UnitQuaternion { /// The rotation identity. /// /// # Example @@ -669,14 +669,14 @@ impl UnitQuaternion { } } -impl One for UnitQuaternion { +impl One for UnitQuaternion { #[inline] fn one() -> Self { Self::identity() } } -impl Distribution> for Standard +impl Distribution> for Standard where OpenClosed01: Distribution { /// Generate a uniformly distributed random rotation quaternion. @@ -701,7 +701,7 @@ where OpenClosed01: Distribution } #[cfg(feature = "arbitrary")] -impl Arbitrary for UnitQuaternion +impl Arbitrary for UnitQuaternion where Owned: Send, Owned: Send, diff --git a/src/geometry/quaternion_conversion.rs b/src/geometry/quaternion_conversion.rs index cd5d9f0c..4ac8b5a7 100644 --- a/src/geometry/quaternion_conversion.rs +++ b/src/geometry/quaternion_conversion.rs @@ -1,6 +1,6 @@ use num::Zero; -use alga::general::{Real, SubsetOf, SupersetOf}; +use alga::general::{RealField, SubsetOf, SupersetOf}; use alga::linear::Rotation as AlgaRotation; #[cfg(feature = "mint")] @@ -34,8 +34,8 @@ use crate::geometry::{ impl SubsetOf> for Quaternion where - N1: Real, - N2: Real + SupersetOf, + N1: RealField, + N2: RealField + SupersetOf, { #[inline] fn to_superset(&self) -> Quaternion { @@ -57,8 +57,8 @@ where impl SubsetOf> for UnitQuaternion where - N1: Real, - N2: Real + SupersetOf, + N1: RealField, + N2: RealField + SupersetOf, { #[inline] fn to_superset(&self) -> UnitQuaternion { @@ -78,8 +78,8 @@ where impl SubsetOf> for UnitQuaternion where - N1: Real, - N2: Real + SupersetOf, + N1: RealField, + N2: RealField + SupersetOf, { #[inline] fn to_superset(&self) -> Rotation3 { @@ -101,8 +101,8 @@ where impl SubsetOf> for UnitQuaternion where - N1: Real, - N2: Real + SupersetOf, + N1: RealField, + N2: RealField + SupersetOf, R: AlgaRotation> + SupersetOf, { #[inline] @@ -123,8 +123,8 @@ where impl SubsetOf> for UnitQuaternion where - N1: Real, - N2: Real + SupersetOf, + N1: RealField, + N2: RealField + SupersetOf, R: AlgaRotation> + SupersetOf, { #[inline] @@ -145,8 +145,8 @@ where impl SubsetOf> for UnitQuaternion where - N1: Real, - N2: Real + SupersetOf, + N1: RealField, + N2: RealField + SupersetOf, C: SuperTCategoryOf, { #[inline] @@ -165,7 +165,7 @@ where } } -impl> SubsetOf> for UnitQuaternion { +impl> SubsetOf> for UnitQuaternion { #[inline] fn to_superset(&self) -> Matrix4 { self.to_homogeneous().to_superset() @@ -184,14 +184,14 @@ impl> SubsetOf> for UnitQuaterni } #[cfg(feature = "mint")] -impl From> for Quaternion { +impl From> for Quaternion { fn from(q: mint::Quaternion) -> Self { Self::new(q.s, q.v.x, q.v.y, q.v.z) } } #[cfg(feature = "mint")] -impl Into> for Quaternion { +impl Into> for Quaternion { fn into(self) -> mint::Quaternion { mint::Quaternion { v: mint::Vector3 { @@ -205,7 +205,7 @@ impl Into> for Quaternion { } #[cfg(feature = "mint")] -impl Into> for UnitQuaternion { +impl Into> for UnitQuaternion { fn into(self) -> mint::Quaternion { mint::Quaternion { v: mint::Vector3 { @@ -218,35 +218,35 @@ impl Into> for UnitQuaternion { } } -impl From> for Matrix4 { +impl From> for Matrix4 { #[inline] fn from(q: UnitQuaternion) -> Self { q.to_homogeneous() } } -impl From> for Rotation3 { +impl From> for Rotation3 { #[inline] fn from(q: UnitQuaternion) -> Self { q.to_rotation_matrix() } } -impl From> for UnitQuaternion { +impl From> for UnitQuaternion { #[inline] fn from(q: Rotation3) -> Self { Self::from_rotation_matrix(&q) } } -impl From> for Matrix3 { +impl From> for Matrix3 { #[inline] fn from(q: UnitQuaternion) -> Self { q.to_rotation_matrix().into_inner() } } -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 05d5af13..a9399f18 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::Real; +use alga::general::RealField; 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 3fc840ff..5e31364b 100644 --- a/src/geometry/quaternion_ops.rs +++ b/src/geometry/quaternion_ops.rs @@ -54,7 +54,7 @@ use std::ops::{ Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign, }; -use alga::general::Real; +use alga::general::RealField; use crate::base::allocator::Allocator; use crate::base::dimension::{U1, U3, U4}; @@ -63,7 +63,7 @@ use crate::base::{DefaultAllocator, Unit, Vector, Vector3}; use crate::geometry::{Point3, Quaternion, Rotation, UnitQuaternion}; -impl Index for Quaternion { +impl Index for Quaternion { type Output = N; #[inline] @@ -72,7 +72,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 +85,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: Real $(, $Storage: $StoragesBound $(<$($BoundParam),*>)*)*> $Op<$Rhs> for $Lhs + impl<$($lives ,)* N: RealField $(, $Storage: $StoragesBound $(<$($BoundParam),*>)*)*> $Op<$Rhs> for $Lhs where DefaultAllocator: Allocator + Allocator { type Output = $Result; @@ -490,7 +490,7 @@ quaternion_op_impl!( 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 +499,7 @@ macro_rules! scalar_op_impl( } } - impl<'a, N: Real> $Op for &'a Quaternion { + impl<'a, N: RealField> $Op for &'a Quaternion { type Output = Quaternion; #[inline] @@ -508,7 +508,7 @@ macro_rules! scalar_op_impl( } } - impl $OpAssign for Quaternion { + impl $OpAssign for Quaternion { #[inline] fn $op_assign(&mut self, n: N) { @@ -547,7 +547,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 +556,7 @@ impl Neg for Quaternion { } } -impl<'a, N: Real> Neg for &'a Quaternion { +impl<'a, N: RealField> Neg for &'a Quaternion { type Output = Quaternion; #[inline] @@ -570,7 +570,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: Real> $OpAssign<$Rhs> for $Lhs + impl<$($lives ,)* N: RealField> $OpAssign<$Rhs> for $Lhs where DefaultAllocator: Allocator + Allocator { diff --git a/src/geometry/rotation.rs b/src/geometry/rotation.rs index 21e240fe..f5d0ad30 100644 --- 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::Real; +use alga::general::RealField; use crate::base::allocator::Allocator; use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; @@ -429,7 +429,7 @@ where */ impl fmt::Display for Rotation where - N: Real + fmt::Display, + N: RealField + fmt::Display, DefaultAllocator: Allocator + Allocator, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { diff --git a/src/geometry/rotation_alga.rs b/src/geometry/rotation_alga.rs index e5c1edad..46bdaa8d 100644 --- a/src/geometry/rotation_alga.rs +++ b/src/geometry/rotation_alga.rs @@ -1,6 +1,6 @@ use alga::general::{ AbstractGroup, AbstractLoop, AbstractMagma, AbstractMonoid, AbstractQuasigroup, - AbstractSemigroup, Id, Identity, TwoSidedInverse, Multiplicative, Real, + AbstractSemigroup, Id, Identity, TwoSidedInverse, Multiplicative, RealField, }; use alga::linear::{ self, AffineTransformation, DirectIsometry, Isometry, OrthogonalTransformation, @@ -18,7 +18,7 @@ use crate::geometry::{Point, Rotation}; * Algebraic structures. * */ -impl Identity for Rotation +impl Identity for Rotation where DefaultAllocator: Allocator { #[inline] @@ -27,7 +27,7 @@ where DefaultAllocator: Allocator } } -impl TwoSidedInverse for Rotation +impl TwoSidedInverse for Rotation where DefaultAllocator: Allocator { #[inline] @@ -41,7 +41,7 @@ where DefaultAllocator: Allocator } } -impl AbstractMagma for Rotation +impl AbstractMagma for Rotation where DefaultAllocator: Allocator { #[inline] @@ -52,7 +52,7 @@ where DefaultAllocator: Allocator macro_rules! impl_multiplicative_structures( ($($marker: ident<$operator: ident>),* $(,)*) => {$( - impl $marker<$operator> for Rotation + impl $marker<$operator> for Rotation where DefaultAllocator: Allocator { } )*} ); @@ -70,7 +70,7 @@ impl_multiplicative_structures!( * Transformation groups. * */ -impl Transformation> for Rotation +impl Transformation> for Rotation where DefaultAllocator: Allocator + Allocator { #[inline] @@ -84,7 +84,7 @@ where DefaultAllocator: Allocator + Allocator } } -impl ProjectiveTransformation> for Rotation +impl ProjectiveTransformation> for Rotation where DefaultAllocator: Allocator + Allocator { #[inline] @@ -98,7 +98,7 @@ where DefaultAllocator: Allocator + Allocator } } -impl AffineTransformation> for Rotation +impl AffineTransformation> for Rotation where DefaultAllocator: Allocator + Allocator { type Rotation = Self; @@ -141,7 +141,7 @@ where DefaultAllocator: Allocator + Allocator } } -impl Similarity> for Rotation +impl Similarity> for Rotation where DefaultAllocator: Allocator + Allocator { type Scaling = Id; @@ -164,7 +164,7 @@ where DefaultAllocator: Allocator + Allocator macro_rules! marker_impl( ($($Trait: ident),*) => {$( - impl $Trait> for Rotation + impl $Trait> for Rotation where DefaultAllocator: Allocator + Allocator { } )*} @@ -173,7 +173,7 @@ macro_rules! marker_impl( marker_impl!(Isometry, DirectIsometry, OrthogonalTransformation); /// Subgroups of the n-dimensional rotation group `SO(n)`. -impl linear::Rotation> for Rotation +impl linear::Rotation> for Rotation where DefaultAllocator: Allocator + Allocator { #[inline] @@ -199,7 +199,7 @@ where DefaultAllocator: Allocator + Allocator } /* -impl Matrix for Rotation { +impl Matrix for Rotation { type Field = N; type Row = Matrix; type Column = Matrix; @@ -241,7 +241,7 @@ impl Matrix for Rotation { } } -impl SquareMatrix for Rotation { +impl SquareMatrix for Rotation { type Vector = Matrix; #[inline] @@ -271,5 +271,5 @@ impl SquareMatrix for Rotation { } } -impl InversibleSquareMatrix for Rotation { } +impl InversibleSquareMatrix for Rotation { } */ diff --git a/src/geometry/rotation_conversion.rs b/src/geometry/rotation_conversion.rs index 6adee2d8..ac314221 100644 --- a/src/geometry/rotation_conversion.rs +++ b/src/geometry/rotation_conversion.rs @@ -1,6 +1,6 @@ use num::Zero; -use alga::general::{Real, SubsetOf, SupersetOf}; +use alga::general::{RealField, SubsetOf, SupersetOf}; use alga::linear::Rotation as AlgaRotation; #[cfg(feature = "mint")] @@ -32,8 +32,8 @@ use crate::geometry::{ impl SubsetOf> for Rotation where - N1: Real, - N2: Real + SupersetOf, + N1: RealField, + N2: RealField + SupersetOf, DefaultAllocator: Allocator + Allocator, { #[inline] @@ -54,8 +54,8 @@ where impl SubsetOf> for Rotation3 where - N1: Real, - N2: Real + SupersetOf, + N1: RealField, + N2: RealField + SupersetOf, { #[inline] fn to_superset(&self) -> UnitQuaternion { @@ -77,8 +77,8 @@ where impl SubsetOf> for Rotation2 where - N1: Real, - N2: Real + SupersetOf, + N1: RealField, + N2: RealField + SupersetOf, { #[inline] fn to_superset(&self) -> UnitComplex { @@ -100,8 +100,8 @@ where impl SubsetOf> for Rotation where - N1: Real, - N2: Real + SupersetOf, + N1: RealField, + N2: RealField + SupersetOf, R: AlgaRotation> + SupersetOf, DefaultAllocator: Allocator + Allocator, { @@ -123,8 +123,8 @@ where impl SubsetOf> for Rotation where - N1: Real, - N2: Real + SupersetOf, + N1: RealField, + N2: RealField + SupersetOf, R: AlgaRotation> + SupersetOf, DefaultAllocator: Allocator + Allocator, { @@ -146,8 +146,8 @@ where impl SubsetOf> for Rotation where - N1: Real, - N2: Real + SupersetOf, + N1: RealField, + N2: RealField + SupersetOf, C: SuperTCategoryOf, D: DimNameAdd + DimMin, // needed by .is_special_orthogonal() DefaultAllocator: Allocator @@ -175,8 +175,8 @@ where impl SubsetOf>> for Rotation where - N1: Real, - N2: Real + SupersetOf, + N1: RealField, + N2: RealField + SupersetOf, D: DimNameAdd + DimMin, // needed by .is_special_orthogonal() DefaultAllocator: Allocator + Allocator @@ -211,34 +211,34 @@ where } #[cfg(feature = "mint")] -impl From> for Rotation3 { +impl From> for Rotation3 { fn from(euler: mint::EulerAngles) -> Self { Self::from_euler_angles(euler.a, euler.b, euler.c) } } -impl From> for Matrix3 { +impl From> for Matrix3 { #[inline] fn from(q: Rotation2) ->Self { q.to_homogeneous() } } -impl From> for Matrix2 { +impl From> for Matrix2 { #[inline] fn from(q: Rotation2) -> Self { q.into_inner() } } -impl From> for Matrix4 { +impl From> for Matrix4 { #[inline] fn from(q: Rotation3) -> Self { q.to_homogeneous() } } -impl From> for Matrix3 { +impl From> for Matrix3 { #[inline] fn from(q: Rotation3) -> Self { q.into_inner() diff --git a/src/geometry/rotation_specialization.rs b/src/geometry/rotation_specialization.rs index 95fa3c07..8d40a51e 100644 --- a/src/geometry/rotation_specialization.rs +++ b/src/geometry/rotation_specialization.rs @@ -3,7 +3,7 @@ use crate::base::storage::Owned; #[cfg(feature = "arbitrary")] use quickcheck::{Arbitrary, Gen}; -use alga::general::Real; +use alga::general::RealField; use num::Zero; use rand::distributions::{Distribution, OpenClosed01, Standard}; use rand::Rng; @@ -20,7 +20,7 @@ use crate::geometry::{Rotation2, Rotation3, UnitComplex, UnitQuaternion}; * 2D Rotation matrix. * */ -impl Rotation2 { +impl Rotation2 { /// Builds a 2 dimensional rotation matrix from an angle in radian. /// /// # Example @@ -232,7 +232,7 @@ impl Rotation2 { } } -impl Distribution> for Standard +impl Distribution> for Standard where OpenClosed01: Distribution { /// Generate a uniformly distributed random rotation. @@ -243,7 +243,7 @@ where OpenClosed01: Distribution } #[cfg(feature = "arbitrary")] -impl Arbitrary for Rotation2 +impl Arbitrary for Rotation2 where Owned: Send { #[inline] @@ -257,7 +257,7 @@ where Owned: Send * 3D Rotation matrix. * */ -impl Rotation3 { +impl Rotation3 { /// Builds a 3 dimensional rotation matrix from an axis and an angle. /// /// # Arguments @@ -819,7 +819,7 @@ impl Rotation3 { } } -impl Distribution> for Standard +impl Distribution> for Standard where OpenClosed01: Distribution { /// Generate a uniformly distributed random rotation. @@ -859,7 +859,7 @@ where OpenClosed01: Distribution } #[cfg(feature = "arbitrary")] -impl Arbitrary for Rotation3 +impl Arbitrary for Rotation3 where Owned: Send, Owned: Send, diff --git a/src/geometry/similarity.rs b/src/geometry/similarity.rs index f0bc6d2e..14e50af0 100644 --- a/src/geometry/similarity.rs +++ b/src/geometry/similarity.rs @@ -10,7 +10,7 @@ use serde::{Deserialize, Serialize}; #[cfg(feature = "abomonation-serialize")] use abomonation::Abomonation; -use alga::general::{Real, SubsetOf}; +use alga::general::{RealField, SubsetOf}; use alga::linear::Rotation; use crate::base::allocator::Allocator; @@ -41,7 +41,7 @@ use crate::geometry::{Isometry, Point, Translation}; Owned: Deserialize<'de>" )) )] -pub struct Similarity +pub struct Similarity where DefaultAllocator: Allocator { /// The part of this similarity that does not include the scaling factor. @@ -50,7 +50,7 @@ where DefaultAllocator: Allocator } #[cfg(feature = "abomonation-serialize")] -impl Abomonation for Similarity +impl Abomonation for Similarity where Isometry: Abomonation, DefaultAllocator: Allocator, @@ -68,7 +68,7 @@ where } } -impl hash::Hash +impl hash::Hash for Similarity where DefaultAllocator: Allocator, @@ -80,13 +80,13 @@ 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] @@ -95,7 +95,7 @@ where DefaultAllocator: Allocator } } -impl Similarity +impl Similarity where R: Rotation>, DefaultAllocator: Allocator, @@ -244,7 +244,7 @@ where // and makes it harder to use it, e.g., for Transform × Isometry implementation. // This is OK since all constructors of the isometry enforce the Rotation bound already (and // explicit struct construction is prevented by the private scaling factor). -impl Similarity +impl Similarity where DefaultAllocator: Allocator { /// Converts this similarity into its equivalent homogeneous transformation matrix. @@ -265,13 +265,13 @@ where DefaultAllocator: Allocator } } -impl Eq for Similarity +impl Eq for Similarity where R: Rotation> + Eq, DefaultAllocator: Allocator, {} -impl PartialEq for Similarity +impl PartialEq for Similarity where R: Rotation> + PartialEq, DefaultAllocator: Allocator, @@ -282,7 +282,7 @@ where } } -impl AbsDiffEq for Similarity +impl AbsDiffEq for Similarity where R: Rotation> + AbsDiffEq, DefaultAllocator: Allocator, @@ -302,7 +302,7 @@ where } } -impl RelativeEq for Similarity +impl RelativeEq for Similarity where R: Rotation> + RelativeEq, DefaultAllocator: Allocator, @@ -329,7 +329,7 @@ where } } -impl UlpsEq for Similarity +impl UlpsEq for Similarity where R: Rotation> + UlpsEq, DefaultAllocator: Allocator, @@ -354,7 +354,7 @@ where */ impl fmt::Display for Similarity where - N: Real + fmt::Display, + N: RealField + fmt::Display, R: Rotation> + fmt::Display, DefaultAllocator: Allocator + Allocator, { diff --git a/src/geometry/similarity_alga.rs b/src/geometry/similarity_alga.rs index 9aaefe48..122ec7b2 100644 --- a/src/geometry/similarity_alga.rs +++ b/src/geometry/similarity_alga.rs @@ -1,6 +1,6 @@ use alga::general::{ AbstractGroup, AbstractLoop, AbstractMagma, AbstractMonoid, AbstractQuasigroup, - AbstractSemigroup, Identity, TwoSidedInverse, Multiplicative, Real, + AbstractSemigroup, Identity, TwoSidedInverse, Multiplicative, RealField, }; use alga::linear::Similarity as AlgaSimilarity; use alga::linear::{AffineTransformation, ProjectiveTransformation, Rotation, Transformation}; @@ -16,7 +16,7 @@ use crate::geometry::{Point, Similarity, Translation}; * Algebraic structures. * */ -impl Identity for Similarity +impl Identity for Similarity where R: Rotation>, DefaultAllocator: Allocator, @@ -27,7 +27,7 @@ where } } -impl TwoSidedInverse for Similarity +impl TwoSidedInverse for Similarity where R: Rotation>, DefaultAllocator: Allocator, @@ -43,7 +43,7 @@ where } } -impl AbstractMagma for Similarity +impl AbstractMagma for Similarity where R: Rotation>, DefaultAllocator: Allocator, @@ -56,7 +56,7 @@ where macro_rules! impl_multiplicative_structures( ($($marker: ident<$operator: ident>),* $(,)*) => {$( - impl $marker<$operator> for Similarity + impl $marker<$operator> for Similarity where R: Rotation>, DefaultAllocator: Allocator { } )*} @@ -75,7 +75,7 @@ impl_multiplicative_structures!( * Transformation groups. * */ -impl Transformation> for Similarity +impl Transformation> for Similarity where R: Rotation>, DefaultAllocator: Allocator, @@ -91,7 +91,7 @@ where } } -impl ProjectiveTransformation> for Similarity +impl ProjectiveTransformation> for Similarity where R: Rotation>, DefaultAllocator: Allocator, @@ -107,7 +107,7 @@ where } } -impl AffineTransformation> for Similarity +impl AffineTransformation> for Similarity where R: Rotation>, DefaultAllocator: Allocator, @@ -164,7 +164,7 @@ where } } -impl AlgaSimilarity> for Similarity +impl AlgaSimilarity> for Similarity where R: Rotation>, DefaultAllocator: Allocator, diff --git a/src/geometry/similarity_construction.rs b/src/geometry/similarity_construction.rs index 0875c189..a3722ba9 100644 --- a/src/geometry/similarity_construction.rs +++ b/src/geometry/similarity_construction.rs @@ -7,7 +7,7 @@ use num::One; use rand::distributions::{Distribution, Standard}; use rand::Rng; -use alga::general::Real; +use alga::general::RealField; use alga::linear::Rotation as AlgaRotation; use crate::base::allocator::Allocator; @@ -19,7 +19,7 @@ use crate::geometry::{ UnitQuaternion, }; -impl Similarity +impl Similarity where R: AlgaRotation>, DefaultAllocator: Allocator, @@ -45,7 +45,7 @@ where } } -impl One for Similarity +impl One for Similarity where R: AlgaRotation>, DefaultAllocator: Allocator, @@ -57,7 +57,7 @@ where } } -impl Distribution> for Standard +impl Distribution> for Standard where R: AlgaRotation>, DefaultAllocator: Allocator, @@ -74,7 +74,7 @@ where } } -impl Similarity +impl Similarity where R: AlgaRotation>, DefaultAllocator: Allocator, @@ -104,7 +104,7 @@ where #[cfg(feature = "arbitrary")] impl Arbitrary for Similarity where - N: Real + Arbitrary + Send, + N: RealField + Arbitrary + Send, R: AlgaRotation> + Arbitrary + Send, DefaultAllocator: Allocator, Owned: Send, @@ -127,7 +127,7 @@ where */ // 2D rotation. -impl Similarity> { +impl Similarity> { /// Creates a new similarity from a translation, a rotation, and an uniform scaling factor. /// /// # Example @@ -150,7 +150,7 @@ impl Similarity> { } } -impl Similarity> { +impl Similarity> { /// Creates a new similarity from a translation and a rotation angle. /// /// # Example @@ -176,7 +176,7 @@ impl Similarity> { // 3D rotation. macro_rules! similarity_construction_impl( ($Rot: ty) => { - impl Similarity { + impl Similarity { /// Creates a new similarity from a translation, rotation axis-angle, and scaling /// factor. /// diff --git a/src/geometry/similarity_conversion.rs b/src/geometry/similarity_conversion.rs index a040def3..a0d207e4 100644 --- a/src/geometry/similarity_conversion.rs +++ b/src/geometry/similarity_conversion.rs @@ -1,4 +1,4 @@ -use alga::general::{Real, SubsetOf, SupersetOf}; +use alga::general::{RealField, SubsetOf, SupersetOf}; use alga::linear::Rotation; use crate::base::allocator::Allocator; @@ -18,8 +18,8 @@ use crate::geometry::{Isometry, Point, Similarity, SuperTCategoryOf, TAffine, Tr impl SubsetOf> for Similarity where - N1: Real + SubsetOf, - N2: Real + SupersetOf, + N1: RealField + SubsetOf, + N2: RealField + SupersetOf, R1: Rotation> + SubsetOf, R2: Rotation>, DefaultAllocator: Allocator + Allocator, @@ -46,8 +46,8 @@ where impl SubsetOf> for Similarity where - N1: Real, - N2: Real + SupersetOf, + N1: RealField, + N2: RealField + SupersetOf, C: SuperTCategoryOf, R: Rotation> + SubsetOf>> @@ -80,8 +80,8 @@ where impl SubsetOf>> for Similarity where - N1: Real, - N2: Real + SupersetOf, + N1: RealField, + N2: RealField + SupersetOf, R: Rotation> + SubsetOf>> + SubsetOf>>, @@ -163,7 +163,7 @@ where } } -impl From> for MatrixN> +impl From> for MatrixN> where D: DimNameAdd, R: SubsetOf>>, diff --git a/src/geometry/similarity_ops.rs b/src/geometry/similarity_ops.rs index fec4bdeb..80d84b86 100644 --- a/src/geometry/similarity_ops.rs +++ b/src/geometry/similarity_ops.rs @@ -1,6 +1,6 @@ use std::ops::{Div, DivAssign, Mul, MulAssign}; -use alga::general::Real; +use alga::general::RealField; use alga::linear::Rotation as AlgaRotation; use crate::base::allocator::Allocator; @@ -66,7 +66,7 @@ macro_rules! similarity_binop_impl( ($Op: ident, $op: ident; $lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty, Output = $Output: ty; $action: expr; $($lives: tt),*) => { - impl<$($lives ,)* N: Real, D: DimName, R> $Op<$Rhs> for $Lhs + impl<$($lives ,)* N: RealField, D: DimName, R> $Op<$Rhs> for $Lhs where R: AlgaRotation>, DefaultAllocator: Allocator { type Output = $Output; @@ -113,7 +113,7 @@ macro_rules! similarity_binop_assign_impl_all( $lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty; [val] => $action_val: expr; [ref] => $action_ref: expr;) => { - impl $OpAssign<$Rhs> for $Lhs + impl $OpAssign<$Rhs> for $Lhs where R: AlgaRotation>, DefaultAllocator: Allocator { #[inline] @@ -122,7 +122,7 @@ macro_rules! similarity_binop_assign_impl_all( } } - impl<'b, N: Real, D: DimName, R> $OpAssign<&'b $Rhs> for $Lhs + impl<'b, N: RealField, D: DimName, R> $OpAssign<&'b $Rhs> for $Lhs where R: AlgaRotation>, DefaultAllocator: Allocator { #[inline] @@ -379,7 +379,7 @@ macro_rules! similarity_from_composition_impl( ($R1: ty, $C1: ty),($R2: ty, $C2: ty) $(for $Dims: ident: $DimsBound: ident),*; $lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty, Output = $Output: ty; $action: expr; $($lives: tt),*) => { - impl<$($lives ,)* N: Real $(, $Dims: $DimsBound)*> $Op<$Rhs> for $Lhs + impl<$($lives ,)* N: RealField $(, $Dims: $DimsBound)*> $Op<$Rhs> for $Lhs where DefaultAllocator: Allocator + Allocator { type Output = $Output; diff --git a/src/geometry/transform.rs b/src/geometry/transform.rs index 9b62d531..f5cf92a3 100644 --- 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::Real; +use alga::general::RealField; use crate::base::allocator::Allocator; use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; @@ -26,7 +26,7 @@ pub trait TCategory: Any + Debug + Copy + PartialEq + Send { /// Checks that the given matrix is a valid homogeneous representation of an element of the /// category `Self`. - fn check_homogeneous_invariants(mat: &MatrixN) -> bool + fn check_homogeneous_invariants(mat: &MatrixN) -> bool where N::Epsilon: Copy, DefaultAllocator: Allocator; @@ -69,7 +69,7 @@ pub enum TAffine {} impl TCategory for TGeneral { #[inline] - fn check_homogeneous_invariants(_: &MatrixN) -> bool + fn check_homogeneous_invariants(_: &MatrixN) -> bool where N::Epsilon: Copy, DefaultAllocator: Allocator, @@ -80,7 +80,7 @@ impl TCategory for TGeneral { impl TCategory for TProjective { #[inline] - fn check_homogeneous_invariants(mat: &MatrixN) -> bool + fn check_homogeneous_invariants(mat: &MatrixN) -> bool where N::Epsilon: Copy, DefaultAllocator: Allocator, @@ -96,7 +96,7 @@ impl TCategory for TAffine { } #[inline] - fn check_homogeneous_invariants(mat: &MatrixN) -> bool + fn check_homogeneous_invariants(mat: &MatrixN) -> bool where N::Epsilon: Copy, DefaultAllocator: Allocator, @@ -155,7 +155,7 @@ super_tcategory_impl!( /// 3D transformation. #[repr(C)] #[derive(Debug)] -pub struct Transform, C: TCategory> +pub struct Transform, C: TCategory> where DefaultAllocator: Allocator, DimNameSum> { matrix: MatrixN>, @@ -163,7 +163,7 @@ where DefaultAllocator: Allocator, DimNameSum> } // FIXME -// impl + hash::Hash, C: TCategory> hash::Hash for Transform +// impl + hash::Hash, C: TCategory> hash::Hash for Transform // where DefaultAllocator: Allocator, DimNameSum>, // Owned, DimNameSum>: hash::Hash { // fn hash(&self, state: &mut H) { @@ -171,14 +171,14 @@ where DefaultAllocator: Allocator, DimNameSum> // } // } -impl + Copy, C: TCategory> Copy for Transform +impl + Copy, C: TCategory> Copy for Transform where DefaultAllocator: Allocator, DimNameSum>, Owned, DimNameSum>: Copy, { } -impl, C: TCategory> Clone for Transform +impl, C: TCategory> Clone for Transform where DefaultAllocator: Allocator, DimNameSum> { #[inline] @@ -188,7 +188,7 @@ where DefaultAllocator: Allocator, DimNameSum> } #[cfg(feature = "serde-serialize")] -impl, C: TCategory> Serialize for Transform +impl, C: TCategory> Serialize for Transform where DefaultAllocator: Allocator, DimNameSum>, Owned, DimNameSum>: Serialize, @@ -200,7 +200,7 @@ where } #[cfg(feature = "serde-serialize")] -impl<'a, N: Real, D: DimNameAdd, C: TCategory> Deserialize<'a> for Transform +impl<'a, N: RealField, D: DimNameAdd, C: TCategory> Deserialize<'a> for Transform where DefaultAllocator: Allocator, DimNameSum>, Owned, DimNameSum>: Deserialize<'a>, @@ -213,10 +213,10 @@ where } } -impl, C: TCategory> Eq for Transform where DefaultAllocator: Allocator, DimNameSum> +impl, C: TCategory> Eq for Transform where DefaultAllocator: Allocator, DimNameSum> {} -impl, C: TCategory> PartialEq for Transform +impl, C: TCategory> PartialEq for Transform where DefaultAllocator: Allocator, DimNameSum> { #[inline] @@ -225,7 +225,7 @@ where DefaultAllocator: Allocator, DimNameSum> } } -impl, C: TCategory> Transform +impl, C: TCategory> Transform where DefaultAllocator: Allocator, DimNameSum> { /// Creates a new transformation from the given homogeneous matrix. The transformation category @@ -452,7 +452,7 @@ where DefaultAllocator: Allocator, DimNameSum> } } -impl> Transform +impl> Transform where DefaultAllocator: Allocator, DimNameSum> { /// A mutable reference to underlying matrix. Use `.matrix_mut_unchecked` instead if this @@ -463,7 +463,7 @@ where DefaultAllocator: Allocator, DimNameSum> } } -impl, C: TCategory> AbsDiffEq for Transform +impl, C: TCategory> AbsDiffEq for Transform where N::Epsilon: Copy, DefaultAllocator: Allocator, DimNameSum>, @@ -481,7 +481,7 @@ where } } -impl, C: TCategory> RelativeEq for Transform +impl, C: TCategory> RelativeEq for Transform where N::Epsilon: Copy, DefaultAllocator: Allocator, DimNameSum>, @@ -504,7 +504,7 @@ where } } -impl, C: TCategory> UlpsEq for Transform +impl, C: TCategory> UlpsEq for Transform where N::Epsilon: Copy, DefaultAllocator: Allocator, DimNameSum>, diff --git a/src/geometry/transform_alga.rs b/src/geometry/transform_alga.rs index 0ece3862..5d0e8bf8 100644 --- a/src/geometry/transform_alga.rs +++ b/src/geometry/transform_alga.rs @@ -1,6 +1,6 @@ use alga::general::{ AbstractGroup, AbstractLoop, AbstractMagma, AbstractMonoid, AbstractQuasigroup, - AbstractSemigroup, Identity, TwoSidedInverse, Multiplicative, Real, + AbstractSemigroup, Identity, TwoSidedInverse, Multiplicative, RealField, }; use alga::linear::{ProjectiveTransformation, Transformation}; @@ -15,7 +15,7 @@ use crate::geometry::{Point, SubTCategoryOf, TCategory, TProjective, Transform}; * Algebraic structures. * */ -impl, C> Identity for Transform +impl, C> Identity for Transform where C: TCategory, DefaultAllocator: Allocator, DimNameSum>, @@ -26,7 +26,7 @@ where } } -impl, C> TwoSidedInverse for Transform +impl, C> TwoSidedInverse for Transform where C: SubTCategoryOf, DefaultAllocator: Allocator, DimNameSum>, @@ -42,7 +42,7 @@ where } } -impl, C> AbstractMagma for Transform +impl, C> AbstractMagma for Transform where C: TCategory, DefaultAllocator: Allocator, DimNameSum>, @@ -55,7 +55,7 @@ where macro_rules! impl_multiplicative_structures( ($($marker: ident<$operator: ident>),* $(,)*) => {$( - impl, C> $marker<$operator> for Transform + impl, C> $marker<$operator> for Transform where C: TCategory, DefaultAllocator: Allocator, DimNameSum> { } )*} @@ -63,7 +63,7 @@ macro_rules! impl_multiplicative_structures( macro_rules! impl_inversible_multiplicative_structures( ($($marker: ident<$operator: ident>),* $(,)*) => {$( - impl, C> $marker<$operator> for Transform + impl, C> $marker<$operator> for Transform where C: SubTCategoryOf, DefaultAllocator: Allocator, DimNameSum> { } )*} @@ -87,7 +87,7 @@ impl_inversible_multiplicative_structures!( */ impl, C> Transformation> for Transform where - N: Real, + N: RealField, C: TCategory, DefaultAllocator: Allocator, DimNameSum> + Allocator> @@ -107,7 +107,7 @@ where impl, C> ProjectiveTransformation> for Transform where - N: Real, + N: RealField, C: SubTCategoryOf, DefaultAllocator: Allocator, DimNameSum> + Allocator> @@ -128,7 +128,7 @@ where // FIXME: we need to implement an SVD for this. // // impl, C> AffineTransformation> for Transform -// where N: Real, +// where N: RealField, // C: SubTCategoryOf, // DefaultAllocator: Allocator, DimNameSum> + // Allocator + diff --git a/src/geometry/transform_construction.rs b/src/geometry/transform_construction.rs index 55733a90..1b23daba 100644 --- a/src/geometry/transform_construction.rs +++ b/src/geometry/transform_construction.rs @@ -1,6 +1,6 @@ use num::One; -use alga::general::Real; +use alga::general::RealField; use crate::base::allocator::Allocator; use crate::base::dimension::{DimNameAdd, DimNameSum, U1}; @@ -8,7 +8,7 @@ use crate::base::{DefaultAllocator, MatrixN}; use crate::geometry::{TCategory, Transform}; -impl, C: TCategory> Transform +impl, C: TCategory> Transform where DefaultAllocator: Allocator, DimNameSum> { /// Creates a new identity transform. @@ -45,7 +45,7 @@ where DefaultAllocator: Allocator, DimNameSum> } } -impl, C: TCategory> One for Transform +impl, C: TCategory> One for Transform where DefaultAllocator: Allocator, DimNameSum> { /// Creates a new identity transform. diff --git a/src/geometry/transform_conversion.rs b/src/geometry/transform_conversion.rs index 651ab69b..a0e00291 100644 --- a/src/geometry/transform_conversion.rs +++ b/src/geometry/transform_conversion.rs @@ -1,4 +1,4 @@ -use alga::general::{Real, SubsetOf}; +use alga::general::{RealField, SubsetOf}; use crate::base::allocator::Allocator; use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; @@ -8,8 +8,8 @@ use crate::geometry::{SuperTCategoryOf, TCategory, Transform}; impl SubsetOf> for Transform where - N1: Real + SubsetOf, - N2: Real, + N1: RealField + SubsetOf, + N2: RealField, C1: TCategory, C2: SuperTCategoryOf, D: DimNameAdd, @@ -36,8 +36,8 @@ where impl SubsetOf>> for Transform where - N1: Real + SubsetOf, - N2: Real, + N1: RealField + SubsetOf, + N2: RealField, C: TCategory, D: DimNameAdd, DefaultAllocator: Allocator, DimNameSum> @@ -61,7 +61,7 @@ where } } -impl From> for MatrixN> +impl From> for MatrixN> where D: DimNameAdd, C: TCategory, diff --git a/src/geometry/transform_ops.rs b/src/geometry/transform_ops.rs index 9d03038d..4aa943e8 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, Real, SubsetOf}; +use alga::general::{ClosedAdd, ClosedMul, RealField, SubsetOf}; use crate::base::allocator::Allocator; use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1, U3, U4}; @@ -79,7 +79,7 @@ use crate::geometry::{ * Indexing. * */ -impl Index<(usize, usize)> for Transform +impl Index<(usize, usize)> for Transform where D: DimName + DimNameAdd, DefaultAllocator: Allocator, DimNameSum>, @@ -93,7 +93,7 @@ where } // Only general transformations are mutably indexable. -impl IndexMut<(usize, usize)> for Transform +impl IndexMut<(usize, usize)> for Transform where D: DimName + DimNameAdd, DefaultAllocator: Allocator, DimNameSum>, @@ -106,7 +106,7 @@ where // Transform × Vector md_impl_all!( - Mul, mul where N: Real; + Mul, mul where N: RealField; (DimNameSum, DimNameSum), (D, U1) for D: DimNameAdd, C: TCategory; self: Transform, rhs: VectorN, Output = VectorN; [val val] => &self * &rhs; @@ -130,7 +130,7 @@ md_impl_all!( // Transform × Point md_impl_all!( - Mul, mul where N: Real; + Mul, mul where N: RealField; (DimNameSum, DimNameSum), (D, U1) for D: DimNameAdd, C: TCategory where DefaultAllocator: Allocator; self: Transform, rhs: Point, Output = Point; @@ -156,7 +156,7 @@ md_impl_all!( // Transform × Transform md_impl_all!( - Mul, mul where N: Real; + Mul, mul where N: RealField; (DimNameSum, DimNameSum), (DimNameSum, DimNameSum) for D: DimNameAdd, CA: TCategoryMul, CB: TCategory; self: Transform, rhs: Transform, Output = Transform; [val val] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.into_inner()); @@ -167,7 +167,7 @@ md_impl_all!( // Transform × Rotation md_impl_all!( - Mul, mul where N: Real; + Mul, mul where N: RealField; (DimNameSum, DimNameSum), (D, D) for D: DimNameAdd, C: TCategoryMul; self: Transform, rhs: Rotation, Output = Transform; [val val] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.to_homogeneous()); @@ -178,7 +178,7 @@ md_impl_all!( // Rotation × Transform md_impl_all!( - Mul, mul where N: Real; + Mul, mul where N: RealField; (D, D), (DimNameSum, DimNameSum) for D: DimNameAdd, C: TCategoryMul; self: Rotation, rhs: Transform, Output = Transform; [val val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.into_inner()); @@ -189,7 +189,7 @@ md_impl_all!( // Transform × UnitQuaternion md_impl_all!( - Mul, mul where N: Real; + Mul, mul where N: RealField; (U4, U4), (U4, U1) for C: TCategoryMul; self: Transform, rhs: UnitQuaternion, Output = Transform; [val val] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.to_homogeneous()); @@ -200,7 +200,7 @@ md_impl_all!( // UnitQuaternion × Transform md_impl_all!( - Mul, mul where N: Real; + Mul, mul where N: RealField; (U4, U1), (U4, U4) for C: TCategoryMul; self: UnitQuaternion, rhs: Transform, Output = Transform; [val val] => Self::Output::from_matrix_unchecked(self.to_homogeneous() * rhs.into_inner()); @@ -211,7 +211,7 @@ md_impl_all!( // Transform × Isometry md_impl_all!( - Mul, mul where N: Real; + Mul, mul where N: RealField; (DimNameSum, DimNameSum), (D, U1) for D: DimNameAdd, C: TCategoryMul, R: SubsetOf> >; self: Transform, rhs: Isometry, Output = Transform; @@ -223,7 +223,7 @@ md_impl_all!( // Isometry × Transform md_impl_all!( - Mul, mul where N: Real; + Mul, mul where N: RealField; (D, U1), (DimNameSum, DimNameSum) for D: DimNameAdd, C: TCategoryMul, R: SubsetOf> >; self: Isometry, rhs: Transform, Output = Transform; @@ -235,7 +235,7 @@ md_impl_all!( // Transform × Similarity md_impl_all!( - Mul, mul where N: Real; + Mul, mul where N: RealField; (DimNameSum, DimNameSum), (D, U1) for D: DimNameAdd, C: TCategoryMul, R: SubsetOf> >; self: Transform, rhs: Similarity, Output = Transform; @@ -247,7 +247,7 @@ md_impl_all!( // Similarity × Transform md_impl_all!( - Mul, mul where N: Real; + Mul, mul where N: RealField; (D, U1), (DimNameSum, DimNameSum) for D: DimNameAdd, C: TCategoryMul, R: SubsetOf> >; self: Similarity, rhs: Transform, Output = Transform; @@ -267,7 +267,7 @@ md_impl_all!( */ // Transform × Translation md_impl_all!( - Mul, mul where N: Real; + Mul, mul where N: RealField; (DimNameSum, DimNameSum), (D, U1) for D: DimNameAdd, C: TCategoryMul; self: Transform, rhs: Translation, Output = Transform; [val val] => Self::Output::from_matrix_unchecked(self.into_inner() * rhs.to_homogeneous()); @@ -278,7 +278,7 @@ md_impl_all!( // Translation × Transform md_impl_all!( - Mul, mul where N: Real; + Mul, mul where N: RealField; (D, U1), (DimNameSum, DimNameSum) for D: DimNameAdd, C: TCategoryMul; self: Translation, rhs: Transform, Output = Transform; @@ -290,7 +290,7 @@ md_impl_all!( // Transform ÷ Transform md_impl_all!( - Div, div where N: Real; + Div, div where N: RealField; (DimNameSum, DimNameSum), (DimNameSum, DimNameSum) for D: DimNameAdd, CA: TCategoryMul, CB: SubTCategoryOf; self: Transform, rhs: Transform, Output = Transform; [val val] => self * rhs.inverse(); @@ -301,7 +301,7 @@ md_impl_all!( // Transform ÷ Rotation md_impl_all!( - Div, div where N: Real; + Div, div where N: RealField; (DimNameSum, DimNameSum), (D, D) for D: DimNameAdd, C: TCategoryMul; self: Transform, rhs: Rotation, Output = Transform; [val val] => self * rhs.inverse(); @@ -312,7 +312,7 @@ md_impl_all!( // Rotation ÷ Transform md_impl_all!( - Div, div where N: Real; + Div, div where N: RealField; (D, D), (DimNameSum, DimNameSum) for D: DimNameAdd, C: TCategoryMul; self: Rotation, rhs: Transform, Output = Transform; [val val] => self.inverse() * rhs; @@ -323,7 +323,7 @@ md_impl_all!( // Transform ÷ UnitQuaternion md_impl_all!( - Div, div where N: Real; + Div, div where N: RealField; (U4, U4), (U4, U1) for C: TCategoryMul; self: Transform, rhs: UnitQuaternion, Output = Transform; [val val] => self * rhs.inverse(); @@ -334,7 +334,7 @@ md_impl_all!( // UnitQuaternion ÷ Transform md_impl_all!( - Div, div where N: Real; + Div, div where N: RealField; (U4, U1), (U4, U4) for C: TCategoryMul; self: UnitQuaternion, rhs: Transform, Output = Transform; [val val] => self.inverse() * rhs; @@ -345,7 +345,7 @@ md_impl_all!( // // Transform ÷ Isometry // md_impl_all!( -// Div, div where N: Real; +// Div, div where N: RealField; // (DimNameSum, DimNameSum), (D, U1) // for D: DimNameAdd, C: TCategoryMul, R: SubsetOf> > // where SB::Alloc: Allocator, DimNameSum >; @@ -358,7 +358,7 @@ md_impl_all!( // // Isometry ÷ Transform // md_impl_all!( -// Div, div where N: Real; +// Div, div where N: RealField; // (D, U1), (DimNameSum, DimNameSum) // for D: DimNameAdd, C: TCategoryMul, R: SubsetOf> > // where SA::Alloc: Allocator, DimNameSum >; @@ -371,7 +371,7 @@ md_impl_all!( // // Transform ÷ Similarity // md_impl_all!( -// Div, div where N: Real; +// Div, div where N: RealField; // (DimNameSum, DimNameSum), (D, U1) // for D: DimNameAdd, C: TCategoryMul, R: SubsetOf> > // where SB::Alloc: Allocator @@ -385,7 +385,7 @@ md_impl_all!( // // Similarity ÷ Transform // md_impl_all!( -// Div, div where N: Real; +// Div, div where N: RealField; // (D, U1), (DimNameSum, DimNameSum) // for D: DimNameAdd, C: TCategoryMul, R: SubsetOf> > // where SA::Alloc: Allocator @@ -399,7 +399,7 @@ md_impl_all!( // Transform ÷ Translation md_impl_all!( - Div, div where N: Real; + Div, div where N: RealField; (DimNameSum, DimNameSum), (D, U1) for D: DimNameAdd, C: TCategoryMul; self: Transform, rhs: Translation, Output = Transform; [val val] => self * rhs.inverse(); @@ -410,7 +410,7 @@ md_impl_all!( // Translation ÷ Transform md_impl_all!( - Div, div where N: Real; + Div, div where N: RealField; (D, U1), (DimNameSum, DimNameSum) for D: DimNameAdd, C: TCategoryMul; self: Translation, rhs: Transform, Output = Transform; @@ -422,7 +422,7 @@ md_impl_all!( // Transform ×= Transform md_assign_impl_all!( - MulAssign, mul_assign where N: Real; + MulAssign, mul_assign where N: RealField; (DimNameSum, DimNameSum), (DimNameSum, DimNameSum) for D: DimNameAdd, CA: TCategory, CB: SubTCategoryOf; self: Transform, rhs: Transform; [val] => *self.matrix_mut_unchecked() *= rhs.into_inner(); @@ -431,7 +431,7 @@ md_assign_impl_all!( // Transform ×= Similarity md_assign_impl_all!( - MulAssign, mul_assign where N: Real; + MulAssign, mul_assign where N: RealField; (DimNameSum, DimNameSum), (D, U1) for D: DimNameAdd, C: TCategory, R: SubsetOf> >; self: Transform, rhs: Similarity; @@ -441,7 +441,7 @@ md_assign_impl_all!( // Transform ×= Isometry md_assign_impl_all!( - MulAssign, mul_assign where N: Real; + MulAssign, mul_assign where N: RealField; (DimNameSum, DimNameSum), (D, U1) for D: DimNameAdd, C: TCategory, R: SubsetOf> >; self: Transform, rhs: Isometry; @@ -459,7 +459,7 @@ md_assign_impl_all!( */ // Transform ×= Translation md_assign_impl_all!( - MulAssign, mul_assign where N: Real; + MulAssign, mul_assign where N: RealField; (DimNameSum, DimNameSum), (D, U1) for D: DimNameAdd, C: TCategory; self: Transform, rhs: Translation; [val] => *self.matrix_mut_unchecked() *= rhs.to_homogeneous(); @@ -468,7 +468,7 @@ md_assign_impl_all!( // Transform ×= Rotation md_assign_impl_all!( - MulAssign, mul_assign where N: Real; + MulAssign, mul_assign where N: RealField; (DimNameSum, DimNameSum), (D, D) for D: DimNameAdd, C: TCategory; self: Transform, rhs: Rotation; [val] => *self.matrix_mut_unchecked() *= rhs.to_homogeneous(); @@ -477,7 +477,7 @@ md_assign_impl_all!( // Transform ×= UnitQuaternion md_assign_impl_all!( - MulAssign, mul_assign where N: Real; + MulAssign, mul_assign where N: RealField; (U4, U4), (U4, U1) for C: TCategory; self: Transform, rhs: UnitQuaternion; [val] => *self.matrix_mut_unchecked() *= rhs.to_homogeneous(); @@ -486,7 +486,7 @@ md_assign_impl_all!( // Transform ÷= Transform md_assign_impl_all!( - DivAssign, div_assign where N: Real; + DivAssign, div_assign where N: RealField; (DimNameSum, DimNameSum), (DimNameSum, DimNameSum) for D: DimNameAdd, CA: SuperTCategoryOf, CB: SubTCategoryOf; self: Transform, rhs: Transform; @@ -517,7 +517,7 @@ md_assign_impl_all!( // Transform ÷= Translation md_assign_impl_all!( - DivAssign, div_assign where N: Real; + DivAssign, div_assign where N: RealField; (DimNameSum, DimNameSum), (D, U1) for D: DimNameAdd, C: TCategory; self: Transform, rhs: Translation; [val] => *self *= rhs.inverse(); @@ -526,7 +526,7 @@ md_assign_impl_all!( // Transform ÷= Rotation md_assign_impl_all!( - DivAssign, div_assign where N: Real; + DivAssign, div_assign where N: RealField; (DimNameSum, DimNameSum), (D, D) for D: DimNameAdd, C: TCategory; self: Transform, rhs: Rotation; [val] => *self *= rhs.inverse(); @@ -535,7 +535,7 @@ md_assign_impl_all!( // Transform ÷= UnitQuaternion md_assign_impl_all!( - DivAssign, div_assign where N: Real; + DivAssign, div_assign where N: RealField; (U4, U4), (U4, U1) for C: TCategory; self: Transform, rhs: UnitQuaternion; [val] => *self *= rhs.inverse(); diff --git a/src/geometry/translation.rs b/src/geometry/translation.rs index 3b620b20..43a340f3 100644 --- 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::{ClosedNeg, Real}; +use alga::general::{ClosedNeg, RealField}; use crate::base::allocator::Allocator; use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1}; @@ -263,7 +263,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 00b54421..f2ced0b3 100644 --- a/src/geometry/translation_alga.rs +++ b/src/geometry/translation_alga.rs @@ -1,6 +1,6 @@ use alga::general::{ AbstractGroup, AbstractLoop, AbstractMagma, AbstractMonoid, AbstractQuasigroup, - AbstractSemigroup, Id, Identity, TwoSidedInverse, Multiplicative, Real, + AbstractSemigroup, Id, Identity, TwoSidedInverse, Multiplicative, RealField, }; use alga::linear::Translation as AlgaTranslation; use alga::linear::{ @@ -19,7 +19,7 @@ use crate::geometry::{Point, Translation}; * Algebraic structures. * */ -impl Identity for Translation +impl Identity for Translation where DefaultAllocator: Allocator { #[inline] @@ -28,7 +28,7 @@ where DefaultAllocator: Allocator } } -impl TwoSidedInverse for Translation +impl TwoSidedInverse for Translation where DefaultAllocator: Allocator { #[inline] @@ -42,7 +42,7 @@ where DefaultAllocator: Allocator } } -impl AbstractMagma for Translation +impl AbstractMagma for Translation where DefaultAllocator: Allocator { #[inline] @@ -53,7 +53,7 @@ where DefaultAllocator: Allocator macro_rules! impl_multiplicative_structures( ($($marker: ident<$operator: ident>),* $(,)*) => {$( - impl $marker<$operator> for Translation + impl $marker<$operator> for Translation where DefaultAllocator: Allocator { } )*} ); @@ -71,7 +71,7 @@ impl_multiplicative_structures!( * Transformation groups. * */ -impl Transformation> for Translation +impl Transformation> for Translation where DefaultAllocator: Allocator { #[inline] @@ -85,7 +85,7 @@ where DefaultAllocator: Allocator } } -impl ProjectiveTransformation> for Translation +impl ProjectiveTransformation> for Translation where DefaultAllocator: Allocator { #[inline] @@ -99,7 +99,7 @@ where DefaultAllocator: Allocator } } -impl AffineTransformation> for Translation +impl AffineTransformation> for Translation where DefaultAllocator: Allocator { type Rotation = Id; @@ -142,7 +142,7 @@ where DefaultAllocator: Allocator } } -impl Similarity> for Translation +impl Similarity> for Translation where DefaultAllocator: Allocator { type Scaling = Id; @@ -165,7 +165,7 @@ where DefaultAllocator: Allocator macro_rules! marker_impl( ($($Trait: ident),*) => {$( - impl $Trait> for Translation + impl $Trait> for Translation where DefaultAllocator: Allocator { } )*} ); @@ -173,7 +173,7 @@ macro_rules! marker_impl( marker_impl!(Isometry, DirectIsometry); /// Subgroups of the n-dimensional translation group `T(n)`. -impl AlgaTranslation> for Translation +impl AlgaTranslation> for Translation where DefaultAllocator: Allocator { #[inline] diff --git a/src/geometry/translation_conversion.rs b/src/geometry/translation_conversion.rs index 9f0e9a25..b44412e6 100644 --- a/src/geometry/translation_conversion.rs +++ b/src/geometry/translation_conversion.rs @@ -1,6 +1,6 @@ use num::{One, Zero}; -use alga::general::{Real, SubsetOf, SupersetOf}; +use alga::general::{RealField, SubsetOf, SupersetOf}; use alga::linear::Rotation; use crate::base::allocator::Allocator; @@ -46,8 +46,8 @@ where impl SubsetOf> for Translation where - N1: Real, - N2: Real + SupersetOf, + N1: RealField, + N2: RealField + SupersetOf, R: Rotation>, DefaultAllocator: Allocator + Allocator, { @@ -69,8 +69,8 @@ where impl SubsetOf> for Translation where - N1: Real, - N2: Real + SupersetOf, + N1: RealField, + N2: RealField + SupersetOf, R: Rotation>, DefaultAllocator: Allocator + Allocator, { @@ -92,8 +92,8 @@ where impl SubsetOf> for Translation where - N1: Real, - N2: Real + SupersetOf, + N1: RealField, + N2: RealField + SupersetOf, C: SuperTCategoryOf, D: DimNameAdd, DefaultAllocator: Allocator @@ -119,8 +119,8 @@ where impl SubsetOf>> for Translation where - N1: Real, - N2: Real + SupersetOf, + N1: RealField, + N2: RealField + SupersetOf, D: DimNameAdd, DefaultAllocator: Allocator + Allocator diff --git a/src/geometry/unit_complex.rs b/src/geometry/unit_complex.rs index d02b46b6..2530cc25 100644 --- a/src/geometry/unit_complex.rs +++ b/src/geometry/unit_complex.rs @@ -2,14 +2,14 @@ use approx::{AbsDiffEq, RelativeEq, UlpsEq}; use num_complex::Complex; use std::fmt; -use alga::general::Real; +use alga::general::RealField; use crate::base::{Matrix2, Matrix3, Unit, Vector1}; use crate::geometry::Rotation2; /// A complex number with a norm equal to 1. pub type UnitComplex = Unit>; -impl UnitComplex { +impl UnitComplex { /// The rotation angle in `]-pi; pi]` of this unit complex number. /// /// # Example @@ -253,13 +253,13 @@ impl UnitComplex { } } -impl fmt::Display for UnitComplex { +impl fmt::Display for UnitComplex { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "UnitComplex angle: {}", self.angle()) } } -impl AbsDiffEq for UnitComplex { +impl AbsDiffEq for UnitComplex { type Epsilon = N; #[inline] @@ -273,7 +273,7 @@ impl AbsDiffEq for UnitComplex { } } -impl RelativeEq for UnitComplex { +impl RelativeEq for UnitComplex { #[inline] fn default_max_relative() -> Self::Epsilon { N::default_max_relative() @@ -292,7 +292,7 @@ impl RelativeEq for UnitComplex { } } -impl UlpsEq for UnitComplex { +impl UlpsEq for UnitComplex { #[inline] fn default_max_ulps() -> u32 { N::default_max_ulps() diff --git a/src/geometry/unit_complex_alga.rs b/src/geometry/unit_complex_alga.rs index d49a3e57..685a588e 100644 --- a/src/geometry/unit_complex_alga.rs +++ b/src/geometry/unit_complex_alga.rs @@ -1,6 +1,6 @@ use alga::general::{ AbstractGroup, AbstractLoop, AbstractMagma, AbstractMonoid, AbstractQuasigroup, - AbstractSemigroup, Id, Identity, TwoSidedInverse, Multiplicative, Real, + AbstractSemigroup, Id, Identity, TwoSidedInverse, Multiplicative, RealField, }; use alga::linear::{ AffineTransformation, DirectIsometry, Isometry, OrthogonalTransformation, @@ -17,21 +17,21 @@ use crate::geometry::{Point2, UnitComplex}; * Implementations for UnitComplex. * */ -impl Identity for UnitComplex { +impl Identity for UnitComplex { #[inline] fn identity() -> Self { Self::identity() } } -impl AbstractMagma for UnitComplex { +impl AbstractMagma for UnitComplex { #[inline] fn operate(&self, rhs: &Self) -> Self { self * rhs } } -impl TwoSidedInverse for UnitComplex { +impl TwoSidedInverse for UnitComplex { #[inline] fn two_sided_inverse(&self) -> Self { self.inverse() @@ -45,7 +45,7 @@ impl TwoSidedInverse for UnitComplex { macro_rules! impl_structures( ($($marker: ident<$operator: ident>),* $(,)*) => {$( - impl $marker<$operator> for UnitComplex { + impl $marker<$operator> for UnitComplex { } )*} ); @@ -58,7 +58,7 @@ impl_structures!( AbstractGroup ); -impl Transformation> for UnitComplex +impl Transformation> for UnitComplex where DefaultAllocator: Allocator { #[inline] @@ -72,7 +72,7 @@ where DefaultAllocator: Allocator } } -impl ProjectiveTransformation> for UnitComplex +impl ProjectiveTransformation> for UnitComplex where DefaultAllocator: Allocator { #[inline] @@ -88,7 +88,7 @@ where DefaultAllocator: Allocator } } -impl AffineTransformation> for UnitComplex +impl AffineTransformation> for UnitComplex where DefaultAllocator: Allocator { type Rotation = Self; @@ -131,7 +131,7 @@ where DefaultAllocator: Allocator } } -impl Similarity> for UnitComplex +impl Similarity> for UnitComplex where DefaultAllocator: Allocator { type Scaling = Id; @@ -154,14 +154,14 @@ where DefaultAllocator: Allocator macro_rules! marker_impl( ($($Trait: ident),*) => {$( - impl $Trait> for UnitComplex + impl $Trait> for UnitComplex where DefaultAllocator: Allocator { } )*} ); marker_impl!(Isometry, DirectIsometry, OrthogonalTransformation); -impl Rotation> for UnitComplex +impl Rotation> for UnitComplex where DefaultAllocator: Allocator { #[inline] diff --git a/src/geometry/unit_complex_construction.rs b/src/geometry/unit_complex_construction.rs index 7e24559c..046142c8 100644 --- a/src/geometry/unit_complex_construction.rs +++ b/src/geometry/unit_complex_construction.rs @@ -6,13 +6,13 @@ use num_complex::Complex; use rand::distributions::{Distribution, OpenClosed01, Standard}; use rand::Rng; -use alga::general::Real; +use alga::general::RealField; use crate::base::dimension::{U1, U2}; use crate::base::storage::Storage; use crate::base::{Unit, Vector, Matrix2}; use crate::geometry::{Rotation2, UnitComplex}; -impl UnitComplex { +impl UnitComplex { /// The unit complex number multiplicative identity. /// /// # Example @@ -268,14 +268,14 @@ impl UnitComplex { } } -impl One for UnitComplex { +impl One for UnitComplex { #[inline] fn one() -> Self { Self::identity() } } -impl Distribution> for Standard +impl Distribution> for Standard where OpenClosed01: Distribution { /// Generate a uniformly distributed random `UnitComplex`. @@ -286,7 +286,7 @@ where OpenClosed01: Distribution } #[cfg(feature = "arbitrary")] -impl Arbitrary for UnitComplex { +impl Arbitrary for UnitComplex { #[inline] fn arbitrary(g: &mut G) -> Self { UnitComplex::from_angle(N::arbitrary(g)) diff --git a/src/geometry/unit_complex_conversion.rs b/src/geometry/unit_complex_conversion.rs index 3adb372c..f7fe4532 100644 --- a/src/geometry/unit_complex_conversion.rs +++ b/src/geometry/unit_complex_conversion.rs @@ -1,7 +1,7 @@ use num::Zero; use num_complex::Complex; -use alga::general::{Real, SubsetOf, SupersetOf}; +use alga::general::{RealField, SubsetOf, SupersetOf}; use alga::linear::Rotation as AlgaRotation; use crate::base::dimension::U2; @@ -28,8 +28,8 @@ use crate::geometry::{ impl SubsetOf> for UnitComplex where - N1: Real, - N2: Real + SupersetOf, + N1: RealField, + N2: RealField + SupersetOf, { #[inline] fn to_superset(&self) -> UnitComplex { @@ -49,8 +49,8 @@ where impl SubsetOf> for UnitComplex where - N1: Real, - N2: Real + SupersetOf, + N1: RealField, + N2: RealField + SupersetOf, { #[inline] fn to_superset(&self) -> Rotation2 { @@ -72,8 +72,8 @@ where impl SubsetOf> for UnitComplex where - N1: Real, - N2: Real + SupersetOf, + N1: RealField, + N2: RealField + SupersetOf, R: AlgaRotation> + SupersetOf, { #[inline] @@ -94,8 +94,8 @@ where impl SubsetOf> for UnitComplex where - N1: Real, - N2: Real + SupersetOf, + N1: RealField, + N2: RealField + SupersetOf, R: AlgaRotation> + SupersetOf, { #[inline] @@ -116,8 +116,8 @@ where impl SubsetOf> for UnitComplex where - N1: Real, - N2: Real + SupersetOf, + N1: RealField, + N2: RealField + SupersetOf, C: SuperTCategoryOf, { #[inline] @@ -136,7 +136,7 @@ where } } -impl> SubsetOf> for UnitComplex { +impl> SubsetOf> for UnitComplex { #[inline] fn to_superset(&self) -> Matrix3 { self.to_homogeneous().to_superset() @@ -155,28 +155,28 @@ impl> SubsetOf> for UnitComplex< } -impl From> for Rotation2 { +impl From> for Rotation2 { #[inline] fn from(q: UnitComplex) -> Self { q.to_rotation_matrix() } } -impl From> for UnitComplex { +impl From> for UnitComplex { #[inline] fn from(q: Rotation2) -> Self { Self::from_rotation_matrix(&q) } } -impl From> for Matrix3 { +impl From> for Matrix3 { #[inline] fn from(q: UnitComplex) -> Matrix3 { q.to_homogeneous() } } -impl From> for Matrix2 { +impl From> for Matrix2 { #[inline] fn from(q: UnitComplex) -> Self { q.to_rotation_matrix().into_inner() diff --git a/src/geometry/unit_complex_ops.rs b/src/geometry/unit_complex_ops.rs index ee8eca64..11ffdc4a 100644 --- a/src/geometry/unit_complex_ops.rs +++ b/src/geometry/unit_complex_ops.rs @@ -1,6 +1,6 @@ use std::ops::{Div, DivAssign, Mul, MulAssign}; -use alga::general::Real; +use alga::general::RealField; use crate::base::allocator::Allocator; use crate::base::dimension::{U1, U2}; use crate::base::storage::Storage; @@ -44,7 +44,7 @@ use crate::geometry::{Isometry, Point2, Rotation, Similarity, Translation, UnitC */ // UnitComplex × UnitComplex -impl Mul for UnitComplex { +impl Mul for UnitComplex { type Output = Self; #[inline] @@ -53,7 +53,7 @@ impl Mul for UnitComplex { } } -impl<'a, N: Real> Mul> for &'a UnitComplex { +impl<'a, N: RealField> Mul> for &'a UnitComplex { type Output = UnitComplex; #[inline] @@ -62,7 +62,7 @@ impl<'a, N: Real> Mul> for &'a UnitComplex { } } -impl<'b, N: Real> Mul<&'b UnitComplex> for UnitComplex { +impl<'b, N: RealField> Mul<&'b UnitComplex> for UnitComplex { type Output = Self; #[inline] @@ -71,7 +71,7 @@ impl<'b, N: Real> Mul<&'b UnitComplex> for UnitComplex { } } -impl<'a, 'b, N: Real> Mul<&'b UnitComplex> for &'a UnitComplex { +impl<'a, 'b, N: RealField> Mul<&'b UnitComplex> for &'a UnitComplex { type Output = UnitComplex; #[inline] @@ -81,7 +81,7 @@ impl<'a, 'b, N: Real> Mul<&'b UnitComplex> for &'a UnitComplex { } // UnitComplex ÷ UnitComplex -impl Div for UnitComplex { +impl Div for UnitComplex { type Output = Self; #[inline] @@ -90,7 +90,7 @@ impl Div for UnitComplex { } } -impl<'a, N: Real> Div> for &'a UnitComplex { +impl<'a, N: RealField> Div> for &'a UnitComplex { type Output = UnitComplex; #[inline] @@ -99,7 +99,7 @@ impl<'a, N: Real> Div> for &'a UnitComplex { } } -impl<'b, N: Real> Div<&'b UnitComplex> for UnitComplex { +impl<'b, N: RealField> Div<&'b UnitComplex> for UnitComplex { type Output = Self; #[inline] @@ -108,7 +108,7 @@ impl<'b, N: Real> Div<&'b UnitComplex> for UnitComplex { } } -impl<'a, 'b, N: Real> Div<&'b UnitComplex> for &'a UnitComplex { +impl<'a, 'b, N: RealField> Div<&'b UnitComplex> for &'a UnitComplex { type Output = UnitComplex; #[inline] @@ -122,7 +122,7 @@ macro_rules! complex_op_impl( ($RDim: ident, $CDim: ident) $(for $Storage: ident: $StoragesBound: ident $(<$($BoundParam: ty),*>)*),*; $lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty, Output = $Result: ty; $action: expr; $($lives: tt),*) => { - impl<$($lives ,)* N: Real $(, $Storage: $StoragesBound $(<$($BoundParam),*>)*)*> $Op<$Rhs> for $Lhs + impl<$($lives ,)* N: RealField $(, $Storage: $StoragesBound $(<$($BoundParam),*>)*)*> $Op<$Rhs> for $Lhs where DefaultAllocator: Allocator { type Output = $Result; @@ -300,14 +300,14 @@ complex_op_impl_all!( ); // UnitComplex ×= UnitComplex -impl MulAssign> for UnitComplex { +impl MulAssign> for UnitComplex { #[inline] fn mul_assign(&mut self, rhs: UnitComplex) { *self = &*self * rhs } } -impl<'b, N: Real> MulAssign<&'b UnitComplex> for UnitComplex { +impl<'b, N: RealField> MulAssign<&'b UnitComplex> for UnitComplex { #[inline] fn mul_assign(&mut self, rhs: &'b UnitComplex) { *self = &*self * rhs @@ -315,14 +315,14 @@ impl<'b, N: Real> MulAssign<&'b UnitComplex> for UnitComplex { } // UnitComplex /= UnitComplex -impl DivAssign> for UnitComplex { +impl DivAssign> for UnitComplex { #[inline] fn div_assign(&mut self, rhs: UnitComplex) { *self = &*self / rhs } } -impl<'b, N: Real> DivAssign<&'b UnitComplex> for UnitComplex { +impl<'b, N: RealField> DivAssign<&'b UnitComplex> for UnitComplex { #[inline] fn div_assign(&mut self, rhs: &'b UnitComplex) { *self = &*self / rhs @@ -330,7 +330,7 @@ impl<'b, N: Real> DivAssign<&'b UnitComplex> for UnitComplex { } // UnitComplex ×= Rotation -impl MulAssign> for UnitComplex +impl MulAssign> for UnitComplex where DefaultAllocator: Allocator { #[inline] @@ -339,7 +339,7 @@ where DefaultAllocator: Allocator } } -impl<'b, N: Real> MulAssign<&'b Rotation> for UnitComplex +impl<'b, N: RealField> MulAssign<&'b Rotation> for UnitComplex where DefaultAllocator: Allocator { #[inline] @@ -349,7 +349,7 @@ where DefaultAllocator: Allocator } // UnitComplex ÷= Rotation -impl DivAssign> for UnitComplex +impl DivAssign> for UnitComplex where DefaultAllocator: Allocator { #[inline] @@ -358,7 +358,7 @@ where DefaultAllocator: Allocator } } -impl<'b, N: Real> DivAssign<&'b Rotation> for UnitComplex +impl<'b, N: RealField> DivAssign<&'b Rotation> for UnitComplex where DefaultAllocator: Allocator { #[inline] @@ -368,7 +368,7 @@ where DefaultAllocator: Allocator } // Rotation ×= UnitComplex -impl MulAssign> for Rotation +impl MulAssign> for Rotation where DefaultAllocator: Allocator { #[inline] @@ -377,7 +377,7 @@ where DefaultAllocator: Allocator } } -impl<'b, N: Real> MulAssign<&'b UnitComplex> for Rotation +impl<'b, N: RealField> MulAssign<&'b UnitComplex> for Rotation where DefaultAllocator: Allocator { #[inline] @@ -387,7 +387,7 @@ where DefaultAllocator: Allocator } // Rotation ÷= UnitComplex -impl DivAssign> for Rotation +impl DivAssign> for Rotation where DefaultAllocator: Allocator { #[inline] @@ -396,7 +396,7 @@ where DefaultAllocator: Allocator } } -impl<'b, N: Real> DivAssign<&'b UnitComplex> for Rotation +impl<'b, N: RealField> DivAssign<&'b UnitComplex> for Rotation where DefaultAllocator: Allocator { #[inline] diff --git a/src/io/matrix_market.rs b/src/io/matrix_market.rs index c2653c16..f0e817a1 100644 --- a/src/io/matrix_market.rs +++ b/src/io/matrix_market.rs @@ -3,7 +3,7 @@ use std::path::Path; use pest::Parser; use crate::sparse::CsMatrix; -use crate::Real; +use crate::RealField; #[derive(Parser)] #[grammar = "io/matrix_market.pest"] @@ -11,14 +11,14 @@ struct MatrixMarketParser; // FIXME: return an Error instead of an Option. /// Parses a Matrix Market file at the given path, and returns the corresponding sparse matrix. -pub fn cs_matrix_from_matrix_market>(path: P) -> Option> { +pub fn cs_matrix_from_matrix_market>(path: P) -> Option> { let file = fs::read_to_string(path).ok()?; cs_matrix_from_matrix_market_str(&file) } // FIXME: return an Error instead of an Option. /// Parses a Matrix Market file described by the given string, and returns the corresponding sparse matrix. -pub fn cs_matrix_from_matrix_market_str(data: &str) -> Option> { +pub fn cs_matrix_from_matrix_market_str(data: &str) -> Option> { let file = MatrixMarketParser::parse(Rule::Document, data) .unwrap() .next()?; diff --git a/src/lib.rs b/src/lib.rs index f66ae4f0..0388290b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,8 +4,8 @@ **nalgebra** is a linear algebra library written for Rust targeting: * General-purpose linear algebra (still lacks a lot of features…) -* Real time computer graphics. -* Real time computer physics. +* RealField time computer graphics. +* RealField time computer physics. ## Using **nalgebra** You will need the last stable build of the [rust compiler](http://www.rust-lang.org) @@ -160,7 +160,7 @@ use alga::linear::SquareMatrix as AlgaSquareMatrix; use alga::linear::{EuclideanSpace, FiniteDimVectorSpace, InnerSpace, NormedSpace}; use num::Signed; -pub use alga::general::{Id, Real, ComplexField}; +pub use alga::general::{Id, RealField, ComplexField}; /* * @@ -297,8 +297,8 @@ pub fn min(a: T, b: T) -> T { /// The absolute value of `a`. /// -/// Deprecated: Use [Matrix::abs] or [Real::abs] instead. -#[deprecated(note = "use `Matrix::abs` or `Real::abs` instead")] +/// Deprecated: Use [Matrix::abs] or [RealField::abs] instead. +#[deprecated(note = "use `Matrix::abs` or `RealField::abs` instead")] #[inline] pub fn abs(a: &T) -> T { a.abs() @@ -460,7 +460,7 @@ pub fn dot(a: &V, b: &V) -> V::Field { /// 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::Real { +pub fn angle(a: &V, b: &V) -> V::RealField { a.angle(b) } @@ -484,7 +484,7 @@ pub fn angle(a: &V, b: &V) -> V::Real { /// 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::Real { +pub fn norm(v: &V) -> V::RealField { v.norm() } @@ -504,7 +504,7 @@ pub fn norm(v: &V) -> V::Real { /// 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::Real { +pub fn norm_squared(v: &V) -> V::RealField { v.norm_squared() } @@ -524,7 +524,7 @@ pub fn norm_squared(v: &V) -> V::Real { /// 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::Real { +pub fn magnitude(v: &V) -> V::RealField { v.norm() } @@ -545,7 +545,7 @@ pub fn magnitude(v: &V) -> V::Real { /// 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::Real { +pub fn magnitude_squared(v: &V) -> V::RealField { v.norm_squared() } @@ -573,7 +573,7 @@ pub fn normalize(v: &V) -> V { /// 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::Real) -> Option { +pub fn try_normalize(v: &V, min_norm: V::RealField) -> Option { v.try_normalize(min_norm) } @@ -600,7 +600,7 @@ 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::Real { +pub fn distance(p1: &P, p2: &P) -> P::RealField { (p2.coordinates() - p1.coordinates()).norm() } @@ -611,7 +611,7 @@ pub fn distance(p1: &P, p2: &P) -> P::Real { /// * [center](fn.center.html) /// * [distance](fn.distance.html) #[inline] -pub fn distance_squared(p1: &P, p2: &P) -> P::Real { +pub fn distance_squared(p1: &P, p2: &P) -> P::RealField { (p2.coordinates() - p1.coordinates()).norm_squared() } diff --git a/src/linalg/balancing.rs b/src/linalg/balancing.rs index 33dcbff6..e8abbefb 100644 --- a/src/linalg/balancing.rs +++ b/src/linalg/balancing.rs @@ -1,6 +1,6 @@ //! Functions for balancing a matrix. -use alga::general::Real; +use alga::general::RealField; use std::ops::{DivAssign, MulAssign}; use crate::allocator::Allocator; @@ -12,7 +12,7 @@ use crate::base::{DefaultAllocator, MatrixN, VectorN}; /// the corresponding diagonal transformation. /// /// See https://arxiv.org/pdf/1401.5766.pdf -pub fn balance_parlett_reinsch(m: &mut MatrixN) -> VectorN +pub fn balance_parlett_reinsch(m: &mut MatrixN) -> VectorN where DefaultAllocator: Allocator + Allocator { assert!(m.is_square(), "Unable to balance a non-square matrix."); @@ -64,7 +64,7 @@ where DefaultAllocator: Allocator + Allocator { } /// Computes in-place `D * m * D.inverse()`, where `D` is the matrix with diagonal `d`. -pub fn unbalance(m: &mut MatrixN, d: &VectorN) +pub fn unbalance(m: &mut MatrixN, d: &VectorN) where DefaultAllocator: Allocator + Allocator { assert!(m.is_square(), "Unable to unbalance a non-square matrix."); assert_eq!(m.nrows(), d.len(), "Unbalancing: mismatched dimensions."); diff --git a/src/linalg/bidiagonal.rs b/src/linalg/bidiagonal.rs index e61c98ec..f766c91e 100644 --- a/src/linalg/bidiagonal.rs +++ b/src/linalg/bidiagonal.rs @@ -265,14 +265,14 @@ where } /// The diagonal part of this decomposed matrix. - pub fn diagonal(&self) -> VectorN> - where DefaultAllocator: Allocator> { + pub fn diagonal(&self) -> VectorN> + 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>> { + pub fn off_diagonal(&self) -> VectorN, U1>> + where DefaultAllocator: Allocator, U1>> { self.off_diagonal.map(|e| e.modulus()) } diff --git a/src/linalg/givens.rs b/src/linalg/givens.rs index 3dd56ee3..ed93a83c 100644 --- a/src/linalg/givens.rs +++ b/src/linalg/givens.rs @@ -12,7 +12,7 @@ use crate::base::{Vector, Matrix}; /// A Givens rotation. #[derive(Debug, Clone, Copy)] pub struct GivensRotation { - c: N::Real, + c: N::RealField, s: N } @@ -21,7 +21,7 @@ impl GivensRotation { /// The Givents rotation that does nothing. pub fn identity() -> Self { Self { - c: N::Real::one(), + c: N::RealField::one(), s: N::zero() } } @@ -30,7 +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::Real, s: N) -> Self { + pub fn new_unchecked(c: N::RealField, s: N) -> Self { Self { c, s } @@ -38,11 +38,11 @@ impl GivensRotation { /// Initializes a Givens rotation from its non-normalized cosine an sine components. pub fn new(c: N, s: N) -> (Self, N) { - Self::try_new(c, s, N::Real::zero()).unwrap() + Self::try_new(c, s, N::RealField::zero()).unwrap() } /// Initializes a Givens rotation form its non-normalized cosine an sine components. - pub fn try_new(c: N, s: N, eps: N::Real) -> Option<(Self, N)> { + pub fn try_new(c: N, s: N, eps: N::RealField) -> Option<(Self, N)> { let (mod0, sign0) = c.to_exp(); let denom = (mod0 * mod0 + s.modulus_squared()).sqrt(); @@ -91,7 +91,7 @@ impl GivensRotation { } /// The cos part of this roration. - pub fn c(&self) -> N::Real { + pub fn c(&self) -> N::RealField { self.c } diff --git a/src/linalg/schur.rs b/src/linalg/schur.rs index 9407cf7f..b31be9f6 100644 --- a/src/linalg/schur.rs +++ b/src/linalg/schur.rs @@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize}; use approx::AbsDiffEq; -use alga::general::{ComplexField, Real}; +use alga::general::{ComplexField, RealField}; use num_complex::Complex as NumComplex; use std::cmp; @@ -18,7 +18,7 @@ use crate::linalg::givens::GivensRotation; /// Schur decomposition of a square matrix. /// -/// If this is a real matrix, this will be a Real Schur decomposition. +/// If this is a real matrix, this will be a RealField Schur decomposition. #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[cfg_attr( feature = "serde-serialize", @@ -58,7 +58,7 @@ where { /// Computes the Schur decomposition of a square matrix. pub fn new(m: MatrixN) -> Self { - Self::try_new(m, N::Real::default_epsilon(), 0).unwrap() + Self::try_new(m, N::RealField::default_epsilon(), 0).unwrap() } /// Attempts to compute the Schur decomposition of a square matrix. @@ -72,7 +72,7 @@ where /// * `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_new(m: MatrixN, eps: N::Real, max_niter: usize) -> Option { + pub fn try_new(m: MatrixN, eps: N::RealField, max_niter: usize) -> Option { let mut work = unsafe { VectorN::new_uninitialized_generic(m.data.shape().0, U1) }; Self::do_decompose(m, &mut work, eps, max_niter, true).map(|(q, t)| Schur { @@ -84,7 +84,7 @@ where fn do_decompose( mut m: MatrixN, work: &mut VectorN, - eps: N::Real, + eps: N::RealField, max_niter: usize, compute_q: bool, ) -> Option<(Option>, MatrixN)> @@ -291,7 +291,7 @@ where /// Computes the complex eigenvalues of the decomposed matrix. fn do_complex_eigenvalues(t: &MatrixN, out: &mut VectorN, D>) - where N: Real, + where N: RealField, DefaultAllocator: Allocator, D> { let dim = t.nrows(); let mut m = 0; @@ -329,7 +329,7 @@ where } } - fn delimit_subproblem(t: &mut MatrixN, eps: N::Real, end: usize) -> (usize, usize) + fn delimit_subproblem(t: &mut MatrixN, eps: N::RealField, end: usize) -> (usize, usize) where D: DimSub, DefaultAllocator: Allocator>, @@ -390,7 +390,7 @@ where /// Computes the complex eigenvalues of the decomposed matrix. pub fn complex_eigenvalues(&self) -> VectorN, D> - where N: Real, + 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); @@ -511,7 +511,7 @@ where /// * `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_schur(self, eps: N::Real, max_niter: usize) -> Option> { + pub fn try_schur(self, eps: N::RealField, max_niter: usize) -> Option> { Schur::try_new(self.into_owned(), eps, max_niter) } @@ -543,7 +543,7 @@ where let schur = Schur::do_decompose( self.clone_owned(), &mut work, - N::Real::default_epsilon(), + N::RealField::default_epsilon(), 0, false, ) @@ -558,7 +558,7 @@ where /// Computes the eigenvalues of this matrix. pub fn complex_eigenvalues(&self) -> VectorN, D> // FIXME: add balancing? - where N: Real, + 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/svd.rs b/src/linalg/svd.rs index 714f398f..b608ec0c 100644 --- a/src/linalg/svd.rs +++ b/src/linalg/svd.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; use num::{Zero, One}; use approx::AbsDiffEq; -use alga::general::{Real, ComplexField}; +use alga::general::{RealField, ComplexField}; use crate::allocator::Allocator; use crate::base::{DefaultAllocator, Matrix, Matrix2x3, MatrixMN, Vector2, VectorN}; use crate::constraint::{SameNumberOfRows, ShapeConstraint}; @@ -20,47 +20,47 @@ use crate::linalg::givens::GivensRotation; #[cfg_attr( feature = "serde-serialize", serde(bound( - serialize = "DefaultAllocator: Allocator> + + serialize = "DefaultAllocator: Allocator> + Allocator, C> + Allocator>, MatrixMN>: Serialize, MatrixMN, C>: Serialize, - VectorN>: Serialize" + VectorN>: Serialize" )) )] #[cfg_attr( feature = "serde-serialize", serde(bound( - deserialize = "DefaultAllocator: Allocator> + + deserialize = "DefaultAllocator: Allocator> + Allocator, C> + Allocator>, MatrixMN>: Deserialize<'de>, MatrixMN, C>: Deserialize<'de>, - VectorN>: Deserialize<'de>" + VectorN>: Deserialize<'de>" )) )] #[derive(Clone, Debug)] pub struct SVD, C: Dim> where DefaultAllocator: Allocator, C> + Allocator> - + Allocator> + + Allocator> { /// The left-singular vectors `U` of this SVD. pub u: Option>>, /// The right-singular vectors `V^t` of this SVD. pub v_t: Option, C>>, /// The singular values of this SVD. - pub singular_values: VectorN>, + pub singular_values: VectorN>, } impl, C: Dim> Copy for SVD where DefaultAllocator: Allocator, C> + Allocator> - + Allocator>, + + Allocator>, MatrixMN>: Copy, MatrixMN, C>: Copy, - VectorN>: Copy, + VectorN>: Copy, {} impl, C: Dim> SVD @@ -73,12 +73,12 @@ where + Allocator, C> + Allocator> + Allocator> - + Allocator> - + Allocator, U1>>, + + Allocator> + + Allocator, U1>>, { /// 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::Real::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. @@ -95,7 +95,7 @@ where mut matrix: MatrixMN, compute_u: bool, compute_v: bool, - eps: N::Real, + eps: N::RealField, max_niter: usize, ) -> Option { @@ -150,7 +150,7 @@ where for k in start..n { let m12 = if k == n - 1 { - N::Real::zero() + N::RealField::zero() } else { off_diagonal[k + 1] }; @@ -158,8 +158,8 @@ where let mut subm = Matrix2x3::new( diagonal[k], off_diagonal[k], - N::Real::zero(), - N::Real::zero(), + N::RealField::zero(), + N::RealField::zero(), diagonal[k + 1], m12, ); @@ -229,7 +229,7 @@ where diagonal[start + 0] = s[0]; diagonal[start + 1] = s[1]; - off_diagonal[start] = N::Real::zero(); + off_diagonal[start] = N::RealField::zero(); if let Some(ref mut u) = u { let rot = if b.is_upper_diagonal() { @@ -269,7 +269,7 @@ where for i in 0..dim { let sval = diagonal[i]; - if sval < N::Real::zero() { + if sval < N::RealField::zero() { diagonal[i] = -sval; if let Some(ref mut u) = u { @@ -301,13 +301,13 @@ where */ fn delimit_subproblem( - diagonal: &mut VectorN>, - off_diagonal: &mut VectorN, U1>>, + diagonal: &mut VectorN>, + off_diagonal: &mut VectorN, U1>>, u: &mut Option>>, v_t: &mut Option, C>>, is_upper_diagonal: bool, end: usize, - eps: N::Real, + eps: N::RealField, ) -> (usize, usize) { let mut n = end; @@ -318,16 +318,16 @@ where if off_diagonal[m].is_zero() || off_diagonal[m].norm1() <= eps * (diagonal[n].norm1() + diagonal[m].norm1()) { - off_diagonal[m] = N::Real::zero(); + off_diagonal[m] = N::RealField::zero(); } else if diagonal[m].norm1() <= eps { - diagonal[m] = N::Real::zero(); + diagonal[m] = N::RealField::zero(); 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); } } else if diagonal[n].norm1() <= eps { - diagonal[n] = N::Real::zero(); + diagonal[n] = N::RealField::zero(); Self::cancel_vertical_off_diagonal_elt(diagonal, off_diagonal, u, v_t, is_upper_diagonal, m); } else { break; @@ -346,12 +346,12 @@ where if off_diagonal[m].norm1() <= eps * (diagonal[new_start].norm1() + diagonal[m].norm1()) { - off_diagonal[m] = N::Real::zero(); + off_diagonal[m] = N::RealField::zero(); break; } // FIXME: write a test that enters this case. else if diagonal[m].norm1() <= eps { - diagonal[m] = N::Real::zero(); + diagonal[m] = N::RealField::zero(); Self::cancel_horizontal_off_diagonal_elt(diagonal, off_diagonal, u, v_t, is_upper_diagonal, m, n); if m != 0 { @@ -368,8 +368,8 @@ where // Cancels the i-th off-diagonal element using givens rotations. fn cancel_horizontal_off_diagonal_elt( - diagonal: &mut VectorN>, - off_diagonal: &mut VectorN, U1>>, + diagonal: &mut VectorN>, + off_diagonal: &mut VectorN, U1>>, u: &mut Option>>, v_t: &mut Option, C>>, is_upper_diagonal: bool, @@ -378,7 +378,7 @@ where ) { let mut v = Vector2::new(off_diagonal[i], diagonal[i + 1]); - off_diagonal[i] = N::Real::zero(); + off_diagonal[i] = N::RealField::zero(); for k in i..end { if let Some((rot, norm)) = GivensRotation::cancel_x(&v) { @@ -407,8 +407,8 @@ where // Cancels the i-th off-diagonal element using givens rotations. fn cancel_vertical_off_diagonal_elt( - diagonal: &mut VectorN>, - off_diagonal: &mut VectorN, U1>>, + diagonal: &mut VectorN>, + off_diagonal: &mut VectorN, U1>>, u: &mut Option>>, v_t: &mut Option, C>>, is_upper_diagonal: bool, @@ -416,7 +416,7 @@ where ) { let mut v = Vector2::new(diagonal[i], off_diagonal[i]); - off_diagonal[i] = N::Real::zero(); + off_diagonal[i] = N::RealField::zero(); for k in (0..i + 1).rev() { if let Some((rot, norm)) = GivensRotation::cancel_y(&v) { @@ -445,9 +445,9 @@ where /// Computes the rank of the decomposed matrix, i.e., the number of singular values greater /// than `eps`. - pub fn rank(&self, eps: N::Real) -> usize { + pub fn rank(&self, eps: N::RealField) -> usize { assert!( - eps >= N::Real::zero(), + eps >= N::RealField::zero(), "SVD rank: the epsilon must be non-negative." ); self.singular_values.iter().filter(|e| **e > eps).count() @@ -478,11 +478,11 @@ where /// Any singular value smaller than `eps` is assumed to be zero. /// Returns `Err` if the right- and left- singular vectors have not /// been computed at construction-time. - pub fn pseudo_inverse(mut self, eps: N::Real) -> Result, &'static str> + pub fn pseudo_inverse(mut self, eps: N::RealField) -> Result, &'static str> where DefaultAllocator: Allocator, { - if eps < N::Real::zero() { + if eps < N::RealField::zero() { Err("SVD pseudo inverse: the epsilon must be non-negative.") } else { @@ -490,9 +490,9 @@ where let val = self.singular_values[i]; if val > eps { - self.singular_values[i] = N::Real::one() / val; + self.singular_values[i] = N::RealField::one() / val; } else { - self.singular_values[i] = N::Real::zero(); + self.singular_values[i] = N::RealField::zero(); } } @@ -508,14 +508,14 @@ where pub fn solve( &self, b: &Matrix, - eps: N::Real, + eps: N::RealField, ) -> Result, &'static str> where S2: Storage, DefaultAllocator: Allocator + Allocator, C2>, ShapeConstraint: SameNumberOfRows, { - if eps < N::Real::zero() { + if eps < N::RealField::zero() { Err("SVD solve: the epsilon must be non-negative.") } else { @@ -556,8 +556,8 @@ where + Allocator, C> + Allocator> + Allocator> - + Allocator> - + Allocator, U1>>, + + Allocator> + + Allocator, U1>>, { /// Computes the Singular Value Decomposition using implicit shift. pub fn svd(self, compute_u: bool, compute_v: bool) -> SVD { @@ -578,7 +578,7 @@ where self, compute_u: bool, compute_v: bool, - eps: N::Real, + eps: N::RealField, max_niter: usize, ) -> Option> { @@ -586,14 +586,14 @@ where } /// Computes the singular values of this matrix. - pub fn singular_values(&self) -> VectorN> { + pub fn singular_values(&self) -> VectorN> { SVD::new(self.clone_owned(), false, false).singular_values } /// Computes the rank of this matrix. /// /// All singular values below `eps` are considered equal to 0. - pub fn rank(&self, eps: N::Real) -> usize { + pub fn rank(&self, eps: N::RealField) -> usize { let svd = SVD::new(self.clone_owned(), false, false); svd.rank(eps) } @@ -601,7 +601,7 @@ where /// Computes the pseudo-inverse of this matrix. /// /// All singular values below `eps` are considered equal to 0. - pub fn pseudo_inverse(self, eps: N::Real) -> Result, &'static str> + pub fn pseudo_inverse(self, eps: N::RealField) -> Result, &'static str> where DefaultAllocator: Allocator, { @@ -613,7 +613,7 @@ where // 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 -fn compute_2x2_uptrig_svd( +fn compute_2x2_uptrig_svd( m11: N, m12: N, m22: N, @@ -621,8 +621,8 @@ fn compute_2x2_uptrig_svd( compute_v: bool, ) -> (Option>, Vector2, Option>) { - let two: N::Real = crate::convert(2.0f64); - let half: N::Real = crate::convert(0.5f64); + let two: N::RealField = crate::convert(2.0f64); + let half: N::RealField = crate::convert(0.5f64); let denom = (m11 + m22).hypot(m12) + (m11 - m22).hypot(m12); diff --git a/src/linalg/symmetric_eigen.rs b/src/linalg/symmetric_eigen.rs index 78e00509..fc493dca 100644 --- a/src/linalg/symmetric_eigen.rs +++ b/src/linalg/symmetric_eigen.rs @@ -19,8 +19,8 @@ use crate::linalg::SymmetricTridiagonal; feature = "serde-serialize", serde(bound( serialize = "DefaultAllocator: Allocator + - Allocator, - VectorN: Serialize, + Allocator, + VectorN: Serialize, MatrixN: Serialize" )) )] @@ -28,31 +28,31 @@ use crate::linalg::SymmetricTridiagonal; feature = "serde-serialize", serde(bound( deserialize = "DefaultAllocator: Allocator + - Allocator, - VectorN: Deserialize<'de>, + Allocator, + VectorN: Deserialize<'de>, MatrixN: Deserialize<'de>" )) )] #[derive(Clone, Debug)] pub struct SymmetricEigen -where DefaultAllocator: Allocator + Allocator +where DefaultAllocator: Allocator + Allocator { /// The eigenvectors of the decomposed matrix. pub eigenvectors: MatrixN, /// The unsorted eigenvalues of the decomposed matrix. - pub eigenvalues: VectorN, + pub eigenvalues: VectorN, } impl Copy for SymmetricEigen where - DefaultAllocator: Allocator + Allocator, + DefaultAllocator: Allocator + Allocator, MatrixN: Copy, - VectorN: Copy, + VectorN: Copy, {} impl SymmetricEigen -where DefaultAllocator: Allocator + Allocator +where DefaultAllocator: Allocator + Allocator { /// Computes the eigendecomposition of the given symmetric matrix. /// @@ -61,9 +61,9 @@ where DefaultAllocator: Allocator + Allocator where D: DimSub, DefaultAllocator: Allocator> + // For tridiagonalization - Allocator>, + Allocator>, { - Self::try_new(m, N::Real::default_epsilon(), 0).unwrap() + Self::try_new(m, N::RealField::default_epsilon(), 0).unwrap() } /// Computes the eigendecomposition of the given symmetric matrix with user-specified @@ -77,11 +77,11 @@ 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_new(m: MatrixN, eps: N::Real, max_niter: usize) -> Option + pub fn try_new(m: MatrixN, eps: N::RealField, max_niter: usize) -> Option where D: DimSub, DefaultAllocator: Allocator> + // For tridiagonalization - Allocator>, + Allocator>, { Self::do_decompose(m, true, eps, max_niter).map(|(vals, vecs)| SymmetricEigen { eigenvectors: vecs.unwrap(), @@ -92,13 +92,13 @@ where DefaultAllocator: Allocator + Allocator fn do_decompose( mut m: MatrixN, eigenvectors: bool, - eps: N::Real, + eps: N::RealField, max_niter: usize, - ) -> Option<(VectorN, Option>)> + ) -> Option<(VectorN, Option>)> where D: DimSub, DefaultAllocator: Allocator> + // For tridiagonalization - Allocator>, + Allocator>, { assert!( m.is_square(), @@ -226,14 +226,14 @@ where DefaultAllocator: Allocator + Allocator } fn delimit_subproblem( - diag: &VectorN, - off_diag: &mut VectorN>, + diag: &VectorN, + off_diag: &mut VectorN>, end: usize, - eps: N::Real, + eps: N::RealField, ) -> (usize, usize) where D: DimSub, - DefaultAllocator: Allocator>, + DefaultAllocator: Allocator>, { let mut n = end; @@ -258,7 +258,7 @@ where DefaultAllocator: Allocator + Allocator if off_diag[m].is_zero() || off_diag[m].norm1() <= eps * (diag[new_start].norm1() + diag[m].norm1()) { - off_diag[m] = N::Real::zero(); + off_diag[m] = N::RealField::zero(); break; } @@ -306,7 +306,7 @@ pub fn wilkinson_shift(tmm: N, tnn: N, tmn: N) -> N { */ impl, S: Storage> SquareMatrix where DefaultAllocator: Allocator + Allocator> + - Allocator + Allocator> + Allocator + Allocator> { /// Computes the eigendecomposition of this symmetric matrix. /// @@ -326,15 +326,15 @@ 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::Real, 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) } /// Computes the eigenvalues of this symmetric matrix. /// /// Only the lower-triangular part of the matrix is read. - pub fn symmetric_eigenvalues(&self) -> VectorN { - SymmetricEigen::do_decompose(self.clone_owned(), false, N::Real::default_epsilon(), 0) + pub fn symmetric_eigenvalues(&self) -> VectorN { + 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 0a04dae8..40da8677 100644 --- a/src/linalg/symmetric_tridiagonal.rs +++ b/src/linalg/symmetric_tridiagonal.rs @@ -98,9 +98,9 @@ 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,19 +108,19 @@ 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()) } + pub fn diagonal(&self) -> VectorN + where DefaultAllocator: Allocator { self.tri.map_diagonal(|e| e.real()) } /// The off-diagonal components of this decomposition. - pub fn off_diagonal(&self) -> VectorN> - where DefaultAllocator: Allocator> { + pub fn off_diagonal(&self) -> VectorN> + where DefaultAllocator: Allocator> { self.off_diagonal.map(N::modulus) } diff --git a/src/sparse/cs_matrix_cholesky.rs b/src/sparse/cs_matrix_cholesky.rs index fc7e97f9..4c3fffd8 100644 --- a/src/sparse/cs_matrix_cholesky.rs +++ b/src/sparse/cs_matrix_cholesky.rs @@ -3,10 +3,10 @@ use std::mem; use crate::allocator::Allocator; use crate::sparse::{CsMatrix, CsStorage, CsStorageIter, CsStorageIterMut, CsVecStorage}; -use crate::{DefaultAllocator, Dim, Real, VectorN, U1}; +use crate::{DefaultAllocator, Dim, RealField, VectorN, U1}; /// The cholesky decomposition of a column compressed sparse matrix. -pub struct CsCholesky +pub struct CsCholesky where DefaultAllocator: Allocator + Allocator { // Non-zero pattern of the original matrix upper-triangular part. @@ -25,7 +25,7 @@ where DefaultAllocator: Allocator + Allocator work_c: VectorN, } -impl CsCholesky +impl CsCholesky where DefaultAllocator: Allocator + Allocator { /// Computes the cholesky decomposition of the sparse matrix `m`. diff --git a/src/sparse/cs_matrix_solve.rs b/src/sparse/cs_matrix_solve.rs index a6bb628d..1dfd7843 100644 --- a/src/sparse/cs_matrix_solve.rs +++ b/src/sparse/cs_matrix_solve.rs @@ -2,9 +2,9 @@ use crate::allocator::Allocator; use crate::constraint::{SameNumberOfRows, ShapeConstraint}; use crate::sparse::{CsMatrix, CsStorage, CsVector}; use crate::storage::{Storage, StorageMut}; -use crate::{DefaultAllocator, Dim, Matrix, MatrixMN, Real, VectorN, U1}; +use crate::{DefaultAllocator, Dim, Matrix, MatrixMN, RealField, VectorN, U1}; -impl> CsMatrix { +impl> CsMatrix { /// Solve a lower-triangular system with a dense right-hand-side. pub fn solve_lower_triangular( &self, diff --git a/tests/core/helper.rs b/tests/core/helper.rs index 9b9dfa75..625a4a46 100644 --- a/tests/core/helper.rs +++ b/tests/core/helper.rs @@ -5,12 +5,12 @@ use quickcheck::{Arbitrary, Gen}; use rand::distributions::{Standard, Distribution}; use rand::Rng; use num_complex::Complex; -use na::Real; +use na::RealField; #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct RandComplex(pub Complex); -impl Arbitrary for RandComplex { +impl Arbitrary for RandComplex { #[inline] fn arbitrary(rng: &mut G) -> Self { let im = Arbitrary::arbitrary(rng); @@ -19,7 +19,7 @@ impl Arbitrary for RandComplex { } } -impl Distribution> for Standard +impl Distribution> for Standard where Standard: Distribution, { @@ -43,7 +43,7 @@ impl Arbitrary for RandScalar { } } -impl Distribution> for Standard +impl Distribution> for Standard where Standard: Distribution, { diff --git a/tests/core/matrix.rs b/tests/core/matrix.rs index 81de11b0..1517091b 100644 --- a/tests/core/matrix.rs +++ b/tests/core/matrix.rs @@ -4,7 +4,7 @@ use std::cmp::Ordering; use na::dimension::{U15, U8}; use na::{ self, DMatrix, DVector, Matrix2, Matrix2x3, Matrix2x4, Matrix3, Matrix3x2, Matrix3x4, Matrix4, - Matrix4x3, Matrix4x5, Matrix5, Matrix6, MatrixMN, Real, RowVector3, RowVector4, RowVector5, + Matrix4x3, Matrix4x5, Matrix5, Matrix6, MatrixMN, RealField, RowVector3, RowVector4, RowVector5, Vector1, Vector2, Vector3, Vector4, Vector5, Vector6, }; @@ -1022,7 +1022,7 @@ mod finite_dim_inner_space_tests { * */ #[cfg(feature = "arbitrary")] - fn is_subspace_basis + Display>(vs: &[T]) -> bool { + fn is_subspace_basis + Display>(vs: &[T]) -> bool { for i in 0..vs.len() { // Basis elements must be normalized. if !relative_eq!(vs[i].norm(), 1.0, epsilon = 1.0e-7) { diff --git a/tests/geometry/rotation.rs b/tests/geometry/rotation.rs index e4b1f9d7..c0886754 100644 --- a/tests/geometry/rotation.rs +++ b/tests/geometry/rotation.rs @@ -1,4 +1,4 @@ -use na::{Quaternion, Real, UnitQuaternion, Vector2, Vector3}; +use na::{Quaternion, RealField, UnitQuaternion, Vector2, Vector3}; #[test] fn angle_2() { @@ -32,7 +32,7 @@ fn quaternion_euler_angles_issue_494() { #[cfg(feature = "arbitrary")] mod quickcheck_tests { - use alga::general::Real; + use alga::general::RealField; use na::{self, Rotation2, Rotation3, Unit, Vector2, Vector3}; use std::f64; From 3b6cd04a804b7dc30538d8574ab3283714e84c0c Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Tue, 26 Mar 2019 18:02:03 +0100 Subject: [PATCH 19/28] Adapt BLAS tests to complex numbers. --- src/base/blas.rs | 253 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 187 insertions(+), 66 deletions(-) diff --git a/src/base/blas.rs b/src/base/blas.rs index 55a20216..e4d7ea7d 100644 --- a/src/base/blas.rs +++ b/src/base/blas.rs @@ -11,7 +11,7 @@ use crate::base::constraint::{ }; use crate::base::dimension::{Dim, Dynamic, U1, U2, U3, U4}; use crate::base::storage::{Storage, StorageMut}; -use crate::base::{DefaultAllocator, Matrix, Scalar, SquareMatrix, Vector, DVectorSlice}; +use crate::base::{DefaultAllocator, Matrix, Scalar, SquareMatrix, Vector, DVectorSlice, VectorSliceN}; // FIXME: find a way to avoid code duplication just for complex number support. @@ -368,6 +368,9 @@ where N: Scalar + Zero + ClosedAdd + ClosedMul /// The dot product between two vectors or matrices (seen as vectors). /// + /// This is equal to `self.transpose() * rhs`. For the sesquilinear complex dot product, use + /// `self.dotc(rhs)`. + /// /// Note that this is **not** the matrix multiplication as in, e.g., numpy. For matrix /// multiplication, use one of: `.gemm`, `.mul_to`, `.mul`, the `*` operator. /// @@ -385,6 +388,7 @@ where N: Scalar + Zero + ClosedAdd + ClosedMul /// 0.4, 0.5, 0.6); /// assert_eq!(mat1.dot(&mat2), 9.1); /// ``` + /// #[inline] pub fn dot(&self, rhs: &Matrix) -> N where @@ -394,24 +398,24 @@ where N: Scalar + Zero + ClosedAdd + ClosedMul self.dotx(rhs, |e| e) } - /// The dot product between two vectors or matrices (seen as vectors). + /// The conjugate-linear dot product between two vectors or matrices (seen as vectors). /// + /// This is equal to `self.adjoint() * rhs`. + /// For real vectors, this is identical to `self.dot(&rhs)`. /// Note that this is **not** the matrix multiplication as in, e.g., numpy. For matrix /// multiplication, use one of: `.gemm`, `.mul_to`, `.mul`, the `*` operator. /// /// # Examples: /// /// ``` - /// # use nalgebra::{Vector3, Matrix2x3}; - /// let vec1 = Vector3::new(1.0, 2.0, 3.0); - /// let vec2 = Vector3::new(0.1, 0.2, 0.3); - /// assert_eq!(vec1.dot(&vec2), 1.4); + /// # use nalgebra::{Vector2, Complex}; + /// let vec1 = Vector2::new(Complex::new(1.0, 2.0), Complex::new(3.0, 4.0)); + /// let vec2 = Vector2::new(Complex::new(0.4, 0.3), Complex::new(0.2, 0.1)); + /// assert_eq!(vec1.dotc(&vec2), Complex::new(2.0, -1.0)); /// - /// let mat1 = Matrix2x3::new(1.0, 2.0, 3.0, - /// 4.0, 5.0, 6.0); - /// let mat2 = Matrix2x3::new(0.1, 0.2, 0.3, - /// 0.4, 0.5, 0.6); - /// assert_eq!(mat1.dot(&mat2), 9.1); + /// // Note that for complex vectors, we generally have: + /// // vec1.dotc(&vec2) != vec2.dot(&vec2) + /// assert_ne!(vec1.dotc(&vec2), vec1.dot(&vec2)); /// ``` #[inline] pub fn dotc(&self, rhs: &Matrix) -> N @@ -579,7 +583,7 @@ where #[inline(always)] - fn xgemv( + fn xxgemv( &mut self, alpha: N, a: &SquareMatrix, @@ -651,6 +655,7 @@ where /// Computes `self = alpha * a * x + beta * self`, where `a` is a **symmetric** matrix, `x` a /// vector, and `alpha, beta` two scalars. /// + /// For hermitian matrices, use `.hegemv` instead. /// If `beta` is zero, `self` is never read. If `self` is read, only its lower-triangular part /// (including the diagonal) is actually read. /// @@ -688,7 +693,7 @@ where SC: Storage, ShapeConstraint: DimEq + AreMultipliable, { - self.xgemv(alpha, a, x, beta, |a, b| a.dot(b)) + self.xxgemv(alpha, a, x, beta, |a, b| a.dot(b)) } /// Computes `self = alpha * a * x + beta * self`, where `a` is an **hermitian** matrix, `x` a @@ -700,23 +705,25 @@ where /// # Examples: /// /// ``` - /// # use nalgebra::{Matrix2, Vector2}; - /// let mat = Matrix2::new(1.0, 2.0, - /// 2.0, 4.0); - /// let mut vec1 = Vector2::new(1.0, 2.0); - /// let vec2 = Vector2::new(0.1, 0.2); - /// vec1.sygemv(10.0, &mat, &vec2, 5.0); - /// assert_eq!(vec1, Vector2::new(10.0, 20.0)); + /// # use nalgebra::{Matrix2, Vector2, Complex}; + /// let mat = Matrix2::new(Complex::new(1.0, 0.0), Complex::new(2.0, -0.1), + /// Complex::new(2.0, 1.0), Complex::new(4.0, 0.0)); + /// let mut vec1 = Vector2::new(Complex::new(1.0, 2.0), Complex::new(3.0, 4.0)); + /// let vec2 = Vector2::new(Complex::new(0.1, 0.2), Complex::new(0.3, 0.4)); + /// vec1.sygemv(Complex::new(10.0, 20.0), &mat, &vec2, Complex::new(5.0, 15.0)); + /// assert_eq!(vec1, Vector2::new(Complex::new(-48.0, 44.0), Complex::new(-75.0, 110.0))); /// /// /// // The matrix upper-triangular elements can be garbage because it is never /// // read by this method. Therefore, it is not necessary for the caller to /// // fill the matrix struct upper-triangle. - /// let mat = Matrix2::new(1.0, 9999999.9999999, - /// 2.0, 4.0); - /// let mut vec1 = Vector2::new(1.0, 2.0); - /// vec1.sygemv(10.0, &mat, &vec2, 5.0); - /// assert_eq!(vec1, Vector2::new(10.0, 20.0)); + /// + /// let mat = Matrix2::new(Complex::new(1.0, 0.0), Complex::new(99999999.9, 999999999.9), + /// Complex::new(2.0, 1.0), Complex::new(4.0, 0.0)); + /// let mut vec1 = Vector2::new(Complex::new(1.0, 2.0), Complex::new(3.0, 4.0)); + /// let vec2 = Vector2::new(Complex::new(0.1, 0.2), Complex::new(0.3, 0.4)); + /// vec1.sygemv(Complex::new(10.0, 20.0), &mat, &vec2, Complex::new(5.0, 15.0)); + /// assert_eq!(vec1, Vector2::new(Complex::new(-48.0, 44.0), Complex::new(-75.0, 110.0))); /// ``` #[inline] pub fn hegemv( @@ -731,9 +738,51 @@ where SC: Storage, ShapeConstraint: DimEq + AreMultipliable, { - self.xgemv(alpha, a, x, beta, |a, b| a.dotc(b)) + self.xxgemv(alpha, a, x, beta, |a, b| a.dotc(b)) } + + #[inline(always)] + fn gemv_xx( + &mut self, + alpha: N, + a: &Matrix, + x: &Vector, + beta: N, + dot: impl Fn(&VectorSliceN, &Vector) -> N, + ) where + N: One, + SB: Storage, + SC: Storage, + ShapeConstraint: DimEq + AreMultipliable, + { + let dim1 = self.nrows(); + let (nrows2, ncols2) = a.shape(); + let dim3 = x.nrows(); + + assert!( + nrows2 == dim3 && dim1 == ncols2, + "Gemv: dimensions mismatch." + ); + + if ncols2 == 0 { + return; + } + + if beta.is_zero() { + for j in 0..ncols2 { + let val = unsafe { self.vget_unchecked_mut(j) }; + *val = alpha * dot(&a.column(j), x) + } + } else { + for j in 0..ncols2 { + let val = unsafe { self.vget_unchecked_mut(j) }; + *val = alpha * dot(&a.column(j), x) + beta * *val; + } + } + } + + /// Computes `self = alpha * a.transpose() * x + beta * self`, where `a` is a matrix, `x` a vector, and /// `alpha, beta` two scalars. /// @@ -765,30 +814,42 @@ where SC: Storage, ShapeConstraint: DimEq + AreMultipliable, { - let dim1 = self.nrows(); - let (nrows2, ncols2) = a.shape(); - let dim3 = x.nrows(); + self.gemv_xx(alpha, a, x, beta, |a, b| a.dot(b)) + } - assert!( - nrows2 == dim3 && dim1 == ncols2, - "Gemv: dimensions mismatch." - ); - - if ncols2 == 0 { - return; - } - - if beta.is_zero() { - for j in 0..ncols2 { - let val = unsafe { self.vget_unchecked_mut(j) }; - *val = alpha * a.column(j).dot(x) - } - } else { - for j in 0..ncols2 { - let val = unsafe { self.vget_unchecked_mut(j) }; - *val = alpha * a.column(j).dot(x) + beta * *val; - } - } + /// Computes `self = alpha * a.adjoint() * x + beta * self`, where `a` is a matrix, `x` a vector, and + /// `alpha, beta` two scalars. + /// + /// For real matrices, this is the same as `.gemv_tr`. + /// If `beta` is zero, `self` is never read. + /// + /// # Examples: + /// + /// ``` + /// # use nalgebra::{Matrix2, Vector2, Complex}; + /// let mat = Matrix2::new(Complex::new(1.0, 2.0), Complex::new(3.0, 4.0), + /// Complex::new(5.0, 6.0), Complex::new(7.0, 8.0)); + /// let mut vec1 = Vector2::new(Complex::new(1.0, 2.0), Complex::new(3.0, 4.0)); + /// let vec2 = Vector2::new(Complex::new(0.1, 0.2), Complex::new(0.3, 0.4)); + /// let expected = mat.adjoint() * vec2 * Complex::new(10.0, 20.0) + vec1 * Complex::new(5.0, 15.0); + /// + /// vec1.gemv_ad(Complex::new(10.0, 20.0), &mat, &vec2, Complex::new(5.0, 15.0)); + /// assert_eq!(vec1, expected); + /// ``` + #[inline] + pub fn gemv_ad( + &mut self, + alpha: N, + a: &Matrix, + x: &Vector, + beta: N, + ) where + N: ComplexField, + SB: Storage, + SC: Storage, + ShapeConstraint: DimEq + AreMultipliable, + { + self.gemv_xx(alpha, a, x, beta, |a, b| a.dotc(b)) } } @@ -857,20 +918,21 @@ where N: Scalar + Zero + ClosedAdd + ClosedMul self.gerx(alpha, x, y, beta, |e| e) } - /// Computes `self = alpha * x * y.transpose() + beta * self`. + /// Computes `self = alpha * x * y.adjoint() + beta * self`. /// /// If `beta` is zero, `self` is never read. /// /// # Examples: /// /// ``` - /// # use nalgebra::{Matrix2x3, Vector2, Vector3}; - /// let mut mat = Matrix2x3::repeat(4.0); - /// let vec1 = Vector2::new(1.0, 2.0); - /// let vec2 = Vector3::new(0.1, 0.2, 0.3); - /// let expected = vec1 * vec2.transpose() * 10.0 + mat * 5.0; + /// # #[macro_use] extern crate approx; + /// # use nalgebra::{Matrix2x3, Vector2, Vector3, Complex}; + /// let mut mat = Matrix2x3::repeat(Complex::new(4.0, 5.0)); + /// let vec1 = Vector2::new(Complex::new(1.0, 2.0), Complex::new(3.0, 4.0)); + /// let vec2 = Vector3::new(Complex::new(0.6, 0.5), Complex::new(0.4, 0.5), Complex::new(0.2, 0.1)); + /// let expected = vec1 * vec2.adjoint() * Complex::new(10.0, 20.0) + mat * Complex::new(5.0, 15.0); /// - /// mat.ger(10.0, &vec1, &vec2, 5.0); + /// mat.gerc(Complex::new(10.0, 20.0), &vec1, &vec2, Complex::new(5.0, 15.0)); /// assert_eq!(mat, expected); /// ``` #[inline] @@ -1041,7 +1103,7 @@ where N: Scalar + Zero + ClosedAdd + ClosedMul /// let expected = mat2.transpose() * mat3 * 10.0 + mat1 * 5.0; /// /// mat1.gemm_tr(10.0, &mat2, &mat3, 5.0); - /// assert_relative_eq!(mat1, expected); + /// assert_eq!(mat1, expected); /// ``` #[inline] pub fn gemm_tr( @@ -1077,6 +1139,64 @@ where N: Scalar + Zero + ClosedAdd + ClosedMul self.column_mut(j1).gemv_tr(alpha, a, &b.column(j1), beta); } } + + + /// Computes `self = alpha * a.adjoint() * b + beta * self`, where `a, b, self` are matrices. + /// `alpha` and `beta` are scalar. + /// + /// If `beta` is zero, `self` is never read. + /// + /// # Examples: + /// + /// ``` + /// # #[macro_use] extern crate approx; + /// # use nalgebra::{Matrix3x2, Matrix3x4, Matrix2x4, Complex}; + /// let mut mat1 = Matrix2x4::identity(); + /// let mat2 = Matrix3x2::new(Complex::new(1.0, 4.0), Complex::new(7.0, 8.0), + /// Complex::new(2.0, 5.0), Complex::new(9.0, 10.0), + /// Complex::new(3.0, 6.0), Complex::new(11.0, 12.0)); + /// let mat3 = Matrix3x4::new(Complex::new(0.1, 1.3), Complex::new(0.2, 1.4), Complex::new(0.3, 1.5), Complex::new(0.4, 1.6), + /// Complex::new(0.5, 1.7), Complex::new(0.6, 1.8), Complex::new(0.7, 1.9), Complex::new(0.8, 2.0), + /// Complex::new(0.9, 2.1), Complex::new(1.0, 2.2), Complex::new(1.1, 2.3), Complex::new(1.2, 2.4)); + /// let expected = mat2.adjoint() * mat3 * Complex::new(10.0, 20.0) + mat1 * Complex::new(5.0, 15.0); + /// + /// mat1.gemm_ad(Complex::new(10.0, 20.0), &mat2, &mat3, Complex::new(5.0, 15.0)); + /// assert_eq!(mat1, expected); + /// ``` + #[inline] + pub fn gemm_ad( + &mut self, + alpha: N, + a: &Matrix, + b: &Matrix, + beta: N, + ) where + N: ComplexField, + SB: Storage, + SC: Storage, + ShapeConstraint: SameNumberOfRows + + SameNumberOfColumns + + AreMultipliable, + { + let (nrows1, ncols1) = self.shape(); + let (nrows2, ncols2) = a.shape(); + let (nrows3, ncols3) = b.shape(); + + assert_eq!( + nrows2, nrows3, + "gemm: dimensions mismatch for multiplication." + ); + assert_eq!( + (nrows1, ncols1), + (ncols2, ncols3), + "gemm: dimensions mismatch for addition." + ); + + for j1 in 0..ncols1 { + // FIXME: avoid bound checks. + self.column_mut(j1).gemv_ad(alpha, a, &b.column(j1), beta); + } + } } impl> Matrix @@ -1157,6 +1277,7 @@ where N: Scalar + Zero + ClosedAdd + ClosedMul /// Computes `self = alpha * x * y.transpose() + beta * self`, where `self` is a **symmetric** /// matrix. /// + /// For hermitian complex matrices, use `.hegerc` instead. /// If `beta` is zero, `self` is never read. The result is symmetric. Only the lower-triangular /// (including the diagonal) part of `self` is read/written. /// @@ -1170,7 +1291,7 @@ where N: Scalar + Zero + ClosedAdd + ClosedMul /// let expected = vec1 * vec2.transpose() * 10.0 + mat * 5.0; /// mat.m12 = 99999.99999; // This component is on the upper-triangular part and will not be read/written. /// - /// mat.ger_symm(10.0, &vec1, &vec2, 5.0); + /// mat.syger(10.0, &vec1, &vec2, 5.0); /// assert_eq!(mat.lower_triangle(), expected.lower_triangle()); /// assert_eq!(mat.m12, 99999.99999); // This was untouched. #[inline] @@ -1189,7 +1310,7 @@ where N: Scalar + Zero + ClosedAdd + ClosedMul self.xxgerx(alpha, x, y, beta, |e| e) } - /// Computes `self = alpha * x * y.transpose() + beta * self`, where `self` is a **symmetric** + /// Computes `self = alpha * x * y.adjoint() + beta * self`, where `self` is an **hermitian** /// matrix. /// /// If `beta` is zero, `self` is never read. The result is symmetric. Only the lower-triangular @@ -1198,16 +1319,16 @@ where N: Scalar + Zero + ClosedAdd + ClosedMul /// # Examples: /// /// ``` - /// # use nalgebra::{Matrix2, Vector2}; + /// # use nalgebra::{Matrix2, Vector2, Complex}; /// let mut mat = Matrix2::identity(); - /// let vec1 = Vector2::new(1.0, 2.0); - /// let vec2 = Vector2::new(0.1, 0.2); - /// let expected = vec1 * vec2.transpose() * 10.0 + mat * 5.0; - /// mat.m12 = 99999.99999; // This component is on the upper-triangular part and will not be read/written. + /// let vec1 = Vector2::new(Complex::new(1.0, 3.0), Complex::new(2.0, 4.0)); + /// let vec2 = Vector2::new(Complex::new(0.2, 0.4), Complex::new(0.1, 0.3)); + /// let expected = vec1 * vec2.adjoint() * Complex::new(10.0, 20.0) + mat * Complex::new(5.0, 15.0); + /// mat.m12 = Complex::new(99999.99999, 88888.88888); // This component is on the upper-triangular part and will not be read/written. /// - /// mat.ger_symm(10.0, &vec1, &vec2, 5.0); + /// mat.hegerc(Complex::new(10.0, 20.0), &vec1, &vec2, Complex::new(5.0, 15.0)); /// assert_eq!(mat.lower_triangle(), expected.lower_triangle()); - /// assert_eq!(mat.m12, 99999.99999); // This was untouched. + /// assert_eq!(mat.m12, Complex::new(99999.99999, 88888.88888)); // This was untouched. #[inline] pub fn hegerc( &mut self, From 56f961c4bc3ca0fbf406c8affddf088055cfa119 Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Tue, 26 Mar 2019 18:02:14 +0100 Subject: [PATCH 20/28] Reexport Complex from num_complex. --- src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib.rs b/src/lib.rs index 0388290b..65b827b5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -161,6 +161,7 @@ use alga::linear::{EuclideanSpace, FiniteDimVectorSpace, InnerSpace, NormedSpace use num::Signed; pub use alga::general::{Id, RealField, ComplexField}; +pub use num_complex::Complex; /* * From f9995f1fcc50b81d0dc9aad8c552394920881d0c Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sun, 31 Mar 2019 09:12:45 +0200 Subject: [PATCH 21/28] Fix tests. --- Cargo.toml | 2 +- tests/core/matrix.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index fe87f723..6da6b04d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nalgebra" -version = "0.17.2" +version = "0.17.3" authors = [ "Sébastien Crozet " ] description = "Linear algebra library with transformations and statically-sized or dynamically-sized matrices." diff --git a/tests/core/matrix.rs b/tests/core/matrix.rs index 1517091b..e4fb4d0c 100644 --- a/tests/core/matrix.rs +++ b/tests/core/matrix.rs @@ -4,7 +4,7 @@ use std::cmp::Ordering; use na::dimension::{U15, U8}; use na::{ self, DMatrix, DVector, Matrix2, Matrix2x3, Matrix2x4, Matrix3, Matrix3x2, Matrix3x4, Matrix4, - Matrix4x3, Matrix4x5, Matrix5, Matrix6, MatrixMN, RealField, RowVector3, RowVector4, RowVector5, + Matrix4x3, Matrix4x5, Matrix5, Matrix6, MatrixMN, RowVector3, RowVector4, RowVector5, Vector1, Vector2, Vector3, Vector4, Vector5, Vector6, }; @@ -417,7 +417,7 @@ fn simple_scalar_conversion() { #[test] fn apply() { let mut a = Matrix4::new( - 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 8.8, 7.7, 6.6, 5.5, 4.4, 3.3, 2.2, + 1.1f32, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 8.8, 7.7, 6.6, 5.5, 4.4, 3.3, 2.2, ); let expected = Matrix4::new( From ba40e8eb55e1ab0096996bc5d4efc7ba6203a123 Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sun, 31 Mar 2019 10:53:11 +0200 Subject: [PATCH 22/28] Fix merge errors due to the switch to rust 2018. --- Cargo.toml | 3 --- src/geometry/quaternion.rs | 4 ++-- src/geometry/rotation.rs | 2 +- src/linalg/convolution.rs | 13 +++++++------ 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7c1f4b1a..424c4483 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,8 +64,5 @@ name = "nalgebra_bench" harness = false path = "benches/lib.rs" -[patch.crates-io] -alga = { path = "../alga/alga" } - [profile.bench] lto = true diff --git a/src/geometry/quaternion.rs b/src/geometry/quaternion.rs index 208145d7..2986dc12 100755 --- a/src/geometry/quaternion.rs +++ b/src/geometry/quaternion.rs @@ -591,13 +591,13 @@ impl Quaternion { /// Divides quaternion into two. #[inline] pub fn half(&self) -> Self { - self / ::convert(2.0f64) + self / crate::convert(2.0f64) } /// Calculates square root. #[inline] pub fn sqrt(&self) -> Self { - self.powf(::convert(0.5)) + self.powf(crate::convert(0.5)) } /// Check if the quaternion is pure. diff --git a/src/geometry/rotation.rs b/src/geometry/rotation.rs index 63ba0279..ec9c8150 100755 --- a/src/geometry/rotation.rs +++ b/src/geometry/rotation.rs @@ -352,7 +352,7 @@ where DefaultAllocator: Allocator } } -impl Rotation +impl Rotation where DefaultAllocator: Allocator + Allocator { /// Rotate the given point. diff --git a/src/linalg/convolution.rs b/src/linalg/convolution.rs index b121b34a..3f934eda 100644 --- a/src/linalg/convolution.rs +++ b/src/linalg/convolution.rs @@ -1,11 +1,12 @@ -use base::allocator::Allocator; -use base::default_allocator::DefaultAllocator; -use base::dimension::{Dim, DimAdd, DimDiff, DimMax, DimMaximum, DimSub, DimSum}; use std::cmp; -use storage::Storage; -use {zero, Real, Vector, VectorN, U1}; -impl> Vector { +use crate::base::allocator::Allocator; +use crate::base::default_allocator::DefaultAllocator; +use crate::base::dimension::{Dim, DimAdd, DimDiff, DimMax, DimMaximum, DimSub, DimSum}; +use crate::storage::Storage; +use crate::{zero, RealField, Vector, VectorN, U1}; + +impl> Vector { /// Returns the convolution of the target vector and a kernel /// /// # Arguments From eddaf669ac18d39fb9b4a527ff91d5b15d5af946 Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sun, 31 Mar 2019 11:11:21 +0200 Subject: [PATCH 23/28] nalgebra-lapack: reuse openblas by default. --- nalgebra-lapack/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nalgebra-lapack/Cargo.toml b/nalgebra-lapack/Cargo.toml index e3b34cd1..3d8a24d8 100644 --- a/nalgebra-lapack/Cargo.toml +++ b/nalgebra-lapack/Cargo.toml @@ -16,7 +16,7 @@ edition = "2018" serde-serialize = [ "serde", "serde_derive" ] # For BLAS/LAPACK -default = ["accelerate"] +default = ["openblas"] openblas = ["lapack-src/openblas"] netlib = ["lapack-src/netlib"] accelerate = ["lapack-src/accelerate"] From 55873cae37f1863b0b7573bc6808e1fc13c67462 Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sun, 31 Mar 2019 12:06:26 +0200 Subject: [PATCH 24/28] Fix compilation with no-std. --- Cargo.toml | 4 +++- src/geometry/reflection.rs | 2 -- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 424c4483..c8a974e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,7 +54,9 @@ alga = { git = "https://github.com/rustsim/alga", branch = "dev" } [dev-dependencies] serde_json = "1.0" rand_xorshift = "0.1" -criterion = "0.2" +# Newer vesrion of criterion make the compilation with no-std fail. +# This problem is partly due to https://github.com/rust-lang/cargo/issues/1796 +criterion = "=0.2.7" [workspace] members = [ "nalgebra-lapack", "nalgebra-glm" ] diff --git a/src/geometry/reflection.rs b/src/geometry/reflection.rs index b36924d2..b4658a11 100644 --- a/src/geometry/reflection.rs +++ b/src/geometry/reflection.rs @@ -87,7 +87,6 @@ impl> Reflection { S2: StorageMut, S3: StorageMut, ShapeConstraint: DimEq + AreMultipliable, - DefaultAllocator: Allocator { lhs.mul_to(&self.axis, work); @@ -109,7 +108,6 @@ impl> Reflection { S2: StorageMut, S3: StorageMut, ShapeConstraint: DimEq + AreMultipliable, - DefaultAllocator: Allocator { lhs.mul_to(&self.axis, work); From 7dbff7c3896eb9a57f38efcbea3a803ac5551ba6 Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sun, 31 Mar 2019 12:26:20 +0200 Subject: [PATCH 25/28] Continue reexporting the deprecated alga::general::Real trait. --- src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 65b827b5..6667ee5a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -161,6 +161,8 @@ use alga::linear::{EuclideanSpace, FiniteDimVectorSpace, InnerSpace, NormedSpace use num::Signed; pub use alga::general::{Id, RealField, ComplexField}; +#[allow(deprecated)] +pub use alga::general::Real; pub use num_complex::Complex; /* From 86fa4bee520060335af4729e6df31b4570ce37c4 Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sun, 31 Mar 2019 13:32:09 +0200 Subject: [PATCH 26/28] Remove the criterion dependency and add comment to re-add it to run benchmarks. We are forced to remove the dependency because of the Cargo bug https://github.com/rust-lang/cargo/issues/4866 that would break compilation for #[no-std]. In practice, this means benchmarks will not compile any more unless we manually uncomment the criterion dependency. --- Cargo.toml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c8a974e3..79d761f3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,9 +54,11 @@ alga = { git = "https://github.com/rustsim/alga", branch = "dev" } [dev-dependencies] serde_json = "1.0" rand_xorshift = "0.1" -# Newer vesrion of criterion make the compilation with no-std fail. -# This problem is partly due to https://github.com/rust-lang/cargo/issues/1796 -criterion = "=0.2.7" +### Uncomment this line before running benchmarks. +### We can't just let this uncommented because that would breack +### compilation for #[no-std] because of the terrible Cargo bug +### https://github.com/rust-lang/cargo/issues/4866 +#criterion = "0.2.10" [workspace] members = [ "nalgebra-lapack", "nalgebra-glm" ] From 18b9f8204268aecd0b02e40654a799a30af4d839 Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sun, 31 Mar 2019 13:32:26 +0200 Subject: [PATCH 27/28] Fix warnings. --- src/base/edition.rs | 2 +- src/sparse/cs_matrix_solve.rs | 9 ++++++--- tests/geometry/isometry.rs | 1 - tests/geometry/similarity.rs | 1 - 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/base/edition.rs b/src/base/edition.rs index 31489f95..5b1c16c4 100644 --- a/src/base/edition.rs +++ b/src/base/edition.rs @@ -58,7 +58,7 @@ impl> Matrix { for j in 0..ncols.value() { // FIXME: use unchecked column indexing let mut res = res.column_mut(j); - let mut src = self.column(j); + let src = self.column(j); for (destination, source) in irows.clone().enumerate() { unsafe { diff --git a/src/sparse/cs_matrix_solve.rs b/src/sparse/cs_matrix_solve.rs index 1dfd7843..14ca9f78 100644 --- a/src/sparse/cs_matrix_solve.rs +++ b/src/sparse/cs_matrix_solve.rs @@ -78,7 +78,8 @@ impl> CsMatrix { } for (i, val) in column { - b[i] -= b[j] * val; + let bj = b[j]; + b[i] -= bj * val; } } } @@ -119,7 +120,8 @@ impl> CsMatrix { if let Some(diag) = diag { for (i, val) in column { - b[j] -= val * b[i]; + let bi = b[i]; + b[j] -= val * bi; } b[j] /= diag; @@ -178,7 +180,8 @@ impl> CsMatrix { } for (i, val) in column { - workspace[i] -= workspace[j] * val; + let wj = workspace[j]; + workspace[i] -= wj * val; } } diff --git a/tests/geometry/isometry.rs b/tests/geometry/isometry.rs index cf3a4dfa..ecf29e94 100644 --- a/tests/geometry/isometry.rs +++ b/tests/geometry/isometry.rs @@ -1,7 +1,6 @@ #![cfg(feature = "arbitrary")] #![allow(non_snake_case)] -use alga::linear::{ProjectiveTransformation, Transformation}; use na::{ Isometry2, Isometry3, Point2, Point3, Rotation2, Rotation3, Translation2, Translation3, UnitComplex, UnitQuaternion, Vector2, Vector3, diff --git a/tests/geometry/similarity.rs b/tests/geometry/similarity.rs index 475af976..a5736864 100644 --- a/tests/geometry/similarity.rs +++ b/tests/geometry/similarity.rs @@ -1,7 +1,6 @@ #![cfg(feature = "arbitrary")] #![allow(non_snake_case)] -use alga::linear::{ProjectiveTransformation, Transformation}; use na::{Isometry3, Point3, Similarity3, Translation3, UnitQuaternion, Vector3}; quickcheck!( From 94a8babcdc7a0388ea73dad39ec7be240ddbf023 Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sun, 31 Mar 2019 14:34:07 +0200 Subject: [PATCH 28/28] Uncomment the fast renormalization of Rotation2. --- src/geometry/rotation_specialization.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/geometry/rotation_specialization.rs b/src/geometry/rotation_specialization.rs index 8d40a51e..973190a6 100644 --- a/src/geometry/rotation_specialization.rs +++ b/src/geometry/rotation_specialization.rs @@ -193,7 +193,6 @@ impl Rotation2 { } - /* FIXME: requires alga v0.9 to be released so that Complex implements VectorSpace. /// 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 +202,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