{-# LANGUAGE FlexibleContexts  #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs             #-}
{-# LANGUAGE TypeFamilies      #-}
-- |
-- Module      : Data.Array.Accelerate.Numeric.LinearAlgebra.Type
-- Copyright   : [2017..2020] Trevor L. McDonell
-- License     : BSD3
--
-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>
-- Stability   : experimental
-- Portability : non-portable (GHC extensions)
--

module Data.Array.Accelerate.Numeric.LinearAlgebra.Type (

  module Data.Array.Accelerate.Numeric.LinearAlgebra.Type,

) where

import Data.Array.Accelerate                                        as A
import Data.Array.Accelerate.Data.Complex                           as A
import Data.Array.Accelerate.Sugar.Elt
import Data.Primitive.Vec

import qualified Prelude                                            as P


-- For explicit dictionary reification, to recover the type the operation should
-- be performed at.
--
data NumericR s r where
  NumericRfloat32   :: NumericR Float Float
  NumericRfloat64   :: NumericR Double Double
  NumericRcomplex32 :: NumericR (Complex Float) (Vec2 Float)
  NumericRcomplex64 :: NumericR (Complex Double) (Vec2 Double)

class Num a => Numeric a where
  numericR :: NumericR a (EltR a)

instance Numeric Float where
  numericR :: NumericR Float (EltR Float)
numericR = NumericR Float Float
NumericR Float (EltR Float)
NumericRfloat32

instance Numeric Double where
  numericR :: NumericR Double (EltR Double)
numericR = NumericR Double Double
NumericR Double (EltR Double)
NumericRfloat64

instance Numeric (Complex Float) where
  numericR :: NumericR (Complex Float) (EltR (Complex Float))
numericR = NumericR (Complex Float) (EltR (Complex Float))
NumericR (Complex Float) (Vec2 Float)
NumericRcomplex32

instance Numeric (Complex Double) where
  numericR :: NumericR (Complex Double) (EltR (Complex Double))
numericR = NumericR (Complex Double) (EltR (Complex Double))
NumericR (Complex Double) (Vec2 Double)
NumericRcomplex64

-- class Numeric a => RealNumeric a
--
-- instance RealNumeric Float
-- instance RealNumeric Double

type family NumericBaseT t where
  NumericBaseT Float            = Float
  NumericBaseT Double           = Double
  NumericBaseT (Complex Float)  = Float
  NumericBaseT (Complex Double) = Double


-- | Orientation of the underlying data.
--
-- Accelerate arrays are naturally stored in row-major format.
--
data Orientation
  = R -- ^ row major
  | C -- ^ column major
  deriving (Orientation -> Orientation -> Bool
(Orientation -> Orientation -> Bool)
-> (Orientation -> Orientation -> Bool) -> Eq Orientation
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Orientation -> Orientation -> Bool
$c/= :: Orientation -> Orientation -> Bool
== :: Orientation -> Orientation -> Bool
$c== :: Orientation -> Orientation -> Bool
P.Eq, Int -> Orientation -> ShowS
[Orientation] -> ShowS
Orientation -> String
(Int -> Orientation -> ShowS)
-> (Orientation -> String)
-> ([Orientation] -> ShowS)
-> Show Orientation
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Orientation] -> ShowS
$cshowList :: [Orientation] -> ShowS
show :: Orientation -> String
$cshow :: Orientation -> String
showsPrec :: Int -> Orientation -> ShowS
$cshowsPrec :: Int -> Orientation -> ShowS
P.Show)

-- | Many operations allow you to implicitly transpose the arguments. For
-- a given input matrix @mat@ with dimensions @Z :. m :. n@ (that is; @m@ rows
-- and @n@ columns):
--
data Transpose
  -- | Leave the matrix as is.
  = N

  -- | Treat the matrix as implicitly transposed, with dimensions @Z :. n :. m@.
  -- Entry @Z :. j :. i@ is treated as actually being entry @Z :. i :. j@.
  | T

  -- | Implicitly transpose and conjugate the input matrix. For complex-valued
  -- matrices a given element @mat ! Z:.j:.i == x :+ y@ will be treated as
  -- actually being @mat ! Z:.i:.j == x :+ (-y)@.
  | H
  deriving (Transpose -> Transpose -> Bool
(Transpose -> Transpose -> Bool)
-> (Transpose -> Transpose -> Bool) -> Eq Transpose
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Transpose -> Transpose -> Bool
$c/= :: Transpose -> Transpose -> Bool
== :: Transpose -> Transpose -> Bool
$c== :: Transpose -> Transpose -> Bool
P.Eq, Int -> Transpose -> ShowS
[Transpose] -> ShowS
Transpose -> String
(Int -> Transpose -> ShowS)
-> (Transpose -> String)
-> ([Transpose] -> ShowS)
-> Show Transpose
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Transpose] -> ShowS
$cshowList :: [Transpose] -> ShowS
show :: Transpose -> String
$cshow :: Transpose -> String
showsPrec :: Int -> Transpose -> ShowS
$cshowsPrec :: Int -> Transpose -> ShowS
P.Show)