{-# LANGUAGE TypeFamilies #-}
module Numeric.LAPACK.Scalar (
   RealOf,
   ComplexOf,
   zero,
   one,
   minusOne,
   isZero,
   selectReal,
   selectFloating,

   equal,
   fromReal,
   toComplex,
   absolute,
   absoluteSquared,
   norm1,
   realPart,
   conjugate,
   ) where

import Numeric.LAPACK.Wrapper (Flip(Flip, getFlip))

import qualified Numeric.Netlib.Class as Class

import Data.Functor.Identity (Identity(Identity, runIdentity))

import qualified Data.Complex as Complex
import Data.Complex (Complex((:+)))
import Data.Monoid (Endo(Endo,appEndo))


type family RealOf x

type instance RealOf Float = Float
type instance RealOf Double = Double
type instance RealOf (Complex a) = a


type ComplexOf x = Complex (RealOf x)


-- move to netlib-carray:Utility or netlib-ffi:Class
zero, one, minusOne :: Class.Floating a => a
zero :: a
zero = Float -> Double -> Complex Float -> Complex Double -> a
forall a.
Floating a =>
Float -> Double -> Complex Float -> Complex Double -> a
selectFloating Float
0 Double
0 Complex Float
0 Complex Double
0
one :: a
one = Float -> Double -> Complex Float -> Complex Double -> a
forall a.
Floating a =>
Float -> Double -> Complex Float -> Complex Double -> a
selectFloating Float
1 Double
1 Complex Float
1 Complex Double
1
minusOne :: a
minusOne = Float -> Double -> Complex Float -> Complex Double -> a
forall a.
Floating a =>
Float -> Double -> Complex Float -> Complex Double -> a
selectFloating (-Float
1) (-Double
1) (-Complex Float
1) (-Complex Double
1)

selectReal :: (Class.Real a) => Float -> Double -> a
selectReal :: Float -> Double -> a
selectReal Float
rf Double
rd =
   Identity a -> a
forall a. Identity a -> a
runIdentity (Identity a -> a) -> Identity a -> a
forall a b. (a -> b) -> a -> b
$ Identity Float -> Identity Double -> Identity a
forall a (f :: * -> *). Real a => f Float -> f Double -> f a
Class.switchReal (Float -> Identity Float
forall a. a -> Identity a
Identity Float
rf) (Double -> Identity Double
forall a. a -> Identity a
Identity Double
rd)

selectFloating ::
   (Class.Floating a) =>
   Float -> Double -> Complex Float -> Complex Double -> a
selectFloating :: Float -> Double -> Complex Float -> Complex Double -> a
selectFloating Float
rf Double
rd Complex Float
cf Complex Double
cd =
   Identity a -> a
forall a. Identity a -> a
runIdentity (Identity a -> a) -> Identity a -> a
forall a b. (a -> b) -> a -> b
$
   Identity Float
-> Identity Double
-> Identity (Complex Float)
-> Identity (Complex Double)
-> Identity a
forall a (f :: * -> *).
Floating a =>
f Float
-> f Double -> f (Complex Float) -> f (Complex Double) -> f a
Class.switchFloating
      (Float -> Identity Float
forall a. a -> Identity a
Identity Float
rf) (Double -> Identity Double
forall a. a -> Identity a
Identity Double
rd) (Complex Float -> Identity (Complex Float)
forall a. a -> Identity a
Identity Complex Float
cf) (Complex Double -> Identity (Complex Double)
forall a. a -> Identity a
Identity Complex Double
cd)



newtype Equal a = Equal {Equal a -> a -> a -> Bool
getEqual :: a -> a -> Bool}

equal :: (Class.Floating a) => a -> a -> Bool
equal :: a -> a -> Bool
equal =
   Equal a -> a -> a -> Bool
forall a. Equal a -> a -> a -> Bool
getEqual (Equal a -> a -> a -> Bool) -> Equal a -> a -> a -> Bool
forall a b. (a -> b) -> a -> b
$
   Equal Float
-> Equal Double
-> Equal (Complex Float)
-> Equal (Complex Double)
-> Equal a
forall a (f :: * -> *).
Floating a =>
f Float
-> f Double -> f (Complex Float) -> f (Complex Double) -> f a
Class.switchFloating ((Float -> Float -> Bool) -> Equal Float
forall a. (a -> a -> Bool) -> Equal a
Equal Float -> Float -> Bool
forall a. Eq a => a -> a -> Bool
(==)) ((Double -> Double -> Bool) -> Equal Double
forall a. (a -> a -> Bool) -> Equal a
Equal Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
(==)) ((Complex Float -> Complex Float -> Bool) -> Equal (Complex Float)
forall a. (a -> a -> Bool) -> Equal a
Equal Complex Float -> Complex Float -> Bool
forall a. Eq a => a -> a -> Bool
(==)) ((Complex Double -> Complex Double -> Bool)
-> Equal (Complex Double)
forall a. (a -> a -> Bool) -> Equal a
Equal Complex Double -> Complex Double -> Bool
forall a. Eq a => a -> a -> Bool
(==))


isZero :: Class.Floating a => a -> Bool
isZero :: a -> Bool
isZero =
   Flip (->) Bool a -> a -> Bool
forall (f :: * -> * -> *) b a. Flip f b a -> f a b
getFlip (Flip (->) Bool a -> a -> Bool) -> Flip (->) Bool a -> a -> Bool
forall a b. (a -> b) -> a -> b
$
   Flip (->) Bool Float
-> Flip (->) Bool Double
-> Flip (->) Bool (Complex Float)
-> Flip (->) Bool (Complex Double)
-> Flip (->) Bool a
forall a (f :: * -> *).
Floating a =>
f Float
-> f Double -> f (Complex Float) -> f (Complex Double) -> f a
Class.switchFloating
      ((Float -> Bool) -> Flip (->) Bool Float
forall (f :: * -> * -> *) b a. f a b -> Flip f b a
Flip (Float
0Float -> Float -> Bool
forall a. Eq a => a -> a -> Bool
==)) ((Double -> Bool) -> Flip (->) Bool Double
forall (f :: * -> * -> *) b a. f a b -> Flip f b a
Flip (Double
0Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
==))
      ((Complex Float -> Bool) -> Flip (->) Bool (Complex Float)
forall (f :: * -> * -> *) b a. f a b -> Flip f b a
Flip (Complex Float
0Complex Float -> Complex Float -> Bool
forall a. Eq a => a -> a -> Bool
==)) ((Complex Double -> Bool) -> Flip (->) Bool (Complex Double)
forall (f :: * -> * -> *) b a. f a b -> Flip f b a
Flip (Complex Double
0Complex Double -> Complex Double -> Bool
forall a. Eq a => a -> a -> Bool
==))


newtype FromReal a = FromReal {FromReal a -> RealOf a -> a
getFromReal :: RealOf a -> a}

fromReal :: (Class.Floating a) => RealOf a -> a
fromReal :: RealOf a -> a
fromReal =
   FromReal a -> RealOf a -> a
forall a. FromReal a -> RealOf a -> a
getFromReal (FromReal a -> RealOf a -> a) -> FromReal a -> RealOf a -> a
forall a b. (a -> b) -> a -> b
$
   FromReal Float
-> FromReal Double
-> FromReal (Complex Float)
-> FromReal (Complex Double)
-> FromReal a
forall a (f :: * -> *).
Floating a =>
f Float
-> f Double -> f (Complex Float) -> f (Complex Double) -> f a
Class.switchFloating
      ((RealOf Float -> Float) -> FromReal Float
forall a. (RealOf a -> a) -> FromReal a
FromReal RealOf Float -> Float
forall a. a -> a
id)
      ((RealOf Double -> Double) -> FromReal Double
forall a. (RealOf a -> a) -> FromReal a
FromReal RealOf Double -> Double
forall a. a -> a
id)
      ((RealOf (Complex Float) -> Complex Float)
-> FromReal (Complex Float)
forall a. (RealOf a -> a) -> FromReal a
FromReal (Float -> Float -> Complex Float
forall a. a -> a -> Complex a
:+Float
0))
      ((RealOf (Complex Double) -> Complex Double)
-> FromReal (Complex Double)
forall a. (RealOf a -> a) -> FromReal a
FromReal (Double -> Double -> Complex Double
forall a. a -> a -> Complex a
:+Double
0))

newtype ToComplex f a = ToComplex {ToComplex f a -> a -> ComplexOf a
getToComplex :: a -> ComplexOf a}

toComplex :: (Class.Floating a) => a -> ComplexOf a
toComplex :: a -> ComplexOf a
toComplex =
   ToComplex Any a -> a -> ComplexOf a
forall f a. ToComplex f a -> a -> ComplexOf a
getToComplex (ToComplex Any a -> a -> ComplexOf a)
-> ToComplex Any a -> a -> ComplexOf a
forall a b. (a -> b) -> a -> b
$
   ToComplex Any Float
-> ToComplex Any Double
-> ToComplex Any (Complex Float)
-> ToComplex Any (Complex Double)
-> ToComplex Any a
forall a (f :: * -> *).
Floating a =>
f Float
-> f Double -> f (Complex Float) -> f (Complex Double) -> f a
Class.switchFloating
      ((Float -> ComplexOf Float) -> ToComplex Any Float
forall f a. (a -> ComplexOf a) -> ToComplex f a
ToComplex (Float -> Float -> Complex Float
forall a. a -> a -> Complex a
:+Float
0))
      ((Double -> ComplexOf Double) -> ToComplex Any Double
forall f a. (a -> ComplexOf a) -> ToComplex f a
ToComplex (Double -> Double -> Complex Double
forall a. a -> a -> Complex a
:+Double
0))
      ((Complex Float -> ComplexOf (Complex Float))
-> ToComplex Any (Complex Float)
forall f a. (a -> ComplexOf a) -> ToComplex f a
ToComplex Complex Float -> ComplexOf (Complex Float)
forall a. a -> a
id)
      ((Complex Double -> ComplexOf (Complex Double))
-> ToComplex Any (Complex Double)
forall f a. (a -> ComplexOf a) -> ToComplex f a
ToComplex Complex Double -> ComplexOf (Complex Double)
forall a. a -> a
id)

newtype ToReal a = ToReal {ToReal a -> a -> RealOf a
getToReal :: a -> RealOf a}

realPart :: (Class.Floating a) => a -> RealOf a
realPart :: a -> RealOf a
realPart =
   ToReal a -> a -> RealOf a
forall a. ToReal a -> a -> RealOf a
getToReal (ToReal a -> a -> RealOf a) -> ToReal a -> a -> RealOf a
forall a b. (a -> b) -> a -> b
$
   ToReal Float
-> ToReal Double
-> ToReal (Complex Float)
-> ToReal (Complex Double)
-> ToReal a
forall a (f :: * -> *).
Floating a =>
f Float
-> f Double -> f (Complex Float) -> f (Complex Double) -> f a
Class.switchFloating
      ((Float -> RealOf Float) -> ToReal Float
forall a. (a -> RealOf a) -> ToReal a
ToReal Float -> RealOf Float
forall a. a -> a
id)
      ((Double -> RealOf Double) -> ToReal Double
forall a. (a -> RealOf a) -> ToReal a
ToReal Double -> RealOf Double
forall a. a -> a
id)
      ((Complex Float -> RealOf (Complex Float)) -> ToReal (Complex Float)
forall a. (a -> RealOf a) -> ToReal a
ToReal Complex Float -> RealOf (Complex Float)
forall a. Complex a -> a
Complex.realPart)
      ((Complex Double -> RealOf (Complex Double))
-> ToReal (Complex Double)
forall a. (a -> RealOf a) -> ToReal a
ToReal Complex Double -> RealOf (Complex Double)
forall a. Complex a -> a
Complex.realPart)

absolute :: (Class.Floating a) => a -> RealOf a
absolute :: a -> RealOf a
absolute =
   ToReal a -> a -> RealOf a
forall a. ToReal a -> a -> RealOf a
getToReal (ToReal a -> a -> RealOf a) -> ToReal a -> a -> RealOf a
forall a b. (a -> b) -> a -> b
$
   ToReal Float
-> ToReal Double
-> ToReal (Complex Float)
-> ToReal (Complex Double)
-> ToReal a
forall a (f :: * -> *).
Floating a =>
f Float
-> f Double -> f (Complex Float) -> f (Complex Double) -> f a
Class.switchFloating
      ((Float -> RealOf Float) -> ToReal Float
forall a. (a -> RealOf a) -> ToReal a
ToReal Float -> RealOf Float
forall a. Num a => a -> a
abs)
      ((Double -> RealOf Double) -> ToReal Double
forall a. (a -> RealOf a) -> ToReal a
ToReal Double -> RealOf Double
forall a. Num a => a -> a
abs)
      ((Complex Float -> RealOf (Complex Float)) -> ToReal (Complex Float)
forall a. (a -> RealOf a) -> ToReal a
ToReal Complex Float -> RealOf (Complex Float)
forall a. RealFloat a => Complex a -> a
Complex.magnitude)
      ((Complex Double -> RealOf (Complex Double))
-> ToReal (Complex Double)
forall a. (a -> RealOf a) -> ToReal a
ToReal Complex Double -> RealOf (Complex Double)
forall a. RealFloat a => Complex a -> a
Complex.magnitude)


norm1 :: (Class.Floating a) => a -> RealOf a
norm1 :: a -> RealOf a
norm1 =
   ToReal a -> a -> RealOf a
forall a. ToReal a -> a -> RealOf a
getToReal (ToReal a -> a -> RealOf a) -> ToReal a -> a -> RealOf a
forall a b. (a -> b) -> a -> b
$
   ToReal Float
-> ToReal Double
-> ToReal (Complex Float)
-> ToReal (Complex Double)
-> ToReal a
forall a (f :: * -> *).
Floating a =>
f Float
-> f Double -> f (Complex Float) -> f (Complex Double) -> f a
Class.switchFloating
      ((Float -> RealOf Float) -> ToReal Float
forall a. (a -> RealOf a) -> ToReal a
ToReal Float -> RealOf Float
forall a. Num a => a -> a
abs)
      ((Double -> RealOf Double) -> ToReal Double
forall a. (a -> RealOf a) -> ToReal a
ToReal Double -> RealOf Double
forall a. Num a => a -> a
abs)
      ((Complex Float -> RealOf (Complex Float)) -> ToReal (Complex Float)
forall a. (a -> RealOf a) -> ToReal a
ToReal Complex Float -> RealOf (Complex Float)
forall a. Real a => Complex a -> a
norm1Complex)
      ((Complex Double -> RealOf (Complex Double))
-> ToReal (Complex Double)
forall a. (a -> RealOf a) -> ToReal a
ToReal Complex Double -> RealOf (Complex Double)
forall a. Real a => Complex a -> a
norm1Complex)

norm1Complex :: (Class.Real a) => Complex a -> a
norm1Complex :: Complex a -> a
norm1Complex (a
r:+a
i) = a -> a
forall a. Num a => a -> a
abs a
r a -> a -> a
forall a. Num a => a -> a -> a
+ a -> a
forall a. Num a => a -> a
abs a
i


absoluteSquared :: (Class.Floating a) => a -> RealOf a
absoluteSquared :: a -> RealOf a
absoluteSquared =
   ToReal a -> a -> RealOf a
forall a. ToReal a -> a -> RealOf a
getToReal (ToReal a -> a -> RealOf a) -> ToReal a -> a -> RealOf a
forall a b. (a -> b) -> a -> b
$
   ToReal Float
-> ToReal Double
-> ToReal (Complex Float)
-> ToReal (Complex Double)
-> ToReal a
forall a (f :: * -> *).
Floating a =>
f Float
-> f Double -> f (Complex Float) -> f (Complex Double) -> f a
Class.switchFloating
      ((Float -> RealOf Float) -> ToReal Float
forall a. (a -> RealOf a) -> ToReal a
ToReal Float -> RealOf Float
forall a. Real a => a -> a
absoluteSquaredReal)
      ((Double -> RealOf Double) -> ToReal Double
forall a. (a -> RealOf a) -> ToReal a
ToReal Double -> RealOf Double
forall a. Real a => a -> a
absoluteSquaredReal)
      ((Complex Float -> RealOf (Complex Float)) -> ToReal (Complex Float)
forall a. (a -> RealOf a) -> ToReal a
ToReal Complex Float -> RealOf (Complex Float)
forall a. Real a => Complex a -> a
absoluteSquaredComplex)
      ((Complex Double -> RealOf (Complex Double))
-> ToReal (Complex Double)
forall a. (a -> RealOf a) -> ToReal a
ToReal Complex Double -> RealOf (Complex Double)
forall a. Real a => Complex a -> a
absoluteSquaredComplex)

absoluteSquaredReal :: (Class.Real a) => a -> a
absoluteSquaredReal :: a -> a
absoluteSquaredReal a
a = a
aa -> a -> a
forall a. Num a => a -> a -> a
*a
a

absoluteSquaredComplex :: (Class.Real a) => Complex a -> a
absoluteSquaredComplex :: Complex a -> a
absoluteSquaredComplex (a
r:+a
i) = a
ra -> a -> a
forall a. Num a => a -> a -> a
*a
ra -> a -> a
forall a. Num a => a -> a -> a
+a
ia -> a -> a
forall a. Num a => a -> a -> a
*a
i


conjugate :: (Class.Floating a) => a -> a
conjugate :: a -> a
conjugate =
   Endo a -> a -> a
forall a. Endo a -> a -> a
appEndo (Endo a -> a -> a) -> Endo a -> a -> a
forall a b. (a -> b) -> a -> b
$
   Endo Float
-> Endo Double
-> Endo (Complex Float)
-> Endo (Complex Double)
-> Endo a
forall a (f :: * -> *).
Floating a =>
f Float
-> f Double -> f (Complex Float) -> f (Complex Double) -> f a
Class.switchFloating
      ((Float -> Float) -> Endo Float
forall a. (a -> a) -> Endo a
Endo Float -> Float
forall a. a -> a
id) ((Double -> Double) -> Endo Double
forall a. (a -> a) -> Endo a
Endo Double -> Double
forall a. a -> a
id) ((Complex Float -> Complex Float) -> Endo (Complex Float)
forall a. (a -> a) -> Endo a
Endo Complex Float -> Complex Float
forall a. Num a => Complex a -> Complex a
Complex.conjugate) ((Complex Double -> Complex Double) -> Endo (Complex Double)
forall a. (a -> a) -> Endo a
Endo Complex Double -> Complex Double
forall a. Num a => Complex a -> Complex a
Complex.conjugate)