2020-11-14 00:26:47 +08:00
use crate ::storage ::Storage ;
use crate ::{
2021-02-25 20:28:42 +08:00
Allocator , Bidiagonal , Cholesky , ColPivQR , ComplexField , DefaultAllocator , Dim , DimDiff ,
2021-02-25 20:20:20 +08:00
DimMin , DimMinimum , DimSub , FullPivLU , Hessenberg , Matrix , RealField , Schur , SymmetricEigen ,
2021-02-25 23:20:11 +08:00
SymmetricTridiagonal , LU , QR , SVD , U1 , UDU ,
2020-11-14 00:26:47 +08:00
} ;
/// # 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. |
2021-02-25 20:28:42 +08:00
/// | QR with column pivoting | `Q * R * P⁻¹` | `Q` is an unitary matrix, and `R` is upper-triangular. `P` is a permutation matrix. |
2020-11-14 00:26:47 +08:00
/// | 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. |
2021-02-25 20:28:42 +08:00
/// | 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. |
2020-11-14 00:26:47 +08:00
/// | 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 ( ) )
}
2021-02-25 20:28:42 +08:00
/// Computes the QR decomposition (with column pivoting) of this matrix.
pub fn col_piv_qr ( self ) -> ColPivQR < N , R , C >
where
R : DimMin < C > ,
DefaultAllocator : Allocator < N , R , C >
+ Allocator < N , R >
+ Allocator < N , DimMinimum < R , C > >
+ Allocator < ( usize , usize ) , DimMinimum < R , C > > ,
{
ColPivQR ::new ( self . into_owned ( ) )
}
2020-11-14 00:26:47 +08:00
/// 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. |
2021-02-25 20:20:20 +08:00
/// | UDU | `U * D * Uᵀ` | `U` is a upper-triangular matrix, and `D` a diagonal matrix. |
2020-11-14 00:26:47 +08:00
/// | 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 ( ) )
}
2021-02-25 20:20:20 +08:00
/// Attempts to compute the UDU decomposition of this matrix.
///
/// The input matrix `self` is assumed to be symmetric and this decomposition will only read
/// the upper-triangular part of `self`.
2021-03-01 00:52:14 +08:00
pub fn udu ( self ) -> Option < UDU < N , D > >
2021-02-25 20:20:20 +08:00
where
N : RealField ,
DefaultAllocator : Allocator < N , D > + Allocator < N , D , D > ,
{
UDU ::new ( self . into_owned ( ) )
}
2020-11-14 00:26:47 +08:00
/// 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 ( ) )
}
}