{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}

-----------------------------------------------------------------------------
-- |
-- Module      :  Numeric.Conversion
-- Copyright   :  (c) Alberto Ruiz 2010
-- License     :  BSD3
-- Maintainer  :  Alberto Ruiz
-- Stability   :  provisional
--
-- Conversion routines
--
-----------------------------------------------------------------------------


module Internal.Conversion (
    Complexable(..), RealElement,
    module Data.Complex
) where

import Internal.Vector
import Internal.Matrix
import Internal.Vectorized
import Data.Complex
import Control.Arrow((***))

-------------------------------------------------------------------

-- | Supported single-double precision type pairs
class (Element s, Element d) => Precision s d | s -> d, d -> s where
    double2FloatG :: Vector d -> Vector s
    float2DoubleG :: Vector s -> Vector d

instance Precision Float Double where
    double2FloatG :: Vector Double -> Vector Float
double2FloatG = Vector Double -> Vector Float
double2FloatV
    float2DoubleG :: Vector Float -> Vector Double
float2DoubleG = Vector Float -> Vector Double
float2DoubleV

instance Precision (Complex Float) (Complex Double) where
    double2FloatG :: Vector (Complex Double) -> Vector (Complex Float)
double2FloatG = forall a.
(RealFloat a, Storable a) =>
Vector a -> Vector (Complex a)
asComplex forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector Double -> Vector Float
double2FloatV forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a.
(RealFloat a, Storable a) =>
Vector (Complex a) -> Vector a
asReal
    float2DoubleG :: Vector (Complex Float) -> Vector (Complex Double)
float2DoubleG = forall a.
(RealFloat a, Storable a) =>
Vector a -> Vector (Complex a)
asComplex forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector Float -> Vector Double
float2DoubleV forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a.
(RealFloat a, Storable a) =>
Vector (Complex a) -> Vector a
asReal

instance Precision I Z where
    double2FloatG :: Vector Z -> Vector I
double2FloatG = Vector Z -> Vector I
long2intV
    float2DoubleG :: Vector I -> Vector Z
float2DoubleG = Vector I -> Vector Z
int2longV


-- | Supported real types
class (Element t, Element (Complex t), RealFloat t)
    => RealElement t

instance RealElement Double
instance RealElement Float


-- | Structures that may contain complex numbers
class Complexable c where
    toComplex'   :: (RealElement e) => (c e, c e) -> c (Complex e)
    fromComplex' :: (RealElement e) => c (Complex e) -> (c e, c e)
    comp'        :: (RealElement e) => c e -> c (Complex e)
    single'      :: Precision a b => c b -> c a
    double'      :: Precision a b => c a -> c b


instance Complexable Vector where
    toComplex' :: forall e.
RealElement e =>
(Vector e, Vector e) -> Vector (Complex e)
toComplex' = forall e.
RealElement e =>
(Vector e, Vector e) -> Vector (Complex e)
toComplexV
    fromComplex' :: forall e.
RealElement e =>
Vector (Complex e) -> (Vector e, Vector e)
fromComplex' = forall e.
RealElement e =>
Vector (Complex e) -> (Vector e, Vector e)
fromComplexV
    comp' :: forall e. RealElement e => Vector e -> Vector (Complex e)
comp' Vector e
v = forall (c :: * -> *) e.
(Complexable c, RealElement e) =>
(c e, c e) -> c (Complex e)
toComplex' (Vector e
v,forall a. Element a => a -> Int -> Vector a
constantD e
0 (forall t. Storable t => Vector t -> Int
dim Vector e
v))
    single' :: forall a b. Precision a b => Vector b -> Vector a
single' = forall a b. Precision a b => Vector b -> Vector a
double2FloatG
    double' :: forall a b. Precision a b => Vector a -> Vector b
double' = forall a b. Precision a b => Vector a -> Vector b
float2DoubleG


-- | creates a complex vector from vectors with real and imaginary parts
toComplexV :: (RealElement a) => (Vector a, Vector a) ->  Vector (Complex a)
toComplexV :: forall e.
RealElement e =>
(Vector e, Vector e) -> Vector (Complex e)
toComplexV (Vector a
r,Vector a
i) = forall a.
(RealFloat a, Storable a) =>
Vector a -> Vector (Complex a)
asComplex forall a b. (a -> b) -> a -> b
$ forall t. Element t => Matrix t -> Vector t
flatten forall a b. (a -> b) -> a -> b
$ forall t. Element t => [Vector t] -> Matrix t
fromColumns [Vector a
r,Vector a
i]

-- | the inverse of 'toComplex'
fromComplexV :: (RealElement a) => Vector (Complex a) -> (Vector a, Vector a)
fromComplexV :: forall e.
RealElement e =>
Vector (Complex e) -> (Vector e, Vector e)
fromComplexV Vector (Complex a)
z = (Vector a
r,Vector a
i) where
    [Vector a
r,Vector a
i] = forall t. Element t => Matrix t -> [Vector t]
toColumns forall a b. (a -> b) -> a -> b
$ forall t. Storable t => Int -> Vector t -> Matrix t
reshape Int
2 forall a b. (a -> b) -> a -> b
$ forall a.
(RealFloat a, Storable a) =>
Vector (Complex a) -> Vector a
asReal Vector (Complex a)
z


instance Complexable Matrix where
    toComplex' :: forall e.
RealElement e =>
(Matrix e, Matrix e) -> Matrix (Complex e)
toComplex' = forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry forall a b. (a -> b) -> a -> b
$ forall t a b.
(Element t, Element a, Element b) =>
(Vector a -> Vector b -> Vector t)
-> Matrix a -> Matrix b -> Matrix t
liftMatrix2 forall a b. (a -> b) -> a -> b
$ forall a b c. ((a, b) -> c) -> a -> b -> c
curry forall (c :: * -> *) e.
(Complexable c, RealElement e) =>
(c e, c e) -> c (Complex e)
toComplex'
    fromComplex' :: forall e.
RealElement e =>
Matrix (Complex e) -> (Matrix e, Matrix e)
fromComplex' Matrix (Complex e)
z = (forall t. Storable t => Int -> Vector t -> Matrix t
reshape Int
c forall (a :: * -> * -> *) b c b' c'.
Arrow a =>
a b c -> a b' c' -> a (b, b') (c, c')
*** forall t. Storable t => Int -> Vector t -> Matrix t
reshape Int
c) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (c :: * -> *) e.
(Complexable c, RealElement e) =>
c (Complex e) -> (c e, c e)
fromComplex' forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall t. Element t => Matrix t -> Vector t
flatten forall a b. (a -> b) -> a -> b
$ Matrix (Complex e)
z
        where c :: Int
c = forall t. Matrix t -> Int
cols Matrix (Complex e)
z
    comp' :: forall e. RealElement e => Matrix e -> Matrix (Complex e)
comp' = forall a b.
(Element a, Element b) =>
(Vector a -> Vector b) -> Matrix a -> Matrix b
liftMatrix forall (c :: * -> *) e.
(Complexable c, RealElement e) =>
c e -> c (Complex e)
comp'
    single' :: forall a b. Precision a b => Matrix b -> Matrix a
single' = forall a b.
(Element a, Element b) =>
(Vector a -> Vector b) -> Matrix a -> Matrix b
liftMatrix forall (c :: * -> *) a b.
(Complexable c, Precision a b) =>
c b -> c a
single'
    double' :: forall a b. Precision a b => Matrix a -> Matrix b
double' = forall a b.
(Element a, Element b) =>
(Vector a -> Vector b) -> Matrix a -> Matrix b
liftMatrix forall (c :: * -> *) a b.
(Complexable c, Precision a b) =>
c a -> c b
double'