module Numeric.LAPACK.Matrix.BandedHermitian.Eigen (
values,
decompose,
) where
import Numeric.LAPACK.Matrix.BandedHermitian.Basic (BandedHermitian)
import qualified Numeric.LAPACK.Matrix.Shape.Private as MatrixShape
import qualified Numeric.LAPACK.Matrix.Private as Matrix
import Numeric.LAPACK.Matrix.Hermitian.Private (TakeDiagonal(..))
import Numeric.LAPACK.Matrix.Shape.Private
(Order(RowMajor,ColumnMajor), uploFromOrder)
import Numeric.LAPACK.Vector (Vector)
import Numeric.LAPACK.Scalar (RealOf)
import Numeric.LAPACK.Private
(copyToTemp, copyCondConjugateToTemp, withInfo, eigenMsg)
import qualified Numeric.LAPACK.FFI.Complex as LapackComplex
import qualified Numeric.LAPACK.FFI.Real as LapackReal
import qualified Numeric.Netlib.Utility as Call
import qualified Numeric.Netlib.Class as Class
import qualified Type.Data.Num.Unary as Unary
import Type.Data.Num (integralFromProxy)
import qualified Data.Array.Comfort.Storable.Internal.Monadic as ArrayIO
import qualified Data.Array.Comfort.Storable.Internal as Array
import qualified Data.Array.Comfort.Shape as Shape
import Data.Array.Comfort.Storable.Internal (Array(Array))
import Foreign.C.Types (CInt, CChar)
import Foreign.Ptr (Ptr, nullPtr)
import Foreign.Storable (Storable)
import Control.Monad.Trans.Cont (evalContT)
import Control.Monad.IO.Class (liftIO)
import Data.Complex (Complex)
values ::
(Unary.Natural offDiag, Shape.C sh, Class.Floating a) =>
BandedHermitian offDiag sh a -> Vector sh (RealOf a)
values =
runTakeDiagonal $
Class.switchFloating
(TakeDiagonal valuesAux) (TakeDiagonal valuesAux)
(TakeDiagonal valuesAux) (TakeDiagonal valuesAux)
valuesAux ::
(Unary.Natural offDiag, Shape.C sh,
Class.Floating a, RealOf a ~ ar, Storable ar) =>
BandedHermitian offDiag sh a -> Vector sh ar
valuesAux (Array (MatrixShape.BandedHermitian numOff order size) a) =
Array.unsafeCreateWithSize size $ \n wPtr -> evalContT $ do
let k = integralFromProxy numOff
let lda = k+1
jobzPtr <- Call.char 'N'
uploPtr <- Call.char $ uploFromOrder order
kPtr <- Call.cint k
aPtr <- copyToTemp (n*lda) a
ldaPtr <- Call.leadingDim lda
let zPtr = nullPtr
ldzPtr <- Call.leadingDim n
liftIO $ withInfo eigenMsg "hbev" $
hbev jobzPtr uploPtr n kPtr aPtr ldaPtr wPtr zPtr ldzPtr
decompose ::
(Unary.Natural offDiag, Shape.C sh, Class.Floating a) =>
BandedHermitian offDiag sh a -> (Matrix.Square sh a, Vector sh (RealOf a))
decompose =
getDecompose $
Class.switchFloating
(Decompose decomposeAux) (Decompose decomposeAux)
(Decompose decomposeAux) (Decompose decomposeAux)
type Decompose_ offDiag sh a =
BandedHermitian offDiag sh a -> (Matrix.Square sh a, Vector sh (RealOf a))
newtype Decompose offDiag sh a =
Decompose {getDecompose :: Decompose_ offDiag sh a}
decomposeAux ::
(Unary.Natural offDiag, Shape.C sh,
Class.Floating a, RealOf a ~ ar, Storable ar) =>
Decompose_ offDiag sh a
decomposeAux (Array (MatrixShape.BandedHermitian numOff order size) a) =
Array.unsafeCreateWithSizeAndResult (MatrixShape.square ColumnMajor size) $
\_ zPtr ->
ArrayIO.unsafeCreateWithSize size $ \n wPtr ->
evalContT $ do
let k = integralFromProxy numOff
let lda = k+1
jobzPtr <- Call.char 'V'
uploPtr <- Call.char $ uploFromOrder order
kPtr <- Call.cint k
aPtr <- copyCondConjugateToTemp (order==RowMajor) (n*lda) a
ldaPtr <- Call.leadingDim lda
ldzPtr <- Call.leadingDim n
liftIO $ withInfo eigenMsg "hbev" $
hbev jobzPtr uploPtr n kPtr aPtr ldaPtr wPtr zPtr ldzPtr
type HBEV_ ar a =
Ptr CChar -> Ptr CChar -> Int -> Ptr CInt -> Ptr a -> Ptr CInt -> Ptr ar ->
Ptr a -> Ptr CInt -> Ptr CInt -> IO ()
newtype HBEV a = HBEV {getHBEV :: HBEV_ (RealOf a) a}
hbev :: Class.Floating a => HBEV_ (RealOf a) a
hbev =
getHBEV $
Class.switchFloating
(HBEV sbevReal) (HBEV sbevReal) (HBEV hbevComplex) (HBEV hbevComplex)
sbevReal :: Class.Real a => HBEV_ a a
sbevReal jobzPtr uploPtr n kdPtr aPtr ldaPtr wPtr zPtr ldzPtr infoPtr =
evalContT $ do
nPtr <- Call.cint n
workPtr <- Call.allocaArray (max 1 (3*n2))
liftIO $
LapackReal.sbev jobzPtr uploPtr
nPtr kdPtr aPtr ldaPtr wPtr zPtr ldzPtr workPtr infoPtr
hbevComplex :: Class.Real a => HBEV_ a (Complex a)
hbevComplex jobzPtr uploPtr n kdPtr aPtr ldaPtr wPtr zPtr ldzPtr infoPtr =
evalContT $ do
nPtr <- Call.cint n
workPtr <- Call.allocaArray n
rworkPtr <- Call.allocaArray (max 1 (3*n2))
liftIO $
LapackComplex.hbev jobzPtr uploPtr
nPtr kdPtr aPtr ldaPtr wPtr zPtr ldzPtr workPtr rworkPtr infoPtr