packages feed

algebraic-0.1.0.2: src/Math/Coordinate/Cartesian.hs

{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE OverlappingInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}

module Math.Coordinate.Cartesian where



import           Data.Array.Accelerate
import           Data.Array.Accelerate.Smart
import           Data.Array.Accelerate.Tuple
import           Data.Array.Accelerate.Array.Sugar
import           Data.Complex
import qualified Data.Foldable as F
import           Data.Typeable

import Control.Applicative

import Math.Coordinate.Coordinate (CoordConversion(..), ManualConversion(..), AutoConversion(..), convertCoord)
import Math.Space.Space           (Space2)

data Cartesian  = Cartesian deriving (Show)

data Point1 a   = Point1 !a deriving (Eq, Ord, Show, Read,Typeable)
data Point2 a   = Point2 !a !a deriving (Eq, Ord, Show, Read,Typeable)
data Point3 a   = Point3 !a !a !a deriving (Eq, Ord, Show, Read,Typeable)
data Point4 a   = Point4 !a !a !a !a deriving (Eq, Ord, Show, Read,Typeable)

toCartesian = convertCoord Cartesian

--------------------------------------------------------------------------------
-- Classes
--------------------------------------------------------------------------------

class CartesianCoord1 coord where
    x :: coord a -> a

class CartesianCoord1 coord => CartesianCoord2 coord where
    y :: coord a -> a

class CartesianCoord2 coord => CartesianCoord3 coord where
    z :: coord a -> a

class CartesianCoord3 coord => CartesianCoord4 coord where
    w :: coord a -> a

--------------------------------------------------------------------------------
-- Functions
--------------------------------------------------------------------------------
uncurry :: (a -> a -> b) -> Point2 a -> b
uncurry f (Point2 x y) = f x y

--------------------------------------------------------------------------------
-- Instances
--------------------------------------------------------------------------------

instance CartesianCoord1 Point1 where x (Point1 x) = x

instance CartesianCoord1 Point2 where x (Point2 x _) = x
instance CartesianCoord2 Point2 where y (Point2 _ y) = y

instance CartesianCoord1 Point3 where x (Point3 x _ _) = x
instance CartesianCoord2 Point3 where y (Point3 _ y _) = y
instance CartesianCoord3 Point3 where z (Point3 _ _ z) = z

instance CartesianCoord1 Point4 where x (Point4 x _ _ _) = x
instance CartesianCoord2 Point4 where y (Point4 _ y _ _) = y
instance CartesianCoord3 Point4 where z (Point4 _ _ z _) = z
instance CartesianCoord4 Point4 where w (Point4 _ _ _ w) = w


instance  ( CoordConversion ManualConversion Cartesian space a b
          , CoordConversion ManualConversion sys space b c) => 
          CoordConversion AutoConversion sys space a c where
    convertCoordBase _ coord space = (convertCoordBase ManualConversion coord space) . (convertCoordBase ManualConversion Cartesian space)


instance CoordConversion ManualConversion Cartesian space (Point2 a) (Point2 a) where
    convertCoordBase _ _ _ = id

--------------------------------------------------------------------------------
-- Point1
--------------------------------------------------------------------------------
instance Functor Point1 where
    fmap f (Point1 a) = Point1 (f a)

instance Applicative Point1 where
    pure a = Point1 a
    {-# INLINE pure #-}
    Point1 a <*> Point1 d = Point1 (a d)
    {-# INLINE (<*>) #-}

instance Num a => Num (Point1 a) where
    (+) = liftA2 (+)
    {-# INLINE (+) #-}
    (-) = liftA2 (-)
    {-# INLINE (-) #-}
    (*) = liftA2 (*)
    {-# INLINE (*) #-}
    negate = fmap negate
    {-# INLINE negate #-}
    abs = fmap abs
    {-# INLINE abs #-}
    signum = fmap signum
    {-# INLINE signum #-}
    fromInteger = pure . fromInteger
    {-# INLINE fromInteger #-}

instance Fractional a => Fractional (Point1 a) where
    recip = fmap recip
    {-# INLINE recip #-}
    (/) = liftA2 (/)
    {-# INLINE (/) #-}
    fromRational = pure . fromRational
    {-# INLINE fromRational #-}

type instance EltRepr (Point1 a) = EltRepr a
type instance EltRepr' (Point1 a) = EltRepr' a

instance Elt a => Elt (Point1 a) where
  eltType _ = eltType (undefined :: a)
  toElt = Point1 . toElt
  fromElt (Point1 a) = fromElt a

  eltType' _ = eltType' (undefined :: a)
  toElt' = Point1 . toElt'
  fromElt' (Point1 a) = fromElt' a

instance IsTuple (Point1 a) where
  type TupleRepr (Point1 a) = ((), a)
  fromTuple (Point1 x) = ((), x)
  toTuple ((), x) = Point1 x

instance (Lift Exp a, Elt (Plain a)) => Lift Exp (Point1 a) where
  type Plain (Point1 a) = Point1 (Plain a)
  lift (Point1 x) = Exp . Tuple $ NilTup `SnocTup` lift x

instance (Elt a, e ~ Exp a) => Unlift Exp (Point1 e) where
  unlift t = Point1 $ Exp $ ZeroTupIdx `Prj` t
--------------------------------------------------------------------------------
-- Point2
--------------------------------------------------------------------------------
instance Functor Point2 where
    fmap f (Point2 a b) = Point2 (f a) (f b)

instance Applicative Point2 where
    pure a = Point2 a a
    {-# INLINE pure #-}
    Point2 a b <*> Point2 d e = Point2 (a d) (b e)
    {-# INLINE (<*>) #-}

instance Num a => Num (Point2 a) where
    (+) = liftA2 (+)
    {-# INLINE (+) #-}
    (-) = liftA2 (-)
    {-# INLINE (-) #-}
    (*) = liftA2 (*)
    {-# INLINE (*) #-}
    negate = fmap negate
    {-# INLINE negate #-}
    abs = fmap abs
    {-# INLINE abs #-}
    signum = fmap signum
    {-# INLINE signum #-}
    fromInteger = pure . fromInteger
    {-# INLINE fromInteger #-}

instance Fractional a => Fractional (Point2 a) where
    recip = fmap recip
    {-# INLINE recip #-}
    (/) = liftA2 (/)
    {-# INLINE (/) #-}
    fromRational = pure . fromRational
    {-# INLINE fromRational #-}

type instance EltRepr (Point2 a)  = EltRepr (a, a)
type instance EltRepr' (Point2 a) = EltRepr' (a, a)

instance Elt a => Elt (Point2 a) where
  eltType _ = eltType (undefined :: (a,a))
  toElt p = case toElt p of
     (x, y) -> Point2 x y
  fromElt (Point2 x y) = fromElt (x, y)

  eltType' _ = eltType' (undefined :: (a,a))
  toElt' p = case toElt' p of
     (x, y) -> Point2 x y
  fromElt' (Point2 x y) = fromElt' (x, y)

instance IsTuple (Point2 a) where
  type TupleRepr (Point2 a) = TupleRepr (a,a)
  fromTuple (Point2 x y) = fromTuple (x,y)
  toTuple t = case toTuple t of
     (x, y) -> Point2 x y

instance (Lift Exp a, Elt (Plain a)) => Lift Exp (Point2 a) where
  type Plain (Point2 a) = Point2 (Plain a)
  --lift = Exp . Tuple . F.foldl SnocTup NilTup
  lift (Point2 x y) = Exp $ Tuple $ NilTup `SnocTup` lift x `SnocTup` lift y

instance (Elt a, e ~ Exp a) => Unlift Exp (Point2 e) where
  unlift t = Point2 (Exp $ SuccTupIdx ZeroTupIdx `Prj` t)
                (Exp $ ZeroTupIdx `Prj` t)

--------------------------------------------------------------------------------
-- Point3
--------------------------------------------------------------------------------
instance Functor Point3 where
    fmap f (Point3 a b c) = Point3 (f a) (f b) (f c)

instance Applicative Point3 where
    pure a = Point3 a a a
    {-# INLINE pure #-}
    Point3 a b c <*> Point3 d e f = Point3 (a d) (b e) (c f)
    {-# INLINE (<*>) #-}

instance Num a => Num (Point3 a) where
    (+) = liftA2 (+)
    {-# INLINE (+) #-}
    (-) = liftA2 (-)
    {-# INLINE (-) #-}
    (*) = liftA2 (*)
    {-# INLINE (*) #-}
    negate = fmap negate
    {-# INLINE negate #-}
    abs = fmap abs
    {-# INLINE abs #-}
    signum = fmap signum
    {-# INLINE signum #-}
    fromInteger = pure . fromInteger
    {-# INLINE fromInteger #-}

instance Fractional a => Fractional (Point3 a) where
    recip = fmap recip
    {-# INLINE recip #-}
    (/) = liftA2 (/)
    {-# INLINE (/) #-}
    fromRational = pure . fromRational
    {-# INLINE fromRational #-}

type instance EltRepr (Point3 a)  = EltRepr (a, a, a)
type instance EltRepr' (Point3 a) = EltRepr' (a, a, a)

instance Elt a => Elt (Point3 a) where
  eltType _ = eltType (undefined :: (a,a,a))
  toElt p = case toElt p of
     (x, y, z) -> Point3 x y z
  fromElt (Point3 x y z) = fromElt (x, y, z)

  eltType' _ = eltType' (undefined :: (a,a,a))
  toElt' p = case toElt' p of
     (x, y, z) -> Point3 x y z
  fromElt' (Point3 x y z) = fromElt' (x, y, z)

instance IsTuple (Point3 a) where
  type TupleRepr (Point3 a) = TupleRepr (a,a,a)
  fromTuple (Point3 x y z) = fromTuple (x,y,z)
  toTuple t = case toTuple t of
     (x, y, z) -> Point3 x y z

instance (Lift Exp a, Elt (Plain a)) => Lift Exp (Point3 a) where
  type Plain (Point3 a) = Point3 (Plain a)
  --lift = Exp . Tuple . F.foldl SnocTup NilTup
  lift (Point3 x y z) = Exp $ Tuple $ NilTup `SnocTup` lift x `SnocTup` lift y `SnocTup` lift z

instance (Elt a, e ~ Exp a) => Unlift Exp (Point3 e) where
  unlift t = Point3 (Exp $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Prj` t)
                (Exp $ SuccTupIdx ZeroTupIdx `Prj` t)
                (Exp $ ZeroTupIdx `Prj` t)

--------------------------------------------------------------------------------
-- Point4
--------------------------------------------------------------------------------
instance Functor Point4 where
    fmap f (Point4 a b c d) = Point4 (f a) (f b) (f c) (f d)

instance Applicative Point4 where
    pure a = Point4 a a a a
    {-# INLINE pure #-}
    Point4 a b c d <*> Point4 e f g h = Point4 (a e) (b f) (c g) (d h)
    {-# INLINE (<*>) #-}

instance Num a => Num (Point4 a) where
    (+) = liftA2 (+)
    {-# INLINE (+) #-}
    (-) = liftA2 (-)
    {-# INLINE (-) #-}
    (*) = liftA2 (*)
    {-# INLINE (*) #-}
    negate = fmap negate
    {-# INLINE negate #-}
    abs = fmap abs
    {-# INLINE abs #-}
    signum = fmap signum
    {-# INLINE signum #-}
    fromInteger = pure . fromInteger
    {-# INLINE fromInteger #-}

instance Fractional a => Fractional (Point4 a) where
    recip = fmap recip
    {-# INLINE recip #-}
    (/) = liftA2 (/)
    {-# INLINE (/) #-}
    fromRational = pure . fromRational
    {-# INLINE fromRational #-}

type instance EltRepr (Point4 a)  = EltRepr (a, a, a, a)
type instance EltRepr' (Point4 a) = EltRepr' (a, a, a, a)

instance Elt a => Elt (Point4 a) where
  eltType _ = eltType (undefined :: (a,a,a,a))
  toElt p = case toElt p of
     (x, y, z, w) -> Point4 x y z w
  fromElt (Point4 x y z w) = fromElt (x, y, z, w)

  eltType' _ = eltType' (undefined :: (a,a,a,a))
  toElt' p = case toElt' p of
     (x, y, z, w) -> Point4 x y z w
  fromElt' (Point4 x y z w) = fromElt' (x, y, z, w)

instance IsTuple (Point4 a) where
  type TupleRepr (Point4 a) = TupleRepr (a,a,a,a)
  fromTuple (Point4 x y z w) = fromTuple (x,y,z,w)
  toTuple t = case toTuple t of
     (x, y, z, w) -> Point4 x y z w

instance (Lift Exp a, Elt (Plain a)) => Lift Exp (Point4 a) where
  type Plain (Point4 a) = Point4 (Plain a)
  --  lift = Exp . Tuple . F.foldl SnocTup NilTup
  lift (Point4 x y z w) = Exp $ Tuple $ NilTup `SnocTup`
                      lift x `SnocTup`
                      lift y `SnocTup`
                      lift z `SnocTup`
                      lift w

instance (Elt a, e ~ Exp a) => Unlift Exp (Point4 e) where
  unlift t = Point4 (Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Prj` t)
                (Exp $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Prj` t)
                (Exp $ SuccTupIdx ZeroTupIdx `Prj` t)
                (Exp $ ZeroTupIdx `Prj` t)