{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
#if __GLASGOW_HASKELL__ >= 702
#endif
#if __GLASGOW_HASKELL__ >= 710
{-# LANGUAGE AutoDeriveTypeable #-}
#endif
module HaskellWorks.Data.SegmentSet.Strict
(
Segment(..), point,
SegmentSet(..),
OrderedMap(..),
delete,
empty,
fromList,
insert,
singleton,
update,
segmentSetToList,
Item(..),
cappedL,
cappedM
) where
import Control.Applicative ((<$>))
import Control.DeepSeq (NFData)
import Data.Foldable (Foldable (foldMap), foldl', toList)
import Data.Semigroup
import Data.Traversable (Traversable (traverse))
import GHC.Generics (Generic)
import HaskellWorks.Data.FingerTree.Strict (FingerTree, Measured (..), ViewL (..), ViewR (..), viewl, viewr, (<|), (><))
import HaskellWorks.Data.Item.Strict
import HaskellWorks.Data.Segment.Strict
import qualified HaskellWorks.Data.FingerTree.Strict as FT
{-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}
infixr 5 >*<
newtype OrderedMap k a = OrderedMap (FingerTree k (Item k a)) deriving (Show, Generic, NFData)
newtype SegmentSet k = SegmentSet (OrderedMap (Max k) (Segment k)) deriving (Show, Generic, NFData)
instance Functor (OrderedMap k) where
fmap f (OrderedMap t) = OrderedMap (FT.unsafeFmap (fmap f) t)
instance Foldable (OrderedMap k) where
foldMap f (OrderedMap t) = foldMap (foldMap f) t
instance Traversable (OrderedMap k) where
traverse f (OrderedMap t) = OrderedMap <$> FT.unsafeTraverse (traverse f) t
segmentSetToList :: SegmentSet k -> [Segment k]
segmentSetToList (SegmentSet m) = toList m
empty :: SegmentSet k
empty = SegmentSet (OrderedMap FT.empty)
singleton :: Segment k -> SegmentSet k
singleton s@(Segment lo hi) = SegmentSet $ OrderedMap $ FT.singleton $ Item (Max lo) s
delete :: forall k a. (Bounded k, Ord k, Enum k, Show k)
=> Segment k
-> SegmentSet k
-> SegmentSet k
delete = flip update False
insert :: forall k a. (Bounded k, Ord k, Enum k, Show k)
=> Segment k
-> SegmentSet k
-> SegmentSet k
insert = flip update True
update :: forall k a. (Ord k, Enum k, Bounded k, Show k)
=> Segment k
-> Bool
-> SegmentSet k
-> SegmentSet k
update (Segment lo hi) _ m | lo > hi = m
update s@(Segment lo hi) b (SegmentSet (OrderedMap t)) =
SegmentSet $ OrderedMap contents
where
contents = if b then at >*< bbbb >*< cccc else at >*< cccc
(fstPivotLt, fstPivotRt) = FT.split (>= Max lo) t
(at, atSurplus) = cappedL lo fstPivotLt
(zs, remainder) = FT.split (> Max hi) (atSurplus >*< fstPivotRt)
e = maybe FT.Empty FT.singleton (FT.maybeLast zs >>= capM hi)
rt = e >< remainder
cccc = cappedM hi rt
bbbb = FT.singleton (Item (Max lo) s)
cappedL :: (Enum k, Ord k, Bounded k, Show k)
=> k
-> FingerTree (Max k) (Item (Max k) (Segment k))
-> (FingerTree (Max k) (Item (Max k) (Segment k)), FingerTree (Max k) (Item (Max k) (Segment k)))
cappedL lo t = case viewr t of
EmptyR -> (FT.empty, FT.empty)
ltp :> item -> resolve ltp item
where resolve ltp (Item _ (Segment lilo lihi))
| lo <= lilo = (ltp , FT.empty)
| lo < lihi = (ltp >< lPart, rPart )
| lo <= lihi = (ltp >< lPart, FT.empty)
| otherwise = (t , FT.empty)
where lPart = FT.singleton (Item (Max lilo) (Segment lilo (pred lo)))
rPart = FT.singleton (Item (Max lo ) (Segment lo lihi ))
cappedM :: (Enum k, Ord k, Bounded k, Show k)
=> k
-> FingerTree (Max k) (Item (Max k) (Segment k))
-> FingerTree (Max k) (Item (Max k) (Segment k))
cappedM hi t = case viewl t of
EmptyL -> t
n :< rtp -> maybe rtp (<| rtp) (capM hi n)
capM :: (Ord k, Enum k, Show k)
=> k
-> Item (Max k) (Segment k)
-> Maybe (Item (Max k) (Segment k))
capM lihi n@(Item _ (Segment rilo rihi))
| lihi < rilo = Just n
| lihi < rihi = Just $ Item (Max (succ lihi)) (Segment (succ lihi) rihi)
| otherwise = Nothing
fromList :: (Ord v, Enum v, Bounded v, Show v)
=> [Segment v]
-> SegmentSet v
fromList = foldl' (flip insert) empty
merge :: (Ord k, Enum k, Bounded k)
=> FingerTree (Max k) (Item (Max k) (Segment k))
-> FingerTree (Max k) (Item (Max k) (Segment k))
-> FingerTree (Max k) (Item (Max k) (Segment k))
merge lt rt = case viewr lt of
EmptyR -> rt
treeL :> Item _ (Segment loL hiL) -> case viewl rt of
EmptyL -> lt
Item _ (Segment loR hiR) :< treeR ->
if succ hiL >= loR
then treeL >< FT.singleton (Item (Max loL) (Segment loL hiR)) >< treeR
else lt >< rt
(>*<) :: (Ord k, Enum k, Bounded k)
=> FingerTree (Max k) (Item (Max k) (Segment k))
-> FingerTree (Max k) (Item (Max k) (Segment k))
-> FingerTree (Max k) (Item (Max k) (Segment k))
(>*<) = merge