{-# LANGUAGE TypeFamilies #-}
module Numeric.LAPACK.Matrix.Hermitian.Linear (
   determinant,
   ) where

import qualified Numeric.LAPACK.Matrix.Symmetric.Unified as Symmetric
import qualified Numeric.LAPACK.Matrix.Layout.Private as Layout
import Numeric.LAPACK.Matrix.Hermitian.Basic (HermitianP)
import Numeric.LAPACK.Matrix.Hermitian.Private (Determinant(..))
import Numeric.LAPACK.Scalar (RealOf, absoluteSquared)
import Numeric.LAPACK.Private (realPtr)

import qualified Numeric.Netlib.Class as Class

import qualified Data.Array.Comfort.Shape as Shape

import Foreign.Ptr (Ptr)
import Foreign.Storable (peek)


determinant ::
   (Layout.Packing pack, Shape.C sh, Class.Floating a) =>
   HermitianP pack sh a -> RealOf a
determinant :: HermitianP pack sh a -> RealOf a
determinant =
   Determinant (Array (Mosaic pack ConjugateMirror Upper sh)) a
-> HermitianP pack sh a -> RealOf a
forall (f :: * -> *) a. Determinant f a -> f a -> RealOf a
getDeterminant (Determinant (Array (Mosaic pack ConjugateMirror Upper sh)) a
 -> HermitianP pack sh a -> RealOf a)
-> Determinant (Array (Mosaic pack ConjugateMirror Upper sh)) a
-> HermitianP pack sh a
-> RealOf a
forall a b. (a -> b) -> a -> b
$
   Determinant (Array (Mosaic pack ConjugateMirror Upper sh)) Float
-> Determinant
     (Array (Mosaic pack ConjugateMirror Upper sh)) Double
-> Determinant
     (Array (Mosaic pack ConjugateMirror Upper sh)) (Complex Float)
-> Determinant
     (Array (Mosaic pack ConjugateMirror Upper sh)) (Complex Double)
-> Determinant (Array (Mosaic pack ConjugateMirror Upper sh)) a
forall a (f :: * -> *).
Floating a =>
f Float
-> f Double -> f (Complex Float) -> f (Complex Double) -> f a
Class.switchFloating
      ((Array (Mosaic pack ConjugateMirror Upper sh) Float
 -> RealOf Float)
-> Determinant (Array (Mosaic pack ConjugateMirror Upper sh)) Float
forall (f :: * -> *) a. (f a -> RealOf a) -> Determinant f a
Determinant ((Array (Mosaic pack ConjugateMirror Upper sh) Float
  -> RealOf Float)
 -> Determinant
      (Array (Mosaic pack ConjugateMirror Upper sh)) Float)
-> (Array (Mosaic pack ConjugateMirror Upper sh) Float
    -> RealOf Float)
-> Determinant (Array (Mosaic pack ConjugateMirror Upper sh)) Float
forall a b. (a -> b) -> a -> b
$ ((Ptr Float, Maybe (Ptr Float, Ptr Float)) -> IO Float)
-> Array (Mosaic pack ConjugateMirror Upper sh) Float -> Float
forall mirror uplo sh a ar pack.
(Mirror mirror, UpLo uplo, C sh, Floating a, Floating ar) =>
((Ptr a, Maybe (Ptr a, Ptr a)) -> IO ar)
-> Mosaic pack mirror uplo sh a -> ar
Symmetric.determinant (Ptr Float, Maybe (Ptr Float, Ptr Float)) -> IO Float
forall a ar.
(Floating a, RealOf a ~ ar, Real ar) =>
(Ptr a, Maybe (Ptr a, Ptr a)) -> IO ar
peekBlockDeterminant)
      ((Array (Mosaic pack ConjugateMirror Upper sh) Double
 -> RealOf Double)
-> Determinant
     (Array (Mosaic pack ConjugateMirror Upper sh)) Double
forall (f :: * -> *) a. (f a -> RealOf a) -> Determinant f a
Determinant ((Array (Mosaic pack ConjugateMirror Upper sh) Double
  -> RealOf Double)
 -> Determinant
      (Array (Mosaic pack ConjugateMirror Upper sh)) Double)
-> (Array (Mosaic pack ConjugateMirror Upper sh) Double
    -> RealOf Double)
-> Determinant
     (Array (Mosaic pack ConjugateMirror Upper sh)) Double
forall a b. (a -> b) -> a -> b
$ ((Ptr Double, Maybe (Ptr Double, Ptr Double)) -> IO Double)
-> Array (Mosaic pack ConjugateMirror Upper sh) Double -> Double
forall mirror uplo sh a ar pack.
(Mirror mirror, UpLo uplo, C sh, Floating a, Floating ar) =>
((Ptr a, Maybe (Ptr a, Ptr a)) -> IO ar)
-> Mosaic pack mirror uplo sh a -> ar
Symmetric.determinant (Ptr Double, Maybe (Ptr Double, Ptr Double)) -> IO Double
forall a ar.
(Floating a, RealOf a ~ ar, Real ar) =>
(Ptr a, Maybe (Ptr a, Ptr a)) -> IO ar
peekBlockDeterminant)
      ((Array (Mosaic pack ConjugateMirror Upper sh) (Complex Float)
 -> RealOf (Complex Float))
-> Determinant
     (Array (Mosaic pack ConjugateMirror Upper sh)) (Complex Float)
forall (f :: * -> *) a. (f a -> RealOf a) -> Determinant f a
Determinant ((Array (Mosaic pack ConjugateMirror Upper sh) (Complex Float)
  -> RealOf (Complex Float))
 -> Determinant
      (Array (Mosaic pack ConjugateMirror Upper sh)) (Complex Float))
-> (Array (Mosaic pack ConjugateMirror Upper sh) (Complex Float)
    -> RealOf (Complex Float))
-> Determinant
     (Array (Mosaic pack ConjugateMirror Upper sh)) (Complex Float)
forall a b. (a -> b) -> a -> b
$ ((Ptr (Complex Float),
  Maybe (Ptr (Complex Float), Ptr (Complex Float)))
 -> IO Float)
-> Array (Mosaic pack ConjugateMirror Upper sh) (Complex Float)
-> Float
forall mirror uplo sh a ar pack.
(Mirror mirror, UpLo uplo, C sh, Floating a, Floating ar) =>
((Ptr a, Maybe (Ptr a, Ptr a)) -> IO ar)
-> Mosaic pack mirror uplo sh a -> ar
Symmetric.determinant (Ptr (Complex Float),
 Maybe (Ptr (Complex Float), Ptr (Complex Float)))
-> IO Float
forall a ar.
(Floating a, RealOf a ~ ar, Real ar) =>
(Ptr a, Maybe (Ptr a, Ptr a)) -> IO ar
peekBlockDeterminant)
      ((Array (Mosaic pack ConjugateMirror Upper sh) (Complex Double)
 -> RealOf (Complex Double))
-> Determinant
     (Array (Mosaic pack ConjugateMirror Upper sh)) (Complex Double)
forall (f :: * -> *) a. (f a -> RealOf a) -> Determinant f a
Determinant ((Array (Mosaic pack ConjugateMirror Upper sh) (Complex Double)
  -> RealOf (Complex Double))
 -> Determinant
      (Array (Mosaic pack ConjugateMirror Upper sh)) (Complex Double))
-> (Array (Mosaic pack ConjugateMirror Upper sh) (Complex Double)
    -> RealOf (Complex Double))
-> Determinant
     (Array (Mosaic pack ConjugateMirror Upper sh)) (Complex Double)
forall a b. (a -> b) -> a -> b
$ ((Ptr (Complex Double),
  Maybe (Ptr (Complex Double), Ptr (Complex Double)))
 -> IO Double)
-> Array (Mosaic pack ConjugateMirror Upper sh) (Complex Double)
-> Double
forall mirror uplo sh a ar pack.
(Mirror mirror, UpLo uplo, C sh, Floating a, Floating ar) =>
((Ptr a, Maybe (Ptr a, Ptr a)) -> IO ar)
-> Mosaic pack mirror uplo sh a -> ar
Symmetric.determinant (Ptr (Complex Double),
 Maybe (Ptr (Complex Double), Ptr (Complex Double)))
-> IO Double
forall a ar.
(Floating a, RealOf a ~ ar, Real ar) =>
(Ptr a, Maybe (Ptr a, Ptr a)) -> IO ar
peekBlockDeterminant)

peekBlockDeterminant ::
   (Class.Floating a, RealOf a ~ ar, Class.Real ar) =>
   (Ptr a, Maybe (Ptr a, Ptr a)) -> IO ar
peekBlockDeterminant :: (Ptr a, Maybe (Ptr a, Ptr a)) -> IO ar
peekBlockDeterminant (Ptr a
a0Ptr,Maybe (Ptr a, Ptr a)
ext) = do
   let peekReal :: Ptr a -> IO (RealOf a)
peekReal = Ptr (RealOf a) -> IO (RealOf a)
forall a. Storable a => Ptr a -> IO a
peek (Ptr (RealOf a) -> IO (RealOf a))
-> (Ptr a -> Ptr (RealOf a)) -> Ptr a -> IO (RealOf a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ptr a -> Ptr (RealOf a)
forall a. Ptr a -> Ptr (RealOf a)
realPtr
   ar
a0 <- Ptr a -> IO (RealOf a)
peekReal Ptr a
a0Ptr
   case Maybe (Ptr a, Ptr a)
ext of
      Maybe (Ptr a, Ptr a)
Nothing -> ar -> IO ar
forall (m :: * -> *) a. Monad m => a -> m a
return ar
a0
      Just (Ptr a
a1Ptr,Ptr a
bPtr) -> do
         ar
a1 <- Ptr a -> IO (RealOf a)
peekReal Ptr a
a1Ptr
         a
b <- Ptr a -> IO a
forall a. Storable a => Ptr a -> IO a
peek Ptr a
bPtr
         ar -> IO ar
forall (m :: * -> *) a. Monad m => a -> m a
return (ar
a0ar -> ar -> ar
forall a. Num a => a -> a -> a
*ar
a1 ar -> ar -> ar
forall a. Num a => a -> a -> a
- a -> RealOf a
forall a. Floating a => a -> RealOf a
absoluteSquared a
b)