{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
module Numeric.LAPACK.Matrix.BandedHermitian (
   BandedHermitian,
   Transposition(..),
   size,
   fromList,
   identity,
   diagonal,
   takeDiagonal,
   toHermitian,
   toBanded,
   multiplyVector,
   multiplyFull,
   gramian,
   sumRank1,

   eigenvalues,
   eigensystem,
   ) where

import qualified Numeric.LAPACK.Matrix.BandedHermitian.Eigen as Eigen
import qualified Numeric.LAPACK.Matrix.BandedHermitian.Basic as Basic

import qualified Numeric.LAPACK.Matrix.Array.Banded as Banded
import qualified Numeric.LAPACK.Matrix.Array as ArrMatrix
import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape
import qualified Numeric.LAPACK.Matrix.Extent as Extent
import Numeric.LAPACK.Matrix.Array.Banded (Square)
import Numeric.LAPACK.Matrix.Array.Triangular (Hermitian)
import Numeric.LAPACK.Matrix.Array (Full)
import Numeric.LAPACK.Matrix.Shape.Private (Order, UnaryProxy)
import Numeric.LAPACK.Matrix.Modifier (Transposition(NonTransposed, Transposed))
import Numeric.LAPACK.Vector (Vector)
import Numeric.LAPACK.Scalar (RealOf)

import qualified Numeric.Netlib.Class as Class

import qualified Type.Data.Num.Unary.Literal as TypeNum
import qualified Type.Data.Num.Unary as Unary
import Type.Data.Num.Unary ((:+:))

import qualified Data.Array.Comfort.Shape as Shape

import Foreign.Storable (Storable)

import Data.Tuple.HT (mapFst)


type BandedHermitian offDiag sh = Banded.Hermitian offDiag sh
type Diagonal size = BandedHermitian TypeNum.U0 size


size :: BandedHermitian offDiag sh a -> sh
size :: BandedHermitian offDiag sh a -> sh
size = BandedHermitian offDiag sh -> sh
forall off size. BandedHermitian off size -> size
MatrixShape.bandedHermitianSize (BandedHermitian offDiag sh -> sh)
-> (BandedHermitian offDiag sh a -> BandedHermitian offDiag sh)
-> BandedHermitian offDiag sh a
-> sh
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BandedHermitian offDiag sh a -> BandedHermitian offDiag sh
forall sh a. ArrayMatrix sh a -> sh
ArrMatrix.shape


fromList ::
   (Unary.Natural offDiag, Shape.C size, Storable a) =>
   UnaryProxy offDiag -> Order -> size -> [a] ->
   BandedHermitian offDiag size a
fromList :: UnaryProxy offDiag
-> Order -> size -> [a] -> BandedHermitian offDiag size a
fromList UnaryProxy offDiag
numOff Order
order size
size_ =
   Array (BandedHermitian offDiag size) a
-> BandedHermitian offDiag size a
forall shA a. Array shA a -> ArrayMatrix shA a
ArrMatrix.lift0 (Array (BandedHermitian offDiag size) a
 -> BandedHermitian offDiag size a)
-> ([a] -> Array (BandedHermitian offDiag size) a)
-> [a]
-> BandedHermitian offDiag size a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnaryProxy offDiag
-> Order -> size -> [a] -> Array (BandedHermitian offDiag size) a
forall offDiag size a.
(Natural offDiag, C size, Storable a) =>
UnaryProxy offDiag
-> Order -> size -> [a] -> BandedHermitian offDiag size a
Basic.fromList UnaryProxy offDiag
numOff Order
order size
size_

identity :: (Shape.C sh, Class.Floating a) => sh -> Diagonal sh a
identity :: sh -> Diagonal sh a
identity = Array (BandedHermitian U0 sh) a -> Diagonal sh a
forall shA a. Array shA a -> ArrayMatrix shA a
ArrMatrix.lift0 (Array (BandedHermitian U0 sh) a -> Diagonal sh a)
-> (sh -> Array (BandedHermitian U0 sh) a) -> sh -> Diagonal sh a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. sh -> Array (BandedHermitian U0 sh) a
forall sh a. (C sh, Floating a) => sh -> Diagonal sh a
Basic.identity

diagonal ::
   (Shape.C sh, Class.Floating a) => Vector sh (RealOf a) -> Diagonal sh a
diagonal :: Vector sh (RealOf a) -> Diagonal sh a
diagonal = Array (BandedHermitian U0 sh) a -> Diagonal sh a
forall shA a. Array shA a -> ArrayMatrix shA a
ArrMatrix.lift0 (Array (BandedHermitian U0 sh) a -> Diagonal sh a)
-> (Vector sh (RealOf a) -> Array (BandedHermitian U0 sh) a)
-> Vector sh (RealOf a)
-> Diagonal sh a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector sh (RealOf a) -> Array (BandedHermitian U0 sh) a
forall sh a.
(C sh, Floating a) =>
Vector sh (RealOf a) -> Diagonal sh a
Basic.diagonal

takeDiagonal ::
   (Unary.Natural offDiag, Shape.C size, Class.Floating a) =>
   BandedHermitian offDiag size a -> Vector size (RealOf a)
takeDiagonal :: BandedHermitian offDiag size a -> Vector size (RealOf a)
takeDiagonal = BandedHermitian offDiag size a -> Vector size (RealOf a)
forall offDiag size a.
(Natural offDiag, C size, Floating a) =>
BandedHermitian offDiag size a -> Vector size (RealOf a)
Basic.takeDiagonal (BandedHermitian offDiag size a -> Vector size (RealOf a))
-> (BandedHermitian offDiag size a
    -> BandedHermitian offDiag size a)
-> BandedHermitian offDiag size a
-> Vector size (RealOf a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BandedHermitian offDiag size a -> BandedHermitian offDiag size a
forall sh a. ArrayMatrix sh a -> Array sh a
ArrMatrix.toVector

toHermitian ::
   (Unary.Natural offDiag, Shape.C size, Class.Floating a) =>
   BandedHermitian offDiag size a -> Hermitian size a
toHermitian :: BandedHermitian offDiag size a -> Hermitian size a
toHermitian = (Array (BandedHermitian offDiag size) a
 -> Array (Hermitian size) a)
-> BandedHermitian offDiag size a -> Hermitian size a
forall shA a shB b.
(Array shA a -> Array shB b)
-> ArrayMatrix shA a -> ArrayMatrix shB b
ArrMatrix.lift1 Array (BandedHermitian offDiag size) a -> Array (Hermitian size) a
forall offDiag size a.
(Natural offDiag, C size, Floating a) =>
BandedHermitian offDiag size a -> Hermitian size a
Basic.toHermitian

toBanded ::
   (Unary.Natural offDiag, Shape.C size, Class.Floating a) =>
   BandedHermitian offDiag size a ->
   Square offDiag offDiag size a
toBanded :: BandedHermitian offDiag size a -> Square offDiag offDiag size a
toBanded = (Array (BandedHermitian offDiag size) a
 -> Array (BandedSquare offDiag offDiag size) a)
-> BandedHermitian offDiag size a -> Square offDiag offDiag size a
forall shA a shB b.
(Array shA a -> Array shB b)
-> ArrayMatrix shA a -> ArrayMatrix shB b
ArrMatrix.lift1 Array (BandedHermitian offDiag size) a
-> Array (BandedSquare offDiag offDiag size) a
forall offDiag size a.
(Natural offDiag, C size, Floating a) =>
BandedHermitian offDiag size a -> Square offDiag offDiag size a
Basic.toBanded

multiplyVector ::
   (Unary.Natural offDiag, Shape.C size, Eq size, Class.Floating a) =>
   Transposition -> BandedHermitian offDiag size a ->
   Vector size a -> Vector size a
multiplyVector :: Transposition
-> BandedHermitian offDiag size a -> Vector size a -> Vector size a
multiplyVector Transposition
transposed = Transposition
-> BandedHermitian offDiag size a -> Vector size a -> Vector size a
forall offDiag size a.
(Natural offDiag, C size, Eq size, Floating a) =>
Transposition
-> BandedHermitian offDiag size a -> Vector size a -> Vector size a
Basic.multiplyVector Transposition
transposed (BandedHermitian offDiag size a -> Vector size a -> Vector size a)
-> (BandedHermitian offDiag size a
    -> BandedHermitian offDiag size a)
-> BandedHermitian offDiag size a
-> Vector size a
-> Vector size a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  BandedHermitian offDiag size a -> BandedHermitian offDiag size a
forall sh a. ArrayMatrix sh a -> Array sh a
ArrMatrix.toVector

gramian ::
   (Shape.C size, Eq size, Class.Floating a,
    Unary.Natural sub, Unary.Natural super) =>
   Square sub super size a ->
   BandedHermitian (sub :+: super) size a
gramian :: Square sub super size a -> BandedHermitian (sub :+: super) size a
gramian = (Array (BandedSquare sub super size) a
 -> Array (BandedHermitian (sub :+: super) size) a)
-> Square sub super size a
-> BandedHermitian (sub :+: super) size a
forall shA a shB b.
(Array shA a -> Array shB b)
-> ArrayMatrix shA a -> ArrayMatrix shB b
ArrMatrix.lift1 Array (BandedSquare sub super size) a
-> Array (BandedHermitian (sub :+: super) size) a
forall size a sub super.
(C size, Eq size, Floating a, Natural sub, Natural super) =>
Square sub super size a -> BandedHermitian (sub :+: super) size a
Basic.gramian

multiplyFull ::
   (Unary.Natural offDiag, Extent.C vert, Extent.C horiz,
    Shape.C height, Eq height, Shape.C width, Class.Floating a) =>
   Transposition -> BandedHermitian offDiag height a ->
   Full vert horiz height width a ->
   Full vert horiz height width a
multiplyFull :: Transposition
-> BandedHermitian offDiag height a
-> Full vert horiz height width a
-> Full vert horiz height width a
multiplyFull = (Array (BandedHermitian offDiag height) a
 -> Array (Full vert horiz height width) a
 -> Array (Full vert horiz height width) a)
-> BandedHermitian offDiag height a
-> Full vert horiz height width a
-> Full vert horiz height width a
forall shA a shB b shC c.
(Array shA a -> Array shB b -> Array shC c)
-> ArrayMatrix shA a -> ArrayMatrix shB b -> ArrayMatrix shC c
ArrMatrix.lift2 ((Array (BandedHermitian offDiag height) a
  -> Array (Full vert horiz height width) a
  -> Array (Full vert horiz height width) a)
 -> BandedHermitian offDiag height a
 -> Full vert horiz height width a
 -> Full vert horiz height width a)
-> (Transposition
    -> Array (BandedHermitian offDiag height) a
    -> Array (Full vert horiz height width) a
    -> Array (Full vert horiz height width) a)
-> Transposition
-> BandedHermitian offDiag height a
-> Full vert horiz height width a
-> Full vert horiz height width a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Transposition
-> Array (BandedHermitian offDiag height) a
-> Array (Full vert horiz height width) a
-> Array (Full vert horiz height width) a
forall offDiag vert horiz height width a.
(Natural offDiag, C vert, C horiz, C height, Eq height, C width,
 Floating a) =>
Transposition
-> BandedHermitian offDiag height a
-> Full vert horiz height width a
-> Full vert horiz height width a
Basic.multiplyFull

{- |
The list represents ragged rows of a sparse matrix.
-}
sumRank1 ::
   (Unary.Natural k, Shape.Indexed sh, Class.Floating a) =>
   Order -> sh ->
   [(RealOf a, (Shape.Index sh, Basic.StaticVector (Unary.Succ k) a))] ->
   BandedHermitian k sh a
sumRank1 :: Order
-> sh
-> [(RealOf a, (Index sh, StaticVector (Succ k) a))]
-> BandedHermitian k sh a
sumRank1 Order
order sh
sh = Array (BandedHermitian k sh) a -> BandedHermitian k sh a
forall shA a. Array shA a -> ArrayMatrix shA a
ArrMatrix.lift0 (Array (BandedHermitian k sh) a -> BandedHermitian k sh a)
-> ([(RealOf a, (Index sh, StaticVector (Succ k) a))]
    -> Array (BandedHermitian k sh) a)
-> [(RealOf a, (Index sh, StaticVector (Succ k) a))]
-> BandedHermitian k sh a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Order
-> sh
-> [(RealOf a, (Index sh, StaticVector (Succ k) a))]
-> Array (BandedHermitian k sh) a
forall k sh a.
(Natural k, Indexed sh, Floating a) =>
Order
-> sh
-> [(RealOf a, (Index sh, StaticVector (Succ k) a))]
-> BandedHermitian k sh a
Basic.sumRank1 Order
order sh
sh


eigenvalues ::
   (Unary.Natural offDiag, Shape.C sh, Class.Floating a) =>
   BandedHermitian offDiag sh a -> Vector sh (RealOf a)
eigenvalues :: BandedHermitian offDiag sh a -> Vector sh (RealOf a)
eigenvalues = BandedHermitian offDiag sh a -> Vector sh (RealOf a)
forall offDiag size a.
(Natural offDiag, C size, Floating a) =>
BandedHermitian offDiag size a -> Vector size (RealOf a)
Eigen.values (BandedHermitian offDiag sh a -> Vector sh (RealOf a))
-> (BandedHermitian offDiag sh a -> BandedHermitian offDiag sh a)
-> BandedHermitian offDiag sh a
-> Vector sh (RealOf a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BandedHermitian offDiag sh a -> BandedHermitian offDiag sh a
forall sh a. ArrayMatrix sh a -> Array sh a
ArrMatrix.toVector

{- |
For symmetric eigenvalue problems, @eigensystem@ and @schur@ coincide.
-}
eigensystem ::
   (Unary.Natural offDiag, Shape.C sh, Class.Floating a) =>
   BandedHermitian offDiag sh a -> (ArrMatrix.Square sh a, Vector sh (RealOf a))
eigensystem :: BandedHermitian offDiag sh a -> (Square sh a, Vector sh (RealOf a))
eigensystem = (Array (Square sh) a -> Square sh a)
-> (Array (Square sh) a, Vector sh (RealOf a))
-> (Square sh a, Vector sh (RealOf a))
forall a c b. (a -> c) -> (a, b) -> (c, b)
mapFst Array (Square sh) a -> Square sh a
forall shA a. Array shA a -> ArrayMatrix shA a
ArrMatrix.lift0 ((Array (Square sh) a, Vector sh (RealOf a))
 -> (Square sh a, Vector sh (RealOf a)))
-> (BandedHermitian offDiag sh a
    -> (Array (Square sh) a, Vector sh (RealOf a)))
-> BandedHermitian offDiag sh a
-> (Square sh a, Vector sh (RealOf a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BandedHermitian offDiag sh a
-> (Array (Square sh) a, Vector sh (RealOf a))
forall offDiag sh a.
(Natural offDiag, C sh, Floating a) =>
BandedHermitian offDiag sh a -> (Square sh a, Vector sh (RealOf a))
Eigen.decompose (BandedHermitian offDiag sh a
 -> (Array (Square sh) a, Vector sh (RealOf a)))
-> (BandedHermitian offDiag sh a -> BandedHermitian offDiag sh a)
-> BandedHermitian offDiag sh a
-> (Array (Square sh) a, Vector sh (RealOf a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BandedHermitian offDiag sh a -> BandedHermitian offDiag sh a
forall sh a. ArrayMatrix sh a -> Array sh a
ArrMatrix.toVector