{-# LANGUAGE GADTs #-}
module Numeric.LAPACK.Matrix.HermitianPositiveDefinite (
   Hermitian.Semidefinite,
   Hermitian.assureFullRank,
   Hermitian.assureAnyRank,
   Hermitian.relaxSemidefinite,
   Hermitian.relaxIndefinite,
   Hermitian.assurePositiveDefiniteness,
   Hermitian.relaxDefiniteness,

   solve,
   solveDecomposed,
   inverse,
   decompose,
   determinant,
   ) where

import qualified Numeric.LAPACK.Matrix.HermitianPositiveDefinite.Linear
                                                                  as Linear
import qualified Numeric.LAPACK.Matrix.Array.Hermitian as Hermitian
import qualified Numeric.LAPACK.Matrix.Array.Private as ArrMatrix
import qualified Numeric.LAPACK.Matrix.Layout.Private as Layout
import qualified Numeric.LAPACK.Matrix.Extent as Extent
import Numeric.LAPACK.Matrix.Array.Mosaic (HermitianPosDefP, UpperP)
import Numeric.LAPACK.Matrix.Array.Private (Full)
import Numeric.LAPACK.Scalar (RealOf)

import qualified Numeric.Netlib.Class as Class

import qualified Data.Array.Comfort.Shape as Shape



solve ::
   (Extent.Measure meas, Extent.C vert, Extent.C horiz,
    Layout.Packing pack, Shape.C sh, Eq sh, Shape.C nrhs, Class.Floating a) =>
   HermitianPosDefP pack sh a ->
   Full meas vert horiz sh nrhs a -> Full meas vert horiz sh nrhs a
solve = ArrMatrix.lift2 Linear.solve

{- |
> solve a b == solveDecomposed (decompose a) b
> solve (gramian u) b == solveDecomposed u b
-}
solveDecomposed ::
   (Extent.Measure meas, Extent.C vert, Extent.C horiz,
    Layout.Packing pack, Shape.C sh, Eq sh, Shape.C nrhs, Class.Floating a) =>
   UpperP pack sh a ->
   Full meas vert horiz sh nrhs a -> Full meas vert horiz sh nrhs a
solveDecomposed = ArrMatrix.lift2 Linear.solveDecomposed

inverse ::
   (Layout.Packing pack, Shape.C sh, Class.Floating a) =>
   HermitianPosDefP pack sh a -> HermitianPosDefP pack sh a
inverse = ArrMatrix.lift1 Linear.inverse

{- |
Cholesky decomposition
-}
decompose ::
   (Layout.Packing pack, Shape.C sh, Class.Floating a) =>
   HermitianPosDefP pack sh a -> UpperP pack sh a
decompose = ArrMatrix.lift1 Linear.decompose

determinant ::
   (Layout.Packing pack, Shape.C sh, Class.Floating a) =>
   HermitianPosDefP pack sh a -> RealOf a
determinant = Linear.determinant . ArrMatrix.toVector