{-# language CPP #-}
{-# language BangPatterns, ScopedTypeVariables, UnboxedTuples, MagicHash #-}
{-# language DeriveTraversable, StandaloneDeriving #-}
{-# language PatternSynonyms #-}
{-# language ViewPatterns #-}
{-# language LambdaCase #-}
module Data.CompactSequence.Queue.Internal where
import qualified Data.CompactSequence.Internal.Array as A
import Data.CompactSequence.Internal.Array (Array)
import qualified Data.CompactSequence.Internal.Size as Sz
import Data.CompactSequence.Internal.Size (Size, Twice)
import qualified Data.Foldable as F
import Data.Function (on)
data FD n a
= FD1 !(Array n a)
| FD2 !(Array n a) !(Array n a)
| FD3 !(Array n a) !(Array n a) !(Array n a)
data RD n a
= RD0
| RD1 !(Array n a)
| RD2 !(Array n a) !(Array n a)
data Queue n a
= Empty
| Node10 !(Array n a) !(Queue (Twice n) a)
| Node11 !(Array n a) !(Queue (Twice n) a) !(Array n a)
| Node12 !(Array n a) !(Queue (Twice n) a) !(Array n a) !(Array n a)
| Node20 !(Array n a) !(Array n a) (Queue (Twice n) a)
| Node21 !(Array n a) !(Array n a) (Queue (Twice n) a) !(Array n a)
| Node22 !(Array n a) !(Array n a) !(Queue (Twice n) a) !(Array n a) !(Array n a)
| Node30 !(Array n a) !(Array n a) !(Array n a) (Queue (Twice n) a)
| Node31 !(Array n a) !(Array n a) !(Array n a) (Queue (Twice n) a) !(Array n a)
| Node32 !(Array n a) !(Array n a) !(Array n a) !(Queue (Twice n) a) !(Array n a) !(Array n a)
deriving (Functor, Foldable, Traversable)
data Queue_ n a
= Empty_
| Node_ !(FD n a) (Queue (Twice n) a) !(RD n a)
matchNode :: Queue n a -> Queue_ n a
matchNode q = case q of
Empty -> Empty_
Node10 x m -> Node_ (FD1 x) m RD0
Node11 x m a -> Node_ (FD1 x) m (RD1 a)
Node12 x m a b -> Node_ (FD1 x) m (RD2 a b)
Node20 x y m -> Node_ (FD2 x y) m RD0
Node21 x y m a -> Node_ (FD2 x y) m (RD1 a)
Node22 x y m a b -> Node_ (FD2 x y) m (RD2 a b)
Node30 x y z m -> Node_ (FD3 x y z) m RD0
Node31 x y z m a -> Node_ (FD3 x y z) m (RD1 a)
Node32 x y z m a b -> Node_ (FD3 x y z) m (RD2 a b)
{-# INLINE matchNode #-}
pattern Node :: FD n a -> Queue (Twice n) a -> RD n a -> Queue n a
pattern Node pr m sf <- (matchNode -> Node_ pr m sf)
where
Node (FD1 x) m RD0 = Node10 x m
Node (FD1 x) m (RD1 a) = Node11 x m a
Node (FD1 x) m (RD2 a b) = Node12 x m a b
Node (FD2 x y) m RD0 = Node20 x y m
Node (FD2 x y) m (RD1 a) = Node21 x y m a
Node (FD2 x y) m (RD2 a b) = Node22 x y m a b
Node (FD3 x y z) m RD0 = Node30 x y z m
Node (FD3 x y z) m (RD1 a) = Node31 x y z m a
Node (FD3 x y z) m (RD2 a b) = Node32 x y z m a b
{-# COMPLETE Empty, Node #-}
data ViewA n a
= EmptyA
| ConsA !(Array n a) (Queue n a)
data ViewA2 n a
= EmptyA2
| ConsA2 !(Array n a) !(Array n a) (Queue n a)
singletonA :: Array n a -> Queue n a
singletonA sa = Node (FD1 sa) Empty RD0
viewA :: Size n -> Queue n a -> ViewA n a
viewA !_ Empty = EmptyA
viewA !_ (Node (FD3 sa1 sa2 sa3) m sf) = ConsA sa1 $ Node (FD2 sa2 sa3) m sf
viewA !_ (Node (FD2 sa1 sa2) m sf) = ConsA sa1 $ Node (FD1 sa2) m sf
viewA !n (Node (FD1 sa1) m (RD2 sa2 sa3)) = ConsA sa1 $
case shiftA n m sa2 sa3 of
ShiftedA sam1 sam2 m'
-> Node (FD2 sam1 sam2) m' RD0
viewA !n (Node (FD1 sa1) m sf) = ConsA sa1 $
case viewA (Sz.twice n) m of
EmptyA -> case sf of
RD2 sa2 sa3 -> Node (FD2 sa2 sa3) Empty RD0
RD1 sa2 -> singletonA sa2
RD0 -> Empty
ConsA sam m'
| (sam1, sam2) <- A.splitArray n sam
-> Node (FD2 sam1 sam2) m' sf
empty :: Queue n a
empty = Empty
snocA :: Size n -> Queue n a -> Array n a -> Queue n a
snocA !_ Empty sa = Node (FD1 sa) empty RD0
snocA !n (Node (FD1 sa0) m (RD2 sa1 sa2)) sa3
| ShiftedA sam1 sam2 m' <- shiftA n m sa1 sa2
= Node (FD3 sa0 sam1 sam2) m' (RD1 sa3)
snocA !_ (Node pr m RD0) sa = Node pr m (RD1 sa)
snocA !_ (Node pr m (RD1 sa1)) sa2 = Node pr m (RD2 sa1 sa2)
snocA !n (Node pr m (RD2 sa1 sa2)) sa3
= Node pr (snocA (Sz.twice n) m (A.append n sa1 sa2)) (RD1 sa3)
shiftA :: Size n -> Queue (Twice n) a -> Array n a -> Array n a -> ShiftedA n a
shiftA !_ Empty !sa1 !sa2 = ShiftedA sa1 sa2 Empty
shiftA !n (Node20 sa1 sa2 m) !sa3 !sa4
= shrift n sa1 $ Node11 sa2 m (A.append n sa3 sa4)
shiftA !n (Node21 sa1 sa2 m sa3) !sa4 !sa5
= shrift n sa1 $ Node12 sa2 m sa3 (A.append n sa4 sa5)
shiftA !n (Node30 sa1 sa2 sa3 m) !sa4 !sa5
= shrift n sa1 $ Node21 sa2 sa3 m (A.append n sa4 sa5)
shiftA !n (Node31 sa1 sa2 sa3 m sa4) !sa5 !sa6
= shrift n sa1 $ Node22 sa2 sa3 m sa4 (A.append n sa5 sa6)
shiftA !n (Node10 sa1 m) !sa3 !sa4
= shrift n sa1 $
case viewA (Sz.twice (Sz.twice n)) m of
EmptyA -> Node10 (A.append n sa3 sa4) Empty
ConsA sam m'
| (sam1, sam2) <- A.splitArray (Sz.twice n) sam
-> Node21 sam1 sam2 m' (A.append n sa3 sa4)
shiftA !n (Node11 sa1 m sa2) !sa3 !sa4
= shrift n sa1 $
case shiftA (Sz.twice n) m sa2 (A.append n sa3 sa4) of
ShiftedA sam1 sam2 m'
-> Node20 sam1 sam2 m'
shiftA n (Node12 sa1 m sa2 sa3) !sa4 !sa5
= shrift n sa1 $
case shiftA (Sz.twice n) m sa2 sa3 of
ShiftedA sam1 sam2 m'
-> Node21 sam1 sam2 m' (A.append n sa4 sa5)
shiftA n (Node22 sa1 sa2 m sa3 sa4) !sa5 !sa6
= shrift n sa1 $
case shiftA (Sz.twice n) m sa3 sa4 of
ShiftedA sam1 sam2 m'
-> Node31 sa2 sam1 sam2 m' (A.append n sa5 sa6)
shiftA n (Node32 sa1 sa2 sa3 m sa4 sa5) !sa6 !sa7
= shrift n sa1 $
Node21 sa2 sa3
(snocA (Sz.twice (Sz.twice n)) m (A.append (Sz.twice n) sa4 sa5))
(A.append n sa6 sa7)
shrift :: Size n -> Array (Twice n) a -> Queue (Twice n) a -> ShiftedA n a
shrift n sa q
| (sa1, sa2) <- A.splitArray n sa
= ShiftedA sa1 sa2 q
data ShiftedA n a = ShiftedA !(Array n a) !(Array n a) (Queue (Twice n) a)
instance Show a => Show (Queue n a) where
showsPrec p xs = showParen (p > 10) $
showString "fromList " . shows (F.toList xs)
instance Eq a => Eq (Queue n a) where
(==) = (==) `on` F.toList
instance Ord a => Ord (Queue n a) where
compare = compare `on` F.toList