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

module ForSyDe.Atom.MoC.SDF.Interface where

import           ForSyDe.Atom.MoC as MoC
import qualified ForSyDe.Atom.MoC.SDF.Core as SDF
import qualified ForSyDe.Atom.MoC.SY.Core as SY
import qualified ForSyDe.Atom.Skel.Vector as V

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

eventToSY :: SDF.SDF a -> SY.SY a
eventToSY :: SDF a -> SY a
eventToSY (SDF.SDF a :: a
a) = a -> SY a
forall a. a -> SY a
SY.SY a
a

toSY1 :: SDF.Prod -> SDF.Signal a -> SY.Signal (V.Vector a)
-- | Transforms a (set of) 'ForSyDe.Atom.MoC.SDF.SDF' signal(s) into the equivalent
-- 'ForSyDe.Atom.MoC.SY.SY' signal(s). The partial ordering is transformed to total
-- ordering with respect to the firings of the interface process(es), and events
-- consumed during one firing are grouped into vectors.
--
-- Constructors: @toSY[1-4]@.
--
-- >>> let s = SDF.signal [1,2,3,4,5,6,7,8,9]
-- >>> toSY1 2 s
-- {<1,2>,<3,4>,<5,6>,<7,8>}
--
-- <<fig/moc-sdf-tosy.png>>
toSY2 :: (SDF.Cons, SDF.Cons) -- ^ consumption rate of interface process
      -> SDF.Signal a         -- ^ 'SDF.SDF' signal
      -> SDF.Signal b         -- ^ 'SDF.SDF' signal
      -> (SY.Signal (V.Vector a), SY.Signal (V.Vector b))
      -- ^ 'SY.SY' signals
toSY3 :: (SDF.Cons, SDF.Cons, SDF.Cons)
      -> SDF.Signal a -> SDF.Signal b -> SDF.Signal c
      -> (SY.Signal (V.Vector a), SY.Signal (V.Vector b), SY.Signal (V.Vector c))
toSY4 :: (SDF.Cons, SDF.Cons, SDF.Cons, SDF.Cons)
      -> SDF.Signal a -> SDF.Signal b -> SDF.Signal c -> SDF.Signal d
      -> (SY.Signal (V.Vector a), SY.Signal (V.Vector b),
          SY.Signal (V.Vector c), SY.Signal (V.Vector d))

toSY1 :: Prod -> Signal a -> Signal (Vector a)
toSY1 c :: Prod
c s1 :: Signal a
s1 = SDF (Vector a) -> SY (Vector a)
forall a. SDF a -> SY a
eventToSY (SDF (Vector a) -> SY (Vector a))
-> Stream (SDF (Vector a)) -> Signal (Vector a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Prod
c, [a] -> Vector a
forall a. [a] -> Vector a
V.vector) Fun SDF a (Vector a) -> Signal a -> Stream (SDF (Vector a))
forall (e :: * -> *) a b.
MoC e =>
Fun e a b -> Stream (e a) -> Stream (e b)
-.- Signal a
s1
toSY2 :: (Prod, Prod)
-> Signal a -> Signal b -> (Signal (Vector a), Signal (Vector b))
toSY2 (c1 :: Prod
c1,c2 :: Prod
c2) s1 :: Signal a
s1 s2 :: Signal b
s2             = (Prod -> Signal a -> Signal (Vector a)
forall a. Prod -> Signal a -> Signal (Vector a)
toSY1 Prod
c1 Signal a
s1, Prod -> Signal b -> Signal (Vector b)
forall a. Prod -> Signal a -> Signal (Vector a)
toSY1 Prod
c2 Signal b
s2)
toSY3 :: (Prod, Prod, Prod)
-> Signal a
-> Signal b
-> Signal c
-> (Signal (Vector a), Signal (Vector b), Signal (Vector c))
toSY3 (c1 :: Prod
c1,c2 :: Prod
c2,c3 :: Prod
c3) s1 :: Signal a
s1 s2 :: Signal b
s2 s3 :: Signal c
s3       = (Prod -> Signal a -> Signal (Vector a)
forall a. Prod -> Signal a -> Signal (Vector a)
toSY1 Prod
c1 Signal a
s1, Prod -> Signal b -> Signal (Vector b)
forall a. Prod -> Signal a -> Signal (Vector a)
toSY1 Prod
c2 Signal b
s2, Prod -> Signal c -> Signal (Vector c)
forall a. Prod -> Signal a -> Signal (Vector a)
toSY1 Prod
c3 Signal c
s3)
toSY4 :: (Prod, Prod, Prod, Prod)
-> Signal a
-> Signal b
-> Signal c
-> Signal d
-> (Signal (Vector a), Signal (Vector b), Signal (Vector c),
    Signal (Vector d))
toSY4 (c1 :: Prod
c1,c2 :: Prod
c2,c3 :: Prod
c3,c4 :: Prod
c4) s1 :: Signal a
s1 s2 :: Signal b
s2 s3 :: Signal c
s3 s4 :: Signal d
s4 = (Prod -> Signal a -> Signal (Vector a)
forall a. Prod -> Signal a -> Signal (Vector a)
toSY1 Prod
c1 Signal a
s1, Prod -> Signal b -> Signal (Vector b)
forall a. Prod -> Signal a -> Signal (Vector a)
toSY1 Prod
c2 Signal b
s2, Prod -> Signal c -> Signal (Vector c)
forall a. Prod -> Signal a -> Signal (Vector a)
toSY1 Prod
c3 Signal c
s3, Prod -> Signal d -> Signal (Vector d)
forall a. Prod -> Signal a -> Signal (Vector a)
toSY1 Prod
c4 Signal d
s4)

toSY1' :: SDF.Signal a -> SY.Signal a
-- | Alternative implementation to 'toSY2', where the consumption rate of the
-- interface process is @1@, meaning that each SDF event has a corresponding SY event.
--
-- Constructors: @toSY[1-4]'@.
--
-- >>> let s = SDF.signal [1,2,3,4,5]
-- >>> toSY1' s
-- {1,2,3,4,5}
--
-- <<fig/moc-sdf-tosyp.png>>
toSY2' :: SDF.Signal a -- ^ 'SDF.SDF' signal
       -> SDF.Signal b -- ^ 'SDF.SDF' signal
       -> (SY.Signal a, SY.Signal b)
       -- ^ 'SY.SY' signals
toSY3' :: SDF.Signal a -> SDF.Signal b -> SDF.Signal c
       -> (SY.Signal a, SY.Signal b, SY.Signal c)
toSY4' :: SDF.Signal a -> SDF.Signal b -> SDF.Signal c -> SDF.Signal d
       -> (SY.Signal a, SY.Signal b, SY.Signal c, SY.Signal d)

toSY1' :: Signal a -> Signal a
toSY1' = (SDF a -> SY a) -> Signal a -> Signal a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap SDF a -> SY a
forall a. SDF a -> SY a
eventToSY
toSY2' :: Signal a -> Signal b -> (Signal a, Signal b)
toSY2' s1 :: Signal a
s1 s2 :: Signal b
s2       = (Signal a -> Signal a
forall a. Signal a -> Signal a
toSY1' Signal a
s1, Signal b -> Signal b
forall a. Signal a -> Signal a
toSY1' Signal b
s2)
toSY3' :: Signal a -> Signal b -> Signal c -> (Signal a, Signal b, Signal c)
toSY3' s1 :: Signal a
s1 s2 :: Signal b
s2 s3 :: Signal c
s3    = (Signal a -> Signal a
forall a. Signal a -> Signal a
toSY1' Signal a
s1, Signal b -> Signal b
forall a. Signal a -> Signal a
toSY1' Signal b
s2, Signal c -> Signal c
forall a. Signal a -> Signal a
toSY1' Signal c
s3)
toSY4' :: Signal a
-> Signal b
-> Signal c
-> Signal d
-> (Signal a, Signal b, Signal c, Signal d)
toSY4' s1 :: Signal a
s1 s2 :: Signal b
s2 s3 :: Signal c
s3 s4 :: Signal d
s4 = (Signal a -> Signal a
forall a. Signal a -> Signal a
toSY1' Signal a
s1, Signal b -> Signal b
forall a. Signal a -> Signal a
toSY1' Signal b
s2, Signal c -> Signal c
forall a. Signal a -> Signal a
toSY1' Signal c
s3, Signal d -> Signal d
forall a. Signal a -> Signal a
toSY1' Signal d
s4)


------- SKELETON INTERFACES -------

-- | Consumes tokens from a vector of signals and merges them into a
-- signal of vectors, with a production rate of 1. It instantiates the
-- 'ForSyDe.Atom.Skel.Vector.zipx' skeleton.
--
-- >>> let s1 = SDF.signal [1,2,3,4,5]
-- >>> let s2 = SDF.signal [11,12,13,14,15]
-- >>> let v1 = V.vector [s1,s1,s2,s2]
-- >>> let r  = V.vector [2,1,2,1]
-- >>> v1
-- <{1,2,3,4,5},{1,2,3,4,5},{11,12,13,14,15},{11,12,13,14,15}>
-- >>> zipx r v1
-- {<1,2,1,11,12,11>,<3,4,2,13,14,12>}
--
-- <<fig/moc-sdf-zipx.png>>
zipx :: V.Vector SDF.Cons       -- ^ consumption rates
     -> V.Vector (SDF.Signal a) -- ^ vector of signals
     -> SDF.Signal (V.Vector a) -- ^ signal of vectors
zipx :: Vector Prod -> Vector (Signal a) -> Signal (Vector a)
zipx rates :: Vector Prod
rates = Vector
  ((Vector a -> Vector a -> Vector a)
   -> Fun SDF (Vector a) (Fun SDF (Vector a) (Ret SDF (Vector a))))
-> Vector (Signal a) -> Signal (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 ((Prod
 -> (Vector a -> Vector a -> Vector a)
 -> (Prod, [Vector a] -> (Prod, [Vector a] -> (Prod, [Vector a]))))
-> Vector Prod
-> Vector
     ((Vector a -> Vector a -> Vector a)
      -> (Prod, [Vector a] -> (Prod, [Vector a] -> (Prod, [Vector a]))))
forall a1 b1. (a1 -> b1) -> Vector a1 -> Vector b1
V.farm11 Prod
-> (Vector a -> Vector a -> Vector a)
-> (Prod, [Vector a] -> (Prod, [Vector a] -> (Prod, [Vector a])))
forall c2 p (f :: * -> *) (t :: * -> *) c1 a a b.
(Num c2, Num p, Functor f, Foldable t) =>
c1
-> (Vector a -> a -> b)
-> (c1, t (Vector a) -> (c2, f a -> (p, f b)))
transpose Vector Prod
rates)
  where transpose :: c1
-> (Vector a -> a -> b)
-> (c1, t (Vector a) -> (c2, f a -> (p, f b)))
transpose r :: c1
r cat :: Vector a -> a -> b
cat = (c1, c2)
-> p
-> (t (Vector a) -> f a -> f b)
-> (c1, t (Vector a) -> (c2, f a -> (p, f b)))
forall c1 c2 p a1 a2 b.
(c1, c2) -> p -> (a1 -> a2 -> b) -> (c1, a1 -> (c2, a2 -> (p, b)))
MoC.ctxt21 (c1
r,1) 1 ((Vector a -> a -> b) -> t (Vector a) -> f a -> f b
forall (f :: * -> *) (t :: * -> *) a a b.
(Functor f, Foldable t) =>
(Vector a -> a -> b) -> t (Vector a) -> f a -> f b
syncf Vector a -> a -> b
cat)
        syncf :: (Vector a -> a -> b) -> t (Vector a) -> f a -> f b
syncf catf :: Vector a -> a -> b
catf a :: t (Vector a)
a b :: f a
b  = ((Vector a -> Vector a -> Vector a) -> t (Vector a) -> Vector a
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 Vector a -> Vector a -> Vector a
forall a. Vector a -> Vector a -> Vector a
(V.<++>) t (Vector a)
a Vector a -> a -> b
`catf`) (a -> b) -> f a -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> f a
b


-- (V.fanout (\cat a b -> V.unit a `cat` b))
-- | Consumes the vectors carried by a signal with a rate of 1, and
-- unzips them into a vector of signals based on the user provided
-- rates. It instantiates the 'ForSyDe.Atom.Skel.Vector.unzipx'
-- skeleton.
--
-- __OBS:__ due to the 'ForSyDe.Atom.Skel.Vector.recur' pattern
-- contained by 'ForSyDe.Atom.Skel.Vector.unzipx', the vector of
-- production rates needs to be provided in reverse order (see
-- "ForSyDe.Atom.Skel.Vector").
--
-- >>> let s1 = SDF.signal [1,2,3,4,5]
-- >>> let s2 = SDF.signal [11,12,13,14,15]
-- >>> let v1 = V.vector [s1,s1,s2,s2]
-- >>> let r  = V.vector [2,1,2,1]
-- >>> let sz = zipx r v1
-- >>> v1
-- <{1,2,3,4,5},{1,2,3,4,5},{11,12,13,14,15},{11,12,13,14,15}>
-- >>> sz
-- {<1,2,1,11,12,11>,<3,4,2,13,14,12>}
-- >>> unzipx (V.reverse r) sz
-- <{1,2,3,4},{1,2},{11,12,13,14},{11,12}>
--
-- <<fig/moc-sdf-unzipx.png>>
unzipx :: V.Vector SDF.Prod  -- ^ production rates (in reverse order)
       -> SDF.Signal (V.Vector a) -- ^ signal of vectors
       -> V.Vector (SDF.Signal a) -- ^ vector of signals
unzipx :: Vector Prod -> Signal (Vector a) -> Vector (Signal a)
unzipx rates :: Vector Prod
rates = (Vector a -> Vector (Ret SDF a))
-> Integer -> Signal (Vector a) -> Vector (Signal 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 (Prod, [a])
Vector a -> Vector (Ret SDF a)
eventify (Vector Prod -> Integer
forall p a. Num p => Vector a -> p
V.length Vector Prod
rates)
  where
    eventify :: Vector a -> Vector (Prod, [a])
eventify  = (Prod -> Vector (Maybe a) -> (Prod, [a]))
-> Vector Prod -> Vector (Vector (Maybe a)) -> Vector (Prod, [a])
forall a1 a2 b1.
(a1 -> a2 -> b1) -> Vector a1 -> Vector a2 -> Vector b1
V.farm21 Prod -> Vector (Maybe a) -> (Prod, [a])
forall p a. p -> Vector (Maybe a) -> (p, [a])
vec2res Vector Prod
rates (Vector (Vector (Maybe a)) -> Vector (Prod, [a]))
-> (Vector a -> Vector (Vector (Maybe a)))
-> Vector a
-> Vector (Prod, [a])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector (Vector Prod) -> Vector a -> Vector (Vector (Maybe a))
forall (c1 :: * -> *) (c2 :: * -> *) a.
(Skeleton c1, Skeleton c2) =>
c1 (c2 Prod) -> Vector a -> c1 (c2 (Maybe a))
V.gather2 Vector (Vector Prod)
parts
    vec2res :: p -> Vector (Maybe a) -> (p, [a])
vec2res r :: p
r = p -> [a] -> (p, [a])
forall p b. p -> b -> (p, b)
MoC.wres p
r ([a] -> (p, [a]))
-> (Vector (Maybe a) -> [a]) -> Vector (Maybe a) -> (p, [a])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector a -> [a]
forall a. Vector a -> [a]
V.fromVector (Vector a -> [a])
-> (Vector (Maybe a) -> Vector a) -> Vector (Maybe a) -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Maybe a -> a) -> Vector (Maybe a) -> Vector a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Maybe a -> a
forall p. Maybe p -> p
getJust
    parts :: Vector (Vector Prod)
parts     = (Prod -> Vector Prod -> Vector Prod)
-> Vector Prod -> Vector (Vector Prod) -> Vector (Vector Prod)
forall a1 a2 b1.
(a1 -> a2 -> b1) -> Vector a1 -> Vector a2 -> Vector b1
V.farm21 Prod -> Vector Prod -> Vector Prod
forall a. Prod -> Vector a -> Vector a
V.take Vector Prod
rates (Vector (Vector Prod) -> Vector (Vector Prod))
-> Vector (Vector Prod) -> Vector (Vector Prod)
forall a b. (a -> b) -> a -> b
$ Vector (Vector Prod) -> Vector (Vector Prod)
forall a. Vector a -> Vector a
V.tail
                (Vector (Vector Prod) -> Vector (Vector Prod))
-> Vector (Vector Prod) -> Vector (Vector Prod)
forall a b. (a -> b) -> a -> b
$ (Prod -> Vector Prod -> Vector Prod)
-> Vector Prod -> Vector Prod -> Vector (Vector Prod)
forall a b. (a -> b -> b) -> Vector a -> b -> Vector b
V.recuri1 Prod -> Vector Prod -> Vector Prod
forall a. Prod -> Vector a -> Vector a
V.drop Vector Prod
rates Vector Prod
V.indexes
    getJust :: Maybe p -> p
getJust (Just a :: p
a) = p
a
    getJust Nothing  = [Char] -> p
forall a. HasCallStack => [Char] -> a
error "[MoC.SDF.unzipx] vectors carried by signal are not large enough"