{-# 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 = Vector Float -> Vector (Complex Float)
forall a.
(RealFloat a, Storable a) =>
Vector a -> Vector (Complex a)
asComplex (Vector Float -> Vector (Complex Float))
-> (Vector (Complex Double) -> Vector Float)
-> Vector (Complex Double)
-> Vector (Complex Float)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector Double -> Vector Float
double2FloatV (Vector Double -> Vector Float)
-> (Vector (Complex Double) -> Vector Double)
-> Vector (Complex Double)
-> Vector Float
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector (Complex Double) -> Vector Double
forall a.
(RealFloat a, Storable a) =>
Vector (Complex a) -> Vector a
asReal
    float2DoubleG :: Vector (Complex Float) -> Vector (Complex Double)
float2DoubleG = Vector Double -> Vector (Complex Double)
forall a.
(RealFloat a, Storable a) =>
Vector a -> Vector (Complex a)
asComplex (Vector Double -> Vector (Complex Double))
-> (Vector (Complex Float) -> Vector Double)
-> Vector (Complex Float)
-> Vector (Complex Double)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector Float -> Vector Double
float2DoubleV (Vector Float -> Vector Double)
-> (Vector (Complex Float) -> Vector Float)
-> Vector (Complex Float)
-> Vector Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector (Complex Float) -> Vector Float
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' :: (Vector e, Vector e) -> Vector (Complex e)
toComplex' = (Vector e, Vector e) -> Vector (Complex e)
forall e.
RealElement e =>
(Vector e, Vector e) -> Vector (Complex e)
toComplexV
    fromComplex' :: Vector (Complex e) -> (Vector e, Vector e)
fromComplex' = Vector (Complex e) -> (Vector e, Vector e)
forall e.
RealElement e =>
Vector (Complex e) -> (Vector e, Vector e)
fromComplexV
    comp' :: Vector e -> Vector (Complex e)
comp' Vector e
v = (Vector e, Vector e) -> Vector (Complex e)
forall (c :: * -> *) e.
(Complexable c, RealElement e) =>
(c e, c e) -> c (Complex e)
toComplex' (Vector e
v,e -> Int -> Vector e
forall a. Element a => a -> Int -> Vector a
constantD e
0 (Vector e -> Int
forall t. Storable t => Vector t -> Int
dim Vector e
v))
    single' :: Vector b -> Vector a
single' = Vector b -> Vector a
forall a b. Precision a b => Vector b -> Vector a
double2FloatG
    double' :: Vector a -> Vector b
double' = Vector a -> Vector b
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 :: (Vector a, Vector a) -> Vector (Complex a)
toComplexV (Vector a
r,Vector a
i) = Vector a -> Vector (Complex a)
forall a.
(RealFloat a, Storable a) =>
Vector a -> Vector (Complex a)
asComplex (Vector a -> Vector (Complex a)) -> Vector a -> Vector (Complex a)
forall a b. (a -> b) -> a -> b
$ Matrix a -> Vector a
forall t. Element t => Matrix t -> Vector t
flatten (Matrix a -> Vector a) -> Matrix a -> Vector a
forall a b. (a -> b) -> a -> b
$ [Vector a] -> Matrix a
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 :: Vector (Complex a) -> (Vector a, Vector a)
fromComplexV Vector (Complex a)
z = (Vector a
r,Vector a
i) where
    [Vector a
r,Vector a
i] = Matrix a -> [Vector a]
forall t. Element t => Matrix t -> [Vector t]
toColumns (Matrix a -> [Vector a]) -> Matrix a -> [Vector a]
forall a b. (a -> b) -> a -> b
$ Int -> Vector a -> Matrix a
forall t. Storable t => Int -> Vector t -> Matrix t
reshape Int
2 (Vector a -> Matrix a) -> Vector a -> Matrix a
forall a b. (a -> b) -> a -> b
$ Vector (Complex a) -> Vector a
forall a.
(RealFloat a, Storable a) =>
Vector (Complex a) -> Vector a
asReal Vector (Complex a)
z


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