    {-# 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' :: forall e.
    RealElement e =>
    (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' :: forall e.
    RealElement e =>
    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' :: forall e. RealElement e => Vector e -> Vector (Complex e)
    comp' Vector e
    v = (Vector e, Vector e) -> Vector (Complex e)
    forall e.
    RealElement e =>
    (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' :: forall a b. Precision a b => Vector b -> Vector a
    single' = Vector b -> Vector a
    forall a b. Precision a b => Vector b -> Vector a
    double2FloatG
        double' :: forall a b. Precision a b => 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 :: forall e.
    RealElement e =>
    (Vector e, Vector e) -> Vector (Complex e)
    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 :: 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] = 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' :: forall e.
    RealElement e =>
    (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 e.
    RealElement e =>
    (Vector e, Vector e) -> Vector (Complex e)
    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 = (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 b c b' c'. (b -> c) -> (b' -> c') -> (b, b') -> (c, c')
    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 e.
    RealElement e =>
    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' :: forall e. RealElement e => 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 e. RealElement e => Vector e -> Vector (Complex e)
    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' = (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 a b. Precision a b => Vector b -> Vector a
    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' = (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 a b. Precision a b => Vector a -> Vector b
    forall (c :: * -> *) a b.
    (Complexable c, Precision a b) =>
    c a -> c b
    double'