co-feldspar-0.1.0.1: src/Feldspar/Array/Queue.hs
{-# language GADTs #-}
{-# language Rank2Types #-}
{-# language FlexibleContexts #-}
{-# language ConstraintKinds #-}
{-# language ScopedTypeVariables #-}
module Feldspar.Array.Queue where
import Feldspar
import Feldspar.Frontend (Arrays)
import Feldspar.Array.Vector
import Prelude hiding (length, mod, reverse, drop, take, (++))
--------------------------------------------------------------------------------
-- * Queues.
--------------------------------------------------------------------------------
data Queue m a = Queue
{ queue_get :: Expr m Index -> m a
, queue_put :: a -> m ()
, queue_with :: forall b . SyntaxM m b => (Pull (Expr m) a -> m b) -> m b
}
type Queues m a =
( Finite (Expr m) (Array m a)
, Finite (Expr m) (IArray m a)
, Indexed (Expr m) (IArray m a)
, ArrElem (IArray m a) ~ a
, Multiplicative (Expr m)
, Vector (Expr m)
, SyntaxM m (Expr m Index)
, SyntaxM m (Expr m Length)
, PredOf (Expr m) Length
)
--------------------------------------------------------------------------------
queueBuffer :: forall m a . (MonadComp m, SyntaxM m a, Queues m a)
=> Array m a -> m (Queue m a)
queueBuffer buf =
do ir <- initRef (0 :: Expr m Index)
let get :: Expr m Index -> m a
get j = do
i <- unsafeFreezeRef ir
getArr buf $ safeIndex i j
let put :: a -> m ()
put a = do
i <- unsafeFreezeRef ir
setArr buf i a
setRef ir ((i+1) `mod` len)
let with :: forall b . (SyntaxM m b) => (Pull (Expr m) a -> m b) -> m b
with f = do
i <- unsafeFreezeRef ir
v <- unsafeFreezeArr buf
f $ backPermute (\_ -> safeIndex i) v
return $ Queue { queue_get = get, queue_put = put, queue_with = with }
where
len = length buf
safeIndex i j = (len + i - j - 1) `mod` len
queueVector ::
( Manifestable m vec a
, Finite (Expr m) vec
, SyntaxM m a
, MonadComp m
, Queues m a
)
=> vec -> m (Queue m a)
queueVector v =
do buf <- newArr $ length v
manifestStore buf v
queueBuffer buf
newQueue :: (SyntaxM m a, MonadComp m, Queues m a)
=> Expr m Length -> m (Queue m a)
newQueue l = newArr l >>= queueBuffer
--------------------------------------------------------------------------------
queueDoubleBuffer :: forall m a . (MonadComp m, SyntaxM m a, Queues m a)
=> Expr m Length -> Array m a -> m (Queue m a)
queueDoubleBuffer len buf =
do ir <- initRef (0 :: Expr m Index)
let get :: Expr m Index -> m a
get j = do
i <- unsafeFreezeRef ir
getArr buf $ len + i - j - 1
let put :: a -> m ()
put a = do
i <- unsafeFreezeRef ir
setArr buf i a
setArr buf (i + len) a
setRef ir ((i + 1) `mod` len)
let with :: forall b . (SyntaxM m b) => (Pull (Expr m) a -> m b) -> m b
with f = do
i <- unsafeFreezeRef ir
v <- unsafeFreezeArr buf
f $ reverse $ take len $ drop i v
return $ Queue { queue_get = get, queue_put = put, queue_with = with }
queueDoubleVector :: forall m vec a .
( Manifestable m vec a
, Finite (Expr m) vec
, Slicable (Expr m) (IArray m a)
, Pushy m vec a
, SyntaxM m a
, MonadComp m
, Loop m
, Queues m a
)
=> vec -> m (Queue m a)
queueDoubleVector v =
do let len = length v
buf <- newArr $ 2 * len
manifestStore buf $ (v ++ v :: Push m a)
queueDoubleBuffer len buf
newDoubleQueue :: (SyntaxM m a, MonadComp m, Queues m a)
=> Expr m Length -> m (Queue m a)
newDoubleQueue l =
do buf <- newArr $ 2 * l
queueDoubleBuffer l buf
--------------------------------------------------------------------------------