lapack-0.2: src/Numeric/LAPACK/Matrix/Square.hs
module Numeric.LAPACK.Matrix.Square (
module Numeric.LAPACK.Matrix.Square.Basic,
module Numeric.LAPACK.Matrix.Square.Linear,
eigenvalues,
Eigen.schur,
eigensystem,
ComplexOf,
) where
import qualified Numeric.LAPACK.Matrix.Square.Eigen as Eigen
import Numeric.LAPACK.Matrix.Square.Basic
import Numeric.LAPACK.Matrix.Square.Linear
import Numeric.LAPACK.Vector (Vector)
import Numeric.LAPACK.Scalar (ComplexOf)
import qualified Numeric.Netlib.Class as Class
import qualified Data.Array.Comfort.Shape as Shape
eigenvalues ::
(Shape.C sh, Class.Floating a) =>
Square sh a -> Vector sh (ComplexOf a)
eigenvalues = Eigen.values
{- |
@(vr,d,vl) = eigensystem a@
Counterintuitively, @vr@ contains the right eigenvectors
and @vl@ contains the left eigenvectors as columns.
The idea is to provide a decomposition of @a@.
If @a@ is diagonalizable, then @vr@ and @vl@ are almost inverse to each other.
More precisely, @adjoint vl \<#\> vr@ is a diagonal matrix.
This is because all eigenvectors are normalized to Euclidean norm 1.
With the following scaling, the decomposition becomes perfect:
> let scal = Array.map recip $ takeDiagonal $ adjoint vl <#> vr
> a == vr <#> diagonal d <#> diagonal scal <#> adjoint vl
If @a@ is non-diagonalizable then some columns of @vr@ and @vl@ are left zero
and the above property does not hold.
-}
eigensystem ::
(Shape.C sh, Class.Floating a) =>
Square sh a ->
(Square sh (ComplexOf a),
Vector sh (ComplexOf a),
Square sh (ComplexOf a))
eigensystem = Eigen.decompose