{-# LANGUAGE PostfixOperators #-}
{-# OPTIONS_HADDOCK hide #-}
----------------------------------------------------------------------
-- |
-- Module      :  ForSyDe.Atom.Skel.Vector.Core
-- Copyright   :  (c) George Ungureanu, KTH/ICT/ESY 2016
-- License     :  BSD-style (see the file LICENSE)
-- 
-- Maintainer  :  ugeorge@kth.se
-- Stability   :  experimental
-- Portability :  portable
--
-- The library for the 'Vector' type. Contains the main skeletons.
----------------------------------------------------------------------
module ForSyDe.Atom.Skel.Vector.Interface where

import ForSyDe.Atom.MoC
import ForSyDe.Atom.MoC.Stream as S
import ForSyDe.Atom.Skel
import ForSyDe.Atom.Skel.Vector.Core
import ForSyDe.Atom.Skel.Vector.Lib as V (recuri, tail, fanout, fanoutn, reduce1)
  

import Prelude hiding (tail, map, length)
import Control.Applicative

mapS :: MoC e => (a -> b) -> Stream (e a) -> Stream (e b)
mapS :: (a -> b) -> Stream (e a) -> Stream (e b)
mapS = (e a -> e b) -> Stream (e a) -> Stream (e b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((e a -> e b) -> Stream (e a) -> Stream (e b))
-> ((a -> b) -> e a -> e b)
-> (a -> b)
-> Stream (e a)
-> Stream (e b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> b) -> e a -> e b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap

-- | 'zipx' is a template skeleton for \"zipping"\ a vector of
-- signals. It synchronizes all signals (of the same MoC) in a vector
-- and outputs one signal with vectors of the synced values. For each
-- signal in the input vector it requires a function which
-- /translates/ a partition of events (see "ForSyDe.Atom.MoC") into
-- sub-vectors.
--
-- There exist helper instances of the 'zipx' skeleton interface for
-- all supported MoCs.
--
-- <<fig/eqs-skel-vector-zipx.png>>
-- <<fig/skel-vector-comm-zipx.png>>
zipx :: MoC e
     => Vector ((Vector a -> Vector a -> Vector a)
                -> Fun e (Vector a) (Fun e (Vector a)
                                      (Ret e (Vector a))))
     -- ^ vector of MoC-specific context wrappers for the function
     -- '<++>'
     -> Vector (Stream (e a))
     -- ^ input vector of signals
     -> Stream (e (Vector a))
     -- ^ output signal of vectors
zipx :: 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))
zipx part :: Vector
  ((Vector a -> Vector a -> Vector a)
   -> Fun e (Vector a) (Fun e (Vector a) (Ret e (Vector a))))
part =  (((Vector a -> Vector a -> Vector a)
  -> Fun e (Vector a) (Fun e (Vector a) (Ret e (Vector a))))
 -> Stream (e (Vector a))
 -> Stream (e (Vector a))
 -> Stream (e (Vector a)))
-> Vector
     ((Vector a -> Vector a -> Vector a)
      -> Fun e (Vector a) (Fun e (Vector a) (Ret e (Vector a))))
-> Vector (Stream (e (Vector a)))
-> Stream (e (Vector a))
forall a1 a. (a1 -> a -> a -> a) -> Vector a1 -> Vector a -> a
V.reduce1 ((Vector a -> Vector a -> Vector a)
 -> Fun e (Vector a) (Fun e (Vector a) (Ret e (Vector a))))
-> Stream (e (Vector a))
-> Stream (e (Vector a))
-> Stream (e (Vector a))
forall (e :: * -> *) a a1 a2 b.
MoC e =>
((Vector a -> Vector a -> Vector a)
 -> Fun e a1 (Fun e a2 (Ret e b)))
-> Stream (e a1) -> Stream (e a2) -> Stream (e b)
sync Vector
  ((Vector a -> Vector a -> Vector a)
   -> Fun e (Vector a) (Fun e (Vector a) (Ret e (Vector a))))
part (Vector (Stream (e (Vector a))) -> Stream (e (Vector a)))
-> (Vector (Stream (e a)) -> Vector (Stream (e (Vector a))))
-> Vector (Stream (e a))
-> Stream (e (Vector a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Stream (e a) -> Stream (e (Vector a)))
-> Vector (Stream (e a)) -> Vector (Stream (e (Vector a)))
forall (c :: * -> *) a b. Skeleton c => (a -> b) -> c a -> c b
farm11 ((a -> Vector a) -> Stream (e a) -> Stream (e (Vector a))
forall (e :: * -> *) a b.
MoC e =>
(a -> b) -> Stream (e a) -> Stream (e b)
mapS a -> Vector a
forall a. a -> Vector a
unit)
  where sync :: ((Vector a -> Vector a -> Vector a)
 -> Fun e a1 (Fun e a2 (Ret e b)))
-> Stream (e a1) -> Stream (e a2) -> Stream (e b)
sync p :: (Vector a -> Vector a -> Vector a) -> Fun e a1 (Fun e a2 (Ret e b))
p = Fun e a1 (Fun e a2 (Ret e b))
-> Stream (e a1) -> Stream (e a2) -> Stream (e b)
forall (e :: * -> *) a1 a2 b.
MoC e =>
Fun e a1 (Fun e a2 (Ret e b))
-> Stream (e a1) -> Stream (e a2) -> Stream (e b)
comb21 ((Vector a -> Vector a -> Vector a) -> Fun e a1 (Fun e a2 (Ret e b))
p Vector a -> Vector a -> Vector a
forall a. Vector a -> Vector a -> Vector a
(<++>))


-- | 'unzipx' is a template skeleton to unzip a signal carrying
-- vectors into a vector of multiple signals. It required a function
-- that /splits/ a vector of values into a vector of event partitions
-- belonging to output signals. Unlike 'zipx', it also requires the
-- number of output signals. The reason for this is that it is
-- impossible to determine the length of the output vector without
-- \"sniffing\" the content of the input events, which is out of the
-- scope of skeletons and may lead to unsafe behavior. The length of
-- the output vector is needed in order to avoid infinite recurrence.
--
-- There exist helper instances of the 'unzipx' skeleton interface for
-- all supported MoCs.
--
-- <<fig/eqs-skel-vector-unzipx.png>>
-- <<fig/skel-vector-comm-unzipx.png>>
unzipx :: (MoC e)
       => (Vector a -> Vector (Ret e a))
       -> Integer
       -> Stream (e (Vector a))
       -> Vector (Stream (e a))
unzipx :: (Vector a -> Vector (Ret e a))
-> Integer -> Stream (e (Vector a)) -> Vector (Stream (e a))
unzipx parts :: Vector a -> Vector (Ret e a)
parts n :: Integer
n = (Stream (e (Vector (Ret e a))) -> Stream (e a))
-> Vector (Stream (e (Vector (Ret e a)))) -> Vector (Stream (e a))
forall (c :: * -> *) a b. Skeleton c => (a -> b) -> c a -> c b
farm11 Stream (e (Vector (Ret e a))) -> Stream (e a)
forall b. Stream (e (Vector (Ret e b))) -> Stream (e b)
rebuild (Vector (Stream (e (Vector (Ret e a)))) -> Vector (Stream (e a)))
-> (Stream (e (Vector a))
    -> Vector (Stream (e (Vector (Ret e a)))))
-> Stream (e (Vector a))
-> Vector (Stream (e a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector
  (Stream (e (Vector (Ret e a))) -> Stream (e (Vector (Ret e a))))
-> Stream (e (Vector (Ret e a)))
-> Vector (Stream (e (Vector (Ret e a))))
forall b. Vector (b -> b) -> b -> Vector b
recuri Vector
  (Stream (e (Vector (Ret e a))) -> Stream (e (Vector (Ret e a))))
forall a. Vector (Stream (e (Vector a)) -> Stream (e (Vector a)))
transpose (Stream (e (Vector (Ret e a)))
 -> Vector (Stream (e (Vector (Ret e a)))))
-> (Stream (e (Vector a)) -> Stream (e (Vector (Ret e a))))
-> Stream (e (Vector a))
-> Vector (Stream (e (Vector (Ret e a))))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Vector a -> Vector (Ret e a))
-> Stream (e (Vector a)) -> Stream (e (Vector (Ret e a)))
forall (e :: * -> *) a b.
MoC e =>
(a -> b) -> Stream (e a) -> Stream (e b)
mapS Vector a -> Vector (Ret e a)
parts
  where transpose :: Vector (Stream (e (Vector a)) -> Stream (e (Vector a)))
transpose = Integer
-> (Stream (e (Vector a)) -> Stream (e (Vector a)))
-> Vector (Stream (e (Vector a)) -> Stream (e (Vector a)))
forall t a. (Ord t, Num t) => t -> a -> Vector a
fanoutn (Integer
nInteger -> Integer -> Integer
forall a. Num a => a -> a -> a
-1) ((Vector a -> Vector a)
-> Stream (e (Vector a)) -> Stream (e (Vector a))
forall (e :: * -> *) a b.
MoC e =>
(a -> b) -> Stream (e a) -> Stream (e b)
mapS Vector a -> Vector a
forall a. Vector a -> Vector a
tail)
        rebuild :: Stream (e (Vector (Ret e b))) -> Stream (e b)
rebuild   = Stream (e (Ret e b)) -> Stream (e b)
forall (e :: * -> *) b.
MoC e =>
Stream (e (Ret e b)) -> Stream (e b)
(-*) (Stream (e (Ret e b)) -> Stream (e b))
-> (Stream (e (Vector (Ret e b))) -> Stream (e (Ret e b)))
-> Stream (e (Vector (Ret e b)))
-> Stream (e b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Vector (Ret e b) -> Ret e b)
-> Stream (e (Vector (Ret e b))) -> Stream (e (Ret e b))
forall (e :: * -> *) a b.
MoC e =>
(a -> b) -> Stream (e a) -> Stream (e b)
mapS Vector (Ret e b) -> Ret e b
forall (c :: * -> *) a. Skeleton c => c a -> a
first



-- zipx :: (MoC e)
--      => Vector (Fun e a (Vector a))
--      -- ^ vector of functions which partition events to vectors
--      -> Vector (Stream (e a))
--      -- ^ input vector of signals
--      -> Stream (e (Vector a))
--      -- ^ output signal of vectors
-- zipx parts = reduce transpose . farm21 ev2vec parts
--   where transpose = (liftA2 . liftA2) (<++>)
--         ev2vec p  = (p -.-) 


-- unzipx :: (MoC e)
--        => Vector (Vector a -> (Ret e a))
--        -> Vector (Vector a -> Vector a)
--        -> Stream (e (Vector a))
--        -> Vector (Stream (e a))
-- unzipx takes drops = farm11 (-*) . farm21 (fmap . fmap) takes . recur1 (fmap . fmap) drops