{- | Fortran COMPLEX value representation.

A Fortran COMPLEX is simply two REALs of the same kind.
-}

module Language.Fortran.Repr.Value.Scalar.Complex where

import Language.Fortran.Repr.Value.Scalar.Common
import Language.Fortran.Repr.Type.Scalar.Real
import GHC.Float ( float2Double )

data FComplex (k :: FTReal) where
    FComplex8  :: Float  -> Float  -> FComplex 'FTReal4
    FComplex16 :: Double -> Double -> FComplex 'FTReal8
deriving stock instance Show (FComplex k)
deriving stock instance Eq   (FComplex k)
deriving stock instance Ord  (FComplex k) -- TODO

type SomeFComplex = SomeFKinded FTReal FComplex
deriving stock instance Show SomeFComplex
instance Eq SomeFComplex where
    (SomeFKinded FComplex fk
l) == :: SomeFComplex -> SomeFComplex -> Bool
== (SomeFKinded FComplex fk
r) = forall b r (kl :: FTReal) (kr :: FTReal).
(forall a. RealFloat a => a -> a -> b)
-> (b -> b -> r) -> FComplex kl -> FComplex kr -> r
fComplexBOp forall a. Eq a => a -> a -> Bool
(==) Bool -> Bool -> Bool
(&&) FComplex fk
l FComplex fk
r

fComplexBOp'
    :: (Float  -> Float  -> a)
    -> (a -> a -> r)
    -> (Double -> Double -> b)
    -> (b -> b -> r)
    -> FComplex kl -> FComplex kr -> r
fComplexBOp' :: forall a r b (kl :: FTReal) (kr :: FTReal).
(Float -> Float -> a)
-> (a -> a -> r)
-> (Double -> Double -> b)
-> (b -> b -> r)
-> FComplex kl
-> FComplex kr
-> r
fComplexBOp' Float -> Float -> a
k8f a -> a -> r
k8g Double -> Double -> b
k16f b -> b -> r
k16g FComplex kl
l FComplex kr
r =
    case (FComplex kl
l, FComplex kr
r) of
      (FComplex8  Float
lr Float
li, FComplex8  Float
rr Float
ri) -> a -> a -> r
k8g  (Float -> Float -> a
k8f  Float
lr Float
rr) (Float -> Float -> a
k8f  Float
li Float
ri)
      (FComplex16 Double
lr Double
li, FComplex16 Double
rr Double
ri) -> b -> b -> r
k16g (Double -> Double -> b
k16f Double
lr Double
rr) (Double -> Double -> b
k16f Double
li Double
ri)
      (FComplex8  Float
lr Float
li, FComplex16 Double
rr Double
ri) ->
        let lr' :: Double
lr' = Float -> Double
float2Double Float
lr
            li' :: Double
li' = Float -> Double
float2Double Float
li
        in  b -> b -> r
k16g (Double -> Double -> b
k16f Double
lr' Double
rr) (Double -> Double -> b
k16f Double
li' Double
ri)
      (FComplex16 Double
lr Double
li, FComplex8  Float
rr Float
ri) ->
        let rr' :: Double
rr' = Float -> Double
float2Double Float
rr
            ri' :: Double
ri' = Float -> Double
float2Double Float
ri
        in  b -> b -> r
k16g (Double -> Double -> b
k16f Double
lr Double
rr') (Double -> Double -> b
k16f Double
li Double
ri')

fComplexBOp
    :: (forall a. RealFloat a => a -> a -> b)
    -> (b -> b -> r)
    -> FComplex kl -> FComplex kr -> r
fComplexBOp :: forall b r (kl :: FTReal) (kr :: FTReal).
(forall a. RealFloat a => a -> a -> b)
-> (b -> b -> r) -> FComplex kl -> FComplex kr -> r
fComplexBOp forall a. RealFloat a => a -> a -> b
f b -> b -> r
g = forall a r b (kl :: FTReal) (kr :: FTReal).
(Float -> Float -> a)
-> (a -> a -> r)
-> (Double -> Double -> b)
-> (b -> b -> r)
-> FComplex kl
-> FComplex kr
-> r
fComplexBOp' forall a. RealFloat a => a -> a -> b
f b -> b -> r
g forall a. RealFloat a => a -> a -> b
f b -> b -> r
g