module Data.PQueue.Internals (
MinQueue (..),
BinomHeap,
BinomForest(..),
BinomTree(..),
Succ(..),
Zero(..),
LEq,
empty,
null,
size,
getMin,
minView,
singleton,
insert,
insertBehind,
union,
mapMaybe,
mapEither,
mapMonotonic,
foldrAsc,
foldlAsc,
insertMinQ,
foldrU,
foldlU,
keysQueue,
seqSpine
) where
import Control.DeepSeq (NFData(rnf), deepseq)
import Data.Functor ((<$>))
import Data.Foldable (Foldable (foldr, foldl))
import Data.Monoid (mappend)
import qualified Data.PQueue.Prio.Internals as Prio
#ifdef __GLASGOW_HASKELL__
import Data.Data
#endif
import Prelude hiding (foldl, foldr, null)
data MinQueue a = Empty | MinQueue !Int a !(BinomHeap a)
#if __GLASGOW_HASKELL__>=707
deriving Typeable
#else
#include "Typeable.h"
INSTANCE_TYPEABLE1(MinQueue,minQTC,"MinQueue")
#endif
#ifdef __GLASGOW_HASKELL__
instance (Ord a, Data a) => Data (MinQueue a) where
gfoldl f z q = case minView q of
Nothing -> z Empty
Just (x, q') -> z insertMinQ `f` x `f` q'
gunfold k z c = case constrIndex c of
1 -> z Empty
2 -> k (k (z insertMinQ))
_ -> error "gunfold"
dataCast1 x = gcast1 x
toConstr q
| null q = emptyConstr
| otherwise = consConstr
dataTypeOf _ = queueDataType
queueDataType :: DataType
queueDataType = mkDataType "Data.PQueue.Min.MinQueue" [emptyConstr, consConstr]
emptyConstr, consConstr :: Constr
emptyConstr = mkConstr queueDataType "empty" [] Prefix
consConstr = mkConstr queueDataType "<|" [] Infix
#endif
type BinomHeap = BinomForest Zero
instance Ord a => Eq (MinQueue a) where
Empty == Empty = True
MinQueue n1 x1 q1 == MinQueue n2 x2 q2 =
n1 == n2 && eqExtract (x1,q1) (x2,q2)
_ == _ = False
eqExtract :: Ord a => (a, BinomHeap a) -> (a, BinomHeap a) -> Bool
eqExtract (x1,q1) (x2,q2) =
x1 == x2 &&
case (extractHeap q1, extractHeap q2) of
(Just h1, Just h2) -> eqExtract h1 h2
(Nothing, Nothing) -> True
_ -> False
instance Ord a => Ord (MinQueue a) where
Empty `compare` Empty = EQ
Empty `compare` _ = LT
_ `compare` Empty = GT
MinQueue _n1 x1 q1 `compare` MinQueue _n2 x2 q2 = cmpExtract (x1,q1) (x2,q2)
cmpExtract :: Ord a => (a, BinomHeap a) -> (a, BinomHeap a) -> Ordering
cmpExtract (x1,q1) (x2,q2) =
compare x1 x2 `mappend`
case (extractHeap q1, extractHeap q2) of
(Just h1, Just h2) -> cmpExtract h1 h2
(Nothing, Nothing) -> EQ
(Just _, Nothing) -> GT
(Nothing, Just _) -> LT
data BinomForest rk a = Nil | Skip (BinomForest (Succ rk) a) |
Cons !(BinomTree rk a) (BinomForest (Succ rk) a)
data BinomTree rk a = BinomTree a (rk a)
data Succ rk a = Succ !(BinomTree rk a) (rk a)
data Zero a = Zero
type LEq a = a -> a -> Bool
empty :: MinQueue a
empty = Empty
null :: MinQueue a -> Bool
null Empty = True
null _ = False
size :: MinQueue a -> Int
size Empty = 0
size (MinQueue n _ _) = n
getMin :: MinQueue a -> Maybe a
getMin (MinQueue _ x _) = Just x
getMin _ = Nothing
minView :: Ord a => MinQueue a -> Maybe (a, MinQueue a)
minView Empty = Nothing
minView (MinQueue n x ts) = Just (x, case extractHeap ts of
Nothing -> Empty
Just (x', ts') -> MinQueue (n1) x' ts')
singleton :: a -> MinQueue a
singleton x = MinQueue 1 x Nil
insert :: Ord a => a -> MinQueue a -> MinQueue a
insert = insert' (<=)
insertBehind :: Ord a => a -> MinQueue a -> MinQueue a
insertBehind = insert' (<)
union :: Ord a => MinQueue a -> MinQueue a -> MinQueue a
union = union' (<=)
mapMaybe :: Ord b => (a -> Maybe b) -> MinQueue a -> MinQueue b
mapMaybe _ Empty = Empty
mapMaybe f (MinQueue _ x ts) = maybe q' (`insert` q') (f x)
where
q' = mapMaybeQueue f (<=) (const Empty) Empty ts
mapEither :: (Ord b, Ord c) => (a -> Either b c) -> MinQueue a -> (MinQueue b, MinQueue c)
mapEither _ Empty = (Empty, Empty)
mapEither f (MinQueue _ x ts) = case (mapEitherQueue f (<=) (<=) (const (Empty, Empty)) (Empty, Empty) ts, f x) of
((qL, qR), Left b) -> (insert b qL, qR)
((qL, qR), Right c) -> (qL, insert c qR)
mapMonotonic :: (a -> b) -> MinQueue a -> MinQueue b
mapMonotonic = mapU
foldrAsc :: Ord a => (a -> b -> b) -> b -> MinQueue a -> b
foldrAsc _ z Empty = z
foldrAsc f z (MinQueue _ x ts) = x `f` foldrUnfold f z extractHeap ts
foldrUnfold :: (a -> c -> c) -> c -> (b -> Maybe (a, b)) -> b -> c
foldrUnfold f z suc s0 = unf s0 where
unf s = case suc s of
Nothing -> z
Just (x, s') -> x `f` unf s'
foldlAsc :: Ord a => (b -> a -> b) -> b -> MinQueue a -> b
foldlAsc _ z Empty = z
foldlAsc f z (MinQueue _ x ts) = foldlUnfold f (z `f` x) extractHeap ts
foldlUnfold :: (c -> a -> c) -> c -> (b -> Maybe (a, b)) -> b -> c
foldlUnfold f z0 suc s0 = unf z0 s0 where
unf z s = case suc s of
Nothing -> z
Just (x, s') -> unf (z `f` x) s'
insert' :: LEq a -> a -> MinQueue a -> MinQueue a
insert' _ x Empty = singleton x
insert' le x (MinQueue n x' ts)
| x `le` x' = MinQueue (n+1) x (incr le (tip x') ts)
| otherwise = MinQueue (n+1) x' (incr le (tip x) ts)
union' :: LEq a -> MinQueue a -> MinQueue a -> MinQueue a
union' _ Empty q = q
union' _ q Empty = q
union' le (MinQueue n1 x1 f1) (MinQueue n2 x2 f2)
| x1 `le` x2 = MinQueue (n1 + n2) x1 (carry le (tip x2) f1 f2)
| otherwise = MinQueue (n1 + n2) x2 (carry le (tip x1) f1 f2)
extractHeap :: Ord a => BinomHeap a -> Maybe (a, BinomHeap a)
extractHeap ts = case extractBin (<=) ts of
Yes (Extract x _ ts') -> Just (x, ts')
_ -> Nothing
data Extract rk a = Extract a (rk a) (BinomForest rk a)
data MExtract rk a = No | Yes !(Extract rk a)
incrExtract :: Extract (Succ rk) a -> Extract rk a
incrExtract (Extract minKey (Succ kChild kChildren) ts)
= Extract minKey kChildren (Cons kChild ts)
incrExtract' :: LEq a -> BinomTree rk a -> Extract (Succ rk) a -> Extract rk a
incrExtract' le t (Extract minKey (Succ kChild kChildren) ts)
= Extract minKey kChildren (Skip (incr le (t `cat` kChild) ts))
where
cat = joinBin le
extractBin :: LEq a -> BinomForest rk a -> MExtract rk a
extractBin _ Nil = No
extractBin le (Skip f) = case extractBin le f of
Yes ex -> Yes (incrExtract ex)
No -> No
extractBin le (Cons t@(BinomTree x ts) f) = Yes $ case extractBin le f of
Yes ex@(Extract minKey _ _)
| minKey `lt` x -> incrExtract' le t ex
_ -> Extract x ts (Skip f)
where a `lt` b = not (b `le` a)
mapMaybeQueue :: (a -> Maybe b) -> LEq b -> (rk a -> MinQueue b) -> MinQueue b -> BinomForest rk a -> MinQueue b
mapMaybeQueue f le fCh q0 forest = q0 `seq` case forest of
Nil -> q0
Skip forest' -> mapMaybeQueue f le fCh' q0 forest'
Cons t forest' -> mapMaybeQueue f le fCh' (union' le (mapMaybeT t) q0) forest'
where fCh' (Succ t tss) = union' le (mapMaybeT t) (fCh tss)
mapMaybeT (BinomTree x0 ts) = maybe (fCh ts) (\ x -> insert' le x (fCh ts)) (f x0)
type Partition a b = (MinQueue a, MinQueue b)
mapEitherQueue :: (a -> Either b c) -> LEq b -> LEq c -> (rk a -> Partition b c) -> Partition b c ->
BinomForest rk a -> Partition b c
mapEitherQueue f0 leB leC fCh (q00, q10) ts0 = q00 `seq` q10 `seq` case ts0 of
Nil -> (q00, q10)
Skip ts' -> mapEitherQueue f0 leB leC fCh' (q00, q10) ts'
Cons t ts' -> mapEitherQueue f0 leB leC fCh' (both (union' leB) (union' leC) (partitionT t) (q00, q10)) ts'
where both f g (x1, x2) (y1, y2) = (f x1 y1, g x2 y2)
fCh' (Succ t tss) = both (union' leB) (union' leC) (partitionT t) (fCh tss)
partitionT (BinomTree x ts) = case fCh ts of
(q0, q1) -> case f0 x of
Left b -> (insert' leB b q0, q1)
Right c -> (q0, insert' leC c q1)
tip :: a -> BinomTree Zero a
tip x = BinomTree x Zero
insertMinQ :: a -> MinQueue a -> MinQueue a
insertMinQ x Empty = singleton x
insertMinQ x (MinQueue n x' f) = MinQueue (n+1) x (insertMin (tip x') f)
insertMin :: BinomTree rk a -> BinomForest rk a -> BinomForest rk a
insertMin t Nil = Cons t Nil
insertMin t (Skip f) = Cons t f
insertMin (BinomTree x ts) (Cons t' f) = Skip (insertMin (BinomTree x (Succ t' ts)) f)
merge :: LEq a -> BinomForest rk a -> BinomForest rk a -> BinomForest rk a
merge le f1 f2 = case (f1, f2) of
(Skip f1', Skip f2') -> Skip (merge le f1' f2')
(Skip f1', Cons t2 f2') -> Cons t2 (merge le f1' f2')
(Cons t1 f1', Skip f2') -> Cons t1 (merge le f1' f2')
(Cons t1 f1', Cons t2 f2')
-> Skip (carry le (t1 `cat` t2) f1' f2')
(Nil, _) -> f2
(_, Nil) -> f1
where cat = joinBin le
carry :: LEq a -> BinomTree rk a -> BinomForest rk a -> BinomForest rk a -> BinomForest rk a
carry le t0 f1 f2 = t0 `seq` case (f1, f2) of
(Skip f1', Skip f2') -> Cons t0 (merge le f1' f2')
(Skip f1', Cons t2 f2') -> Skip (mergeCarry t0 t2 f1' f2')
(Cons t1 f1', Skip f2') -> Skip (mergeCarry t0 t1 f1' f2')
(Cons t1 f1', Cons t2 f2')
-> Cons t0 (mergeCarry t1 t2 f1' f2')
(Nil, _f2) -> incr le t0 f2
(_f1, Nil) -> incr le t0 f1
where cat = joinBin le
mergeCarry tA tB = carry le (tA `cat` tB)
incr :: LEq a -> BinomTree rk a -> BinomForest rk a -> BinomForest rk a
incr le t f0 = t `seq` case f0 of
Nil -> Cons t Nil
Skip f -> Cons t f
Cons t' f' -> Skip (incr le (t `cat` t') f')
where cat = joinBin le
joinBin :: LEq a -> BinomTree rk a -> BinomTree rk a -> BinomTree (Succ rk) a
joinBin le t1@(BinomTree x1 ts1) t2@(BinomTree x2 ts2)
| x1 `le` x2 = BinomTree x1 (Succ t2 ts1)
| otherwise = BinomTree x2 (Succ t1 ts2)
instance Functor Zero where
fmap _ _ = Zero
instance Functor rk => Functor (Succ rk) where
fmap f (Succ t ts) = Succ (fmap f t) (fmap f ts)
instance Functor rk => Functor (BinomTree rk) where
fmap f (BinomTree x ts) = BinomTree (f x) (fmap f ts)
instance Functor rk => Functor (BinomForest rk) where
fmap _ Nil = Nil
fmap f (Skip ts) = Skip (fmap f ts)
fmap f (Cons t ts) = Cons (fmap f t) (fmap f ts)
instance Foldable Zero where
foldr _ z _ = z
foldl _ z _ = z
instance Foldable rk => Foldable (Succ rk) where
foldr f z (Succ t ts) = foldr f (foldr f z ts) t
foldl f z (Succ t ts) = foldl f (foldl f z t) ts
instance Foldable rk => Foldable (BinomTree rk) where
foldr f z (BinomTree x ts) = x `f` foldr f z ts
foldl f z (BinomTree x ts) = foldl f (z `f` x) ts
instance Foldable rk => Foldable (BinomForest rk) where
foldr _ z Nil = z
foldr f z (Skip tss) = foldr f z tss
foldr f z (Cons t tss) = foldr f (foldr f z tss) t
foldl _ z Nil = z
foldl f z (Skip tss) = foldl f z tss
foldl f z (Cons t tss) = foldl f (foldl f z t) tss
mapU :: (a -> b) -> MinQueue a -> MinQueue b
mapU _ Empty = Empty
mapU f (MinQueue n x ts) = MinQueue n (f x) (f <$> ts)
foldrU :: (a -> b -> b) -> b -> MinQueue a -> b
foldrU _ z Empty = z
foldrU f z (MinQueue _ x ts) = x `f` foldr f z ts
foldlU :: (b -> a -> b) -> b -> MinQueue a -> b
foldlU _ z Empty = z
foldlU f z (MinQueue _ x ts) = foldl f (z `f` x) ts
seqSpine :: MinQueue a -> b -> b
seqSpine Empty z = z
seqSpine (MinQueue _ _ ts) z = seqSpineF ts z
seqSpineF :: BinomForest rk a -> b -> b
seqSpineF Nil z = z
seqSpineF (Skip ts') z = seqSpineF ts' z
seqSpineF (Cons _ ts') z = seqSpineF ts' z
keysQueue :: Prio.MinPQueue k a -> MinQueue k
keysQueue Prio.Empty = Empty
keysQueue (Prio.MinPQ n k _ ts) = MinQueue n k (keysF (const Zero) ts)
keysF :: (pRk k a -> rk k) -> Prio.BinomForest pRk k a -> BinomForest rk k
keysF f ts0 = case ts0 of
Prio.Nil -> Nil
Prio.Skip ts' -> Skip (keysF f' ts')
Prio.Cons (Prio.BinomTree k _ ts) ts'
-> Cons (BinomTree k (f ts)) (keysF f' ts')
where f' (Prio.Succ (Prio.BinomTree k _ ts) tss) = Succ (BinomTree k (f ts)) (f tss)
class NFRank rk where
rnfRk :: NFData a => rk a -> ()
instance NFRank Zero where
rnfRk _ = ()
instance NFRank rk => NFRank (Succ rk) where
rnfRk (Succ t ts) = t `deepseq` rnfRk ts
instance (NFData a, NFRank rk) => NFData (BinomTree rk a) where
rnf (BinomTree x ts) = x `deepseq` rnfRk ts
instance (NFData a, NFRank rk) => NFData (BinomForest rk a) where
rnf Nil = ()
rnf (Skip ts) = rnf ts
rnf (Cons t ts) = t `deepseq` rnf ts
instance NFData a => NFData (MinQueue a) where
rnf Empty = ()
rnf (MinQueue _ x ts) = x `deepseq` rnf ts