Move all matrix decomposition methods under a single impl.
This commit is contained in:
parent
4f443b06a9
commit
45f2fc4f92
|
@ -75,6 +75,21 @@ pub type MatrixCross<N, R1, C1, R2, C2> =
|
||||||
/// Note that mixing `Dynamic` with type-level unsigned integers is allowed. Actually, a
|
/// Note that mixing `Dynamic` with type-level unsigned integers is allowed. Actually, a
|
||||||
/// dynamically-sized column vector should be represented as a `Matrix<N, Dynamic, U1, S>` (given
|
/// dynamically-sized column vector should be represented as a `Matrix<N, Dynamic, U1, S>` (given
|
||||||
/// some concrete types for `N` and a compatible data storage type `S`).
|
/// some concrete types for `N` and a compatible data storage type `S`).
|
||||||
|
///
|
||||||
|
/// # Documentation by feature
|
||||||
|
/// Because `Matrix` is the most generic types that groups all matrix and vectors of **nalgebra**
|
||||||
|
/// this documentation page contains every single matrix/vector-related method. In order to make
|
||||||
|
/// browsing this page simpler, the next subsections contain direct links to groups of methods
|
||||||
|
/// related to a specific topic.
|
||||||
|
///
|
||||||
|
/// #### Matrix decomposition
|
||||||
|
/// - [Rectangular matrix decomposition](#rectangular-matrix-decomposition).
|
||||||
|
/// - [Square matrix decomposition](#square-matrix-decomposition).
|
||||||
|
///
|
||||||
|
/// #### Matrix slicing
|
||||||
|
/// - [Slicing](#slicing)
|
||||||
|
/// - [Mutable slicing](#mutable-slicing)
|
||||||
|
/// - [Range-based slicing](#range-based-slicing), [mutable range-based slicing](#mutable-range-based-slicing).
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct Matrix<N: Scalar, R: Dim, C: Dim, S> {
|
pub struct Matrix<N: Scalar, R: Dim, C: Dim, S> {
|
||||||
|
|
|
@ -40,7 +40,7 @@ where
|
||||||
+ Allocator<N, DimMinimum<R, C>>
|
+ Allocator<N, DimMinimum<R, C>>
|
||||||
+ Allocator<N, DimDiff<DimMinimum<R, C>, U1>>,
|
+ Allocator<N, DimDiff<DimMinimum<R, C>, U1>>,
|
||||||
{
|
{
|
||||||
// FIXME: perhaps we should pack the axises into different vectors so that axises for `v_t` are
|
// FIXME: perhaps we should pack the axes into different vectors so that axes for `v_t` are
|
||||||
// contiguous. This prevents some useless copies.
|
// contiguous. This prevents some useless copies.
|
||||||
uv: MatrixMN<N, R, C>,
|
uv: MatrixMN<N, R, C>,
|
||||||
/// The diagonal elements of the decomposed matrix.
|
/// The diagonal elements of the decomposed matrix.
|
||||||
|
@ -359,18 +359,3 @@ where
|
||||||
// // res self.q_determinant()
|
// // res self.q_determinant()
|
||||||
// // }
|
// // }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
impl<N: ComplexField, R: DimMin<C>, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S>
|
|
||||||
where
|
|
||||||
DimMinimum<R, C>: DimSub<U1>,
|
|
||||||
DefaultAllocator: Allocator<N, R, C>
|
|
||||||
+ Allocator<N, C>
|
|
||||||
+ Allocator<N, R>
|
|
||||||
+ Allocator<N, DimMinimum<R, C>>
|
|
||||||
+ Allocator<N, DimDiff<DimMinimum<R, C>, U1>>,
|
|
||||||
{
|
|
||||||
/// Computes the bidiagonalization using householder reflections.
|
|
||||||
pub fn bidiagonalize(self) -> Bidiagonal<N, R, C> {
|
|
||||||
Bidiagonal::new(self.into_owned())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ use simba::scalar::ComplexField;
|
||||||
use simba::simd::SimdComplexField;
|
use simba::simd::SimdComplexField;
|
||||||
|
|
||||||
use crate::allocator::Allocator;
|
use crate::allocator::Allocator;
|
||||||
use crate::base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, SquareMatrix, Vector};
|
use crate::base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, Vector};
|
||||||
use crate::constraint::{SameNumberOfRows, ShapeConstraint};
|
use crate::constraint::{SameNumberOfRows, ShapeConstraint};
|
||||||
use crate::dimension::{Dim, DimAdd, DimDiff, DimSub, DimSum, U1};
|
use crate::dimension::{Dim, DimAdd, DimDiff, DimSub, DimSum, U1};
|
||||||
use crate::storage::{Storage, StorageMut};
|
use crate::storage::{Storage, StorageMut};
|
||||||
|
@ -363,16 +363,3 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: ComplexField, D: Dim, S: Storage<N, D, D>> SquareMatrix<N, D, S>
|
|
||||||
where
|
|
||||||
DefaultAllocator: Allocator<N, D, D>,
|
|
||||||
{
|
|
||||||
/// Attempts to compute the Cholesky decomposition of this matrix.
|
|
||||||
///
|
|
||||||
/// Returns `None` if the input matrix is not definite-positive. The input matrix is assumed
|
|
||||||
/// to be symmetric and only the lower-triangular part is read.
|
|
||||||
pub fn cholesky(self) -> Option<Cholesky<N, D>> {
|
|
||||||
Cholesky::new(self.into_owned())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,232 @@
|
||||||
|
use crate::storage::Storage;
|
||||||
|
use crate::{
|
||||||
|
Allocator, Bidiagonal, Cholesky, ComplexField, DefaultAllocator, Dim, DimDiff, DimMin,
|
||||||
|
DimMinimum, DimSub, FullPivLU, Hessenberg, Matrix, Schur, SymmetricEigen, SymmetricTridiagonal,
|
||||||
|
LU, QR, SVD, U1,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// # Rectangular matrix decomposition
|
||||||
|
///
|
||||||
|
/// This section contains the methods for computing some common decompositions of rectangular
|
||||||
|
/// matrices with real or complex components. The following are currently supported:
|
||||||
|
///
|
||||||
|
/// | Decomposition | Factors | Details |
|
||||||
|
/// | -------------------------|---------------------|--------------|
|
||||||
|
/// | QR | `Q * R` | `Q` is an unitary matrix, and `R` is upper-triangular. |
|
||||||
|
/// | LU with partial pivoting | `P⁻¹ * L * U` | `L` is lower-triangular with a diagonal filled with `1` and `U` is upper-triangular. `P` is a permutation matrix. |
|
||||||
|
/// | LU with full pivoting | `P⁻¹ * L * U ~ Q⁻¹` | `L` is lower-triangular with a diagonal filled with `1` and `U` is upper-triangular. `P` and `Q` are permutation matrices. |
|
||||||
|
/// | SVD | `U * Σ * Vᵀ` | `U` and `V` are two orthogonal matrices and `Σ` is a diagonal matrix containing the singular values. |
|
||||||
|
impl<N: ComplexField, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
|
||||||
|
/// Computes the bidiagonalization using householder reflections.
|
||||||
|
pub fn bidiagonalize(self) -> Bidiagonal<N, R, C>
|
||||||
|
where
|
||||||
|
R: DimMin<C>,
|
||||||
|
DimMinimum<R, C>: DimSub<U1>,
|
||||||
|
DefaultAllocator: Allocator<N, R, C>
|
||||||
|
+ Allocator<N, C>
|
||||||
|
+ Allocator<N, R>
|
||||||
|
+ Allocator<N, DimMinimum<R, C>>
|
||||||
|
+ Allocator<N, DimDiff<DimMinimum<R, C>, U1>>,
|
||||||
|
{
|
||||||
|
Bidiagonal::new(self.into_owned())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes the LU decomposition with full pivoting of `matrix`.
|
||||||
|
///
|
||||||
|
/// This effectively computes `P, L, U, Q` such that `P * matrix * Q = LU`.
|
||||||
|
pub fn full_piv_lu(self) -> FullPivLU<N, R, C>
|
||||||
|
where
|
||||||
|
R: DimMin<C>,
|
||||||
|
DefaultAllocator: Allocator<N, R, C> + Allocator<(usize, usize), DimMinimum<R, C>>,
|
||||||
|
{
|
||||||
|
FullPivLU::new(self.into_owned())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes the LU decomposition with partial (row) pivoting of `matrix`.
|
||||||
|
pub fn lu(self) -> LU<N, R, C>
|
||||||
|
where
|
||||||
|
R: DimMin<C>,
|
||||||
|
DefaultAllocator: Allocator<N, R, C> + Allocator<(usize, usize), DimMinimum<R, C>>,
|
||||||
|
{
|
||||||
|
LU::new(self.into_owned())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes the QR decomposition of this matrix.
|
||||||
|
pub fn qr(self) -> QR<N, R, C>
|
||||||
|
where
|
||||||
|
R: DimMin<C>,
|
||||||
|
DefaultAllocator: Allocator<N, R, C> + Allocator<N, R> + Allocator<N, DimMinimum<R, C>>,
|
||||||
|
{
|
||||||
|
QR::new(self.into_owned())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes the Singular Value Decomposition using implicit shift.
|
||||||
|
pub fn svd(self, compute_u: bool, compute_v: bool) -> SVD<N, R, C>
|
||||||
|
where
|
||||||
|
R: DimMin<C>,
|
||||||
|
DimMinimum<R, C>: DimSub<U1>, // for Bidiagonal.
|
||||||
|
DefaultAllocator: Allocator<N, R, C>
|
||||||
|
+ Allocator<N, C>
|
||||||
|
+ Allocator<N, R>
|
||||||
|
+ Allocator<N, DimDiff<DimMinimum<R, C>, U1>>
|
||||||
|
+ Allocator<N, DimMinimum<R, C>, C>
|
||||||
|
+ Allocator<N, R, DimMinimum<R, C>>
|
||||||
|
+ Allocator<N, DimMinimum<R, C>>
|
||||||
|
+ Allocator<N::RealField, DimMinimum<R, C>>
|
||||||
|
+ Allocator<N::RealField, DimDiff<DimMinimum<R, C>, U1>>,
|
||||||
|
{
|
||||||
|
SVD::new(self.into_owned(), compute_u, compute_v)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Attempts to compute the Singular Value Decomposition of `matrix` using implicit shift.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `compute_u` − set this to `true` to enable the computation of left-singular vectors.
|
||||||
|
/// * `compute_v` − set this to `true` to enable the computation of right-singular vectors.
|
||||||
|
/// * `eps` − tolerance used to determine when a value converged to 0.
|
||||||
|
/// * `max_niter` − maximum total number of iterations performed by the algorithm. If this
|
||||||
|
/// number of iteration is exceeded, `None` is returned. If `niter == 0`, then the algorithm
|
||||||
|
/// continues indefinitely until convergence.
|
||||||
|
pub fn try_svd(
|
||||||
|
self,
|
||||||
|
compute_u: bool,
|
||||||
|
compute_v: bool,
|
||||||
|
eps: N::RealField,
|
||||||
|
max_niter: usize,
|
||||||
|
) -> Option<SVD<N, R, C>>
|
||||||
|
where
|
||||||
|
R: DimMin<C>,
|
||||||
|
DimMinimum<R, C>: DimSub<U1>, // for Bidiagonal.
|
||||||
|
DefaultAllocator: Allocator<N, R, C>
|
||||||
|
+ Allocator<N, C>
|
||||||
|
+ Allocator<N, R>
|
||||||
|
+ Allocator<N, DimDiff<DimMinimum<R, C>, U1>>
|
||||||
|
+ Allocator<N, DimMinimum<R, C>, C>
|
||||||
|
+ Allocator<N, R, DimMinimum<R, C>>
|
||||||
|
+ Allocator<N, DimMinimum<R, C>>
|
||||||
|
+ Allocator<N::RealField, DimMinimum<R, C>>
|
||||||
|
+ Allocator<N::RealField, DimDiff<DimMinimum<R, C>, U1>>,
|
||||||
|
{
|
||||||
|
SVD::try_new(self.into_owned(), compute_u, compute_v, eps, max_niter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// # Square matrix decomposition
|
||||||
|
///
|
||||||
|
/// This section contains the methods for computing some common decompositions of square
|
||||||
|
/// matrices with real or complex components. The following are currently supported:
|
||||||
|
///
|
||||||
|
/// | Decomposition | Factors | Details |
|
||||||
|
/// | -------------------------|---------------------------|--------------|
|
||||||
|
/// | Hessenberg | `Q * H * Qᵀ` | `Q` is a unitary matrix and `H` an upper-Hessenberg matrix. |
|
||||||
|
/// | Cholesky | `L * Lᵀ` | `L` is a lower-triangular matrix. |
|
||||||
|
/// | Schur decomposition | `Q * T * Qᵀ` | `Q` is an unitary matrix and `T` a quasi-upper-triangular matrix. |
|
||||||
|
/// | Symmetric eigendecomposition | `Q ~ Λ ~ Qᵀ` | `Q` is an unitary matrix, and `Λ` is a real diagonal matrix. |
|
||||||
|
/// | Symmetric tridiagonalization | `Q ~ T ~ Qᵀ` | `Q` is an unitary matrix, and `T` is a tridiagonal matrix. |
|
||||||
|
impl<N: ComplexField, D: Dim, S: Storage<N, D, D>> Matrix<N, D, D, S> {
|
||||||
|
/// Attempts to compute the Cholesky decomposition of this matrix.
|
||||||
|
///
|
||||||
|
/// Returns `None` if the input matrix is not definite-positive. The input matrix is assumed
|
||||||
|
/// to be symmetric and only the lower-triangular part is read.
|
||||||
|
pub fn cholesky(self) -> Option<Cholesky<N, D>>
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<N, D, D>,
|
||||||
|
{
|
||||||
|
Cholesky::new(self.into_owned())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes the Hessenberg decomposition of this matrix using householder reflections.
|
||||||
|
pub fn hessenberg(self) -> Hessenberg<N, D>
|
||||||
|
where
|
||||||
|
D: DimSub<U1>,
|
||||||
|
DefaultAllocator: Allocator<N, D, D> + Allocator<N, D> + Allocator<N, DimDiff<D, U1>>,
|
||||||
|
{
|
||||||
|
Hessenberg::new(self.into_owned())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes the Schur decomposition of a square matrix.
|
||||||
|
pub fn schur(self) -> Schur<N, D>
|
||||||
|
where
|
||||||
|
D: DimSub<U1>, // For Hessenberg.
|
||||||
|
DefaultAllocator: Allocator<N, D, DimDiff<D, U1>>
|
||||||
|
+ Allocator<N, DimDiff<D, U1>>
|
||||||
|
+ Allocator<N, D, D>
|
||||||
|
+ Allocator<N, D>,
|
||||||
|
{
|
||||||
|
Schur::new(self.into_owned())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Attempts to compute the Schur decomposition of a square matrix.
|
||||||
|
///
|
||||||
|
/// If only eigenvalues are needed, it is more efficient to call the matrix method
|
||||||
|
/// `.eigenvalues()` instead.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `eps` − tolerance used to determine when a value converged to 0.
|
||||||
|
/// * `max_niter` − maximum total number of iterations performed by the algorithm. If this
|
||||||
|
/// number of iteration is exceeded, `None` is returned. If `niter == 0`, then the algorithm
|
||||||
|
/// continues indefinitely until convergence.
|
||||||
|
pub fn try_schur(self, eps: N::RealField, max_niter: usize) -> Option<Schur<N, D>>
|
||||||
|
where
|
||||||
|
D: DimSub<U1>, // For Hessenberg.
|
||||||
|
DefaultAllocator: Allocator<N, D, DimDiff<D, U1>>
|
||||||
|
+ Allocator<N, DimDiff<D, U1>>
|
||||||
|
+ Allocator<N, D, D>
|
||||||
|
+ Allocator<N, D>,
|
||||||
|
{
|
||||||
|
Schur::try_new(self.into_owned(), eps, max_niter)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes the eigendecomposition of this symmetric matrix.
|
||||||
|
///
|
||||||
|
/// Only the lower-triangular part (including the diagonal) of `m` is read.
|
||||||
|
pub fn symmetric_eigen(self) -> SymmetricEigen<N, D>
|
||||||
|
where
|
||||||
|
D: DimSub<U1>,
|
||||||
|
DefaultAllocator: Allocator<N, D, D>
|
||||||
|
+ Allocator<N, DimDiff<D, U1>>
|
||||||
|
+ Allocator<N::RealField, D>
|
||||||
|
+ Allocator<N::RealField, DimDiff<D, U1>>,
|
||||||
|
{
|
||||||
|
SymmetricEigen::new(self.into_owned())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes the eigendecomposition of the given symmetric matrix with user-specified
|
||||||
|
/// convergence parameters.
|
||||||
|
///
|
||||||
|
/// Only the lower-triangular part (including the diagonal) of `m` is read.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `eps` − tolerance used to determine when a value converged to 0.
|
||||||
|
/// * `max_niter` − maximum total number of iterations performed by the algorithm. If this
|
||||||
|
/// number of iteration is exceeded, `None` is returned. If `niter == 0`, then the algorithm
|
||||||
|
/// continues indefinitely until convergence.
|
||||||
|
pub fn try_symmetric_eigen(
|
||||||
|
self,
|
||||||
|
eps: N::RealField,
|
||||||
|
max_niter: usize,
|
||||||
|
) -> Option<SymmetricEigen<N, D>>
|
||||||
|
where
|
||||||
|
D: DimSub<U1>,
|
||||||
|
DefaultAllocator: Allocator<N, D, D>
|
||||||
|
+ Allocator<N, DimDiff<D, U1>>
|
||||||
|
+ Allocator<N::RealField, D>
|
||||||
|
+ Allocator<N::RealField, DimDiff<D, U1>>,
|
||||||
|
{
|
||||||
|
SymmetricEigen::try_new(self.into_owned(), eps, max_niter)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Computes the tridiagonalization of this symmetric matrix.
|
||||||
|
///
|
||||||
|
/// Only the lower-triangular part (including the diagonal) of `m` is read.
|
||||||
|
pub fn symmetric_tridiagonalize(self) -> SymmetricTridiagonal<N, D>
|
||||||
|
where
|
||||||
|
D: DimSub<U1>,
|
||||||
|
DefaultAllocator: Allocator<N, D, D> + Allocator<N, DimDiff<D, U1>>,
|
||||||
|
{
|
||||||
|
SymmetricTridiagonal::new(self.into_owned())
|
||||||
|
}
|
||||||
|
}
|
|
@ -257,15 +257,3 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: ComplexField, R: DimMin<C>, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S>
|
|
||||||
where
|
|
||||||
DefaultAllocator: Allocator<N, R, C> + Allocator<(usize, usize), DimMinimum<R, C>>,
|
|
||||||
{
|
|
||||||
/// Computes the LU decomposition with full pivoting of `matrix`.
|
|
||||||
///
|
|
||||||
/// This effectively computes `P, L, U, Q` such that `P * matrix * Q = LU`.
|
|
||||||
pub fn full_piv_lu(self) -> FullPivLU<N, R, C> {
|
|
||||||
FullPivLU::new(self.into_owned())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::allocator::Allocator;
|
use crate::allocator::Allocator;
|
||||||
use crate::base::{DefaultAllocator, MatrixMN, MatrixN, SquareMatrix, VectorN};
|
use crate::base::{DefaultAllocator, MatrixMN, MatrixN, 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 simba::scalar::ComplexField;
|
||||||
|
@ -131,13 +131,3 @@ where
|
||||||
&self.hess
|
&self.hess
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: ComplexField, D: DimSub<U1>, S: Storage<N, D, D>> SquareMatrix<N, D, S>
|
|
||||||
where
|
|
||||||
DefaultAllocator: Allocator<N, D, D> + Allocator<N, D> + Allocator<N, DimDiff<D, U1>>,
|
|
||||||
{
|
|
||||||
/// Computes the Hessenberg decomposition of this matrix using householder reflections.
|
|
||||||
pub fn hessenberg(self) -> Hessenberg<N, D> {
|
|
||||||
Hessenberg::new(self.into_owned())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -379,13 +379,3 @@ pub fn gauss_step_swap<N, R: Dim, C: Dim, S>(
|
||||||
.axpy(-pivot_row[k].inlined_clone(), &coeffs, N::one());
|
.axpy(-pivot_row[k].inlined_clone(), &coeffs, N::one());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: ComplexField, R: DimMin<C>, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S>
|
|
||||||
where
|
|
||||||
DefaultAllocator: Allocator<N, R, C> + Allocator<(usize, usize), DimMinimum<R, C>>,
|
|
||||||
{
|
|
||||||
/// Computes the LU decomposition with partial (row) pivoting of `matrix`.
|
|
||||||
pub fn lu(self) -> LU<N, R, C> {
|
|
||||||
LU::new(self.into_owned())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ mod determinant;
|
||||||
// FIXME: this should not be needed. However, the exp uses
|
// FIXME: this should not be needed. However, the exp uses
|
||||||
// explicit float operations on `f32` and `f64`. We need to
|
// explicit float operations on `f32` and `f64`. We need to
|
||||||
// get rid of these to allow exp to be used on a no-std context.
|
// get rid of these to allow exp to be used on a no-std context.
|
||||||
|
mod decomposition;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
mod exp;
|
mod exp;
|
||||||
mod full_piv_lu;
|
mod full_piv_lu;
|
||||||
|
|
|
@ -288,13 +288,3 @@ where
|
||||||
// res self.q_determinant()
|
// res self.q_determinant()
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: ComplexField, R: DimMin<C>, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S>
|
|
||||||
where
|
|
||||||
DefaultAllocator: Allocator<N, R, C> + Allocator<N, R> + Allocator<N, DimMinimum<R, C>>,
|
|
||||||
{
|
|
||||||
/// Computes the QR decomposition of this matrix.
|
|
||||||
pub fn qr(self) -> QR<N, R, C> {
|
|
||||||
QR::new(self.into_owned())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -496,26 +496,6 @@ where
|
||||||
+ Allocator<N, D, D>
|
+ Allocator<N, D, D>
|
||||||
+ Allocator<N, D>,
|
+ Allocator<N, D>,
|
||||||
{
|
{
|
||||||
/// Computes the Schur decomposition of a square matrix.
|
|
||||||
pub fn schur(self) -> Schur<N, D> {
|
|
||||||
Schur::new(self.into_owned())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Attempts to compute the Schur decomposition of a square matrix.
|
|
||||||
///
|
|
||||||
/// If only eigenvalues are needed, it is more efficient to call the matrix method
|
|
||||||
/// `.eigenvalues()` instead.
|
|
||||||
///
|
|
||||||
/// # Arguments
|
|
||||||
///
|
|
||||||
/// * `eps` − tolerance used to determine when a value converged to 0.
|
|
||||||
/// * `max_niter` − maximum total number of iterations performed by the algorithm. If this
|
|
||||||
/// number of iteration is exceeded, `None` is returned. If `niter == 0`, then the algorithm
|
|
||||||
/// continues indefinitely until convergence.
|
|
||||||
pub fn try_schur(self, eps: N::RealField, max_niter: usize) -> Option<Schur<N, D>> {
|
|
||||||
Schur::try_new(self.into_owned(), eps, max_niter)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Computes the eigenvalues of this matrix.
|
/// Computes the eigenvalues of this matrix.
|
||||||
pub fn eigenvalues(&self) -> Option<VectorN<N, D>> {
|
pub fn eigenvalues(&self) -> Option<VectorN<N, D>> {
|
||||||
assert!(
|
assert!(
|
||||||
|
|
|
@ -616,31 +616,6 @@ where
|
||||||
+ Allocator<N::RealField, DimMinimum<R, C>>
|
+ Allocator<N::RealField, DimMinimum<R, C>>
|
||||||
+ Allocator<N::RealField, DimDiff<DimMinimum<R, C>, U1>>,
|
+ Allocator<N::RealField, DimDiff<DimMinimum<R, C>, U1>>,
|
||||||
{
|
{
|
||||||
/// Computes the Singular Value Decomposition using implicit shift.
|
|
||||||
pub fn svd(self, compute_u: bool, compute_v: bool) -> SVD<N, R, C> {
|
|
||||||
SVD::new(self.into_owned(), compute_u, compute_v)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Attempts to compute the Singular Value Decomposition of `matrix` using implicit shift.
|
|
||||||
///
|
|
||||||
/// # Arguments
|
|
||||||
///
|
|
||||||
/// * `compute_u` − set this to `true` to enable the computation of left-singular vectors.
|
|
||||||
/// * `compute_v` − set this to `true` to enable the computation of right-singular vectors.
|
|
||||||
/// * `eps` − tolerance used to determine when a value converged to 0.
|
|
||||||
/// * `max_niter` − maximum total number of iterations performed by the algorithm. If this
|
|
||||||
/// number of iteration is exceeded, `None` is returned. If `niter == 0`, then the algorithm
|
|
||||||
/// continues indefinitely until convergence.
|
|
||||||
pub fn try_svd(
|
|
||||||
self,
|
|
||||||
compute_u: bool,
|
|
||||||
compute_v: bool,
|
|
||||||
eps: N::RealField,
|
|
||||||
max_niter: usize,
|
|
||||||
) -> Option<SVD<N, R, C>> {
|
|
||||||
SVD::try_new(self.into_owned(), compute_u, compute_v, eps, max_niter)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Computes the singular values of this matrix.
|
/// Computes the singular values of this matrix.
|
||||||
pub fn singular_values(&self) -> VectorN<N::RealField, DimMinimum<R, C>> {
|
pub fn singular_values(&self) -> VectorN<N::RealField, DimMinimum<R, C>> {
|
||||||
SVD::new(self.clone_owned(), false, false).singular_values
|
SVD::new(self.clone_owned(), false, false).singular_values
|
||||||
|
|
|
@ -308,32 +308,6 @@ where
|
||||||
+ Allocator<N::RealField, D>
|
+ Allocator<N::RealField, D>
|
||||||
+ Allocator<N::RealField, DimDiff<D, U1>>,
|
+ Allocator<N::RealField, DimDiff<D, U1>>,
|
||||||
{
|
{
|
||||||
/// Computes the eigendecomposition of this symmetric matrix.
|
|
||||||
///
|
|
||||||
/// Only the lower-triangular part (including the diagonal) of `m` is read.
|
|
||||||
pub fn symmetric_eigen(self) -> SymmetricEigen<N, D> {
|
|
||||||
SymmetricEigen::new(self.into_owned())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Computes the eigendecomposition of the given symmetric matrix with user-specified
|
|
||||||
/// convergence parameters.
|
|
||||||
///
|
|
||||||
/// Only the lower-triangular part (including the diagonal) of `m` is read.
|
|
||||||
///
|
|
||||||
/// # Arguments
|
|
||||||
///
|
|
||||||
/// * `eps` − tolerance used to determine when a value converged to 0.
|
|
||||||
/// * `max_niter` − maximum total number of iterations performed by the algorithm. If this
|
|
||||||
/// number of iteration is exceeded, `None` is returned. If `niter == 0`, then the algorithm
|
|
||||||
/// continues indefinitely until convergence.
|
|
||||||
pub fn try_symmetric_eigen(
|
|
||||||
self,
|
|
||||||
eps: N::RealField,
|
|
||||||
max_niter: usize,
|
|
||||||
) -> Option<SymmetricEigen<N, D>> {
|
|
||||||
SymmetricEigen::try_new(self.into_owned(), eps, max_niter)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Computes the eigenvalues of this symmetric matrix.
|
/// Computes the eigenvalues of this symmetric matrix.
|
||||||
///
|
///
|
||||||
/// Only the lower-triangular part of the matrix is read.
|
/// Only the lower-triangular part of the matrix is read.
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::allocator::Allocator;
|
use crate::allocator::Allocator;
|
||||||
use crate::base::{DefaultAllocator, MatrixMN, MatrixN, SquareMatrix, VectorN};
|
use crate::base::{DefaultAllocator, MatrixMN, MatrixN, 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 simba::scalar::ComplexField;
|
||||||
|
@ -162,15 +162,3 @@ where
|
||||||
&q * self.tri * q.adjoint()
|
&q * self.tri * q.adjoint()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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>>,
|
|
||||||
{
|
|
||||||
/// Computes the tridiagonalization of this symmetric matrix.
|
|
||||||
///
|
|
||||||
/// Only the lower-triangular part (including the diagonal) of `m` is read.
|
|
||||||
pub fn symmetric_tridiagonalize(self) -> SymmetricTridiagonal<N, D> {
|
|
||||||
SymmetricTridiagonal::new(self.into_owned())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue