{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE GADTs #-}
module Numeric.LAPACK.Matrix.Array.Hermitian (
   Semidefinite,
   AnyHermitian,
   AnyHermitianP,
   assureFullRank,
   assureAnyRank,
   relaxSemidefinite,
   relaxIndefinite,
   assurePositiveDefiniteness,
   relaxDefiniteness,
   asUnknownDefiniteness,
   ) where

import qualified Numeric.LAPACK.Matrix.Shape.Omni as Omni
import Numeric.LAPACK.Matrix.Array.Private (Matrix(Array), Quadratic)
import Numeric.LAPACK.Matrix.Layout.Private (Packed)

import qualified Type.Data.Bool as TBool
import Type.Data.Bool (False, True)

import qualified Data.Array.Comfort.Storable.Unchecked as Array
import Data.Function.HT (Id)


class (TBool.C neg, TBool.C pos) => Semidefinite neg pos where
instance Semidefinite False True where
instance Semidefinite True False where

type AnyHermitian neg zero pos bands sh =
      AnyHermitianP Packed neg zero pos bands sh
type AnyHermitianP pack neg zero pos bands sh =
      Quadratic pack (Omni.Hermitian neg zero pos) bands bands sh

{-
If a semidefinite matrix has full rank, then it is definite.
You can verify this by watching the eigenvalue decomposition of the matrix.
-}
assureFullRank ::
   (Semidefinite neg pos, TBool.C zero) =>
   AnyHermitianP pack neg zero pos bands sh a ->
   AnyHermitianP pack neg False pos bands sh a
assureFullRank :: forall neg pos zero pack bands sh a.
(Semidefinite neg pos, C zero) =>
AnyHermitianP pack neg zero pos bands sh a
-> AnyHermitianP pack neg False pos bands sh a
assureFullRank = AnyHermitianP pack neg zero pos bands sh a
-> AnyHermitianP pack neg False pos bands sh a
forall negA zeroA posA negB zeroB posB pack bands sh a.
(C negA, C zeroA, C posA, C negB, C zeroB, C posB) =>
AnyHermitianP pack negA zeroA posA bands sh a
-> AnyHermitianP pack negB zeroB posB bands sh a
alterDefiniteness

assureAnyRank ::
   (Semidefinite neg pos, TBool.C zero) =>
   AnyHermitianP pack neg True pos bands sh a ->
   AnyHermitianP pack neg zero pos bands sh a
assureAnyRank :: forall neg pos zero pack bands sh a.
(Semidefinite neg pos, C zero) =>
AnyHermitianP pack neg True pos bands sh a
-> AnyHermitianP pack neg zero pos bands sh a
assureAnyRank = AnyHermitianP pack neg True pos bands sh a
-> AnyHermitianP pack neg zero pos bands sh a
forall negA zeroA posA negB zeroB posB pack bands sh a.
(C negA, C zeroA, C posA, C negB, C zeroB, C posB) =>
AnyHermitianP pack negA zeroA posA bands sh a
-> AnyHermitianP pack negB zeroB posB bands sh a
alterDefiniteness

relaxSemidefinite ::
   (TBool.C neg, TBool.C zero, TBool.C pos) =>
   AnyHermitianP pack neg False pos bands sh a ->
   AnyHermitianP pack neg zero pos bands sh a
relaxSemidefinite :: forall neg zero pos pack bands sh a.
(C neg, C zero, C pos) =>
AnyHermitianP pack neg False pos bands sh a
-> AnyHermitianP pack neg zero pos bands sh a
relaxSemidefinite = AnyHermitianP pack neg False pos bands sh a
-> AnyHermitianP pack neg zero pos bands sh a
forall negA zeroA posA negB zeroB posB pack bands sh a.
(C negA, C zeroA, C posA, C negB, C zeroB, C posB) =>
AnyHermitianP pack negA zeroA posA bands sh a
-> AnyHermitianP pack negB zeroB posB bands sh a
alterDefiniteness

relaxIndefinite ::
   (TBool.C neg, TBool.C zero, TBool.C pos) =>
   AnyHermitianP pack neg zero pos bands sh a ->
   Quadratic pack Omni.HermitianUnknownDefiniteness bands bands sh a
relaxIndefinite :: forall neg zero pos pack bands sh a.
(C neg, C zero, C pos) =>
AnyHermitianP pack neg zero pos bands sh a
-> Quadratic pack HermitianUnknownDefiniteness bands bands sh a
relaxIndefinite = AnyHermitianP pack neg zero pos bands sh a
-> AnyHermitianP pack True True True bands sh a
forall negA zeroA posA negB zeroB posB pack bands sh a.
(C negA, C zeroA, C posA, C negB, C zeroB, C posB) =>
AnyHermitianP pack negA zeroA posA bands sh a
-> AnyHermitianP pack negB zeroB posB bands sh a
alterDefiniteness

assurePositiveDefiniteness ::
   (TBool.C neg, TBool.C zero, TBool.C pos) =>
   AnyHermitianP pack neg zero pos bands sh a ->
   Quadratic pack Omni.HermitianPositiveDefinite bands bands sh a
assurePositiveDefiniteness :: forall neg zero pos pack bands sh a.
(C neg, C zero, C pos) =>
AnyHermitianP pack neg zero pos bands sh a
-> Quadratic pack HermitianPositiveDefinite bands bands sh a
assurePositiveDefiniteness = AnyHermitianP pack neg zero pos bands sh a
-> AnyHermitianP pack False False True bands sh a
forall negA zeroA posA negB zeroB posB pack bands sh a.
(C negA, C zeroA, C posA, C negB, C zeroB, C posB) =>
AnyHermitianP pack negA zeroA posA bands sh a
-> AnyHermitianP pack negB zeroB posB bands sh a
alterDefiniteness

relaxDefiniteness ::
   (TBool.C neg, TBool.C zero, TBool.C pos) =>
   Quadratic pack Omni.HermitianPositiveDefinite bands bands sh a ->
   AnyHermitianP pack neg zero pos bands sh a
relaxDefiniteness :: forall neg zero pos pack bands sh a.
(C neg, C zero, C pos) =>
Quadratic pack HermitianPositiveDefinite bands bands sh a
-> AnyHermitianP pack neg zero pos bands sh a
relaxDefiniteness = AnyHermitianP pack False False True bands sh a
-> AnyHermitianP pack neg zero pos bands sh a
forall negA zeroA posA negB zeroB posB pack bands sh a.
(C negA, C zeroA, C posA, C negB, C zeroB, C posB) =>
AnyHermitianP pack negA zeroA posA bands sh a
-> AnyHermitianP pack negB zeroB posB bands sh a
alterDefiniteness

alterDefiniteness ::
   (TBool.C negA, TBool.C zeroA, TBool.C posA,
    TBool.C negB, TBool.C zeroB, TBool.C posB) =>
   AnyHermitianP pack negA zeroA posA bands sh a ->
   AnyHermitianP pack negB zeroB posB bands sh a
alterDefiniteness :: forall negA zeroA posA negB zeroB posB pack bands sh a.
(C negA, C zeroA, C posA, C negB, C zeroB, C posB) =>
AnyHermitianP pack negA zeroA posA bands sh a
-> AnyHermitianP pack negB zeroB posB bands sh a
alterDefiniteness (Array OmniArray
  pack
  (Hermitian negA zeroA posA)
  bands
  bands
  Shape
  Small
  Small
  sh
  sh
  a
a) =
   OmniArray
  pack
  (Hermitian negB zeroB posB)
  bands
  bands
  Shape
  Small
  Small
  sh
  sh
  a
-> Matrix
     (Array pack (Hermitian negB zeroB posB))
     ()
     ()
     bands
     bands
     Shape
     Small
     Small
     sh
     sh
     a
forall pack prop lower upper meas vert horiz height width a.
OmniArray pack prop lower upper meas vert horiz height width a
-> Matrix
     (Array pack prop) () () lower upper meas vert horiz height width a
Array (OmniArray
   pack
   (Hermitian negB zeroB posB)
   bands
   bands
   Shape
   Small
   Small
   sh
   sh
   a
 -> Matrix
      (Array pack (Hermitian negB zeroB posB))
      ()
      ()
      bands
      bands
      Shape
      Small
      Small
      sh
      sh
      a)
-> OmniArray
     pack
     (Hermitian negB zeroB posB)
     bands
     bands
     Shape
     Small
     Small
     sh
     sh
     a
-> Matrix
     (Array pack (Hermitian negB zeroB posB))
     ()
     ()
     bands
     bands
     Shape
     Small
     Small
     sh
     sh
     a
forall a b. (a -> b) -> a -> b
$ ((Omni
    pack
    (Hermitian negA zeroA posA)
    bands
    bands
    Shape
    Small
    Small
    sh
    sh
  -> Omni
       pack
       (Hermitian negB zeroB posB)
       bands
       bands
       Shape
       Small
       Small
       sh
       sh)
 -> OmniArray
      pack
      (Hermitian negA zeroA posA)
      bands
      bands
      Shape
      Small
      Small
      sh
      sh
      a
 -> OmniArray
      pack
      (Hermitian negB zeroB posB)
      bands
      bands
      Shape
      Small
      Small
      sh
      sh
      a)
-> OmniArray
     pack
     (Hermitian negA zeroA posA)
     bands
     bands
     Shape
     Small
     Small
     sh
     sh
     a
-> (Omni
      pack
      (Hermitian negA zeroA posA)
      bands
      bands
      Shape
      Small
      Small
      sh
      sh
    -> Omni
         pack
         (Hermitian negB zeroB posB)
         bands
         bands
         Shape
         Small
         Small
         sh
         sh)
-> OmniArray
     pack
     (Hermitian negB zeroB posB)
     bands
     bands
     Shape
     Small
     Small
     sh
     sh
     a
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Omni
   pack
   (Hermitian negA zeroA posA)
   bands
   bands
   Shape
   Small
   Small
   sh
   sh
 -> Omni
      pack
      (Hermitian negB zeroB posB)
      bands
      bands
      Shape
      Small
      Small
      sh
      sh)
-> OmniArray
     pack
     (Hermitian negA zeroA posA)
     bands
     bands
     Shape
     Small
     Small
     sh
     sh
     a
-> OmniArray
     pack
     (Hermitian negB zeroB posB)
     bands
     bands
     Shape
     Small
     Small
     sh
     sh
     a
forall sh0 sh1 a. (sh0 -> sh1) -> Array sh0 a -> Array sh1 a
Array.mapShape OmniArray
  pack
  (Hermitian negA zeroA posA)
  bands
  bands
  Shape
  Small
  Small
  sh
  sh
  a
a ((Omni
    pack
    (Hermitian negA zeroA posA)
    bands
    bands
    Shape
    Small
    Small
    sh
    sh
  -> Omni
       pack
       (Hermitian negB zeroB posB)
       bands
       bands
       Shape
       Small
       Small
       sh
       sh)
 -> OmniArray
      pack
      (Hermitian negB zeroB posB)
      bands
      bands
      Shape
      Small
      Small
      sh
      sh
      a)
-> (Omni
      pack
      (Hermitian negA zeroA posA)
      bands
      bands
      Shape
      Small
      Small
      sh
      sh
    -> Omni
         pack
         (Hermitian negB zeroB posB)
         bands
         bands
         Shape
         Small
         Small
         sh
         sh)
-> OmniArray
     pack
     (Hermitian negB zeroB posB)
     bands
     bands
     Shape
     Small
     Small
     sh
     sh
     a
forall a b. (a -> b) -> a -> b
$ \Omni
  pack
  (Hermitian negA zeroA posA)
  bands
  bands
  Shape
  Small
  Small
  sh
  sh
omni ->
      case Omni
  pack
  (Hermitian negA zeroA posA)
  bands
  bands
  Shape
  Small
  Small
  sh
  sh
omni of
         Omni.Full Full Shape Small Small sh sh
sh -> Full Shape Small Small sh sh
-> Omni
     Unpacked
     (Hermitian negB zeroB posB)
     bands
     bands
     Shape
     Small
     Small
     sh
     sh
forall property lower upper meas vert horiz height width.
(Property property, Strip lower, Strip upper) =>
Full meas vert horiz height width
-> Omni Unpacked property lower upper meas vert horiz height width
Omni.Full Full Shape Small Small sh sh
sh
         Omni.Hermitian Hermitian sh
sh -> Hermitian sh
-> Omni
     Packed
     (Hermitian negB zeroB posB)
     Filled
     Filled
     Shape
     Small
     Small
     sh
     sh
forall neg zero pos height.
(C neg, C zero, C pos) =>
Hermitian height
-> Omni
     Packed
     (Hermitian neg zero pos)
     Filled
     Filled
     Shape
     Small
     Small
     height
     height
Omni.Hermitian Hermitian sh
sh
         Omni.BandedHermitian BandedHermitian offDiag sh
sh -> BandedHermitian offDiag sh
-> Omni
     Packed
     (Hermitian negB zeroB posB)
     (Bands offDiag)
     (Bands offDiag)
     Shape
     Small
     Small
     sh
     sh
forall neg zero pos offDiag height.
(C neg, C zero, C pos, Natural offDiag) =>
BandedHermitian offDiag height
-> Omni
     Packed
     (Hermitian neg zero pos)
     (Bands offDiag)
     (Bands offDiag)
     Shape
     Small
     Small
     height
     height
Omni.BandedHermitian BandedHermitian offDiag sh
sh


asUnknownDefiniteness ::
   Id (Quadratic pack Omni.HermitianUnknownDefiniteness bands bands sh a)
asUnknownDefiniteness :: forall pack bands sh a.
Id (Quadratic pack HermitianUnknownDefiniteness bands bands sh a)
asUnknownDefiniteness = Quadratic pack HermitianUnknownDefiniteness bands bands sh a
-> Quadratic pack HermitianUnknownDefiniteness bands bands sh a
forall a. a -> a
id