{-# LANGUAGE PostfixOperators #-}
{-# OPTIONS_HADDOCK hide #-}

module ForSyDe.Atom.MoC.CT.Interface where

import ForSyDe.Atom.MoC ((-.-), (-*-))
import ForSyDe.Atom.MoC.CT.Core as CT
import ForSyDe.Atom.MoC.DE.Core as DE
import ForSyDe.Atom.MoC.DE.Interface (toCT1)
import ForSyDe.Atom.MoC.Stream (Stream(..))
import ForSyDe.Atom.MoC.Time (Time(..))
import qualified ForSyDe.Atom.Skel.Vector as V (
  Vector, zipx, unzipx, fanout, unit, length, vector)
import ForSyDe.Atom.Utility.Tuple (($$),($$$),($$$$))

------- DOCTEST SETUP -------

-- $setup
-- >>> import ForSyDe.Atom.MoC.Stream (takeS)
-- >>> import ForSyDe.Atom.MoC.DE.Lib as DE
-- >>> import ForSyDe.Atom.MoC.CT.Lib as CT
-- >>> import qualified Data.Number.FixedFunctions as RatF
-- >>> let pi'  = realToFrac pi
-- >>> let sin' = RatF.sin 0.001
-- >>> let cos' = RatF.cos 0.001


------- MoC INTERFACES -------

-- | Translates a (set of) 'ForSyDe.Atom.MoC.CT.CT' signal(s) into
-- 'ForSyDe.Atom.MoC.DE.DE' semantics without loss of information. In
-- 'ForSyDe.Atom.MoC.DE.DE', the abstract function of time inferred by
-- the 'ForSyDe.Atom.MoC.CT.CT' event loses its abstraction and it is
-- "dropped" to explicit form, under a lower layer. In other words the
-- implicit time semantics are lost, the carried value simply becoming
-- an ordinary function.
--
-- Constructors: @toDE[1-4]@.
--
-- <<fig/moc-ct-tode.png>>
toDE1 :: (Num ts, Ord ts, Eq ts, Num tm, Ord tm) 
      => CT.SignalBase ts tm a
      -> DE.SignalBase ts (tm -> a)
toDE2 :: (Num ts, Ord ts, Eq ts, Num tm, Ord tm) 
      => (CT.SignalBase ts tm a, CT.SignalBase ts tm b)
      -> (DE.SignalBase ts (tm -> a), DE.SignalBase ts (tm -> b))
toDE3 :: (Num ts, Ord ts, Eq ts, Num tm, Ord tm) 
      => (CT.SignalBase ts tm a, CT.SignalBase ts tm b, CT.SignalBase ts tm c)
      -> (DE.SignalBase ts (tm -> a), DE.SignalBase ts (tm -> b),
          DE.SignalBase ts (tm -> c))
toDE4 :: (Num ts, Ord ts, Eq ts, Num tm, Ord tm) 
      => (CT.SignalBase ts tm a, CT.SignalBase ts tm b,
          CT.SignalBase ts tm c, CT.SignalBase ts tm d)
      -> (DE.SignalBase ts (tm -> a), DE.SignalBase ts (tm -> b),
          DE.SignalBase ts (tm -> c), DE.SignalBase ts (tm -> d))

toDE1 :: SignalBase ts tm a -> SignalBase ts (tm -> a)
toDE1 = (CT ts tm a -> DE ts (tm -> a))
-> SignalBase ts tm a -> SignalBase ts (tm -> a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(CT ts :: ts
ts p :: tm
p f :: tm -> a
f) -> ts -> (tm -> a) -> DE ts (tm -> a)
forall t a. (Num t, Ord t, Eq t) => t -> a -> DE t a
DE ts
ts (\t :: tm
t -> tm -> a
f (tm
t tm -> tm -> tm
forall a. Num a => a -> a -> a
+ tm
p)))
toDE2 :: (SignalBase ts tm a, SignalBase ts tm b)
-> (SignalBase ts (tm -> a), SignalBase ts (tm -> b))
toDE2 = (SignalBase ts tm a -> SignalBase ts (tm -> a),
 SignalBase ts tm b -> SignalBase ts (tm -> b))
-> (SignalBase ts tm a, SignalBase ts tm b)
-> (SignalBase ts (tm -> a), SignalBase ts (tm -> b))
forall a1 b1 a2 b2. (a1 -> b1, a2 -> b2) -> (a1, a2) -> (b1, b2)
($$) (SignalBase ts tm a -> SignalBase ts (tm -> a)
forall ts tm a.
(Num ts, Ord ts, Eq ts, Num tm, Ord tm) =>
SignalBase ts tm a -> SignalBase ts (tm -> a)
toDE1, SignalBase ts tm b -> SignalBase ts (tm -> b)
forall ts tm a.
(Num ts, Ord ts, Eq ts, Num tm, Ord tm) =>
SignalBase ts tm a -> SignalBase ts (tm -> a)
toDE1)
toDE3 :: (SignalBase ts tm a, SignalBase ts tm b, SignalBase ts tm c)
-> (SignalBase ts (tm -> a), SignalBase ts (tm -> b),
    SignalBase ts (tm -> c))
toDE3 = (SignalBase ts tm a -> SignalBase ts (tm -> a),
 SignalBase ts tm b -> SignalBase ts (tm -> b),
 SignalBase ts tm c -> SignalBase ts (tm -> c))
-> (SignalBase ts tm a, SignalBase ts tm b, SignalBase ts tm c)
-> (SignalBase ts (tm -> a), SignalBase ts (tm -> b),
    SignalBase ts (tm -> c))
forall t1 a t2 b t3 c.
(t1 -> a, t2 -> b, t3 -> c) -> (t1, t2, t3) -> (a, b, c)
($$$) (SignalBase ts tm a -> SignalBase ts (tm -> a)
forall ts tm a.
(Num ts, Ord ts, Eq ts, Num tm, Ord tm) =>
SignalBase ts tm a -> SignalBase ts (tm -> a)
toDE1, SignalBase ts tm b -> SignalBase ts (tm -> b)
forall ts tm a.
(Num ts, Ord ts, Eq ts, Num tm, Ord tm) =>
SignalBase ts tm a -> SignalBase ts (tm -> a)
toDE1, SignalBase ts tm c -> SignalBase ts (tm -> c)
forall ts tm a.
(Num ts, Ord ts, Eq ts, Num tm, Ord tm) =>
SignalBase ts tm a -> SignalBase ts (tm -> a)
toDE1)
toDE4 :: (SignalBase ts tm a, SignalBase ts tm b, SignalBase ts tm c,
 SignalBase ts tm d)
-> (SignalBase ts (tm -> a), SignalBase ts (tm -> b),
    SignalBase ts (tm -> c), SignalBase ts (tm -> d))
toDE4 = (SignalBase ts tm a -> SignalBase ts (tm -> a),
 SignalBase ts tm b -> SignalBase ts (tm -> b),
 SignalBase ts tm c -> SignalBase ts (tm -> c),
 SignalBase ts tm d -> SignalBase ts (tm -> d))
-> (SignalBase ts tm a, SignalBase ts tm b, SignalBase ts tm c,
    SignalBase ts tm d)
-> (SignalBase ts (tm -> a), SignalBase ts (tm -> b),
    SignalBase ts (tm -> c), SignalBase ts (tm -> d))
forall t1 a t2 b t3 c t4 d.
(t1 -> a, t2 -> b, t3 -> c, t4 -> d)
-> (t1, t2, t3, t4) -> (a, b, c, d)
($$$$) (SignalBase ts tm a -> SignalBase ts (tm -> a)
forall ts tm a.
(Num ts, Ord ts, Eq ts, Num tm, Ord tm) =>
SignalBase ts tm a -> SignalBase ts (tm -> a)
toDE1, SignalBase ts tm b -> SignalBase ts (tm -> b)
forall ts tm a.
(Num ts, Ord ts, Eq ts, Num tm, Ord tm) =>
SignalBase ts tm a -> SignalBase ts (tm -> a)
toDE1, SignalBase ts tm c -> SignalBase ts (tm -> c)
forall ts tm a.
(Num ts, Ord ts, Eq ts, Num tm, Ord tm) =>
SignalBase ts tm a -> SignalBase ts (tm -> a)
toDE1, SignalBase ts tm d -> SignalBase ts (tm -> d)
forall ts tm a.
(Num ts, Ord ts, Eq ts, Num tm, Ord tm) =>
SignalBase ts tm a -> SignalBase ts (tm -> a)
toDE1)

-- | Synchronizes a (set of) 'ForSyDe.Atom.MoC.CT.CT' signal(s) with a
-- 'ForSyDe.Atom.MoC.DE.DE' carrier which holds the timestamps at
-- which the CT signal must be sampled, and outputs the respective
-- (set of) 'ForSyDe.Atom.MoC.DE.DE' signal(s).
--
-- Constructors: @sampDE[1-4]@.
--
-- >>> let s = CT.infinite (fromRational . sin')
-- >>> let c = DE.generate1 id (pi'/2, 1)
-- >>> takeS 6 $ sampDE1 c s
-- {0.0@0.0,1.0@1.5707963267948966,1.2246489323228883e-16@3.141592653589793,-1.0@4.71238898038469,0.0@6.283185307179586,1.0@7.853981633974483}

--
-- <<fig/moc-ct-sampde.png>>
sampDE2 :: (Num ts, Real ts, Ord ts, Eq ts, Num tm, Fractional tm, Ord tm) 
        => DE.SignalBase ts t -- ^ 'ForSyDe.Atom.MoC.DE.DE' timestamp carrier 
        -> CT.SignalBase ts tm a -- ^ 'ForSyDe.Atom.MoC.CT.CT' input
        -> CT.SignalBase ts tm b -- ^ 'ForSyDe.Atom.MoC.CT.CT' input
        -> (DE.SignalBase ts a, DE.SignalBase ts b) -- ^ 'ForSyDe.Atom.MoC.DE.DE' outputs
sampDE1 :: (Num ts, Real ts, Ord ts, Eq ts, Num tm, Fractional tm, Ord tm) 
        => DE.SignalBase ts t
        -> CT.SignalBase ts tm a
        -> DE.SignalBase ts a
sampDE3 :: (Num ts, Real ts, Ord ts, Eq ts, Num tm, Fractional tm, Ord tm) 
        => DE.SignalBase ts t
        -> CT.SignalBase ts tm a -> CT.SignalBase ts tm b -> CT.SignalBase ts tm c
        -> (DE.SignalBase ts a, DE.SignalBase ts b, DE.SignalBase ts c)
sampDE4 :: (Num ts, Real ts, Ord ts, Eq ts, Num tm, Fractional tm, Ord tm) 
        => DE.SignalBase ts t
        -> CT.SignalBase ts tm a -> CT.SignalBase ts tm b -> CT.SignalBase ts tm c
        -> CT.SignalBase ts tm d
        -> (DE.SignalBase ts a, DE.SignalBase ts b, DE.SignalBase ts c,
            DE.SignalBase ts d)

sampDE1 :: SignalBase ts t -> SignalBase ts tm a -> SignalBase ts a
sampDE1 carrier :: SignalBase ts t
carrier = (CT ts tm a -> DE ts a) -> SignalBase ts tm a -> SignalBase ts a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap CT ts tm a -> DE ts a
forall timestamp time a.
(Real timestamp, Fractional time) =>
CT timestamp time a -> DE timestamp a
evalEvent (SignalBase ts tm a -> SignalBase ts a)
-> (SignalBase ts tm a -> SignalBase ts tm a)
-> SignalBase ts tm a
-> SignalBase ts a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SignalBase ts t -> SignalBase ts tm a -> SignalBase ts tm a
forall t time a a.
(Real t, Fractional time, Ord time) =>
Stream (DE t a) -> Stream (CT t time a) -> Stream (CT t time a)
sync SignalBase ts t
carrier
  where evalEvent :: CT timestamp time a -> DE timestamp a
evalEvent e :: CT timestamp time a
e@(CT ts :: timestamp
ts _ _) = timestamp -> a -> DE timestamp a
forall t a. (Num t, Ord t, Eq t) => t -> a -> DE t a
DE.DE timestamp
ts (timestamp -> CT timestamp time a -> a
forall p1 time timestamp p2.
(Real p1, Fractional time) =>
p1 -> CT timestamp time p2 -> p2
CT.evalTs timestamp
ts CT timestamp time a
e)
        sync :: Stream (DE t a) -> Stream (CT t time a) -> Stream (CT t time a)
sync c :: Stream (DE t a)
c s :: Stream (CT t time a)
s = (\_ x :: a
x -> a
x) Fun (CT t time) () (a -> a)
-> Stream (CT t time ()) -> Stream (CT t time (a -> a))
forall (e :: * -> *) a b.
MoC e =>
Fun e a b -> Stream (e a) -> Stream (e b)
-.- Stream (DE t (time -> ())) -> Stream (CT t time ())
forall (f :: * -> *) time t a.
(Functor f, Num time) =>
f (DE t (time -> a)) -> f (CT t time a)
toCT1 (((time -> ()) -> a -> time -> ()
forall a b. a -> b -> a
const ((time -> ()) -> a -> time -> ())
-> (() -> time -> ()) -> () -> a -> time -> ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. () -> time -> ()
forall a b. a -> b -> a
const) () Fun (DE t) a (time -> ())
-> Stream (DE t a) -> Stream (DE t (time -> ()))
forall (e :: * -> *) a b.
MoC e =>
Fun e a b -> Stream (e a) -> Stream (e b)
-.- Stream (DE t a)
c) Stream (CT t time (Fun (CT t time) a a))
-> Stream (CT t time a) -> Stream (CT t time a)
forall (e :: * -> *) a b.
MoC e =>
Stream (e (Fun e a b)) -> Stream (e a) -> Stream (e b)
-*- Stream (CT t time a)
s
sampDE2 :: SignalBase ts t
-> SignalBase ts tm a
-> SignalBase ts tm b
-> (SignalBase ts a, SignalBase ts b)
sampDE2 c :: SignalBase ts t
c s1 :: SignalBase ts tm a
s1 s2 :: SignalBase ts tm b
s2       = (SignalBase ts t -> SignalBase ts tm a -> SignalBase ts a
forall ts tm t a.
(Num ts, Real ts, Ord ts, Eq ts, Num tm, Fractional tm, Ord tm) =>
SignalBase ts t -> SignalBase ts tm a -> SignalBase ts a
sampDE1 SignalBase ts t
c SignalBase ts tm a
s1, SignalBase ts t -> SignalBase ts tm b -> SignalBase ts b
forall ts tm t a.
(Num ts, Real ts, Ord ts, Eq ts, Num tm, Fractional tm, Ord tm) =>
SignalBase ts t -> SignalBase ts tm a -> SignalBase ts a
sampDE1 SignalBase ts t
c SignalBase ts tm b
s2)
sampDE3 :: SignalBase ts t
-> SignalBase ts tm a
-> SignalBase ts tm b
-> SignalBase ts tm c
-> (SignalBase ts a, SignalBase ts b, SignalBase ts c)
sampDE3 c :: SignalBase ts t
c s1 :: SignalBase ts tm a
s1 s2 :: SignalBase ts tm b
s2 s3 :: SignalBase ts tm c
s3    = (SignalBase ts t -> SignalBase ts tm a -> SignalBase ts a
forall ts tm t a.
(Num ts, Real ts, Ord ts, Eq ts, Num tm, Fractional tm, Ord tm) =>
SignalBase ts t -> SignalBase ts tm a -> SignalBase ts a
sampDE1 SignalBase ts t
c SignalBase ts tm a
s1, SignalBase ts t -> SignalBase ts tm b -> SignalBase ts b
forall ts tm t a.
(Num ts, Real ts, Ord ts, Eq ts, Num tm, Fractional tm, Ord tm) =>
SignalBase ts t -> SignalBase ts tm a -> SignalBase ts a
sampDE1 SignalBase ts t
c SignalBase ts tm b
s2, SignalBase ts t -> SignalBase ts tm c -> SignalBase ts c
forall ts tm t a.
(Num ts, Real ts, Ord ts, Eq ts, Num tm, Fractional tm, Ord tm) =>
SignalBase ts t -> SignalBase ts tm a -> SignalBase ts a
sampDE1 SignalBase ts t
c SignalBase ts tm c
s3) 
sampDE4 :: SignalBase ts t
-> SignalBase ts tm a
-> SignalBase ts tm b
-> SignalBase ts tm c
-> SignalBase ts tm d
-> (SignalBase ts a, SignalBase ts b, SignalBase ts c,
    SignalBase ts d)
sampDE4 c :: SignalBase ts t
c s1 :: SignalBase ts tm a
s1 s2 :: SignalBase ts tm b
s2 s3 :: SignalBase ts tm c
s3 s4 :: SignalBase ts tm d
s4 = (SignalBase ts t -> SignalBase ts tm a -> SignalBase ts a
forall ts tm t a.
(Num ts, Real ts, Ord ts, Eq ts, Num tm, Fractional tm, Ord tm) =>
SignalBase ts t -> SignalBase ts tm a -> SignalBase ts a
sampDE1 SignalBase ts t
c SignalBase ts tm a
s1, SignalBase ts t -> SignalBase ts tm b -> SignalBase ts b
forall ts tm t a.
(Num ts, Real ts, Ord ts, Eq ts, Num tm, Fractional tm, Ord tm) =>
SignalBase ts t -> SignalBase ts tm a -> SignalBase ts a
sampDE1 SignalBase ts t
c SignalBase ts tm b
s2, SignalBase ts t -> SignalBase ts tm c -> SignalBase ts c
forall ts tm t a.
(Num ts, Real ts, Ord ts, Eq ts, Num tm, Fractional tm, Ord tm) =>
SignalBase ts t -> SignalBase ts tm a -> SignalBase ts a
sampDE1 SignalBase ts t
c SignalBase ts tm c
s3, SignalBase ts t -> SignalBase ts tm d -> SignalBase ts d
forall ts tm t a.
(Num ts, Real ts, Ord ts, Eq ts, Num tm, Fractional tm, Ord tm) =>
SignalBase ts t -> SignalBase ts tm a -> SignalBase ts a
sampDE1 SignalBase ts t
c SignalBase ts tm d
s4)

-- Towards skeleton layer

-- | Synchronizes all the signals contained by a vector and zips them
-- into one signal of vectors. It instantiates the
-- 'ForSyDe.Atom.Skel.Vector.zipx' skeleton.
--
-- >>> let s1 = CT.signal [(0,const 1), (2,const 2), (6,const 3)]
-- >>> let s2 = CT.signal [(0,const 1), (2,const 2), (4,const 3)]
-- >>> let v1 = V.vector [s1,s1,s2,s2]
-- >>> zipx v1
-- {<1,1,1,1>@0,<2,2,2,2>@2,<2,2,3,3>@4,<3,3,3,3>@6}
--
-- See 'ForSyDe.Atom.MoC.DE.zipx' from the "ForSyDe.Atom.MoC.DE"
-- library for a comprehensive visual example.
zipx :: (Num ts, Real ts, Ord ts, Eq ts, Num tm, Fractional tm, Ord tm) 
     => V.Vector (CT.SignalBase ts tm a) -> CT.SignalBase ts tm (V.Vector a)
zipx :: Vector (SignalBase ts tm a) -> SignalBase ts tm (Vector a)
zipx = Vector
  ((Vector a -> Vector a -> Vector a)
   -> Fun
        (CT ts tm)
        (Vector a)
        (Fun (CT ts tm) (Vector a) (Ret (CT ts tm) (Vector a))))
-> Vector (SignalBase ts tm a) -> SignalBase ts tm (Vector a)
forall (e :: * -> *) a.
MoC e =>
Vector
  ((Vector a -> Vector a -> Vector a)
   -> Fun e (Vector a) (Fun e (Vector a) (Ret e (Vector a))))
-> Vector (Stream (e a)) -> Stream (e (Vector a))
V.zipx (((Vector a -> Vector a -> Vector a)
 -> Vector a -> Vector a -> Vector a)
-> Vector
     ((Vector a -> Vector a -> Vector a)
      -> Vector a -> Vector a -> Vector a)
forall t. t -> Vector t
V.fanout (\cat :: Vector a -> Vector a -> Vector a
cat a :: Vector a
a b :: Vector a
b -> Vector a
a Vector a -> Vector a -> Vector a
`cat` Vector a
b))

-- | Unzips the vectors carried by a signal into a vector of
-- signals. It instantiates the 'ForSyCt.Atom.Skel.Vector.unzipx'
-- skeleton. To avoid infinite recurrence, the user needs to provict
-- the length of the output vector.
--
-- >>> let v1 = V.vector [1,2,3,4]
-- >>> let s1 = CT.signal [(0,const v1),(2,const v1),(6,const v1)]
-- >>> unzipx 4 s1
-- <{4@0,4@2,4@6},{3@0,3@2,3@6},{2@0,2@2,2@6},{1@0,1@2,1@6}>
--
-- See 'ForSyDe.Atom.MoC.DE.unzipx' from the "ForSyDe.Atom.MoC.DE"
-- library for a comprehensive visual example.
unzipx :: (Num ts, Real ts, Ord ts, Eq ts, Num tm, Fractional tm, Ord tm) 
       => Integer -> CT.SignalBase ts tm (V.Vector a)
       -> V.Vector (CT.SignalBase ts tm a)
unzipx :: Integer
-> SignalBase ts tm (Vector a) -> Vector (SignalBase ts tm a)
unzipx = (Vector a -> Vector (Ret (CT ts tm) a))
-> Integer
-> SignalBase ts tm (Vector a)
-> Vector (SignalBase ts tm a)
forall (e :: * -> *) a.
MoC e =>
(Vector a -> Vector (Ret e a))
-> Integer -> Stream (e (Vector a)) -> Vector (Stream (e a))
V.unzipx Vector a -> Vector (Ret (CT ts tm) a)
forall a. a -> a
id

-- | Same as 'unzipx', but \"sniffs\" the first event to determine the
-- length of the output vector. Has unsafe behavior!
--
-- >>> let v1 = V.vector [1,2,3,4]
-- >>> let s1 = CT.signal [(0,const v1),(2,const v1),(6,const v1)]
-- >>> unzipx' s1
-- <{4@0,4@2,4@6},{3@0,3@2,3@6},{2@0,2@2,2@6},{1@0,1@2,1@6}>
unzipx' :: (Num ts, Real ts, Ord ts, Eq ts, Num tm, Fractional tm, Ord tm) 
        => CT.SignalBase ts tm (V.Vector a) -> V.Vector (CT.SignalBase ts tm a)
unzipx' :: SignalBase ts tm (Vector a) -> Vector (SignalBase ts tm a)
unzipx' s :: SignalBase ts tm (Vector a)
s@(a :: CT ts tm (Vector a)
a:-_) = Integer
-> SignalBase ts tm (Vector a) -> Vector (SignalBase ts tm a)
forall ts tm a.
(Num ts, Real ts, Ord ts, Eq ts, Num tm, Fractional tm, Ord tm) =>
Integer
-> SignalBase ts tm (Vector a) -> Vector (SignalBase ts tm a)
unzipx (Vector a -> Integer
forall p a. Num p => Vector a -> p
V.length (Vector a -> Integer) -> Vector a -> Integer
forall a b. (a -> b) -> a -> b
$ CT ts tm (Vector a) -> Vector a
forall timestamp time p.
(Real timestamp, Fractional time) =>
CT timestamp time p -> p
CT.evalEv CT ts tm (Vector a)
a) SignalBase ts tm (Vector a)
s