module Control.Parallel.HdpH.Internal.Data.Deque
(
Deque,
empty,
fromList,
pushFront,
pushBack,
popFront,
popBack,
first,
last,
null,
length,
maxLength,
DequeIO,
emptyIO,
fromListIO,
pushFrontIO,
pushBackIO,
popFrontIO,
popBackIO,
firstIO,
lastIO,
nullIO,
lengthIO,
maxLengthIO
) where
import Prelude hiding (error, last, length, null)
import Data.Functor ((<$>))
import Data.IORef (IORef, newIORef, readIORef, atomicModifyIORef)
import qualified Data.List as List (length)
import Data.Sequence (Seq, (|>), (<|), ViewR((:>)), viewr, ViewL((:<)), viewl)
import qualified Data.Sequence as Seq (empty, null, length, fromList)
data Deque a = Deque { q :: Seq a,
mx :: !Int }
empty :: Deque a
empty = Deque { q = Seq.empty, mx = 0 }
fromList :: [a] -> Deque a
fromList xs = Deque { q = Seq.fromList xs, mx = List.length xs }
pushFront :: Deque a -> a -> Deque a
pushFront dq x = dq { q = x <| q dq, mx = max (length dq + 1) (maxLength dq) }
pushBack :: Deque a -> a -> Deque a
pushBack dq x = dq { q = q dq |> x, mx = max (length dq + 1) (maxLength dq) }
popFront :: Deque a -> (Maybe a, Deque a)
popFront dq = case viewl (q dq) of
hd :< rest -> (Just hd, dq { q = rest })
_ -> (Nothing, dq)
popBack :: Deque a -> (Maybe a, Deque a)
popBack dq = case viewr (q dq) of
rest :> tl -> (Just tl, dq { q = rest })
_ -> (Nothing, dq)
first :: Deque a -> Maybe a
first dq = case viewl (q dq) of
x :< _ -> Just x
_ -> Nothing
last :: Deque a -> Maybe a
last dq = case viewr (q dq) of
_ :> x -> Just x
_ -> Nothing
null :: Deque a -> Bool
null = Seq.null . q
length :: Deque a -> Int
length = Seq.length . q
maxLength :: Deque a -> Int
maxLength = mx
newtype DequeIO a = DequeIO (IORef (Deque a))
emptyIO :: IO (DequeIO a)
emptyIO = DequeIO <$> newIORef empty
fromListIO :: [a] -> IO (DequeIO a)
fromListIO xs = DequeIO <$> newIORef (fromList xs)
pushFrontIO :: DequeIO a -> a -> IO ()
pushFrontIO (DequeIO dqRef) x =
atomicModifyIORef dqRef $ \ dq -> (pushFront dq x, ())
pushBackIO :: DequeIO a -> a -> IO ()
pushBackIO (DequeIO dqRef) x =
atomicModifyIORef dqRef $ \ dq -> (pushBack dq x, ())
popFrontIO :: DequeIO a -> IO (Maybe a)
popFrontIO (DequeIO dqRef) =
atomicModifyIORef dqRef $ swap . popFront
popBackIO :: DequeIO a -> IO (Maybe a)
popBackIO (DequeIO dqRef) =
atomicModifyIORef dqRef $ swap . popBack
firstIO :: DequeIO a -> IO (Maybe a)
firstIO (DequeIO dqRef) = first <$> readIORef dqRef
lastIO :: DequeIO a -> IO (Maybe a)
lastIO (DequeIO dqRef) = last <$> readIORef dqRef
nullIO :: DequeIO a -> IO Bool
nullIO (DequeIO dqRef) = null <$> readIORef dqRef
lengthIO :: DequeIO a -> IO Int
lengthIO (DequeIO dqRef) = length <$> readIORef dqRef
maxLengthIO :: DequeIO a -> IO Int
maxLengthIO (DequeIO dqRef) = maxLength <$> readIORef dqRef
swap :: (a,b) -> (b,a)
swap (a,b) = (b,a)