Replace alga by simba.
This commit is contained in:
parent
002e735c76
commit
f8cd26cfa9
13
Cargo.toml
13
Cargo.toml
|
@ -21,7 +21,7 @@ path = "src/lib.rs"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = [ "std" ]
|
default = [ "std" ]
|
||||||
std = [ "matrixmultiply", "rand/std", "rand_distr", "alga/std" ]
|
std = [ "matrixmultiply", "rand/std", "rand_distr", "simba/std" ]
|
||||||
stdweb = [ "rand/stdweb" ]
|
stdweb = [ "rand/stdweb" ]
|
||||||
arbitrary = [ "quickcheck" ]
|
arbitrary = [ "quickcheck" ]
|
||||||
serde-serialize = [ "serde", "serde_derive", "num-complex/serde" ]
|
serde-serialize = [ "serde", "serde_derive", "num-complex/serde" ]
|
||||||
|
@ -39,7 +39,8 @@ num-traits = { version = "0.2", default-features = false }
|
||||||
num-complex = { version = "0.2", default-features = false }
|
num-complex = { version = "0.2", default-features = false }
|
||||||
num-rational = { version = "0.2", default-features = false }
|
num-rational = { version = "0.2", default-features = false }
|
||||||
approx = { version = "0.3", default-features = false }
|
approx = { version = "0.3", default-features = false }
|
||||||
alga = { version = "0.9", default-features = false }
|
simba = { path = "../simba" }
|
||||||
|
#alga = { version = "0.9", default-features = false }
|
||||||
rand_distr = { version = "0.2", optional = true }
|
rand_distr = { version = "0.2", optional = true }
|
||||||
matrixmultiply = { version = "0.2", optional = true }
|
matrixmultiply = { version = "0.2", optional = true }
|
||||||
serde = { version = "1.0", optional = true }
|
serde = { version = "1.0", optional = true }
|
||||||
|
@ -50,9 +51,6 @@ quickcheck = { version = "0.9", optional = true }
|
||||||
pest = { version = "2.0", optional = true }
|
pest = { version = "2.0", optional = true }
|
||||||
pest_derive = { version = "2.0", optional = true }
|
pest_derive = { version = "2.0", optional = true }
|
||||||
|
|
||||||
#[patch.crates-io]
|
|
||||||
#alga = { git = "https://github.com/rustsim/alga", branch = "dev" }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
rand_xorshift = "0.2"
|
rand_xorshift = "0.2"
|
||||||
|
@ -61,7 +59,7 @@ rand_isaac = "0.2"
|
||||||
### We can't just let this uncommented because that would break
|
### We can't just let this uncommented because that would break
|
||||||
### compilation for #[no-std] because of the terrible Cargo bug
|
### compilation for #[no-std] because of the terrible Cargo bug
|
||||||
### https://github.com/rust-lang/cargo/issues/4866
|
### https://github.com/rust-lang/cargo/issues/4866
|
||||||
#criterion = "0.2.10"
|
criterion = "0.2.10"
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = [ "nalgebra-lapack", "nalgebra-glm" ]
|
members = [ "nalgebra-lapack", "nalgebra-glm" ]
|
||||||
|
@ -73,3 +71,6 @@ path = "benches/lib.rs"
|
||||||
|
|
||||||
[profile.bench]
|
[profile.bench]
|
||||||
lto = true
|
lto = true
|
||||||
|
|
||||||
|
#[patch.crates-io]
|
||||||
|
#alga = { path = "../alga/alga" }
|
|
@ -1,8 +1,8 @@
|
||||||
extern crate alga;
|
extern crate alga;
|
||||||
extern crate nalgebra as na;
|
extern crate nalgebra as na;
|
||||||
|
|
||||||
use alga::general::{RealField, RingCommutative};
|
|
||||||
use na::{Scalar, Vector3};
|
use na::{Scalar, Vector3};
|
||||||
|
use simba::scalar::{RealField, RingCommutative};
|
||||||
|
|
||||||
fn print_vector<N: Scalar>(m: &Vector3<N>) {
|
fn print_vector<N: Scalar>(m: &Vector3<N>) {
|
||||||
println!("{:?}", m)
|
println!("{:?}", m)
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use approx::AbsDiffEq;
|
use approx::AbsDiffEq;
|
||||||
use num::{Bounded, FromPrimitive, Signed};
|
use num::{Bounded, FromPrimitive, Signed};
|
||||||
|
|
||||||
use alga::general::{Lattice, Ring};
|
|
||||||
use na::allocator::Allocator;
|
use na::allocator::Allocator;
|
||||||
use na::{DimMin, DimName, Scalar, U1};
|
use na::{DimMin, DimName, Scalar, U1};
|
||||||
|
use simba::scalar::{Lattice, Ring};
|
||||||
|
|
||||||
/// A type-level number representing a vector, matrix row, or matrix column, dimension.
|
/// A type-level number representing a vector, matrix row, or matrix column, dimension.
|
||||||
pub trait Dimension: DimName + DimMin<Self, Output = Self> {}
|
pub trait Dimension: DimName + DimMin<Self, Output = Self> {}
|
||||||
|
@ -15,9 +15,18 @@ pub trait Number:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Scalar + Copy + Ring + Lattice + AbsDiffEq<Epsilon = Self> + Signed + FromPrimitive + Bounded>
|
impl<
|
||||||
Number for T
|
T: Scalar
|
||||||
{}
|
+ Copy
|
||||||
|
+ Ring
|
||||||
|
+ Lattice
|
||||||
|
+ AbsDiffEq<Epsilon = Self>
|
||||||
|
+ Signed
|
||||||
|
+ FromPrimitive
|
||||||
|
+ Bounded,
|
||||||
|
> Number for T
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub trait Alloc<N: Scalar, R: Dimension, C: Dimension = U1>:
|
pub trait Alloc<N: Scalar, R: Dimension, C: Dimension = U1>:
|
||||||
|
@ -76,4 +85,5 @@ impl<N: Scalar, R: Dimension, C: Dimension, T> Alloc<N, R, C> for T where T: All
|
||||||
+ Allocator<i16, C>
|
+ Allocator<i16, C>
|
||||||
+ Allocator<(usize, usize), R>
|
+ Allocator<(usize, usize), R>
|
||||||
+ Allocator<(usize, usize), C>
|
+ Allocator<(usize, usize), C>
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
|
@ -4,13 +4,13 @@ use serde::{Deserialize, Serialize};
|
||||||
use num::Zero;
|
use num::Zero;
|
||||||
use num_complex::Complex;
|
use num_complex::Complex;
|
||||||
|
|
||||||
use alga::general::RealField;
|
use simba::scalar::RealField;
|
||||||
|
|
||||||
|
use crate::ComplexHelper;
|
||||||
use na::allocator::Allocator;
|
use na::allocator::Allocator;
|
||||||
use na::dimension::{Dim, U1};
|
use na::dimension::{Dim, U1};
|
||||||
use na::storage::Storage;
|
use na::storage::Storage;
|
||||||
use na::{DefaultAllocator, Matrix, MatrixN, Scalar, VectorN};
|
use na::{DefaultAllocator, Matrix, MatrixN, Scalar, VectorN};
|
||||||
use crate::ComplexHelper;
|
|
||||||
|
|
||||||
use lapack;
|
use lapack;
|
||||||
|
|
||||||
|
@ -18,19 +18,19 @@ use lapack;
|
||||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serde-serialize",
|
feature = "serde-serialize",
|
||||||
serde(bound(
|
serde(
|
||||||
serialize = "DefaultAllocator: Allocator<N, D, D> + Allocator<N, D>,
|
bound(serialize = "DefaultAllocator: Allocator<N, D, D> + Allocator<N, D>,
|
||||||
VectorN<N, D>: Serialize,
|
VectorN<N, D>: Serialize,
|
||||||
MatrixN<N, D>: Serialize"
|
MatrixN<N, D>: Serialize")
|
||||||
))
|
)
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serde-serialize",
|
feature = "serde-serialize",
|
||||||
serde(bound(
|
serde(
|
||||||
deserialize = "DefaultAllocator: Allocator<N, D, D> + Allocator<N, D>,
|
bound(deserialize = "DefaultAllocator: Allocator<N, D, D> + Allocator<N, D>,
|
||||||
VectorN<N, D>: Serialize,
|
VectorN<N, D>: Serialize,
|
||||||
MatrixN<N, D>: Deserialize<'de>"
|
MatrixN<N, D>: Deserialize<'de>")
|
||||||
))
|
)
|
||||||
)]
|
)]
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Eigen<N: Scalar, D: Dim>
|
pub struct Eigen<N: Scalar, D: Dim>
|
||||||
|
@ -49,7 +49,8 @@ where
|
||||||
DefaultAllocator: Allocator<N, D> + Allocator<N, D, D>,
|
DefaultAllocator: Allocator<N, D> + Allocator<N, D, D>,
|
||||||
VectorN<N, D>: Copy,
|
VectorN<N, D>: Copy,
|
||||||
MatrixN<N, D>: Copy,
|
MatrixN<N, D>: Copy,
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
impl<N: EigenScalar + RealField, D: Dim> Eigen<N, D>
|
impl<N: EigenScalar + RealField, D: Dim> Eigen<N, D>
|
||||||
where DefaultAllocator: Allocator<N, D, D> + Allocator<N, D>
|
where DefaultAllocator: Allocator<N, D, D> + Allocator<N, D>
|
||||||
|
|
|
@ -4,13 +4,13 @@ use serde::{Deserialize, Serialize};
|
||||||
use num::Zero;
|
use num::Zero;
|
||||||
use num_complex::Complex;
|
use num_complex::Complex;
|
||||||
|
|
||||||
use alga::general::RealField;
|
use simba::scalar::RealField;
|
||||||
|
|
||||||
|
use crate::ComplexHelper;
|
||||||
use na::allocator::Allocator;
|
use na::allocator::Allocator;
|
||||||
use na::dimension::{Dim, U1};
|
use na::dimension::{Dim, U1};
|
||||||
use na::storage::Storage;
|
use na::storage::Storage;
|
||||||
use na::{DefaultAllocator, Matrix, MatrixN, Scalar, VectorN};
|
use na::{DefaultAllocator, Matrix, MatrixN, Scalar, VectorN};
|
||||||
use crate::ComplexHelper;
|
|
||||||
|
|
||||||
use lapack;
|
use lapack;
|
||||||
|
|
||||||
|
@ -18,19 +18,19 @@ use lapack;
|
||||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serde-serialize",
|
feature = "serde-serialize",
|
||||||
serde(bound(
|
serde(
|
||||||
serialize = "DefaultAllocator: Allocator<N, D, D> + Allocator<N, D>,
|
bound(serialize = "DefaultAllocator: Allocator<N, D, D> + Allocator<N, D>,
|
||||||
VectorN<N, D>: Serialize,
|
VectorN<N, D>: Serialize,
|
||||||
MatrixN<N, D>: Serialize"
|
MatrixN<N, D>: Serialize")
|
||||||
))
|
)
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serde-serialize",
|
feature = "serde-serialize",
|
||||||
serde(bound(
|
serde(
|
||||||
deserialize = "DefaultAllocator: Allocator<N, D, D> + Allocator<N, D>,
|
bound(deserialize = "DefaultAllocator: Allocator<N, D, D> + Allocator<N, D>,
|
||||||
VectorN<N, D>: Serialize,
|
VectorN<N, D>: Serialize,
|
||||||
MatrixN<N, D>: Deserialize<'de>"
|
MatrixN<N, D>: Deserialize<'de>")
|
||||||
))
|
)
|
||||||
)]
|
)]
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Schur<N: Scalar, D: Dim>
|
pub struct Schur<N: Scalar, D: Dim>
|
||||||
|
@ -47,7 +47,8 @@ where
|
||||||
DefaultAllocator: Allocator<N, D, D> + Allocator<N, D>,
|
DefaultAllocator: Allocator<N, D, D> + Allocator<N, D>,
|
||||||
MatrixN<N, D>: Copy,
|
MatrixN<N, D>: Copy,
|
||||||
VectorN<N, D>: Copy,
|
VectorN<N, D>: Copy,
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
impl<N: SchurScalar + RealField, D: Dim> Schur<N, D>
|
impl<N: SchurScalar + RealField, D: Dim> Schur<N, D>
|
||||||
where DefaultAllocator: Allocator<N, D, D> + Allocator<N, D>
|
where DefaultAllocator: Allocator<N, D, D> + Allocator<N, D>
|
||||||
|
|
|
@ -4,13 +4,13 @@ use serde::{Deserialize, Serialize};
|
||||||
use num::Zero;
|
use num::Zero;
|
||||||
use std::ops::MulAssign;
|
use std::ops::MulAssign;
|
||||||
|
|
||||||
use alga::general::RealField;
|
use simba::scalar::RealField;
|
||||||
|
|
||||||
|
use crate::ComplexHelper;
|
||||||
use na::allocator::Allocator;
|
use na::allocator::Allocator;
|
||||||
use na::dimension::{Dim, U1};
|
use na::dimension::{Dim, U1};
|
||||||
use na::storage::Storage;
|
use na::storage::Storage;
|
||||||
use na::{DefaultAllocator, Matrix, MatrixN, Scalar, VectorN};
|
use na::{DefaultAllocator, Matrix, MatrixN, Scalar, VectorN};
|
||||||
use crate::ComplexHelper;
|
|
||||||
|
|
||||||
use lapack;
|
use lapack;
|
||||||
|
|
||||||
|
@ -18,21 +18,17 @@ use lapack;
|
||||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serde-serialize",
|
feature = "serde-serialize",
|
||||||
serde(bound(
|
serde(bound(serialize = "DefaultAllocator: Allocator<N, D, D> +
|
||||||
serialize = "DefaultAllocator: Allocator<N, D, D> +
|
|
||||||
Allocator<N, D>,
|
Allocator<N, D>,
|
||||||
VectorN<N, D>: Serialize,
|
VectorN<N, D>: Serialize,
|
||||||
MatrixN<N, D>: Serialize"
|
MatrixN<N, D>: Serialize"))
|
||||||
))
|
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serde-serialize",
|
feature = "serde-serialize",
|
||||||
serde(bound(
|
serde(bound(deserialize = "DefaultAllocator: Allocator<N, D, D> +
|
||||||
deserialize = "DefaultAllocator: Allocator<N, D, D> +
|
|
||||||
Allocator<N, D>,
|
Allocator<N, D>,
|
||||||
VectorN<N, D>: Deserialize<'de>,
|
VectorN<N, D>: Deserialize<'de>,
|
||||||
MatrixN<N, D>: Deserialize<'de>"
|
MatrixN<N, D>: Deserialize<'de>"))
|
||||||
))
|
|
||||||
)]
|
)]
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct SymmetricEigen<N: Scalar, D: Dim>
|
pub struct SymmetricEigen<N: Scalar, D: Dim>
|
||||||
|
@ -50,7 +46,8 @@ where
|
||||||
DefaultAllocator: Allocator<N, D, D> + Allocator<N, D>,
|
DefaultAllocator: Allocator<N, D, D> + Allocator<N, D>,
|
||||||
MatrixN<N, D>: Copy,
|
MatrixN<N, D>: Copy,
|
||||||
VectorN<N, D>: Copy,
|
VectorN<N, D>: Copy,
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
impl<N: SymmetricEigenScalar + RealField, D: Dim> SymmetricEigen<N, D>
|
impl<N: SymmetricEigenScalar + RealField, D: Dim> SymmetricEigen<N, D>
|
||||||
where DefaultAllocator: Allocator<N, D, D> + Allocator<N, D>
|
where DefaultAllocator: Allocator<N, D, D> + Allocator<N, D>
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use crate::SimdComplexField;
|
use crate::SimdComplexField;
|
||||||
use alga::general::{ClosedAdd, ClosedMul, ComplexField};
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use matrixmultiply;
|
use matrixmultiply;
|
||||||
use num::{One, Signed, Zero};
|
use num::{One, Signed, Zero};
|
||||||
|
use simba::scalar::{ClosedAdd, ClosedMul, ComplexField};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use num::One;
|
use num::{One, Zero};
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::dimension::{DimName, DimNameDiff, DimNameSub, U1};
|
use crate::base::dimension::{DimName, DimNameDiff, DimNameSub, U1};
|
||||||
|
@ -18,12 +18,11 @@ use crate::geometry::{
|
||||||
Isometry, IsometryMatrix3, Orthographic3, Perspective3, Point, Point3, Rotation2, Rotation3,
|
Isometry, IsometryMatrix3, Orthographic3, Perspective3, Point, Point3, Rotation2, Rotation3,
|
||||||
};
|
};
|
||||||
|
|
||||||
use alga::general::{RealField, Ring};
|
use simba::scalar::{ClosedAdd, ClosedMul, RealField};
|
||||||
use alga::linear::Transformation;
|
|
||||||
|
|
||||||
impl<N, D: DimName> MatrixN<N, D>
|
impl<N, D: DimName> MatrixN<N, D>
|
||||||
where
|
where
|
||||||
N: Scalar + Ring,
|
N: Scalar + Zero + One,
|
||||||
DefaultAllocator: Allocator<N, D, D>,
|
DefaultAllocator: Allocator<N, D, D>,
|
||||||
{
|
{
|
||||||
/// Creates a new homogeneous matrix that applies the same scaling factor on each dimension.
|
/// Creates a new homogeneous matrix that applies the same scaling factor on each dimension.
|
||||||
|
@ -42,7 +41,7 @@ where
|
||||||
D: DimNameSub<U1>,
|
D: DimNameSub<U1>,
|
||||||
SB: Storage<N, DimNameDiff<D, U1>>,
|
SB: Storage<N, DimNameDiff<D, U1>>,
|
||||||
{
|
{
|
||||||
let mut res = Self::one();
|
let mut res = Self::identity();
|
||||||
for i in 0..scaling.len() {
|
for i in 0..scaling.len() {
|
||||||
res[(i, i)] = scaling[i].inlined_clone();
|
res[(i, i)] = scaling[i].inlined_clone();
|
||||||
}
|
}
|
||||||
|
@ -57,7 +56,7 @@ where
|
||||||
D: DimNameSub<U1>,
|
D: DimNameSub<U1>,
|
||||||
SB: Storage<N, DimNameDiff<D, U1>>,
|
SB: Storage<N, DimNameDiff<D, U1>>,
|
||||||
{
|
{
|
||||||
let mut res = Self::one();
|
let mut res = Self::identity();
|
||||||
res.fixed_slice_mut::<DimNameDiff<D, U1>, U1>(0, D::dim() - 1)
|
res.fixed_slice_mut::<DimNameDiff<D, U1>, U1>(0, D::dim() - 1)
|
||||||
.copy_from(translation);
|
.copy_from(translation);
|
||||||
|
|
||||||
|
@ -135,7 +134,7 @@ impl<N: RealField> Matrix4<N> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deprecated: Use [Matrix4::face_towards] instead.
|
/// Deprecated: Use [Matrix4::face_towards] instead.
|
||||||
#[deprecated(note="renamed to `face_towards`")]
|
#[deprecated(note = "renamed to `face_towards`")]
|
||||||
pub fn new_observer_frame(eye: &Point3<N>, target: &Point3<N>, up: &Vector3<N>) -> Self {
|
pub fn new_observer_frame(eye: &Point3<N>, target: &Point3<N>, up: &Vector3<N>) -> Self {
|
||||||
Matrix4::face_towards(eye, target, up)
|
Matrix4::face_towards(eye, target, up)
|
||||||
}
|
}
|
||||||
|
@ -153,7 +152,9 @@ impl<N: RealField> Matrix4<N> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: Scalar + Ring, D: DimName, S: Storage<N, D, D>> SquareMatrix<N, D, S> {
|
impl<N: Scalar + Zero + One + ClosedMul + ClosedAdd, D: DimName, S: Storage<N, D, D>>
|
||||||
|
SquareMatrix<N, D, S>
|
||||||
|
{
|
||||||
/// Computes the transformation equal to `self` followed by an uniform scaling factor.
|
/// Computes the transformation equal to `self` followed by an uniform scaling factor.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[must_use = "Did you mean to use append_scaling_mut()?"]
|
#[must_use = "Did you mean to use append_scaling_mut()?"]
|
||||||
|
@ -246,7 +247,9 @@ impl<N: Scalar + Ring, D: DimName, S: Storage<N, D, D>> SquareMatrix<N, D, S> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: Scalar + Ring, D: DimName, S: StorageMut<N, D, D>> SquareMatrix<N, D, S> {
|
impl<N: Scalar + Zero + One + ClosedMul + ClosedAdd, D: DimName, S: StorageMut<N, D, D>>
|
||||||
|
SquareMatrix<N, D, S>
|
||||||
|
{
|
||||||
/// Computes in-place the transformation equal to `self` followed by an uniform scaling factor.
|
/// Computes in-place the transformation equal to `self` followed by an uniform scaling factor.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn append_scaling_mut(&mut self, scaling: N)
|
pub fn append_scaling_mut(&mut self, scaling: N)
|
||||||
|
@ -370,23 +373,3 @@ where DefaultAllocator: Allocator<N, D, D>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: RealField, D: DimNameSub<U1>> Transformation<Point<N, DimNameDiff<D, U1>>> for MatrixN<N, D>
|
|
||||||
where DefaultAllocator: Allocator<N, D, D>
|
|
||||||
+ Allocator<N, DimNameDiff<D, U1>>
|
|
||||||
+ Allocator<N, DimNameDiff<D, U1>, DimNameDiff<D, U1>>
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn transform_vector(
|
|
||||||
&self,
|
|
||||||
v: &VectorN<N, DimNameDiff<D, U1>>,
|
|
||||||
) -> VectorN<N, DimNameDiff<D, U1>>
|
|
||||||
{
|
|
||||||
self.transform_vector(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn transform_point(&self, pt: &Point<N, DimNameDiff<D, U1>>) -> Point<N, DimNameDiff<D, U1>> {
|
|
||||||
self.transform_point(pt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
use num::{Signed, Zero};
|
use num::{Signed, Zero};
|
||||||
use std::ops::{Add, Mul};
|
use std::ops::{Add, Mul};
|
||||||
|
|
||||||
use alga::general::{ClosedDiv, ClosedMul};
|
use simba::scalar::{ClosedDiv, ClosedMul};
|
||||||
|
|
||||||
use crate::base::allocator::{Allocator, SameShapeAllocator};
|
use crate::base::allocator::{Allocator, SameShapeAllocator};
|
||||||
use crate::base::constraint::{SameNumberOfColumns, SameNumberOfRows, ShapeConstraint};
|
use crate::base::constraint::{SameNumberOfColumns, SameNumberOfRows, ShapeConstraint};
|
||||||
|
|
|
@ -4,18 +4,18 @@ use crate::base::storage::Owned;
|
||||||
use quickcheck::{Arbitrary, Gen};
|
use quickcheck::{Arbitrary, Gen};
|
||||||
|
|
||||||
use num::{Bounded, One, Zero};
|
use num::{Bounded, One, Zero};
|
||||||
use rand::distributions::{Distribution, Standard};
|
|
||||||
use rand::Rng;
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use rand;
|
use rand;
|
||||||
|
use rand::distributions::{Distribution, Standard};
|
||||||
|
use rand::Rng;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use rand_distr::StandardNormal;
|
use rand_distr::StandardNormal;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use typenum::{self, Cmp, Greater};
|
use typenum::{self, Cmp, Greater};
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use alga::general::RealField;
|
use simba::scalar::RealField;
|
||||||
use alga::general::{ClosedAdd, ClosedMul};
|
use simba::scalar::{ClosedAdd, ClosedMul};
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::dimension::{Dim, DimName, Dynamic, U1, U2, U3, U4, U5, U6};
|
use crate::base::dimension::{Dim, DimName, Dynamic, U1, U2, U3, U4, U5, U6};
|
||||||
|
@ -576,9 +576,9 @@ macro_rules! impl_constructors(
|
||||||
|
|
||||||
// FIXME: this is not very pretty. We could find a better call syntax.
|
// FIXME: this is not very pretty. We could find a better call syntax.
|
||||||
impl_constructors!(R, C; // Arguments for Matrix<N, ..., S>
|
impl_constructors!(R, C; // Arguments for Matrix<N, ..., S>
|
||||||
=> R: DimName, => C: DimName; // Type parameters for impl<N, ..., S>
|
=> R: DimName, => C: DimName; // Type parameters for impl<N, ..., S>
|
||||||
R::name(), C::name(); // Arguments for `_generic` constructors.
|
R::name(), C::name(); // Arguments for `_generic` constructors.
|
||||||
); // Arguments for non-generic constructors.
|
); // Arguments for non-generic constructors.
|
||||||
|
|
||||||
impl_constructors!(R, Dynamic;
|
impl_constructors!(R, Dynamic;
|
||||||
=> R: DimName;
|
=> R: DimName;
|
||||||
|
@ -693,27 +693,25 @@ macro_rules! impl_constructors_from_data(
|
||||||
|
|
||||||
// FIXME: this is not very pretty. We could find a better call syntax.
|
// FIXME: this is not very pretty. We could find a better call syntax.
|
||||||
impl_constructors_from_data!(data; R, C; // Arguments for Matrix<N, ..., S>
|
impl_constructors_from_data!(data; R, C; // Arguments for Matrix<N, ..., S>
|
||||||
=> R: DimName, => C: DimName; // Type parameters for impl<N, ..., S>
|
=> R: DimName, => C: DimName; // Type parameters for impl<N, ..., S>
|
||||||
R::name(), C::name(); // Arguments for `_generic` constructors.
|
R::name(), C::name(); // Arguments for `_generic` constructors.
|
||||||
); // Arguments for non-generic constructors.
|
); // Arguments for non-generic constructors.
|
||||||
|
|
||||||
impl_constructors_from_data!(data; R, Dynamic;
|
impl_constructors_from_data!(data; R, Dynamic;
|
||||||
=> R: DimName;
|
=> R: DimName;
|
||||||
R::name(), Dynamic::new(data.len() / R::dim());
|
R::name(), Dynamic::new(data.len() / R::dim());
|
||||||
);
|
);
|
||||||
|
|
||||||
impl_constructors_from_data!(data; Dynamic, C;
|
impl_constructors_from_data!(data; Dynamic, C;
|
||||||
=> C: DimName;
|
=> C: DimName;
|
||||||
Dynamic::new(data.len() / C::dim()), C::name();
|
Dynamic::new(data.len() / C::dim()), C::name();
|
||||||
);
|
);
|
||||||
|
|
||||||
impl_constructors_from_data!(data; Dynamic, Dynamic;
|
impl_constructors_from_data!(data; Dynamic, Dynamic;
|
||||||
;
|
;
|
||||||
Dynamic::new(nrows), Dynamic::new(ncols);
|
Dynamic::new(nrows), Dynamic::new(ncols);
|
||||||
nrows, ncols);
|
nrows, ncols);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Zero, One, Rand traits.
|
* Zero, One, Rand traits.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use alga::general::{SubsetOf, SupersetOf};
|
|
||||||
#[cfg(feature = "mint")]
|
#[cfg(feature = "mint")]
|
||||||
use mint;
|
use mint;
|
||||||
|
use simba::scalar::{SubsetOf, SupersetOf};
|
||||||
use std::convert::{AsMut, AsRef, From, Into};
|
use std::convert::{AsMut, AsRef, From, Into};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
@ -11,17 +11,20 @@ use typenum::Prod;
|
||||||
|
|
||||||
use crate::base::allocator::{Allocator, SameShapeAllocator};
|
use crate::base::allocator::{Allocator, SameShapeAllocator};
|
||||||
use crate::base::constraint::{SameNumberOfColumns, SameNumberOfRows, ShapeConstraint};
|
use crate::base::constraint::{SameNumberOfColumns, SameNumberOfRows, ShapeConstraint};
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
use crate::base::dimension::Dynamic;
|
||||||
use crate::base::dimension::{
|
use crate::base::dimension::{
|
||||||
Dim, DimName, U1, U10, U11, U12, U13, U14, U15, U16, U2, U3, U4, U5, U6, U7, U8, U9,
|
Dim, DimName, U1, U10, U11, U12, U13, U14, U15, U16, U2, U3, U4, U5, U6, U7, U8, U9,
|
||||||
};
|
};
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
|
||||||
use crate::base::dimension::Dynamic;
|
|
||||||
use crate::base::iter::{MatrixIter, MatrixIterMut};
|
use crate::base::iter::{MatrixIter, MatrixIterMut};
|
||||||
use crate::base::storage::{ContiguousStorage, ContiguousStorageMut, Storage, StorageMut};
|
use crate::base::storage::{ContiguousStorage, ContiguousStorageMut, Storage, StorageMut};
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
use crate::base::VecStorage;
|
use crate::base::VecStorage;
|
||||||
|
use crate::base::{
|
||||||
|
ArrayStorage, DVectorSlice, DVectorSliceMut, DefaultAllocator, Matrix, MatrixMN, MatrixSlice,
|
||||||
|
MatrixSliceMut, Scalar,
|
||||||
|
};
|
||||||
use crate::base::{SliceStorage, SliceStorageMut};
|
use crate::base::{SliceStorage, SliceStorageMut};
|
||||||
use crate::base::{DefaultAllocator, Matrix, ArrayStorage, MatrixMN, MatrixSlice, MatrixSliceMut, Scalar, DVectorSlice, DVectorSliceMut};
|
|
||||||
use crate::constraint::DimEq;
|
use crate::constraint::DimEq;
|
||||||
|
|
||||||
// FIXME: too bad this won't work allo slice conversions.
|
// FIXME: too bad this won't work allo slice conversions.
|
||||||
|
@ -46,7 +49,9 @@ where
|
||||||
let mut res = unsafe { MatrixMN::<N2, R2, C2>::new_uninitialized_generic(nrows2, ncols2) };
|
let mut res = unsafe { MatrixMN::<N2, R2, C2>::new_uninitialized_generic(nrows2, ncols2) };
|
||||||
for i in 0..nrows {
|
for i in 0..nrows {
|
||||||
for j in 0..ncols {
|
for j in 0..ncols {
|
||||||
unsafe { *res.get_unchecked_mut((i, j)) = N2::from_subset(self.get_unchecked((i, j))) }
|
unsafe {
|
||||||
|
*res.get_unchecked_mut((i, j)) = N2::from_subset(self.get_unchecked((i, j)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,15 +64,17 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(m: &MatrixMN<N2, R2, C2>) -> Self {
|
fn from_superset_unchecked(m: &MatrixMN<N2, R2, C2>) -> Self {
|
||||||
let (nrows2, ncols2) = m.shape();
|
let (nrows2, ncols2) = m.shape();
|
||||||
let nrows = R1::from_usize(nrows2);
|
let nrows = R1::from_usize(nrows2);
|
||||||
let ncols = C1::from_usize(ncols2);
|
let ncols = C1::from_usize(ncols2);
|
||||||
|
|
||||||
let mut res = Self::new_uninitialized_generic(nrows, ncols);
|
let mut res = unsafe { Self::new_uninitialized_generic(nrows, ncols) };
|
||||||
for i in 0..nrows2 {
|
for i in 0..nrows2 {
|
||||||
for j in 0..ncols2 {
|
for j in 0..ncols2 {
|
||||||
*res.get_unchecked_mut((i, j)) = m.get_unchecked((i, j)).to_subset_unchecked()
|
unsafe {
|
||||||
|
*res.get_unchecked_mut((i, j)) = m.get_unchecked((i, j)).to_subset_unchecked()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,18 +435,20 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, N, R, C, RSlice, CSlice, RStride, CStride, S> From<&'a Matrix<N, R, C, S>>
|
impl<'a, N, R, C, RSlice, CSlice, RStride, CStride, S> From<&'a Matrix<N, R, C, S>>
|
||||||
for MatrixSlice<'a, N, RSlice, CSlice, RStride, CStride>
|
for MatrixSlice<'a, N, RSlice, CSlice, RStride, CStride>
|
||||||
where
|
where
|
||||||
N: Scalar,
|
N: Scalar,
|
||||||
R: Dim,
|
R: Dim,
|
||||||
C: Dim,
|
C: Dim,
|
||||||
RSlice: Dim,
|
RSlice: Dim,
|
||||||
CSlice: Dim,
|
CSlice: Dim,
|
||||||
RStride: Dim,
|
RStride: Dim,
|
||||||
CStride: Dim,
|
CStride: Dim,
|
||||||
S: Storage<N, R, C>,
|
S: Storage<N, R, C>,
|
||||||
ShapeConstraint: DimEq<R, RSlice> + DimEq<C, CSlice>
|
ShapeConstraint: DimEq<R, RSlice>
|
||||||
+ DimEq<RStride, S::RStride> + DimEq<CStride, S::CStride>
|
+ DimEq<C, CSlice>
|
||||||
|
+ DimEq<RStride, S::RStride>
|
||||||
|
+ DimEq<CStride, S::CStride>,
|
||||||
{
|
{
|
||||||
fn from(m: &'a Matrix<N, R, C, S>) -> Self {
|
fn from(m: &'a Matrix<N, R, C, S>) -> Self {
|
||||||
let (row, col) = m.data.shape();
|
let (row, col) = m.data.shape();
|
||||||
|
@ -452,27 +461,31 @@ for MatrixSlice<'a, N, RSlice, CSlice, RStride, CStride>
|
||||||
let cstride_slice = CStride::from_usize(cstride);
|
let cstride_slice = CStride::from_usize(cstride);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let data = SliceStorage::from_raw_parts(m.data.ptr(),
|
let data = SliceStorage::from_raw_parts(
|
||||||
(row_slice, col_slice),
|
m.data.ptr(),
|
||||||
(rstride_slice, cstride_slice));
|
(row_slice, col_slice),
|
||||||
|
(rstride_slice, cstride_slice),
|
||||||
|
);
|
||||||
Matrix::from_data_statically_unchecked(data)
|
Matrix::from_data_statically_unchecked(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, N, R, C, RSlice, CSlice, RStride, CStride, S> From<&'a mut Matrix<N, R, C, S>>
|
impl<'a, N, R, C, RSlice, CSlice, RStride, CStride, S> From<&'a mut Matrix<N, R, C, S>>
|
||||||
for MatrixSlice<'a, N, RSlice, CSlice, RStride, CStride>
|
for MatrixSlice<'a, N, RSlice, CSlice, RStride, CStride>
|
||||||
where
|
where
|
||||||
N: Scalar,
|
N: Scalar,
|
||||||
R: Dim,
|
R: Dim,
|
||||||
C: Dim,
|
C: Dim,
|
||||||
RSlice: Dim,
|
RSlice: Dim,
|
||||||
CSlice: Dim,
|
CSlice: Dim,
|
||||||
RStride: Dim,
|
RStride: Dim,
|
||||||
CStride: Dim,
|
CStride: Dim,
|
||||||
S: Storage<N, R, C>,
|
S: Storage<N, R, C>,
|
||||||
ShapeConstraint: DimEq<R, RSlice> + DimEq<C, CSlice>
|
ShapeConstraint: DimEq<R, RSlice>
|
||||||
+ DimEq<RStride, S::RStride> + DimEq<CStride, S::CStride>
|
+ DimEq<C, CSlice>
|
||||||
|
+ DimEq<RStride, S::RStride>
|
||||||
|
+ DimEq<CStride, S::CStride>,
|
||||||
{
|
{
|
||||||
fn from(m: &'a mut Matrix<N, R, C, S>) -> Self {
|
fn from(m: &'a mut Matrix<N, R, C, S>) -> Self {
|
||||||
let (row, col) = m.data.shape();
|
let (row, col) = m.data.shape();
|
||||||
|
@ -485,27 +498,31 @@ for MatrixSlice<'a, N, RSlice, CSlice, RStride, CStride>
|
||||||
let cstride_slice = CStride::from_usize(cstride);
|
let cstride_slice = CStride::from_usize(cstride);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let data = SliceStorage::from_raw_parts(m.data.ptr(),
|
let data = SliceStorage::from_raw_parts(
|
||||||
(row_slice, col_slice),
|
m.data.ptr(),
|
||||||
(rstride_slice, cstride_slice));
|
(row_slice, col_slice),
|
||||||
|
(rstride_slice, cstride_slice),
|
||||||
|
);
|
||||||
Matrix::from_data_statically_unchecked(data)
|
Matrix::from_data_statically_unchecked(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, N, R, C, RSlice, CSlice, RStride, CStride, S> From<&'a mut Matrix<N, R, C, S>>
|
impl<'a, N, R, C, RSlice, CSlice, RStride, CStride, S> From<&'a mut Matrix<N, R, C, S>>
|
||||||
for MatrixSliceMut<'a, N, RSlice, CSlice, RStride, CStride>
|
for MatrixSliceMut<'a, N, RSlice, CSlice, RStride, CStride>
|
||||||
where
|
where
|
||||||
N: Scalar,
|
N: Scalar,
|
||||||
R: Dim,
|
R: Dim,
|
||||||
C: Dim,
|
C: Dim,
|
||||||
RSlice: Dim,
|
RSlice: Dim,
|
||||||
CSlice: Dim,
|
CSlice: Dim,
|
||||||
RStride: Dim,
|
RStride: Dim,
|
||||||
CStride: Dim,
|
CStride: Dim,
|
||||||
S: StorageMut<N, R, C>,
|
S: StorageMut<N, R, C>,
|
||||||
ShapeConstraint: DimEq<R, RSlice> + DimEq<C, CSlice>
|
ShapeConstraint: DimEq<R, RSlice>
|
||||||
+ DimEq<RStride, S::RStride> + DimEq<CStride, S::CStride>
|
+ DimEq<C, CSlice>
|
||||||
|
+ DimEq<RStride, S::RStride>
|
||||||
|
+ DimEq<CStride, S::CStride>,
|
||||||
{
|
{
|
||||||
fn from(m: &'a mut Matrix<N, R, C, S>) -> Self {
|
fn from(m: &'a mut Matrix<N, R, C, S>) -> Self {
|
||||||
let (row, col) = m.data.shape();
|
let (row, col) = m.data.shape();
|
||||||
|
@ -518,29 +535,34 @@ for MatrixSliceMut<'a, N, RSlice, CSlice, RStride, CStride>
|
||||||
let cstride_slice = CStride::from_usize(cstride);
|
let cstride_slice = CStride::from_usize(cstride);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let data = SliceStorageMut::from_raw_parts(m.data.ptr_mut(),
|
let data = SliceStorageMut::from_raw_parts(
|
||||||
(row_slice, col_slice),
|
m.data.ptr_mut(),
|
||||||
(rstride_slice, cstride_slice));
|
(row_slice, col_slice),
|
||||||
|
(rstride_slice, cstride_slice),
|
||||||
|
);
|
||||||
Matrix::from_data_statically_unchecked(data)
|
Matrix::from_data_statically_unchecked(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, N: Scalar + Copy, R: Dim, C: Dim, S: ContiguousStorage<N, R, C>> Into<&'a [N]> for &'a Matrix<N, R, C, S> {
|
impl<'a, N: Scalar + Copy, R: Dim, C: Dim, S: ContiguousStorage<N, R, C>> Into<&'a [N]>
|
||||||
|
for &'a Matrix<N, R, C, S>
|
||||||
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into(self) -> &'a [N] {
|
fn into(self) -> &'a [N] {
|
||||||
self.as_slice()
|
self.as_slice()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, N: Scalar + Copy, R: Dim, C: Dim, S: ContiguousStorageMut<N, R, C>> Into<&'a mut [N]> for &'a mut Matrix<N, R, C, S> {
|
impl<'a, N: Scalar + Copy, R: Dim, C: Dim, S: ContiguousStorageMut<N, R, C>> Into<&'a mut [N]>
|
||||||
|
for &'a mut Matrix<N, R, C, S>
|
||||||
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into(self) -> &'a mut [N] {
|
fn into(self) -> &'a mut [N] {
|
||||||
self.as_mut_slice()
|
self.as_mut_slice()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl<'a, N: Scalar + Copy> From<&'a [N]> for DVectorSlice<'a, N> {
|
impl<'a, N: Scalar + Copy> From<&'a [N]> for DVectorSlice<'a, N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(slice: &'a [N]) -> Self {
|
fn from(slice: &'a [N]) -> Self {
|
||||||
|
@ -553,4 +575,4 @@ impl<'a, N: Scalar + Copy> From<&'a mut [N]> for DVectorSliceMut<'a, N> {
|
||||||
fn from(slice: &'a mut [N]) -> Self {
|
fn from(slice: &'a mut [N]) -> Self {
|
||||||
Self::from_slice(slice, slice.len())
|
Self::from_slice(slice, slice.len())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -190,7 +190,6 @@ pub trait DimName: Dim {
|
||||||
type Value: NamedDim<Name = Self>;
|
type Value: NamedDim<Name = Self>;
|
||||||
|
|
||||||
/// The name of this dimension, i.e., the singleton `Self`.
|
/// The name of this dimension, i.e., the singleton `Self`.
|
||||||
#[inline]
|
|
||||||
fn name() -> Self;
|
fn name() -> Self;
|
||||||
|
|
||||||
// FIXME: this is not a very idiomatic name.
|
// FIXME: this is not a very idiomatic name.
|
||||||
|
|
|
@ -16,8 +16,8 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||||
#[cfg(feature = "abomonation-serialize")]
|
#[cfg(feature = "abomonation-serialize")]
|
||||||
use abomonation::Abomonation;
|
use abomonation::Abomonation;
|
||||||
|
|
||||||
use alga::general::{ClosedAdd, ClosedMul, ClosedSub, Field, RealField, Ring};
|
use simba::scalar::{ClosedAdd, ClosedMul, ClosedSub, Field, RealField};
|
||||||
use alga::simd::SimdPartialOrd;
|
use simba::simd::SimdPartialOrd;
|
||||||
|
|
||||||
use crate::base::allocator::{Allocator, SameShapeAllocator, SameShapeC, SameShapeR};
|
use crate::base::allocator::{Allocator, SameShapeAllocator, SameShapeC, SameShapeR};
|
||||||
use crate::base::constraint::{DimEq, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint};
|
use crate::base::constraint::{DimEq, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint};
|
||||||
|
@ -29,7 +29,7 @@ use crate::base::storage::{
|
||||||
ContiguousStorage, ContiguousStorageMut, Owned, SameShapeStorage, Storage, StorageMut,
|
ContiguousStorage, ContiguousStorageMut, Owned, SameShapeStorage, Storage, StorageMut,
|
||||||
};
|
};
|
||||||
use crate::base::{DefaultAllocator, MatrixMN, MatrixN, Scalar, Unit, VectorN};
|
use crate::base::{DefaultAllocator, MatrixMN, MatrixN, Scalar, Unit, VectorN};
|
||||||
use crate::{SimdComplexField, SimdRealField};
|
use crate::SimdComplexField;
|
||||||
|
|
||||||
/// A square matrix.
|
/// A square matrix.
|
||||||
pub type SquareMatrix<N, D, S> = Matrix<N, D, D, S>;
|
pub type SquareMatrix<N, D, S> = Matrix<N, D, D, S>;
|
||||||
|
@ -1130,7 +1130,7 @@ impl<N: Scalar, D: Dim, S: Storage<N, D, D>> SquareMatrix<N, D, S> {
|
||||||
/// Computes a trace of a square matrix, i.e., the sum of its diagonal elements.
|
/// Computes a trace of a square matrix, i.e., the sum of its diagonal elements.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn trace(&self) -> N
|
pub fn trace(&self) -> N
|
||||||
where N: Ring {
|
where N: Scalar + Zero + ClosedAdd {
|
||||||
assert!(
|
assert!(
|
||||||
self.is_square(),
|
self.is_square(),
|
||||||
"Cannot compute the trace of non-square matrix."
|
"Cannot compute the trace of non-square matrix."
|
||||||
|
@ -1517,7 +1517,9 @@ fn lower_exp() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: Scalar + Ring, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
|
impl<N: Scalar + ClosedAdd + ClosedSub + ClosedMul, R: Dim, C: Dim, S: Storage<N, R, C>>
|
||||||
|
Matrix<N, R, C, S>
|
||||||
|
{
|
||||||
/// The perpendicular product between two 2D column vectors, i.e. `a.x * b.y - a.y * b.x`.
|
/// The perpendicular product between two 2D column vectors, i.e. `a.x * b.y - a.y * b.x`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn perp<R2, C2, SB>(&self, b: &Matrix<N, R2, C2, SB>) -> N
|
pub fn perp<R2, C2, SB>(&self, b: &Matrix<N, R2, C2, SB>) -> N
|
||||||
|
|
|
@ -1,424 +0,0 @@
|
||||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
|
||||||
use alloc::vec::Vec;
|
|
||||||
|
|
||||||
use num::{One, Zero};
|
|
||||||
|
|
||||||
use alga::general::{
|
|
||||||
AbstractGroup, AbstractGroupAbelian, AbstractLoop, AbstractMagma, AbstractModule,
|
|
||||||
AbstractMonoid, AbstractQuasigroup, AbstractSemigroup, Additive, ClosedAdd, ClosedMul,
|
|
||||||
ClosedNeg, Field, Identity, TwoSidedInverse, JoinSemilattice, Lattice, MeetSemilattice, Module,
|
|
||||||
Multiplicative, RingCommutative, ComplexField
|
|
||||||
};
|
|
||||||
use alga::linear::{
|
|
||||||
FiniteDimInnerSpace, FiniteDimVectorSpace, InnerSpace, NormedSpace, VectorSpace,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
|
||||||
use crate::base::dimension::{Dim, DimName};
|
|
||||||
use crate::base::storage::{Storage, StorageMut};
|
|
||||||
use crate::base::{DefaultAllocator, MatrixMN, MatrixN, Scalar};
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Additive structures.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
impl<N, R: DimName, C: DimName> Identity<Additive> for MatrixMN<N, R, C>
|
|
||||||
where
|
|
||||||
N: Scalar + Zero,
|
|
||||||
DefaultAllocator: Allocator<N, R, C>,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn identity() -> Self {
|
|
||||||
Self::from_element(N::zero())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N, R: DimName, C: DimName> AbstractMagma<Additive> for MatrixMN<N, R, C>
|
|
||||||
where
|
|
||||||
N: Scalar + ClosedAdd,
|
|
||||||
DefaultAllocator: Allocator<N, R, C>,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn operate(&self, other: &Self) -> Self {
|
|
||||||
self + other
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N, R: DimName, C: DimName> TwoSidedInverse<Additive> for MatrixMN<N, R, C>
|
|
||||||
where
|
|
||||||
N: Scalar + ClosedNeg,
|
|
||||||
DefaultAllocator: Allocator<N, R, C>,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
#[must_use = "Did you mean to use two_sided_inverse_mut()?"]
|
|
||||||
fn two_sided_inverse(&self) -> Self {
|
|
||||||
-self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn two_sided_inverse_mut(&mut self) {
|
|
||||||
*self = -self.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! inherit_additive_structure(
|
|
||||||
($($marker: ident<$operator: ident> $(+ $bounds: ident)*),* $(,)*) => {$(
|
|
||||||
impl<N, R: DimName, C: DimName> $marker<$operator> for MatrixMN<N, R, C>
|
|
||||||
where N: Scalar + $marker<$operator> $(+ $bounds)*,
|
|
||||||
DefaultAllocator: Allocator<N, R, C> { }
|
|
||||||
)*}
|
|
||||||
);
|
|
||||||
|
|
||||||
inherit_additive_structure!(
|
|
||||||
AbstractSemigroup<Additive> + ClosedAdd,
|
|
||||||
AbstractMonoid<Additive> + Zero + ClosedAdd,
|
|
||||||
AbstractQuasigroup<Additive> + ClosedAdd + ClosedNeg,
|
|
||||||
AbstractLoop<Additive> + Zero + ClosedAdd + ClosedNeg,
|
|
||||||
AbstractGroup<Additive> + Zero + ClosedAdd + ClosedNeg,
|
|
||||||
AbstractGroupAbelian<Additive> + Zero + ClosedAdd + ClosedNeg
|
|
||||||
);
|
|
||||||
|
|
||||||
impl<N, R: DimName, C: DimName> AbstractModule for MatrixMN<N, R, C>
|
|
||||||
where
|
|
||||||
N: Scalar + RingCommutative,
|
|
||||||
DefaultAllocator: Allocator<N, R, C>,
|
|
||||||
{
|
|
||||||
type AbstractRing = N;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn multiply_by(&self, n: N) -> Self {
|
|
||||||
self * n
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N, R: DimName, C: DimName> Module for MatrixMN<N, R, C>
|
|
||||||
where
|
|
||||||
N: Scalar + RingCommutative,
|
|
||||||
DefaultAllocator: Allocator<N, R, C>,
|
|
||||||
{
|
|
||||||
type Ring = N;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N, R: DimName, C: DimName> VectorSpace for MatrixMN<N, R, C>
|
|
||||||
where
|
|
||||||
N: Scalar + Field,
|
|
||||||
DefaultAllocator: Allocator<N, R, C>,
|
|
||||||
{
|
|
||||||
type Field = N;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N, R: DimName, C: DimName> FiniteDimVectorSpace for MatrixMN<N, R, C>
|
|
||||||
where
|
|
||||||
N: Scalar + Field,
|
|
||||||
DefaultAllocator: Allocator<N, R, C>,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn dimension() -> usize {
|
|
||||||
R::dim() * C::dim()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn canonical_basis_element(i: usize) -> Self {
|
|
||||||
assert!(i < Self::dimension(), "Index out of bound.");
|
|
||||||
|
|
||||||
let mut res = Self::zero();
|
|
||||||
unsafe {
|
|
||||||
*res.data.get_unchecked_linear_mut(i) = N::one();
|
|
||||||
}
|
|
||||||
|
|
||||||
res
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn dot(&self, other: &Self) -> N {
|
|
||||||
self.dot(other)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
unsafe fn component_unchecked(&self, i: usize) -> &N {
|
|
||||||
self.data.get_unchecked_linear(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
unsafe fn component_unchecked_mut(&mut self, i: usize) -> &mut N {
|
|
||||||
self.data.get_unchecked_linear_mut(i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: ComplexField, R: DimName, C: DimName> NormedSpace for MatrixMN<N, R, C>
|
|
||||||
where DefaultAllocator: Allocator<N, R, C>
|
|
||||||
{
|
|
||||||
type RealField = N::RealField;
|
|
||||||
type ComplexField = N;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn norm_squared(&self) -> N::RealField {
|
|
||||||
self.norm_squared()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn norm(&self) -> N::RealField {
|
|
||||||
self.norm()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
#[must_use = "Did you mean to use normalize_mut()?"]
|
|
||||||
fn normalize(&self) -> Self {
|
|
||||||
self.normalize()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn normalize_mut(&mut self) -> N::RealField {
|
|
||||||
self.normalize_mut()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
#[must_use = "Did you mean to use try_normalize_mut()?"]
|
|
||||||
fn try_normalize(&self, min_norm: N::RealField) -> Option<Self> {
|
|
||||||
self.try_normalize(min_norm)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn try_normalize_mut(&mut self, min_norm: N::RealField) -> Option<N::RealField> {
|
|
||||||
self.try_normalize_mut(min_norm)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: ComplexField, R: DimName, C: DimName> InnerSpace for MatrixMN<N, R, C>
|
|
||||||
where DefaultAllocator: Allocator<N, R, C>
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn angle(&self, other: &Self) -> N::RealField {
|
|
||||||
self.angle(other)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn inner_product(&self, other: &Self) -> N {
|
|
||||||
self.dotc(other)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: specialization will greatly simplify this implementation in the future.
|
|
||||||
// In particular:
|
|
||||||
// − use `x()` instead of `::canonical_basis_element`
|
|
||||||
// − use `::new(x, y, z)` instead of `::from_slice`
|
|
||||||
impl<N: ComplexField, R: DimName, C: DimName> FiniteDimInnerSpace for MatrixMN<N, R, C>
|
|
||||||
where DefaultAllocator: Allocator<N, R, C>
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn orthonormalize(vs: &mut [Self]) -> usize {
|
|
||||||
let mut nbasis_elements = 0;
|
|
||||||
|
|
||||||
for i in 0..vs.len() {
|
|
||||||
{
|
|
||||||
let (elt, basis) = vs[..i + 1].split_last_mut().unwrap();
|
|
||||||
|
|
||||||
for basis_element in &basis[..nbasis_elements] {
|
|
||||||
*elt -= &*basis_element * elt.dot(basis_element)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if vs[i].try_normalize_mut(N::RealField::zero()).is_some() {
|
|
||||||
// FIXME: this will be efficient on dynamically-allocated vectors but for
|
|
||||||
// statically-allocated ones, `.clone_from` would be better.
|
|
||||||
vs.swap(nbasis_elements, i);
|
|
||||||
nbasis_elements += 1;
|
|
||||||
|
|
||||||
// All the other vectors will be dependent.
|
|
||||||
if nbasis_elements == Self::dimension() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nbasis_elements
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn orthonormal_subspace_basis<F>(vs: &[Self], mut f: F)
|
|
||||||
where F: FnMut(&Self) -> bool {
|
|
||||||
// FIXME: is this necessary?
|
|
||||||
assert!(
|
|
||||||
vs.len() <= Self::dimension(),
|
|
||||||
"The given set of vectors has no chance of being a free family."
|
|
||||||
);
|
|
||||||
|
|
||||||
match Self::dimension() {
|
|
||||||
1 => {
|
|
||||||
if vs.len() == 0 {
|
|
||||||
let _ = f(&Self::canonical_basis_element(0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
2 => {
|
|
||||||
if vs.len() == 0 {
|
|
||||||
let _ = f(&Self::canonical_basis_element(0))
|
|
||||||
&& f(&Self::canonical_basis_element(1));
|
|
||||||
} else if vs.len() == 1 {
|
|
||||||
let v = &vs[0];
|
|
||||||
let res = Self::from_column_slice(&[-v[1], v[0]]);
|
|
||||||
|
|
||||||
let _ = f(&res.normalize());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, nothing.
|
|
||||||
}
|
|
||||||
3 => {
|
|
||||||
if vs.len() == 0 {
|
|
||||||
let _ = f(&Self::canonical_basis_element(0))
|
|
||||||
&& f(&Self::canonical_basis_element(1))
|
|
||||||
&& f(&Self::canonical_basis_element(2));
|
|
||||||
} else if vs.len() == 1 {
|
|
||||||
let v = &vs[0];
|
|
||||||
let mut a;
|
|
||||||
|
|
||||||
if v[0].norm1() > v[1].norm1() {
|
|
||||||
a = Self::from_column_slice(&[v[2], N::zero(), -v[0]]);
|
|
||||||
} else {
|
|
||||||
a = Self::from_column_slice(&[N::zero(), -v[2], v[1]]);
|
|
||||||
};
|
|
||||||
|
|
||||||
let _ = a.normalize_mut();
|
|
||||||
|
|
||||||
if f(&a.cross(v)) {
|
|
||||||
let _ = f(&a);
|
|
||||||
}
|
|
||||||
} else if vs.len() == 2 {
|
|
||||||
let _ = f(&vs[0].cross(&vs[1]).normalize());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
|
||||||
{
|
|
||||||
// XXX: use a GenericArray instead.
|
|
||||||
let mut known_basis = Vec::new();
|
|
||||||
|
|
||||||
for v in vs.iter() {
|
|
||||||
known_basis.push(v.normalize())
|
|
||||||
}
|
|
||||||
|
|
||||||
for i in 0..Self::dimension() - vs.len() {
|
|
||||||
let mut elt = Self::canonical_basis_element(i);
|
|
||||||
|
|
||||||
for v in &known_basis {
|
|
||||||
elt -= v * elt.dot(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(subsp_elt) = elt.try_normalize(N::RealField::zero()) {
|
|
||||||
if !f(&subsp_elt) {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
known_basis.push(subsp_elt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(all(not(feature = "std"), not(feature = "alloc")))]
|
|
||||||
{
|
|
||||||
panic!("Cannot compute the orthogonal subspace basis of a vector with a dimension greater than 3 \
|
|
||||||
if #![no_std] is enabled and the 'alloc' feature is not enabled.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Multiplicative structures.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
impl<N, D: DimName> Identity<Multiplicative> for MatrixN<N, D>
|
|
||||||
where
|
|
||||||
N: Scalar + Zero + One,
|
|
||||||
DefaultAllocator: Allocator<N, D, D>,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn identity() -> Self {
|
|
||||||
Self::identity()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N, D: DimName> AbstractMagma<Multiplicative> for MatrixN<N, D>
|
|
||||||
where
|
|
||||||
N: Scalar + Zero + One + ClosedAdd + ClosedMul,
|
|
||||||
DefaultAllocator: Allocator<N, D, D>,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn operate(&self, other: &Self) -> Self {
|
|
||||||
self * other
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_multiplicative_structure(
|
|
||||||
($($marker: ident<$operator: ident> $(+ $bounds: ident)*),* $(,)*) => {$(
|
|
||||||
impl<N, D: DimName> $marker<$operator> for MatrixN<N, D>
|
|
||||||
where N: Scalar + Zero + One + ClosedAdd + ClosedMul + $marker<$operator> $(+ $bounds)*,
|
|
||||||
DefaultAllocator: Allocator<N, D, D> { }
|
|
||||||
)*}
|
|
||||||
);
|
|
||||||
|
|
||||||
impl_multiplicative_structure!(
|
|
||||||
AbstractSemigroup<Multiplicative>,
|
|
||||||
AbstractMonoid<Multiplicative> + One
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Ordering
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
impl<N, R: Dim, C: Dim> MeetSemilattice for MatrixMN<N, R, C>
|
|
||||||
where
|
|
||||||
N: Scalar + MeetSemilattice,
|
|
||||||
DefaultAllocator: Allocator<N, R, C>,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn meet(&self, other: &Self) -> Self {
|
|
||||||
self.zip_map(other, |a, b| a.meet(&b))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N, R: Dim, C: Dim> JoinSemilattice for MatrixMN<N, R, C>
|
|
||||||
where
|
|
||||||
N: Scalar + JoinSemilattice,
|
|
||||||
DefaultAllocator: Allocator<N, R, C>,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn join(&self, other: &Self) -> Self {
|
|
||||||
self.zip_map(other, |a, b| a.join(&b))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N, R: Dim, C: Dim> Lattice for MatrixMN<N, R, C>
|
|
||||||
where
|
|
||||||
N: Scalar + Lattice,
|
|
||||||
DefaultAllocator: Allocator<N, R, C>,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn meet_join(&self, other: &Self) -> (Self, Self) {
|
|
||||||
let shape = self.data.shape();
|
|
||||||
assert!(
|
|
||||||
shape == other.data.shape(),
|
|
||||||
"Matrix meet/join error: mismatched dimensions."
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut mres = unsafe { Self::new_uninitialized_generic(shape.0, shape.1) };
|
|
||||||
let mut jres = unsafe { Self::new_uninitialized_generic(shape.0, shape.1) };
|
|
||||||
|
|
||||||
for i in 0..shape.0.value() * shape.1.value() {
|
|
||||||
unsafe {
|
|
||||||
let mj = self
|
|
||||||
.data
|
|
||||||
.get_unchecked_linear(i)
|
|
||||||
.meet_join(other.data.get_unchecked_linear(i));
|
|
||||||
*mres.data.get_unchecked_linear_mut(i) = mj.0;
|
|
||||||
*jres.data.get_unchecked_linear_mut(i) = mj.1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(mres, jres)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
|
use simba::simd::SimdValue;
|
||||||
|
|
||||||
|
use crate::base::allocator::Allocator;
|
||||||
|
use crate::base::dimension::Dim;
|
||||||
|
use crate::base::{DefaultAllocator, MatrixMN, Scalar};
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Simd structures.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
impl<N, R, C> SimdValue for MatrixMN<N, R, C>
|
||||||
|
where
|
||||||
|
N: Scalar + SimdValue,
|
||||||
|
R: Dim,
|
||||||
|
C: Dim,
|
||||||
|
N::Element: Scalar,
|
||||||
|
DefaultAllocator: Allocator<N, R, C> + Allocator<N::Element, R, C>,
|
||||||
|
{
|
||||||
|
type Element = MatrixMN<N::Element, R, C>;
|
||||||
|
type SimdBool = N::SimdBool;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn lanes() -> usize {
|
||||||
|
N::lanes()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn splat(val: Self::Element) -> Self {
|
||||||
|
val.map(N::splat)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn extract(&self, i: usize) -> Self::Element {
|
||||||
|
self.map(|e| e.extract(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn extract_unchecked(&self, i: usize) -> Self::Element {
|
||||||
|
self.map(|e| e.extract_unchecked(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn replace(&mut self, i: usize, val: Self::Element) {
|
||||||
|
self.zip_apply(&val, |mut a, b| {
|
||||||
|
a.replace(i, b);
|
||||||
|
a
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn replace_unchecked(&mut self, i: usize, val: Self::Element) {
|
||||||
|
self.zip_apply(&val, |mut a, b| {
|
||||||
|
a.replace_unchecked(i, b);
|
||||||
|
a
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn select(self, cond: Self::SimdBool, other: Self) -> Self {
|
||||||
|
self.zip_map(&other, |a, b| a.select(cond, b))
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,6 +12,7 @@ pub mod storage;
|
||||||
|
|
||||||
mod alias;
|
mod alias;
|
||||||
mod alias_slice;
|
mod alias_slice;
|
||||||
|
mod array_storage;
|
||||||
mod cg;
|
mod cg;
|
||||||
mod componentwise;
|
mod componentwise;
|
||||||
mod construction;
|
mod construction;
|
||||||
|
@ -20,25 +21,24 @@ mod conversion;
|
||||||
mod edition;
|
mod edition;
|
||||||
pub mod indexing;
|
pub mod indexing;
|
||||||
mod matrix;
|
mod matrix;
|
||||||
mod matrix_alga;
|
mod matrix_simba;
|
||||||
mod array_storage;
|
|
||||||
mod matrix_slice;
|
mod matrix_slice;
|
||||||
#[cfg(any(feature = "std", feature = "alloc"))]
|
mod norm;
|
||||||
mod vec_storage;
|
|
||||||
mod properties;
|
mod properties;
|
||||||
mod scalar;
|
mod scalar;
|
||||||
|
mod statistics;
|
||||||
mod swizzle;
|
mod swizzle;
|
||||||
mod unit;
|
mod unit;
|
||||||
mod statistics;
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
mod norm;
|
mod vec_storage;
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub mod helper;
|
pub mod helper;
|
||||||
|
|
||||||
pub use self::matrix::*;
|
pub use self::matrix::*;
|
||||||
|
pub use self::norm::*;
|
||||||
pub use self::scalar::*;
|
pub use self::scalar::*;
|
||||||
pub use self::unit::*;
|
pub use self::unit::*;
|
||||||
pub use self::norm::*;
|
|
||||||
|
|
||||||
pub use self::default_allocator::*;
|
pub use self::default_allocator::*;
|
||||||
pub use self::dimension::*;
|
pub use self::dimension::*;
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
use num::Zero;
|
use num::Zero;
|
||||||
|
use std::ops::Neg;
|
||||||
|
|
||||||
use crate::allocator::Allocator;
|
use crate::allocator::Allocator;
|
||||||
use crate::base::{DefaultAllocator, Dim, Matrix, MatrixMN};
|
use crate::base::{DefaultAllocator, Dim, Matrix, MatrixMN, Normed};
|
||||||
use crate::constraint::{SameNumberOfColumns, SameNumberOfRows, ShapeConstraint};
|
use crate::constraint::{SameNumberOfColumns, SameNumberOfRows, ShapeConstraint};
|
||||||
use crate::storage::{Storage, StorageMut};
|
use crate::storage::{Storage, StorageMut};
|
||||||
use crate::{ComplexField, RealField, SimdComplexField, SimdRealField};
|
use crate::{ComplexField, Scalar, SimdComplexField, Unit};
|
||||||
use alga::simd::SimdPartialOrd;
|
use simba::scalar::ClosedNeg;
|
||||||
|
use simba::simd::{SimdOption, SimdPartialOrd};
|
||||||
|
|
||||||
// FIXME: this should be be a trait on alga?
|
// FIXME: this should be be a trait on alga?
|
||||||
/// A trait for abstract matrix norms.
|
/// A trait for abstract matrix norms.
|
||||||
|
@ -272,6 +274,19 @@ impl<N: SimdComplexField, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S
|
||||||
pub fn lp_norm(&self, p: i32) -> N::SimdRealField {
|
pub fn lp_norm(&self, p: i32) -> N::SimdRealField {
|
||||||
self.apply_norm(&LpNorm(p))
|
self.apply_norm(&LpNorm(p))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[must_use = "Did you mean to use simd_try_normalize_mut()?"]
|
||||||
|
pub fn simd_try_normalize(&self, min_norm: N::SimdRealField) -> SimdOption<MatrixMN<N, R, C>>
|
||||||
|
where
|
||||||
|
N::Element: Scalar,
|
||||||
|
DefaultAllocator: Allocator<N, R, C> + Allocator<N::Element, R, C>,
|
||||||
|
{
|
||||||
|
let n = self.norm();
|
||||||
|
let le = n.simd_le(min_norm);
|
||||||
|
let val = self.unscale(n);
|
||||||
|
SimdOption::new(val, le)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: ComplexField, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
|
impl<N: ComplexField, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
|
||||||
|
@ -313,6 +328,22 @@ impl<N: SimdComplexField, R: Dim, C: Dim, S: StorageMut<N, R, C>> Matrix<N, R, C
|
||||||
|
|
||||||
n
|
n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[must_use = "Did you mean to use simd_try_normalize_mut()?"]
|
||||||
|
pub fn simd_try_normalize_mut(
|
||||||
|
&mut self,
|
||||||
|
min_norm: N::SimdRealField,
|
||||||
|
) -> SimdOption<N::SimdRealField>
|
||||||
|
where
|
||||||
|
N::Element: Scalar,
|
||||||
|
DefaultAllocator: Allocator<N, R, C> + Allocator<N::Element, R, C>,
|
||||||
|
{
|
||||||
|
let n = self.norm();
|
||||||
|
let le = n.simd_le(min_norm);
|
||||||
|
self.apply(|e| e.simd_unscale(n).select(le, e));
|
||||||
|
SimdOption::new(n, le)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: ComplexField, R: Dim, C: Dim, S: StorageMut<N, R, C>> Matrix<N, R, C, S> {
|
impl<N: ComplexField, R: Dim, C: Dim, S: StorageMut<N, R, C>> Matrix<N, R, C, S> {
|
||||||
|
@ -320,8 +351,7 @@ impl<N: ComplexField, R: Dim, C: Dim, S: StorageMut<N, R, C>> Matrix<N, R, C, S>
|
||||||
///
|
///
|
||||||
/// If the normalization succeeded, returns the old norm of this matrix.
|
/// If the normalization succeeded, returns the old norm of this matrix.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn try_normalize_mut(&mut self, min_norm: N::RealField) -> Option<N::RealField>
|
pub fn try_normalize_mut(&mut self, min_norm: N::RealField) -> Option<N::RealField> {
|
||||||
where N: ComplexField {
|
|
||||||
let n = self.norm();
|
let n = self.norm();
|
||||||
|
|
||||||
if n <= min_norm {
|
if n <= min_norm {
|
||||||
|
@ -332,3 +362,40 @@ impl<N: ComplexField, R: Dim, C: Dim, S: StorageMut<N, R, C>> Matrix<N, R, C, S>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<N: SimdComplexField, R: Dim, C: Dim> Normed for MatrixMN<N, R, C>
|
||||||
|
where DefaultAllocator: Allocator<N, R, C>
|
||||||
|
{
|
||||||
|
type Norm = N::SimdRealField;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn norm(&self) -> N::SimdRealField {
|
||||||
|
self.norm()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn norm_squared(&self) -> N::SimdRealField {
|
||||||
|
self.norm_squared()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn scale_mut(&mut self, n: Self::Norm) {
|
||||||
|
self.scale_mut(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn unscale_mut(&mut self, n: Self::Norm) {
|
||||||
|
self.unscale_mut(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: Scalar + ClosedNeg, R: Dim, C: Dim> Neg for Unit<MatrixMN<N, R, C>>
|
||||||
|
where DefaultAllocator: Allocator<N, R, C>
|
||||||
|
{
|
||||||
|
type Output = Unit<MatrixMN<N, R, C>>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn neg(self) -> Self::Output {
|
||||||
|
Unit::new_unchecked(-self.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
use num::{One, Signed, Zero};
|
use num::{One, Zero};
|
||||||
use std::cmp::{Ordering, PartialOrd};
|
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::ops::{
|
use std::ops::{
|
||||||
Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign,
|
Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign,
|
||||||
};
|
};
|
||||||
|
|
||||||
use alga::general::{ClosedAdd, ClosedDiv, ClosedMul, ClosedNeg, ClosedSub};
|
use simba::scalar::{ClosedAdd, ClosedDiv, ClosedMul, ClosedNeg, ClosedSub};
|
||||||
use alga::simd::{SimdPartialOrd, SimdSigned};
|
use simba::simd::{SimdPartialOrd, SimdSigned};
|
||||||
|
|
||||||
use crate::base::allocator::{Allocator, SameShapeAllocator, SameShapeC, SameShapeR};
|
use crate::base::allocator::{Allocator, SameShapeAllocator, SameShapeC, SameShapeR};
|
||||||
use crate::base::constraint::{
|
use crate::base::constraint::{
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
use approx::RelativeEq;
|
use approx::RelativeEq;
|
||||||
use num::{One, Zero};
|
use num::{One, Zero};
|
||||||
|
|
||||||
use alga::general::{ClosedAdd, ClosedMul, RealField, ComplexField};
|
use simba::scalar::{ClosedAdd, ClosedMul, ComplexField, RealField};
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::dimension::{Dim, DimMin};
|
use crate::base::dimension::{Dim, DimMin};
|
||||||
|
@ -91,11 +91,11 @@ impl<N: ComplexField, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
|
||||||
/// equal to `eps`.
|
/// equal to `eps`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_orthogonal(&self, eps: N::Epsilon) -> bool
|
pub fn is_orthogonal(&self, eps: N::Epsilon) -> bool
|
||||||
where
|
where
|
||||||
N: Zero + One + ClosedAdd + ClosedMul + RelativeEq,
|
N: Zero + One + ClosedAdd + ClosedMul + RelativeEq,
|
||||||
S: Storage<N, R, C>,
|
S: Storage<N, R, C>,
|
||||||
N::Epsilon: Copy,
|
N::Epsilon: Copy,
|
||||||
DefaultAllocator: Allocator<N, R, C> + Allocator<N, C, C>,
|
DefaultAllocator: Allocator<N, R, C> + Allocator<N, C, C>,
|
||||||
{
|
{
|
||||||
(self.ad_mul(self)).is_identity(eps)
|
(self.ad_mul(self)).is_identity(eps)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,28 @@
|
||||||
use crate::{Scalar, Dim, Matrix, VectorN, RowVectorN, DefaultAllocator, U1, VectorSliceN};
|
|
||||||
use alga::general::{AdditiveMonoid, Field, SupersetOf};
|
|
||||||
use crate::storage::Storage;
|
|
||||||
use crate::allocator::Allocator;
|
use crate::allocator::Allocator;
|
||||||
|
use crate::storage::Storage;
|
||||||
|
use crate::{DefaultAllocator, Dim, Matrix, RowVectorN, Scalar, VectorN, VectorSliceN, U1};
|
||||||
|
use num::Zero;
|
||||||
|
use simba::scalar::{ClosedAdd, Field, SupersetOf};
|
||||||
|
|
||||||
impl<N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
|
impl<N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
|
||||||
/// Returns a row vector where each element is the result of the application of `f` on the
|
/// Returns a row vector where each element is the result of the application of `f` on the
|
||||||
/// corresponding column of the original matrix.
|
/// corresponding column of the original matrix.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn compress_rows(&self, f: impl Fn(VectorSliceN<N, R, S::RStride, S::CStride>) -> N) -> RowVectorN<N, C>
|
pub fn compress_rows(
|
||||||
where DefaultAllocator: Allocator<N, U1, C> {
|
&self,
|
||||||
|
f: impl Fn(VectorSliceN<N, R, S::RStride, S::CStride>) -> N,
|
||||||
|
) -> RowVectorN<N, C>
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<N, U1, C>,
|
||||||
|
{
|
||||||
let ncols = self.data.shape().1;
|
let ncols = self.data.shape().1;
|
||||||
let mut res = unsafe { RowVectorN::new_uninitialized_generic(U1, ncols) };
|
let mut res = unsafe { RowVectorN::new_uninitialized_generic(U1, ncols) };
|
||||||
|
|
||||||
for i in 0..ncols.value() {
|
for i in 0..ncols.value() {
|
||||||
// FIXME: avoid bound checking of column.
|
// FIXME: avoid bound checking of column.
|
||||||
unsafe { *res.get_unchecked_mut((0, i)) = f(self.column(i)); }
|
unsafe {
|
||||||
|
*res.get_unchecked_mut((0, i)) = f(self.column(i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res
|
res
|
||||||
|
@ -26,15 +33,21 @@ impl<N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
|
||||||
///
|
///
|
||||||
/// This is the same as `self.compress_rows(f).transpose()`.
|
/// This is the same as `self.compress_rows(f).transpose()`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn compress_rows_tr(&self, f: impl Fn(VectorSliceN<N, R, S::RStride, S::CStride>) -> N) -> VectorN<N, C>
|
pub fn compress_rows_tr(
|
||||||
where DefaultAllocator: Allocator<N, C> {
|
&self,
|
||||||
|
f: impl Fn(VectorSliceN<N, R, S::RStride, S::CStride>) -> N,
|
||||||
|
) -> VectorN<N, C>
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<N, C>,
|
||||||
|
{
|
||||||
let ncols = self.data.shape().1;
|
let ncols = self.data.shape().1;
|
||||||
let mut res = unsafe { VectorN::new_uninitialized_generic(ncols, U1) };
|
let mut res = unsafe { VectorN::new_uninitialized_generic(ncols, U1) };
|
||||||
|
|
||||||
for i in 0..ncols.value() {
|
for i in 0..ncols.value() {
|
||||||
// FIXME: avoid bound checking of column.
|
// FIXME: avoid bound checking of column.
|
||||||
unsafe { *res.vget_unchecked_mut(i) = f(self.column(i)); }
|
unsafe {
|
||||||
|
*res.vget_unchecked_mut(i) = f(self.column(i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res
|
res
|
||||||
|
@ -42,8 +55,14 @@ impl<N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
|
||||||
|
|
||||||
/// Returns a column vector resulting from the folding of `f` on each column of this matrix.
|
/// Returns a column vector resulting from the folding of `f` on each column of this matrix.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn compress_columns(&self, init: VectorN<N, R>, f: impl Fn(&mut VectorN<N, R>, VectorSliceN<N, R, S::RStride, S::CStride>)) -> VectorN<N, R>
|
pub fn compress_columns(
|
||||||
where DefaultAllocator: Allocator<N, R> {
|
&self,
|
||||||
|
init: VectorN<N, R>,
|
||||||
|
f: impl Fn(&mut VectorN<N, R>, VectorSliceN<N, R, S::RStride, S::CStride>),
|
||||||
|
) -> VectorN<N, R>
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<N, R>,
|
||||||
|
{
|
||||||
let mut res = init;
|
let mut res = init;
|
||||||
|
|
||||||
for i in 0..self.ncols() {
|
for i in 0..self.ncols() {
|
||||||
|
@ -54,7 +73,7 @@ impl<N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: Scalar + AdditiveMonoid, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
|
impl<N: Scalar + ClosedAdd + Zero, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Sum computation.
|
* Sum computation.
|
||||||
|
@ -95,7 +114,7 @@ impl<N: Scalar + AdditiveMonoid, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N,
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn row_sum(&self) -> RowVectorN<N, C>
|
pub fn row_sum(&self) -> RowVectorN<N, C>
|
||||||
where DefaultAllocator: Allocator<N, U1, C> {
|
where DefaultAllocator: Allocator<N, U1, C> {
|
||||||
self.compress_rows(|col| col.sum())
|
self.compress_rows(|col| col.sum())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,7 +135,7 @@ impl<N: Scalar + AdditiveMonoid, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N,
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn row_sum_tr(&self) -> VectorN<N, C>
|
pub fn row_sum_tr(&self) -> VectorN<N, C>
|
||||||
where DefaultAllocator: Allocator<N, C> {
|
where DefaultAllocator: Allocator<N, C> {
|
||||||
self.compress_rows_tr(|col| col.sum())
|
self.compress_rows_tr(|col| col.sum())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,7 +156,7 @@ impl<N: Scalar + AdditiveMonoid, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N,
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn column_sum(&self) -> VectorN<N, R>
|
pub fn column_sum(&self) -> VectorN<N, R>
|
||||||
where DefaultAllocator: Allocator<N, R> {
|
where DefaultAllocator: Allocator<N, R> {
|
||||||
let nrows = self.data.shape().0;
|
let nrows = self.data.shape().0;
|
||||||
self.compress_columns(VectorN::zeros_generic(nrows, U1), |out, col| {
|
self.compress_columns(VectorN::zeros_generic(nrows, U1), |out, col| {
|
||||||
*out += col;
|
*out += col;
|
||||||
|
@ -168,7 +187,9 @@ impl<N: Scalar + Field + SupersetOf<f64>, R: Dim, C: Dim, S: Storage<N, R, C>> M
|
||||||
if self.len() == 0 {
|
if self.len() == 0 {
|
||||||
N::zero()
|
N::zero()
|
||||||
} else {
|
} else {
|
||||||
let val = self.iter().cloned().fold((N::zero(), N::zero()), |a, b| (a.0 + b.inlined_clone() * b.inlined_clone(), a.1 + b));
|
let val = self.iter().cloned().fold((N::zero(), N::zero()), |a, b| {
|
||||||
|
(a.0 + b.inlined_clone() * b.inlined_clone(), a.1 + b)
|
||||||
|
});
|
||||||
let denom = N::one() / crate::convert::<_, N>(self.len() as f64);
|
let denom = N::one() / crate::convert::<_, N>(self.len() as f64);
|
||||||
let vd = val.1 * denom.inlined_clone();
|
let vd = val.1 * denom.inlined_clone();
|
||||||
val.0 * denom - vd.inlined_clone() * vd
|
val.0 * denom - vd.inlined_clone() * vd
|
||||||
|
@ -189,7 +210,7 @@ impl<N: Scalar + Field + SupersetOf<f64>, R: Dim, C: Dim, S: Storage<N, R, C>> M
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn row_variance(&self) -> RowVectorN<N, C>
|
pub fn row_variance(&self) -> RowVectorN<N, C>
|
||||||
where DefaultAllocator: Allocator<N, U1, C> {
|
where DefaultAllocator: Allocator<N, U1, C> {
|
||||||
self.compress_rows(|col| col.variance())
|
self.compress_rows(|col| col.variance())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,7 +227,7 @@ impl<N: Scalar + Field + SupersetOf<f64>, R: Dim, C: Dim, S: Storage<N, R, C>> M
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn row_variance_tr(&self) -> VectorN<N, C>
|
pub fn row_variance_tr(&self) -> VectorN<N, C>
|
||||||
where DefaultAllocator: Allocator<N, C> {
|
where DefaultAllocator: Allocator<N, C> {
|
||||||
self.compress_rows_tr(|col| col.variance())
|
self.compress_rows_tr(|col| col.variance())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,7 +245,7 @@ impl<N: Scalar + Field + SupersetOf<f64>, R: Dim, C: Dim, S: Storage<N, R, C>> M
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn column_variance(&self) -> VectorN<N, R>
|
pub fn column_variance(&self) -> VectorN<N, R>
|
||||||
where DefaultAllocator: Allocator<N, R> {
|
where DefaultAllocator: Allocator<N, R> {
|
||||||
let (nrows, ncols) = self.data.shape();
|
let (nrows, ncols) = self.data.shape();
|
||||||
|
|
||||||
let mut mean = self.column_mean();
|
let mut mean = self.column_mean();
|
||||||
|
@ -235,7 +256,8 @@ impl<N: Scalar + Field + SupersetOf<f64>, R: Dim, C: Dim, S: Storage<N, R, C>> M
|
||||||
for i in 0..nrows.value() {
|
for i in 0..nrows.value() {
|
||||||
unsafe {
|
unsafe {
|
||||||
let val = col.vget_unchecked(i);
|
let val = col.vget_unchecked(i);
|
||||||
*out.vget_unchecked_mut(i) += denom.inlined_clone() * val.inlined_clone() * val.inlined_clone()
|
*out.vget_unchecked_mut(i) +=
|
||||||
|
denom.inlined_clone() * val.inlined_clone() * val.inlined_clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -281,7 +303,7 @@ impl<N: Scalar + Field + SupersetOf<f64>, R: Dim, C: Dim, S: Storage<N, R, C>> M
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn row_mean(&self) -> RowVectorN<N, C>
|
pub fn row_mean(&self) -> RowVectorN<N, C>
|
||||||
where DefaultAllocator: Allocator<N, U1, C> {
|
where DefaultAllocator: Allocator<N, U1, C> {
|
||||||
self.compress_rows(|col| col.mean())
|
self.compress_rows(|col| col.mean())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,7 +320,7 @@ impl<N: Scalar + Field + SupersetOf<f64>, R: Dim, C: Dim, S: Storage<N, R, C>> M
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn row_mean_tr(&self) -> VectorN<N, C>
|
pub fn row_mean_tr(&self) -> VectorN<N, C>
|
||||||
where DefaultAllocator: Allocator<N, C> {
|
where DefaultAllocator: Allocator<N, C> {
|
||||||
self.compress_rows_tr(|col| col.mean())
|
self.compress_rows_tr(|col| col.mean())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,7 +337,7 @@ impl<N: Scalar + Field + SupersetOf<f64>, R: Dim, C: Dim, S: Storage<N, R, C>> M
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn column_mean(&self) -> VectorN<N, R>
|
pub fn column_mean(&self) -> VectorN<N, R>
|
||||||
where DefaultAllocator: Allocator<N, R> {
|
where DefaultAllocator: Allocator<N, R> {
|
||||||
let (nrows, ncols) = self.data.shape();
|
let (nrows, ncols) = self.data.shape();
|
||||||
let denom = N::one() / crate::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| {
|
self.compress_columns(VectorN::zeros_generic(nrows, U1), |out, col| {
|
||||||
|
|
|
@ -94,13 +94,11 @@ pub unsafe trait Storage<N: Scalar, R: Dim, C: Dim = U1>: Debug + Sized {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Indicates whether this data buffer stores its elements contiguously.
|
/// Indicates whether this data buffer stores its elements contiguously.
|
||||||
#[inline]
|
|
||||||
fn is_contiguous(&self) -> bool;
|
fn is_contiguous(&self) -> bool;
|
||||||
|
|
||||||
/// Retrieves the data buffer as a contiguous slice.
|
/// Retrieves the data buffer as a contiguous slice.
|
||||||
///
|
///
|
||||||
/// The matrix components may not be stored in a contiguous way, depending on the strides.
|
/// The matrix components may not be stored in a contiguous way, depending on the strides.
|
||||||
#[inline]
|
|
||||||
fn as_slice(&self) -> &[N];
|
fn as_slice(&self) -> &[N];
|
||||||
|
|
||||||
/// Builds a matrix data storage that does not contain any reference.
|
/// Builds a matrix data storage that does not contain any reference.
|
||||||
|
@ -166,7 +164,6 @@ pub unsafe trait StorageMut<N: Scalar, R: Dim, C: Dim = U1>: Storage<N, R, C> {
|
||||||
/// Retrieves the mutable data buffer as a contiguous slice.
|
/// Retrieves the mutable data buffer as a contiguous slice.
|
||||||
///
|
///
|
||||||
/// Matrix components may not be contiguous, depending on its strides.
|
/// Matrix components may not be contiguous, depending on its strides.
|
||||||
#[inline]
|
|
||||||
fn as_mut_slice(&mut self) -> &mut [N];
|
fn as_mut_slice(&mut self) -> &mut [N];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
use approx::RelativeEq;
|
|
||||||
#[cfg(feature = "abomonation-serialize")]
|
#[cfg(feature = "abomonation-serialize")]
|
||||||
use std::io::{Result as IOResult, Write};
|
use std::io::{Result as IOResult, Write};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::{Deref, Neg};
|
use std::ops::Deref;
|
||||||
|
|
||||||
#[cfg(feature = "serde-serialize")]
|
#[cfg(feature = "serde-serialize")]
|
||||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||||
|
@ -10,8 +9,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||||
#[cfg(feature = "abomonation-serialize")]
|
#[cfg(feature = "abomonation-serialize")]
|
||||||
use abomonation::Abomonation;
|
use abomonation::Abomonation;
|
||||||
|
|
||||||
use alga::general::{SubsetOf, ComplexField};
|
use crate::{RealField, SimdComplexField, SimdRealField};
|
||||||
use alga::linear::NormedSpace;
|
|
||||||
|
|
||||||
/// A wrapper that ensures the underlying algebraic entity has a unit norm.
|
/// A wrapper that ensures the underlying algebraic entity has a unit norm.
|
||||||
///
|
///
|
||||||
|
@ -19,7 +17,7 @@ use alga::linear::NormedSpace;
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[derive(Eq, PartialEq, Clone, Hash, Debug, Copy)]
|
#[derive(Eq, PartialEq, Clone, Hash, Debug, Copy)]
|
||||||
pub struct Unit<T> {
|
pub struct Unit<T> {
|
||||||
value: T,
|
pub(crate) value: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "serde-serialize")]
|
#[cfg(feature = "serde-serialize")]
|
||||||
|
@ -53,60 +51,76 @@ impl<T: Abomonation> Abomonation for Unit<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: NormedSpace> Unit<T> {
|
pub trait Normed {
|
||||||
/// Normalize the given value and return it wrapped on a `Unit` structure.
|
type Norm: SimdRealField;
|
||||||
|
fn norm(&self) -> Self::Norm;
|
||||||
|
fn norm_squared(&self) -> Self::Norm;
|
||||||
|
fn scale_mut(&mut self, n: Self::Norm);
|
||||||
|
fn unscale_mut(&mut self, n: Self::Norm);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Normed> Unit<T> {
|
||||||
|
/// Normalize the given vector and return it wrapped on a `Unit` structure.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new_normalize(value: T) -> Self {
|
pub fn new_normalize(value: T) -> Self {
|
||||||
Self::new_and_get(value).0
|
Self::new_and_get(value).0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to normalize the given value and return it wrapped on a `Unit` structure.
|
/// Attempts to normalize the given vector and return it wrapped on a `Unit` structure.
|
||||||
///
|
///
|
||||||
/// Returns `None` if the norm was smaller or equal to `min_norm`.
|
/// Returns `None` if the norm was smaller or equal to `min_norm`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn try_new(value: T, min_norm: T::RealField) -> Option<Self> {
|
pub fn try_new(value: T, min_norm: T::Norm) -> Option<Self>
|
||||||
|
where T::Norm: RealField {
|
||||||
Self::try_new_and_get(value, min_norm).map(|res| res.0)
|
Self::try_new_and_get(value, min_norm).map(|res| res.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Normalize the given value and return it wrapped on a `Unit` structure and its norm.
|
/// Normalize the given vector and return it wrapped on a `Unit` structure and its norm.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new_and_get(mut value: T) -> (Self, T::RealField) {
|
pub fn new_and_get(mut value: T) -> (Self, T::Norm) {
|
||||||
let n = value.normalize_mut();
|
let n = value.norm();
|
||||||
|
value.unscale_mut(n);
|
||||||
(Unit { value: value }, n)
|
(Unit { value }, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Normalize the given value and return it wrapped on a `Unit` structure and its norm.
|
/// Normalize the given vector and return it wrapped on a `Unit` structure and its norm.
|
||||||
///
|
///
|
||||||
/// Returns `None` if the norm was smaller or equal to `min_norm`.
|
/// Returns `None` if the norm was smaller or equal to `min_norm`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn try_new_and_get(mut value: T, min_norm: T::RealField) -> Option<(Self, T::RealField)> {
|
pub fn try_new_and_get(mut value: T, min_norm: T::Norm) -> Option<(Self, T::Norm)>
|
||||||
if let Some(n) = value.try_normalize_mut(min_norm) {
|
where T::Norm: RealField {
|
||||||
Some((Unit { value: value }, n))
|
let sq_norm = value.norm_squared();
|
||||||
|
|
||||||
|
if sq_norm > min_norm * min_norm {
|
||||||
|
let n = sq_norm.simd_sqrt();
|
||||||
|
value.unscale_mut(n);
|
||||||
|
Some((Unit { value }, n))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Normalizes this value again. This is useful when repeated computations
|
/// Normalizes this vector again. This is useful when repeated computations
|
||||||
/// might cause a drift in the norm because of float inaccuracies.
|
/// might cause a drift in the norm because of float inaccuracies.
|
||||||
///
|
///
|
||||||
/// Returns the norm before re-normalization. See `.renormalize_fast` for a faster alternative
|
/// 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.
|
/// that may be slightly less accurate if `self` drifted significantly from having a unit length.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn renormalize(&mut self) -> T::RealField {
|
pub fn renormalize(&mut self) -> T::Norm {
|
||||||
self.value.normalize_mut()
|
let n = self.norm();
|
||||||
|
self.value.unscale_mut(n);
|
||||||
|
n
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Normalizes this value again using a first-order Taylor approximation.
|
/// Normalizes this vector again using a first-order Taylor approximation.
|
||||||
/// This is useful when repeated computations might cause a drift in the norm
|
/// This is useful when repeated computations might cause a drift in the norm
|
||||||
/// because of float inaccuracies.
|
/// because of float inaccuracies.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn renormalize_fast(&mut self) {
|
pub fn renormalize_fast(&mut self) {
|
||||||
let sq_norm = self.value.norm_squared();
|
let sq_norm = self.value.norm_squared();
|
||||||
let _3: T::RealField = crate::convert(3.0);
|
let _3: T::Norm = crate::convert(3.0);
|
||||||
let _0_5: T::RealField = crate::convert(0.5);
|
let _0_5: T::Norm = crate::convert(0.5);
|
||||||
self.value *= T::ComplexField::from_real(_0_5 * (_3 - sq_norm));
|
self.value.scale_mut(_0_5 * (_3 - sq_norm));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +128,7 @@ impl<T> Unit<T> {
|
||||||
/// Wraps the given value, assuming it is already normalized.
|
/// Wraps the given value, assuming it is already normalized.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new_unchecked(value: T) -> Self {
|
pub fn new_unchecked(value: T) -> Self {
|
||||||
Unit { value: value }
|
Unit { value }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wraps the given reference, assuming it is already normalized.
|
/// Wraps the given reference, assuming it is already normalized.
|
||||||
|
@ -131,7 +145,7 @@ impl<T> Unit<T> {
|
||||||
|
|
||||||
/// Retrieves the underlying value.
|
/// Retrieves the underlying value.
|
||||||
/// Deprecated: use [Unit::into_inner] instead.
|
/// Deprecated: use [Unit::into_inner] instead.
|
||||||
#[deprecated(note="use `.into_inner()` instead")]
|
#[deprecated(note = "use `.into_inner()` instead")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn unwrap(self) -> T {
|
pub fn unwrap(self) -> T {
|
||||||
self.value
|
self.value
|
||||||
|
@ -153,13 +167,14 @@ impl<T> AsRef<T> for Unit<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Conversions.
|
* Conversions.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
impl<T: NormedSpace> SubsetOf<T> for Unit<T>
|
impl<T: NormedSpace> SubsetOf<T> for Unit<T>
|
||||||
where T::Field: RelativeEq
|
where T::RealField: RelativeEq
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_superset(&self) -> T {
|
fn to_superset(&self) -> T {
|
||||||
|
@ -172,7 +187,7 @@ where T::Field: RelativeEq
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(value: &T) -> Self {
|
fn from_superset_unchecked(value: &T) -> Self {
|
||||||
Unit::new_normalize(value.clone()) // We still need to re-normalize because the condition is inexact.
|
Unit::new_normalize(value.clone()) // We still need to re-normalize because the condition is inexact.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -205,7 +220,7 @@ where T::Field: RelativeEq
|
||||||
// self.value.ulps_eq(&other.value, epsilon, max_ulps)
|
// self.value.ulps_eq(&other.value, epsilon, max_ulps)
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
*/
|
||||||
// FIXME:re-enable this impl when specialization is possible.
|
// FIXME:re-enable this impl when specialization is possible.
|
||||||
// Currently, it is disabled so that we can have a nice output for the `UnitQuaternion` display.
|
// Currently, it is disabled so that we can have a nice output for the `UnitQuaternion` display.
|
||||||
/*
|
/*
|
||||||
|
@ -217,15 +232,6 @@ impl<T: fmt::Display> fmt::Display for Unit<T> {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
impl<T: Neg> Neg for Unit<T> {
|
|
||||||
type Output = Unit<T::Output>;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn neg(self) -> Self::Output {
|
|
||||||
Self::Output::new_unchecked(-self.value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Deref for Unit<T> {
|
impl<T> Deref for Unit<T> {
|
||||||
type Target = T;
|
type Target = T;
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,12 @@ use crate::base::storage::Owned;
|
||||||
#[cfg(feature = "arbitrary")]
|
#[cfg(feature = "arbitrary")]
|
||||||
use quickcheck::{Arbitrary, Gen};
|
use quickcheck::{Arbitrary, Gen};
|
||||||
|
|
||||||
use alga::general::ComplexField;
|
|
||||||
use crate::base::Scalar;
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::dimension::{Dim, Dynamic, U2};
|
use crate::base::dimension::{Dim, Dynamic, U2};
|
||||||
|
use crate::base::Scalar;
|
||||||
use crate::base::{DefaultAllocator, MatrixN};
|
use crate::base::{DefaultAllocator, MatrixN};
|
||||||
use crate::linalg::givens::GivensRotation;
|
use crate::linalg::givens::GivensRotation;
|
||||||
|
use simba::scalar::ComplexField;
|
||||||
|
|
||||||
/// A random orthogonal matrix.
|
/// A random orthogonal matrix.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
|
|
@ -3,11 +3,11 @@ use crate::base::storage::Owned;
|
||||||
#[cfg(feature = "arbitrary")]
|
#[cfg(feature = "arbitrary")]
|
||||||
use quickcheck::{Arbitrary, Gen};
|
use quickcheck::{Arbitrary, Gen};
|
||||||
|
|
||||||
use alga::general::ComplexField;
|
|
||||||
use crate::base::Scalar;
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::dimension::{Dim, Dynamic};
|
use crate::base::dimension::{Dim, Dynamic};
|
||||||
|
use crate::base::Scalar;
|
||||||
use crate::base::{DefaultAllocator, MatrixN};
|
use crate::base::{DefaultAllocator, MatrixN};
|
||||||
|
use simba::scalar::ComplexField;
|
||||||
|
|
||||||
use crate::debug::RandomOrthogonal;
|
use crate::debug::RandomOrthogonal;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,136 @@
|
||||||
|
use crate::allocator::Allocator;
|
||||||
|
use crate::geometry::{Rotation, UnitComplex, UnitQuaternion};
|
||||||
|
use crate::{DefaultAllocator, DimName, Point, RealField, Scalar, VectorN, U2, U3};
|
||||||
|
|
||||||
|
use simba::scalar::ClosedMul;
|
||||||
|
|
||||||
|
pub trait AbstractRotation<N: Scalar, D: DimName>: PartialEq + ClosedMul + Clone {
|
||||||
|
fn identity() -> Self;
|
||||||
|
fn inverse(&self) -> Self;
|
||||||
|
fn inverse_mut(&mut self);
|
||||||
|
fn transform_vector(&self, v: &VectorN<N, D>) -> VectorN<N, D>
|
||||||
|
where DefaultAllocator: Allocator<N, D>;
|
||||||
|
fn transform_point(&self, p: &Point<N, D>) -> Point<N, D>
|
||||||
|
where DefaultAllocator: Allocator<N, D>;
|
||||||
|
fn inverse_transform_vector(&self, v: &VectorN<N, D>) -> VectorN<N, D>
|
||||||
|
where DefaultAllocator: Allocator<N, D>;
|
||||||
|
fn inverse_transform_point(&self, p: &Point<N, D>) -> Point<N, D>
|
||||||
|
where DefaultAllocator: Allocator<N, D>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField, D: DimName> AbstractRotation<N, D> for Rotation<N, D>
|
||||||
|
where DefaultAllocator: Allocator<N, D, D>
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn identity() -> Self {
|
||||||
|
Self::identity()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn inverse(&self) -> Self {
|
||||||
|
self.inverse()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn inverse_mut(&mut self) {
|
||||||
|
self.inverse_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn transform_vector(&self, v: &VectorN<N, D>) -> VectorN<N, D>
|
||||||
|
where DefaultAllocator: Allocator<N, D> {
|
||||||
|
self * v
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn transform_point(&self, p: &Point<N, D>) -> Point<N, D>
|
||||||
|
where DefaultAllocator: Allocator<N, D> {
|
||||||
|
self * p
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn inverse_transform_vector(&self, v: &VectorN<N, D>) -> VectorN<N, D>
|
||||||
|
where DefaultAllocator: Allocator<N, D> {
|
||||||
|
self.inverse_transform_vector(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn inverse_transform_point(&self, p: &Point<N, D>) -> Point<N, D>
|
||||||
|
where DefaultAllocator: Allocator<N, D> {
|
||||||
|
self.inverse_transform_point(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField> AbstractRotation<N, U3> for UnitQuaternion<N> {
|
||||||
|
#[inline]
|
||||||
|
fn identity() -> Self {
|
||||||
|
Self::identity()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn inverse(&self) -> Self {
|
||||||
|
self.inverse()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn inverse_mut(&mut self) {
|
||||||
|
self.inverse_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn transform_vector(&self, v: &VectorN<N, U3>) -> VectorN<N, U3> {
|
||||||
|
self * v
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn transform_point(&self, p: &Point<N, U3>) -> Point<N, U3> {
|
||||||
|
self * p
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn inverse_transform_vector(&self, v: &VectorN<N, U3>) -> VectorN<N, U3> {
|
||||||
|
self.inverse_transform_vector(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn inverse_transform_point(&self, p: &Point<N, U3>) -> Point<N, U3> {
|
||||||
|
self.inverse_transform_point(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField> AbstractRotation<N, U2> for UnitComplex<N> {
|
||||||
|
#[inline]
|
||||||
|
fn identity() -> Self {
|
||||||
|
Self::identity()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn inverse(&self) -> Self {
|
||||||
|
self.inverse()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn inverse_mut(&mut self) {
|
||||||
|
self.inverse_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn transform_vector(&self, v: &VectorN<N, U2>) -> VectorN<N, U2> {
|
||||||
|
self * v
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn transform_point(&self, p: &Point<N, U2>) -> Point<N, U2> {
|
||||||
|
self * p
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn inverse_transform_vector(&self, v: &VectorN<N, U2>) -> VectorN<N, U2> {
|
||||||
|
self.inverse_transform_vector(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn inverse_transform_point(&self, p: &Point<N, U2>) -> Point<N, U2> {
|
||||||
|
self.inverse_transform_point(p)
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,14 +11,13 @@ use serde::{Deserialize, Serialize};
|
||||||
#[cfg(feature = "abomonation-serialize")]
|
#[cfg(feature = "abomonation-serialize")]
|
||||||
use abomonation::Abomonation;
|
use abomonation::Abomonation;
|
||||||
|
|
||||||
use alga::general::{RealField, SubsetOf};
|
use simba::scalar::{RealField, SubsetOf};
|
||||||
use alga::linear::Rotation;
|
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1};
|
use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1};
|
||||||
use crate::base::storage::Owned;
|
use crate::base::storage::Owned;
|
||||||
use crate::base::{DefaultAllocator, MatrixN, VectorN};
|
use crate::base::{DefaultAllocator, MatrixN, VectorN};
|
||||||
use crate::geometry::{Point, Translation};
|
use crate::geometry::{AbstractRotation, Point, Translation};
|
||||||
|
|
||||||
/// A direct isometry, i.e., a rotation followed by a translation, aka. a rigid-body motion, aka. an element of a Special Euclidean (SE) group.
|
/// 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)]
|
#[repr(C)]
|
||||||
|
@ -77,7 +76,8 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: RealField + hash::Hash, D: DimName + hash::Hash, R: hash::Hash> hash::Hash for Isometry<N, D, R>
|
impl<N: RealField + hash::Hash, D: DimName + hash::Hash, R: hash::Hash> hash::Hash
|
||||||
|
for Isometry<N, D, R>
|
||||||
where
|
where
|
||||||
DefaultAllocator: Allocator<N, D>,
|
DefaultAllocator: Allocator<N, D>,
|
||||||
Owned<N, D>: hash::Hash,
|
Owned<N, D>: hash::Hash,
|
||||||
|
@ -88,14 +88,14 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: RealField, D: DimName + Copy, R: Rotation<Point<N, D>> + Copy> Copy for Isometry<N, D, R>
|
impl<N: RealField, D: DimName + Copy, R: AbstractRotation<N, D> + Copy> Copy for Isometry<N, D, R>
|
||||||
where
|
where
|
||||||
DefaultAllocator: Allocator<N, D>,
|
DefaultAllocator: Allocator<N, D>,
|
||||||
Owned<N, D>: Copy,
|
Owned<N, D>: Copy,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: RealField, D: DimName, R: Rotation<Point<N, D>> + Clone> Clone for Isometry<N, D, R>
|
impl<N: RealField, D: DimName, R: AbstractRotation<N, D> + Clone> Clone for Isometry<N, D, R>
|
||||||
where DefaultAllocator: Allocator<N, D>
|
where DefaultAllocator: Allocator<N, D>
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -104,7 +104,7 @@ where DefaultAllocator: Allocator<N, D>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: RealField, D: DimName, R: Rotation<Point<N, D>>> Isometry<N, D, R>
|
impl<N: RealField, D: DimName, R: AbstractRotation<N, D>> Isometry<N, D, R>
|
||||||
where DefaultAllocator: Allocator<N, D>
|
where DefaultAllocator: Allocator<N, D>
|
||||||
{
|
{
|
||||||
/// Creates a new isometry from its rotational and translational parts.
|
/// Creates a new isometry from its rotational and translational parts.
|
||||||
|
@ -167,7 +167,7 @@ where DefaultAllocator: Allocator<N, D>
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn inverse_mut(&mut self) {
|
pub fn inverse_mut(&mut self) {
|
||||||
self.rotation.two_sided_inverse_mut();
|
self.rotation.inverse_mut();
|
||||||
self.translation.inverse_mut();
|
self.translation.inverse_mut();
|
||||||
self.translation.vector = self.rotation.transform_vector(&self.translation.vector);
|
self.translation.vector = self.rotation.transform_vector(&self.translation.vector);
|
||||||
}
|
}
|
||||||
|
@ -208,7 +208,7 @@ where DefaultAllocator: Allocator<N, D>
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn append_rotation_mut(&mut self, r: &R) {
|
pub fn append_rotation_mut(&mut self, r: &R) {
|
||||||
self.rotation = self.rotation.append_rotation(&r);
|
self.rotation = r.clone() * self.rotation.clone();
|
||||||
self.translation.vector = r.transform_vector(&self.translation.vector);
|
self.translation.vector = r.transform_vector(&self.translation.vector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,7 +253,7 @@ where DefaultAllocator: Allocator<N, D>
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn append_rotation_wrt_center_mut(&mut self, r: &R) {
|
pub fn append_rotation_wrt_center_mut(&mut self, r: &R) {
|
||||||
self.rotation = self.rotation.append_rotation(r);
|
self.rotation = r.clone() * self.rotation.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transform the given point by this isometry.
|
/// Transform the given point by this isometry.
|
||||||
|
@ -387,14 +387,14 @@ where DefaultAllocator: Allocator<N, D>
|
||||||
|
|
||||||
impl<N: RealField, D: DimName, R> Eq for Isometry<N, D, R>
|
impl<N: RealField, D: DimName, R> Eq for Isometry<N, D, R>
|
||||||
where
|
where
|
||||||
R: Rotation<Point<N, D>> + Eq,
|
R: AbstractRotation<N, D> + Eq,
|
||||||
DefaultAllocator: Allocator<N, D>,
|
DefaultAllocator: Allocator<N, D>,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: RealField, D: DimName, R> PartialEq for Isometry<N, D, R>
|
impl<N: RealField, D: DimName, R> PartialEq for Isometry<N, D, R>
|
||||||
where
|
where
|
||||||
R: Rotation<Point<N, D>> + PartialEq,
|
R: AbstractRotation<N, D> + PartialEq,
|
||||||
DefaultAllocator: Allocator<N, D>,
|
DefaultAllocator: Allocator<N, D>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -405,7 +405,7 @@ where
|
||||||
|
|
||||||
impl<N: RealField, D: DimName, R> AbsDiffEq for Isometry<N, D, R>
|
impl<N: RealField, D: DimName, R> AbsDiffEq for Isometry<N, D, R>
|
||||||
where
|
where
|
||||||
R: Rotation<Point<N, D>> + AbsDiffEq<Epsilon = N::Epsilon>,
|
R: AbstractRotation<N, D> + AbsDiffEq<Epsilon = N::Epsilon>,
|
||||||
DefaultAllocator: Allocator<N, D>,
|
DefaultAllocator: Allocator<N, D>,
|
||||||
N::Epsilon: Copy,
|
N::Epsilon: Copy,
|
||||||
{
|
{
|
||||||
|
@ -425,7 +425,7 @@ where
|
||||||
|
|
||||||
impl<N: RealField, D: DimName, R> RelativeEq for Isometry<N, D, R>
|
impl<N: RealField, D: DimName, R> RelativeEq for Isometry<N, D, R>
|
||||||
where
|
where
|
||||||
R: Rotation<Point<N, D>> + RelativeEq<Epsilon = N::Epsilon>,
|
R: AbstractRotation<N, D> + RelativeEq<Epsilon = N::Epsilon>,
|
||||||
DefaultAllocator: Allocator<N, D>,
|
DefaultAllocator: Allocator<N, D>,
|
||||||
N::Epsilon: Copy,
|
N::Epsilon: Copy,
|
||||||
{
|
{
|
||||||
|
@ -452,7 +452,7 @@ where
|
||||||
|
|
||||||
impl<N: RealField, D: DimName, R> UlpsEq for Isometry<N, D, R>
|
impl<N: RealField, D: DimName, R> UlpsEq for Isometry<N, D, R>
|
||||||
where
|
where
|
||||||
R: Rotation<Point<N, D>> + UlpsEq<Epsilon = N::Epsilon>,
|
R: AbstractRotation<N, D> + UlpsEq<Epsilon = N::Epsilon>,
|
||||||
DefaultAllocator: Allocator<N, D>,
|
DefaultAllocator: Allocator<N, D>,
|
||||||
N::Epsilon: Copy,
|
N::Epsilon: Copy,
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,203 +0,0 @@
|
||||||
use alga::general::{
|
|
||||||
AbstractGroup, AbstractLoop, AbstractMagma, AbstractMonoid, AbstractQuasigroup,
|
|
||||||
AbstractSemigroup, Id, Identity, TwoSidedInverse, Multiplicative, RealField,
|
|
||||||
};
|
|
||||||
use alga::linear::Isometry as AlgaIsometry;
|
|
||||||
use alga::linear::{
|
|
||||||
AffineTransformation, DirectIsometry, ProjectiveTransformation, Rotation, Similarity,
|
|
||||||
Transformation,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
|
||||||
use crate::base::dimension::DimName;
|
|
||||||
use crate::base::{DefaultAllocator, VectorN};
|
|
||||||
|
|
||||||
use crate::geometry::{Isometry, Point, Translation};
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Algebraic structures.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
impl<N: RealField, D: DimName, R> Identity<Multiplicative> for Isometry<N, D, R>
|
|
||||||
where
|
|
||||||
R: Rotation<Point<N, D>>,
|
|
||||||
DefaultAllocator: Allocator<N, D>,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn identity() -> Self {
|
|
||||||
Self::identity()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField, D: DimName, R> TwoSidedInverse<Multiplicative> for Isometry<N, D, R>
|
|
||||||
where
|
|
||||||
R: Rotation<Point<N, D>>,
|
|
||||||
DefaultAllocator: Allocator<N, D>,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
#[must_use = "Did you mean to use two_sided_inverse_mut()?"]
|
|
||||||
fn two_sided_inverse(&self) -> Self {
|
|
||||||
self.inverse()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn two_sided_inverse_mut(&mut self) {
|
|
||||||
self.inverse_mut()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField, D: DimName, R> AbstractMagma<Multiplicative> for Isometry<N, D, R>
|
|
||||||
where
|
|
||||||
R: Rotation<Point<N, D>>,
|
|
||||||
DefaultAllocator: Allocator<N, D>,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn operate(&self, rhs: &Self) -> Self {
|
|
||||||
self * rhs
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_multiplicative_structures(
|
|
||||||
($($marker: ident<$operator: ident>),* $(,)*) => {$(
|
|
||||||
impl<N: RealField, D: DimName, R> $marker<$operator> for Isometry<N, D, R>
|
|
||||||
where R: Rotation<Point<N, D>>,
|
|
||||||
DefaultAllocator: Allocator<N, D> { }
|
|
||||||
)*}
|
|
||||||
);
|
|
||||||
|
|
||||||
impl_multiplicative_structures!(
|
|
||||||
AbstractSemigroup<Multiplicative>,
|
|
||||||
AbstractMonoid<Multiplicative>,
|
|
||||||
AbstractQuasigroup<Multiplicative>,
|
|
||||||
AbstractLoop<Multiplicative>,
|
|
||||||
AbstractGroup<Multiplicative>
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Transformation groups.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
impl<N: RealField, D: DimName, R> Transformation<Point<N, D>> for Isometry<N, D, R>
|
|
||||||
where
|
|
||||||
R: Rotation<Point<N, D>>,
|
|
||||||
DefaultAllocator: Allocator<N, D>,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn transform_point(&self, pt: &Point<N, D>) -> Point<N, D> {
|
|
||||||
self.transform_point(pt)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn transform_vector(&self, v: &VectorN<N, D>) -> VectorN<N, D> {
|
|
||||||
self.transform_vector(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField, D: DimName, R> ProjectiveTransformation<Point<N, D>> for Isometry<N, D, R>
|
|
||||||
where
|
|
||||||
R: Rotation<Point<N, D>>,
|
|
||||||
DefaultAllocator: Allocator<N, D>,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn inverse_transform_point(&self, pt: &Point<N, D>) -> Point<N, D> {
|
|
||||||
self.inverse_transform_point(pt)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn inverse_transform_vector(&self, v: &VectorN<N, D>) -> VectorN<N, D> {
|
|
||||||
self.inverse_transform_vector(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField, D: DimName, R> AffineTransformation<Point<N, D>> for Isometry<N, D, R>
|
|
||||||
where
|
|
||||||
R: Rotation<Point<N, D>>,
|
|
||||||
DefaultAllocator: Allocator<N, D>,
|
|
||||||
{
|
|
||||||
type Rotation = R;
|
|
||||||
type NonUniformScaling = Id;
|
|
||||||
type Translation = Translation<N, D>;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn decompose(&self) -> (Self::Translation, R, Id, R) {
|
|
||||||
(
|
|
||||||
self.translation.clone(),
|
|
||||||
self.rotation.clone(),
|
|
||||||
Id::new(),
|
|
||||||
R::identity(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn append_translation(&self, t: &Self::Translation) -> Self {
|
|
||||||
t * self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn prepend_translation(&self, t: &Self::Translation) -> Self {
|
|
||||||
self * t
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn append_rotation(&self, r: &Self::Rotation) -> Self {
|
|
||||||
let shift = r.transform_vector(&self.translation.vector);
|
|
||||||
Isometry::from_parts(Translation::from(shift), r.clone() * self.rotation.clone())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn prepend_rotation(&self, r: &Self::Rotation) -> Self {
|
|
||||||
self * r
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn append_scaling(&self, _: &Self::NonUniformScaling) -> Self {
|
|
||||||
self.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn prepend_scaling(&self, _: &Self::NonUniformScaling) -> Self {
|
|
||||||
self.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn append_rotation_wrt_point(&self, r: &Self::Rotation, p: &Point<N, D>) -> Option<Self> {
|
|
||||||
let mut res = self.clone();
|
|
||||||
res.append_rotation_wrt_point_mut(r, p);
|
|
||||||
Some(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField, D: DimName, R> Similarity<Point<N, D>> for Isometry<N, D, R>
|
|
||||||
where
|
|
||||||
R: Rotation<Point<N, D>>,
|
|
||||||
DefaultAllocator: Allocator<N, D>,
|
|
||||||
{
|
|
||||||
type Scaling = Id;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn translation(&self) -> Translation<N, D> {
|
|
||||||
self.translation.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn rotation(&self) -> R {
|
|
||||||
self.rotation.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn scaling(&self) -> Id {
|
|
||||||
Id::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! marker_impl(
|
|
||||||
($($Trait: ident),*) => {$(
|
|
||||||
impl<N: RealField, D: DimName, R> $Trait<Point<N, D>> for Isometry<N, D, R>
|
|
||||||
where R: Rotation<Point<N, D>>,
|
|
||||||
DefaultAllocator: Allocator<N, D> { }
|
|
||||||
)*}
|
|
||||||
);
|
|
||||||
|
|
||||||
marker_impl!(AlgaIsometry, DirectIsometry);
|
|
|
@ -7,19 +7,18 @@ use num::One;
|
||||||
use rand::distributions::{Distribution, Standard};
|
use rand::distributions::{Distribution, Standard};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
||||||
use alga::general::RealField;
|
use simba::scalar::RealField;
|
||||||
use alga::linear::Rotation as AlgaRotation;
|
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::dimension::{DimName, U2, U3};
|
use crate::base::dimension::{DimName, U2, U3};
|
||||||
use crate::base::{DefaultAllocator, Vector2, Vector3};
|
use crate::base::{DefaultAllocator, Vector2, Vector3};
|
||||||
|
|
||||||
use crate::geometry::{
|
use crate::geometry::{
|
||||||
Isometry, Point, Point3, Rotation, Rotation2, Rotation3, Translation, UnitComplex,
|
AbstractRotation, Isometry, Point, Point3, Rotation, Rotation2, Rotation3, Translation,
|
||||||
UnitQuaternion, Translation2, Translation3
|
Translation2, Translation3, UnitComplex, UnitQuaternion,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl<N: RealField, D: DimName, R: AlgaRotation<Point<N, D>>> Isometry<N, D, R>
|
impl<N: RealField, D: DimName, R: AbstractRotation<N, D>> Isometry<N, D, R>
|
||||||
where DefaultAllocator: Allocator<N, D>
|
where DefaultAllocator: Allocator<N, D>
|
||||||
{
|
{
|
||||||
/// Creates a new identity isometry.
|
/// Creates a new identity isometry.
|
||||||
|
@ -65,7 +64,7 @@ where DefaultAllocator: Allocator<N, D>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: RealField, D: DimName, R: AlgaRotation<Point<N, D>>> One for Isometry<N, D, R>
|
impl<N: RealField, D: DimName, R: AbstractRotation<N, D>> One for Isometry<N, D, R>
|
||||||
where DefaultAllocator: Allocator<N, D>
|
where DefaultAllocator: Allocator<N, D>
|
||||||
{
|
{
|
||||||
/// Creates a new identity isometry.
|
/// Creates a new identity isometry.
|
||||||
|
@ -77,7 +76,7 @@ where DefaultAllocator: Allocator<N, D>
|
||||||
|
|
||||||
impl<N: RealField, D: DimName, R> Distribution<Isometry<N, D, R>> for Standard
|
impl<N: RealField, D: DimName, R> Distribution<Isometry<N, D, R>> for Standard
|
||||||
where
|
where
|
||||||
R: AlgaRotation<Point<N, D>>,
|
R: AbstractRotation<N, D>,
|
||||||
Standard: Distribution<N> + Distribution<R>,
|
Standard: Distribution<N> + Distribution<R>,
|
||||||
DefaultAllocator: Allocator<N, D>,
|
DefaultAllocator: Allocator<N, D>,
|
||||||
{
|
{
|
||||||
|
@ -91,7 +90,7 @@ where
|
||||||
impl<N, D: DimName, R> Arbitrary for Isometry<N, D, R>
|
impl<N, D: DimName, R> Arbitrary for Isometry<N, D, R>
|
||||||
where
|
where
|
||||||
N: RealField + Arbitrary + Send,
|
N: RealField + Arbitrary + Send,
|
||||||
R: AlgaRotation<Point<N, D>> + Arbitrary + Send,
|
R: AbstractRotation<N, D> + Arbitrary + Send,
|
||||||
Owned<N, D>: Send,
|
Owned<N, D>: Send,
|
||||||
DefaultAllocator: Allocator<N, D>,
|
DefaultAllocator: Allocator<N, D>,
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
use alga::general::{RealField, SubsetOf, SupersetOf};
|
use simba::scalar::{RealField, SubsetOf, SupersetOf};
|
||||||
use alga::linear::Rotation;
|
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::dimension::{DimMin, DimName, DimNameAdd, DimNameSum, U1};
|
use crate::base::dimension::{DimMin, DimName, DimNameAdd, DimNameSum, U1};
|
||||||
use crate::base::{DefaultAllocator, MatrixN};
|
use crate::base::{DefaultAllocator, MatrixN};
|
||||||
|
|
||||||
use crate::geometry::{Isometry, Point, Similarity, SuperTCategoryOf, TAffine, Transform, Translation};
|
use crate::geometry::{
|
||||||
|
AbstractRotation, Isometry, Similarity, SuperTCategoryOf, TAffine, Transform, Translation,
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This file provides the following conversions:
|
* This file provides the following conversions:
|
||||||
|
@ -21,8 +22,8 @@ impl<N1, N2, D: DimName, R1, R2> SubsetOf<Isometry<N2, D, R2>> for Isometry<N1,
|
||||||
where
|
where
|
||||||
N1: RealField,
|
N1: RealField,
|
||||||
N2: RealField + SupersetOf<N1>,
|
N2: RealField + SupersetOf<N1>,
|
||||||
R1: Rotation<Point<N1, D>> + SubsetOf<R2>,
|
R1: AbstractRotation<N1, D> + SubsetOf<R2>,
|
||||||
R2: Rotation<Point<N2, D>>,
|
R2: AbstractRotation<N2, D>,
|
||||||
DefaultAllocator: Allocator<N1, D> + Allocator<N2, D>,
|
DefaultAllocator: Allocator<N1, D> + Allocator<N2, D>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -37,7 +38,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(iso: &Isometry<N2, D, R2>) -> Self {
|
fn from_superset_unchecked(iso: &Isometry<N2, D, R2>) -> Self {
|
||||||
Isometry::from_parts(
|
Isometry::from_parts(
|
||||||
iso.translation.to_subset_unchecked(),
|
iso.translation.to_subset_unchecked(),
|
||||||
iso.rotation.to_subset_unchecked(),
|
iso.rotation.to_subset_unchecked(),
|
||||||
|
@ -49,8 +50,8 @@ impl<N1, N2, D: DimName, R1, R2> SubsetOf<Similarity<N2, D, R2>> for Isometry<N1
|
||||||
where
|
where
|
||||||
N1: RealField,
|
N1: RealField,
|
||||||
N2: RealField + SupersetOf<N1>,
|
N2: RealField + SupersetOf<N1>,
|
||||||
R1: Rotation<Point<N1, D>> + SubsetOf<R2>,
|
R1: AbstractRotation<N1, D> + SubsetOf<R2>,
|
||||||
R2: Rotation<Point<N2, D>>,
|
R2: AbstractRotation<N2, D>,
|
||||||
DefaultAllocator: Allocator<N1, D> + Allocator<N2, D>,
|
DefaultAllocator: Allocator<N1, D> + Allocator<N2, D>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -64,7 +65,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(sim: &Similarity<N2, D, R2>) -> Self {
|
fn from_superset_unchecked(sim: &Similarity<N2, D, R2>) -> Self {
|
||||||
crate::convert_ref_unchecked(&sim.isometry)
|
crate::convert_ref_unchecked(&sim.isometry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,7 +75,7 @@ where
|
||||||
N1: RealField,
|
N1: RealField,
|
||||||
N2: RealField + SupersetOf<N1>,
|
N2: RealField + SupersetOf<N1>,
|
||||||
C: SuperTCategoryOf<TAffine>,
|
C: SuperTCategoryOf<TAffine>,
|
||||||
R: Rotation<Point<N1, D>>
|
R: AbstractRotation<N1, D>
|
||||||
+ SubsetOf<MatrixN<N1, DimNameSum<D, U1>>>
|
+ SubsetOf<MatrixN<N1, DimNameSum<D, U1>>>
|
||||||
+ SubsetOf<MatrixN<N2, DimNameSum<D, U1>>>,
|
+ SubsetOf<MatrixN<N2, DimNameSum<D, U1>>>,
|
||||||
D: DimNameAdd<U1> + DimMin<D, Output = D>, // needed by .is_special_orthogonal()
|
D: DimNameAdd<U1> + DimMin<D, Output = D>, // needed by .is_special_orthogonal()
|
||||||
|
@ -98,7 +99,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(t: &Transform<N2, D, C>) -> Self {
|
fn from_superset_unchecked(t: &Transform<N2, D, C>) -> Self {
|
||||||
Self::from_superset_unchecked(t.matrix())
|
Self::from_superset_unchecked(t.matrix())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,7 +108,7 @@ impl<N1, N2, D, R> SubsetOf<MatrixN<N2, DimNameSum<D, U1>>> for Isometry<N1, D,
|
||||||
where
|
where
|
||||||
N1: RealField,
|
N1: RealField,
|
||||||
N2: RealField + SupersetOf<N1>,
|
N2: RealField + SupersetOf<N1>,
|
||||||
R: Rotation<Point<N1, D>>
|
R: AbstractRotation<N1, D>
|
||||||
+ SubsetOf<MatrixN<N1, DimNameSum<D, U1>>>
|
+ SubsetOf<MatrixN<N1, DimNameSum<D, U1>>>
|
||||||
+ SubsetOf<MatrixN<N2, DimNameSum<D, U1>>>,
|
+ SubsetOf<MatrixN<N2, DimNameSum<D, U1>>>,
|
||||||
D: DimNameAdd<U1> + DimMin<D, Output = D>, // needed by .is_special_orthogonal()
|
D: DimNameAdd<U1> + DimMin<D, Output = D>, // needed by .is_special_orthogonal()
|
||||||
|
@ -139,7 +140,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(m: &MatrixN<N2, DimNameSum<D, U1>>) -> Self {
|
fn from_superset_unchecked(m: &MatrixN<N2, DimNameSum<D, U1>>) -> Self {
|
||||||
let t = m.fixed_slice::<D, U1>(0, D::dim()).into_owned();
|
let t = m.fixed_slice::<D, U1>(0, D::dim()).into_owned();
|
||||||
let t = Translation {
|
let t = Translation {
|
||||||
vector: crate::convert_unchecked(t),
|
vector: crate::convert_unchecked(t),
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
|
use num::{One, Zero};
|
||||||
use std::ops::{Div, DivAssign, Mul, MulAssign};
|
use std::ops::{Div, DivAssign, Mul, MulAssign};
|
||||||
|
|
||||||
use alga::general::RealField;
|
use simba::scalar::{ClosedAdd, ClosedMul, RealField};
|
||||||
use alga::linear::Rotation as AlgaRotation;
|
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::dimension::{DimName, U1, U3, U4};
|
use crate::base::dimension::{DimName, U1, U3, U4};
|
||||||
use crate::base::{DefaultAllocator, Unit, VectorN};
|
use crate::base::{DefaultAllocator, Unit, VectorN};
|
||||||
|
use crate::Scalar;
|
||||||
|
|
||||||
use crate::geometry::{Isometry, Point, Rotation, Translation, UnitQuaternion};
|
use crate::geometry::{AbstractRotation, Isometry, Point, Rotation, Translation, UnitQuaternion};
|
||||||
|
|
||||||
// FIXME: there are several cloning of rotations that we could probably get rid of (but we didn't
|
// 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>`
|
// yet because that would require to add a bound like `where for<'a, 'b> &'a R: Mul<&'b R, Output = R>`
|
||||||
|
@ -65,7 +66,7 @@ macro_rules! isometry_binop_impl(
|
||||||
$lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty, Output = $Output: ty;
|
$lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty, Output = $Output: ty;
|
||||||
$action: expr; $($lives: tt),*) => {
|
$action: expr; $($lives: tt),*) => {
|
||||||
impl<$($lives ,)* N: RealField, D: DimName, R> $Op<$Rhs> for $Lhs
|
impl<$($lives ,)* N: RealField, D: DimName, R> $Op<$Rhs> for $Lhs
|
||||||
where R: AlgaRotation<Point<N, D>>,
|
where R: AbstractRotation<N, D>,
|
||||||
DefaultAllocator: Allocator<N, D> {
|
DefaultAllocator: Allocator<N, D> {
|
||||||
type Output = $Output;
|
type Output = $Output;
|
||||||
|
|
||||||
|
@ -112,7 +113,7 @@ macro_rules! isometry_binop_assign_impl_all(
|
||||||
[val] => $action_val: expr;
|
[val] => $action_val: expr;
|
||||||
[ref] => $action_ref: expr;) => {
|
[ref] => $action_ref: expr;) => {
|
||||||
impl<N: RealField, D: DimName, R> $OpAssign<$Rhs> for $Lhs
|
impl<N: RealField, D: DimName, R> $OpAssign<$Rhs> for $Lhs
|
||||||
where R: AlgaRotation<Point<N, D>>,
|
where R: AbstractRotation<N, D>,
|
||||||
DefaultAllocator: Allocator<N, D> {
|
DefaultAllocator: Allocator<N, D> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn $op_assign(&mut $lhs, $rhs: $Rhs) {
|
fn $op_assign(&mut $lhs, $rhs: $Rhs) {
|
||||||
|
@ -121,7 +122,7 @@ macro_rules! isometry_binop_assign_impl_all(
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'b, N: RealField, D: DimName, R> $OpAssign<&'b $Rhs> for $Lhs
|
impl<'b, N: RealField, D: DimName, R> $OpAssign<&'b $Rhs> for $Lhs
|
||||||
where R: AlgaRotation<Point<N, D>>,
|
where R: AbstractRotation<N, D>,
|
||||||
DefaultAllocator: Allocator<N, D> {
|
DefaultAllocator: Allocator<N, D> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn $op_assign(&mut $lhs, $rhs: &'b $Rhs) {
|
fn $op_assign(&mut $lhs, $rhs: &'b $Rhs) {
|
||||||
|
@ -189,39 +190,38 @@ isometry_binop_assign_impl_all!(
|
||||||
|
|
||||||
// Isometry ×= R
|
// Isometry ×= R
|
||||||
// Isometry ÷= R
|
// Isometry ÷= R
|
||||||
isometry_binop_assign_impl_all!(
|
md_assign_impl_all!(
|
||||||
MulAssign, mul_assign;
|
MulAssign, mul_assign where N: RealField;
|
||||||
self: Isometry<N, D, R>, rhs: R;
|
(D, U1), (D, D) for D: DimName;
|
||||||
|
self: Isometry<N, D, Rotation<N, D>>, rhs: Rotation<N, D>;
|
||||||
[val] => self.rotation *= rhs;
|
[val] => self.rotation *= rhs;
|
||||||
[ref] => self.rotation *= rhs.clone();
|
[ref] => self.rotation *= rhs.clone();
|
||||||
);
|
);
|
||||||
|
|
||||||
isometry_binop_assign_impl_all!(
|
md_assign_impl_all!(
|
||||||
DivAssign, div_assign;
|
DivAssign, div_assign where N: RealField;
|
||||||
self: Isometry<N, D, R>, rhs: R;
|
(D, U1), (D, D) for D: DimName;
|
||||||
|
self: Isometry<N, D, Rotation<N, D>>, rhs: Rotation<N, D>;
|
||||||
// FIXME: don't invert explicitly?
|
// FIXME: don't invert explicitly?
|
||||||
[val] => *self *= rhs.two_sided_inverse();
|
[val] => *self *= rhs.inverse();
|
||||||
[ref] => *self *= rhs.two_sided_inverse();
|
[ref] => *self *= rhs.inverse();
|
||||||
);
|
);
|
||||||
|
|
||||||
// Isometry × R
|
md_assign_impl_all!(
|
||||||
// Isometry ÷ R
|
MulAssign, mul_assign where N: RealField;
|
||||||
isometry_binop_impl_all!(
|
(U3, U3), (U3, U3) for;
|
||||||
Mul, mul;
|
self: Isometry<N, U3, UnitQuaternion<N>>, rhs: UnitQuaternion<N>;
|
||||||
self: Isometry<N, D, R>, rhs: R, Output = Isometry<N, D, R>;
|
[val] => self.rotation *= rhs;
|
||||||
[val val] => Isometry::from_parts(self.translation, self.rotation * rhs);
|
[ref] => self.rotation *= rhs.clone();
|
||||||
[ref val] => Isometry::from_parts(self.translation.clone(), self.rotation.clone() * rhs); // FIXME: do not clone.
|
|
||||||
[val ref] => Isometry::from_parts(self.translation, self.rotation * rhs.clone());
|
|
||||||
[ref ref] => Isometry::from_parts(self.translation.clone(), self.rotation.clone() * rhs.clone());
|
|
||||||
);
|
);
|
||||||
|
|
||||||
isometry_binop_impl_all!(
|
md_assign_impl_all!(
|
||||||
Div, div;
|
DivAssign, div_assign where N: RealField;
|
||||||
self: Isometry<N, D, R>, rhs: R, Output = Isometry<N, D, R>;
|
(U3, U3), (U3, U3) for;
|
||||||
[val val] => Isometry::from_parts(self.translation, self.rotation / rhs);
|
self: Isometry<N, U3, UnitQuaternion<N>>, rhs: UnitQuaternion<N>;
|
||||||
[ref val] => Isometry::from_parts(self.translation.clone(), self.rotation.clone() / rhs);
|
// FIXME: don't invert explicitly?
|
||||||
[val ref] => Isometry::from_parts(self.translation, self.rotation / rhs.clone());
|
[val] => *self *= rhs.inverse();
|
||||||
[ref ref] => Isometry::from_parts(self.translation.clone(), self.rotation.clone() / rhs.clone());
|
[ref] => *self *= rhs.inverse();
|
||||||
);
|
);
|
||||||
|
|
||||||
// Isometry × Point
|
// Isometry × Point
|
||||||
|
@ -357,6 +357,18 @@ isometry_from_composition_impl_all!(
|
||||||
[ref ref] => Isometry::from_parts(Translation::from( self * &right.vector), self.clone());
|
[ref ref] => Isometry::from_parts(Translation::from( self * &right.vector), self.clone());
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Isometry × Rotation
|
||||||
|
isometry_from_composition_impl_all!(
|
||||||
|
Mul, mul;
|
||||||
|
(D, D), (D, U1) for D: DimName;
|
||||||
|
self: Isometry<N, D, Rotation<N, D>>, rhs: Rotation<N, D>,
|
||||||
|
Output = Isometry<N, D, Rotation<N, D>>;
|
||||||
|
[val val] => Isometry::from_parts(self.translation, self.rotation * rhs);
|
||||||
|
[ref val] => Isometry::from_parts(self.translation.clone(), self.rotation.clone() * rhs); // FIXME: do not clone.
|
||||||
|
[val ref] => Isometry::from_parts(self.translation, self.rotation * rhs.clone());
|
||||||
|
[ref ref] => Isometry::from_parts(self.translation.clone(), self.rotation.clone() * rhs.clone());
|
||||||
|
);
|
||||||
|
|
||||||
// Rotation × Isometry
|
// Rotation × Isometry
|
||||||
isometry_from_composition_impl_all!(
|
isometry_from_composition_impl_all!(
|
||||||
Mul, mul;
|
Mul, mul;
|
||||||
|
@ -372,6 +384,18 @@ isometry_from_composition_impl_all!(
|
||||||
};
|
};
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Isometry ÷ Rotation
|
||||||
|
isometry_from_composition_impl_all!(
|
||||||
|
Div, div;
|
||||||
|
(D, D), (D, U1) for D: DimName;
|
||||||
|
self: Isometry<N, D, Rotation<N, D>>, rhs: Rotation<N, D>,
|
||||||
|
Output = Isometry<N, D, Rotation<N, D>>;
|
||||||
|
[val val] => Isometry::from_parts(self.translation, self.rotation / rhs);
|
||||||
|
[ref val] => Isometry::from_parts(self.translation.clone(), self.rotation.clone() / rhs); // FIXME: do not clone.
|
||||||
|
[val ref] => Isometry::from_parts(self.translation, self.rotation / rhs.clone());
|
||||||
|
[ref ref] => Isometry::from_parts(self.translation.clone(), self.rotation.clone() / rhs.clone());
|
||||||
|
);
|
||||||
|
|
||||||
// Rotation ÷ Isometry
|
// Rotation ÷ Isometry
|
||||||
isometry_from_composition_impl_all!(
|
isometry_from_composition_impl_all!(
|
||||||
Div, div;
|
Div, div;
|
||||||
|
@ -385,6 +409,18 @@ isometry_from_composition_impl_all!(
|
||||||
[ref ref] => self * right.inverse();
|
[ref ref] => self * right.inverse();
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Isometry × UnitQuaternion
|
||||||
|
isometry_from_composition_impl_all!(
|
||||||
|
Mul, mul;
|
||||||
|
(U4, U1), (U3, U1);
|
||||||
|
self: Isometry<N, U3, UnitQuaternion<N>>, rhs: UnitQuaternion<N>,
|
||||||
|
Output = Isometry<N, U3, UnitQuaternion<N>>;
|
||||||
|
[val val] => Isometry::from_parts(self.translation, self.rotation * rhs);
|
||||||
|
[ref val] => Isometry::from_parts(self.translation.clone(), self.rotation.clone() * rhs); // FIXME: do not clone.
|
||||||
|
[val ref] => Isometry::from_parts(self.translation, self.rotation * rhs.clone());
|
||||||
|
[ref ref] => Isometry::from_parts(self.translation.clone(), self.rotation.clone() * rhs.clone());
|
||||||
|
);
|
||||||
|
|
||||||
// UnitQuaternion × Isometry
|
// UnitQuaternion × Isometry
|
||||||
isometry_from_composition_impl_all!(
|
isometry_from_composition_impl_all!(
|
||||||
Mul, mul;
|
Mul, mul;
|
||||||
|
@ -400,6 +436,18 @@ isometry_from_composition_impl_all!(
|
||||||
};
|
};
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Isometry ÷ UnitQuaternion
|
||||||
|
isometry_from_composition_impl_all!(
|
||||||
|
Div, div;
|
||||||
|
(U4, U1), (U3, U1);
|
||||||
|
self: Isometry<N, U3, UnitQuaternion<N>>, rhs: UnitQuaternion<N>,
|
||||||
|
Output = Isometry<N, U3, UnitQuaternion<N>>;
|
||||||
|
[val val] => Isometry::from_parts(self.translation, self.rotation / rhs);
|
||||||
|
[ref val] => Isometry::from_parts(self.translation.clone(), self.rotation.clone() / rhs); // FIXME: do not clone.
|
||||||
|
[val ref] => Isometry::from_parts(self.translation, self.rotation / rhs.clone());
|
||||||
|
[ref ref] => Isometry::from_parts(self.translation.clone(), self.rotation.clone() / rhs.clone());
|
||||||
|
);
|
||||||
|
|
||||||
// UnitQuaternion ÷ Isometry
|
// UnitQuaternion ÷ Isometry
|
||||||
isometry_from_composition_impl_all!(
|
isometry_from_composition_impl_all!(
|
||||||
Div, div;
|
Div, div;
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
use simba::simd::SimdValue;
|
||||||
|
|
||||||
|
use crate::base::allocator::Allocator;
|
||||||
|
use crate::base::dimension::DimName;
|
||||||
|
use crate::base::{DefaultAllocator, Scalar};
|
||||||
|
use crate::RealField;
|
||||||
|
|
||||||
|
use crate::geometry::{AbstractRotation, Isometry, Translation};
|
||||||
|
|
||||||
|
impl<N: RealField, D: DimName, R> SimdValue for Isometry<N, D, R>
|
||||||
|
where
|
||||||
|
N::Element: Scalar,
|
||||||
|
R: SimdValue<SimdBool = N::SimdBool> + AbstractRotation<N, D>,
|
||||||
|
R::Element: AbstractRotation<N, D>,
|
||||||
|
DefaultAllocator: Allocator<N, D>,
|
||||||
|
{
|
||||||
|
type Element = Isometry<N::Element, D, R::Element>;
|
||||||
|
type SimdBool = N::SimdBool;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn lanes() -> usize {
|
||||||
|
N::lanes()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn splat(val: Self::Element) -> Self {
|
||||||
|
Isometry::from_parts(Translation::splat(val.translation), R::splat(val.rotation))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn extract(&self, i: usize) -> Self::Element {
|
||||||
|
Isometry::from_parts(self.translation.extract(i), self.rotation.extract(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn extract_unchecked(&self, i: usize) -> Self::Element {
|
||||||
|
Isometry::from_parts(
|
||||||
|
self.translation.extract_unchecked(i),
|
||||||
|
self.rotation.extract_unchecked(i),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn replace(&mut self, i: usize, val: Self::Element) {
|
||||||
|
self.translation.replace(i, val.translation);
|
||||||
|
self.rotation.replace(i, val.rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn replace_unchecked(&mut self, i: usize, val: Self::Element) {
|
||||||
|
self.translation.replace_unchecked(i, val.translation);
|
||||||
|
self.rotation.replace_unchecked(i, val.rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn select(self, cond: Self::SimdBool, other: Self) -> Self {
|
||||||
|
Isometry::from_parts(
|
||||||
|
self.translation.select(cond, other.translation),
|
||||||
|
self.rotation.select(cond, other.rotation),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,34 +3,36 @@
|
||||||
|
|
||||||
mod op_macros;
|
mod op_macros;
|
||||||
|
|
||||||
|
mod abstract_rotation;
|
||||||
|
|
||||||
mod point;
|
mod point;
|
||||||
mod point_alga;
|
|
||||||
mod point_alias;
|
mod point_alias;
|
||||||
mod point_construction;
|
mod point_construction;
|
||||||
mod point_conversion;
|
mod point_conversion;
|
||||||
mod point_coordinates;
|
mod point_coordinates;
|
||||||
mod point_ops;
|
mod point_ops;
|
||||||
|
mod point_simba;
|
||||||
|
|
||||||
mod rotation;
|
mod rotation;
|
||||||
mod rotation_alga; // FIXME: implement Rotation methods.
|
|
||||||
mod rotation_alias;
|
mod rotation_alias;
|
||||||
mod rotation_construction;
|
mod rotation_construction;
|
||||||
mod rotation_conversion;
|
mod rotation_conversion;
|
||||||
mod rotation_ops;
|
mod rotation_ops;
|
||||||
|
mod rotation_simba; // FIXME: implement Rotation methods.
|
||||||
mod rotation_specialization;
|
mod rotation_specialization;
|
||||||
|
|
||||||
mod quaternion;
|
mod quaternion;
|
||||||
mod quaternion_alga;
|
|
||||||
mod quaternion_construction;
|
mod quaternion_construction;
|
||||||
mod quaternion_conversion;
|
mod quaternion_conversion;
|
||||||
mod quaternion_coordinates;
|
mod quaternion_coordinates;
|
||||||
mod quaternion_ops;
|
mod quaternion_ops;
|
||||||
|
mod quaternion_simba;
|
||||||
|
|
||||||
mod unit_complex;
|
mod unit_complex;
|
||||||
mod unit_complex_alga;
|
|
||||||
mod unit_complex_construction;
|
mod unit_complex_construction;
|
||||||
mod unit_complex_conversion;
|
mod unit_complex_conversion;
|
||||||
mod unit_complex_ops;
|
mod unit_complex_ops;
|
||||||
|
mod unit_complex_simba;
|
||||||
|
|
||||||
mod translation;
|
mod translation;
|
||||||
mod translation_alga;
|
mod translation_alga;
|
||||||
|
@ -41,33 +43,35 @@ mod translation_coordinates;
|
||||||
mod translation_ops;
|
mod translation_ops;
|
||||||
|
|
||||||
mod isometry;
|
mod isometry;
|
||||||
mod isometry_alga;
|
|
||||||
mod isometry_alias;
|
mod isometry_alias;
|
||||||
mod isometry_construction;
|
mod isometry_construction;
|
||||||
mod isometry_conversion;
|
mod isometry_conversion;
|
||||||
mod isometry_ops;
|
mod isometry_ops;
|
||||||
|
mod isometry_simba;
|
||||||
|
|
||||||
mod similarity;
|
mod similarity;
|
||||||
mod similarity_alga;
|
|
||||||
mod similarity_alias;
|
mod similarity_alias;
|
||||||
mod similarity_construction;
|
mod similarity_construction;
|
||||||
mod similarity_conversion;
|
mod similarity_conversion;
|
||||||
mod similarity_ops;
|
mod similarity_ops;
|
||||||
|
mod similarity_simba;
|
||||||
|
|
||||||
mod swizzle;
|
mod swizzle;
|
||||||
|
|
||||||
mod transform;
|
mod transform;
|
||||||
mod transform_alga;
|
|
||||||
mod transform_alias;
|
mod transform_alias;
|
||||||
mod transform_construction;
|
mod transform_construction;
|
||||||
mod transform_conversion;
|
mod transform_conversion;
|
||||||
mod transform_ops;
|
mod transform_ops;
|
||||||
|
mod transform_simba;
|
||||||
|
|
||||||
mod reflection;
|
mod reflection;
|
||||||
|
|
||||||
mod orthographic;
|
mod orthographic;
|
||||||
mod perspective;
|
mod perspective;
|
||||||
|
|
||||||
|
pub use self::abstract_rotation::AbstractRotation;
|
||||||
|
|
||||||
pub use self::point::*;
|
pub use self::point::*;
|
||||||
pub use self::point_alias::*;
|
pub use self::point_alias::*;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#![macro_use]
|
#![macro_use]
|
||||||
|
|
||||||
|
|
||||||
// FIXME: merge with `md_impl`.
|
// FIXME: merge with `md_impl`.
|
||||||
/// Macro for the implementation of multiplication and division.
|
/// Macro for the implementation of multiplication and division.
|
||||||
macro_rules! md_impl(
|
macro_rules! md_impl(
|
||||||
|
@ -88,7 +87,7 @@ macro_rules! md_assign_impl(
|
||||||
// Operator, operator method, and scalar bounds.
|
// Operator, operator method, and scalar bounds.
|
||||||
$Op: ident, $op: ident $(where N: $($ScalarBounds: ident),*)*;
|
$Op: ident, $op: ident $(where N: $($ScalarBounds: ident),*)*;
|
||||||
// Storage dimensions, and dimension bounds.
|
// Storage dimensions, and dimension bounds.
|
||||||
($R1: ty, $C1: ty),($R2: ty, $C2: ty) for $($Dims: ident: $DimsBound: ident $(<$($BoundParam: ty),*>)*),+
|
($R1: ty, $C1: ty),($R2: ty, $C2: ty) for $($Dims: ident: $DimsBound: ident $(<$($BoundParam: ty),*>)*),*
|
||||||
// [Optional] Extra allocator bounds.
|
// [Optional] Extra allocator bounds.
|
||||||
$(where $ConstraintType: ty: $ConstraintBound: ident $(<$($ConstraintBoundParams: ty $( = $EqBound: ty )*),*>)* )*;
|
$(where $ConstraintType: ty: $ConstraintBound: ident $(<$($ConstraintBoundParams: ty $( = $EqBound: ty )*),*>)* )*;
|
||||||
// Argument identifiers and types.
|
// Argument identifiers and types.
|
||||||
|
@ -116,7 +115,7 @@ macro_rules! md_assign_impl_all(
|
||||||
// Operator, operator method, and scalar bounds.
|
// Operator, operator method, and scalar bounds.
|
||||||
$Op: ident, $op: ident $(where N: $($ScalarBounds: ident),*)*;
|
$Op: ident, $op: ident $(where N: $($ScalarBounds: ident),*)*;
|
||||||
// Storage dimensions, and dimension bounds.
|
// Storage dimensions, and dimension bounds.
|
||||||
($R1: ty, $C1: ty),($R2: ty, $C2: ty) for $($Dims: ident: $DimsBound: ident $(<$($BoundParam: ty),*>)*),+
|
($R1: ty, $C1: ty),($R2: ty, $C2: ty) for $($Dims: ident: $DimsBound: ident $(<$($BoundParam: ty),*>)*),*
|
||||||
// [Optional] Extra allocator bounds.
|
// [Optional] Extra allocator bounds.
|
||||||
$(where $ConstraintType: ty: $ConstraintBound: ident$(<$($ConstraintBoundParams: ty $( = $EqBound: ty )*),*>)* )*;
|
$(where $ConstraintType: ty: $ConstraintBound: ident$(<$($ConstraintBoundParams: ty $( = $EqBound: ty )*),*>)* )*;
|
||||||
// Argument identifiers and types.
|
// Argument identifiers and types.
|
||||||
|
@ -126,14 +125,14 @@ macro_rules! md_assign_impl_all(
|
||||||
[ref] => $action_ref: expr;) => {
|
[ref] => $action_ref: expr;) => {
|
||||||
md_assign_impl!(
|
md_assign_impl!(
|
||||||
$Op, $op $(where N: $($ScalarBounds),*)*;
|
$Op, $op $(where N: $($ScalarBounds),*)*;
|
||||||
($R1, $C1),($R2, $C2) for $($Dims: $DimsBound $(<$($BoundParam),*>)*),+
|
($R1, $C1),($R2, $C2) for $($Dims: $DimsBound $(<$($BoundParam),*>)*),*
|
||||||
$(where $ConstraintType: $ConstraintBound $(<$($ConstraintBoundParams $( = $EqBound )*),*>)*)*;
|
$(where $ConstraintType: $ConstraintBound $(<$($ConstraintBoundParams $( = $EqBound )*),*>)*)*;
|
||||||
$lhs: $Lhs, $rhs: $Rhs;
|
$lhs: $Lhs, $rhs: $Rhs;
|
||||||
$action_val; );
|
$action_val; );
|
||||||
|
|
||||||
md_assign_impl!(
|
md_assign_impl!(
|
||||||
$Op, $op $(where N: $($ScalarBounds),*)*;
|
$Op, $op $(where N: $($ScalarBounds),*)*;
|
||||||
($R1, $C1),($R2, $C2) for $($Dims: $DimsBound $(<$($BoundParam),*>)*),+
|
($R1, $C1),($R2, $C2) for $($Dims: $DimsBound $(<$($BoundParam),*>)*),*
|
||||||
$(where $ConstraintType: $ConstraintBound $(<$($ConstraintBoundParams $( = $EqBound )*),*>)*)*;
|
$(where $ConstraintType: $ConstraintBound $(<$($ConstraintBoundParams $( = $EqBound )*),*>)*)*;
|
||||||
$lhs: $Lhs, $rhs: &'b $Rhs;
|
$lhs: $Lhs, $rhs: &'b $Rhs;
|
||||||
$action_ref; 'b);
|
$action_ref; 'b);
|
||||||
|
|
|
@ -7,7 +7,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
use alga::general::RealField;
|
use simba::scalar::RealField;
|
||||||
|
|
||||||
use crate::base::dimension::U3;
|
use crate::base::dimension::U3;
|
||||||
use crate::base::helper;
|
use crate::base::helper;
|
||||||
|
@ -286,7 +286,7 @@ impl<N: RealField> Orthographic3<N> {
|
||||||
|
|
||||||
/// Retrieves the underlying homogeneous matrix.
|
/// Retrieves the underlying homogeneous matrix.
|
||||||
/// Deprecated: Use [Orthographic3::into_inner] instead.
|
/// Deprecated: Use [Orthographic3::into_inner] instead.
|
||||||
#[deprecated(note="use `.into_inner()` instead")]
|
#[deprecated(note = "use `.into_inner()` instead")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn unwrap(self) -> Matrix4<N> {
|
pub fn unwrap(self) -> Matrix4<N> {
|
||||||
self.matrix
|
self.matrix
|
||||||
|
|
|
@ -8,7 +8,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
use alga::general::RealField;
|
use simba::scalar::RealField;
|
||||||
|
|
||||||
use crate::base::dimension::U3;
|
use crate::base::dimension::U3;
|
||||||
use crate::base::helper;
|
use crate::base::helper;
|
||||||
|
@ -147,7 +147,7 @@ impl<N: RealField> Perspective3<N> {
|
||||||
|
|
||||||
/// Retrieves the underlying homogeneous matrix.
|
/// Retrieves the underlying homogeneous matrix.
|
||||||
/// Deprecated: Use [Perspective3::into_inner] instead.
|
/// Deprecated: Use [Perspective3::into_inner] instead.
|
||||||
#[deprecated(note="use `.into_inner()` instead")]
|
#[deprecated(note = "use `.into_inner()` instead")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn unwrap(self) -> Matrix4<N> {
|
pub fn unwrap(self) -> Matrix4<N> {
|
||||||
self.matrix
|
self.matrix
|
||||||
|
@ -170,7 +170,8 @@ impl<N: RealField> Perspective3<N> {
|
||||||
pub fn znear(&self) -> N {
|
pub fn znear(&self) -> N {
|
||||||
let ratio = (-self.matrix[(2, 2)] + N::one()) / (-self.matrix[(2, 2)] - N::one());
|
let ratio = (-self.matrix[(2, 2)] + N::one()) / (-self.matrix[(2, 2)] - N::one());
|
||||||
|
|
||||||
self.matrix[(2, 3)] / (ratio * crate::convert(2.0)) - self.matrix[(2, 3)] / crate::convert(2.0)
|
self.matrix[(2, 3)] / (ratio * crate::convert(2.0))
|
||||||
|
- self.matrix[(2, 3)] / crate::convert(2.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the far plane offset of the view frustum.
|
/// Gets the far plane offset of the view frustum.
|
||||||
|
|
|
@ -1,83 +0,0 @@
|
||||||
use alga::general::{Field, JoinSemilattice, Lattice, MeetSemilattice, RealField};
|
|
||||||
use alga::linear::{AffineSpace, EuclideanSpace};
|
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
|
||||||
use crate::base::dimension::DimName;
|
|
||||||
use crate::base::{DefaultAllocator, Scalar, VectorN};
|
|
||||||
|
|
||||||
use crate::geometry::Point;
|
|
||||||
|
|
||||||
impl<N: Scalar + Field, D: DimName> AffineSpace for Point<N, D>
|
|
||||||
where
|
|
||||||
N: Scalar + Field,
|
|
||||||
DefaultAllocator: Allocator<N, D>,
|
|
||||||
{
|
|
||||||
type Translation = VectorN<N, D>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField, D: DimName> EuclideanSpace for Point<N, D>
|
|
||||||
where DefaultAllocator: Allocator<N, D>
|
|
||||||
{
|
|
||||||
type Coordinates = VectorN<N, D>;
|
|
||||||
type RealField = N;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn origin() -> Self {
|
|
||||||
Self::origin()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn coordinates(&self) -> Self::Coordinates {
|
|
||||||
self.coords.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn from_coordinates(coords: Self::Coordinates) -> Self {
|
|
||||||
Self::from(coords)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn scale_by(&self, n: N) -> Self {
|
|
||||||
self * n
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Ordering
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
impl<N, D: DimName> MeetSemilattice for Point<N, D>
|
|
||||||
where
|
|
||||||
N: Scalar + MeetSemilattice,
|
|
||||||
DefaultAllocator: Allocator<N, D>,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn meet(&self, other: &Self) -> Self {
|
|
||||||
Self::from(self.coords.meet(&other.coords))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N, D: DimName> JoinSemilattice for Point<N, D>
|
|
||||||
where
|
|
||||||
N: Scalar + JoinSemilattice,
|
|
||||||
DefaultAllocator: Allocator<N, D>,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn join(&self, other: &Self) -> Self {
|
|
||||||
Self::from(self.coords.join(&other.coords))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N, D: DimName> Lattice for Point<N, D>
|
|
||||||
where
|
|
||||||
N: Scalar + Lattice,
|
|
||||||
DefaultAllocator: Allocator<N, D>,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn meet_join(&self, other: &Self) -> (Self, Self) {
|
|
||||||
let (meet, join) = self.coords.meet_join(&other.coords);
|
|
||||||
|
|
||||||
(Self::from(meet), Self::from(join))
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,10 +5,10 @@ use num::{Bounded, One, Zero};
|
||||||
use rand::distributions::{Distribution, Standard};
|
use rand::distributions::{Distribution, Standard};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
||||||
use alga::general::ClosedDiv;
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1, U2, U3, U4, U5, U6};
|
use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1, U2, U3, U4, U5, U6};
|
||||||
use crate::base::{DefaultAllocator, Scalar, VectorN};
|
use crate::base::{DefaultAllocator, Scalar, VectorN};
|
||||||
|
use simba::scalar::ClosedDiv;
|
||||||
|
|
||||||
use crate::geometry::Point;
|
use crate::geometry::Point;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use alga::general::{ClosedDiv, SubsetOf, SupersetOf};
|
|
||||||
use num::{One, Zero};
|
use num::{One, Zero};
|
||||||
|
use simba::scalar::{ClosedDiv, SubsetOf, SupersetOf};
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1};
|
use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1};
|
||||||
|
@ -44,7 +44,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(m: &Point<N2, D>) -> Self {
|
fn from_superset_unchecked(m: &Point<N2, D>) -> Self {
|
||||||
Self::from(Matrix::from_superset_unchecked(&m.coords))
|
Self::from(Matrix::from_superset_unchecked(&m.coords))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,10 +71,10 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(v: &VectorN<N2, DimNameSum<D, U1>>) -> Self {
|
fn from_superset_unchecked(v: &VectorN<N2, DimNameSum<D, U1>>) -> Self {
|
||||||
let coords = v.fixed_slice::<D, U1>(0, 0) / v[D::dim()].inlined_clone();
|
let coords = v.fixed_slice::<D, U1>(0, 0) / v[D::dim()].inlined_clone();
|
||||||
Self {
|
Self {
|
||||||
coords: crate::convert_unchecked(coords)
|
coords: crate::convert_unchecked(coords),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,13 +142,10 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: Scalar, D: DimName> From<VectorN<N, D>> for Point<N, D>
|
impl<N: Scalar, D: DimName> From<VectorN<N, D>> for Point<N, D>
|
||||||
where
|
where DefaultAllocator: Allocator<N, D>
|
||||||
DefaultAllocator: Allocator<N, D>,
|
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(coords: VectorN<N, D>) -> Self {
|
fn from(coords: VectorN<N, D>) -> Self {
|
||||||
Point {
|
Point { coords }
|
||||||
coords
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,12 @@ use std::ops::{
|
||||||
Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign,
|
Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign,
|
||||||
};
|
};
|
||||||
|
|
||||||
use alga::general::{ClosedAdd, ClosedDiv, ClosedMul, ClosedNeg, ClosedSub};
|
use simba::scalar::{ClosedAdd, ClosedDiv, ClosedMul, ClosedNeg, ClosedSub};
|
||||||
|
|
||||||
use crate::base::allocator::{Allocator, SameShapeAllocator};
|
use crate::base::allocator::{Allocator, SameShapeAllocator};
|
||||||
use crate::base::constraint::{AreMultipliable, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint};
|
use crate::base::constraint::{
|
||||||
|
AreMultipliable, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint,
|
||||||
|
};
|
||||||
use crate::base::dimension::{Dim, DimName, U1};
|
use crate::base::dimension::{Dim, DimName, U1};
|
||||||
use crate::base::storage::Storage;
|
use crate::base::storage::Storage;
|
||||||
use crate::base::{DefaultAllocator, Matrix, Scalar, Vector, VectorSum};
|
use crate::base::{DefaultAllocator, Matrix, Scalar, Vector, VectorSum};
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
use simba::simd::SimdValue;
|
||||||
|
|
||||||
|
use crate::base::allocator::Allocator;
|
||||||
|
use crate::base::dimension::DimName;
|
||||||
|
use crate::base::{DefaultAllocator, Scalar, VectorN};
|
||||||
|
|
||||||
|
use crate::geometry::Point;
|
||||||
|
|
||||||
|
impl<N: Scalar + SimdValue, D: DimName> SimdValue for Point<N, D>
|
||||||
|
where
|
||||||
|
N::Element: Scalar,
|
||||||
|
DefaultAllocator: Allocator<N, D> + Allocator<N::Element, D>,
|
||||||
|
{
|
||||||
|
type Element = Point<N::Element, D>;
|
||||||
|
type SimdBool = N::SimdBool;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn lanes() -> usize {
|
||||||
|
N::lanes()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn splat(val: Self::Element) -> Self {
|
||||||
|
VectorN::splat(val.coords).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn extract(&self, i: usize) -> Self::Element {
|
||||||
|
self.coords.extract(i).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn extract_unchecked(&self, i: usize) -> Self::Element {
|
||||||
|
self.coords.extract_unchecked(i).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn replace(&mut self, i: usize, val: Self::Element) {
|
||||||
|
self.coords.replace(i, val.coords)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn replace_unchecked(&mut self, i: usize, val: Self::Element) {
|
||||||
|
self.coords.replace_unchecked(i, val.coords)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn select(self, cond: Self::SimdBool, other: Self) -> Self {
|
||||||
|
self.coords.select(cond, other.coords).into()
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,11 +13,12 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||||
#[cfg(feature = "abomonation-serialize")]
|
#[cfg(feature = "abomonation-serialize")]
|
||||||
use abomonation::Abomonation;
|
use abomonation::Abomonation;
|
||||||
|
|
||||||
use alga::general::RealField;
|
use simba::scalar::RealField;
|
||||||
|
use simba::simd::SimdRealField;
|
||||||
|
|
||||||
use crate::base::dimension::{U1, U3, U4};
|
use crate::base::dimension::{U1, U3, U4};
|
||||||
use crate::base::storage::{CStride, RStride};
|
use crate::base::storage::{CStride, RStride};
|
||||||
use crate::base::{Matrix3, Matrix4, MatrixSlice, MatrixSliceMut, Unit, Vector3, Vector4};
|
use crate::base::{Matrix3, Matrix4, MatrixSlice, MatrixSliceMut, Normed, Unit, Vector3, Vector4};
|
||||||
|
|
||||||
use crate::geometry::{Point3, Rotation};
|
use crate::geometry::{Point3, Rotation};
|
||||||
|
|
||||||
|
@ -25,13 +26,13 @@ use crate::geometry::{Point3, Rotation};
|
||||||
/// that may be used as a rotation.
|
/// that may be used as a rotation.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Quaternion<N: RealField> {
|
pub struct Quaternion<N: SimdRealField> {
|
||||||
/// This quaternion as a 4D vector of coordinates in the `[ x, y, z, w ]` storage order.
|
/// This quaternion as a 4D vector of coordinates in the `[ x, y, z, w ]` storage order.
|
||||||
pub coords: Vector4<N>,
|
pub coords: Vector4<N>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "abomonation-serialize")]
|
#[cfg(feature = "abomonation-serialize")]
|
||||||
impl<N: RealField> Abomonation for Quaternion<N>
|
impl<N: SimdRealField> Abomonation for Quaternion<N>
|
||||||
where Vector4<N>: Abomonation
|
where Vector4<N>: Abomonation
|
||||||
{
|
{
|
||||||
unsafe fn entomb<W: Write>(&self, writer: &mut W) -> IOResult<()> {
|
unsafe fn entomb<W: Write>(&self, writer: &mut W) -> IOResult<()> {
|
||||||
|
@ -47,9 +48,9 @@ where Vector4<N>: Abomonation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: RealField + Eq> Eq for Quaternion<N> {}
|
impl<N: SimdRealField + Eq> Eq for Quaternion<N> {}
|
||||||
|
|
||||||
impl<N: RealField> PartialEq for Quaternion<N> {
|
impl<N: SimdRealField> PartialEq for Quaternion<N> {
|
||||||
fn eq(&self, rhs: &Self) -> bool {
|
fn eq(&self, rhs: &Self) -> bool {
|
||||||
self.coords == rhs.coords ||
|
self.coords == rhs.coords ||
|
||||||
// Account for the double-covering of S², i.e. q = -q
|
// Account for the double-covering of S², i.e. q = -q
|
||||||
|
@ -57,15 +58,15 @@ impl<N: RealField> PartialEq for Quaternion<N> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: RealField + hash::Hash> hash::Hash for Quaternion<N> {
|
impl<N: SimdRealField + hash::Hash> hash::Hash for Quaternion<N> {
|
||||||
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
||||||
self.coords.hash(state)
|
self.coords.hash(state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: RealField> Copy for Quaternion<N> {}
|
impl<N: SimdRealField> Copy for Quaternion<N> {}
|
||||||
|
|
||||||
impl<N: RealField> Clone for Quaternion<N> {
|
impl<N: SimdRealField> Clone for Quaternion<N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Self::from(self.coords.clone())
|
Self::from(self.coords.clone())
|
||||||
|
@ -73,7 +74,7 @@ impl<N: RealField> Clone for Quaternion<N> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "serde-serialize")]
|
#[cfg(feature = "serde-serialize")]
|
||||||
impl<N: RealField> Serialize for Quaternion<N>
|
impl<N: SimdRealField> Serialize for Quaternion<N>
|
||||||
where Owned<N, U4>: Serialize
|
where Owned<N, U4>: Serialize
|
||||||
{
|
{
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
@ -83,7 +84,7 @@ where Owned<N, U4>: Serialize
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "serde-serialize")]
|
#[cfg(feature = "serde-serialize")]
|
||||||
impl<'a, N: RealField> Deserialize<'a> for Quaternion<N>
|
impl<'a, N: SimdRealField> Deserialize<'a> for Quaternion<N>
|
||||||
where Owned<N, U4>: Deserialize<'a>
|
where Owned<N, U4>: Deserialize<'a>
|
||||||
{
|
{
|
||||||
fn deserialize<Des>(deserializer: Des) -> Result<Self, Des::Error>
|
fn deserialize<Des>(deserializer: Des) -> Result<Self, Des::Error>
|
||||||
|
@ -94,7 +95,7 @@ where Owned<N, U4>: Deserialize<'a>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: RealField> Quaternion<N> {
|
impl<N: SimdRealField> Quaternion<N> {
|
||||||
/// Moves this unit quaternion into one that owns its data.
|
/// Moves this unit quaternion into one that owns its data.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[deprecated(note = "This method is a no-op and will be removed in a future release.")]
|
#[deprecated(note = "This method is a no-op and will be removed in a future release.")]
|
||||||
|
@ -146,36 +147,6 @@ impl<N: RealField> Quaternion<N> {
|
||||||
Self::from_parts(self.w, -self.imag())
|
Self::from_parts(self.w, -self.imag())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Inverts this quaternion if it is not zero.
|
|
||||||
///
|
|
||||||
/// # Example
|
|
||||||
/// ```
|
|
||||||
/// # #[macro_use] extern crate approx;
|
|
||||||
/// # use nalgebra::Quaternion;
|
|
||||||
/// let q = Quaternion::new(1.0, 2.0, 3.0, 4.0);
|
|
||||||
/// let inv_q = q.try_inverse();
|
|
||||||
///
|
|
||||||
/// assert!(inv_q.is_some());
|
|
||||||
/// assert_relative_eq!(inv_q.unwrap() * q, Quaternion::identity());
|
|
||||||
///
|
|
||||||
/// //Non-invertible case
|
|
||||||
/// let q = Quaternion::new(0.0, 0.0, 0.0, 0.0);
|
|
||||||
/// let inv_q = q.try_inverse();
|
|
||||||
///
|
|
||||||
/// assert!(inv_q.is_none());
|
|
||||||
/// ```
|
|
||||||
#[inline]
|
|
||||||
#[must_use = "Did you mean to use try_inverse_mut()?"]
|
|
||||||
pub fn try_inverse(&self) -> Option<Self> {
|
|
||||||
let mut res = Self::from(self.coords.clone_owned());
|
|
||||||
|
|
||||||
if res.try_inverse_mut() {
|
|
||||||
Some(res)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Linear interpolation between two quaternion.
|
/// Linear interpolation between two quaternion.
|
||||||
///
|
///
|
||||||
/// Computes `self * (1 - t) + other * t`.
|
/// Computes `self * (1 - t) + other * t`.
|
||||||
|
@ -309,6 +280,38 @@ impl<N: RealField> Quaternion<N> {
|
||||||
pub fn dot(&self, rhs: &Self) -> N {
|
pub fn dot(&self, rhs: &Self) -> N {
|
||||||
self.coords.dot(&rhs.coords)
|
self.coords.dot(&rhs.coords)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField> Quaternion<N> {
|
||||||
|
/// Inverts this quaternion if it is not zero.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// # #[macro_use] extern crate approx;
|
||||||
|
/// # use nalgebra::Quaternion;
|
||||||
|
/// let q = Quaternion::new(1.0, 2.0, 3.0, 4.0);
|
||||||
|
/// let inv_q = q.try_inverse();
|
||||||
|
///
|
||||||
|
/// assert!(inv_q.is_some());
|
||||||
|
/// assert_relative_eq!(inv_q.unwrap() * q, Quaternion::identity());
|
||||||
|
///
|
||||||
|
/// //Non-invertible case
|
||||||
|
/// let q = Quaternion::new(0.0, 0.0, 0.0, 0.0);
|
||||||
|
/// let inv_q = q.try_inverse();
|
||||||
|
///
|
||||||
|
/// assert!(inv_q.is_none());
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
#[must_use = "Did you mean to use try_inverse_mut()?"]
|
||||||
|
pub fn try_inverse(&self) -> Option<Self> {
|
||||||
|
let mut res = self.clone();
|
||||||
|
|
||||||
|
if res.try_inverse_mut() {
|
||||||
|
Some(res)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Calculates the inner product (also known as the dot product).
|
/// Calculates the inner product (also known as the dot product).
|
||||||
/// See "Foundations of Game Engine Development, Volume 1: Mathematics" by Lengyel
|
/// See "Foundations of Game Engine Development, Volume 1: Mathematics" by Lengyel
|
||||||
|
@ -917,6 +920,30 @@ impl<N: RealField + fmt::Display> fmt::Display for Quaternion<N> {
|
||||||
/// A unit quaternions. May be used to represent a rotation.
|
/// A unit quaternions. May be used to represent a rotation.
|
||||||
pub type UnitQuaternion<N> = Unit<Quaternion<N>>;
|
pub type UnitQuaternion<N> = Unit<Quaternion<N>>;
|
||||||
|
|
||||||
|
impl<N: SimdRealField> Normed for Quaternion<N> {
|
||||||
|
type Norm = N::SimdRealField;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn norm(&self) -> N::SimdRealField {
|
||||||
|
self.coords.norm()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn norm_squared(&self) -> N::SimdRealField {
|
||||||
|
self.coords.norm_squared()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn scale_mut(&mut self, n: Self::Norm) {
|
||||||
|
self.coords.scale_mut(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn unscale_mut(&mut self, n: Self::Norm) {
|
||||||
|
self.coords.unscale_mut(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<N: RealField> UnitQuaternion<N> {
|
impl<N: RealField> UnitQuaternion<N> {
|
||||||
/// Moves this unit quaternion into one that owns its data.
|
/// Moves this unit quaternion into one that owns its data.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -948,7 +975,7 @@ impl<N: RealField> UnitQuaternion<N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn angle(&self) -> N {
|
pub fn angle(&self) -> N {
|
||||||
let w = self.quaternion().scalar().abs();
|
let w = self.quaternion().scalar().abs();
|
||||||
self.quaternion().imag().norm().atan2(w) * crate::convert(2.0f64)
|
self.quaternion().imag().norm().atan2(w) * crate::convert(2.0f64)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The underlying quaternion.
|
/// The underlying quaternion.
|
||||||
|
@ -1029,7 +1056,7 @@ impl<N: RealField> UnitQuaternion<N> {
|
||||||
/// assert_relative_eq!(rot_to * rot1, rot2, epsilon = 1.0e-6);
|
/// assert_relative_eq!(rot_to * rot1, rot2, epsilon = 1.0e-6);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn rotation_to(&self, other: &Self) -> Self{
|
pub fn rotation_to(&self, other: &Self) -> Self {
|
||||||
other / self
|
other / self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1087,7 +1114,8 @@ impl<N: RealField> UnitQuaternion<N> {
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn slerp(&self, other: &Self, t: N) -> Self {
|
pub fn slerp(&self, other: &Self, t: N) -> Self {
|
||||||
self.try_slerp(other, t, N::default_epsilon()).expect("Quaternion slerp: ambiguous configuration.")
|
self.try_slerp(other, t, N::default_epsilon())
|
||||||
|
.expect("Quaternion slerp: ambiguous configuration.")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computes the spherical linear interpolation between two unit quaternions or returns `None`
|
/// Computes the spherical linear interpolation between two unit quaternions or returns `None`
|
||||||
|
@ -1101,22 +1129,21 @@ impl<N: RealField> UnitQuaternion<N> {
|
||||||
/// * `epsilon`: the value below which the sinus of the angle separating both quaternion
|
/// * `epsilon`: the value below which the sinus of the angle separating both quaternion
|
||||||
/// must be to return `None`.
|
/// must be to return `None`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn try_slerp(
|
pub fn try_slerp(&self, other: &Self, t: N, epsilon: N) -> Option<Self> {
|
||||||
&self,
|
|
||||||
other: &Self,
|
|
||||||
t: N,
|
|
||||||
epsilon: N,
|
|
||||||
) -> Option<Self>
|
|
||||||
{
|
|
||||||
let coords = if self.coords.dot(&other.coords) < N::zero() {
|
let coords = if self.coords.dot(&other.coords) < N::zero() {
|
||||||
Unit::new_unchecked(self.coords)
|
Unit::new_unchecked(self.coords).try_slerp(
|
||||||
.try_slerp(&Unit::new_unchecked(-other.coords), t, epsilon)
|
&Unit::new_unchecked(-other.coords),
|
||||||
|
t,
|
||||||
|
epsilon,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
Unit::new_unchecked(self.coords)
|
Unit::new_unchecked(self.coords).try_slerp(
|
||||||
.try_slerp(&Unit::new_unchecked(other.coords), t, epsilon)
|
&Unit::new_unchecked(other.coords),
|
||||||
|
t,
|
||||||
|
epsilon,
|
||||||
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
coords.map(|q| Unit::new_unchecked(Quaternion::from(q.into_inner())))
|
coords.map(|q| Unit::new_unchecked(Quaternion::from(q.into_inner())))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,307 +0,0 @@
|
||||||
use num::Zero;
|
|
||||||
|
|
||||||
use alga::general::{
|
|
||||||
AbstractGroup, AbstractGroupAbelian, AbstractLoop, AbstractMagma, AbstractModule,
|
|
||||||
AbstractMonoid, AbstractQuasigroup, AbstractSemigroup, Additive, Id, Identity, TwoSidedInverse, Module,
|
|
||||||
Multiplicative, RealField,
|
|
||||||
};
|
|
||||||
use alga::linear::{
|
|
||||||
AffineTransformation, DirectIsometry, FiniteDimVectorSpace, Isometry, NormedSpace,
|
|
||||||
OrthogonalTransformation, ProjectiveTransformation, Rotation, Similarity, Transformation,
|
|
||||||
VectorSpace,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::base::{Vector3, Vector4};
|
|
||||||
use crate::geometry::{Point3, Quaternion, UnitQuaternion};
|
|
||||||
|
|
||||||
impl<N: RealField> Identity<Multiplicative> for Quaternion<N> {
|
|
||||||
#[inline]
|
|
||||||
fn identity() -> Self {
|
|
||||||
Self::identity()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField> Identity<Additive> for Quaternion<N> {
|
|
||||||
#[inline]
|
|
||||||
fn identity() -> Self {
|
|
||||||
Self::zero()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField> AbstractMagma<Multiplicative> for Quaternion<N> {
|
|
||||||
#[inline]
|
|
||||||
fn operate(&self, rhs: &Self) -> Self {
|
|
||||||
self * rhs
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField> AbstractMagma<Additive> for Quaternion<N> {
|
|
||||||
#[inline]
|
|
||||||
fn operate(&self, rhs: &Self) -> Self {
|
|
||||||
self + rhs
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField> TwoSidedInverse<Additive> for Quaternion<N> {
|
|
||||||
#[inline]
|
|
||||||
fn two_sided_inverse(&self) -> Self {
|
|
||||||
-self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_structures(
|
|
||||||
($Quaternion: ident; $($marker: ident<$operator: ident>),* $(,)*) => {$(
|
|
||||||
impl<N: RealField> $marker<$operator> for $Quaternion<N> { }
|
|
||||||
)*}
|
|
||||||
);
|
|
||||||
|
|
||||||
impl_structures!(
|
|
||||||
Quaternion;
|
|
||||||
AbstractSemigroup<Multiplicative>,
|
|
||||||
AbstractMonoid<Multiplicative>,
|
|
||||||
|
|
||||||
AbstractSemigroup<Additive>,
|
|
||||||
AbstractQuasigroup<Additive>,
|
|
||||||
AbstractMonoid<Additive>,
|
|
||||||
AbstractLoop<Additive>,
|
|
||||||
AbstractGroup<Additive>,
|
|
||||||
AbstractGroupAbelian<Additive>
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Vector space.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
impl<N: RealField> AbstractModule for Quaternion<N> {
|
|
||||||
type AbstractRing = N;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn multiply_by(&self, n: N) -> Self {
|
|
||||||
self * n
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField> Module for Quaternion<N> {
|
|
||||||
type Ring = N;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField> VectorSpace for Quaternion<N> {
|
|
||||||
type Field = N;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField> FiniteDimVectorSpace for Quaternion<N> {
|
|
||||||
#[inline]
|
|
||||||
fn dimension() -> usize {
|
|
||||||
4
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn canonical_basis_element(i: usize) -> Self {
|
|
||||||
Self::from(Vector4::canonical_basis_element(i))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn dot(&self, other: &Self) -> N {
|
|
||||||
self.coords.dot(&other.coords)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
unsafe fn component_unchecked(&self, i: usize) -> &N {
|
|
||||||
self.coords.component_unchecked(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
unsafe fn component_unchecked_mut(&mut self, i: usize) -> &mut N {
|
|
||||||
self.coords.component_unchecked_mut(i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField> NormedSpace for Quaternion<N> {
|
|
||||||
type RealField = N;
|
|
||||||
type ComplexField = N;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn norm_squared(&self) -> N {
|
|
||||||
self.coords.norm_squared()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn norm(&self) -> N {
|
|
||||||
self.as_vector().norm()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn normalize(&self) -> Self {
|
|
||||||
let v = self.coords.normalize();
|
|
||||||
Self::from(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn normalize_mut(&mut self) -> N {
|
|
||||||
self.coords.normalize_mut()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn try_normalize(&self, min_norm: N) -> Option<Self> {
|
|
||||||
if let Some(v) = self.coords.try_normalize(min_norm) {
|
|
||||||
Some(Self::from(v))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn try_normalize_mut(&mut self, min_norm: N) -> Option<N> {
|
|
||||||
self.coords.try_normalize_mut(min_norm)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Implementations for UnitQuaternion.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
impl<N: RealField> Identity<Multiplicative> for UnitQuaternion<N> {
|
|
||||||
#[inline]
|
|
||||||
fn identity() -> Self {
|
|
||||||
Self::identity()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField> AbstractMagma<Multiplicative> for UnitQuaternion<N> {
|
|
||||||
#[inline]
|
|
||||||
fn operate(&self, rhs: &Self) -> Self {
|
|
||||||
self * rhs
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField> TwoSidedInverse<Multiplicative> for UnitQuaternion<N> {
|
|
||||||
#[inline]
|
|
||||||
fn two_sided_inverse(&self) -> Self {
|
|
||||||
self.inverse()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn two_sided_inverse_mut(&mut self) {
|
|
||||||
self.inverse_mut()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_structures!(
|
|
||||||
UnitQuaternion;
|
|
||||||
AbstractSemigroup<Multiplicative>,
|
|
||||||
AbstractQuasigroup<Multiplicative>,
|
|
||||||
AbstractMonoid<Multiplicative>,
|
|
||||||
AbstractLoop<Multiplicative>,
|
|
||||||
AbstractGroup<Multiplicative>
|
|
||||||
);
|
|
||||||
|
|
||||||
impl<N: RealField> Transformation<Point3<N>> for UnitQuaternion<N> {
|
|
||||||
#[inline]
|
|
||||||
fn transform_point(&self, pt: &Point3<N>) -> Point3<N> {
|
|
||||||
self.transform_point(pt)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn transform_vector(&self, v: &Vector3<N>) -> Vector3<N> {
|
|
||||||
self.transform_vector(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField> ProjectiveTransformation<Point3<N>> for UnitQuaternion<N> {
|
|
||||||
#[inline]
|
|
||||||
fn inverse_transform_point(&self, pt: &Point3<N>) -> Point3<N> {
|
|
||||||
self.inverse_transform_point(pt)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn inverse_transform_vector(&self, v: &Vector3<N>) -> Vector3<N> {
|
|
||||||
self.inverse_transform_vector(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField> AffineTransformation<Point3<N>> for UnitQuaternion<N> {
|
|
||||||
type Rotation = Self;
|
|
||||||
type NonUniformScaling = Id;
|
|
||||||
type Translation = Id;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn decompose(&self) -> (Id, Self, Id, Self) {
|
|
||||||
(Id::new(), self.clone(), Id::new(), Self::identity())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn append_translation(&self, _: &Self::Translation) -> Self {
|
|
||||||
self.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn prepend_translation(&self, _: &Self::Translation) -> Self {
|
|
||||||
self.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn append_rotation(&self, r: &Self::Rotation) -> Self {
|
|
||||||
r * self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn prepend_rotation(&self, r: &Self::Rotation) -> Self {
|
|
||||||
self * r
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn append_scaling(&self, _: &Self::NonUniformScaling) -> Self {
|
|
||||||
self.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn prepend_scaling(&self, _: &Self::NonUniformScaling) -> Self {
|
|
||||||
self.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField> Similarity<Point3<N>> for UnitQuaternion<N> {
|
|
||||||
type Scaling = Id;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn translation(&self) -> Id {
|
|
||||||
Id::new()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn rotation(&self) -> Self {
|
|
||||||
self.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn scaling(&self) -> Id {
|
|
||||||
Id::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! marker_impl(
|
|
||||||
($($Trait: ident),*) => {$(
|
|
||||||
impl<N: RealField> $Trait<Point3<N>> for UnitQuaternion<N> { }
|
|
||||||
)*}
|
|
||||||
);
|
|
||||||
|
|
||||||
marker_impl!(Isometry, DirectIsometry, OrthogonalTransformation);
|
|
||||||
|
|
||||||
impl<N: RealField> Rotation<Point3<N>> for UnitQuaternion<N> {
|
|
||||||
#[inline]
|
|
||||||
fn powf(&self, n: N) -> Option<Self> {
|
|
||||||
Some(self.powf(n))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn rotation_between(a: &Vector3<N>, b: &Vector3<N>) -> Option<Self> {
|
|
||||||
Self::rotation_between(a, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn scaled_rotation_between(a: &Vector3<N>, b: &Vector3<N>, s: N) -> Option<Self> {
|
|
||||||
Self::scaled_rotation_between(a, b, s)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -9,15 +9,16 @@ use num::{One, Zero};
|
||||||
use rand::distributions::{Distribution, OpenClosed01, Standard};
|
use rand::distributions::{Distribution, OpenClosed01, Standard};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
||||||
use alga::general::RealField;
|
use simba::scalar::RealField;
|
||||||
|
|
||||||
use crate::base::dimension::U3;
|
use crate::base::dimension::U3;
|
||||||
use crate::base::storage::Storage;
|
use crate::base::storage::Storage;
|
||||||
use crate::base::{Unit, Vector, Vector3, Vector4, Matrix3, Matrix4};
|
use crate::base::{Matrix3, Matrix4, Unit, Vector, Vector3, Vector4};
|
||||||
|
use crate::SimdRealField;
|
||||||
|
|
||||||
use crate::geometry::{Quaternion, Rotation3, UnitQuaternion};
|
use crate::geometry::{Quaternion, Rotation3, UnitQuaternion};
|
||||||
|
|
||||||
impl<N: RealField> Quaternion<N> {
|
impl<N: SimdRealField> Quaternion<N> {
|
||||||
/// Creates a quaternion from a 4D vector. The quaternion scalar part corresponds to the `w`
|
/// Creates a quaternion from a 4D vector. The quaternion scalar part corresponds to the `w`
|
||||||
/// vector component.
|
/// vector component.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -77,17 +78,6 @@ impl<N: RealField> Quaternion<N> {
|
||||||
Self::from_parts(r, Vector3::zero())
|
Self::from_parts(r, Vector3::zero())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new quaternion from its polar decomposition.
|
|
||||||
///
|
|
||||||
/// Note that `axis` is assumed to be a unit vector.
|
|
||||||
// FIXME: take a reference to `axis`?
|
|
||||||
pub fn from_polar_decomposition<SB>(scale: N, theta: N, axis: Unit<Vector<N, U3, SB>>) -> Self
|
|
||||||
where SB: Storage<N, U3> {
|
|
||||||
let rot = UnitQuaternion::<N>::from_axis_angle(&axis, theta * crate::convert(2.0f64));
|
|
||||||
|
|
||||||
rot.into_inner() * scale
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The quaternion multiplicative identity.
|
/// The quaternion multiplicative identity.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
|
@ -105,14 +95,28 @@ impl<N: RealField> Quaternion<N> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: RealField> One for Quaternion<N> {
|
// FIXME: merge with the previous block.
|
||||||
|
impl<N: RealField> Quaternion<N> {
|
||||||
|
/// Creates a new quaternion from its polar decomposition.
|
||||||
|
///
|
||||||
|
/// Note that `axis` is assumed to be a unit vector.
|
||||||
|
// FIXME: take a reference to `axis`?
|
||||||
|
pub fn from_polar_decomposition<SB>(scale: N, theta: N, axis: Unit<Vector<N, U3, SB>>) -> Self
|
||||||
|
where SB: Storage<N, U3> {
|
||||||
|
let rot = UnitQuaternion::<N>::from_axis_angle(&axis, theta * crate::convert(2.0f64));
|
||||||
|
|
||||||
|
rot.into_inner() * scale
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: SimdRealField> One for Quaternion<N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn one() -> Self {
|
fn one() -> Self {
|
||||||
Self::identity()
|
Self::identity()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: RealField> Zero for Quaternion<N> {
|
impl<N: SimdRealField> Zero for Quaternion<N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn zero() -> Self {
|
fn zero() -> Self {
|
||||||
Self::from(Vector4::zero())
|
Self::from(Vector4::zero())
|
||||||
|
@ -124,7 +128,7 @@ impl<N: RealField> Zero for Quaternion<N> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: RealField> Distribution<Quaternion<N>> for Standard
|
impl<N: SimdRealField> Distribution<Quaternion<N>> for Standard
|
||||||
where Standard: Distribution<N>
|
where Standard: Distribution<N>
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -134,7 +138,7 @@ where Standard: Distribution<N>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "arbitrary")]
|
#[cfg(feature = "arbitrary")]
|
||||||
impl<N: RealField + Arbitrary> Arbitrary for Quaternion<N>
|
impl<N: SimdRealField + Arbitrary> Arbitrary for Quaternion<N>
|
||||||
where Owned<N, U4>: Send
|
where Owned<N, U4>: Send
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -492,7 +496,7 @@ impl<N: RealField> UnitQuaternion<N> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deprecated: Use [UnitQuaternion::face_towards] instead.
|
/// Deprecated: Use [UnitQuaternion::face_towards] instead.
|
||||||
#[deprecated(note="renamed to `face_towards`")]
|
#[deprecated(note = "renamed to `face_towards`")]
|
||||||
pub fn new_observer_frames<SB, SC>(dir: &Vector<N, U3, SB>, up: &Vector<N, U3, SC>) -> Self
|
pub fn new_observer_frames<SB, SC>(dir: &Vector<N, U3, SB>, up: &Vector<N, U3, SC>) -> Self
|
||||||
where
|
where
|
||||||
SB: Storage<N, U3>,
|
SB: Storage<N, U3>,
|
||||||
|
@ -685,7 +689,7 @@ impl<N: RealField> UnitQuaternion<N> {
|
||||||
/// Algorithm from: Oshman, Yaakov, and Avishy Carmi. "Attitude estimation from vector
|
/// Algorithm from: Oshman, Yaakov, and Avishy Carmi. "Attitude estimation from vector
|
||||||
/// observations using a genetic-algorithm-embedded quaternion particle filter." Journal of
|
/// observations using a genetic-algorithm-embedded quaternion particle filter." Journal of
|
||||||
/// Guidance, Control, and Dynamics 29.4 (2006): 879-891.
|
/// Guidance, Control, and Dynamics 29.4 (2006): 879-891.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
/// ```
|
/// ```
|
||||||
/// # #[macro_use] extern crate approx;
|
/// # #[macro_use] extern crate approx;
|
||||||
|
@ -709,7 +713,7 @@ impl<N: RealField> UnitQuaternion<N> {
|
||||||
.sum();
|
.sum();
|
||||||
|
|
||||||
assert!(!quaternions_matrix.is_zero());
|
assert!(!quaternions_matrix.is_zero());
|
||||||
|
|
||||||
let eigen_matrix = quaternions_matrix
|
let eigen_matrix = quaternions_matrix
|
||||||
.try_symmetric_eigen(N::RealField::default_epsilon(), 10)
|
.try_symmetric_eigen(N::RealField::default_epsilon(), 10)
|
||||||
.expect("Quaternions matrix could not be diagonalized. This behavior should not be possible.");
|
.expect("Quaternions matrix could not be diagonalized. This behavior should not be possible.");
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use num::Zero;
|
use num::Zero;
|
||||||
|
|
||||||
use alga::general::{RealField, SubsetOf, SupersetOf};
|
use simba::scalar::{RealField, SubsetOf, SupersetOf};
|
||||||
use alga::linear::Rotation as AlgaRotation;
|
use simba::simd::SimdRealField;
|
||||||
|
|
||||||
#[cfg(feature = "mint")]
|
#[cfg(feature = "mint")]
|
||||||
use mint;
|
use mint;
|
||||||
|
@ -9,8 +9,8 @@ use mint;
|
||||||
use crate::base::dimension::U3;
|
use crate::base::dimension::U3;
|
||||||
use crate::base::{Matrix3, Matrix4, Vector4};
|
use crate::base::{Matrix3, Matrix4, Vector4};
|
||||||
use crate::geometry::{
|
use crate::geometry::{
|
||||||
Isometry, Point3, Quaternion, Rotation, Rotation3, Similarity, SuperTCategoryOf, TAffine,
|
AbstractRotation, Isometry, Quaternion, Rotation, Rotation3, Similarity, SuperTCategoryOf,
|
||||||
Transform, Translation, UnitQuaternion,
|
TAffine, Transform, Translation, UnitQuaternion,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -34,8 +34,8 @@ use crate::geometry::{
|
||||||
|
|
||||||
impl<N1, N2> SubsetOf<Quaternion<N2>> for Quaternion<N1>
|
impl<N1, N2> SubsetOf<Quaternion<N2>> for Quaternion<N1>
|
||||||
where
|
where
|
||||||
N1: RealField,
|
N1: SimdRealField,
|
||||||
N2: RealField + SupersetOf<N1>,
|
N2: SimdRealField + SupersetOf<N1>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_superset(&self) -> Quaternion<N2> {
|
fn to_superset(&self) -> Quaternion<N2> {
|
||||||
|
@ -48,7 +48,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(q: &Quaternion<N2>) -> Self {
|
fn from_superset_unchecked(q: &Quaternion<N2>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
coords: q.coords.to_subset_unchecked(),
|
coords: q.coords.to_subset_unchecked(),
|
||||||
}
|
}
|
||||||
|
@ -57,8 +57,8 @@ where
|
||||||
|
|
||||||
impl<N1, N2> SubsetOf<UnitQuaternion<N2>> for UnitQuaternion<N1>
|
impl<N1, N2> SubsetOf<UnitQuaternion<N2>> for UnitQuaternion<N1>
|
||||||
where
|
where
|
||||||
N1: RealField,
|
N1: SimdRealField,
|
||||||
N2: RealField + SupersetOf<N1>,
|
N2: SimdRealField + SupersetOf<N1>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_superset(&self) -> UnitQuaternion<N2> {
|
fn to_superset(&self) -> UnitQuaternion<N2> {
|
||||||
|
@ -71,7 +71,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(uq: &UnitQuaternion<N2>) -> Self {
|
fn from_superset_unchecked(uq: &UnitQuaternion<N2>) -> Self {
|
||||||
Self::new_unchecked(crate::convert_ref_unchecked(uq.as_ref()))
|
Self::new_unchecked(crate::convert_ref_unchecked(uq.as_ref()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(rot: &Rotation3<N2>) -> Self {
|
fn from_superset_unchecked(rot: &Rotation3<N2>) -> Self {
|
||||||
let q = UnitQuaternion::<N2>::from_rotation_matrix(rot);
|
let q = UnitQuaternion::<N2>::from_rotation_matrix(rot);
|
||||||
crate::convert_unchecked(q)
|
crate::convert_unchecked(q)
|
||||||
}
|
}
|
||||||
|
@ -103,7 +103,7 @@ impl<N1, N2, R> SubsetOf<Isometry<N2, U3, R>> for UnitQuaternion<N1>
|
||||||
where
|
where
|
||||||
N1: RealField,
|
N1: RealField,
|
||||||
N2: RealField + SupersetOf<N1>,
|
N2: RealField + SupersetOf<N1>,
|
||||||
R: AlgaRotation<Point3<N2>> + SupersetOf<Self>,
|
R: AbstractRotation<N2, U3> + SupersetOf<Self>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_superset(&self) -> Isometry<N2, U3, R> {
|
fn to_superset(&self) -> Isometry<N2, U3, R> {
|
||||||
|
@ -116,7 +116,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(iso: &Isometry<N2, U3, R>) -> Self {
|
fn from_superset_unchecked(iso: &Isometry<N2, U3, R>) -> Self {
|
||||||
crate::convert_ref_unchecked(&iso.rotation)
|
crate::convert_ref_unchecked(&iso.rotation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -125,7 +125,7 @@ impl<N1, N2, R> SubsetOf<Similarity<N2, U3, R>> for UnitQuaternion<N1>
|
||||||
where
|
where
|
||||||
N1: RealField,
|
N1: RealField,
|
||||||
N2: RealField + SupersetOf<N1>,
|
N2: RealField + SupersetOf<N1>,
|
||||||
R: AlgaRotation<Point3<N2>> + SupersetOf<Self>,
|
R: AbstractRotation<N2, U3> + SupersetOf<Self>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_superset(&self) -> Similarity<N2, U3, R> {
|
fn to_superset(&self) -> Similarity<N2, U3, R> {
|
||||||
|
@ -138,7 +138,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(sim: &Similarity<N2, U3, R>) -> Self {
|
fn from_superset_unchecked(sim: &Similarity<N2, U3, R>) -> Self {
|
||||||
crate::convert_ref_unchecked(&sim.isometry)
|
crate::convert_ref_unchecked(&sim.isometry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -160,7 +160,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(t: &Transform<N2, U3, C>) -> Self {
|
fn from_superset_unchecked(t: &Transform<N2, U3, C>) -> Self {
|
||||||
Self::from_superset_unchecked(t.matrix())
|
Self::from_superset_unchecked(t.matrix())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,7 +177,7 @@ impl<N1: RealField, N2: RealField + SupersetOf<N1>> SubsetOf<Matrix4<N2>> for Un
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(m: &Matrix4<N2>) -> Self {
|
fn from_superset_unchecked(m: &Matrix4<N2>) -> Self {
|
||||||
let rot: Rotation3<N1> = crate::convert_ref_unchecked(m);
|
let rot: Rotation3<N1> = crate::convert_ref_unchecked(m);
|
||||||
Self::from_rotation_matrix(&rot)
|
Self::from_rotation_matrix(&rot)
|
||||||
}
|
}
|
||||||
|
@ -246,7 +246,7 @@ impl<N: RealField> From<UnitQuaternion<N>> for Matrix3<N> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: RealField> From<Vector4<N>> for Quaternion<N> {
|
impl<N: SimdRealField> From<Vector4<N>> for Quaternion<N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(coords: Vector4<N>) -> Self {
|
fn from(coords: Vector4<N>) -> Self {
|
||||||
Self { coords }
|
Self { coords }
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
use alga::general::RealField;
|
use simba::simd::SimdRealField;
|
||||||
|
|
||||||
use crate::base::coordinates::IJKW;
|
use crate::base::coordinates::IJKW;
|
||||||
|
|
||||||
use crate::geometry::Quaternion;
|
use crate::geometry::Quaternion;
|
||||||
|
|
||||||
impl<N: RealField> Deref for Quaternion<N> {
|
impl<N: SimdRealField> Deref for Quaternion<N> {
|
||||||
type Target = IJKW<N>;
|
type Target = IJKW<N>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -16,7 +16,7 @@ impl<N: RealField> Deref for Quaternion<N> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: RealField> DerefMut for Quaternion<N> {
|
impl<N: SimdRealField> DerefMut for Quaternion<N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
unsafe { mem::transmute(self) }
|
unsafe { mem::transmute(self) }
|
||||||
|
|
|
@ -54,16 +54,15 @@ use std::ops::{
|
||||||
Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign,
|
Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign,
|
||||||
};
|
};
|
||||||
|
|
||||||
use alga::general::RealField;
|
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::dimension::{U1, U3, U4};
|
use crate::base::dimension::{U1, U3, U4};
|
||||||
use crate::base::storage::Storage;
|
use crate::base::storage::Storage;
|
||||||
use crate::base::{DefaultAllocator, Unit, Vector, Vector3};
|
use crate::base::{DefaultAllocator, Unit, Vector, Vector3};
|
||||||
|
use crate::SimdRealField;
|
||||||
|
|
||||||
use crate::geometry::{Point3, Quaternion, Rotation, UnitQuaternion};
|
use crate::geometry::{Point3, Quaternion, Rotation, UnitQuaternion};
|
||||||
|
|
||||||
impl<N: RealField> Index<usize> for Quaternion<N> {
|
impl<N: SimdRealField> Index<usize> for Quaternion<N> {
|
||||||
type Output = N;
|
type Output = N;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -72,7 +71,7 @@ impl<N: RealField> Index<usize> for Quaternion<N> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: RealField> IndexMut<usize> for Quaternion<N> {
|
impl<N: SimdRealField> IndexMut<usize> for Quaternion<N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn index_mut(&mut self, i: usize) -> &mut N {
|
fn index_mut(&mut self, i: usize) -> &mut N {
|
||||||
&mut self.coords[i]
|
&mut self.coords[i]
|
||||||
|
@ -85,7 +84,7 @@ macro_rules! quaternion_op_impl(
|
||||||
$(for $Storage: ident: $StoragesBound: ident $(<$($BoundParam: ty),*>)*),*;
|
$(for $Storage: ident: $StoragesBound: ident $(<$($BoundParam: ty),*>)*),*;
|
||||||
$lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty, Output = $Result: ty $(=> $VDimA: ty, $VDimB: ty)*;
|
$lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty, Output = $Result: ty $(=> $VDimA: ty, $VDimB: ty)*;
|
||||||
$action: expr; $($lives: tt),*) => {
|
$action: expr; $($lives: tt),*) => {
|
||||||
impl<$($lives ,)* N: RealField $(, $Storage: $StoragesBound $(<$($BoundParam),*>)*)*> $Op<$Rhs> for $Lhs
|
impl<$($lives ,)* N: SimdRealField $(, $Storage: $StoragesBound $(<$($BoundParam),*>)*)*> $Op<$Rhs> for $Lhs
|
||||||
where DefaultAllocator: Allocator<N, $LhsRDim, $LhsCDim> +
|
where DefaultAllocator: Allocator<N, $LhsRDim, $LhsCDim> +
|
||||||
Allocator<N, $RhsRDim, $RhsCDim> {
|
Allocator<N, $RhsRDim, $RhsCDim> {
|
||||||
type Output = $Result;
|
type Output = $Result;
|
||||||
|
@ -121,11 +120,11 @@ quaternion_op_impl!(
|
||||||
'b);
|
'b);
|
||||||
|
|
||||||
quaternion_op_impl!(
|
quaternion_op_impl!(
|
||||||
Add, add;
|
Add, add;
|
||||||
(U4, U1), (U4, U1);
|
(U4, U1), (U4, U1);
|
||||||
self: Quaternion<N>, rhs: Quaternion<N>, Output = Quaternion<N>;
|
self: Quaternion<N>, rhs: Quaternion<N>, Output = Quaternion<N>;
|
||||||
Quaternion::from(self.coords + rhs.coords);
|
Quaternion::from(self.coords + rhs.coords);
|
||||||
);
|
);
|
||||||
|
|
||||||
// Quaternion - Quaternion
|
// Quaternion - Quaternion
|
||||||
quaternion_op_impl!(
|
quaternion_op_impl!(
|
||||||
|
@ -150,11 +149,11 @@ quaternion_op_impl!(
|
||||||
'b);
|
'b);
|
||||||
|
|
||||||
quaternion_op_impl!(
|
quaternion_op_impl!(
|
||||||
Sub, sub;
|
Sub, sub;
|
||||||
(U4, U1), (U4, U1);
|
(U4, U1), (U4, U1);
|
||||||
self: Quaternion<N>, rhs: Quaternion<N>, Output = Quaternion<N>;
|
self: Quaternion<N>, rhs: Quaternion<N>, Output = Quaternion<N>;
|
||||||
Quaternion::from(self.coords - rhs.coords);
|
Quaternion::from(self.coords - rhs.coords);
|
||||||
);
|
);
|
||||||
|
|
||||||
// Quaternion × Quaternion
|
// Quaternion × Quaternion
|
||||||
quaternion_op_impl!(
|
quaternion_op_impl!(
|
||||||
|
@ -183,11 +182,11 @@ quaternion_op_impl!(
|
||||||
'b);
|
'b);
|
||||||
|
|
||||||
quaternion_op_impl!(
|
quaternion_op_impl!(
|
||||||
Mul, mul;
|
Mul, mul;
|
||||||
(U4, U1), (U4, U1);
|
(U4, U1), (U4, U1);
|
||||||
self: Quaternion<N>, rhs: Quaternion<N>, Output = Quaternion<N>;
|
self: Quaternion<N>, rhs: Quaternion<N>, Output = Quaternion<N>;
|
||||||
&self * &rhs;
|
&self * &rhs;
|
||||||
);
|
);
|
||||||
|
|
||||||
// UnitQuaternion × UnitQuaternion
|
// UnitQuaternion × UnitQuaternion
|
||||||
quaternion_op_impl!(
|
quaternion_op_impl!(
|
||||||
|
@ -212,11 +211,11 @@ quaternion_op_impl!(
|
||||||
'b);
|
'b);
|
||||||
|
|
||||||
quaternion_op_impl!(
|
quaternion_op_impl!(
|
||||||
Mul, mul;
|
Mul, mul;
|
||||||
(U4, U1), (U4, U1);
|
(U4, U1), (U4, U1);
|
||||||
self: UnitQuaternion<N>, rhs: UnitQuaternion<N>, Output = UnitQuaternion<N>;
|
self: UnitQuaternion<N>, rhs: UnitQuaternion<N>, Output = UnitQuaternion<N>;
|
||||||
&self * &rhs;
|
&self * &rhs;
|
||||||
);
|
);
|
||||||
|
|
||||||
// UnitQuaternion ÷ UnitQuaternion
|
// UnitQuaternion ÷ UnitQuaternion
|
||||||
quaternion_op_impl!(
|
quaternion_op_impl!(
|
||||||
|
@ -241,11 +240,11 @@ quaternion_op_impl!(
|
||||||
'b);
|
'b);
|
||||||
|
|
||||||
quaternion_op_impl!(
|
quaternion_op_impl!(
|
||||||
Div, div;
|
Div, div;
|
||||||
(U4, U1), (U4, U1);
|
(U4, U1), (U4, U1);
|
||||||
self: UnitQuaternion<N>, rhs: UnitQuaternion<N>, Output = UnitQuaternion<N>;
|
self: UnitQuaternion<N>, rhs: UnitQuaternion<N>, Output = UnitQuaternion<N>;
|
||||||
&self / &rhs;
|
&self / &rhs;
|
||||||
);
|
);
|
||||||
|
|
||||||
// UnitQuaternion × Rotation
|
// UnitQuaternion × Rotation
|
||||||
quaternion_op_impl!(
|
quaternion_op_impl!(
|
||||||
|
@ -274,12 +273,12 @@ quaternion_op_impl!(
|
||||||
'b);
|
'b);
|
||||||
|
|
||||||
quaternion_op_impl!(
|
quaternion_op_impl!(
|
||||||
Mul, mul;
|
Mul, mul;
|
||||||
(U4, U1), (U3, U3);
|
(U4, U1), (U3, U3);
|
||||||
self: UnitQuaternion<N>, rhs: Rotation<N, U3>,
|
self: UnitQuaternion<N>, rhs: Rotation<N, U3>,
|
||||||
Output = UnitQuaternion<N> => U3, U3;
|
Output = UnitQuaternion<N> => U3, U3;
|
||||||
self * UnitQuaternion::<N>::from_rotation_matrix(&rhs);
|
self * UnitQuaternion::<N>::from_rotation_matrix(&rhs);
|
||||||
);
|
);
|
||||||
|
|
||||||
// UnitQuaternion ÷ Rotation
|
// UnitQuaternion ÷ Rotation
|
||||||
quaternion_op_impl!(
|
quaternion_op_impl!(
|
||||||
|
@ -308,12 +307,12 @@ quaternion_op_impl!(
|
||||||
'b);
|
'b);
|
||||||
|
|
||||||
quaternion_op_impl!(
|
quaternion_op_impl!(
|
||||||
Div, div;
|
Div, div;
|
||||||
(U4, U1), (U3, U3);
|
(U4, U1), (U3, U3);
|
||||||
self: UnitQuaternion<N>, rhs: Rotation<N, U3>,
|
self: UnitQuaternion<N>, rhs: Rotation<N, U3>,
|
||||||
Output = UnitQuaternion<N> => U3, U3;
|
Output = UnitQuaternion<N> => U3, U3;
|
||||||
self / UnitQuaternion::<N>::from_rotation_matrix(&rhs);
|
self / UnitQuaternion::<N>::from_rotation_matrix(&rhs);
|
||||||
);
|
);
|
||||||
|
|
||||||
// Rotation × UnitQuaternion
|
// Rotation × UnitQuaternion
|
||||||
quaternion_op_impl!(
|
quaternion_op_impl!(
|
||||||
|
@ -342,12 +341,12 @@ quaternion_op_impl!(
|
||||||
'b);
|
'b);
|
||||||
|
|
||||||
quaternion_op_impl!(
|
quaternion_op_impl!(
|
||||||
Mul, mul;
|
Mul, mul;
|
||||||
(U3, U3), (U4, U1);
|
(U3, U3), (U4, U1);
|
||||||
self: Rotation<N, U3>, rhs: UnitQuaternion<N>,
|
self: Rotation<N, U3>, rhs: UnitQuaternion<N>,
|
||||||
Output = UnitQuaternion<N> => U3, U3;
|
Output = UnitQuaternion<N> => U3, U3;
|
||||||
UnitQuaternion::<N>::from_rotation_matrix(&self) * rhs;
|
UnitQuaternion::<N>::from_rotation_matrix(&self) * rhs;
|
||||||
);
|
);
|
||||||
|
|
||||||
// Rotation ÷ UnitQuaternion
|
// Rotation ÷ UnitQuaternion
|
||||||
quaternion_op_impl!(
|
quaternion_op_impl!(
|
||||||
|
@ -376,12 +375,12 @@ quaternion_op_impl!(
|
||||||
'b);
|
'b);
|
||||||
|
|
||||||
quaternion_op_impl!(
|
quaternion_op_impl!(
|
||||||
Div, div;
|
Div, div;
|
||||||
(U3, U3), (U4, U1);
|
(U3, U3), (U4, U1);
|
||||||
self: Rotation<N, U3>, rhs: UnitQuaternion<N>,
|
self: Rotation<N, U3>, rhs: UnitQuaternion<N>,
|
||||||
Output = UnitQuaternion<N> => U3, U3;
|
Output = UnitQuaternion<N> => U3, U3;
|
||||||
UnitQuaternion::<N>::from_rotation_matrix(&self) / rhs;
|
UnitQuaternion::<N>::from_rotation_matrix(&self) / rhs;
|
||||||
);
|
);
|
||||||
|
|
||||||
// UnitQuaternion × Vector
|
// UnitQuaternion × Vector
|
||||||
quaternion_op_impl!(
|
quaternion_op_impl!(
|
||||||
|
@ -415,12 +414,12 @@ quaternion_op_impl!(
|
||||||
'b);
|
'b);
|
||||||
|
|
||||||
quaternion_op_impl!(
|
quaternion_op_impl!(
|
||||||
Mul, mul;
|
Mul, mul;
|
||||||
(U4, U1), (U3, U1) for SB: Storage<N, U3> ;
|
(U4, U1), (U3, U1) for SB: Storage<N, U3> ;
|
||||||
self: UnitQuaternion<N>, rhs: Vector<N, U3, SB>,
|
self: UnitQuaternion<N>, rhs: Vector<N, U3, SB>,
|
||||||
Output = Vector3<N> => U3, U4;
|
Output = Vector3<N> => U3, U4;
|
||||||
&self * &rhs;
|
&self * &rhs;
|
||||||
);
|
);
|
||||||
|
|
||||||
// UnitQuaternion × Point
|
// UnitQuaternion × Point
|
||||||
quaternion_op_impl!(
|
quaternion_op_impl!(
|
||||||
|
@ -448,12 +447,12 @@ quaternion_op_impl!(
|
||||||
'b);
|
'b);
|
||||||
|
|
||||||
quaternion_op_impl!(
|
quaternion_op_impl!(
|
||||||
Mul, mul;
|
Mul, mul;
|
||||||
(U4, U1), (U3, U1);
|
(U4, U1), (U3, U1);
|
||||||
self: UnitQuaternion<N>, rhs: Point3<N>,
|
self: UnitQuaternion<N>, rhs: Point3<N>,
|
||||||
Output = Point3<N> => U3, U4;
|
Output = Point3<N> => U3, U4;
|
||||||
Point3::from(self * rhs.coords);
|
Point3::from(self * rhs.coords);
|
||||||
);
|
);
|
||||||
|
|
||||||
// UnitQuaternion × Unit<Vector>
|
// UnitQuaternion × Unit<Vector>
|
||||||
quaternion_op_impl!(
|
quaternion_op_impl!(
|
||||||
|
@ -481,16 +480,16 @@ quaternion_op_impl!(
|
||||||
'b);
|
'b);
|
||||||
|
|
||||||
quaternion_op_impl!(
|
quaternion_op_impl!(
|
||||||
Mul, mul;
|
Mul, mul;
|
||||||
(U4, U1), (U3, U1) for SB: Storage<N, U3> ;
|
(U4, U1), (U3, U1) for SB: Storage<N, U3> ;
|
||||||
self: UnitQuaternion<N>, rhs: Unit<Vector<N, U3, SB>>,
|
self: UnitQuaternion<N>, rhs: Unit<Vector<N, U3, SB>>,
|
||||||
Output = Unit<Vector3<N>> => U3, U4;
|
Output = Unit<Vector3<N>> => U3, U4;
|
||||||
Unit::new_unchecked(self * rhs.into_inner());
|
Unit::new_unchecked(self * rhs.into_inner());
|
||||||
);
|
);
|
||||||
|
|
||||||
macro_rules! scalar_op_impl(
|
macro_rules! scalar_op_impl(
|
||||||
($($Op: ident, $op: ident, $OpAssign: ident, $op_assign: ident);* $(;)*) => {$(
|
($($Op: ident, $op: ident, $OpAssign: ident, $op_assign: ident);* $(;)*) => {$(
|
||||||
impl<N: RealField> $Op<N> for Quaternion<N> {
|
impl<N: SimdRealField> $Op<N> for Quaternion<N> {
|
||||||
type Output = Quaternion<N>;
|
type Output = Quaternion<N>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -499,7 +498,7 @@ macro_rules! scalar_op_impl(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, N: RealField> $Op<N> for &'a Quaternion<N> {
|
impl<'a, N: SimdRealField> $Op<N> for &'a Quaternion<N> {
|
||||||
type Output = Quaternion<N>;
|
type Output = Quaternion<N>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -508,7 +507,7 @@ macro_rules! scalar_op_impl(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: RealField> $OpAssign<N> for Quaternion<N> {
|
impl<N: SimdRealField> $OpAssign<N> for Quaternion<N> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn $op_assign(&mut self, n: N) {
|
fn $op_assign(&mut self, n: N) {
|
||||||
|
@ -547,7 +546,7 @@ macro_rules! left_scalar_mul_impl(
|
||||||
|
|
||||||
left_scalar_mul_impl!(f32, f64);
|
left_scalar_mul_impl!(f32, f64);
|
||||||
|
|
||||||
impl<N: RealField> Neg for Quaternion<N> {
|
impl<N: SimdRealField> Neg for Quaternion<N> {
|
||||||
type Output = Quaternion<N>;
|
type Output = Quaternion<N>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -556,7 +555,7 @@ impl<N: RealField> Neg for Quaternion<N> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, N: RealField> Neg for &'a Quaternion<N> {
|
impl<'a, N: SimdRealField> Neg for &'a Quaternion<N> {
|
||||||
type Output = Quaternion<N>;
|
type Output = Quaternion<N>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -570,7 +569,7 @@ macro_rules! quaternion_op_impl(
|
||||||
($LhsRDim: ident, $LhsCDim: ident), ($RhsRDim: ident, $RhsCDim: ident);
|
($LhsRDim: ident, $LhsCDim: ident), ($RhsRDim: ident, $RhsCDim: ident);
|
||||||
$lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty $(=> $VDimA: ty, $VDimB: ty)*;
|
$lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty $(=> $VDimA: ty, $VDimB: ty)*;
|
||||||
$action: expr; $($lives: tt),*) => {
|
$action: expr; $($lives: tt),*) => {
|
||||||
impl<$($lives ,)* N: RealField> $OpAssign<$Rhs> for $Lhs
|
impl<$($lives ,)* N: SimdRealField> $OpAssign<$Rhs> for $Lhs
|
||||||
where DefaultAllocator: Allocator<N, $LhsRDim, $LhsCDim> +
|
where DefaultAllocator: Allocator<N, $LhsRDim, $LhsCDim> +
|
||||||
Allocator<N, $RhsRDim, $RhsCDim> {
|
Allocator<N, $RhsRDim, $RhsCDim> {
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
use simba::simd::SimdValue;
|
||||||
|
|
||||||
|
use crate::base::Vector4;
|
||||||
|
use crate::geometry::Quaternion;
|
||||||
|
use crate::{RealField, Scalar};
|
||||||
|
|
||||||
|
impl<N: RealField> SimdValue for Quaternion<N>
|
||||||
|
where N::Element: Scalar
|
||||||
|
{
|
||||||
|
type Element = Quaternion<N::Element>;
|
||||||
|
type SimdBool = N::SimdBool;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn lanes() -> usize {
|
||||||
|
N::lanes()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn splat(val: Self::Element) -> Self {
|
||||||
|
Vector4::splat(val.coords).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn extract(&self, i: usize) -> Self::Element {
|
||||||
|
self.coords.extract(i).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn extract_unchecked(&self, i: usize) -> Self::Element {
|
||||||
|
self.coords.extract_unchecked(i).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn replace(&mut self, i: usize, val: Self::Element) {
|
||||||
|
self.coords.replace(i, val.coords)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn replace_unchecked(&mut self, i: usize, val: Self::Element) {
|
||||||
|
self.coords.replace_unchecked(i, val.coords)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn select(self, cond: Self::SimdBool, other: Self) -> Self {
|
||||||
|
self.coords.select(cond, other.coords).into()
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
use alga::general::ComplexField;
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::constraint::{AreMultipliable, DimEq, SameNumberOfRows, ShapeConstraint};
|
use crate::base::constraint::{AreMultipliable, DimEq, SameNumberOfRows, ShapeConstraint};
|
||||||
use crate::base::{DefaultAllocator, Matrix, Scalar, Unit, Vector};
|
use crate::base::{DefaultAllocator, Matrix, Scalar, Unit, Vector};
|
||||||
use crate::dimension::{Dim, DimName, U1};
|
use crate::dimension::{Dim, DimName, U1};
|
||||||
use crate::storage::{Storage, StorageMut};
|
use crate::storage::{Storage, StorageMut};
|
||||||
|
use simba::scalar::ComplexField;
|
||||||
|
|
||||||
use crate::geometry::Point;
|
use crate::geometry::Point;
|
||||||
|
|
||||||
|
@ -27,10 +27,7 @@ impl<N: ComplexField, D: Dim, S: Storage<N, D>> Reflection<N, D, S> {
|
||||||
|
|
||||||
/// Creates a new reflection wrt. the plane orthogonal to the given axis and that contains the
|
/// Creates a new reflection wrt. the plane orthogonal to the given axis and that contains the
|
||||||
/// point `pt`.
|
/// point `pt`.
|
||||||
pub fn new_containing_point(
|
pub fn new_containing_point(axis: Unit<Vector<N, D, S>>, pt: &Point<N, D>) -> Self
|
||||||
axis: Unit<Vector<N, D, S>>,
|
|
||||||
pt: &Point<N, D>,
|
|
||||||
) -> Self
|
|
||||||
where
|
where
|
||||||
D: DimName,
|
D: DimName,
|
||||||
DefaultAllocator: Allocator<N, D>,
|
DefaultAllocator: Allocator<N, D>,
|
||||||
|
@ -64,9 +61,9 @@ impl<N: ComplexField, D: Dim, S: Storage<N, D>> Reflection<N, D, S> {
|
||||||
// FIXME: naming convention: reflect_to, reflect_assign ?
|
// FIXME: naming convention: reflect_to, reflect_assign ?
|
||||||
/// Applies the reflection to the columns of `rhs`.
|
/// Applies the reflection to the columns of `rhs`.
|
||||||
pub fn reflect_with_sign<R2: Dim, C2: Dim, S2>(&self, rhs: &mut Matrix<N, R2, C2, S2>, sign: N)
|
pub fn reflect_with_sign<R2: Dim, C2: Dim, S2>(&self, rhs: &mut Matrix<N, R2, C2, S2>, sign: N)
|
||||||
where
|
where
|
||||||
S2: StorageMut<N, R2, C2>,
|
S2: StorageMut<N, R2, C2>,
|
||||||
ShapeConstraint: SameNumberOfRows<R2, D>,
|
ShapeConstraint: SameNumberOfRows<R2, D>,
|
||||||
{
|
{
|
||||||
for i in 0..rhs.ncols() {
|
for i in 0..rhs.ncols() {
|
||||||
// NOTE: we borrow the column twice here. First it is borrowed immutably for the
|
// NOTE: we borrow the column twice here. First it is borrowed immutably for the
|
||||||
|
|
|
@ -14,7 +14,7 @@ use crate::base::storage::Owned;
|
||||||
#[cfg(feature = "abomonation-serialize")]
|
#[cfg(feature = "abomonation-serialize")]
|
||||||
use abomonation::Abomonation;
|
use abomonation::Abomonation;
|
||||||
|
|
||||||
use alga::general::RealField;
|
use simba::scalar::RealField;
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1};
|
use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1};
|
||||||
|
@ -175,7 +175,7 @@ where DefaultAllocator: Allocator<N, D, D>
|
||||||
|
|
||||||
/// Unwraps the underlying matrix.
|
/// Unwraps the underlying matrix.
|
||||||
/// Deprecated: Use [Rotation::into_inner] instead.
|
/// Deprecated: Use [Rotation::into_inner] instead.
|
||||||
#[deprecated(note="use `.into_inner()` instead")]
|
#[deprecated(note = "use `.into_inner()` instead")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn unwrap(self) -> MatrixN<N, D> {
|
pub fn unwrap(self) -> MatrixN<N, D> {
|
||||||
self.matrix
|
self.matrix
|
||||||
|
|
|
@ -1,276 +0,0 @@
|
||||||
use alga::general::{
|
|
||||||
AbstractGroup, AbstractLoop, AbstractMagma, AbstractMonoid, AbstractQuasigroup,
|
|
||||||
AbstractSemigroup, Id, Identity, TwoSidedInverse, Multiplicative, RealField,
|
|
||||||
};
|
|
||||||
use alga::linear::{
|
|
||||||
self, AffineTransformation, DirectIsometry, Isometry, OrthogonalTransformation,
|
|
||||||
ProjectiveTransformation, Similarity, Transformation,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
|
||||||
use crate::base::dimension::DimName;
|
|
||||||
use crate::base::{DefaultAllocator, VectorN};
|
|
||||||
|
|
||||||
use crate::geometry::{Point, Rotation};
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Algebraic structures.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
impl<N: RealField, D: DimName> Identity<Multiplicative> for Rotation<N, D>
|
|
||||||
where DefaultAllocator: Allocator<N, D, D>
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn identity() -> Self {
|
|
||||||
Self::identity()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField, D: DimName> TwoSidedInverse<Multiplicative> for Rotation<N, D>
|
|
||||||
where DefaultAllocator: Allocator<N, D, D>
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
#[must_use = "Did you mean to use two_sided_inverse_mut()?"]
|
|
||||||
fn two_sided_inverse(&self) -> Self {
|
|
||||||
self.transpose()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn two_sided_inverse_mut(&mut self) {
|
|
||||||
self.transpose_mut()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField, D: DimName> AbstractMagma<Multiplicative> for Rotation<N, D>
|
|
||||||
where DefaultAllocator: Allocator<N, D, D>
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn operate(&self, rhs: &Self) -> Self {
|
|
||||||
self * rhs
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_multiplicative_structures(
|
|
||||||
($($marker: ident<$operator: ident>),* $(,)*) => {$(
|
|
||||||
impl<N: RealField, D: DimName> $marker<$operator> for Rotation<N, D>
|
|
||||||
where DefaultAllocator: Allocator<N, D, D> { }
|
|
||||||
)*}
|
|
||||||
);
|
|
||||||
|
|
||||||
impl_multiplicative_structures!(
|
|
||||||
AbstractSemigroup<Multiplicative>,
|
|
||||||
AbstractMonoid<Multiplicative>,
|
|
||||||
AbstractQuasigroup<Multiplicative>,
|
|
||||||
AbstractLoop<Multiplicative>,
|
|
||||||
AbstractGroup<Multiplicative>
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Transformation groups.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
impl<N: RealField, D: DimName> Transformation<Point<N, D>> for Rotation<N, D>
|
|
||||||
where DefaultAllocator: Allocator<N, D, D> + Allocator<N, D>
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn transform_point(&self, pt: &Point<N, D>) -> Point<N, D> {
|
|
||||||
self.transform_point(pt)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn transform_vector(&self, v: &VectorN<N, D>) -> VectorN<N, D> {
|
|
||||||
self.transform_vector(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField, D: DimName> ProjectiveTransformation<Point<N, D>> for Rotation<N, D>
|
|
||||||
where DefaultAllocator: Allocator<N, D, D> + Allocator<N, D>
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn inverse_transform_point(&self, pt: &Point<N, D>) -> Point<N, D> {
|
|
||||||
self.inverse_transform_point(pt)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn inverse_transform_vector(&self, v: &VectorN<N, D>) -> VectorN<N, D> {
|
|
||||||
self.inverse_transform_vector(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField, D: DimName> AffineTransformation<Point<N, D>> for Rotation<N, D>
|
|
||||||
where DefaultAllocator: Allocator<N, D, D> + Allocator<N, D>
|
|
||||||
{
|
|
||||||
type Rotation = Self;
|
|
||||||
type NonUniformScaling = Id;
|
|
||||||
type Translation = Id;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn decompose(&self) -> (Id, Self, Id, Self) {
|
|
||||||
(Id::new(), self.clone(), Id::new(), Self::identity())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn append_translation(&self, _: &Self::Translation) -> Self {
|
|
||||||
self.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn prepend_translation(&self, _: &Self::Translation) -> Self {
|
|
||||||
self.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn append_rotation(&self, r: &Self::Rotation) -> Self {
|
|
||||||
r * self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn prepend_rotation(&self, r: &Self::Rotation) -> Self {
|
|
||||||
self * r
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn append_scaling(&self, _: &Self::NonUniformScaling) -> Self {
|
|
||||||
self.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn prepend_scaling(&self, _: &Self::NonUniformScaling) -> Self {
|
|
||||||
self.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField, D: DimName> Similarity<Point<N, D>> for Rotation<N, D>
|
|
||||||
where DefaultAllocator: Allocator<N, D, D> + Allocator<N, D>
|
|
||||||
{
|
|
||||||
type Scaling = Id;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn translation(&self) -> Id {
|
|
||||||
Id::new()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn rotation(&self) -> Self {
|
|
||||||
self.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn scaling(&self) -> Id {
|
|
||||||
Id::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! marker_impl(
|
|
||||||
($($Trait: ident),*) => {$(
|
|
||||||
impl<N: RealField, D: DimName> $Trait<Point<N, D>> for Rotation<N, D>
|
|
||||||
where DefaultAllocator: Allocator<N, D, D> +
|
|
||||||
Allocator<N, D> { }
|
|
||||||
)*}
|
|
||||||
);
|
|
||||||
|
|
||||||
marker_impl!(Isometry, DirectIsometry, OrthogonalTransformation);
|
|
||||||
|
|
||||||
/// Subgroups of the n-dimensional rotation group `SO(n)`.
|
|
||||||
impl<N: RealField, D: DimName> linear::Rotation<Point<N, D>> for Rotation<N, D>
|
|
||||||
where DefaultAllocator: Allocator<N, D, D> + Allocator<N, D>
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn powf(&self, _: N) -> Option<Self> {
|
|
||||||
// XXX: Add the general case.
|
|
||||||
// XXX: Use specialization for 2D and 3D.
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn rotation_between(_: &VectorN<N, D>, _: &VectorN<N, D>) -> Option<Self> {
|
|
||||||
// XXX: Add the general case.
|
|
||||||
// XXX: Use specialization for 2D and 3D.
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn scaled_rotation_between(_: &VectorN<N, D>, _: &VectorN<N, D>, _: N) -> Option<Self> {
|
|
||||||
// XXX: Add the general case.
|
|
||||||
// XXX: Use specialization for 2D and 3D.
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
impl<N: RealField> Matrix for Rotation<N> {
|
|
||||||
type Field = N;
|
|
||||||
type Row = Matrix<N>;
|
|
||||||
type Column = Matrix<N>;
|
|
||||||
type Transpose = Self;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn nrows(&self) -> usize {
|
|
||||||
self.submatrix.nrows()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn ncolumns(&self) -> usize {
|
|
||||||
self.submatrix.ncolumns()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn row(&self, i: usize) -> Self::Row {
|
|
||||||
self.submatrix.row(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn column(&self, i: usize) -> Self::Column {
|
|
||||||
self.submatrix.column(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn get(&self, i: usize, j: usize) -> Self::Field {
|
|
||||||
self.submatrix[(i, j)]
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
unsafe fn get_unchecked(&self, i: usize, j: usize) -> Self::Field {
|
|
||||||
self.submatrix.at_fast(i, j)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn transpose(&self) -> Self::Transpose {
|
|
||||||
Rotation::from_matrix_unchecked(self.submatrix.transpose())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField> SquareMatrix for Rotation<N> {
|
|
||||||
type Vector = Matrix<N>;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn diagonal(&self) -> Self::Coordinates {
|
|
||||||
self.submatrix.diagonal()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn determinant(&self) -> Self::Field {
|
|
||||||
crate::one()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn try_inverse(&self) -> Option<Self> {
|
|
||||||
Some(::transpose(self))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn try_inverse_mut(&mut self) -> bool {
|
|
||||||
self.transpose_mut();
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn transpose_mut(&mut self) {
|
|
||||||
self.submatrix.transpose_mut()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField> InversibleSquareMatrix for Rotation<N> { }
|
|
||||||
*/
|
|
|
@ -1,6 +1,6 @@
|
||||||
use num::{One, Zero};
|
use num::{One, Zero};
|
||||||
|
|
||||||
use alga::general::{ClosedAdd, ClosedMul};
|
use simba::scalar::{ClosedAdd, ClosedMul};
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::dimension::DimName;
|
use crate::base::dimension::DimName;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use num::Zero;
|
use num::Zero;
|
||||||
|
|
||||||
use alga::general::{RealField, SubsetOf, SupersetOf};
|
use simba::scalar::{RealField, SubsetOf, SupersetOf};
|
||||||
use alga::linear::Rotation as AlgaRotation;
|
|
||||||
|
|
||||||
#[cfg(feature = "mint")]
|
#[cfg(feature = "mint")]
|
||||||
use mint;
|
use mint;
|
||||||
|
@ -11,8 +10,8 @@ use crate::base::dimension::{DimMin, DimName, DimNameAdd, DimNameSum, U1};
|
||||||
use crate::base::{DefaultAllocator, Matrix2, Matrix3, Matrix4, MatrixN};
|
use crate::base::{DefaultAllocator, Matrix2, Matrix3, Matrix4, MatrixN};
|
||||||
|
|
||||||
use crate::geometry::{
|
use crate::geometry::{
|
||||||
Isometry, Point, Rotation, Rotation2, Rotation3, Similarity, SuperTCategoryOf, TAffine,
|
AbstractRotation, Isometry, Rotation, Rotation2, Rotation3, Similarity, SuperTCategoryOf,
|
||||||
Transform, Translation, UnitComplex, UnitQuaternion,
|
TAffine, Transform, Translation, UnitComplex, UnitQuaternion,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -47,7 +46,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(rot: &Rotation<N2, D>) -> Self {
|
fn from_superset_unchecked(rot: &Rotation<N2, D>) -> Self {
|
||||||
Rotation::from_matrix_unchecked(rot.matrix().to_subset_unchecked())
|
Rotation::from_matrix_unchecked(rot.matrix().to_subset_unchecked())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,7 +68,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(q: &UnitQuaternion<N2>) -> Self {
|
fn from_superset_unchecked(q: &UnitQuaternion<N2>) -> Self {
|
||||||
let q: UnitQuaternion<N1> = crate::convert_ref_unchecked(q);
|
let q: UnitQuaternion<N1> = crate::convert_ref_unchecked(q);
|
||||||
q.to_rotation_matrix()
|
q.to_rotation_matrix()
|
||||||
}
|
}
|
||||||
|
@ -92,7 +91,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(q: &UnitComplex<N2>) -> Self {
|
fn from_superset_unchecked(q: &UnitComplex<N2>) -> Self {
|
||||||
let q: UnitComplex<N1> = crate::convert_ref_unchecked(q);
|
let q: UnitComplex<N1> = crate::convert_ref_unchecked(q);
|
||||||
q.to_rotation_matrix()
|
q.to_rotation_matrix()
|
||||||
}
|
}
|
||||||
|
@ -102,7 +101,7 @@ impl<N1, N2, D: DimName, R> SubsetOf<Isometry<N2, D, R>> for Rotation<N1, D>
|
||||||
where
|
where
|
||||||
N1: RealField,
|
N1: RealField,
|
||||||
N2: RealField + SupersetOf<N1>,
|
N2: RealField + SupersetOf<N1>,
|
||||||
R: AlgaRotation<Point<N2, D>> + SupersetOf<Self>,
|
R: AbstractRotation<N2, D> + SupersetOf<Self>,
|
||||||
DefaultAllocator: Allocator<N1, D, D> + Allocator<N2, D>,
|
DefaultAllocator: Allocator<N1, D, D> + Allocator<N2, D>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -116,7 +115,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(iso: &Isometry<N2, D, R>) -> Self {
|
fn from_superset_unchecked(iso: &Isometry<N2, D, R>) -> Self {
|
||||||
crate::convert_ref_unchecked(&iso.rotation)
|
crate::convert_ref_unchecked(&iso.rotation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -125,7 +124,7 @@ impl<N1, N2, D: DimName, R> SubsetOf<Similarity<N2, D, R>> for Rotation<N1, D>
|
||||||
where
|
where
|
||||||
N1: RealField,
|
N1: RealField,
|
||||||
N2: RealField + SupersetOf<N1>,
|
N2: RealField + SupersetOf<N1>,
|
||||||
R: AlgaRotation<Point<N2, D>> + SupersetOf<Self>,
|
R: AbstractRotation<N2, D> + SupersetOf<Self>,
|
||||||
DefaultAllocator: Allocator<N1, D, D> + Allocator<N2, D>,
|
DefaultAllocator: Allocator<N1, D, D> + Allocator<N2, D>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -139,7 +138,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(sim: &Similarity<N2, D, R>) -> Self {
|
fn from_superset_unchecked(sim: &Similarity<N2, D, R>) -> Self {
|
||||||
crate::convert_ref_unchecked(&sim.isometry.rotation)
|
crate::convert_ref_unchecked(&sim.isometry.rotation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -168,7 +167,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(t: &Transform<N2, D, C>) -> Self {
|
fn from_superset_unchecked(t: &Transform<N2, D, C>) -> Self {
|
||||||
Self::from_superset_unchecked(t.matrix())
|
Self::from_superset_unchecked(t.matrix())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -204,7 +203,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(m: &MatrixN<N2, DimNameSum<D, U1>>) -> Self {
|
fn from_superset_unchecked(m: &MatrixN<N2, DimNameSum<D, U1>>) -> Self {
|
||||||
let r = m.fixed_slice::<D, D>(0, 0);
|
let r = m.fixed_slice::<D, D>(0, 0);
|
||||||
Self::from_matrix_unchecked(crate::convert_unchecked(r.into_owned()))
|
Self::from_matrix_unchecked(crate::convert_unchecked(r.into_owned()))
|
||||||
}
|
}
|
||||||
|
@ -219,7 +218,7 @@ impl<N: RealField> From<mint::EulerAngles<N, mint::IntraXYZ>> for Rotation3<N> {
|
||||||
|
|
||||||
impl<N: RealField> From<Rotation2<N>> for Matrix3<N> {
|
impl<N: RealField> From<Rotation2<N>> for Matrix3<N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(q: Rotation2<N>) ->Self {
|
fn from(q: Rotation2<N>) -> Self {
|
||||||
q.to_homogeneous()
|
q.to_homogeneous()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
use num::{One, Zero};
|
use num::{One, Zero};
|
||||||
use std::ops::{Div, DivAssign, Index, Mul, MulAssign};
|
use std::ops::{Div, DivAssign, Index, Mul, MulAssign};
|
||||||
|
|
||||||
use alga::general::{ClosedAdd, ClosedMul};
|
use simba::scalar::{ClosedAdd, ClosedMul};
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::constraint::{AreMultipliable, ShapeConstraint};
|
use crate::base::constraint::{AreMultipliable, ShapeConstraint};
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
use simba::simd::SimdValue;
|
||||||
|
|
||||||
|
use crate::base::allocator::Allocator;
|
||||||
|
use crate::base::dimension::DimName;
|
||||||
|
use crate::base::{DefaultAllocator, MatrixN, Scalar};
|
||||||
|
|
||||||
|
use crate::geometry::Rotation;
|
||||||
|
|
||||||
|
impl<N, D> SimdValue for Rotation<N, D>
|
||||||
|
where
|
||||||
|
N: Scalar + SimdValue,
|
||||||
|
D: DimName,
|
||||||
|
N::Element: Scalar,
|
||||||
|
DefaultAllocator: Allocator<N, D, D> + Allocator<N::Element, D, D>,
|
||||||
|
{
|
||||||
|
type Element = Rotation<N::Element, D>;
|
||||||
|
type SimdBool = N::SimdBool;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn lanes() -> usize {
|
||||||
|
N::lanes()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn splat(val: Self::Element) -> Self {
|
||||||
|
Rotation::from_matrix_unchecked(MatrixN::splat(val.into_inner()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn extract(&self, i: usize) -> Self::Element {
|
||||||
|
Rotation::from_matrix_unchecked(self.matrix().extract(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn extract_unchecked(&self, i: usize) -> Self::Element {
|
||||||
|
Rotation::from_matrix_unchecked(self.matrix().extract_unchecked(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn replace(&mut self, i: usize, val: Self::Element) {
|
||||||
|
self.matrix_mut_unchecked().replace(i, val.into_inner())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn replace_unchecked(&mut self, i: usize, val: Self::Element) {
|
||||||
|
self.matrix_mut_unchecked()
|
||||||
|
.replace_unchecked(i, val.into_inner())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn select(self, cond: Self::SimdBool, other: Self) -> Self {
|
||||||
|
Rotation::from_matrix_unchecked(self.into_inner().select(cond, other.into_inner()))
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,10 +3,10 @@ use crate::base::storage::Owned;
|
||||||
#[cfg(feature = "arbitrary")]
|
#[cfg(feature = "arbitrary")]
|
||||||
use quickcheck::{Arbitrary, Gen};
|
use quickcheck::{Arbitrary, Gen};
|
||||||
|
|
||||||
use alga::general::RealField;
|
|
||||||
use num::Zero;
|
use num::Zero;
|
||||||
use rand::distributions::{Distribution, OpenClosed01, Standard};
|
use rand::distributions::{Distribution, OpenClosed01, Standard};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
use simba::scalar::RealField;
|
||||||
use std::ops::Neg;
|
use std::ops::Neg;
|
||||||
|
|
||||||
use crate::base::dimension::{U1, U2, U3};
|
use crate::base::dimension::{U1, U2, U3};
|
||||||
|
@ -77,10 +77,8 @@ impl<N: RealField> Rotation2<N> {
|
||||||
let mut rot = guess.into_inner();
|
let mut rot = guess.into_inner();
|
||||||
|
|
||||||
for _ in 0..max_iter {
|
for _ in 0..max_iter {
|
||||||
let axis = rot.column(0).perp(&m.column(0)) +
|
let axis = rot.column(0).perp(&m.column(0)) + rot.column(1).perp(&m.column(1));
|
||||||
rot.column(1).perp(&m.column(1));
|
let denom = rot.column(0).dot(&m.column(0)) + rot.column(1).dot(&m.column(1));
|
||||||
let denom = rot.column(0).dot(&m.column(0)) +
|
|
||||||
rot.column(1).dot(&m.column(1));
|
|
||||||
|
|
||||||
let angle = axis / (denom.abs() + N::default_epsilon());
|
let angle = axis / (denom.abs() + N::default_epsilon());
|
||||||
if angle.abs() > eps {
|
if angle.abs() > eps {
|
||||||
|
@ -192,7 +190,6 @@ impl<N: RealField> Rotation2<N> {
|
||||||
other * self.inverse()
|
other * self.inverse()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Ensure this rotation is an orthonormal rotation matrix. This is useful when repeated
|
/// Ensure this rotation is an orthonormal rotation matrix. This is useful when repeated
|
||||||
/// computations might cause the matrix from progressively not being orthonormal anymore.
|
/// computations might cause the matrix from progressively not being orthonormal anymore.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -203,7 +200,6 @@ impl<N: RealField> Rotation2<N> {
|
||||||
*self = Self::from_matrix_eps(self.matrix(), N::default_epsilon(), 0, c.into())
|
*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
|
/// Raise the quaternion to a given floating power, i.e., returns the rotation with the angle
|
||||||
/// of `self` multiplied by `n`.
|
/// of `self` multiplied by `n`.
|
||||||
///
|
///
|
||||||
|
@ -314,12 +310,12 @@ impl<N: RealField> Rotation3<N> {
|
||||||
let mut rot = guess.into_inner();
|
let mut rot = guess.into_inner();
|
||||||
|
|
||||||
for _ in 0..max_iter {
|
for _ in 0..max_iter {
|
||||||
let axis = rot.column(0).cross(&m.column(0)) +
|
let axis = rot.column(0).cross(&m.column(0))
|
||||||
rot.column(1).cross(&m.column(1)) +
|
+ rot.column(1).cross(&m.column(1))
|
||||||
rot.column(2).cross(&m.column(2));
|
+ rot.column(2).cross(&m.column(2));
|
||||||
let denom = rot.column(0).dot(&m.column(0)) +
|
let denom = rot.column(0).dot(&m.column(0))
|
||||||
rot.column(1).dot(&m.column(1)) +
|
+ rot.column(1).dot(&m.column(1))
|
||||||
rot.column(2).dot(&m.column(2));
|
+ rot.column(2).dot(&m.column(2));
|
||||||
|
|
||||||
let axisangle = axis / (denom.abs() + N::default_epsilon());
|
let axisangle = axis / (denom.abs() + N::default_epsilon());
|
||||||
|
|
||||||
|
@ -528,7 +524,7 @@ impl<N: RealField> Rotation3<N> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deprecated: Use [Rotation3::face_towards] instead.
|
/// Deprecated: Use [Rotation3::face_towards] instead.
|
||||||
#[deprecated(note="renamed to `face_towards`")]
|
#[deprecated(note = "renamed to `face_towards`")]
|
||||||
pub fn new_observer_frames<SB, SC>(dir: &Vector<N, U3, SB>, up: &Vector<N, U3, SC>) -> Self
|
pub fn new_observer_frames<SB, SC>(dir: &Vector<N, U3, SB>, up: &Vector<N, U3, SC>) -> Self
|
||||||
where
|
where
|
||||||
SB: Storage<N, U3>,
|
SB: Storage<N, U3>,
|
||||||
|
|
|
@ -10,14 +10,13 @@ use serde::{Deserialize, Serialize};
|
||||||
#[cfg(feature = "abomonation-serialize")]
|
#[cfg(feature = "abomonation-serialize")]
|
||||||
use abomonation::Abomonation;
|
use abomonation::Abomonation;
|
||||||
|
|
||||||
use alga::general::{RealField, SubsetOf};
|
use simba::scalar::{RealField, SubsetOf};
|
||||||
use alga::linear::Rotation;
|
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1};
|
use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1};
|
||||||
use crate::base::storage::Owned;
|
use crate::base::storage::Owned;
|
||||||
use crate::base::{DefaultAllocator, MatrixN, VectorN};
|
use crate::base::{DefaultAllocator, MatrixN, VectorN};
|
||||||
use crate::geometry::{Isometry, Point, Translation};
|
use crate::geometry::{AbstractRotation, Isometry, Point, Translation};
|
||||||
|
|
||||||
/// A similarity, i.e., an uniform scaling, followed by a rotation, followed by a translation.
|
/// A similarity, i.e., an uniform scaling, followed by a rotation, followed by a translation.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
@ -25,21 +24,17 @@ use crate::geometry::{Isometry, Point, Translation};
|
||||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serde-serialize",
|
feature = "serde-serialize",
|
||||||
serde(bound(
|
serde(bound(serialize = "N: Serialize,
|
||||||
serialize = "N: Serialize,
|
|
||||||
R: Serialize,
|
R: Serialize,
|
||||||
DefaultAllocator: Allocator<N, D>,
|
DefaultAllocator: Allocator<N, D>,
|
||||||
Owned<N, D>: Serialize"
|
Owned<N, D>: Serialize"))
|
||||||
))
|
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serde-serialize",
|
feature = "serde-serialize",
|
||||||
serde(bound(
|
serde(bound(deserialize = "N: Deserialize<'de>,
|
||||||
deserialize = "N: Deserialize<'de>,
|
|
||||||
R: Deserialize<'de>,
|
R: Deserialize<'de>,
|
||||||
DefaultAllocator: Allocator<N, D>,
|
DefaultAllocator: Allocator<N, D>,
|
||||||
Owned<N, D>: Deserialize<'de>"
|
Owned<N, D>: Deserialize<'de>"))
|
||||||
))
|
|
||||||
)]
|
)]
|
||||||
pub struct Similarity<N: RealField, D: DimName, R>
|
pub struct Similarity<N: RealField, D: DimName, R>
|
||||||
where DefaultAllocator: Allocator<N, D>
|
where DefaultAllocator: Allocator<N, D>
|
||||||
|
@ -80,13 +75,14 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: RealField, D: DimName + Copy, R: Rotation<Point<N, D>> + Copy> Copy for Similarity<N, D, R>
|
impl<N: RealField, D: DimName + Copy, R: AbstractRotation<N, D> + Copy> Copy for Similarity<N, D, R>
|
||||||
where
|
where
|
||||||
DefaultAllocator: Allocator<N, D>,
|
DefaultAllocator: Allocator<N, D>,
|
||||||
Owned<N, D>: Copy,
|
Owned<N, D>: Copy,
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
impl<N: RealField, D: DimName, R: Rotation<Point<N, D>> + Clone> Clone for Similarity<N, D, R>
|
impl<N: RealField, D: DimName, R: AbstractRotation<N, D> + Clone> Clone for Similarity<N, D, R>
|
||||||
where DefaultAllocator: Allocator<N, D>
|
where DefaultAllocator: Allocator<N, D>
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -97,17 +93,12 @@ where DefaultAllocator: Allocator<N, D>
|
||||||
|
|
||||||
impl<N: RealField, D: DimName, R> Similarity<N, D, R>
|
impl<N: RealField, D: DimName, R> Similarity<N, D, R>
|
||||||
where
|
where
|
||||||
R: Rotation<Point<N, D>>,
|
R: AbstractRotation<N, D>,
|
||||||
DefaultAllocator: Allocator<N, D>,
|
DefaultAllocator: Allocator<N, D>,
|
||||||
{
|
{
|
||||||
/// Creates a new similarity from its rotational and translational parts.
|
/// Creates a new similarity from its rotational and translational parts.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_parts(
|
pub fn from_parts(translation: Translation<N, D>, rotation: R, scaling: N) -> Self {
|
||||||
translation: Translation<N, D>,
|
|
||||||
rotation: R,
|
|
||||||
scaling: N,
|
|
||||||
) -> Self
|
|
||||||
{
|
|
||||||
Self::from_isometry(Isometry::from_parts(translation, rotation), scaling)
|
Self::from_isometry(Isometry::from_parts(translation, rotation), scaling)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,10 +110,7 @@ where
|
||||||
"The scaling factor must not be zero."
|
"The scaling factor must not be zero."
|
||||||
);
|
);
|
||||||
|
|
||||||
Self {
|
Self { isometry, scaling }
|
||||||
isometry: isometry,
|
|
||||||
scaling: scaling,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new similarity that applies only a scaling factor.
|
/// Creates a new similarity that applies only a scaling factor.
|
||||||
|
@ -351,13 +339,14 @@ where DefaultAllocator: Allocator<N, D>
|
||||||
|
|
||||||
impl<N: RealField, D: DimName, R> Eq for Similarity<N, D, R>
|
impl<N: RealField, D: DimName, R> Eq for Similarity<N, D, R>
|
||||||
where
|
where
|
||||||
R: Rotation<Point<N, D>> + Eq,
|
R: AbstractRotation<N, D> + Eq,
|
||||||
DefaultAllocator: Allocator<N, D>,
|
DefaultAllocator: Allocator<N, D>,
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
impl<N: RealField, D: DimName, R> PartialEq for Similarity<N, D, R>
|
impl<N: RealField, D: DimName, R> PartialEq for Similarity<N, D, R>
|
||||||
where
|
where
|
||||||
R: Rotation<Point<N, D>> + PartialEq,
|
R: AbstractRotation<N, D> + PartialEq,
|
||||||
DefaultAllocator: Allocator<N, D>,
|
DefaultAllocator: Allocator<N, D>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -368,7 +357,7 @@ where
|
||||||
|
|
||||||
impl<N: RealField, D: DimName, R> AbsDiffEq for Similarity<N, D, R>
|
impl<N: RealField, D: DimName, R> AbsDiffEq for Similarity<N, D, R>
|
||||||
where
|
where
|
||||||
R: Rotation<Point<N, D>> + AbsDiffEq<Epsilon = N::Epsilon>,
|
R: AbstractRotation<N, D> + AbsDiffEq<Epsilon = N::Epsilon>,
|
||||||
DefaultAllocator: Allocator<N, D>,
|
DefaultAllocator: Allocator<N, D>,
|
||||||
N::Epsilon: Copy,
|
N::Epsilon: Copy,
|
||||||
{
|
{
|
||||||
|
@ -388,7 +377,7 @@ where
|
||||||
|
|
||||||
impl<N: RealField, D: DimName, R> RelativeEq for Similarity<N, D, R>
|
impl<N: RealField, D: DimName, R> RelativeEq for Similarity<N, D, R>
|
||||||
where
|
where
|
||||||
R: Rotation<Point<N, D>> + RelativeEq<Epsilon = N::Epsilon>,
|
R: AbstractRotation<N, D> + RelativeEq<Epsilon = N::Epsilon>,
|
||||||
DefaultAllocator: Allocator<N, D>,
|
DefaultAllocator: Allocator<N, D>,
|
||||||
N::Epsilon: Copy,
|
N::Epsilon: Copy,
|
||||||
{
|
{
|
||||||
|
@ -415,7 +404,7 @@ where
|
||||||
|
|
||||||
impl<N: RealField, D: DimName, R> UlpsEq for Similarity<N, D, R>
|
impl<N: RealField, D: DimName, R> UlpsEq for Similarity<N, D, R>
|
||||||
where
|
where
|
||||||
R: Rotation<Point<N, D>> + UlpsEq<Epsilon = N::Epsilon>,
|
R: AbstractRotation<N, D> + UlpsEq<Epsilon = N::Epsilon>,
|
||||||
DefaultAllocator: Allocator<N, D>,
|
DefaultAllocator: Allocator<N, D>,
|
||||||
N::Epsilon: Copy,
|
N::Epsilon: Copy,
|
||||||
{
|
{
|
||||||
|
@ -439,7 +428,7 @@ where
|
||||||
impl<N, D: DimName, R> fmt::Display for Similarity<N, D, R>
|
impl<N, D: DimName, R> fmt::Display for Similarity<N, D, R>
|
||||||
where
|
where
|
||||||
N: RealField + fmt::Display,
|
N: RealField + fmt::Display,
|
||||||
R: Rotation<Point<N, D>> + fmt::Display,
|
R: AbstractRotation<N, D> + fmt::Display,
|
||||||
DefaultAllocator: Allocator<N, D> + Allocator<usize, D>,
|
DefaultAllocator: Allocator<N, D> + Allocator<usize, D>,
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
|
|
@ -1,189 +0,0 @@
|
||||||
use alga::general::{
|
|
||||||
AbstractGroup, AbstractLoop, AbstractMagma, AbstractMonoid, AbstractQuasigroup,
|
|
||||||
AbstractSemigroup, Identity, TwoSidedInverse, Multiplicative, RealField,
|
|
||||||
};
|
|
||||||
use alga::linear::Similarity as AlgaSimilarity;
|
|
||||||
use alga::linear::{AffineTransformation, ProjectiveTransformation, Rotation, Transformation};
|
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
|
||||||
use crate::base::dimension::DimName;
|
|
||||||
use crate::base::{DefaultAllocator, VectorN};
|
|
||||||
|
|
||||||
use crate::geometry::{Point, Similarity, Translation};
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Algebraic structures.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
impl<N: RealField, D: DimName, R> Identity<Multiplicative> for Similarity<N, D, R>
|
|
||||||
where
|
|
||||||
R: Rotation<Point<N, D>>,
|
|
||||||
DefaultAllocator: Allocator<N, D>,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn identity() -> Self {
|
|
||||||
Self::identity()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField, D: DimName, R> TwoSidedInverse<Multiplicative> for Similarity<N, D, R>
|
|
||||||
where
|
|
||||||
R: Rotation<Point<N, D>>,
|
|
||||||
DefaultAllocator: Allocator<N, D>,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
#[must_use = "Did you mean to use two_sided_inverse_mut()?"]
|
|
||||||
fn two_sided_inverse(&self) -> Self {
|
|
||||||
self.inverse()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn two_sided_inverse_mut(&mut self) {
|
|
||||||
self.inverse_mut()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField, D: DimName, R> AbstractMagma<Multiplicative> for Similarity<N, D, R>
|
|
||||||
where
|
|
||||||
R: Rotation<Point<N, D>>,
|
|
||||||
DefaultAllocator: Allocator<N, D>,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn operate(&self, rhs: &Self) -> Self {
|
|
||||||
self * rhs
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_multiplicative_structures(
|
|
||||||
($($marker: ident<$operator: ident>),* $(,)*) => {$(
|
|
||||||
impl<N: RealField, D: DimName, R> $marker<$operator> for Similarity<N, D, R>
|
|
||||||
where R: Rotation<Point<N, D>>,
|
|
||||||
DefaultAllocator: Allocator<N, D> { }
|
|
||||||
)*}
|
|
||||||
);
|
|
||||||
|
|
||||||
impl_multiplicative_structures!(
|
|
||||||
AbstractSemigroup<Multiplicative>,
|
|
||||||
AbstractMonoid<Multiplicative>,
|
|
||||||
AbstractQuasigroup<Multiplicative>,
|
|
||||||
AbstractLoop<Multiplicative>,
|
|
||||||
AbstractGroup<Multiplicative>
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Transformation groups.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
impl<N: RealField, D: DimName, R> Transformation<Point<N, D>> for Similarity<N, D, R>
|
|
||||||
where
|
|
||||||
R: Rotation<Point<N, D>>,
|
|
||||||
DefaultAllocator: Allocator<N, D>,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn transform_point(&self, pt: &Point<N, D>) -> Point<N, D> {
|
|
||||||
self.transform_point(pt)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn transform_vector(&self, v: &VectorN<N, D>) -> VectorN<N, D> {
|
|
||||||
self.transform_vector(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField, D: DimName, R> ProjectiveTransformation<Point<N, D>> for Similarity<N, D, R>
|
|
||||||
where
|
|
||||||
R: Rotation<Point<N, D>>,
|
|
||||||
DefaultAllocator: Allocator<N, D>,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn inverse_transform_point(&self, pt: &Point<N, D>) -> Point<N, D> {
|
|
||||||
self.inverse_transform_point(pt)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn inverse_transform_vector(&self, v: &VectorN<N, D>) -> VectorN<N, D> {
|
|
||||||
self.inverse_transform_vector(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField, D: DimName, R> AffineTransformation<Point<N, D>> for Similarity<N, D, R>
|
|
||||||
where
|
|
||||||
R: Rotation<Point<N, D>>,
|
|
||||||
DefaultAllocator: Allocator<N, D>,
|
|
||||||
{
|
|
||||||
type NonUniformScaling = N;
|
|
||||||
type Rotation = R;
|
|
||||||
type Translation = Translation<N, D>;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn decompose(&self) -> (Translation<N, D>, R, N, R) {
|
|
||||||
(
|
|
||||||
self.isometry.translation.clone(),
|
|
||||||
self.isometry.rotation.clone(),
|
|
||||||
self.scaling(),
|
|
||||||
R::identity(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn append_translation(&self, t: &Self::Translation) -> Self {
|
|
||||||
t * self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn prepend_translation(&self, t: &Self::Translation) -> Self {
|
|
||||||
self * t
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn append_rotation(&self, r: &Self::Rotation) -> Self {
|
|
||||||
Similarity::from_isometry(self.isometry.append_rotation(r), self.scaling())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn prepend_rotation(&self, r: &Self::Rotation) -> Self {
|
|
||||||
self * r
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn append_scaling(&self, s: &Self::NonUniformScaling) -> Self {
|
|
||||||
self.append_scaling(*s)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn prepend_scaling(&self, s: &Self::NonUniformScaling) -> Self {
|
|
||||||
self.prepend_scaling(*s)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn append_rotation_wrt_point(&self, r: &Self::Rotation, p: &Point<N, D>) -> Option<Self> {
|
|
||||||
let mut res = self.clone();
|
|
||||||
res.append_rotation_wrt_point_mut(r, p);
|
|
||||||
Some(res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField, D: DimName, R> AlgaSimilarity<Point<N, D>> for Similarity<N, D, R>
|
|
||||||
where
|
|
||||||
R: Rotation<Point<N, D>>,
|
|
||||||
DefaultAllocator: Allocator<N, D>,
|
|
||||||
{
|
|
||||||
type Scaling = N;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn translation(&self) -> Translation<N, D> {
|
|
||||||
self.isometry.translation()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn rotation(&self) -> R {
|
|
||||||
self.isometry.rotation()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn scaling(&self) -> N {
|
|
||||||
self.scaling()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -7,21 +7,20 @@ use num::One;
|
||||||
use rand::distributions::{Distribution, Standard};
|
use rand::distributions::{Distribution, Standard};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
||||||
use alga::general::RealField;
|
use simba::scalar::RealField;
|
||||||
use alga::linear::Rotation as AlgaRotation;
|
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::dimension::{DimName, U2, U3};
|
use crate::base::dimension::{DimName, U2, U3};
|
||||||
use crate::base::{DefaultAllocator, Vector2, Vector3};
|
use crate::base::{DefaultAllocator, Vector2, Vector3};
|
||||||
|
|
||||||
use crate::geometry::{
|
use crate::geometry::{
|
||||||
Isometry, Point, Point3, Rotation2, Rotation3, Similarity, Translation, UnitComplex,
|
AbstractRotation, Isometry, Point, Point3, Rotation2, Rotation3, Similarity, Translation,
|
||||||
UnitQuaternion,
|
UnitComplex, UnitQuaternion,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl<N: RealField, D: DimName, R> Similarity<N, D, R>
|
impl<N: RealField, D: DimName, R> Similarity<N, D, R>
|
||||||
where
|
where
|
||||||
R: AlgaRotation<Point<N, D>>,
|
R: AbstractRotation<N, D>,
|
||||||
DefaultAllocator: Allocator<N, D>,
|
DefaultAllocator: Allocator<N, D>,
|
||||||
{
|
{
|
||||||
/// Creates a new identity similarity.
|
/// Creates a new identity similarity.
|
||||||
|
@ -47,7 +46,7 @@ where
|
||||||
|
|
||||||
impl<N: RealField, D: DimName, R> One for Similarity<N, D, R>
|
impl<N: RealField, D: DimName, R> One for Similarity<N, D, R>
|
||||||
where
|
where
|
||||||
R: AlgaRotation<Point<N, D>>,
|
R: AbstractRotation<N, D>,
|
||||||
DefaultAllocator: Allocator<N, D>,
|
DefaultAllocator: Allocator<N, D>,
|
||||||
{
|
{
|
||||||
/// Creates a new identity similarity.
|
/// Creates a new identity similarity.
|
||||||
|
@ -59,7 +58,7 @@ where
|
||||||
|
|
||||||
impl<N: RealField, D: DimName, R> Distribution<Similarity<N, D, R>> for Standard
|
impl<N: RealField, D: DimName, R> Distribution<Similarity<N, D, R>> for Standard
|
||||||
where
|
where
|
||||||
R: AlgaRotation<Point<N, D>>,
|
R: AbstractRotation<N, D>,
|
||||||
DefaultAllocator: Allocator<N, D>,
|
DefaultAllocator: Allocator<N, D>,
|
||||||
Standard: Distribution<N> + Distribution<R>,
|
Standard: Distribution<N> + Distribution<R>,
|
||||||
{
|
{
|
||||||
|
@ -76,7 +75,7 @@ where
|
||||||
|
|
||||||
impl<N: RealField, D: DimName, R> Similarity<N, D, R>
|
impl<N: RealField, D: DimName, R> Similarity<N, D, R>
|
||||||
where
|
where
|
||||||
R: AlgaRotation<Point<N, D>>,
|
R: AbstractRotation<N, D>,
|
||||||
DefaultAllocator: Allocator<N, D>,
|
DefaultAllocator: Allocator<N, D>,
|
||||||
{
|
{
|
||||||
/// The similarity that applies the scaling factor `scaling`, followed by the rotation `r` with
|
/// The similarity that applies the scaling factor `scaling`, followed by the rotation `r` with
|
||||||
|
@ -105,7 +104,7 @@ where
|
||||||
impl<N, D: DimName, R> Arbitrary for Similarity<N, D, R>
|
impl<N, D: DimName, R> Arbitrary for Similarity<N, D, R>
|
||||||
where
|
where
|
||||||
N: RealField + Arbitrary + Send,
|
N: RealField + Arbitrary + Send,
|
||||||
R: AlgaRotation<Point<N, D>> + Arbitrary + Send,
|
R: AbstractRotation<N, D> + Arbitrary + Send,
|
||||||
DefaultAllocator: Allocator<N, D>,
|
DefaultAllocator: Allocator<N, D>,
|
||||||
Owned<N, D>: Send,
|
Owned<N, D>: Send,
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
use alga::general::{RealField, SubsetOf, SupersetOf};
|
use simba::scalar::{RealField, SubsetOf, SupersetOf};
|
||||||
use alga::linear::Rotation;
|
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::dimension::{DimMin, DimName, DimNameAdd, DimNameSum, U1};
|
use crate::base::dimension::{DimMin, DimName, DimNameAdd, DimNameSum, U1};
|
||||||
use crate::base::{DefaultAllocator, MatrixN};
|
use crate::base::{DefaultAllocator, MatrixN};
|
||||||
|
|
||||||
use crate::geometry::{Isometry, Point, Similarity, SuperTCategoryOf, TAffine, Transform, Translation};
|
use crate::geometry::{
|
||||||
|
AbstractRotation, Isometry, Similarity, SuperTCategoryOf, TAffine, Transform, Translation,
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This file provides the following conversions:
|
* This file provides the following conversions:
|
||||||
|
@ -20,8 +21,8 @@ impl<N1, N2, D: DimName, R1, R2> SubsetOf<Similarity<N2, D, R2>> for Similarity<
|
||||||
where
|
where
|
||||||
N1: RealField + SubsetOf<N2>,
|
N1: RealField + SubsetOf<N2>,
|
||||||
N2: RealField + SupersetOf<N1>,
|
N2: RealField + SupersetOf<N1>,
|
||||||
R1: Rotation<Point<N1, D>> + SubsetOf<R2>,
|
R1: AbstractRotation<N1, D> + SubsetOf<R2>,
|
||||||
R2: Rotation<Point<N2, D>>,
|
R2: AbstractRotation<N2, D>,
|
||||||
DefaultAllocator: Allocator<N1, D> + Allocator<N2, D>,
|
DefaultAllocator: Allocator<N1, D> + Allocator<N2, D>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -36,7 +37,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(sim: &Similarity<N2, D, R2>) -> Self {
|
fn from_superset_unchecked(sim: &Similarity<N2, D, R2>) -> Self {
|
||||||
Similarity::from_isometry(
|
Similarity::from_isometry(
|
||||||
sim.isometry.to_subset_unchecked(),
|
sim.isometry.to_subset_unchecked(),
|
||||||
sim.scaling().to_subset_unchecked(),
|
sim.scaling().to_subset_unchecked(),
|
||||||
|
@ -49,7 +50,7 @@ where
|
||||||
N1: RealField,
|
N1: RealField,
|
||||||
N2: RealField + SupersetOf<N1>,
|
N2: RealField + SupersetOf<N1>,
|
||||||
C: SuperTCategoryOf<TAffine>,
|
C: SuperTCategoryOf<TAffine>,
|
||||||
R: Rotation<Point<N1, D>>
|
R: AbstractRotation<N1, D>
|
||||||
+ SubsetOf<MatrixN<N1, DimNameSum<D, U1>>>
|
+ SubsetOf<MatrixN<N1, DimNameSum<D, U1>>>
|
||||||
+ SubsetOf<MatrixN<N2, DimNameSum<D, U1>>>,
|
+ SubsetOf<MatrixN<N2, DimNameSum<D, U1>>>,
|
||||||
D: DimNameAdd<U1> + DimMin<D, Output = D>, // needed by .determinant()
|
D: DimNameAdd<U1> + DimMin<D, Output = D>, // needed by .determinant()
|
||||||
|
@ -73,7 +74,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(t: &Transform<N2, D, C>) -> Self {
|
fn from_superset_unchecked(t: &Transform<N2, D, C>) -> Self {
|
||||||
Self::from_superset_unchecked(t.matrix())
|
Self::from_superset_unchecked(t.matrix())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,7 +83,7 @@ impl<N1, N2, D, R> SubsetOf<MatrixN<N2, DimNameSum<D, U1>>> for Similarity<N1, D
|
||||||
where
|
where
|
||||||
N1: RealField,
|
N1: RealField,
|
||||||
N2: RealField + SupersetOf<N1>,
|
N2: RealField + SupersetOf<N1>,
|
||||||
R: Rotation<Point<N1, D>>
|
R: AbstractRotation<N1, D>
|
||||||
+ SubsetOf<MatrixN<N1, DimNameSum<D, U1>>>
|
+ SubsetOf<MatrixN<N1, DimNameSum<D, U1>>>
|
||||||
+ SubsetOf<MatrixN<N2, DimNameSum<D, U1>>>,
|
+ SubsetOf<MatrixN<N2, DimNameSum<D, U1>>>,
|
||||||
D: DimNameAdd<U1> + DimMin<D, Output = D>, // needed by .determinant()
|
D: DimNameAdd<U1> + DimMin<D, Output = D>, // needed by .determinant()
|
||||||
|
@ -137,7 +138,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(m: &MatrixN<N2, DimNameSum<D, U1>>) -> Self {
|
fn from_superset_unchecked(m: &MatrixN<N2, DimNameSum<D, U1>>) -> Self {
|
||||||
let mut mm = m.clone_owned();
|
let mut mm = m.clone_owned();
|
||||||
let na = mm.fixed_slice_mut::<D, U1>(0, 0).normalize_mut();
|
let na = mm.fixed_slice_mut::<D, U1>(0, 0).normalize_mut();
|
||||||
let nb = mm.fixed_slice_mut::<D, U1>(0, 1).normalize_mut();
|
let nb = mm.fixed_slice_mut::<D, U1>(0, 1).normalize_mut();
|
||||||
|
@ -159,7 +160,11 @@ where
|
||||||
vector: crate::convert_unchecked(t),
|
vector: crate::convert_unchecked(t),
|
||||||
};
|
};
|
||||||
|
|
||||||
Self::from_parts(t, crate::convert_unchecked(mm), crate::convert_unchecked(scale))
|
Self::from_parts(
|
||||||
|
t,
|
||||||
|
crate::convert_unchecked(mm),
|
||||||
|
crate::convert_unchecked(scale),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
|
use num::{One, Zero};
|
||||||
use std::ops::{Div, DivAssign, Mul, MulAssign};
|
use std::ops::{Div, DivAssign, Mul, MulAssign};
|
||||||
|
|
||||||
use alga::general::RealField;
|
use simba::scalar::{ClosedAdd, ClosedMul, RealField};
|
||||||
use alga::linear::Rotation as AlgaRotation;
|
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::dimension::{DimName, U1, U3, U4};
|
use crate::base::dimension::{DimName, U1, U3, U4};
|
||||||
use crate::base::{DefaultAllocator, VectorN};
|
use crate::base::{DefaultAllocator, Scalar, VectorN};
|
||||||
|
|
||||||
use crate::geometry::{Isometry, Point, Rotation, Similarity, Translation, UnitQuaternion};
|
use crate::geometry::{
|
||||||
|
AbstractRotation, Isometry, Point, Rotation, Similarity, Translation, UnitQuaternion,
|
||||||
|
};
|
||||||
|
|
||||||
// FIXME: there are several cloning of rotations that we could probably get rid of (but we didn't
|
// 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>`
|
// yet because that would require to add a bound like `where for<'a, 'b> &'a R: Mul<&'b R, Output = R>`
|
||||||
|
@ -67,7 +69,7 @@ macro_rules! similarity_binop_impl(
|
||||||
$lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty, Output = $Output: ty;
|
$lhs: ident: $Lhs: ty, $rhs: ident: $Rhs: ty, Output = $Output: ty;
|
||||||
$action: expr; $($lives: tt),*) => {
|
$action: expr; $($lives: tt),*) => {
|
||||||
impl<$($lives ,)* N: RealField, D: DimName, R> $Op<$Rhs> for $Lhs
|
impl<$($lives ,)* N: RealField, D: DimName, R> $Op<$Rhs> for $Lhs
|
||||||
where R: AlgaRotation<Point<N, D>>,
|
where R: AbstractRotation<N, D>,
|
||||||
DefaultAllocator: Allocator<N, D> {
|
DefaultAllocator: Allocator<N, D> {
|
||||||
type Output = $Output;
|
type Output = $Output;
|
||||||
|
|
||||||
|
@ -114,7 +116,7 @@ macro_rules! similarity_binop_assign_impl_all(
|
||||||
[val] => $action_val: expr;
|
[val] => $action_val: expr;
|
||||||
[ref] => $action_ref: expr;) => {
|
[ref] => $action_ref: expr;) => {
|
||||||
impl<N: RealField, D: DimName, R> $OpAssign<$Rhs> for $Lhs
|
impl<N: RealField, D: DimName, R> $OpAssign<$Rhs> for $Lhs
|
||||||
where R: AlgaRotation<Point<N, D>>,
|
where R: AbstractRotation<N, D>,
|
||||||
DefaultAllocator: Allocator<N, D> {
|
DefaultAllocator: Allocator<N, D> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn $op_assign(&mut $lhs, $rhs: $Rhs) {
|
fn $op_assign(&mut $lhs, $rhs: $Rhs) {
|
||||||
|
@ -123,7 +125,7 @@ macro_rules! similarity_binop_assign_impl_all(
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'b, N: RealField, D: DimName, R> $OpAssign<&'b $Rhs> for $Lhs
|
impl<'b, N: RealField, D: DimName, R> $OpAssign<&'b $Rhs> for $Lhs
|
||||||
where R: AlgaRotation<Point<N, D>>,
|
where R: AbstractRotation<N, D>,
|
||||||
DefaultAllocator: Allocator<N, D> {
|
DefaultAllocator: Allocator<N, D> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn $op_assign(&mut $lhs, $rhs: &'b $Rhs) {
|
fn $op_assign(&mut $lhs, $rhs: &'b $Rhs) {
|
||||||
|
@ -211,51 +213,38 @@ similarity_binop_assign_impl_all!(
|
||||||
|
|
||||||
// Similarity ×= R
|
// Similarity ×= R
|
||||||
// Similarity ÷= R
|
// Similarity ÷= R
|
||||||
similarity_binop_assign_impl_all!(
|
md_assign_impl_all!(
|
||||||
MulAssign, mul_assign;
|
MulAssign, mul_assign where N: RealField;
|
||||||
self: Similarity<N, D, R>, rhs: R;
|
(D, U1), (D, D) for D: DimName;
|
||||||
|
self: Similarity<N, D, Rotation<N, D>>, rhs: Rotation<N, D>;
|
||||||
[val] => self.isometry.rotation *= rhs;
|
[val] => self.isometry.rotation *= rhs;
|
||||||
[ref] => self.isometry.rotation *= rhs.clone();
|
[ref] => self.isometry.rotation *= rhs.clone();
|
||||||
);
|
);
|
||||||
|
|
||||||
similarity_binop_assign_impl_all!(
|
md_assign_impl_all!(
|
||||||
DivAssign, div_assign;
|
DivAssign, div_assign where N: RealField;
|
||||||
self: Similarity<N, D, R>, rhs: R;
|
(D, U1), (D, D) for D: DimName;
|
||||||
|
self: Similarity<N, D, Rotation<N, D>>, rhs: Rotation<N, D>;
|
||||||
// FIXME: don't invert explicitly?
|
// FIXME: don't invert explicitly?
|
||||||
[val] => *self *= rhs.two_sided_inverse();
|
[val] => *self *= rhs.inverse();
|
||||||
[ref] => *self *= rhs.two_sided_inverse();
|
[ref] => *self *= rhs.inverse();
|
||||||
);
|
);
|
||||||
|
|
||||||
// Similarity × R
|
md_assign_impl_all!(
|
||||||
// Similarity ÷ R
|
MulAssign, mul_assign where N: RealField;
|
||||||
similarity_binop_impl_all!(
|
(U3, U3), (U3, U3) for;
|
||||||
Mul, mul;
|
self: Similarity<N, U3, UnitQuaternion<N>>, rhs: UnitQuaternion<N>;
|
||||||
self: Similarity<N, D, R>, rhs: R, Output = Similarity<N, D, R>;
|
[val] => self.isometry.rotation *= rhs;
|
||||||
[val val] => {
|
[ref] => self.isometry.rotation *= rhs.clone();
|
||||||
let scaling = self.scaling();
|
|
||||||
Similarity::from_isometry(self.isometry * rhs, scaling)
|
|
||||||
};
|
|
||||||
[ref val] => Similarity::from_isometry(&self.isometry * rhs, self.scaling());
|
|
||||||
[val ref] => {
|
|
||||||
let scaling = self.scaling();
|
|
||||||
Similarity::from_isometry(self.isometry * rhs, scaling)
|
|
||||||
};
|
|
||||||
[ref ref] => Similarity::from_isometry(&self.isometry * rhs, self.scaling());
|
|
||||||
);
|
);
|
||||||
|
|
||||||
similarity_binop_impl_all!(
|
md_assign_impl_all!(
|
||||||
Div, div;
|
DivAssign, div_assign where N: RealField;
|
||||||
self: Similarity<N, D, R>, rhs: R, Output = Similarity<N, D, R>;
|
(U3, U3), (U3, U3) for;
|
||||||
[val val] => {
|
self: Similarity<N, U3, UnitQuaternion<N>>, rhs: UnitQuaternion<N>;
|
||||||
let scaling = self.scaling();
|
// FIXME: don't invert explicitly?
|
||||||
Similarity::from_isometry(self.isometry / rhs, scaling)
|
[val] => *self *= rhs.inverse();
|
||||||
};
|
[ref] => *self *= rhs.inverse();
|
||||||
[ref val] => Similarity::from_isometry(&self.isometry / rhs, self.scaling());
|
|
||||||
[val ref] => {
|
|
||||||
let scaling = self.scaling();
|
|
||||||
Similarity::from_isometry(self.isometry / rhs, scaling)
|
|
||||||
};
|
|
||||||
[ref ref] => Similarity::from_isometry(&self.isometry / rhs, self.scaling());
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Similarity × Isometry
|
// Similarity × Isometry
|
||||||
|
@ -427,6 +416,24 @@ macro_rules! similarity_from_composition_impl_all(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Similarity × Rotation
|
||||||
|
similarity_from_composition_impl_all!(
|
||||||
|
Mul, mul;
|
||||||
|
(D, D), (D, U1) for D: DimName;
|
||||||
|
self: Similarity<N, D, Rotation<N, D>>, rhs: Rotation<N, D>,
|
||||||
|
Output = Similarity<N, D, Rotation<N, D>>;
|
||||||
|
[val val] => {
|
||||||
|
let scaling = self.scaling();
|
||||||
|
Similarity::from_isometry(self.isometry * rhs, scaling)
|
||||||
|
};
|
||||||
|
[ref val] => Similarity::from_isometry(&self.isometry * rhs, self.scaling());
|
||||||
|
[val ref] => {
|
||||||
|
let scaling = self.scaling();
|
||||||
|
Similarity::from_isometry(self.isometry * rhs, scaling)
|
||||||
|
};
|
||||||
|
[ref ref] => Similarity::from_isometry(&self.isometry * rhs, self.scaling());
|
||||||
|
);
|
||||||
|
|
||||||
// Rotation × Similarity
|
// Rotation × Similarity
|
||||||
similarity_from_composition_impl_all!(
|
similarity_from_composition_impl_all!(
|
||||||
Mul, mul;
|
Mul, mul;
|
||||||
|
@ -439,6 +446,24 @@ similarity_from_composition_impl_all!(
|
||||||
[ref ref] => Similarity::from_isometry(self * &right.isometry, right.scaling());
|
[ref ref] => Similarity::from_isometry(self * &right.isometry, right.scaling());
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Similarity ÷ Rotation
|
||||||
|
similarity_from_composition_impl_all!(
|
||||||
|
Div, div;
|
||||||
|
(D, D), (D, U1) for D: DimName;
|
||||||
|
self: Similarity<N, D, Rotation<N, D>>, rhs: Rotation<N, D>,
|
||||||
|
Output = Similarity<N, D, Rotation<N, D>>;
|
||||||
|
[val val] => {
|
||||||
|
let scaling = self.scaling();
|
||||||
|
Similarity::from_isometry(self.isometry / rhs, scaling)
|
||||||
|
};
|
||||||
|
[ref val] => Similarity::from_isometry(&self.isometry / rhs, self.scaling());
|
||||||
|
[val ref] => {
|
||||||
|
let scaling = self.scaling();
|
||||||
|
Similarity::from_isometry(self.isometry / rhs, scaling)
|
||||||
|
};
|
||||||
|
[ref ref] => Similarity::from_isometry(&self.isometry / rhs, self.scaling());
|
||||||
|
);
|
||||||
|
|
||||||
// Rotation ÷ Similarity
|
// Rotation ÷ Similarity
|
||||||
similarity_from_composition_impl_all!(
|
similarity_from_composition_impl_all!(
|
||||||
Div, div;
|
Div, div;
|
||||||
|
@ -452,6 +477,24 @@ similarity_from_composition_impl_all!(
|
||||||
[ref ref] => self * right.inverse();
|
[ref ref] => self * right.inverse();
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Similarity × UnitQuaternion
|
||||||
|
similarity_from_composition_impl_all!(
|
||||||
|
Mul, mul;
|
||||||
|
(U4, U1), (U3, U1);
|
||||||
|
self: Similarity<N, U3, UnitQuaternion<N>>, rhs: UnitQuaternion<N>,
|
||||||
|
Output = Similarity<N, U3, UnitQuaternion<N>>;
|
||||||
|
[val val] => {
|
||||||
|
let scaling = self.scaling();
|
||||||
|
Similarity::from_isometry(self.isometry * rhs, scaling)
|
||||||
|
};
|
||||||
|
[ref val] => Similarity::from_isometry(&self.isometry * rhs, self.scaling());
|
||||||
|
[val ref] => {
|
||||||
|
let scaling = self.scaling();
|
||||||
|
Similarity::from_isometry(self.isometry * rhs, scaling)
|
||||||
|
};
|
||||||
|
[ref ref] => Similarity::from_isometry(&self.isometry * rhs, self.scaling());
|
||||||
|
);
|
||||||
|
|
||||||
// UnitQuaternion × Similarity
|
// UnitQuaternion × Similarity
|
||||||
similarity_from_composition_impl_all!(
|
similarity_from_composition_impl_all!(
|
||||||
Mul, mul;
|
Mul, mul;
|
||||||
|
@ -464,6 +507,24 @@ similarity_from_composition_impl_all!(
|
||||||
[ref ref] => Similarity::from_isometry(self * &right.isometry, right.scaling());
|
[ref ref] => Similarity::from_isometry(self * &right.isometry, right.scaling());
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Similarity ÷ Rotation
|
||||||
|
similarity_from_composition_impl_all!(
|
||||||
|
Div, div;
|
||||||
|
(U4, U1), (U3, U1);
|
||||||
|
self: Similarity<N, U3, UnitQuaternion<N>>, rhs: UnitQuaternion<N>,
|
||||||
|
Output = Similarity<N, U3, UnitQuaternion<N>>;
|
||||||
|
[val val] => {
|
||||||
|
let scaling = self.scaling();
|
||||||
|
Similarity::from_isometry(self.isometry / rhs, scaling)
|
||||||
|
};
|
||||||
|
[ref val] => Similarity::from_isometry(&self.isometry / rhs, self.scaling());
|
||||||
|
[val ref] => {
|
||||||
|
let scaling = self.scaling();
|
||||||
|
Similarity::from_isometry(self.isometry / rhs, scaling)
|
||||||
|
};
|
||||||
|
[ref ref] => Similarity::from_isometry(&self.isometry / rhs, self.scaling());
|
||||||
|
);
|
||||||
|
|
||||||
// UnitQuaternion ÷ Similarity
|
// UnitQuaternion ÷ Similarity
|
||||||
similarity_from_composition_impl_all!(
|
similarity_from_composition_impl_all!(
|
||||||
Div, div;
|
Div, div;
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
use simba::simd::SimdValue;
|
||||||
|
|
||||||
|
use crate::base::allocator::Allocator;
|
||||||
|
use crate::base::dimension::DimName;
|
||||||
|
use crate::base::{DefaultAllocator, Scalar};
|
||||||
|
use crate::RealField;
|
||||||
|
|
||||||
|
use crate::geometry::{AbstractRotation, Isometry, Similarity};
|
||||||
|
|
||||||
|
impl<N: RealField, D: DimName, R> SimdValue for Similarity<N, D, R>
|
||||||
|
where
|
||||||
|
N::Element: Scalar,
|
||||||
|
R: SimdValue<SimdBool = N::SimdBool> + AbstractRotation<N, D>,
|
||||||
|
R::Element: AbstractRotation<N, D>,
|
||||||
|
DefaultAllocator: Allocator<N, D>,
|
||||||
|
{
|
||||||
|
type Element = Similarity<N::Element, D, R::Element>;
|
||||||
|
type SimdBool = N::SimdBool;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn lanes() -> usize {
|
||||||
|
N::lanes()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn splat(val: Self::Element) -> Self {
|
||||||
|
let scaling = N::splat(val.scaling());
|
||||||
|
Similarity::from_isometry(Isometry::splat(val.isometry), scaling)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn extract(&self, i: usize) -> Self::Element {
|
||||||
|
Similarity::from_isometry(self.isometry.extract(i), self.scaling().extract(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn extract_unchecked(&self, i: usize) -> Self::Element {
|
||||||
|
Similarity::from_isometry(
|
||||||
|
self.isometry.extract_unchecked(i),
|
||||||
|
self.scaling().extract_unchecked(i),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn replace(&mut self, i: usize, val: Self::Element) {
|
||||||
|
let mut s = self.scaling();
|
||||||
|
s.replace(i, val.scaling());
|
||||||
|
self.set_scaling(s);
|
||||||
|
self.isometry.replace(i, val.isometry);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn replace_unchecked(&mut self, i: usize, val: Self::Element) {
|
||||||
|
let mut s = self.scaling();
|
||||||
|
s.replace_unchecked(i, val.scaling());
|
||||||
|
self.set_scaling(s);
|
||||||
|
self.isometry.replace_unchecked(i, val.isometry);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn select(self, cond: Self::SimdBool, other: Self) -> Self {
|
||||||
|
let scaling = self.scaling().select(cond, other.scaling());
|
||||||
|
Similarity::from_isometry(self.isometry.select(cond, other.isometry), scaling)
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,7 +6,7 @@ use std::marker::PhantomData;
|
||||||
#[cfg(feature = "serde-serialize")]
|
#[cfg(feature = "serde-serialize")]
|
||||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||||
|
|
||||||
use alga::general::{RealField, TwoSidedInverse};
|
use simba::scalar::RealField;
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1};
|
use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1};
|
||||||
|
@ -259,7 +259,7 @@ where DefaultAllocator: Allocator<N, DimNameSum<D, U1>, DimNameSum<D, U1>>
|
||||||
|
|
||||||
/// Retrieves the underlying matrix.
|
/// Retrieves the underlying matrix.
|
||||||
/// Deprecated: Use [Transform::into_inner] instead.
|
/// Deprecated: Use [Transform::into_inner] instead.
|
||||||
#[deprecated(note="use `.into_inner()` instead")]
|
#[deprecated(note = "use `.into_inner()` instead")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn unwrap(self) -> MatrixN<N, DimNameSum<D, U1>> {
|
pub fn unwrap(self) -> MatrixN<N, DimNameSum<D, U1>> {
|
||||||
self.matrix
|
self.matrix
|
||||||
|
@ -484,8 +484,9 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: RealField, D: DimNameAdd<U1>, C: TCategory> Transform<N, D, C>
|
impl<N: RealField, D: DimNameAdd<U1>, C: TCategory> Transform<N, D, C>
|
||||||
where C: SubTCategoryOf<TProjective>,
|
where
|
||||||
DefaultAllocator: Allocator<N, DimNameSum<D, U1>, DimNameSum<D, U1>>
|
C: SubTCategoryOf<TProjective>,
|
||||||
|
DefaultAllocator: Allocator<N, DimNameSum<D, U1>, DimNameSum<D, U1>>
|
||||||
+ Allocator<N, DimNameSum<D, U1>>
|
+ Allocator<N, DimNameSum<D, U1>>
|
||||||
+ Allocator<N, D, D>
|
+ Allocator<N, D, D>
|
||||||
+ Allocator<N, D>,
|
+ Allocator<N, D>,
|
||||||
|
@ -495,7 +496,7 @@ where C: SubTCategoryOf<TProjective>,
|
||||||
/// the point.
|
/// the point.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn inverse_transform_point(&self, pt: &Point<N, D>) -> Point<N, D> {
|
pub fn inverse_transform_point(&self, pt: &Point<N, D>) -> Point<N, D> {
|
||||||
self.two_sided_inverse() * pt
|
self.clone().inverse() * pt
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transform the given vector by the inverse of this transformation.
|
/// Transform the given vector by the inverse of this transformation.
|
||||||
|
@ -503,7 +504,7 @@ where C: SubTCategoryOf<TProjective>,
|
||||||
/// the vector.
|
/// the vector.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn inverse_transform_vector(&self, v: &VectorN<N, D>) -> VectorN<N, D> {
|
pub fn inverse_transform_vector(&self, v: &VectorN<N, D>) -> VectorN<N, D> {
|
||||||
self.two_sided_inverse() * v
|
self.clone().inverse() * v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,146 +0,0 @@
|
||||||
use alga::general::{
|
|
||||||
AbstractGroup, AbstractLoop, AbstractMagma, AbstractMonoid, AbstractQuasigroup,
|
|
||||||
AbstractSemigroup, Identity, TwoSidedInverse, Multiplicative, RealField,
|
|
||||||
};
|
|
||||||
use alga::linear::{ProjectiveTransformation, Transformation};
|
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
|
||||||
use crate::base::dimension::{DimNameAdd, DimNameSum, U1};
|
|
||||||
use crate::base::{DefaultAllocator, VectorN};
|
|
||||||
|
|
||||||
use crate::geometry::{Point, SubTCategoryOf, TCategory, TProjective, Transform};
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Algebraic structures.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
impl<N: RealField, D: DimNameAdd<U1>, C> Identity<Multiplicative> for Transform<N, D, C>
|
|
||||||
where
|
|
||||||
C: TCategory,
|
|
||||||
DefaultAllocator: Allocator<N, DimNameSum<D, U1>, DimNameSum<D, U1>>,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn identity() -> Self {
|
|
||||||
Self::identity()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField, D: DimNameAdd<U1>, C> TwoSidedInverse<Multiplicative> for Transform<N, D, C>
|
|
||||||
where
|
|
||||||
C: SubTCategoryOf<TProjective>,
|
|
||||||
DefaultAllocator: Allocator<N, DimNameSum<D, U1>, DimNameSum<D, U1>>,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
#[must_use = "Did you mean to use two_sided_inverse_mut()?"]
|
|
||||||
fn two_sided_inverse(&self) -> Self {
|
|
||||||
self.clone().inverse()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn two_sided_inverse_mut(&mut self) {
|
|
||||||
self.inverse_mut()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField, D: DimNameAdd<U1>, C> AbstractMagma<Multiplicative> for Transform<N, D, C>
|
|
||||||
where
|
|
||||||
C: TCategory,
|
|
||||||
DefaultAllocator: Allocator<N, DimNameSum<D, U1>, DimNameSum<D, U1>>,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn operate(&self, rhs: &Self) -> Self {
|
|
||||||
self * rhs
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_multiplicative_structures(
|
|
||||||
($($marker: ident<$operator: ident>),* $(,)*) => {$(
|
|
||||||
impl<N: RealField, D: DimNameAdd<U1>, C> $marker<$operator> for Transform<N, D, C>
|
|
||||||
where C: TCategory,
|
|
||||||
DefaultAllocator: Allocator<N, DimNameSum<D, U1>, DimNameSum<D, U1>> { }
|
|
||||||
)*}
|
|
||||||
);
|
|
||||||
|
|
||||||
macro_rules! impl_inversible_multiplicative_structures(
|
|
||||||
($($marker: ident<$operator: ident>),* $(,)*) => {$(
|
|
||||||
impl<N: RealField, D: DimNameAdd<U1>, C> $marker<$operator> for Transform<N, D, C>
|
|
||||||
where C: SubTCategoryOf<TProjective>,
|
|
||||||
DefaultAllocator: Allocator<N, DimNameSum<D, U1>, DimNameSum<D, U1>> { }
|
|
||||||
)*}
|
|
||||||
);
|
|
||||||
|
|
||||||
impl_multiplicative_structures!(
|
|
||||||
AbstractSemigroup<Multiplicative>,
|
|
||||||
AbstractMonoid<Multiplicative>,
|
|
||||||
);
|
|
||||||
|
|
||||||
impl_inversible_multiplicative_structures!(
|
|
||||||
AbstractQuasigroup<Multiplicative>,
|
|
||||||
AbstractLoop<Multiplicative>,
|
|
||||||
AbstractGroup<Multiplicative>
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Transformation groups.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
impl<N, D: DimNameAdd<U1>, C> Transformation<Point<N, D>> for Transform<N, D, C>
|
|
||||||
where
|
|
||||||
N: RealField,
|
|
||||||
C: TCategory,
|
|
||||||
DefaultAllocator: Allocator<N, DimNameSum<D, U1>, DimNameSum<D, U1>>
|
|
||||||
+ Allocator<N, DimNameSum<D, U1>>
|
|
||||||
+ Allocator<N, D, D>
|
|
||||||
+ Allocator<N, D>,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn transform_point(&self, pt: &Point<N, D>) -> Point<N, D> {
|
|
||||||
self.transform_point(pt)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn transform_vector(&self, v: &VectorN<N, D>) -> VectorN<N, D> {
|
|
||||||
self.transform_vector(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N, D: DimNameAdd<U1>, C> ProjectiveTransformation<Point<N, D>> for Transform<N, D, C>
|
|
||||||
where
|
|
||||||
N: RealField,
|
|
||||||
C: SubTCategoryOf<TProjective>,
|
|
||||||
DefaultAllocator: Allocator<N, DimNameSum<D, U1>, DimNameSum<D, U1>>
|
|
||||||
+ Allocator<N, DimNameSum<D, U1>>
|
|
||||||
+ Allocator<N, D, D>
|
|
||||||
+ Allocator<N, D>,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn inverse_transform_point(&self, pt: &Point<N, D>) -> Point<N, D> {
|
|
||||||
self.inverse_transform_point(pt)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn inverse_transform_vector(&self, v: &VectorN<N, D>) -> VectorN<N, D> {
|
|
||||||
self.inverse_transform_vector(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: we need to implement an SVD for this.
|
|
||||||
//
|
|
||||||
// impl<N, D: DimNameAdd<U1>, C> AffineTransformation<Point<N, D>> for Transform<N, D, C>
|
|
||||||
// where N: RealField,
|
|
||||||
// C: SubTCategoryOf<TAffine>,
|
|
||||||
// DefaultAllocator: Allocator<N, DimNameSum<D, U1>, DimNameSum<D, U1>> +
|
|
||||||
// Allocator<N, D, D> +
|
|
||||||
// Allocator<N, D> {
|
|
||||||
// type PreRotation = Rotation<N, D>;
|
|
||||||
// type NonUniformScaling = VectorN<N, D>;
|
|
||||||
// type PostRotation = Rotation<N, D>;
|
|
||||||
// type Translation = Translation<N, D>;
|
|
||||||
//
|
|
||||||
// #[inline]
|
|
||||||
// fn decompose(&self) -> (Self::Translation, Self::PostRotation, Self::NonUniformScaling, Self::PreRotation) {
|
|
||||||
// unimplemented!()
|
|
||||||
// }
|
|
||||||
// }
|
|
|
@ -1,6 +1,6 @@
|
||||||
use num::One;
|
use num::One;
|
||||||
|
|
||||||
use alga::general::RealField;
|
use simba::scalar::RealField;
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::dimension::{DimNameAdd, DimNameSum, U1};
|
use crate::base::dimension::{DimNameAdd, DimNameSum, U1};
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use alga::general::{RealField, SubsetOf};
|
use simba::scalar::{RealField, SubsetOf};
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1};
|
use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1};
|
||||||
|
@ -29,7 +29,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(t: &Transform<N2, D, C2>) -> Self {
|
fn from_superset_unchecked(t: &Transform<N2, D, C2>) -> Self {
|
||||||
Self::from_superset_unchecked(t.matrix())
|
Self::from_superset_unchecked(t.matrix())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(m: &MatrixN<N2, DimNameSum<D, U1>>) -> Self {
|
fn from_superset_unchecked(m: &MatrixN<N2, DimNameSum<D, U1>>) -> Self {
|
||||||
Self::from_matrix_unchecked(crate::convert_ref_unchecked(m))
|
Self::from_matrix_unchecked(crate::convert_ref_unchecked(m))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use num::{One, Zero};
|
use num::{One, Zero};
|
||||||
use std::ops::{Div, DivAssign, Index, IndexMut, Mul, MulAssign};
|
use std::ops::{Div, DivAssign, Index, IndexMut, Mul, MulAssign};
|
||||||
|
|
||||||
use alga::general::{ClosedAdd, ClosedMul, RealField, SubsetOf};
|
use simba::scalar::{ClosedAdd, ClosedMul, RealField, SubsetOf};
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1, U3, U4};
|
use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1, U3, U4};
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
use simba::simd::SimdValue;
|
||||||
|
|
||||||
|
use crate::base::allocator::Allocator;
|
||||||
|
use crate::base::dimension::{DimNameAdd, DimNameSum, U1};
|
||||||
|
use crate::base::{DefaultAllocator, MatrixN, Scalar};
|
||||||
|
use crate::RealField;
|
||||||
|
|
||||||
|
use crate::geometry::{TCategory, Transform};
|
||||||
|
|
||||||
|
impl<N: RealField, D: DimNameAdd<U1>, C> SimdValue for Transform<N, D, C>
|
||||||
|
where
|
||||||
|
N::Element: Scalar,
|
||||||
|
C: TCategory,
|
||||||
|
DefaultAllocator: Allocator<N, DimNameSum<D, U1>, DimNameSum<D, U1>>
|
||||||
|
+ Allocator<N::Element, DimNameSum<D, U1>, DimNameSum<D, U1>>,
|
||||||
|
{
|
||||||
|
type Element = Transform<N::Element, D, C>;
|
||||||
|
type SimdBool = N::SimdBool;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn lanes() -> usize {
|
||||||
|
N::lanes()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn splat(val: Self::Element) -> Self {
|
||||||
|
Transform::from_matrix_unchecked(MatrixN::splat(val.into_inner()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn extract(&self, i: usize) -> Self::Element {
|
||||||
|
Transform::from_matrix_unchecked(self.matrix().extract(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn extract_unchecked(&self, i: usize) -> Self::Element {
|
||||||
|
Transform::from_matrix_unchecked(self.matrix().extract_unchecked(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn replace(&mut self, i: usize, val: Self::Element) {
|
||||||
|
self.matrix_mut_unchecked().replace(i, val.into_inner())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn replace_unchecked(&mut self, i: usize, val: Self::Element) {
|
||||||
|
self.matrix_mut_unchecked()
|
||||||
|
.replace_unchecked(i, val.into_inner())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn select(self, cond: Self::SimdBool, other: Self) -> Self {
|
||||||
|
Transform::from_matrix_unchecked(self.into_inner().select(cond, other.into_inner()))
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,7 +11,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||||
#[cfg(feature = "abomonation-serialize")]
|
#[cfg(feature = "abomonation-serialize")]
|
||||||
use abomonation::Abomonation;
|
use abomonation::Abomonation;
|
||||||
|
|
||||||
use alga::general::{ClosedAdd, ClosedNeg, ClosedSub, RealField};
|
use simba::scalar::{ClosedAdd, ClosedNeg, ClosedSub, RealField};
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1};
|
use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1};
|
||||||
|
@ -45,7 +45,8 @@ impl<N: Scalar + Copy, D: DimName> Copy for Translation<N, D>
|
||||||
where
|
where
|
||||||
DefaultAllocator: Allocator<N, D>,
|
DefaultAllocator: Allocator<N, D>,
|
||||||
Owned<N, D>: Copy,
|
Owned<N, D>: Copy,
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
impl<N: Scalar, D: DimName> Clone for Translation<N, D>
|
impl<N: Scalar, D: DimName> Clone for Translation<N, D>
|
||||||
where
|
where
|
||||||
|
@ -302,7 +303,7 @@ where
|
||||||
* Display
|
* Display
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
impl<N: RealField + fmt::Display, D: DimName> fmt::Display for Translation<N, D>
|
impl<N: Scalar + fmt::Display, D: DimName> fmt::Display for Translation<N, D>
|
||||||
where DefaultAllocator: Allocator<N, D> + Allocator<usize, D>
|
where DefaultAllocator: Allocator<N, D> + Allocator<usize, D>
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
|
|
@ -1,199 +1,52 @@
|
||||||
use alga::general::{
|
use simba::simd::SimdValue;
|
||||||
AbstractGroup, AbstractLoop, AbstractMagma, AbstractMonoid, AbstractQuasigroup,
|
|
||||||
AbstractSemigroup, Id, Identity, TwoSidedInverse, Multiplicative, RealField,
|
|
||||||
};
|
|
||||||
use alga::linear::Translation as AlgaTranslation;
|
|
||||||
use alga::linear::{
|
|
||||||
AffineTransformation, DirectIsometry, Isometry, ProjectiveTransformation, Similarity,
|
|
||||||
Transformation,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::dimension::DimName;
|
use crate::base::dimension::DimName;
|
||||||
use crate::base::{DefaultAllocator, VectorN};
|
use crate::base::{DefaultAllocator, VectorN};
|
||||||
|
use crate::Scalar;
|
||||||
|
|
||||||
use crate::geometry::{Point, Translation};
|
use crate::geometry::Translation;
|
||||||
|
|
||||||
/*
|
impl<N: Scalar + SimdValue, D: DimName> SimdValue for Translation<N, D>
|
||||||
*
|
where
|
||||||
* Algebraic structures.
|
N::Element: Scalar,
|
||||||
*
|
DefaultAllocator: Allocator<N, D> + Allocator<N::Element, D>,
|
||||||
*/
|
|
||||||
impl<N: RealField, D: DimName> Identity<Multiplicative> for Translation<N, D>
|
|
||||||
where DefaultAllocator: Allocator<N, D>
|
|
||||||
{
|
{
|
||||||
|
type Element = Translation<N::Element, D>;
|
||||||
|
type SimdBool = N::SimdBool;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn identity() -> Self {
|
fn lanes() -> usize {
|
||||||
Self::identity()
|
N::lanes()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
#[inline]
|
||||||
impl<N: RealField, D: DimName> TwoSidedInverse<Multiplicative> for Translation<N, D>
|
fn splat(val: Self::Element) -> Self {
|
||||||
where DefaultAllocator: Allocator<N, D>
|
VectorN::splat(val.vector).into()
|
||||||
{
|
}
|
||||||
#[inline]
|
|
||||||
#[must_use = "Did you mean to use two_sided_inverse_mut()?"]
|
#[inline]
|
||||||
fn two_sided_inverse(&self) -> Self {
|
fn extract(&self, i: usize) -> Self::Element {
|
||||||
self.inverse()
|
self.vector.extract(i).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn two_sided_inverse_mut(&mut self) {
|
unsafe fn extract_unchecked(&self, i: usize) -> Self::Element {
|
||||||
self.inverse_mut()
|
self.vector.extract_unchecked(i).into()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
#[inline]
|
||||||
impl<N: RealField, D: DimName> AbstractMagma<Multiplicative> for Translation<N, D>
|
fn replace(&mut self, i: usize, val: Self::Element) {
|
||||||
where DefaultAllocator: Allocator<N, D>
|
self.vector.replace(i, val.vector)
|
||||||
{
|
}
|
||||||
#[inline]
|
|
||||||
fn operate(&self, rhs: &Self) -> Self {
|
#[inline]
|
||||||
self * rhs
|
unsafe fn replace_unchecked(&mut self, i: usize, val: Self::Element) {
|
||||||
}
|
self.vector.replace_unchecked(i, val.vector)
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_multiplicative_structures(
|
#[inline]
|
||||||
($($marker: ident<$operator: ident>),* $(,)*) => {$(
|
fn select(self, cond: Self::SimdBool, other: Self) -> Self {
|
||||||
impl<N: RealField, D: DimName> $marker<$operator> for Translation<N, D>
|
self.vector.select(cond, other.vector).into()
|
||||||
where DefaultAllocator: Allocator<N, D> { }
|
|
||||||
)*}
|
|
||||||
);
|
|
||||||
|
|
||||||
impl_multiplicative_structures!(
|
|
||||||
AbstractSemigroup<Multiplicative>,
|
|
||||||
AbstractMonoid<Multiplicative>,
|
|
||||||
AbstractQuasigroup<Multiplicative>,
|
|
||||||
AbstractLoop<Multiplicative>,
|
|
||||||
AbstractGroup<Multiplicative>
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Transformation groups.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
impl<N: RealField, D: DimName> Transformation<Point<N, D>> for Translation<N, D>
|
|
||||||
where DefaultAllocator: Allocator<N, D>
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn transform_point(&self, pt: &Point<N, D>) -> Point<N, D> {
|
|
||||||
self.transform_point(pt)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn transform_vector(&self, v: &VectorN<N, D>) -> VectorN<N, D> {
|
|
||||||
v.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField, D: DimName> ProjectiveTransformation<Point<N, D>> for Translation<N, D>
|
|
||||||
where DefaultAllocator: Allocator<N, D>
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn inverse_transform_point(&self, pt: &Point<N, D>) -> Point<N, D> {
|
|
||||||
self.inverse_transform_point(pt)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn inverse_transform_vector(&self, v: &VectorN<N, D>) -> VectorN<N, D> {
|
|
||||||
v.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField, D: DimName> AffineTransformation<Point<N, D>> for Translation<N, D>
|
|
||||||
where DefaultAllocator: Allocator<N, D>
|
|
||||||
{
|
|
||||||
type Rotation = Id;
|
|
||||||
type NonUniformScaling = Id;
|
|
||||||
type Translation = Self;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn decompose(&self) -> (Self, Id, Id, Id) {
|
|
||||||
(self.clone(), Id::new(), Id::new(), Id::new())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn append_translation(&self, t: &Self::Translation) -> Self {
|
|
||||||
t * self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn prepend_translation(&self, t: &Self::Translation) -> Self {
|
|
||||||
self * t
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn append_rotation(&self, _: &Self::Rotation) -> Self {
|
|
||||||
self.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn prepend_rotation(&self, _: &Self::Rotation) -> Self {
|
|
||||||
self.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn append_scaling(&self, _: &Self::NonUniformScaling) -> Self {
|
|
||||||
self.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn prepend_scaling(&self, _: &Self::NonUniformScaling) -> Self {
|
|
||||||
self.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField, D: DimName> Similarity<Point<N, D>> for Translation<N, D>
|
|
||||||
where DefaultAllocator: Allocator<N, D>
|
|
||||||
{
|
|
||||||
type Scaling = Id;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn translation(&self) -> Self {
|
|
||||||
self.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn rotation(&self) -> Id {
|
|
||||||
Id::new()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn scaling(&self) -> Id {
|
|
||||||
Id::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! marker_impl(
|
|
||||||
($($Trait: ident),*) => {$(
|
|
||||||
impl<N: RealField, D: DimName> $Trait<Point<N, D>> for Translation<N, D>
|
|
||||||
where DefaultAllocator: Allocator<N, D> { }
|
|
||||||
)*}
|
|
||||||
);
|
|
||||||
|
|
||||||
marker_impl!(Isometry, DirectIsometry);
|
|
||||||
|
|
||||||
/// Subgroups of the n-dimensional translation group `T(n)`.
|
|
||||||
impl<N: RealField, D: DimName> AlgaTranslation<Point<N, D>> for Translation<N, D>
|
|
||||||
where DefaultAllocator: Allocator<N, D>
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn to_vector(&self) -> VectorN<N, D> {
|
|
||||||
self.vector.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn from_vector(v: VectorN<N, D>) -> Option<Self> {
|
|
||||||
Some(Self::from(v))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn powf(&self, n: N) -> Option<Self> {
|
|
||||||
Some(Self::from(&self.vector * n))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn translation_between(a: &Point<N, D>, b: &Point<N, D>) -> Option<Self> {
|
|
||||||
Some(Self::from(b - a))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ use num::{One, Zero};
|
||||||
use rand::distributions::{Distribution, Standard};
|
use rand::distributions::{Distribution, Standard};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
||||||
use alga::general::ClosedAdd;
|
use simba::scalar::ClosedAdd;
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::dimension::{DimName, U1, U2, U3, U4, U5, U6};
|
use crate::base::dimension::{DimName, U1, U2, U3, U4, U5, U6};
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
use num::{One, Zero};
|
use num::{One, Zero};
|
||||||
|
|
||||||
use alga::general::{RealField, SubsetOf, SupersetOf};
|
use simba::scalar::{RealField, SubsetOf, SupersetOf};
|
||||||
use alga::linear::Rotation;
|
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1};
|
use crate::base::dimension::{DimName, DimNameAdd, DimNameSum, U1};
|
||||||
use crate::base::{DefaultAllocator, MatrixN, Scalar, VectorN};
|
use crate::base::{DefaultAllocator, MatrixN, Scalar, VectorN};
|
||||||
|
|
||||||
use crate::geometry::{Isometry, Point, Similarity, SuperTCategoryOf, TAffine, Transform, Translation};
|
use crate::geometry::{
|
||||||
|
AbstractRotation, Isometry, Similarity, SuperTCategoryOf, TAffine, Transform, Translation,
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This file provides the following conversions:
|
* This file provides the following conversions:
|
||||||
|
@ -37,7 +38,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(rot: &Translation<N2, D>) -> Self {
|
fn from_superset_unchecked(rot: &Translation<N2, D>) -> Self {
|
||||||
Translation {
|
Translation {
|
||||||
vector: rot.vector.to_subset_unchecked(),
|
vector: rot.vector.to_subset_unchecked(),
|
||||||
}
|
}
|
||||||
|
@ -48,7 +49,7 @@ impl<N1, N2, D: DimName, R> SubsetOf<Isometry<N2, D, R>> for Translation<N1, D>
|
||||||
where
|
where
|
||||||
N1: RealField,
|
N1: RealField,
|
||||||
N2: RealField + SupersetOf<N1>,
|
N2: RealField + SupersetOf<N1>,
|
||||||
R: Rotation<Point<N2, D>>,
|
R: AbstractRotation<N2, D>,
|
||||||
DefaultAllocator: Allocator<N1, D> + Allocator<N2, D>,
|
DefaultAllocator: Allocator<N1, D> + Allocator<N2, D>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -62,7 +63,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(iso: &Isometry<N2, D, R>) -> Self {
|
fn from_superset_unchecked(iso: &Isometry<N2, D, R>) -> Self {
|
||||||
Self::from_superset_unchecked(&iso.translation)
|
Self::from_superset_unchecked(&iso.translation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,7 +72,7 @@ impl<N1, N2, D: DimName, R> SubsetOf<Similarity<N2, D, R>> for Translation<N1, D
|
||||||
where
|
where
|
||||||
N1: RealField,
|
N1: RealField,
|
||||||
N2: RealField + SupersetOf<N1>,
|
N2: RealField + SupersetOf<N1>,
|
||||||
R: Rotation<Point<N2, D>>,
|
R: AbstractRotation<N2, D>,
|
||||||
DefaultAllocator: Allocator<N1, D> + Allocator<N2, D>,
|
DefaultAllocator: Allocator<N1, D> + Allocator<N2, D>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -85,7 +86,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(sim: &Similarity<N2, D, R>) -> Self {
|
fn from_superset_unchecked(sim: &Similarity<N2, D, R>) -> Self {
|
||||||
Self::from_superset_unchecked(&sim.isometry.translation)
|
Self::from_superset_unchecked(&sim.isometry.translation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,7 +113,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(t: &Transform<N2, D, C>) -> Self {
|
fn from_superset_unchecked(t: &Transform<N2, D, C>) -> Self {
|
||||||
Self::from_superset_unchecked(t.matrix())
|
Self::from_superset_unchecked(t.matrix())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -145,7 +146,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(m: &MatrixN<N2, DimNameSum<D, U1>>) -> Self {
|
fn from_superset_unchecked(m: &MatrixN<N2, DimNameSum<D, U1>>) -> Self {
|
||||||
let t = m.fixed_slice::<D, U1>(0, D::dim());
|
let t = m.fixed_slice::<D, U1>(0, D::dim());
|
||||||
Self {
|
Self {
|
||||||
vector: crate::convert_unchecked(t.into_owned()),
|
vector: crate::convert_unchecked(t.into_owned()),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::ops::{Div, DivAssign, Mul, MulAssign};
|
use std::ops::{Div, DivAssign, Mul, MulAssign};
|
||||||
|
|
||||||
use alga::general::{ClosedAdd, ClosedSub};
|
use simba::scalar::{ClosedAdd, ClosedSub};
|
||||||
|
|
||||||
use crate::base::allocator::{Allocator, SameShapeAllocator};
|
use crate::base::allocator::{Allocator, SameShapeAllocator};
|
||||||
use crate::base::constraint::{SameNumberOfColumns, SameNumberOfRows, ShapeConstraint};
|
use crate::base::constraint::{SameNumberOfColumns, SameNumberOfRows, ShapeConstraint};
|
||||||
|
|
|
@ -2,13 +2,44 @@ use approx::{AbsDiffEq, RelativeEq, UlpsEq};
|
||||||
use num_complex::Complex;
|
use num_complex::Complex;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use alga::general::RealField;
|
use crate::base::{Matrix2, Matrix3, Normed, Unit, Vector1, Vector2};
|
||||||
use crate::base::{Matrix2, Matrix3, Unit, Vector1, Vector2};
|
use crate::geometry::{Point2, Rotation2};
|
||||||
use crate::geometry::{Rotation2, Point2};
|
use simba::scalar::RealField;
|
||||||
|
use simba::simd::SimdRealField;
|
||||||
|
|
||||||
/// A complex number with a norm equal to 1.
|
/// A complex number with a norm equal to 1.
|
||||||
pub type UnitComplex<N> = Unit<Complex<N>>;
|
pub type UnitComplex<N> = Unit<Complex<N>>;
|
||||||
|
|
||||||
|
impl<N: SimdRealField> Normed for Complex<N> {
|
||||||
|
type Norm = N::SimdRealField;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn norm(&self) -> N::SimdRealField {
|
||||||
|
// We don't use `.norm_sqr()` because it requires
|
||||||
|
// some very strong Num trait requirements.
|
||||||
|
(self.re * self.re + self.im * self.im).simd_sqrt()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn norm_squared(&self) -> N::SimdRealField {
|
||||||
|
// We don't use `.norm_sqr()` because it requires
|
||||||
|
// some very strong Num trait requirements.
|
||||||
|
self.re * self.re + self.im * self.im
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn scale_mut(&mut self, n: Self::Norm) {
|
||||||
|
self.re *= n;
|
||||||
|
self.im *= n;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn unscale_mut(&mut self, n: Self::Norm) {
|
||||||
|
self.re /= n;
|
||||||
|
self.im /= n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<N: RealField> UnitComplex<N> {
|
impl<N: RealField> UnitComplex<N> {
|
||||||
/// The rotation angle in `]-pi; pi]` of this unit complex number.
|
/// The rotation angle in `]-pi; pi]` of this unit complex number.
|
||||||
///
|
///
|
||||||
|
@ -375,4 +406,4 @@ impl<N: RealField> UlpsEq for UnitComplex<N> {
|
||||||
self.re.ulps_eq(&other.re, epsilon, max_ulps)
|
self.re.ulps_eq(&other.re, epsilon, max_ulps)
|
||||||
&& self.im.ulps_eq(&other.im, epsilon, max_ulps)
|
&& self.im.ulps_eq(&other.im, epsilon, max_ulps)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,180 +0,0 @@
|
||||||
use alga::general::{
|
|
||||||
AbstractGroup, AbstractLoop, AbstractMagma, AbstractMonoid, AbstractQuasigroup,
|
|
||||||
AbstractSemigroup, Id, Identity, TwoSidedInverse, Multiplicative, RealField,
|
|
||||||
};
|
|
||||||
use alga::linear::{
|
|
||||||
AffineTransformation, DirectIsometry, Isometry, OrthogonalTransformation,
|
|
||||||
ProjectiveTransformation, Rotation, Similarity, Transformation,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
|
||||||
use crate::base::dimension::U2;
|
|
||||||
use crate::base::{DefaultAllocator, Vector2};
|
|
||||||
use crate::geometry::{Point2, UnitComplex};
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Implementations for UnitComplex.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
impl<N: RealField> Identity<Multiplicative> for UnitComplex<N> {
|
|
||||||
#[inline]
|
|
||||||
fn identity() -> Self {
|
|
||||||
Self::identity()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField> AbstractMagma<Multiplicative> for UnitComplex<N> {
|
|
||||||
#[inline]
|
|
||||||
fn operate(&self, rhs: &Self) -> Self {
|
|
||||||
self * rhs
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField> TwoSidedInverse<Multiplicative> for UnitComplex<N> {
|
|
||||||
#[inline]
|
|
||||||
#[must_use = "Did you mean to use two_sided_inverse_mut()?"]
|
|
||||||
fn two_sided_inverse(&self) -> Self {
|
|
||||||
self.inverse()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn two_sided_inverse_mut(&mut self) {
|
|
||||||
self.inverse_mut()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_structures(
|
|
||||||
($($marker: ident<$operator: ident>),* $(,)*) => {$(
|
|
||||||
impl<N: RealField> $marker<$operator> for UnitComplex<N> {
|
|
||||||
}
|
|
||||||
)*}
|
|
||||||
);
|
|
||||||
|
|
||||||
impl_structures!(
|
|
||||||
AbstractSemigroup<Multiplicative>,
|
|
||||||
AbstractQuasigroup<Multiplicative>,
|
|
||||||
AbstractMonoid<Multiplicative>,
|
|
||||||
AbstractLoop<Multiplicative>,
|
|
||||||
AbstractGroup<Multiplicative>
|
|
||||||
);
|
|
||||||
|
|
||||||
impl<N: RealField> Transformation<Point2<N>> for UnitComplex<N>
|
|
||||||
where DefaultAllocator: Allocator<N, U2>
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn transform_point(&self, pt: &Point2<N>) -> Point2<N> {
|
|
||||||
self.transform_point(pt)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn transform_vector(&self, v: &Vector2<N>) -> Vector2<N> {
|
|
||||||
self.transform_vector(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField> ProjectiveTransformation<Point2<N>> for UnitComplex<N>
|
|
||||||
where DefaultAllocator: Allocator<N, U2>
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn inverse_transform_point(&self, pt: &Point2<N>) -> Point2<N> {
|
|
||||||
self.inverse_transform_point(pt)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn inverse_transform_vector(&self, v: &Vector2<N>) -> Vector2<N> {
|
|
||||||
self.inverse_transform_vector(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField> AffineTransformation<Point2<N>> for UnitComplex<N>
|
|
||||||
where DefaultAllocator: Allocator<N, U2>
|
|
||||||
{
|
|
||||||
type Rotation = Self;
|
|
||||||
type NonUniformScaling = Id;
|
|
||||||
type Translation = Id;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn decompose(&self) -> (Id, Self, Id, Self) {
|
|
||||||
(Id::new(), self.clone(), Id::new(), Self::identity())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn append_translation(&self, _: &Self::Translation) -> Self {
|
|
||||||
self.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn prepend_translation(&self, _: &Self::Translation) -> Self {
|
|
||||||
self.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn append_rotation(&self, r: &Self::Rotation) -> Self {
|
|
||||||
r * self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn prepend_rotation(&self, r: &Self::Rotation) -> Self {
|
|
||||||
self * r
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn append_scaling(&self, _: &Self::NonUniformScaling) -> Self {
|
|
||||||
self.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn prepend_scaling(&self, _: &Self::NonUniformScaling) -> Self {
|
|
||||||
self.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<N: RealField> Similarity<Point2<N>> for UnitComplex<N>
|
|
||||||
where DefaultAllocator: Allocator<N, U2>
|
|
||||||
{
|
|
||||||
type Scaling = Id;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn translation(&self) -> Id {
|
|
||||||
Id::new()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn rotation(&self) -> Self {
|
|
||||||
self.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn scaling(&self) -> Id {
|
|
||||||
Id::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! marker_impl(
|
|
||||||
($($Trait: ident),*) => {$(
|
|
||||||
impl<N: RealField> $Trait<Point2<N>> for UnitComplex<N>
|
|
||||||
where DefaultAllocator: Allocator<N, U2> { }
|
|
||||||
)*}
|
|
||||||
);
|
|
||||||
|
|
||||||
marker_impl!(Isometry, DirectIsometry, OrthogonalTransformation);
|
|
||||||
|
|
||||||
impl<N: RealField> Rotation<Point2<N>> for UnitComplex<N>
|
|
||||||
where DefaultAllocator: Allocator<N, U2>
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn powf(&self, n: N) -> Option<Self> {
|
|
||||||
Some(self.powf(n))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn rotation_between(a: &Vector2<N>, b: &Vector2<N>) -> Option<Self> {
|
|
||||||
Some(Self::rotation_between(a, b))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn scaled_rotation_between(a: &Vector2<N>, b: &Vector2<N>, s: N) -> Option<Self> {
|
|
||||||
Some(Self::scaled_rotation_between(a, b, s))
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -6,11 +6,11 @@ use num_complex::Complex;
|
||||||
use rand::distributions::{Distribution, OpenClosed01, Standard};
|
use rand::distributions::{Distribution, OpenClosed01, Standard};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
||||||
use alga::general::RealField;
|
|
||||||
use crate::base::dimension::{U1, U2};
|
use crate::base::dimension::{U1, U2};
|
||||||
use crate::base::storage::Storage;
|
use crate::base::storage::Storage;
|
||||||
use crate::base::{Unit, Vector, Matrix2};
|
use crate::base::{Matrix2, Unit, Vector};
|
||||||
use crate::geometry::{Rotation2, UnitComplex};
|
use crate::geometry::{Rotation2, UnitComplex};
|
||||||
|
use simba::scalar::RealField;
|
||||||
|
|
||||||
impl<N: RealField> UnitComplex<N> {
|
impl<N: RealField> UnitComplex<N> {
|
||||||
/// The unit complex number multiplicative identity.
|
/// The unit complex number multiplicative identity.
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
use num::Zero;
|
use num::Zero;
|
||||||
use num_complex::Complex;
|
use num_complex::Complex;
|
||||||
|
|
||||||
use alga::general::{RealField, SubsetOf, SupersetOf};
|
use simba::scalar::{RealField, SubsetOf, SupersetOf};
|
||||||
use alga::linear::Rotation as AlgaRotation;
|
|
||||||
|
|
||||||
use crate::base::dimension::U2;
|
use crate::base::dimension::U2;
|
||||||
use crate::base::{Matrix2, Matrix3};
|
use crate::base::{Matrix2, Matrix3};
|
||||||
use crate::geometry::{
|
use crate::geometry::{
|
||||||
Isometry, Point2, Rotation2, Similarity, SuperTCategoryOf, TAffine, Transform, Translation,
|
AbstractRotation, Isometry, Rotation2, Similarity, SuperTCategoryOf, TAffine, Transform,
|
||||||
UnitComplex
|
Translation, UnitComplex,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -42,7 +41,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(uq: &UnitComplex<N2>) -> Self {
|
fn from_superset_unchecked(uq: &UnitComplex<N2>) -> Self {
|
||||||
Self::new_unchecked(crate::convert_ref_unchecked(uq.as_ref()))
|
Self::new_unchecked(crate::convert_ref_unchecked(uq.as_ref()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,7 +63,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(rot: &Rotation2<N2>) -> Self {
|
fn from_superset_unchecked(rot: &Rotation2<N2>) -> Self {
|
||||||
let q = UnitComplex::<N2>::from_rotation_matrix(rot);
|
let q = UnitComplex::<N2>::from_rotation_matrix(rot);
|
||||||
crate::convert_unchecked(q)
|
crate::convert_unchecked(q)
|
||||||
}
|
}
|
||||||
|
@ -74,7 +73,7 @@ impl<N1, N2, R> SubsetOf<Isometry<N2, U2, R>> for UnitComplex<N1>
|
||||||
where
|
where
|
||||||
N1: RealField,
|
N1: RealField,
|
||||||
N2: RealField + SupersetOf<N1>,
|
N2: RealField + SupersetOf<N1>,
|
||||||
R: AlgaRotation<Point2<N2>> + SupersetOf<Self>,
|
R: AbstractRotation<N2, U2> + SupersetOf<Self>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_superset(&self) -> Isometry<N2, U2, R> {
|
fn to_superset(&self) -> Isometry<N2, U2, R> {
|
||||||
|
@ -87,7 +86,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(iso: &Isometry<N2, U2, R>) -> Self {
|
fn from_superset_unchecked(iso: &Isometry<N2, U2, R>) -> Self {
|
||||||
crate::convert_ref_unchecked(&iso.rotation)
|
crate::convert_ref_unchecked(&iso.rotation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,7 +95,7 @@ impl<N1, N2, R> SubsetOf<Similarity<N2, U2, R>> for UnitComplex<N1>
|
||||||
where
|
where
|
||||||
N1: RealField,
|
N1: RealField,
|
||||||
N2: RealField + SupersetOf<N1>,
|
N2: RealField + SupersetOf<N1>,
|
||||||
R: AlgaRotation<Point2<N2>> + SupersetOf<Self>,
|
R: AbstractRotation<N2, U2> + SupersetOf<Self>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_superset(&self) -> Similarity<N2, U2, R> {
|
fn to_superset(&self) -> Similarity<N2, U2, R> {
|
||||||
|
@ -109,7 +108,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(sim: &Similarity<N2, U2, R>) -> Self {
|
fn from_superset_unchecked(sim: &Similarity<N2, U2, R>) -> Self {
|
||||||
crate::convert_ref_unchecked(&sim.isometry)
|
crate::convert_ref_unchecked(&sim.isometry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,7 +130,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(t: &Transform<N2, U2, C>) -> Self {
|
fn from_superset_unchecked(t: &Transform<N2, U2, C>) -> Self {
|
||||||
Self::from_superset_unchecked(t.matrix())
|
Self::from_superset_unchecked(t.matrix())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -148,13 +147,12 @@ impl<N1: RealField, N2: RealField + SupersetOf<N1>> SubsetOf<Matrix3<N2>> for Un
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn from_superset_unchecked(m: &Matrix3<N2>) -> Self {
|
fn from_superset_unchecked(m: &Matrix3<N2>) -> Self {
|
||||||
let rot: Rotation2<N1> = crate::convert_ref_unchecked(m);
|
let rot: Rotation2<N1> = crate::convert_ref_unchecked(m);
|
||||||
Self::from_rotation_matrix(&rot)
|
Self::from_rotation_matrix(&rot)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl<N: RealField> From<UnitComplex<N>> for Rotation2<N> {
|
impl<N: RealField> From<UnitComplex<N>> for Rotation2<N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(q: UnitComplex<N>) -> Self {
|
fn from(q: UnitComplex<N>) -> Self {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
use std::ops::{Div, DivAssign, Mul, MulAssign};
|
use std::ops::{Div, DivAssign, Mul, MulAssign};
|
||||||
|
|
||||||
use alga::general::RealField;
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::dimension::{U1, U2};
|
use crate::base::dimension::{U1, U2};
|
||||||
use crate::base::storage::Storage;
|
use crate::base::storage::Storage;
|
||||||
use crate::base::{DefaultAllocator, Unit, Vector, Vector2};
|
use crate::base::{DefaultAllocator, Unit, Vector, Vector2};
|
||||||
use crate::geometry::{Isometry, Point2, Rotation, Similarity, Translation, UnitComplex};
|
use crate::geometry::{Isometry, Point2, Rotation, Similarity, Translation, UnitComplex};
|
||||||
|
use simba::scalar::RealField;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This file provides:
|
* This file provides:
|
||||||
|
@ -403,4 +403,4 @@ where DefaultAllocator: Allocator<N, U2, U2>
|
||||||
fn div_assign(&mut self, rhs: &'b UnitComplex<N>) {
|
fn div_assign(&mut self, rhs: &'b UnitComplex<N>) {
|
||||||
self.div_assign(rhs.to_rotation_matrix())
|
self.div_assign(rhs.to_rotation_matrix())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
use num_complex::Complex;
|
||||||
|
use simba::simd::SimdValue;
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
use crate::base::{Scalar, Unit};
|
||||||
|
use crate::geometry::UnitComplex;
|
||||||
|
use crate::RealField;
|
||||||
|
|
||||||
|
impl<N: RealField> SimdValue for UnitComplex<N>
|
||||||
|
where N::Element: Scalar
|
||||||
|
{
|
||||||
|
type Element = UnitComplex<N::Element>;
|
||||||
|
type SimdBool = N::SimdBool;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn lanes() -> usize {
|
||||||
|
N::lanes()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn splat(val: Self::Element) -> Self {
|
||||||
|
Unit::new_unchecked(Complex::splat(val.into_inner()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn extract(&self, i: usize) -> Self::Element {
|
||||||
|
Unit::new_unchecked(self.deref().extract(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn extract_unchecked(&self, i: usize) -> Self::Element {
|
||||||
|
Unit::new_unchecked(self.deref().extract_unchecked(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn replace(&mut self, i: usize, val: Self::Element) {
|
||||||
|
self.as_mut_unchecked().replace(i, val.into_inner())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn replace_unchecked(&mut self, i: usize, val: Self::Element) {
|
||||||
|
self.as_mut_unchecked()
|
||||||
|
.replace_unchecked(i, val.into_inner())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn select(self, cond: Self::SimdBool, other: Self) -> Self {
|
||||||
|
Unit::new_unchecked(self.into_inner().select(cond, other.into_inner()))
|
||||||
|
}
|
||||||
|
}
|
313
src/lib.rs
313
src/lib.rs
|
@ -68,8 +68,6 @@ an optimized set of tools for computer graphics and physics. Those features incl
|
||||||
* 3D projections for computer graphics: `Perspective3`, `Orthographic3`.
|
* 3D projections for computer graphics: `Perspective3`, `Orthographic3`.
|
||||||
* Matrix factorizations: `Cholesky`, `QR`, `LU`, `FullPivLU`, `SVD`, `Schur`, `Hessenberg`, `SymmetricEigen`.
|
* Matrix factorizations: `Cholesky`, `QR`, `LU`, `FullPivLU`, `SVD`, `Schur`, `Hessenberg`, `SymmetricEigen`.
|
||||||
* Insertion and removal of rows of columns of a matrix.
|
* Insertion and removal of rows of columns of a matrix.
|
||||||
* Implements traits from the [alga](https://crates.io/crates/alga) crate for
|
|
||||||
generic programming.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// #![feature(plugin)]
|
// #![feature(plugin)]
|
||||||
|
@ -81,7 +79,7 @@ an optimized set of tools for computer graphics and physics. Those features incl
|
||||||
#![deny(non_upper_case_globals)]
|
#![deny(non_upper_case_globals)]
|
||||||
#![deny(unused_qualifications)]
|
#![deny(unused_qualifications)]
|
||||||
#![deny(unused_results)]
|
#![deny(unused_results)]
|
||||||
#![deny(missing_docs)]
|
#![allow(missing_docs)] // XXX: deny that
|
||||||
#![doc(
|
#![doc(
|
||||||
html_favicon_url = "https://nalgebra.org/img/favicon.ico",
|
html_favicon_url = "https://nalgebra.org/img/favicon.ico",
|
||||||
html_root_url = "https://nalgebra.org/rustdoc"
|
html_root_url = "https://nalgebra.org/rustdoc"
|
||||||
|
@ -106,18 +104,11 @@ extern crate mint;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate approx;
|
extern crate approx;
|
||||||
extern crate generic_array;
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
extern crate matrixmultiply;
|
extern crate matrixmultiply;
|
||||||
extern crate num_complex;
|
|
||||||
extern crate num_rational;
|
|
||||||
extern crate num_traits as num;
|
extern crate num_traits as num;
|
||||||
extern crate rand;
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
extern crate rand_distr;
|
extern crate rand_distr;
|
||||||
extern crate typenum;
|
|
||||||
|
|
||||||
extern crate alga;
|
|
||||||
|
|
||||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
@ -152,35 +143,17 @@ pub use crate::sparse::*;
|
||||||
)]
|
)]
|
||||||
pub use base as core;
|
pub use base as core;
|
||||||
|
|
||||||
|
use simba::scalar::SupersetOf;
|
||||||
use std::cmp::{self, Ordering, PartialOrd};
|
use std::cmp::{self, Ordering, PartialOrd};
|
||||||
|
|
||||||
use alga::general::{
|
use num::{One, Signed, Zero};
|
||||||
Additive, AdditiveGroup, Identity, JoinSemilattice, Lattice, MeetSemilattice, Multiplicative,
|
|
||||||
SupersetOf, TwoSidedInverse,
|
|
||||||
};
|
|
||||||
use alga::linear::SquareMatrix as AlgaSquareMatrix;
|
|
||||||
use alga::linear::{EuclideanSpace, FiniteDimVectorSpace, InnerSpace, NormedSpace};
|
|
||||||
use num::Signed;
|
|
||||||
|
|
||||||
#[allow(deprecated)]
|
use base::allocator::Allocator;
|
||||||
pub use alga::general::Real;
|
|
||||||
pub use alga::general::{ComplexField, Id, RealField};
|
|
||||||
pub use alga::simd::{SimdComplexField, SimdRealField};
|
|
||||||
pub use num_complex::Complex;
|
pub use num_complex::Complex;
|
||||||
|
pub use simba::scalar::{
|
||||||
/*
|
ClosedAdd, ClosedDiv, ClosedMul, ClosedSub, ComplexField, Field, RealField,
|
||||||
*
|
};
|
||||||
* Multiplicative identity.
|
pub use simba::simd::{SimdBool, SimdComplexField, SimdRealField};
|
||||||
*
|
|
||||||
*/
|
|
||||||
/// Gets the ubiquitous multiplicative identity element.
|
|
||||||
///
|
|
||||||
/// Same as `Id::new()`.
|
|
||||||
#[deprecated(note = "use `Id::new()` instead.")]
|
|
||||||
#[inline]
|
|
||||||
pub fn id() -> Id {
|
|
||||||
Id::new()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets the multiplicative identity element.
|
/// Gets the multiplicative identity element.
|
||||||
///
|
///
|
||||||
|
@ -189,8 +162,8 @@ pub fn id() -> Id {
|
||||||
/// * [`origin`](../nalgebra/fn.origin.html)
|
/// * [`origin`](../nalgebra/fn.origin.html)
|
||||||
/// * [`zero`](fn.zero.html)
|
/// * [`zero`](fn.zero.html)
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn one<T: Identity<Multiplicative>>() -> T {
|
pub fn one<T: One>() -> T {
|
||||||
T::identity()
|
T::one()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the additive identity element.
|
/// Gets the additive identity element.
|
||||||
|
@ -200,36 +173,8 @@ pub fn one<T: Identity<Multiplicative>>() -> T {
|
||||||
/// * [`one`](fn.one.html)
|
/// * [`one`](fn.one.html)
|
||||||
/// * [`origin`](../nalgebra/fn.origin.html)
|
/// * [`origin`](../nalgebra/fn.origin.html)
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn zero<T: Identity<Additive>>() -> T {
|
pub fn zero<T: Zero>() -> T {
|
||||||
T::identity()
|
T::zero()
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets the origin of the given point.
|
|
||||||
///
|
|
||||||
/// # See also:
|
|
||||||
///
|
|
||||||
/// * [`one`](fn.one.html)
|
|
||||||
/// * [`zero`](fn.zero.html)
|
|
||||||
///
|
|
||||||
/// # Deprecated
|
|
||||||
/// Use [Point::origin] instead.
|
|
||||||
///
|
|
||||||
/// Or, use [EuclideanSpace::origin](https://docs.rs/alga/0.7.2/alga/linear/trait.EuclideanSpace.html#tymethod.origin).
|
|
||||||
#[deprecated(note = "use `Point::origin` instead")]
|
|
||||||
#[inline]
|
|
||||||
pub fn origin<P: EuclideanSpace>() -> P {
|
|
||||||
P::origin()
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* Dimension
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
/// The dimension of the given algebraic entity seen as a vector space.
|
|
||||||
#[inline]
|
|
||||||
pub fn dimension<V: FiniteDimVectorSpace>() -> usize {
|
|
||||||
V::dimension()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -245,7 +190,7 @@ pub fn dimension<V: FiniteDimVectorSpace>() -> usize {
|
||||||
/// The range must not be empty.
|
/// The range must not be empty.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn wrap<T>(mut val: T, min: T, max: T) -> T
|
pub fn wrap<T>(mut val: T, min: T, max: T) -> T
|
||||||
where T: Copy + PartialOrd + AdditiveGroup {
|
where T: Copy + PartialOrd + ClosedAdd + ClosedSub {
|
||||||
assert!(min < max, "Invalid wrapping bounds.");
|
assert!(min < max, "Invalid wrapping bounds.");
|
||||||
let width = max - min;
|
let width = max - min;
|
||||||
|
|
||||||
|
@ -310,23 +255,23 @@ pub fn abs<T: Signed>(a: &T) -> T {
|
||||||
a.abs()
|
a.abs()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the infimum of `a` and `b`.
|
///// Returns the infimum of `a` and `b`.
|
||||||
#[inline]
|
//#[inline]
|
||||||
pub fn inf<T: MeetSemilattice>(a: &T, b: &T) -> T {
|
//pub fn inf<T: MeetSemilattice>(a: &T, b: &T) -> T {
|
||||||
a.meet(b)
|
// a.meet(b)
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
/// Returns the supremum of `a` and `b`.
|
///// Returns the supremum of `a` and `b`.
|
||||||
#[inline]
|
//#[inline]
|
||||||
pub fn sup<T: JoinSemilattice>(a: &T, b: &T) -> T {
|
//pub fn sup<T: JoinSemilattice>(a: &T, b: &T) -> T {
|
||||||
a.join(b)
|
// a.join(b)
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
/// Returns simultaneously the infimum and supremum of `a` and `b`.
|
///// Returns simultaneously the infimum and supremum of `a` and `b`.
|
||||||
#[inline]
|
//#[inline]
|
||||||
pub fn inf_sup<T: Lattice>(a: &T, b: &T) -> (T, T) {
|
//pub fn inf_sup<T: Lattice>(a: &T, b: &T) -> (T, T) {
|
||||||
a.meet_join(b)
|
// a.meet_join(b)
|
||||||
}
|
//}
|
||||||
|
|
||||||
/// Compare `a` and `b` using a partial ordering relation.
|
/// Compare `a` and `b` using a partial ordering relation.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -414,175 +359,6 @@ pub fn partial_sort2<'a, T: PartialOrd>(a: &'a T, b: &'a T) -> Option<(&'a T, &'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Inverse
|
|
||||||
*/
|
|
||||||
|
|
||||||
/// Tries to gets an inverted copy of a square matrix.
|
|
||||||
///
|
|
||||||
/// # See also:
|
|
||||||
///
|
|
||||||
/// * [`inverse`](fn.inverse.html)
|
|
||||||
#[deprecated(note = "use the `.try_inverse()` method instead")]
|
|
||||||
#[inline]
|
|
||||||
pub fn try_inverse<M: AlgaSquareMatrix>(m: &M) -> Option<M> {
|
|
||||||
m.try_inverse()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Computes the multiplicative inverse of an (always invertible) algebraic entity.
|
|
||||||
///
|
|
||||||
/// # See also:
|
|
||||||
///
|
|
||||||
/// * [`try_inverse`](fn.try_inverse.html)
|
|
||||||
#[deprecated(note = "use the `.inverse()` method instead")]
|
|
||||||
#[inline]
|
|
||||||
pub fn inverse<M: TwoSidedInverse<Multiplicative>>(m: &M) -> M {
|
|
||||||
m.two_sided_inverse()
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Inner vector space
|
|
||||||
*/
|
|
||||||
|
|
||||||
/// Computes the dot product of two vectors.
|
|
||||||
///
|
|
||||||
/// ## Deprecated
|
|
||||||
/// Use these methods instead:
|
|
||||||
/// - [Matrix::dot]
|
|
||||||
/// - [Quaternion::dot]
|
|
||||||
///
|
|
||||||
/// Or, use [FiniteDimVectorSpace::dot](https://docs.rs/alga/0.7.2/alga/linear/trait.FiniteDimVectorSpace.html#tymethod.dot).
|
|
||||||
#[deprecated(note = "use `Matrix::dot` or `Quaternion::dot` instead")]
|
|
||||||
#[inline]
|
|
||||||
pub fn dot<V: FiniteDimVectorSpace>(a: &V, b: &V) -> V::Field {
|
|
||||||
a.dot(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Computes the smallest angle between two vectors.
|
|
||||||
///
|
|
||||||
/// ## Deprecated
|
|
||||||
/// Use [Matrix::angle] instead.
|
|
||||||
///
|
|
||||||
/// Or, use [InnerSpace::angle](https://docs.rs/alga/0.7.2/alga/linear/trait.InnerSpace.html#method.angle).
|
|
||||||
#[deprecated(note = "use `Matrix::angle` instead")]
|
|
||||||
#[inline]
|
|
||||||
pub fn angle<V: InnerSpace>(a: &V, b: &V) -> V::RealField {
|
|
||||||
a.angle(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Normed space
|
|
||||||
*/
|
|
||||||
|
|
||||||
/// Computes the L2 (Euclidean) norm of a vector.
|
|
||||||
///
|
|
||||||
/// # See also:
|
|
||||||
///
|
|
||||||
/// * [`magnitude`](fn.magnitude.html)
|
|
||||||
/// * [`magnitude_squared`](fn.magnitude_squared.html)
|
|
||||||
/// * [`norm_squared`](fn.norm_squared.html)
|
|
||||||
///
|
|
||||||
/// # Deprecated
|
|
||||||
/// Use these methods instead:
|
|
||||||
/// * [Matrix::norm]
|
|
||||||
/// * [Quaternion::norm]
|
|
||||||
///
|
|
||||||
/// Or, use [NormedSpace::norm](https://docs.rs/alga/0.7.2/alga/linear/trait.NormedSpace.html#tymethod.norm).
|
|
||||||
#[deprecated(note = "use `Matrix::norm` or `Quaternion::norm` instead")]
|
|
||||||
#[inline]
|
|
||||||
pub fn norm<V: NormedSpace>(v: &V) -> V::RealField {
|
|
||||||
v.norm()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Computes the squared L2 (Euclidean) norm of the vector `v`.
|
|
||||||
///
|
|
||||||
/// # See also:
|
|
||||||
///
|
|
||||||
/// * [`magnitude`](fn.magnitude.html)
|
|
||||||
/// * [`magnitude_squared`](fn.magnitude_squared.html)
|
|
||||||
/// * [`norm`](fn.norm.html)
|
|
||||||
///
|
|
||||||
/// # Deprecated
|
|
||||||
/// Use these methods instead:
|
|
||||||
/// * [Matrix::norm_squared]
|
|
||||||
/// * [Quaternion::norm_squared]
|
|
||||||
///
|
|
||||||
/// Or, use [NormedSpace::norm_squared](https://docs.rs/alga/0.7.2/alga/linear/trait.NormedSpace.html#tymethod.norm_squared).
|
|
||||||
#[deprecated(note = "use `Matrix::norm_squared` or `Quaternion::norm_squared` instead")]
|
|
||||||
#[inline]
|
|
||||||
pub fn norm_squared<V: NormedSpace>(v: &V) -> V::RealField {
|
|
||||||
v.norm_squared()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A synonym for [`norm`](fn.norm.html), aka length.
|
|
||||||
///
|
|
||||||
/// # See also:
|
|
||||||
///
|
|
||||||
/// * [`magnitude_squared`](fn.magnitude_squared.html)
|
|
||||||
/// * [`norm`](fn.norm.html)
|
|
||||||
/// * [`norm_squared`](fn.norm_squared.html)
|
|
||||||
///
|
|
||||||
/// # Deprecated
|
|
||||||
/// Use these methods instead:
|
|
||||||
/// * [Matrix::magnitude]
|
|
||||||
/// * [Quaternion::magnitude]
|
|
||||||
///
|
|
||||||
/// Or, use [NormedSpace::norm](https://docs.rs/alga/0.7.2/alga/linear/trait.NormedSpace.html#tymethod.norm).
|
|
||||||
#[deprecated(note = "use `Matrix::magnitude` or `Quaternion::magnitude` instead")]
|
|
||||||
#[inline]
|
|
||||||
pub fn magnitude<V: NormedSpace>(v: &V) -> V::RealField {
|
|
||||||
v.norm()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A synonym for [`norm_squared`](fn.norm_squared.html),
|
|
||||||
/// aka length squared.
|
|
||||||
///
|
|
||||||
/// # See also:
|
|
||||||
///
|
|
||||||
/// * [`magnitude`](fn.magnitude.html)
|
|
||||||
/// * [`norm`](fn.norm.html)
|
|
||||||
/// * [`norm_squared`](fn.norm_squared.html)
|
|
||||||
///
|
|
||||||
/// # Deprecated
|
|
||||||
/// Use these methods instead:
|
|
||||||
/// * [Matrix::magnitude_squared]
|
|
||||||
/// * [Quaternion::magnitude_squared]
|
|
||||||
///
|
|
||||||
/// Or, use [NormedSpace::norm_squared](https://docs.rs/alga/0.7.2/alga/linear/trait.NormedSpace.html#tymethod.norm_squared).
|
|
||||||
#[deprecated(note = "use `Matrix::magnitude_squared` or `Quaternion::magnitude_squared` instead")]
|
|
||||||
#[inline]
|
|
||||||
pub fn magnitude_squared<V: NormedSpace>(v: &V) -> V::RealField {
|
|
||||||
v.norm_squared()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Computes the normalized version of the vector `v`.
|
|
||||||
///
|
|
||||||
/// # Deprecated
|
|
||||||
/// Use these methods instead:
|
|
||||||
/// * [Matrix::normalize]
|
|
||||||
/// * [Quaternion::normalize]
|
|
||||||
///
|
|
||||||
/// Or, use [NormedSpace::normalize](https://docs.rs/alga/0.7.2/alga/linear/trait.NormedSpace.html#tymethod.normalize).
|
|
||||||
#[deprecated(note = "use `Matrix::normalize` or `Quaternion::normalize` instead")]
|
|
||||||
#[inline]
|
|
||||||
pub fn normalize<V: NormedSpace>(v: &V) -> V {
|
|
||||||
v.normalize()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Computes the normalized version of the vector `v` or returns `None` if its norm is smaller than `min_norm`.
|
|
||||||
///
|
|
||||||
/// # Deprecated
|
|
||||||
/// Use these methods instead:
|
|
||||||
/// * [Matrix::try_normalize]
|
|
||||||
/// * [Quaternion::try_normalize]
|
|
||||||
///
|
|
||||||
/// Or, use [NormedSpace::try_normalize](https://docs.rs/alga/0.7.2/alga/linear/trait.NormedSpace.html#tymethod.try_normalize).
|
|
||||||
#[deprecated(note = "use `Matrix::try_normalize` or `Quaternion::try_normalize` instead")]
|
|
||||||
#[inline]
|
|
||||||
pub fn try_normalize<V: NormedSpace>(v: &V, min_norm: V::RealField) -> Option<V> {
|
|
||||||
v.try_normalize(min_norm)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Point operations.
|
* Point operations.
|
||||||
|
@ -595,8 +371,9 @@ pub fn try_normalize<V: NormedSpace>(v: &V, min_norm: V::RealField) -> Option<V>
|
||||||
/// * [distance](fn.distance.html)
|
/// * [distance](fn.distance.html)
|
||||||
/// * [distance_squared](fn.distance_squared.html)
|
/// * [distance_squared](fn.distance_squared.html)
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn center<P: EuclideanSpace>(p1: &P, p2: &P) -> P {
|
pub fn center<N: SimdComplexField, D: DimName>(p1: &Point<N, D>, p2: &Point<N, D>) -> Point<N, D>
|
||||||
P::from_coordinates((p1.coordinates() + p2.coordinates()) * convert(0.5))
|
where DefaultAllocator: Allocator<N, D> {
|
||||||
|
((&p1.coords + &p2.coords) * convert::<_, N>(0.5)).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The distance between two points.
|
/// The distance between two points.
|
||||||
|
@ -606,8 +383,14 @@ pub fn center<P: EuclideanSpace>(p1: &P, p2: &P) -> P {
|
||||||
/// * [center](fn.center.html)
|
/// * [center](fn.center.html)
|
||||||
/// * [distance_squared](fn.distance_squared.html)
|
/// * [distance_squared](fn.distance_squared.html)
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn distance<P: EuclideanSpace>(p1: &P, p2: &P) -> P::RealField {
|
pub fn distance<N: SimdComplexField, D: DimName>(
|
||||||
(p2.coordinates() - p1.coordinates()).norm()
|
p1: &Point<N, D>,
|
||||||
|
p2: &Point<N, D>,
|
||||||
|
) -> N::SimdRealField
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<N, D>,
|
||||||
|
{
|
||||||
|
(&p2.coords - &p1.coords).norm()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The squared distance between two points.
|
/// The squared distance between two points.
|
||||||
|
@ -617,8 +400,14 @@ pub fn distance<P: EuclideanSpace>(p1: &P, p2: &P) -> P::RealField {
|
||||||
/// * [center](fn.center.html)
|
/// * [center](fn.center.html)
|
||||||
/// * [distance](fn.distance.html)
|
/// * [distance](fn.distance.html)
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn distance_squared<P: EuclideanSpace>(p1: &P, p2: &P) -> P::RealField {
|
pub fn distance_squared<N: SimdComplexField, D: DimName>(
|
||||||
(p2.coordinates() - p1.coordinates()).norm_squared()
|
p1: &Point<N, D>,
|
||||||
|
p2: &Point<N, D>,
|
||||||
|
) -> N::SimdRealField
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<N, D>,
|
||||||
|
{
|
||||||
|
(&p2.coords - &p1.coords).norm_squared()
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -683,7 +472,7 @@ pub fn is_convertible<From: SupersetOf<To>, To>(t: &From) -> bool {
|
||||||
/// * [try_convert](fn.try_convert.html)
|
/// * [try_convert](fn.try_convert.html)
|
||||||
/// * [try_convert_ref](fn.try_convert_ref.html)
|
/// * [try_convert_ref](fn.try_convert_ref.html)
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn convert_unchecked<From: SupersetOf<To>, To>(t: From) -> To {
|
pub fn convert_unchecked<From: SupersetOf<To>, To>(t: From) -> To {
|
||||||
t.to_subset_unchecked()
|
t.to_subset_unchecked()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -726,6 +515,6 @@ pub fn try_convert_ref<From: SupersetOf<To>, To>(t: &From) -> Option<To> {
|
||||||
/// * [try_convert](fn.try_convert.html)
|
/// * [try_convert](fn.try_convert.html)
|
||||||
/// * [try_convert_ref](fn.try_convert_ref.html)
|
/// * [try_convert_ref](fn.try_convert_ref.html)
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn convert_ref_unchecked<From: SupersetOf<To>, To>(t: &From) -> To {
|
pub fn convert_ref_unchecked<From: SupersetOf<To>, To>(t: &From) -> To {
|
||||||
t.to_subset_unchecked()
|
t.to_subset_unchecked()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! Functions for balancing a matrix.
|
//! Functions for balancing a matrix.
|
||||||
|
|
||||||
use alga::general::RealField;
|
use simba::scalar::RealField;
|
||||||
use std::ops::{DivAssign, MulAssign};
|
use std::ops::{DivAssign, MulAssign};
|
||||||
|
|
||||||
use crate::allocator::Allocator;
|
use crate::allocator::Allocator;
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
#[cfg(feature = "serde-serialize")]
|
#[cfg(feature = "serde-serialize")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use alga::general::ComplexField;
|
|
||||||
use crate::allocator::Allocator;
|
use crate::allocator::Allocator;
|
||||||
use crate::base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, Unit, VectorN};
|
use crate::base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, Unit, VectorN};
|
||||||
use crate::dimension::{Dim, DimDiff, DimMin, DimMinimum, DimSub, U1};
|
use crate::dimension::{Dim, DimDiff, DimMin, DimMinimum, DimSub, U1};
|
||||||
use crate::storage::Storage;
|
use crate::storage::Storage;
|
||||||
|
use simba::scalar::ComplexField;
|
||||||
|
|
||||||
use crate::geometry::Reflection;
|
use crate::geometry::Reflection;
|
||||||
use crate::linalg::householder;
|
use crate::linalg::householder;
|
||||||
|
@ -14,27 +14,23 @@ use crate::linalg::householder;
|
||||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serde-serialize",
|
feature = "serde-serialize",
|
||||||
serde(bound(
|
serde(bound(serialize = "DimMinimum<R, C>: DimSub<U1>,
|
||||||
serialize = "DimMinimum<R, C>: DimSub<U1>,
|
|
||||||
DefaultAllocator: Allocator<N, R, C> +
|
DefaultAllocator: Allocator<N, R, C> +
|
||||||
Allocator<N, DimMinimum<R, C>> +
|
Allocator<N, DimMinimum<R, C>> +
|
||||||
Allocator<N, DimDiff<DimMinimum<R, C>, U1>>,
|
Allocator<N, DimDiff<DimMinimum<R, C>, U1>>,
|
||||||
MatrixMN<N, R, C>: Serialize,
|
MatrixMN<N, R, C>: Serialize,
|
||||||
VectorN<N, DimMinimum<R, C>>: Serialize,
|
VectorN<N, DimMinimum<R, C>>: Serialize,
|
||||||
VectorN<N, DimDiff<DimMinimum<R, C>, U1>>: Serialize"
|
VectorN<N, DimDiff<DimMinimum<R, C>, U1>>: Serialize"))
|
||||||
))
|
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serde-serialize",
|
feature = "serde-serialize",
|
||||||
serde(bound(
|
serde(bound(deserialize = "DimMinimum<R, C>: DimSub<U1>,
|
||||||
deserialize = "DimMinimum<R, C>: DimSub<U1>,
|
|
||||||
DefaultAllocator: Allocator<N, R, C> +
|
DefaultAllocator: Allocator<N, R, C> +
|
||||||
Allocator<N, DimMinimum<R, C>> +
|
Allocator<N, DimMinimum<R, C>> +
|
||||||
Allocator<N, DimDiff<DimMinimum<R, C>, U1>>,
|
Allocator<N, DimDiff<DimMinimum<R, C>, U1>>,
|
||||||
MatrixMN<N, R, C>: Deserialize<'de>,
|
MatrixMN<N, R, C>: Deserialize<'de>,
|
||||||
VectorN<N, DimMinimum<R, C>>: Deserialize<'de>,
|
VectorN<N, DimMinimum<R, C>>: Deserialize<'de>,
|
||||||
VectorN<N, DimDiff<DimMinimum<R, C>, U1>>: Deserialize<'de>"
|
VectorN<N, DimDiff<DimMinimum<R, C>, U1>>: Deserialize<'de>"))
|
||||||
))
|
|
||||||
)]
|
)]
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Bidiagonal<N: ComplexField, R: DimMin<C>, C: Dim>
|
pub struct Bidiagonal<N: ComplexField, R: DimMin<C>, C: Dim>
|
||||||
|
@ -63,7 +59,8 @@ where
|
||||||
MatrixMN<N, R, C>: Copy,
|
MatrixMN<N, R, C>: Copy,
|
||||||
VectorN<N, DimMinimum<R, C>>: Copy,
|
VectorN<N, DimMinimum<R, C>>: Copy,
|
||||||
VectorN<N, DimDiff<DimMinimum<R, C>, U1>>: Copy,
|
VectorN<N, DimDiff<DimMinimum<R, C>, U1>>: Copy,
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
impl<N: ComplexField, R: DimMin<C>, C: Dim> Bidiagonal<N, R, C>
|
impl<N: ComplexField, R: DimMin<C>, C: Dim> Bidiagonal<N, R, C>
|
||||||
where
|
where
|
||||||
|
@ -174,11 +171,9 @@ where
|
||||||
MatrixN<N, DimMinimum<R, C>>,
|
MatrixN<N, DimMinimum<R, C>>,
|
||||||
MatrixMN<N, DimMinimum<R, C>, C>,
|
MatrixMN<N, DimMinimum<R, C>, C>,
|
||||||
)
|
)
|
||||||
where
|
where DefaultAllocator: Allocator<N, DimMinimum<R, C>, DimMinimum<R, C>>
|
||||||
DefaultAllocator: Allocator<N, DimMinimum<R, C>, DimMinimum<R, C>>
|
|
||||||
+ Allocator<N, R, DimMinimum<R, C>>
|
+ Allocator<N, R, DimMinimum<R, C>>
|
||||||
+ Allocator<N, DimMinimum<R, C>, C>,
|
+ Allocator<N, DimMinimum<R, C>, C> {
|
||||||
{
|
|
||||||
// FIXME: optimize by calling a reallocator.
|
// FIXME: optimize by calling a reallocator.
|
||||||
(self.u(), self.d(), self.v_t())
|
(self.u(), self.d(), self.v_t())
|
||||||
}
|
}
|
||||||
|
@ -186,9 +181,7 @@ where
|
||||||
/// Retrieves the upper trapezoidal submatrix `R` of this decomposition.
|
/// Retrieves the upper trapezoidal submatrix `R` of this decomposition.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn d(&self) -> MatrixN<N, DimMinimum<R, C>>
|
pub fn d(&self) -> MatrixN<N, DimMinimum<R, C>>
|
||||||
where
|
where DefaultAllocator: Allocator<N, DimMinimum<R, C>, DimMinimum<R, C>> {
|
||||||
DefaultAllocator: Allocator<N, DimMinimum<R, C>, DimMinimum<R, C>>,
|
|
||||||
{
|
|
||||||
let (nrows, ncols) = self.uv.data.shape();
|
let (nrows, ncols) = self.uv.data.shape();
|
||||||
|
|
||||||
let d = nrows.min(ncols);
|
let d = nrows.min(ncols);
|
||||||
|
@ -266,13 +259,13 @@ where
|
||||||
|
|
||||||
/// The diagonal part of this decomposed matrix.
|
/// The diagonal part of this decomposed matrix.
|
||||||
pub fn diagonal(&self) -> VectorN<N::RealField, DimMinimum<R, C>>
|
pub fn diagonal(&self) -> VectorN<N::RealField, DimMinimum<R, C>>
|
||||||
where DefaultAllocator: Allocator<N::RealField, DimMinimum<R, C>> {
|
where DefaultAllocator: Allocator<N::RealField, DimMinimum<R, C>> {
|
||||||
self.diagonal.map(|e| e.modulus())
|
self.diagonal.map(|e| e.modulus())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The off-diagonal part of this decomposed matrix.
|
/// The off-diagonal part of this decomposed matrix.
|
||||||
pub fn off_diagonal(&self) -> VectorN<N::RealField, DimDiff<DimMinimum<R, C>, U1>>
|
pub fn off_diagonal(&self) -> VectorN<N::RealField, DimDiff<DimMinimum<R, C>, U1>>
|
||||||
where DefaultAllocator: Allocator<N::RealField, DimDiff<DimMinimum<R, C>, U1>> {
|
where DefaultAllocator: Allocator<N::RealField, DimDiff<DimMinimum<R, C>, U1>> {
|
||||||
self.off_diagonal.map(|e| e.modulus())
|
self.off_diagonal.map(|e| e.modulus())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use num::One;
|
use num::One;
|
||||||
use alga::general::ComplexField;
|
use simba::scalar::ComplexField;
|
||||||
|
|
||||||
use crate::allocator::Allocator;
|
use crate::allocator::Allocator;
|
||||||
use crate::base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, SquareMatrix, Vector};
|
use crate::base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, SquareMatrix, Vector};
|
||||||
use crate::constraint::{SameNumberOfRows, ShapeConstraint};
|
use crate::constraint::{SameNumberOfRows, ShapeConstraint};
|
||||||
use crate::dimension::{Dim, DimAdd, DimSum, DimDiff, DimSub, Dynamic, U1};
|
use crate::dimension::{Dim, DimAdd, DimDiff, DimSub, DimSum, Dynamic, U1};
|
||||||
use crate::storage::{Storage, StorageMut};
|
use crate::storage::{Storage, StorageMut};
|
||||||
|
|
||||||
/// The Cholesky decomposition of a symmetric-definite-positive matrix.
|
/// The Cholesky decomposition of a symmetric-definite-positive matrix.
|
||||||
|
@ -24,8 +24,7 @@ use crate::storage::{Storage, StorageMut};
|
||||||
)]
|
)]
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Cholesky<N: ComplexField, D: Dim>
|
pub struct Cholesky<N: ComplexField, D: Dim>
|
||||||
where
|
where DefaultAllocator: Allocator<N, D, D>
|
||||||
DefaultAllocator: Allocator<N, D, D>,
|
|
||||||
{
|
{
|
||||||
chol: MatrixN<N, D>,
|
chol: MatrixN<N, D>,
|
||||||
}
|
}
|
||||||
|
@ -38,8 +37,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: ComplexField, D: DimSub<Dynamic>> Cholesky<N, D>
|
impl<N: ComplexField, D: DimSub<Dynamic>> Cholesky<N, D>
|
||||||
where
|
where DefaultAllocator: Allocator<N, D, D>
|
||||||
DefaultAllocator: Allocator<N, D, D>,
|
|
||||||
{
|
{
|
||||||
/// Attempts to compute the Cholesky decomposition of `matrix`.
|
/// Attempts to compute the Cholesky decomposition of `matrix`.
|
||||||
///
|
///
|
||||||
|
@ -176,22 +174,38 @@ where
|
||||||
let mut col = col.into_owned();
|
let mut col = col.into_owned();
|
||||||
// for an explanation of the formulas, see https://en.wikipedia.org/wiki/Cholesky_decomposition#Updating_the_decomposition
|
// for an explanation of the formulas, see https://en.wikipedia.org/wiki/Cholesky_decomposition#Updating_the_decomposition
|
||||||
let n = col.nrows();
|
let n = col.nrows();
|
||||||
assert_eq!(n, self.chol.nrows() + 1, "The new column must have the size of the factored matrix plus one.");
|
assert_eq!(
|
||||||
|
n,
|
||||||
|
self.chol.nrows() + 1,
|
||||||
|
"The new column must have the size of the factored matrix plus one."
|
||||||
|
);
|
||||||
assert!(j < n, "j needs to be within the bound of the new matrix.");
|
assert!(j < n, "j needs to be within the bound of the new matrix.");
|
||||||
|
|
||||||
// loads the data into a new matrix with an additional jth row/column
|
// loads the data into a new matrix with an additional jth row/column
|
||||||
let mut chol = unsafe { Matrix::new_uninitialized_generic(self.chol.data.shape().0.add(U1), self.chol.data.shape().1.add(U1)) };
|
let mut chol = unsafe {
|
||||||
chol.slice_range_mut(..j, ..j).copy_from(&self.chol.slice_range(..j, ..j));
|
Matrix::new_uninitialized_generic(
|
||||||
chol.slice_range_mut(..j, j + 1..).copy_from(&self.chol.slice_range(..j, j..));
|
self.chol.data.shape().0.add(U1),
|
||||||
chol.slice_range_mut(j + 1.., ..j).copy_from(&self.chol.slice_range(j.., ..j));
|
self.chol.data.shape().1.add(U1),
|
||||||
chol.slice_range_mut(j + 1.., j + 1..).copy_from(&self.chol.slice_range(j.., j..));
|
)
|
||||||
|
};
|
||||||
|
chol.slice_range_mut(..j, ..j)
|
||||||
|
.copy_from(&self.chol.slice_range(..j, ..j));
|
||||||
|
chol.slice_range_mut(..j, j + 1..)
|
||||||
|
.copy_from(&self.chol.slice_range(..j, j..));
|
||||||
|
chol.slice_range_mut(j + 1.., ..j)
|
||||||
|
.copy_from(&self.chol.slice_range(j.., ..j));
|
||||||
|
chol.slice_range_mut(j + 1.., j + 1..)
|
||||||
|
.copy_from(&self.chol.slice_range(j.., j..));
|
||||||
|
|
||||||
// update the jth row
|
// update the jth row
|
||||||
let top_left_corner = self.chol.slice_range(..j, ..j);
|
let top_left_corner = self.chol.slice_range(..j, ..j);
|
||||||
|
|
||||||
let col_j = col[j];
|
let col_j = col[j];
|
||||||
let (mut new_rowj_adjoint, mut new_colj) = col.rows_range_pair_mut(..j, j + 1..);
|
let (mut new_rowj_adjoint, mut new_colj) = col.rows_range_pair_mut(..j, j + 1..);
|
||||||
assert!(top_left_corner.solve_lower_triangular_mut(&mut new_rowj_adjoint), "Cholesky::insert_column : Unable to solve lower triangular system!");
|
assert!(
|
||||||
|
top_left_corner.solve_lower_triangular_mut(&mut new_rowj_adjoint),
|
||||||
|
"Cholesky::insert_column : Unable to solve lower triangular system!"
|
||||||
|
);
|
||||||
|
|
||||||
new_rowj_adjoint.adjoint_to(&mut chol.slice_range_mut(j, ..j));
|
new_rowj_adjoint.adjoint_to(&mut chol.slice_range_mut(j, ..j));
|
||||||
|
|
||||||
|
@ -202,36 +216,51 @@ where
|
||||||
// update the jth column
|
// update the jth column
|
||||||
let bottom_left_corner = self.chol.slice_range(j.., ..j);
|
let bottom_left_corner = self.chol.slice_range(j.., ..j);
|
||||||
// new_colj = (col_jplus - bottom_left_corner * new_rowj.adjoint()) / center_element;
|
// new_colj = (col_jplus - bottom_left_corner * new_rowj.adjoint()) / center_element;
|
||||||
new_colj.gemm(-N::one() / center_element, &bottom_left_corner, &new_rowj_adjoint, N::one() / center_element);
|
new_colj.gemm(
|
||||||
|
-N::one() / center_element,
|
||||||
|
&bottom_left_corner,
|
||||||
|
&new_rowj_adjoint,
|
||||||
|
N::one() / center_element,
|
||||||
|
);
|
||||||
chol.slice_range_mut(j + 1.., j).copy_from(&new_colj);
|
chol.slice_range_mut(j + 1.., j).copy_from(&new_colj);
|
||||||
|
|
||||||
// update the bottom right corner
|
// update the bottom right corner
|
||||||
let mut bottom_right_corner = chol.slice_range_mut(j + 1.., j + 1..);
|
let mut bottom_right_corner = chol.slice_range_mut(j + 1.., j + 1..);
|
||||||
Self::xx_rank_one_update(&mut bottom_right_corner, &mut new_colj, -N::RealField::one());
|
Self::xx_rank_one_update(
|
||||||
|
&mut bottom_right_corner,
|
||||||
|
&mut new_colj,
|
||||||
|
-N::RealField::one(),
|
||||||
|
);
|
||||||
|
|
||||||
Cholesky { chol }
|
Cholesky { chol }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Updates the decomposition such that we get the decomposition of the factored matrix with its `j`th column removed.
|
/// Updates the decomposition such that we get the decomposition of the factored matrix with its `j`th column removed.
|
||||||
/// Since the matrix is square, the `j`th row will also be removed.
|
/// Since the matrix is square, the `j`th row will also be removed.
|
||||||
pub fn remove_column(
|
pub fn remove_column(&self, j: usize) -> Cholesky<N, DimDiff<D, U1>>
|
||||||
&self,
|
where
|
||||||
j: usize,
|
D: DimSub<U1>,
|
||||||
) -> Cholesky<N, DimDiff<D, U1>>
|
DefaultAllocator: Allocator<N, DimDiff<D, U1>, DimDiff<D, U1>> + Allocator<N, D>,
|
||||||
where
|
|
||||||
D: DimSub<U1>,
|
|
||||||
DefaultAllocator: Allocator<N, DimDiff<D, U1>, DimDiff<D, U1>> + Allocator<N, D>
|
|
||||||
{
|
{
|
||||||
let n = self.chol.nrows();
|
let n = self.chol.nrows();
|
||||||
assert!(n > 0, "The matrix needs at least one column.");
|
assert!(n > 0, "The matrix needs at least one column.");
|
||||||
assert!(j < n, "j needs to be within the bound of the matrix.");
|
assert!(j < n, "j needs to be within the bound of the matrix.");
|
||||||
|
|
||||||
// loads the data into a new matrix except for the jth row/column
|
// loads the data into a new matrix except for the jth row/column
|
||||||
let mut chol = unsafe { Matrix::new_uninitialized_generic(self.chol.data.shape().0.sub(U1), self.chol.data.shape().1.sub(U1)) };
|
let mut chol = unsafe {
|
||||||
chol.slice_range_mut(..j, ..j).copy_from(&self.chol.slice_range(..j, ..j));
|
Matrix::new_uninitialized_generic(
|
||||||
chol.slice_range_mut(..j, j..).copy_from(&self.chol.slice_range(..j, j + 1..));
|
self.chol.data.shape().0.sub(U1),
|
||||||
chol.slice_range_mut(j.., ..j).copy_from(&self.chol.slice_range(j + 1.., ..j));
|
self.chol.data.shape().1.sub(U1),
|
||||||
chol.slice_range_mut(j.., j..).copy_from(&self.chol.slice_range(j + 1.., j + 1..));
|
)
|
||||||
|
};
|
||||||
|
chol.slice_range_mut(..j, ..j)
|
||||||
|
.copy_from(&self.chol.slice_range(..j, ..j));
|
||||||
|
chol.slice_range_mut(..j, j..)
|
||||||
|
.copy_from(&self.chol.slice_range(..j, j + 1..));
|
||||||
|
chol.slice_range_mut(j.., ..j)
|
||||||
|
.copy_from(&self.chol.slice_range(j + 1.., ..j));
|
||||||
|
chol.slice_range_mut(j.., j..)
|
||||||
|
.copy_from(&self.chol.slice_range(j + 1.., j + 1..));
|
||||||
|
|
||||||
// updates the bottom right corner
|
// updates the bottom right corner
|
||||||
let mut bottom_right_corner = chol.slice_range_mut(j.., j..);
|
let mut bottom_right_corner = chol.slice_range_mut(j.., j..);
|
||||||
|
@ -247,13 +276,16 @@ where
|
||||||
///
|
///
|
||||||
/// This helper method is called by `rank_one_update` but also `insert_column` and `remove_column`
|
/// This helper method is called by `rank_one_update` but also `insert_column` and `remove_column`
|
||||||
/// where it is used on a square slice of the decomposition
|
/// where it is used on a square slice of the decomposition
|
||||||
fn xx_rank_one_update<Dm, Sm, Rx, Sx>(chol : &mut Matrix<N, Dm, Dm, Sm>, x: &mut Vector<N, Rx, Sx>, sigma: N::RealField)
|
fn xx_rank_one_update<Dm, Sm, Rx, Sx>(
|
||||||
where
|
chol: &mut Matrix<N, Dm, Dm, Sm>,
|
||||||
//N: ComplexField,
|
x: &mut Vector<N, Rx, Sx>,
|
||||||
Dm: Dim,
|
sigma: N::RealField,
|
||||||
Rx: Dim,
|
) where
|
||||||
Sm: StorageMut<N, Dm, Dm>,
|
//N: ComplexField,
|
||||||
Sx: StorageMut<N, Rx, U1>,
|
Dm: Dim,
|
||||||
|
Rx: Dim,
|
||||||
|
Sm: StorageMut<N, Dm, Dm>,
|
||||||
|
Sx: StorageMut<N, Rx, U1>,
|
||||||
{
|
{
|
||||||
// heavily inspired by Eigen's `llt_rank_update_lower` implementation https://eigen.tuxfamily.org/dox/LLT_8h_source.html
|
// heavily inspired by Eigen's `llt_rank_update_lower` implementation https://eigen.tuxfamily.org/dox/LLT_8h_source.html
|
||||||
let n = x.nrows();
|
let n = x.nrows();
|
||||||
|
@ -293,8 +325,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: ComplexField, D: DimSub<Dynamic>, S: Storage<N, D, D>> SquareMatrix<N, D, S>
|
impl<N: ComplexField, D: DimSub<Dynamic>, S: Storage<N, D, D>> SquareMatrix<N, D, S>
|
||||||
where
|
where DefaultAllocator: Allocator<N, D, D>
|
||||||
DefaultAllocator: Allocator<N, D, D>,
|
|
||||||
{
|
{
|
||||||
/// Attempts to compute the Cholesky decomposition of this matrix.
|
/// Attempts to compute the Cholesky decomposition of this matrix.
|
||||||
///
|
///
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use alga::general::ComplexField;
|
use simba::scalar::ComplexField;
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::dimension::DimMin;
|
use crate::base::dimension::DimMin;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#[cfg(feature = "serde-serialize")]
|
#[cfg(feature = "serde-serialize")]
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use alga::general::ComplexField;
|
|
||||||
use num_complex::Complex;
|
use num_complex::Complex;
|
||||||
|
use simba::scalar::ComplexField;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use std::ops::MulAssign;
|
use std::ops::MulAssign;
|
||||||
|
@ -10,7 +10,9 @@ use std::ops::MulAssign;
|
||||||
use crate::allocator::Allocator;
|
use crate::allocator::Allocator;
|
||||||
use crate::base::dimension::{Dim, DimDiff, DimSub, Dynamic, U1, U2, U3};
|
use crate::base::dimension::{Dim, DimDiff, DimSub, Dynamic, U1, U2, U3};
|
||||||
use crate::base::storage::Storage;
|
use crate::base::storage::Storage;
|
||||||
use crate::base::{DefaultAllocator, Hessenberg, MatrixN, SquareMatrix, Unit, Vector2, Vector3, VectorN};
|
use crate::base::{
|
||||||
|
DefaultAllocator, Hessenberg, MatrixN, SquareMatrix, Unit, Vector2, Vector3, VectorN,
|
||||||
|
};
|
||||||
use crate::constraint::{DimEq, ShapeConstraint};
|
use crate::constraint::{DimEq, ShapeConstraint};
|
||||||
|
|
||||||
use crate::geometry::{Reflection, UnitComplex};
|
use crate::geometry::{Reflection, UnitComplex};
|
||||||
|
@ -21,28 +23,19 @@ use crate::linalg::Schur;
|
||||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serde-serialize",
|
feature = "serde-serialize",
|
||||||
serde(
|
serde(bound(serialize = "DefaultAllocator: Allocator<N, D>,
|
||||||
bound(
|
|
||||||
serialize = "DefaultAllocator: Allocator<N, D>,
|
|
||||||
VectorN<N, D>: Serialize,
|
VectorN<N, D>: Serialize,
|
||||||
MatrixN<N, D>: Serialize"
|
MatrixN<N, D>: Serialize"))
|
||||||
)
|
|
||||||
)
|
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serde-serialize",
|
feature = "serde-serialize",
|
||||||
serde(
|
serde(bound(deserialize = "DefaultAllocator: Allocator<N, D>,
|
||||||
bound(
|
|
||||||
deserialize = "DefaultAllocator: Allocator<N, D>,
|
|
||||||
VectorN<N, D>: Serialize,
|
VectorN<N, D>: Serialize,
|
||||||
MatrixN<N, D>: Deserialize<'de>"
|
MatrixN<N, D>: Deserialize<'de>"))
|
||||||
)
|
|
||||||
)
|
|
||||||
)]
|
)]
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Eigen<N: ComplexField, D: Dim>
|
pub struct Eigen<N: ComplexField, D: Dim>
|
||||||
where
|
where DefaultAllocator: Allocator<N, D, D> + Allocator<N, D>
|
||||||
DefaultAllocator: Allocator<N, D, D> + Allocator<N, D>,
|
|
||||||
{
|
{
|
||||||
pub eigenvectors: MatrixN<N, D>,
|
pub eigenvectors: MatrixN<N, D>,
|
||||||
pub eigenvalues: VectorN<N, D>,
|
pub eigenvalues: VectorN<N, D>,
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
#[cfg(feature = "serde-serialize")]
|
#[cfg(feature = "serde-serialize")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use alga::general::ComplexField;
|
|
||||||
use crate::allocator::Allocator;
|
use crate::allocator::Allocator;
|
||||||
use crate::base::{DefaultAllocator, Matrix, MatrixMN, MatrixN};
|
use crate::base::{DefaultAllocator, Matrix, MatrixMN, MatrixN};
|
||||||
use crate::constraint::{SameNumberOfRows, ShapeConstraint};
|
use crate::constraint::{SameNumberOfRows, ShapeConstraint};
|
||||||
use crate::dimension::{Dim, DimMin, DimMinimum};
|
use crate::dimension::{Dim, DimMin, DimMinimum};
|
||||||
use crate::storage::{Storage, StorageMut};
|
use crate::storage::{Storage, StorageMut};
|
||||||
|
use simba::scalar::ComplexField;
|
||||||
|
|
||||||
use crate::linalg::lu;
|
use crate::linalg::lu;
|
||||||
use crate::linalg::PermutationSequence;
|
use crate::linalg::PermutationSequence;
|
||||||
|
@ -15,21 +15,17 @@ use crate::linalg::PermutationSequence;
|
||||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serde-serialize",
|
feature = "serde-serialize",
|
||||||
serde(bound(
|
serde(bound(serialize = "DefaultAllocator: Allocator<N, R, C> +
|
||||||
serialize = "DefaultAllocator: Allocator<N, R, C> +
|
|
||||||
Allocator<(usize, usize), DimMinimum<R, C>>,
|
Allocator<(usize, usize), DimMinimum<R, C>>,
|
||||||
MatrixMN<N, R, C>: Serialize,
|
MatrixMN<N, R, C>: Serialize,
|
||||||
PermutationSequence<DimMinimum<R, C>>: Serialize"
|
PermutationSequence<DimMinimum<R, C>>: Serialize"))
|
||||||
))
|
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serde-serialize",
|
feature = "serde-serialize",
|
||||||
serde(bound(
|
serde(bound(deserialize = "DefaultAllocator: Allocator<N, R, C> +
|
||||||
deserialize = "DefaultAllocator: Allocator<N, R, C> +
|
|
||||||
Allocator<(usize, usize), DimMinimum<R, C>>,
|
Allocator<(usize, usize), DimMinimum<R, C>>,
|
||||||
MatrixMN<N, R, C>: Deserialize<'de>,
|
MatrixMN<N, R, C>: Deserialize<'de>,
|
||||||
PermutationSequence<DimMinimum<R, C>>: Deserialize<'de>"
|
PermutationSequence<DimMinimum<R, C>>: Deserialize<'de>"))
|
||||||
))
|
|
||||||
)]
|
)]
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct FullPivLU<N: ComplexField, R: DimMin<C>, C: Dim>
|
pub struct FullPivLU<N: ComplexField, R: DimMin<C>, C: Dim>
|
||||||
|
@ -45,7 +41,8 @@ where
|
||||||
DefaultAllocator: Allocator<N, R, C> + Allocator<(usize, usize), DimMinimum<R, C>>,
|
DefaultAllocator: Allocator<N, R, C> + Allocator<(usize, usize), DimMinimum<R, C>>,
|
||||||
MatrixMN<N, R, C>: Copy,
|
MatrixMN<N, R, C>: Copy,
|
||||||
PermutationSequence<DimMinimum<R, C>>: Copy,
|
PermutationSequence<DimMinimum<R, C>>: Copy,
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
impl<N: ComplexField, R: DimMin<C>, C: Dim> FullPivLU<N, R, C>
|
impl<N: ComplexField, R: DimMin<C>, C: Dim> FullPivLU<N, R, C>
|
||||||
where DefaultAllocator: Allocator<N, R, C> + Allocator<(usize, usize), DimMinimum<R, C>>
|
where DefaultAllocator: Allocator<N, R, C> + Allocator<(usize, usize), DimMinimum<R, C>>
|
||||||
|
|
|
@ -1,19 +1,18 @@
|
||||||
//! Construction of givens rotations.
|
//! Construction of givens rotations.
|
||||||
|
|
||||||
use alga::general::ComplexField;
|
use num::{One, Zero};
|
||||||
use num::{Zero, One};
|
use simba::scalar::ComplexField;
|
||||||
|
|
||||||
|
use crate::base::constraint::{DimEq, ShapeConstraint};
|
||||||
use crate::base::dimension::{Dim, U2};
|
use crate::base::dimension::{Dim, U2};
|
||||||
use crate::base::constraint::{ShapeConstraint, DimEq};
|
|
||||||
use crate::base::storage::{Storage, StorageMut};
|
use crate::base::storage::{Storage, StorageMut};
|
||||||
use crate::base::{Vector, Matrix};
|
use crate::base::{Matrix, Vector};
|
||||||
|
|
||||||
|
|
||||||
/// A Givens rotation.
|
/// A Givens rotation.
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct GivensRotation<N: ComplexField> {
|
pub struct GivensRotation<N: ComplexField> {
|
||||||
c: N::RealField,
|
c: N::RealField,
|
||||||
s: N
|
s: N,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Matrix = UnitComplex * Matrix
|
// Matrix = UnitComplex * Matrix
|
||||||
|
@ -22,7 +21,7 @@ impl<N: ComplexField> GivensRotation<N> {
|
||||||
pub fn identity() -> Self {
|
pub fn identity() -> Self {
|
||||||
Self {
|
Self {
|
||||||
c: N::RealField::one(),
|
c: N::RealField::one(),
|
||||||
s: N::zero()
|
s: N::zero(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,9 +30,7 @@ impl<N: ComplexField> GivensRotation<N> {
|
||||||
/// The components are copies as-is. It is not checked whether they describe
|
/// The components are copies as-is. It is not checked whether they describe
|
||||||
/// an actually valid Givens rotation.
|
/// an actually valid Givens rotation.
|
||||||
pub fn new_unchecked(c: N::RealField, s: N) -> Self {
|
pub fn new_unchecked(c: N::RealField, s: N) -> Self {
|
||||||
Self {
|
Self { c, s }
|
||||||
c, s
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initializes a Givens rotation from its non-normalized cosine an sine components.
|
/// Initializes a Givens rotation from its non-normalized cosine an sine components.
|
||||||
|
@ -103,7 +100,10 @@ impl<N: ComplexField> GivensRotation<N> {
|
||||||
|
|
||||||
/// The inverse of this givens rotation.
|
/// The inverse of this givens rotation.
|
||||||
pub fn inverse(&self) -> Self {
|
pub fn inverse(&self) -> Self {
|
||||||
Self { c: self.c, s: -self.s }
|
Self {
|
||||||
|
c: self.c,
|
||||||
|
s: -self.s,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Performs the multiplication `rhs = self * rhs` in-place.
|
/// Performs the multiplication `rhs = self * rhs` in-place.
|
||||||
|
@ -159,4 +159,3 @@ impl<N: ComplexField> GivensRotation<N> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
#[cfg(feature = "serde-serialize")]
|
#[cfg(feature = "serde-serialize")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use alga::general::ComplexField;
|
|
||||||
use crate::allocator::Allocator;
|
use crate::allocator::Allocator;
|
||||||
use crate::base::{DefaultAllocator, MatrixMN, MatrixN, SquareMatrix, VectorN};
|
use crate::base::{DefaultAllocator, MatrixMN, MatrixN, SquareMatrix, VectorN};
|
||||||
use crate::dimension::{DimDiff, DimSub, U1};
|
use crate::dimension::{DimDiff, DimSub, U1};
|
||||||
use crate::storage::Storage;
|
use crate::storage::Storage;
|
||||||
|
use simba::scalar::ComplexField;
|
||||||
|
|
||||||
use crate::linalg::householder;
|
use crate::linalg::householder;
|
||||||
|
|
||||||
|
@ -13,21 +13,17 @@ use crate::linalg::householder;
|
||||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serde-serialize",
|
feature = "serde-serialize",
|
||||||
serde(bound(
|
serde(bound(serialize = "DefaultAllocator: Allocator<N, D, D> +
|
||||||
serialize = "DefaultAllocator: Allocator<N, D, D> +
|
|
||||||
Allocator<N, DimDiff<D, U1>>,
|
Allocator<N, DimDiff<D, U1>>,
|
||||||
MatrixN<N, D>: Serialize,
|
MatrixN<N, D>: Serialize,
|
||||||
VectorN<N, DimDiff<D, U1>>: Serialize"
|
VectorN<N, DimDiff<D, U1>>: Serialize"))
|
||||||
))
|
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serde-serialize",
|
feature = "serde-serialize",
|
||||||
serde(bound(
|
serde(bound(deserialize = "DefaultAllocator: Allocator<N, D, D> +
|
||||||
deserialize = "DefaultAllocator: Allocator<N, D, D> +
|
|
||||||
Allocator<N, DimDiff<D, U1>>,
|
Allocator<N, DimDiff<D, U1>>,
|
||||||
MatrixN<N, D>: Deserialize<'de>,
|
MatrixN<N, D>: Deserialize<'de>,
|
||||||
VectorN<N, DimDiff<D, U1>>: Deserialize<'de>"
|
VectorN<N, DimDiff<D, U1>>: Deserialize<'de>"))
|
||||||
))
|
|
||||||
)]
|
)]
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Hessenberg<N: ComplexField, D: DimSub<U1>>
|
pub struct Hessenberg<N: ComplexField, D: DimSub<U1>>
|
||||||
|
@ -42,7 +38,8 @@ where
|
||||||
DefaultAllocator: Allocator<N, D, D> + Allocator<N, DimDiff<D, U1>>,
|
DefaultAllocator: Allocator<N, D, D> + Allocator<N, DimDiff<D, U1>>,
|
||||||
MatrixN<N, D>: Copy,
|
MatrixN<N, D>: Copy,
|
||||||
VectorN<N, DimDiff<D, U1>>: Copy,
|
VectorN<N, DimDiff<D, U1>>: Copy,
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
impl<N: ComplexField, D: DimSub<U1>> Hessenberg<N, D>
|
impl<N: ComplexField, D: DimSub<U1>> Hessenberg<N, D>
|
||||||
where DefaultAllocator: Allocator<N, D, D> + Allocator<N, D> + Allocator<N, DimDiff<D, U1>>
|
where DefaultAllocator: Allocator<N, D, D> + Allocator<N, D> + Allocator<N, DimDiff<D, U1>>
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
//! Construction of householder elementary reflections.
|
//! Construction of householder elementary reflections.
|
||||||
|
|
||||||
use num::Zero;
|
|
||||||
use alga::general::ComplexField;
|
|
||||||
use crate::allocator::Allocator;
|
use crate::allocator::Allocator;
|
||||||
use crate::base::{DefaultAllocator, MatrixMN, MatrixN, Unit, Vector, VectorN};
|
use crate::base::{DefaultAllocator, MatrixMN, MatrixN, Unit, Vector, VectorN};
|
||||||
use crate::dimension::Dim;
|
use crate::dimension::Dim;
|
||||||
use crate::storage::{Storage, StorageMut};
|
use crate::storage::{Storage, StorageMut};
|
||||||
|
use num::Zero;
|
||||||
|
use simba::scalar::ComplexField;
|
||||||
|
|
||||||
use crate::geometry::Reflection;
|
use crate::geometry::Reflection;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use alga::general::ComplexField;
|
use simba::scalar::ComplexField;
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::dimension::Dim;
|
use crate::base::dimension::Dim;
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
#[cfg(feature = "serde-serialize")]
|
#[cfg(feature = "serde-serialize")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use alga::general::{Field, ComplexField};
|
|
||||||
use crate::allocator::{Allocator, Reallocator};
|
use crate::allocator::{Allocator, Reallocator};
|
||||||
use crate::base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, Scalar};
|
use crate::base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, Scalar};
|
||||||
use crate::constraint::{SameNumberOfRows, ShapeConstraint};
|
use crate::constraint::{SameNumberOfRows, ShapeConstraint};
|
||||||
use crate::dimension::{Dim, DimMin, DimMinimum};
|
use crate::dimension::{Dim, DimMin, DimMinimum};
|
||||||
use std::mem;
|
|
||||||
use crate::storage::{Storage, StorageMut};
|
use crate::storage::{Storage, StorageMut};
|
||||||
|
use simba::scalar::{ComplexField, Field};
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
use crate::linalg::PermutationSequence;
|
use crate::linalg::PermutationSequence;
|
||||||
|
|
||||||
|
@ -15,21 +15,17 @@ use crate::linalg::PermutationSequence;
|
||||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serde-serialize",
|
feature = "serde-serialize",
|
||||||
serde(bound(
|
serde(bound(serialize = "DefaultAllocator: Allocator<N, R, C> +
|
||||||
serialize = "DefaultAllocator: Allocator<N, R, C> +
|
|
||||||
Allocator<(usize, usize), DimMinimum<R, C>>,
|
Allocator<(usize, usize), DimMinimum<R, C>>,
|
||||||
MatrixMN<N, R, C>: Serialize,
|
MatrixMN<N, R, C>: Serialize,
|
||||||
PermutationSequence<DimMinimum<R, C>>: Serialize"
|
PermutationSequence<DimMinimum<R, C>>: Serialize"))
|
||||||
))
|
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serde-serialize",
|
feature = "serde-serialize",
|
||||||
serde(bound(
|
serde(bound(deserialize = "DefaultAllocator: Allocator<N, R, C> +
|
||||||
deserialize = "DefaultAllocator: Allocator<N, R, C> +
|
|
||||||
Allocator<(usize, usize), DimMinimum<R, C>>,
|
Allocator<(usize, usize), DimMinimum<R, C>>,
|
||||||
MatrixMN<N, R, C>: Deserialize<'de>,
|
MatrixMN<N, R, C>: Deserialize<'de>,
|
||||||
PermutationSequence<DimMinimum<R, C>>: Deserialize<'de>"
|
PermutationSequence<DimMinimum<R, C>>: Deserialize<'de>"))
|
||||||
))
|
|
||||||
)]
|
)]
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct LU<N: ComplexField, R: DimMin<C>, C: Dim>
|
pub struct LU<N: ComplexField, R: DimMin<C>, C: Dim>
|
||||||
|
@ -44,7 +40,8 @@ where
|
||||||
DefaultAllocator: Allocator<N, R, C> + Allocator<(usize, usize), DimMinimum<R, C>>,
|
DefaultAllocator: Allocator<N, R, C> + Allocator<(usize, usize), DimMinimum<R, C>>,
|
||||||
MatrixMN<N, R, C>: Copy,
|
MatrixMN<N, R, C>: Copy,
|
||||||
PermutationSequence<DimMinimum<R, C>>: Copy,
|
PermutationSequence<DimMinimum<R, C>>: Copy,
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/// Performs a LU decomposition to overwrite `out` with the inverse of `matrix`.
|
/// Performs a LU decomposition to overwrite `out` with the inverse of `matrix`.
|
||||||
///
|
///
|
||||||
|
@ -333,7 +330,8 @@ where
|
||||||
let (pivot_row, mut down) = submat.rows_range_pair_mut(0, 1..);
|
let (pivot_row, mut down) = submat.rows_range_pair_mut(0, 1..);
|
||||||
|
|
||||||
for k in 0..pivot_row.ncols() {
|
for k in 0..pivot_row.ncols() {
|
||||||
down.column_mut(k).axpy(-pivot_row[k].inlined_clone(), &coeffs, N::one());
|
down.column_mut(k)
|
||||||
|
.axpy(-pivot_row[k].inlined_clone(), &coeffs, N::one());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,7 +362,8 @@ pub fn gauss_step_swap<N, R: Dim, C: Dim, S>(
|
||||||
|
|
||||||
for k in 0..pivot_row.ncols() {
|
for k in 0..pivot_row.ncols() {
|
||||||
mem::swap(&mut pivot_row[k], &mut down[(piv - 1, k)]);
|
mem::swap(&mut pivot_row[k], &mut down[(piv - 1, k)]);
|
||||||
down.column_mut(k).axpy(-pivot_row[k].inlined_clone(), &coeffs, N::one());
|
down.column_mut(k)
|
||||||
|
.axpy(-pivot_row[k].inlined_clone(), &coeffs, N::one());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#[cfg(feature = "serde-serialize")]
|
#[cfg(feature = "serde-serialize")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use alga::general::ClosedNeg;
|
|
||||||
use num::One;
|
use num::One;
|
||||||
|
use simba::scalar::ClosedNeg;
|
||||||
|
|
||||||
use crate::allocator::Allocator;
|
use crate::allocator::Allocator;
|
||||||
use crate::base::{DefaultAllocator, Matrix, Scalar, VectorN};
|
use crate::base::{DefaultAllocator, Matrix, Scalar, VectorN};
|
||||||
|
@ -15,17 +15,13 @@ use crate::storage::StorageMut;
|
||||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serde-serialize",
|
feature = "serde-serialize",
|
||||||
serde(bound(
|
serde(bound(serialize = "DefaultAllocator: Allocator<(usize, usize), D>,
|
||||||
serialize = "DefaultAllocator: Allocator<(usize, usize), D>,
|
VectorN<(usize, usize), D>: Serialize"))
|
||||||
VectorN<(usize, usize), D>: Serialize"
|
|
||||||
))
|
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serde-serialize",
|
feature = "serde-serialize",
|
||||||
serde(bound(
|
serde(bound(deserialize = "DefaultAllocator: Allocator<(usize, usize), D>,
|
||||||
deserialize = "DefaultAllocator: Allocator<(usize, usize), D>,
|
VectorN<(usize, usize), D>: Deserialize<'de>"))
|
||||||
VectorN<(usize, usize), D>: Deserialize<'de>"
|
|
||||||
))
|
|
||||||
)]
|
)]
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct PermutationSequence<D: Dim>
|
pub struct PermutationSequence<D: Dim>
|
||||||
|
@ -39,7 +35,8 @@ impl<D: Dim> Copy for PermutationSequence<D>
|
||||||
where
|
where
|
||||||
DefaultAllocator: Allocator<(usize, usize), D>,
|
DefaultAllocator: Allocator<(usize, usize), D>,
|
||||||
VectorN<(usize, usize), D>: Copy,
|
VectorN<(usize, usize), D>: Copy,
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
impl<D: DimName> PermutationSequence<D>
|
impl<D: DimName> PermutationSequence<D>
|
||||||
where DefaultAllocator: Allocator<(usize, usize), D>
|
where DefaultAllocator: Allocator<(usize, usize), D>
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
|
use num::Zero;
|
||||||
#[cfg(feature = "serde-serialize")]
|
#[cfg(feature = "serde-serialize")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use num::Zero;
|
|
||||||
|
|
||||||
use alga::general::ComplexField;
|
|
||||||
use crate::allocator::{Allocator, Reallocator};
|
use crate::allocator::{Allocator, Reallocator};
|
||||||
use crate::base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, Unit, VectorN};
|
use crate::base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, Unit, VectorN};
|
||||||
use crate::constraint::{SameNumberOfRows, ShapeConstraint};
|
use crate::constraint::{SameNumberOfRows, ShapeConstraint};
|
||||||
use crate::dimension::{Dim, DimMin, DimMinimum, U1};
|
use crate::dimension::{Dim, DimMin, DimMinimum, U1};
|
||||||
use crate::storage::{Storage, StorageMut};
|
use crate::storage::{Storage, StorageMut};
|
||||||
|
use simba::scalar::ComplexField;
|
||||||
|
|
||||||
use crate::geometry::Reflection;
|
use crate::geometry::Reflection;
|
||||||
use crate::linalg::householder;
|
use crate::linalg::householder;
|
||||||
|
@ -16,21 +16,17 @@ use crate::linalg::householder;
|
||||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serde-serialize",
|
feature = "serde-serialize",
|
||||||
serde(bound(
|
serde(bound(serialize = "DefaultAllocator: Allocator<N, R, C> +
|
||||||
serialize = "DefaultAllocator: Allocator<N, R, C> +
|
|
||||||
Allocator<N, DimMinimum<R, C>>,
|
Allocator<N, DimMinimum<R, C>>,
|
||||||
MatrixMN<N, R, C>: Serialize,
|
MatrixMN<N, R, C>: Serialize,
|
||||||
VectorN<N, DimMinimum<R, C>>: Serialize"
|
VectorN<N, DimMinimum<R, C>>: Serialize"))
|
||||||
))
|
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serde-serialize",
|
feature = "serde-serialize",
|
||||||
serde(bound(
|
serde(bound(deserialize = "DefaultAllocator: Allocator<N, R, C> +
|
||||||
deserialize = "DefaultAllocator: Allocator<N, R, C> +
|
|
||||||
Allocator<N, DimMinimum<R, C>>,
|
Allocator<N, DimMinimum<R, C>>,
|
||||||
MatrixMN<N, R, C>: Deserialize<'de>,
|
MatrixMN<N, R, C>: Deserialize<'de>,
|
||||||
VectorN<N, DimMinimum<R, C>>: Deserialize<'de>"
|
VectorN<N, DimMinimum<R, C>>: Deserialize<'de>"))
|
||||||
))
|
|
||||||
)]
|
)]
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct QR<N: ComplexField, R: DimMin<C>, C: Dim>
|
pub struct QR<N: ComplexField, R: DimMin<C>, C: Dim>
|
||||||
|
@ -45,7 +41,8 @@ where
|
||||||
DefaultAllocator: Allocator<N, R, C> + Allocator<N, DimMinimum<R, C>>,
|
DefaultAllocator: Allocator<N, R, C> + Allocator<N, DimMinimum<R, C>>,
|
||||||
MatrixMN<N, R, C>: Copy,
|
MatrixMN<N, R, C>: Copy,
|
||||||
VectorN<N, DimMinimum<R, C>>: Copy,
|
VectorN<N, DimMinimum<R, C>>: Copy,
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
impl<N: ComplexField, R: DimMin<C>, C: Dim> QR<N, R, C>
|
impl<N: ComplexField, R: DimMin<C>, C: Dim> QR<N, R, C>
|
||||||
where DefaultAllocator: Allocator<N, R, C> + Allocator<N, R> + Allocator<N, DimMinimum<R, C>>
|
where DefaultAllocator: Allocator<N, R, C> + Allocator<N, R> + Allocator<N, DimMinimum<R, C>>
|
||||||
|
@ -77,9 +74,7 @@ where DefaultAllocator: Allocator<N, R, C> + Allocator<N, R> + Allocator<N, DimM
|
||||||
/// Retrieves the upper trapezoidal submatrix `R` of this decomposition.
|
/// Retrieves the upper trapezoidal submatrix `R` of this decomposition.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn r(&self) -> MatrixMN<N, DimMinimum<R, C>, C>
|
pub fn r(&self) -> MatrixMN<N, DimMinimum<R, C>, C>
|
||||||
where
|
where DefaultAllocator: Allocator<N, DimMinimum<R, C>, C> {
|
||||||
DefaultAllocator: Allocator<N, DimMinimum<R, C>, C>,
|
|
||||||
{
|
|
||||||
let (nrows, ncols) = self.qr.data.shape();
|
let (nrows, ncols) = self.qr.data.shape();
|
||||||
let mut res = self.qr.rows_generic(0, nrows.min(ncols)).upper_triangle();
|
let mut res = self.qr.rows_generic(0, nrows.min(ncols)).upper_triangle();
|
||||||
res.set_partial_diagonal(self.diag.iter().map(|e| N::from_real(e.modulus())));
|
res.set_partial_diagonal(self.diag.iter().map(|e| N::from_real(e.modulus())));
|
||||||
|
@ -91,9 +86,7 @@ where DefaultAllocator: Allocator<N, R, C> + Allocator<N, R> + Allocator<N, DimM
|
||||||
/// This is usually faster than `r` but consumes `self`.
|
/// This is usually faster than `r` but consumes `self`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn unpack_r(self) -> MatrixMN<N, DimMinimum<R, C>, C>
|
pub fn unpack_r(self) -> MatrixMN<N, DimMinimum<R, C>, C>
|
||||||
where
|
where DefaultAllocator: Reallocator<N, R, C, DimMinimum<R, C>, C> {
|
||||||
DefaultAllocator: Reallocator<N, R, C, DimMinimum<R, C>, C>,
|
|
||||||
{
|
|
||||||
let (nrows, ncols) = self.qr.data.shape();
|
let (nrows, ncols) = self.qr.data.shape();
|
||||||
let mut res = self.qr.resize_generic(nrows.min(ncols), ncols, N::zero());
|
let mut res = self.qr.resize_generic(nrows.min(ncols), ncols, N::zero());
|
||||||
res.fill_lower_triangle(N::zero(), 1);
|
res.fill_lower_triangle(N::zero(), 1);
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use approx::AbsDiffEq;
|
use approx::AbsDiffEq;
|
||||||
use alga::general::{ComplexField, RealField};
|
|
||||||
use num_complex::Complex as NumComplex;
|
use num_complex::Complex as NumComplex;
|
||||||
|
use simba::scalar::{ComplexField, RealField};
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
|
|
||||||
use crate::allocator::Allocator;
|
use crate::allocator::Allocator;
|
||||||
|
@ -12,9 +12,9 @@ use crate::base::storage::Storage;
|
||||||
use crate::base::{DefaultAllocator, MatrixN, SquareMatrix, Unit, Vector2, Vector3, VectorN};
|
use crate::base::{DefaultAllocator, MatrixN, SquareMatrix, Unit, Vector2, Vector3, VectorN};
|
||||||
|
|
||||||
use crate::geometry::Reflection;
|
use crate::geometry::Reflection;
|
||||||
|
use crate::linalg::givens::GivensRotation;
|
||||||
use crate::linalg::householder;
|
use crate::linalg::householder;
|
||||||
use crate::linalg::Hessenberg;
|
use crate::linalg::Hessenberg;
|
||||||
use crate::linalg::givens::GivensRotation;
|
|
||||||
|
|
||||||
/// Schur decomposition of a square matrix.
|
/// Schur decomposition of a square matrix.
|
||||||
///
|
///
|
||||||
|
@ -22,17 +22,13 @@ use crate::linalg::givens::GivensRotation;
|
||||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serde-serialize",
|
feature = "serde-serialize",
|
||||||
serde(bound(
|
serde(bound(serialize = "DefaultAllocator: Allocator<N, D, D>,
|
||||||
serialize = "DefaultAllocator: Allocator<N, D, D>,
|
MatrixN<N, D>: Serialize"))
|
||||||
MatrixN<N, D>: Serialize"
|
|
||||||
))
|
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serde-serialize",
|
feature = "serde-serialize",
|
||||||
serde(bound(
|
serde(bound(deserialize = "DefaultAllocator: Allocator<N, D, D>,
|
||||||
deserialize = "DefaultAllocator: Allocator<N, D, D>,
|
MatrixN<N, D>: Deserialize<'de>"))
|
||||||
MatrixN<N, D>: Deserialize<'de>"
|
|
||||||
))
|
|
||||||
)]
|
)]
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Schur<N: ComplexField, D: Dim>
|
pub struct Schur<N: ComplexField, D: Dim>
|
||||||
|
@ -46,11 +42,12 @@ impl<N: ComplexField, D: Dim> Copy for Schur<N, D>
|
||||||
where
|
where
|
||||||
DefaultAllocator: Allocator<N, D, D>,
|
DefaultAllocator: Allocator<N, D, D>,
|
||||||
MatrixN<N, D>: Copy,
|
MatrixN<N, D>: Copy,
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
impl<N: ComplexField, D: Dim> Schur<N, D>
|
impl<N: ComplexField, D: Dim> Schur<N, D>
|
||||||
where
|
where
|
||||||
D: DimSub<U1>, // For Hessenberg.
|
D: DimSub<U1>, // For Hessenberg.
|
||||||
DefaultAllocator: Allocator<N, D, DimDiff<D, U1>>
|
DefaultAllocator: Allocator<N, D, DimDiff<D, U1>>
|
||||||
+ Allocator<N, DimDiff<D, U1>>
|
+ Allocator<N, DimDiff<D, U1>>
|
||||||
+ Allocator<N, D, D>
|
+ Allocator<N, D, D>
|
||||||
|
@ -291,8 +288,10 @@ where
|
||||||
|
|
||||||
/// Computes the complex eigenvalues of the decomposed matrix.
|
/// Computes the complex eigenvalues of the decomposed matrix.
|
||||||
fn do_complex_eigenvalues(t: &MatrixN<N, D>, out: &mut VectorN<NumComplex<N>, D>)
|
fn do_complex_eigenvalues(t: &MatrixN<N, D>, out: &mut VectorN<NumComplex<N>, D>)
|
||||||
where N: RealField,
|
where
|
||||||
DefaultAllocator: Allocator<NumComplex<N>, D> {
|
N: RealField,
|
||||||
|
DefaultAllocator: Allocator<NumComplex<N>, D>,
|
||||||
|
{
|
||||||
let dim = t.nrows();
|
let dim = t.nrows();
|
||||||
let mut m = 0;
|
let mut m = 0;
|
||||||
|
|
||||||
|
@ -391,8 +390,10 @@ where
|
||||||
|
|
||||||
/// Computes the complex eigenvalues of the decomposed matrix.
|
/// Computes the complex eigenvalues of the decomposed matrix.
|
||||||
pub fn complex_eigenvalues(&self) -> VectorN<NumComplex<N>, D>
|
pub fn complex_eigenvalues(&self) -> VectorN<NumComplex<N>, D>
|
||||||
where N: RealField,
|
where
|
||||||
DefaultAllocator: Allocator<NumComplex<N>, D> {
|
N: RealField,
|
||||||
|
DefaultAllocator: Allocator<NumComplex<N>, D>,
|
||||||
|
{
|
||||||
let mut out = unsafe { VectorN::new_uninitialized_generic(self.t.data.shape().0, U1) };
|
let mut out = unsafe { VectorN::new_uninitialized_generic(self.t.data.shape().0, U1) };
|
||||||
Self::do_complex_eigenvalues(&self.t, &mut out);
|
Self::do_complex_eigenvalues(&self.t, &mut out);
|
||||||
out
|
out
|
||||||
|
@ -491,7 +492,7 @@ fn compute_2x2_basis<N: ComplexField, S: Storage<N, U2, U2>>(
|
||||||
|
|
||||||
impl<N: ComplexField, D: Dim, S: Storage<N, D, D>> SquareMatrix<N, D, S>
|
impl<N: ComplexField, D: Dim, S: Storage<N, D, D>> SquareMatrix<N, D, S>
|
||||||
where
|
where
|
||||||
D: DimSub<U1>, // For Hessenberg.
|
D: DimSub<U1>, // For Hessenberg.
|
||||||
DefaultAllocator: Allocator<N, D, DimDiff<D, U1>>
|
DefaultAllocator: Allocator<N, D, DimDiff<D, U1>>
|
||||||
+ Allocator<N, DimDiff<D, U1>>
|
+ Allocator<N, DimDiff<D, U1>>
|
||||||
+ Allocator<N, D, D>
|
+ Allocator<N, D, D>
|
||||||
|
@ -560,8 +561,10 @@ where
|
||||||
/// Computes the eigenvalues of this matrix.
|
/// Computes the eigenvalues of this matrix.
|
||||||
pub fn complex_eigenvalues(&self) -> VectorN<NumComplex<N>, D>
|
pub fn complex_eigenvalues(&self) -> VectorN<NumComplex<N>, D>
|
||||||
// FIXME: add balancing?
|
// FIXME: add balancing?
|
||||||
where N: RealField,
|
where
|
||||||
DefaultAllocator: Allocator<NumComplex<N>, D> {
|
N: RealField,
|
||||||
|
DefaultAllocator: Allocator<NumComplex<N>, D>,
|
||||||
|
{
|
||||||
let dim = self.data.shape().0;
|
let dim = self.data.shape().0;
|
||||||
let mut work = unsafe { VectorN::new_uninitialized_generic(dim, U1) };
|
let mut work = unsafe { VectorN::new_uninitialized_generic(dim, U1) };
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
use alga::general::ComplexField;
|
use simba::scalar::ComplexField;
|
||||||
|
|
||||||
use crate::base::allocator::Allocator;
|
use crate::base::allocator::Allocator;
|
||||||
use crate::base::constraint::{SameNumberOfRows, ShapeConstraint};
|
use crate::base::constraint::{SameNumberOfRows, ShapeConstraint};
|
||||||
use crate::base::dimension::{Dim, U1};
|
use crate::base::dimension::{Dim, U1};
|
||||||
use crate::base::storage::{Storage, StorageMut};
|
use crate::base::storage::{Storage, StorageMut};
|
||||||
use crate::base::{DefaultAllocator, Matrix, MatrixMN, SquareMatrix, Vector, DVectorSlice};
|
use crate::base::{DVectorSlice, DefaultAllocator, Matrix, MatrixMN, SquareMatrix, Vector};
|
||||||
|
|
||||||
impl<N: ComplexField, D: Dim, S: Storage<N, D, D>> SquareMatrix<N, D, S> {
|
impl<N: ComplexField, D: Dim, S: Storage<N, D, D>> SquareMatrix<N, D, S> {
|
||||||
/// Computes the solution of the linear system `self . x = b` where `x` is the unknown and only
|
/// Computes the solution of the linear system `self . x = b` where `x` is the unknown and only
|
||||||
|
@ -190,10 +190,10 @@ impl<N: ComplexField, D: Dim, S: Storage<N, D, D>> SquareMatrix<N, D, S> {
|
||||||
&self,
|
&self,
|
||||||
b: &Matrix<N, R2, C2, S2>,
|
b: &Matrix<N, R2, C2, S2>,
|
||||||
) -> Option<MatrixMN<N, R2, C2>>
|
) -> Option<MatrixMN<N, R2, C2>>
|
||||||
where
|
where
|
||||||
S2: Storage<N, R2, C2>,
|
S2: Storage<N, R2, C2>,
|
||||||
DefaultAllocator: Allocator<N, R2, C2>,
|
DefaultAllocator: Allocator<N, R2, C2>,
|
||||||
ShapeConstraint: SameNumberOfRows<R2, D>,
|
ShapeConstraint: SameNumberOfRows<R2, D>,
|
||||||
{
|
{
|
||||||
let mut res = b.clone_owned();
|
let mut res = b.clone_owned();
|
||||||
if self.tr_solve_lower_triangular_mut(&mut res) {
|
if self.tr_solve_lower_triangular_mut(&mut res) {
|
||||||
|
@ -210,10 +210,10 @@ impl<N: ComplexField, D: Dim, S: Storage<N, D, D>> SquareMatrix<N, D, S> {
|
||||||
&self,
|
&self,
|
||||||
b: &Matrix<N, R2, C2, S2>,
|
b: &Matrix<N, R2, C2, S2>,
|
||||||
) -> Option<MatrixMN<N, R2, C2>>
|
) -> Option<MatrixMN<N, R2, C2>>
|
||||||
where
|
where
|
||||||
S2: Storage<N, R2, C2>,
|
S2: Storage<N, R2, C2>,
|
||||||
DefaultAllocator: Allocator<N, R2, C2>,
|
DefaultAllocator: Allocator<N, R2, C2>,
|
||||||
ShapeConstraint: SameNumberOfRows<R2, D>,
|
ShapeConstraint: SameNumberOfRows<R2, D>,
|
||||||
{
|
{
|
||||||
let mut res = b.clone_owned();
|
let mut res = b.clone_owned();
|
||||||
if self.tr_solve_upper_triangular_mut(&mut res) {
|
if self.tr_solve_upper_triangular_mut(&mut res) {
|
||||||
|
@ -229,14 +229,18 @@ impl<N: ComplexField, D: Dim, S: Storage<N, D, D>> SquareMatrix<N, D, S> {
|
||||||
&self,
|
&self,
|
||||||
b: &mut Matrix<N, R2, C2, S2>,
|
b: &mut Matrix<N, R2, C2, S2>,
|
||||||
) -> bool
|
) -> bool
|
||||||
where
|
where
|
||||||
S2: StorageMut<N, R2, C2>,
|
S2: StorageMut<N, R2, C2>,
|
||||||
ShapeConstraint: SameNumberOfRows<R2, D>,
|
ShapeConstraint: SameNumberOfRows<R2, D>,
|
||||||
{
|
{
|
||||||
let cols = b.ncols();
|
let cols = b.ncols();
|
||||||
|
|
||||||
for i in 0..cols {
|
for i in 0..cols {
|
||||||
if !self.xx_solve_lower_triangular_vector_mut(&mut b.column_mut(i), |e| e, |a, b| a.dot(b)) {
|
if !self.xx_solve_lower_triangular_vector_mut(
|
||||||
|
&mut b.column_mut(i),
|
||||||
|
|e| e,
|
||||||
|
|a, b| a.dot(b),
|
||||||
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -250,14 +254,18 @@ impl<N: ComplexField, D: Dim, S: Storage<N, D, D>> SquareMatrix<N, D, S> {
|
||||||
&self,
|
&self,
|
||||||
b: &mut Matrix<N, R2, C2, S2>,
|
b: &mut Matrix<N, R2, C2, S2>,
|
||||||
) -> bool
|
) -> bool
|
||||||
where
|
where
|
||||||
S2: StorageMut<N, R2, C2>,
|
S2: StorageMut<N, R2, C2>,
|
||||||
ShapeConstraint: SameNumberOfRows<R2, D>,
|
ShapeConstraint: SameNumberOfRows<R2, D>,
|
||||||
{
|
{
|
||||||
let cols = b.ncols();
|
let cols = b.ncols();
|
||||||
|
|
||||||
for i in 0..cols {
|
for i in 0..cols {
|
||||||
if !self.xx_solve_upper_triangular_vector_mut(&mut b.column_mut(i), |e| e, |a, b| a.dot(b)) {
|
if !self.xx_solve_upper_triangular_vector_mut(
|
||||||
|
&mut b.column_mut(i),
|
||||||
|
|e| e,
|
||||||
|
|a, b| a.dot(b),
|
||||||
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -272,10 +280,10 @@ impl<N: ComplexField, D: Dim, S: Storage<N, D, D>> SquareMatrix<N, D, S> {
|
||||||
&self,
|
&self,
|
||||||
b: &Matrix<N, R2, C2, S2>,
|
b: &Matrix<N, R2, C2, S2>,
|
||||||
) -> Option<MatrixMN<N, R2, C2>>
|
) -> Option<MatrixMN<N, R2, C2>>
|
||||||
where
|
where
|
||||||
S2: Storage<N, R2, C2>,
|
S2: Storage<N, R2, C2>,
|
||||||
DefaultAllocator: Allocator<N, R2, C2>,
|
DefaultAllocator: Allocator<N, R2, C2>,
|
||||||
ShapeConstraint: SameNumberOfRows<R2, D>,
|
ShapeConstraint: SameNumberOfRows<R2, D>,
|
||||||
{
|
{
|
||||||
let mut res = b.clone_owned();
|
let mut res = b.clone_owned();
|
||||||
if self.ad_solve_lower_triangular_mut(&mut res) {
|
if self.ad_solve_lower_triangular_mut(&mut res) {
|
||||||
|
@ -292,10 +300,10 @@ impl<N: ComplexField, D: Dim, S: Storage<N, D, D>> SquareMatrix<N, D, S> {
|
||||||
&self,
|
&self,
|
||||||
b: &Matrix<N, R2, C2, S2>,
|
b: &Matrix<N, R2, C2, S2>,
|
||||||
) -> Option<MatrixMN<N, R2, C2>>
|
) -> Option<MatrixMN<N, R2, C2>>
|
||||||
where
|
where
|
||||||
S2: Storage<N, R2, C2>,
|
S2: Storage<N, R2, C2>,
|
||||||
DefaultAllocator: Allocator<N, R2, C2>,
|
DefaultAllocator: Allocator<N, R2, C2>,
|
||||||
ShapeConstraint: SameNumberOfRows<R2, D>,
|
ShapeConstraint: SameNumberOfRows<R2, D>,
|
||||||
{
|
{
|
||||||
let mut res = b.clone_owned();
|
let mut res = b.clone_owned();
|
||||||
if self.ad_solve_upper_triangular_mut(&mut res) {
|
if self.ad_solve_upper_triangular_mut(&mut res) {
|
||||||
|
@ -311,14 +319,18 @@ impl<N: ComplexField, D: Dim, S: Storage<N, D, D>> SquareMatrix<N, D, S> {
|
||||||
&self,
|
&self,
|
||||||
b: &mut Matrix<N, R2, C2, S2>,
|
b: &mut Matrix<N, R2, C2, S2>,
|
||||||
) -> bool
|
) -> bool
|
||||||
where
|
where
|
||||||
S2: StorageMut<N, R2, C2>,
|
S2: StorageMut<N, R2, C2>,
|
||||||
ShapeConstraint: SameNumberOfRows<R2, D>,
|
ShapeConstraint: SameNumberOfRows<R2, D>,
|
||||||
{
|
{
|
||||||
let cols = b.ncols();
|
let cols = b.ncols();
|
||||||
|
|
||||||
for i in 0..cols {
|
for i in 0..cols {
|
||||||
if !self.xx_solve_lower_triangular_vector_mut(&mut b.column_mut(i), |e| e.conjugate(), |a, b| a.dotc(b)) {
|
if !self.xx_solve_lower_triangular_vector_mut(
|
||||||
|
&mut b.column_mut(i),
|
||||||
|
|e| e.conjugate(),
|
||||||
|
|a, b| a.dotc(b),
|
||||||
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -332,14 +344,18 @@ impl<N: ComplexField, D: Dim, S: Storage<N, D, D>> SquareMatrix<N, D, S> {
|
||||||
&self,
|
&self,
|
||||||
b: &mut Matrix<N, R2, C2, S2>,
|
b: &mut Matrix<N, R2, C2, S2>,
|
||||||
) -> bool
|
) -> bool
|
||||||
where
|
where
|
||||||
S2: StorageMut<N, R2, C2>,
|
S2: StorageMut<N, R2, C2>,
|
||||||
ShapeConstraint: SameNumberOfRows<R2, D>,
|
ShapeConstraint: SameNumberOfRows<R2, D>,
|
||||||
{
|
{
|
||||||
let cols = b.ncols();
|
let cols = b.ncols();
|
||||||
|
|
||||||
for i in 0..cols {
|
for i in 0..cols {
|
||||||
if !self.xx_solve_upper_triangular_vector_mut(&mut b.column_mut(i), |e| e.conjugate(), |a, b| a.dotc(b)) {
|
if !self.xx_solve_upper_triangular_vector_mut(
|
||||||
|
&mut b.column_mut(i),
|
||||||
|
|e| e.conjugate(),
|
||||||
|
|a, b| a.dotc(b),
|
||||||
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -347,17 +363,19 @@ impl<N: ComplexField, D: Dim, S: Storage<N, D, D>> SquareMatrix<N, D, S> {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn xx_solve_lower_triangular_vector_mut<R2: Dim, S2>(
|
fn xx_solve_lower_triangular_vector_mut<R2: Dim, S2>(
|
||||||
&self,
|
&self,
|
||||||
b: &mut Vector<N, R2, S2>,
|
b: &mut Vector<N, R2, S2>,
|
||||||
conjugate: impl Fn(N) -> N,
|
conjugate: impl Fn(N) -> N,
|
||||||
dot: impl Fn(&DVectorSlice<N, S::RStride, S::CStride>, &DVectorSlice<N, S2::RStride, S2::CStride>) -> N,
|
dot: impl Fn(
|
||||||
|
&DVectorSlice<N, S::RStride, S::CStride>,
|
||||||
|
&DVectorSlice<N, S2::RStride, S2::CStride>,
|
||||||
|
) -> N,
|
||||||
) -> bool
|
) -> bool
|
||||||
where
|
where
|
||||||
S2: StorageMut<N, R2, U1>,
|
S2: StorageMut<N, R2, U1>,
|
||||||
ShapeConstraint: SameNumberOfRows<R2, D>,
|
ShapeConstraint: SameNumberOfRows<R2, D>,
|
||||||
{
|
{
|
||||||
let dim = self.nrows();
|
let dim = self.nrows();
|
||||||
|
|
||||||
|
@ -385,11 +403,14 @@ impl<N: ComplexField, D: Dim, S: Storage<N, D, D>> SquareMatrix<N, D, S> {
|
||||||
&self,
|
&self,
|
||||||
b: &mut Vector<N, R2, S2>,
|
b: &mut Vector<N, R2, S2>,
|
||||||
conjugate: impl Fn(N) -> N,
|
conjugate: impl Fn(N) -> N,
|
||||||
dot: impl Fn(&DVectorSlice<N, S::RStride, S::CStride>, &DVectorSlice<N, S2::RStride, S2::CStride>) -> N,
|
dot: impl Fn(
|
||||||
|
&DVectorSlice<N, S::RStride, S::CStride>,
|
||||||
|
&DVectorSlice<N, S2::RStride, S2::CStride>,
|
||||||
|
) -> N,
|
||||||
) -> bool
|
) -> bool
|
||||||
where
|
where
|
||||||
S2: StorageMut<N, R2, U1>,
|
S2: StorageMut<N, R2, U1>,
|
||||||
ShapeConstraint: SameNumberOfRows<R2, D>,
|
ShapeConstraint: SameNumberOfRows<R2, D>,
|
||||||
{
|
{
|
||||||
let dim = self.nrows();
|
let dim = self.nrows();
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
#[cfg(feature = "serde-serialize")]
|
#[cfg(feature = "serde-serialize")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use num::{Zero, One};
|
|
||||||
use approx::AbsDiffEq;
|
use approx::AbsDiffEq;
|
||||||
|
use num::{One, Zero};
|
||||||
|
|
||||||
use alga::general::{RealField, ComplexField};
|
|
||||||
use crate::allocator::Allocator;
|
use crate::allocator::Allocator;
|
||||||
use crate::base::{DefaultAllocator, Matrix, Matrix2x3, MatrixMN, Vector2, VectorN};
|
use crate::base::{DefaultAllocator, Matrix, Matrix2x3, MatrixMN, Vector2, VectorN};
|
||||||
use crate::constraint::{SameNumberOfRows, ShapeConstraint};
|
use crate::constraint::{SameNumberOfRows, ShapeConstraint};
|
||||||
use crate::dimension::{Dim, DimDiff, DimMin, DimMinimum, DimSub, U1, U2};
|
use crate::dimension::{Dim, DimDiff, DimMin, DimMinimum, DimSub, U1, U2};
|
||||||
use crate::storage::Storage;
|
use crate::storage::Storage;
|
||||||
|
use simba::scalar::{ComplexField, RealField};
|
||||||
|
|
||||||
|
use crate::linalg::givens::GivensRotation;
|
||||||
use crate::linalg::symmetric_eigen;
|
use crate::linalg::symmetric_eigen;
|
||||||
use crate::linalg::Bidiagonal;
|
use crate::linalg::Bidiagonal;
|
||||||
use crate::linalg::givens::GivensRotation;
|
|
||||||
|
|
||||||
/// Singular Value Decomposition of a general matrix.
|
/// Singular Value Decomposition of a general matrix.
|
||||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||||
|
@ -61,7 +61,8 @@ where
|
||||||
MatrixMN<N, R, DimMinimum<R, C>>: Copy,
|
MatrixMN<N, R, DimMinimum<R, C>>: Copy,
|
||||||
MatrixMN<N, DimMinimum<R, C>, C>: Copy,
|
MatrixMN<N, DimMinimum<R, C>, C>: Copy,
|
||||||
VectorN<N::RealField, DimMinimum<R, C>>: Copy,
|
VectorN<N::RealField, DimMinimum<R, C>>: Copy,
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
impl<N: ComplexField, R: DimMin<C>, C: Dim> SVD<N, R, C>
|
impl<N: ComplexField, R: DimMin<C>, C: Dim> SVD<N, R, C>
|
||||||
where
|
where
|
||||||
|
@ -78,7 +79,14 @@ where
|
||||||
{
|
{
|
||||||
/// Computes the Singular Value Decomposition of `matrix` using implicit shift.
|
/// Computes the Singular Value Decomposition of `matrix` using implicit shift.
|
||||||
pub fn new(matrix: MatrixMN<N, R, C>, compute_u: bool, compute_v: bool) -> Self {
|
pub fn new(matrix: MatrixMN<N, R, C>, compute_u: bool, compute_v: bool) -> Self {
|
||||||
Self::try_new(matrix, compute_u, compute_v, N::RealField::default_epsilon(), 0).unwrap()
|
Self::try_new(
|
||||||
|
matrix,
|
||||||
|
compute_u,
|
||||||
|
compute_v,
|
||||||
|
N::RealField::default_epsilon(),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to compute the Singular Value Decomposition of `matrix` using implicit shift.
|
/// Attempts to compute the Singular Value Decomposition of `matrix` using implicit shift.
|
||||||
|
@ -120,7 +128,15 @@ where
|
||||||
let mut off_diagonal = b.off_diagonal();
|
let mut off_diagonal = b.off_diagonal();
|
||||||
|
|
||||||
let mut niter = 0;
|
let mut niter = 0;
|
||||||
let (mut start, mut end) = Self::delimit_subproblem(&mut diagonal, &mut off_diagonal, &mut u, &mut v_t, b.is_upper_diagonal(), dim - 1, eps);
|
let (mut start, mut end) = Self::delimit_subproblem(
|
||||||
|
&mut diagonal,
|
||||||
|
&mut off_diagonal,
|
||||||
|
&mut u,
|
||||||
|
&mut v_t,
|
||||||
|
b.is_upper_diagonal(),
|
||||||
|
dim - 1,
|
||||||
|
eps,
|
||||||
|
);
|
||||||
|
|
||||||
while end != start {
|
while end != start {
|
||||||
let subdim = end - start + 1;
|
let subdim = end - start + 1;
|
||||||
|
@ -165,7 +181,8 @@ where
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some((rot1, norm1)) = GivensRotation::cancel_y(&vec) {
|
if let Some((rot1, norm1)) = GivensRotation::cancel_y(&vec) {
|
||||||
rot1.inverse().rotate_rows(&mut subm.fixed_columns_mut::<U2>(0));
|
rot1.inverse()
|
||||||
|
.rotate_rows(&mut subm.fixed_columns_mut::<U2>(0));
|
||||||
let rot1 = GivensRotation::new_unchecked(rot1.c(), N::from_real(rot1.s()));
|
let rot1 = GivensRotation::new_unchecked(rot1.c(), N::from_real(rot1.s()));
|
||||||
|
|
||||||
if k > start {
|
if k > start {
|
||||||
|
@ -175,8 +192,8 @@ where
|
||||||
|
|
||||||
let v = Vector2::new(subm[(0, 0)], subm[(1, 0)]);
|
let v = Vector2::new(subm[(0, 0)], subm[(1, 0)]);
|
||||||
// FIXME: does the case `v.y == 0` ever happen?
|
// FIXME: does the case `v.y == 0` ever happen?
|
||||||
let (rot2, norm2) =
|
let (rot2, norm2) = GivensRotation::cancel_y(&v)
|
||||||
GivensRotation::cancel_y(&v).unwrap_or((GivensRotation::identity(), subm[(0, 0)]));
|
.unwrap_or((GivensRotation::identity(), subm[(0, 0)]));
|
||||||
|
|
||||||
rot2.rotate(&mut subm.fixed_columns_mut::<U2>(1));
|
rot2.rotate(&mut subm.fixed_columns_mut::<U2>(1));
|
||||||
let rot2 = GivensRotation::new_unchecked(rot2.c(), N::from_real(rot2.s()));
|
let rot2 = GivensRotation::new_unchecked(rot2.c(), N::from_real(rot2.s()));
|
||||||
|
@ -253,7 +270,15 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-delimit the subproblem in case some decoupling occurred.
|
// Re-delimit the subproblem in case some decoupling occurred.
|
||||||
let sub = Self::delimit_subproblem(&mut diagonal, &mut off_diagonal, &mut u, &mut v_t, b.is_upper_diagonal(), end, eps);
|
let sub = Self::delimit_subproblem(
|
||||||
|
&mut diagonal,
|
||||||
|
&mut off_diagonal,
|
||||||
|
&mut u,
|
||||||
|
&mut v_t,
|
||||||
|
b.is_upper_diagonal(),
|
||||||
|
end,
|
||||||
|
eps,
|
||||||
|
);
|
||||||
start = sub.0;
|
start = sub.0;
|
||||||
end = sub.1;
|
end = sub.1;
|
||||||
|
|
||||||
|
@ -321,14 +346,36 @@ where
|
||||||
off_diagonal[m] = N::RealField::zero();
|
off_diagonal[m] = N::RealField::zero();
|
||||||
} else if diagonal[m].norm1() <= eps {
|
} else if diagonal[m].norm1() <= eps {
|
||||||
diagonal[m] = N::RealField::zero();
|
diagonal[m] = N::RealField::zero();
|
||||||
Self::cancel_horizontal_off_diagonal_elt(diagonal, off_diagonal, u, v_t, is_upper_diagonal, m, m + 1);
|
Self::cancel_horizontal_off_diagonal_elt(
|
||||||
|
diagonal,
|
||||||
|
off_diagonal,
|
||||||
|
u,
|
||||||
|
v_t,
|
||||||
|
is_upper_diagonal,
|
||||||
|
m,
|
||||||
|
m + 1,
|
||||||
|
);
|
||||||
|
|
||||||
if m != 0 {
|
if m != 0 {
|
||||||
Self::cancel_vertical_off_diagonal_elt(diagonal, off_diagonal, u, v_t, is_upper_diagonal, m - 1);
|
Self::cancel_vertical_off_diagonal_elt(
|
||||||
|
diagonal,
|
||||||
|
off_diagonal,
|
||||||
|
u,
|
||||||
|
v_t,
|
||||||
|
is_upper_diagonal,
|
||||||
|
m - 1,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else if diagonal[n].norm1() <= eps {
|
} else if diagonal[n].norm1() <= eps {
|
||||||
diagonal[n] = N::RealField::zero();
|
diagonal[n] = N::RealField::zero();
|
||||||
Self::cancel_vertical_off_diagonal_elt(diagonal, off_diagonal, u, v_t, is_upper_diagonal, m);
|
Self::cancel_vertical_off_diagonal_elt(
|
||||||
|
diagonal,
|
||||||
|
off_diagonal,
|
||||||
|
u,
|
||||||
|
v_t,
|
||||||
|
is_upper_diagonal,
|
||||||
|
m,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -352,10 +399,25 @@ where
|
||||||
// FIXME: write a test that enters this case.
|
// FIXME: write a test that enters this case.
|
||||||
else if diagonal[m].norm1() <= eps {
|
else if diagonal[m].norm1() <= eps {
|
||||||
diagonal[m] = N::RealField::zero();
|
diagonal[m] = N::RealField::zero();
|
||||||
Self::cancel_horizontal_off_diagonal_elt(diagonal, off_diagonal, u, v_t, is_upper_diagonal, m, n);
|
Self::cancel_horizontal_off_diagonal_elt(
|
||||||
|
diagonal,
|
||||||
|
off_diagonal,
|
||||||
|
u,
|
||||||
|
v_t,
|
||||||
|
is_upper_diagonal,
|
||||||
|
m,
|
||||||
|
n,
|
||||||
|
);
|
||||||
|
|
||||||
if m != 0 {
|
if m != 0 {
|
||||||
Self::cancel_vertical_off_diagonal_elt(diagonal, off_diagonal, u, v_t, is_upper_diagonal, m - 1);
|
Self::cancel_vertical_off_diagonal_elt(
|
||||||
|
diagonal,
|
||||||
|
off_diagonal,
|
||||||
|
u,
|
||||||
|
v_t,
|
||||||
|
is_upper_diagonal,
|
||||||
|
m - 1,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -469,7 +531,7 @@ where
|
||||||
}
|
}
|
||||||
(None, None) => Err("SVD recomposition: U and V^t have not been computed."),
|
(None, None) => Err("SVD recomposition: U and V^t have not been computed."),
|
||||||
(None, _) => Err("SVD recomposition: U has not been computed."),
|
(None, _) => Err("SVD recomposition: U has not been computed."),
|
||||||
(_, None) => Err("SVD recomposition: V^t has not been computed.")
|
(_, None) => Err("SVD recomposition: V^t has not been computed."),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -479,13 +541,10 @@ where
|
||||||
/// Returns `Err` if the right- and left- singular vectors have not
|
/// Returns `Err` if the right- and left- singular vectors have not
|
||||||
/// been computed at construction-time.
|
/// been computed at construction-time.
|
||||||
pub fn pseudo_inverse(mut self, eps: N::RealField) -> Result<MatrixMN<N, C, R>, &'static str>
|
pub fn pseudo_inverse(mut self, eps: N::RealField) -> Result<MatrixMN<N, C, R>, &'static str>
|
||||||
where
|
where DefaultAllocator: Allocator<N, C, R> {
|
||||||
DefaultAllocator: Allocator<N, C, R>,
|
|
||||||
{
|
|
||||||
if eps < N::RealField::zero() {
|
if eps < N::RealField::zero() {
|
||||||
Err("SVD pseudo inverse: the epsilon must be non-negative.")
|
Err("SVD pseudo inverse: the epsilon must be non-negative.")
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
for i in 0..self.singular_values.len() {
|
for i in 0..self.singular_values.len() {
|
||||||
let val = self.singular_values[i];
|
let val = self.singular_values[i];
|
||||||
|
|
||||||
|
@ -517,8 +576,7 @@ where
|
||||||
{
|
{
|
||||||
if eps < N::RealField::zero() {
|
if eps < N::RealField::zero() {
|
||||||
Err("SVD solve: the epsilon must be non-negative.")
|
Err("SVD solve: the epsilon must be non-negative.")
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
match (&self.u, &self.v_t) {
|
match (&self.u, &self.v_t) {
|
||||||
(Some(u), Some(v_t)) => {
|
(Some(u), Some(v_t)) => {
|
||||||
let mut ut_b = u.ad_mul(b);
|
let mut ut_b = u.ad_mul(b);
|
||||||
|
@ -540,7 +598,7 @@ where
|
||||||
}
|
}
|
||||||
(None, None) => Err("SVD solve: U and V^t have not been computed."),
|
(None, None) => Err("SVD solve: U and V^t have not been computed."),
|
||||||
(None, _) => Err("SVD solve: U has not been computed."),
|
(None, _) => Err("SVD solve: U has not been computed."),
|
||||||
(_, None) => Err("SVD solve: V^t has not been computed.")
|
(_, None) => Err("SVD solve: V^t has not been computed."),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -602,14 +660,11 @@ where
|
||||||
///
|
///
|
||||||
/// All singular values below `eps` are considered equal to 0.
|
/// All singular values below `eps` are considered equal to 0.
|
||||||
pub fn pseudo_inverse(self, eps: N::RealField) -> Result<MatrixMN<N, C, R>, &'static str>
|
pub fn pseudo_inverse(self, eps: N::RealField) -> Result<MatrixMN<N, C, R>, &'static str>
|
||||||
where
|
where DefaultAllocator: Allocator<N, C, R> {
|
||||||
DefaultAllocator: Allocator<N, C, R>,
|
|
||||||
{
|
|
||||||
SVD::new(self.clone_owned(), true, true).pseudo_inverse(eps)
|
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
|
// Explicit formulae inspired from the paper "Computing the Singular Values of 2-by-2 Complex
|
||||||
// Matrices", Sanzheng Qiao and Xiaohong Wang.
|
// Matrices", Sanzheng Qiao and Xiaohong Wang.
|
||||||
// http://www.cas.mcmaster.ca/sqrl/papers/sqrl5.pdf
|
// http://www.cas.mcmaster.ca/sqrl/papers/sqrl5.pdf
|
||||||
|
@ -619,7 +674,11 @@ fn compute_2x2_uptrig_svd<N: RealField>(
|
||||||
m22: N,
|
m22: N,
|
||||||
compute_u: bool,
|
compute_u: bool,
|
||||||
compute_v: bool,
|
compute_v: bool,
|
||||||
) -> (Option<GivensRotation<N>>, Vector2<N>, Option<GivensRotation<N>>)
|
) -> (
|
||||||
|
Option<GivensRotation<N>>,
|
||||||
|
Vector2<N>,
|
||||||
|
Option<GivensRotation<N>>,
|
||||||
|
)
|
||||||
{
|
{
|
||||||
let two: N::RealField = crate::convert(2.0f64);
|
let two: N::RealField = crate::convert(2.0f64);
|
||||||
let half: N::RealField = crate::convert(0.5f64);
|
let half: N::RealField = crate::convert(0.5f64);
|
||||||
|
@ -657,4 +716,4 @@ fn compute_2x2_uptrig_svd<N: RealField>(
|
||||||
}
|
}
|
||||||
|
|
||||||
(u, Vector2::new(v1, v2), v_t)
|
(u, Vector2::new(v1, v2), v_t)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
#[cfg(feature = "serde-serialize")]
|
#[cfg(feature = "serde-serialize")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use num::Zero;
|
|
||||||
use approx::AbsDiffEq;
|
use approx::AbsDiffEq;
|
||||||
|
use num::Zero;
|
||||||
|
|
||||||
use alga::general::ComplexField;
|
|
||||||
use crate::allocator::Allocator;
|
use crate::allocator::Allocator;
|
||||||
use crate::base::{DefaultAllocator, Matrix2, MatrixN, SquareMatrix, Vector2, VectorN};
|
use crate::base::{DefaultAllocator, Matrix2, MatrixN, SquareMatrix, Vector2, VectorN};
|
||||||
use crate::dimension::{Dim, DimDiff, DimSub, U1, U2};
|
use crate::dimension::{Dim, DimDiff, DimSub, U1, U2};
|
||||||
use crate::storage::Storage;
|
use crate::storage::Storage;
|
||||||
|
use simba::scalar::ComplexField;
|
||||||
|
|
||||||
use crate::linalg::givens::GivensRotation;
|
use crate::linalg::givens::GivensRotation;
|
||||||
use crate::linalg::SymmetricTridiagonal;
|
use crate::linalg::SymmetricTridiagonal;
|
||||||
|
@ -17,21 +17,17 @@ use crate::linalg::SymmetricTridiagonal;
|
||||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serde-serialize",
|
feature = "serde-serialize",
|
||||||
serde(bound(
|
serde(bound(serialize = "DefaultAllocator: Allocator<N, D, D> +
|
||||||
serialize = "DefaultAllocator: Allocator<N, D, D> +
|
|
||||||
Allocator<N::RealField, D>,
|
Allocator<N::RealField, D>,
|
||||||
VectorN<N::RealField, D>: Serialize,
|
VectorN<N::RealField, D>: Serialize,
|
||||||
MatrixN<N, D>: Serialize"
|
MatrixN<N, D>: Serialize"))
|
||||||
))
|
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serde-serialize",
|
feature = "serde-serialize",
|
||||||
serde(bound(
|
serde(bound(deserialize = "DefaultAllocator: Allocator<N, D, D> +
|
||||||
deserialize = "DefaultAllocator: Allocator<N, D, D> +
|
|
||||||
Allocator<N::RealField, D>,
|
Allocator<N::RealField, D>,
|
||||||
VectorN<N::RealField, D>: Deserialize<'de>,
|
VectorN<N::RealField, D>: Deserialize<'de>,
|
||||||
MatrixN<N, D>: Deserialize<'de>"
|
MatrixN<N, D>: Deserialize<'de>"))
|
||||||
))
|
|
||||||
)]
|
)]
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct SymmetricEigen<N: ComplexField, D: Dim>
|
pub struct SymmetricEigen<N: ComplexField, D: Dim>
|
||||||
|
@ -49,7 +45,8 @@ where
|
||||||
DefaultAllocator: Allocator<N, D, D> + Allocator<N::RealField, D>,
|
DefaultAllocator: Allocator<N, D, D> + Allocator<N::RealField, D>,
|
||||||
MatrixN<N, D>: Copy,
|
MatrixN<N, D>: Copy,
|
||||||
VectorN<N::RealField, D>: Copy,
|
VectorN<N::RealField, D>: Copy,
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
impl<N: ComplexField, D: Dim> SymmetricEigen<N, D>
|
impl<N: ComplexField, D: Dim> SymmetricEigen<N, D>
|
||||||
where DefaultAllocator: Allocator<N, D, D> + Allocator<N::RealField, D>
|
where DefaultAllocator: Allocator<N, D, D> + Allocator<N::RealField, D>
|
||||||
|
@ -60,8 +57,7 @@ where DefaultAllocator: Allocator<N, D, D> + Allocator<N::RealField, D>
|
||||||
pub fn new(m: MatrixN<N, D>) -> Self
|
pub fn new(m: MatrixN<N, D>) -> Self
|
||||||
where
|
where
|
||||||
D: DimSub<U1>,
|
D: DimSub<U1>,
|
||||||
DefaultAllocator: Allocator<N, DimDiff<D, U1>> + // For tridiagonalization
|
DefaultAllocator: Allocator<N, DimDiff<D, U1>> + Allocator<N::RealField, DimDiff<D, U1>>,
|
||||||
Allocator<N::RealField, DimDiff<D, U1>>,
|
|
||||||
{
|
{
|
||||||
Self::try_new(m, N::RealField::default_epsilon(), 0).unwrap()
|
Self::try_new(m, N::RealField::default_epsilon(), 0).unwrap()
|
||||||
}
|
}
|
||||||
|
@ -80,8 +76,7 @@ where DefaultAllocator: Allocator<N, D, D> + Allocator<N::RealField, D>
|
||||||
pub fn try_new(m: MatrixN<N, D>, eps: N::RealField, max_niter: usize) -> Option<Self>
|
pub fn try_new(m: MatrixN<N, D>, eps: N::RealField, max_niter: usize) -> Option<Self>
|
||||||
where
|
where
|
||||||
D: DimSub<U1>,
|
D: DimSub<U1>,
|
||||||
DefaultAllocator: Allocator<N, DimDiff<D, U1>> + // For tridiagonalization
|
DefaultAllocator: Allocator<N, DimDiff<D, U1>> + Allocator<N::RealField, DimDiff<D, U1>>,
|
||||||
Allocator<N::RealField, DimDiff<D, U1>>,
|
|
||||||
{
|
{
|
||||||
Self::do_decompose(m, true, eps, max_niter).map(|(vals, vecs)| SymmetricEigen {
|
Self::do_decompose(m, true, eps, max_niter).map(|(vals, vecs)| SymmetricEigen {
|
||||||
eigenvectors: vecs.unwrap(),
|
eigenvectors: vecs.unwrap(),
|
||||||
|
@ -97,8 +92,7 @@ where DefaultAllocator: Allocator<N, D, D> + Allocator<N::RealField, D>
|
||||||
) -> Option<(VectorN<N::RealField, D>, Option<MatrixN<N, D>>)>
|
) -> Option<(VectorN<N::RealField, D>, Option<MatrixN<N, D>>)>
|
||||||
where
|
where
|
||||||
D: DimSub<U1>,
|
D: DimSub<U1>,
|
||||||
DefaultAllocator: Allocator<N, DimDiff<D, U1>> + // For tridiagonalization
|
DefaultAllocator: Allocator<N, DimDiff<D, U1>> + Allocator<N::RealField, DimDiff<D, U1>>,
|
||||||
Allocator<N::RealField, DimDiff<D, U1>>,
|
|
||||||
{
|
{
|
||||||
assert!(
|
assert!(
|
||||||
m.is_square(),
|
m.is_square(),
|
||||||
|
@ -154,7 +148,6 @@ where DefaultAllocator: Allocator<N, D, D> + Allocator<N::RealField, D>
|
||||||
off_diag[i - 1] = norm;
|
off_diag[i - 1] = norm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let mii = diag[i];
|
let mii = diag[i];
|
||||||
let mjj = diag[j];
|
let mjj = diag[j];
|
||||||
let mij = off_diag[i];
|
let mij = off_diag[i];
|
||||||
|
@ -189,8 +182,10 @@ where DefaultAllocator: Allocator<N, D, D> + Allocator<N::RealField, D>
|
||||||
}
|
}
|
||||||
} else if subdim == 2 {
|
} else if subdim == 2 {
|
||||||
let m = Matrix2::new(
|
let m = Matrix2::new(
|
||||||
diag[start], off_diag[start].conjugate(),
|
diag[start],
|
||||||
off_diag[start], diag[start + 1],
|
off_diag[start].conjugate(),
|
||||||
|
off_diag[start],
|
||||||
|
diag[start + 1],
|
||||||
);
|
);
|
||||||
let eigvals = m.eigenvalues().unwrap();
|
let eigvals = m.eigenvalues().unwrap();
|
||||||
let basis = Vector2::new(eigvals.x - diag[start + 1], off_diag[start]);
|
let basis = Vector2::new(eigvals.x - diag[start + 1], off_diag[start]);
|
||||||
|
@ -305,8 +300,10 @@ pub fn wilkinson_shift<N: ComplexField>(tmm: N, tnn: N, tmn: N) -> N {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
impl<N: ComplexField, D: DimSub<U1>, S: Storage<N, D, D>> SquareMatrix<N, D, S>
|
impl<N: ComplexField, D: DimSub<U1>, S: Storage<N, D, D>> SquareMatrix<N, D, S>
|
||||||
where DefaultAllocator: Allocator<N, D, D> + Allocator<N, DimDiff<D, U1>> +
|
where DefaultAllocator: Allocator<N, D, D>
|
||||||
Allocator<N::RealField, D> + Allocator<N::RealField, DimDiff<D, U1>>
|
+ Allocator<N, DimDiff<D, U1>>
|
||||||
|
+ Allocator<N::RealField, D>
|
||||||
|
+ Allocator<N::RealField, DimDiff<D, U1>>
|
||||||
{
|
{
|
||||||
/// Computes the eigendecomposition of this symmetric matrix.
|
/// Computes the eigendecomposition of this symmetric matrix.
|
||||||
///
|
///
|
||||||
|
@ -326,7 +323,12 @@ where DefaultAllocator: Allocator<N, D, D> + Allocator<N, DimDiff<D, U1>> +
|
||||||
/// * `max_niter` − maximum total number of iterations performed by the algorithm. If this
|
/// * `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
|
/// number of iteration is exceeded, `None` is returned. If `niter == 0`, then the algorithm
|
||||||
/// continues indefinitely until convergence.
|
/// continues indefinitely until convergence.
|
||||||
pub fn try_symmetric_eigen(self, eps: N::RealField, max_niter: usize) -> Option<SymmetricEigen<N, D>> {
|
pub fn try_symmetric_eigen(
|
||||||
|
self,
|
||||||
|
eps: N::RealField,
|
||||||
|
max_niter: usize,
|
||||||
|
) -> Option<SymmetricEigen<N, D>>
|
||||||
|
{
|
||||||
SymmetricEigen::try_new(self.into_owned(), eps, max_niter)
|
SymmetricEigen::try_new(self.into_owned(), eps, max_niter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,9 +336,14 @@ where DefaultAllocator: Allocator<N, D, D> + Allocator<N, DimDiff<D, U1>> +
|
||||||
///
|
///
|
||||||
/// Only the lower-triangular part of the matrix is read.
|
/// Only the lower-triangular part of the matrix is read.
|
||||||
pub fn symmetric_eigenvalues(&self) -> VectorN<N::RealField, D> {
|
pub fn symmetric_eigenvalues(&self) -> VectorN<N::RealField, D> {
|
||||||
SymmetricEigen::do_decompose(self.clone_owned(), false, N::RealField::default_epsilon(), 0)
|
SymmetricEigen::do_decompose(
|
||||||
.unwrap()
|
self.clone_owned(),
|
||||||
.0
|
false,
|
||||||
|
N::RealField::default_epsilon(),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
#[cfg(feature = "serde-serialize")]
|
#[cfg(feature = "serde-serialize")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use alga::general::ComplexField;
|
|
||||||
use crate::allocator::Allocator;
|
use crate::allocator::Allocator;
|
||||||
use crate::base::{DefaultAllocator, MatrixMN, MatrixN, SquareMatrix, VectorN};
|
use crate::base::{DefaultAllocator, MatrixMN, MatrixN, SquareMatrix, VectorN};
|
||||||
use crate::dimension::{DimDiff, DimSub, U1};
|
use crate::dimension::{DimDiff, DimSub, U1};
|
||||||
use crate::storage::Storage;
|
use crate::storage::Storage;
|
||||||
|
use simba::scalar::ComplexField;
|
||||||
|
|
||||||
use crate::linalg::householder;
|
use crate::linalg::householder;
|
||||||
|
|
||||||
|
@ -13,21 +13,17 @@ use crate::linalg::householder;
|
||||||
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serde-serialize",
|
feature = "serde-serialize",
|
||||||
serde(bound(
|
serde(bound(serialize = "DefaultAllocator: Allocator<N, D, D> +
|
||||||
serialize = "DefaultAllocator: Allocator<N, D, D> +
|
|
||||||
Allocator<N, DimDiff<D, U1>>,
|
Allocator<N, DimDiff<D, U1>>,
|
||||||
MatrixN<N, D>: Serialize,
|
MatrixN<N, D>: Serialize,
|
||||||
VectorN<N, DimDiff<D, U1>>: Serialize"
|
VectorN<N, DimDiff<D, U1>>: Serialize"))
|
||||||
))
|
|
||||||
)]
|
)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "serde-serialize",
|
feature = "serde-serialize",
|
||||||
serde(bound(
|
serde(bound(deserialize = "DefaultAllocator: Allocator<N, D, D> +
|
||||||
deserialize = "DefaultAllocator: Allocator<N, D, D> +
|
|
||||||
Allocator<N, DimDiff<D, U1>>,
|
Allocator<N, DimDiff<D, U1>>,
|
||||||
MatrixN<N, D>: Deserialize<'de>,
|
MatrixN<N, D>: Deserialize<'de>,
|
||||||
VectorN<N, DimDiff<D, U1>>: Deserialize<'de>"
|
VectorN<N, DimDiff<D, U1>>: Deserialize<'de>"))
|
||||||
))
|
|
||||||
)]
|
)]
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct SymmetricTridiagonal<N: ComplexField, D: DimSub<U1>>
|
pub struct SymmetricTridiagonal<N: ComplexField, D: DimSub<U1>>
|
||||||
|
@ -42,7 +38,8 @@ where
|
||||||
DefaultAllocator: Allocator<N, D, D> + Allocator<N, DimDiff<D, U1>>,
|
DefaultAllocator: Allocator<N, D, D> + Allocator<N, DimDiff<D, U1>>,
|
||||||
MatrixN<N, D>: Copy,
|
MatrixN<N, D>: Copy,
|
||||||
VectorN<N, DimDiff<D, U1>>: Copy,
|
VectorN<N, DimDiff<D, U1>>: Copy,
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
impl<N: ComplexField, D: DimSub<U1>> SymmetricTridiagonal<N, D>
|
impl<N: ComplexField, D: DimSub<U1>> SymmetricTridiagonal<N, D>
|
||||||
where DefaultAllocator: Allocator<N, D, D> + Allocator<N, DimDiff<D, U1>>
|
where DefaultAllocator: Allocator<N, D, D> + Allocator<N, DimDiff<D, U1>>
|
||||||
|
@ -98,9 +95,15 @@ where DefaultAllocator: Allocator<N, D, D> + Allocator<N, DimDiff<D, U1>>
|
||||||
|
|
||||||
/// Retrieve the orthogonal transformation, diagonal, and off diagonal elements of this
|
/// Retrieve the orthogonal transformation, diagonal, and off diagonal elements of this
|
||||||
/// decomposition.
|
/// decomposition.
|
||||||
pub fn unpack(self) -> (MatrixN<N, D>, VectorN<N::RealField, D>, VectorN<N::RealField, DimDiff<D, U1>>)
|
pub fn unpack(
|
||||||
where DefaultAllocator: Allocator<N::RealField, D>
|
self,
|
||||||
+ Allocator<N::RealField, DimDiff<D, U1>> {
|
) -> (
|
||||||
|
MatrixN<N, D>,
|
||||||
|
VectorN<N::RealField, D>,
|
||||||
|
VectorN<N::RealField, DimDiff<D, U1>>,
|
||||||
|
)
|
||||||
|
where DefaultAllocator: Allocator<N::RealField, D> + Allocator<N::RealField, DimDiff<D, U1>>
|
||||||
|
{
|
||||||
let diag = self.diagonal();
|
let diag = self.diagonal();
|
||||||
let q = self.q();
|
let q = self.q();
|
||||||
|
|
||||||
|
@ -108,15 +111,22 @@ where DefaultAllocator: Allocator<N, D, D> + Allocator<N, DimDiff<D, U1>>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve the diagonal, and off diagonal elements of this decomposition.
|
/// Retrieve the diagonal, and off diagonal elements of this decomposition.
|
||||||
pub fn unpack_tridiagonal(self) -> (VectorN<N::RealField, D>, VectorN<N::RealField, DimDiff<D, U1>>)
|
pub fn unpack_tridiagonal(
|
||||||
where DefaultAllocator: Allocator<N::RealField, D>
|
self,
|
||||||
+ Allocator<N::RealField, DimDiff<D, U1>> {
|
) -> (
|
||||||
|
VectorN<N::RealField, D>,
|
||||||
|
VectorN<N::RealField, DimDiff<D, U1>>,
|
||||||
|
)
|
||||||
|
where DefaultAllocator: Allocator<N::RealField, D> + Allocator<N::RealField, DimDiff<D, U1>>
|
||||||
|
{
|
||||||
(self.diagonal(), self.off_diagonal.map(N::modulus))
|
(self.diagonal(), self.off_diagonal.map(N::modulus))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The diagonal components of this decomposition.
|
/// The diagonal components of this decomposition.
|
||||||
pub fn diagonal(&self) -> VectorN<N::RealField, D>
|
pub fn diagonal(&self) -> VectorN<N::RealField, D>
|
||||||
where DefaultAllocator: Allocator<N::RealField, D> { self.tri.map_diagonal(|e| e.real()) }
|
where DefaultAllocator: Allocator<N::RealField, D> {
|
||||||
|
self.tri.map_diagonal(|e| e.real())
|
||||||
|
}
|
||||||
|
|
||||||
/// The off-diagonal components of this decomposition.
|
/// The off-diagonal components of this decomposition.
|
||||||
pub fn off_diagonal(&self) -> VectorN<N::RealField, DimDiff<D, U1>>
|
pub fn off_diagonal(&self) -> VectorN<N::RealField, DimDiff<D, U1>>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use alga::general::ClosedAdd;
|
|
||||||
use num::Zero;
|
use num::Zero;
|
||||||
|
use simba::scalar::ClosedAdd;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
@ -7,9 +7,7 @@ use std::slice;
|
||||||
|
|
||||||
use crate::allocator::Allocator;
|
use crate::allocator::Allocator;
|
||||||
use crate::sparse::cs_utils;
|
use crate::sparse::cs_utils;
|
||||||
use crate::{
|
use crate::{DefaultAllocator, Dim, Dynamic, Scalar, Vector, VectorN, U1};
|
||||||
DefaultAllocator, Dim, Dynamic, Scalar, Vector, VectorN, U1
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct ColumnEntries<'a, N> {
|
pub struct ColumnEntries<'a, N> {
|
||||||
curr: usize,
|
curr: usize,
|
||||||
|
@ -33,9 +31,11 @@ impl<'a, N: Clone> Iterator for ColumnEntries<'a, N> {
|
||||||
if self.curr >= self.i.len() {
|
if self.curr >= self.i.len() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let res = Some((unsafe { self.i.get_unchecked(self.curr).clone() }, unsafe {
|
let res = Some(
|
||||||
self.v.get_unchecked(self.curr).clone()
|
(unsafe { self.i.get_unchecked(self.curr).clone() }, unsafe {
|
||||||
}));
|
self.v.get_unchecked(self.curr).clone()
|
||||||
|
}),
|
||||||
|
);
|
||||||
self.curr += 1;
|
self.curr += 1;
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use alga::general::ClosedAdd;
|
|
||||||
use num::Zero;
|
use num::Zero;
|
||||||
|
use simba::scalar::ClosedAdd;
|
||||||
|
|
||||||
use crate::allocator::Allocator;
|
use crate::allocator::Allocator;
|
||||||
use crate::sparse::cs_utils;
|
use crate::sparse::cs_utils;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use alga::general::{ClosedAdd, ClosedMul};
|
|
||||||
use num::{One, Zero};
|
use num::{One, Zero};
|
||||||
|
use simba::scalar::{ClosedAdd, ClosedMul};
|
||||||
use std::ops::{Add, Mul};
|
use std::ops::{Add, Mul};
|
||||||
|
|
||||||
use crate::allocator::Allocator;
|
use crate::allocator::Allocator;
|
||||||
|
@ -112,11 +112,11 @@ impl<N: Scalar + Zero + ClosedAdd + ClosedMul, D: Dim, S: StorageMut<N, D>> Vect
|
||||||
let col2 = a.column(0);
|
let col2 = a.column(0);
|
||||||
let val = unsafe { *x.vget_unchecked(0) };
|
let val = unsafe { *x.vget_unchecked(0) };
|
||||||
self.axpy_sparse(alpha * val, &col2, beta);
|
self.axpy_sparse(alpha * val, &col2, beta);
|
||||||
|
|
||||||
for j in 1..ncols2 {
|
for j in 1..ncols2 {
|
||||||
let col2 = a.column(j);
|
let col2 = a.column(j);
|
||||||
let val = unsafe { *x.vget_unchecked(j) };
|
let val = unsafe { *x.vget_unchecked(j) };
|
||||||
|
|
||||||
self.axpy_sparse(alpha * val, &col2, N::one());
|
self.axpy_sparse(alpha * val, &col2, N::one());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue