{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE FlexibleContexts #-}
module Data.IntervalSet (
Interval(..)
, IntervalSet(..)
, (\\)
, null
, size
, member
, notMember
, lookupLT
, lookupGT
, lookupLE
, lookupGE
, containing
, intersecting
, within
, empty
, singleton
, insert
, delete
, union
, unions
, difference
, intersection
, map
, mapMonotonic
, foldr, foldl
, foldl', foldr'
, flattenWith, flattenWithMonotonic
, elems
, toList
, fromList
, toAscList
, toDescList
, fromAscList
, fromDistinctAscList
, filter
, partition
, split
, splitMember
, splitAt
, splitIntersecting
, isSubsetOf, isProperSubsetOf
, findMin
, findMax
, findLast
, deleteMin
, deleteMax
, deleteFindMin
, deleteFindMax
, minView
, maxView
, valid
) where
import Prelude hiding (null, map, filter, foldr, foldl, splitAt)
import Data.Bits (shiftR, (.&.))
import qualified Data.Semigroup as Sem
import Data.Monoid (Monoid(..))
import qualified Data.Foldable as Foldable
import qualified Data.List as L
import Control.DeepSeq
import Control.Applicative ((<|>))
import Data.IntervalMap.Generic.Interval
infixl 9 \\
(\\) :: (Interval k e, Ord k) => IntervalSet k -> IntervalSet k -> IntervalSet k
m1 \\ m2 = difference m1 m2
data Color = R | B deriving (Eq)
data IntervalSet k = Nil
| Node !Color
!k
!k
!(IntervalSet k)
!(IntervalSet k)
instance (Eq k) => Eq (IntervalSet k) where
a == b = toAscList a == toAscList b
instance (Ord k) => Ord (IntervalSet k) where
compare a b = compare (toAscList a) (toAscList b)
instance (Interval i k, Ord i) => Sem.Semigroup (IntervalSet i) where
(<>) = union
sconcat = unions . Foldable.toList
stimes = Sem.stimesIdempotentMonoid
instance (Interval i k, Ord i) => Monoid (IntervalSet i) where
mempty = empty
mappend = union
mconcat = unions
instance Foldable.Foldable IntervalSet where
fold t = go t
where go Nil = mempty
go (Node _ k _ l r) = go l `mappend` (k `mappend` go r)
foldr = foldr
foldl = foldl
foldMap f t = go t
where go Nil = mempty
go (Node _ k _ l r) = go l `mappend` (f k `mappend` go r)
instance (NFData k) => NFData (IntervalSet k) where
rnf Nil = ()
rnf (Node _ kx _ l r) = kx `deepseq` l `deepseq` r `deepseq` ()
instance (Interval i k, Ord i, Read i) => Read (IntervalSet i) where
readsPrec p = readParen (p > 10) $ \ r -> do
("fromList",s) <- lex r
(xs,t) <- reads s
return (fromList xs,t)
instance (Show k) => Show (IntervalSet k) where
showsPrec d m = showParen (d > 10) $
showString "fromList " . shows (toList m)
isRed :: IntervalSet k -> Bool
isRed (Node R _ _ _ _) = True
isRed _ = False
turnBlack :: IntervalSet k -> IntervalSet k
turnBlack (Node R k m l r) = Node B k m l r
turnBlack t = t
turnRed :: IntervalSet k -> IntervalSet k
turnRed Nil = error "turnRed: Leaf"
turnRed (Node B k m l r) = Node R k m l r
turnRed t = t
mNode :: (Interval k e) => Color -> k -> IntervalSet k -> IntervalSet k -> IntervalSet k
mNode c k l r = Node c k (maxUpper k l r) l r
maxUpper :: (Interval i k) => i -> IntervalSet i -> IntervalSet i -> i
maxUpper k Nil Nil = k
maxUpper k Nil (Node _ _ m _ _) = maxByUpper k m
maxUpper k (Node _ _ m _ _) Nil = maxByUpper k m
maxUpper k (Node _ _ l _ _) (Node _ _ r _ _) = maxByUpper k (maxByUpper l r)
maxByUpper :: (Interval i e) => i -> i -> i
maxByUpper a b = a `seq` b `seq`
case compareUpperBounds a b of
LT -> b
_ -> a
empty :: IntervalSet k
empty = Nil
singleton :: k -> IntervalSet k
singleton k = Node B k k Nil Nil
null :: IntervalSet k -> Bool
null Nil = True
null _ = False
size :: IntervalSet k -> Int
size t = h 0 t
where
h n s = n `seq` case s of
Nil -> n
Node _ _ _ l r -> h (h n l + 1) r
member :: (Ord k) => k -> IntervalSet k -> Bool
member k Nil = k `seq` False
member k (Node _ key _ l r) = case compare k key of
LT -> member k l
GT -> member k r
EQ -> True
notMember :: (Ord k) => k -> IntervalSet k -> Bool
notMember key tree = not (member key tree)
lookupLT :: (Ord k) => k -> IntervalSet k -> Maybe k
lookupLT k m = go m
where
go Nil = Nothing
go (Node _ key _ l r) | k <= key = go l
| otherwise = go1 key r
go1 rk Nil = Just rk
go1 rk (Node _ key _ l r) | k <= key = go1 rk l
| otherwise = go1 key r
lookupGT :: (Ord k) => k -> IntervalSet k -> Maybe k
lookupGT k m = go m
where
go Nil = Nothing
go (Node _ key _ l r) | k >= key = go r
| otherwise = go1 key l
go1 rk Nil = Just rk
go1 rk (Node _ key _ l r) | k >= key = go1 rk r
| otherwise = go1 key l
lookupLE :: (Ord k) => k -> IntervalSet k -> Maybe k
lookupLE k m = go m
where
go Nil = Nothing
go (Node _ key _ l r) = case compare k key of
LT -> go l
EQ -> Just key
GT -> go1 key r
go1 rk Nil = Just rk
go1 rk (Node _ key _ l r) = case compare k key of
LT -> go1 rk l
EQ -> Just key
GT -> go1 key r
lookupGE :: (Ord k) => k -> IntervalSet k -> Maybe k
lookupGE k m = go m
where
go Nil = Nothing
go (Node _ key _ l r) = case compare k key of
LT -> go1 key l
EQ -> Just key
GT -> go r
go1 rk Nil = Just rk
go1 rk (Node _ key _ l r) = case compare k key of
LT -> go1 key l
EQ -> Just key
GT -> go1 rk r
containing :: (Interval k e) => IntervalSet k -> e -> IntervalSet k
t `containing` p = p `seq` fromDistinctAscList (go [] t)
where
go xs Nil = xs
go xs (Node _ k m l r)
| p `above` m = xs
| p `below` k = go xs l
| p `inside` k = go (k : go xs r) l
| otherwise = go (go xs r) l
intersecting :: (Interval k e) => IntervalSet k -> k -> IntervalSet k
t `intersecting` i = i `seq` fromDistinctAscList (go [] t)
where
go xs Nil = xs
go xs (Node _ k m l r)
| i `after` m = xs
| i `before` k = go xs l
| i `overlaps` k = go (k : go xs r) l
| otherwise = go (go xs r) l
within :: (Interval k e) => IntervalSet k -> k -> IntervalSet k
t `within` i = i `seq` fromDistinctAscList (go [] t)
where
go xs Nil = xs
go xs (Node _ k m l r)
| i `after` m = xs
| i `before` k = go xs l
| i `subsumes` k = go (k : go xs r) l
| otherwise = go (go xs r) l
insert :: (Interval k e, Ord k) => k -> IntervalSet k -> IntervalSet k
insert v s = v `seq` turnBlack (ins s)
where
singletonR k = Node R k k Nil Nil
ins Nil = singletonR v
ins (Node color k m l r) =
case compare v k of
LT -> balanceL color k (ins l) r
GT -> balanceR color k l (ins r)
EQ -> Node color v m l r
balanceL :: (Interval k e) => Color -> k -> IntervalSet k -> IntervalSet k -> IntervalSet k
balanceL B zk (Node R yk _ (Node R xk _ a b) c) d =
mNode R yk (mNode B xk a b) (mNode B zk c d)
balanceL B zk (Node R xk _ a (Node R yk _ b c)) d =
mNode R yk (mNode B xk a b) (mNode B zk c d)
balanceL c xk l r = mNode c xk l r
balanceR :: (Interval k e) => Color -> k -> IntervalSet k -> IntervalSet k -> IntervalSet k
balanceR B xk a (Node R yk _ b (Node R zk _ c d)) =
mNode R yk (mNode B xk a b) (mNode B zk c d)
balanceR B xk a (Node R zk _ (Node R yk _ b c) d) =
mNode R yk (mNode B xk a b) (mNode B zk c d)
balanceR c xk l r = mNode c xk l r
findMin :: IntervalSet k -> Maybe k
findMin (Node _ k _ Nil _) = Just k
findMin (Node _ _ _ l _) = findMin l
findMin Nil = Nothing
findMax :: IntervalSet k -> Maybe k
findMax (Node _ k _ _ Nil) = Just k
findMax (Node _ _ _ _ r) = findMax r
findMax Nil = Nothing
findLast :: (Interval k e) => IntervalSet k -> Maybe k
findLast Nil = Nothing
findLast t@(Node _ _ mx _ _) = go t
where
go (Node _ k m l r) | sameU m mx = if sameU k m then go r <|> Just k
else go r <|> go l
| otherwise = Nothing
go Nil = Nothing
sameU a b = compareUpperBounds a b == EQ
data DeleteResult k = U !(IntervalSet k)
| S !(IntervalSet k)
unwrap :: DeleteResult k -> IntervalSet k
unwrap (U m) = m
unwrap (S m) = m
data DeleteResult' k a = U' !(IntervalSet k) a
| S' !(IntervalSet k) a
unwrap' :: DeleteResult' k a -> IntervalSet k
unwrap' (U' m _) = m
unwrap' (S' m _) = m
annotate :: DeleteResult k -> a -> DeleteResult' k a
annotate (U m) x = U' m x
annotate (S m) x = S' m x
deleteMin :: (Interval k e, Ord k) => IntervalSet k -> IntervalSet k
deleteMin Nil = Nil
deleteMin m = turnBlack (unwrap' (deleteMin' m))
deleteMin' :: (Interval k e, Ord k) => IntervalSet k -> DeleteResult' k k
deleteMin' Nil = error "deleteMin': Nil"
deleteMin' (Node B k _ Nil Nil) = S' Nil k
deleteMin' (Node B k _ Nil r@(Node R _ _ _ _)) = U' (turnBlack r) k
deleteMin' (Node R k _ Nil r) = U' r k
deleteMin' (Node c k _ l r) =
case deleteMin' l of
(U' l' kv) -> U' (mNode c k l' r) kv
(S' l' kv) -> annotate (unbalancedR c k l' r) kv
deleteMax' :: (Interval k e, Ord k) => IntervalSet k -> DeleteResult' k k
deleteMax' Nil = error "deleteMax': Nil"
deleteMax' (Node B k _ Nil Nil) = S' Nil k
deleteMax' (Node B k _ l@(Node R _ _ _ _) Nil) = U' (turnBlack l) k
deleteMax' (Node R k _ l Nil) = U' l k
deleteMax' (Node c k _ l r) =
case deleteMax' r of
(U' r' kv) -> U' (mNode c k l r') kv
(S' r' kv) -> annotate (unbalancedL c k l r') kv
unbalancedR :: (Interval k e, Ord k) => Color -> k -> IntervalSet k -> IntervalSet k -> DeleteResult k
unbalancedR B k l r@(Node B _ _ _ _) = S (balanceR B k l (turnRed r))
unbalancedR R k l r@(Node B _ _ _ _) = U (balanceR B k l (turnRed r))
unbalancedR B k l (Node R rk _ rl@(Node B _ _ _ _) rr)
= U (mNode B rk (balanceR B k l (turnRed rl)) rr)
unbalancedR _ _ _ _ = error "unbalancedR"
unbalancedL :: (Interval k e, Ord k) => Color -> k -> IntervalSet k -> IntervalSet k -> DeleteResult k
unbalancedL R k l@(Node B _ _ _ _) r = U (balanceL B k (turnRed l) r)
unbalancedL B k l@(Node B _ _ _ _) r = S (balanceL B k (turnRed l) r)
unbalancedL B k (Node R lk _ ll lr@(Node B _ _ _ _)) r
= U (mNode B lk ll (balanceL B k (turnRed lr) r))
unbalancedL _ _ _ _ = error "unbalancedL"
deleteMax :: (Interval k e, Ord k) => IntervalSet k -> IntervalSet k
deleteMax Nil = Nil
deleteMax m = turnBlack (unwrap' (deleteMax' m))
deleteFindMin :: (Interval k e, Ord k) => IntervalSet k -> (k, IntervalSet k)
deleteFindMin mp = case deleteMin' mp of
(U' r v) -> (v, turnBlack r)
(S' r v) -> (v, turnBlack r)
deleteFindMax :: (Interval k e, Ord k) => IntervalSet k -> (k, IntervalSet k)
deleteFindMax mp = case deleteMax' mp of
(U' r v) -> (v, turnBlack r)
(S' r v) -> (v, turnBlack r)
minView :: (Interval k e, Ord k) => IntervalSet k -> Maybe (k, IntervalSet k)
minView Nil = Nothing
minView x = Just (deleteFindMin x)
maxView :: (Interval k e, Ord k) => IntervalSet k -> Maybe (k, IntervalSet k)
maxView Nil = Nothing
maxView x = Just (deleteFindMax x)
foldr :: (k -> b -> b) -> b -> IntervalSet k -> b
foldr _ z Nil = z
foldr f z (Node _ k _ l r) = foldr f (f k (foldr f z r)) l
foldr' :: (k -> b -> b) -> b -> IntervalSet k -> b
foldr' f z s = z `seq` case s of
Nil -> z
Node _ k _ l r -> foldr' f (f k (foldr' f z r)) l
foldl :: (b -> k -> b) -> b -> IntervalSet k -> b
foldl _ z Nil = z
foldl f z (Node _ k _ l r) = foldl f (f (foldl f z l) k) r
foldl' :: (b -> k -> b) -> b -> IntervalSet k -> b
foldl' f z s = z `seq` case s of
Nil -> z
Node _ k _ l r -> foldl' f (f (foldl' f z l) k) r
delete :: (Interval k e, Ord k) => k -> IntervalSet k -> IntervalSet k
delete key mp = turnBlack (unwrap (delete' key mp))
delete' :: (Interval k e, Ord k) => k -> IntervalSet k -> DeleteResult k
delete' x Nil = x `seq` U Nil
delete' x (Node c k _ l r) =
case compare x k of
LT -> case delete' x l of
(U l') -> U (mNode c k l' r)
(S l') -> unbalancedR c k l' r
GT -> case delete' x r of
(U r') -> U (mNode c k l r')
(S r') -> unbalancedL c k l r'
EQ -> case r of
Nil -> if c == B then blackify l else U l
_ -> case deleteMin' r of
(U' r' rk) -> U (mNode c rk l r')
(S' r' rk) -> unbalancedL c rk l r'
blackify :: IntervalSet k -> DeleteResult k
blackify (Node R k m l r) = U (Node B k m l r)
blackify s = S s
union :: (Interval k e, Ord k) => IntervalSet k -> IntervalSet k -> IntervalSet k
union m1 m2 = fromDistinctAscList (ascListUnion (toAscList m1) (toAscList m2))
unions :: (Interval k e, Ord k) => [IntervalSet k] -> IntervalSet k
unions [] = empty
unions [s] = s
unions iss = fromDistinctAscList (head (go (L.map toAscList iss)))
where
go [] = []
go xs@[_] = xs
go (x:y:xs) = go (ascListUnion x y : go xs)
difference :: (Interval k e, Ord k) => IntervalSet k -> IntervalSet k -> IntervalSet k
difference m1 m2 = fromDistinctAscList (ascListDifference (toAscList m1) (toAscList m2))
intersection :: (Interval k e, Ord k) => IntervalSet k -> IntervalSet k -> IntervalSet k
intersection m1 m2 = fromDistinctAscList (ascListIntersection (toAscList m1) (toAscList m2))
ascListUnion :: Ord k => [k] -> [k] -> [k]
ascListUnion [] [] = []
ascListUnion [] ys = ys
ascListUnion xs [] = xs
ascListUnion xs@(x:xs') ys@(y:ys') =
case compare x y of
LT -> x : ascListUnion xs' ys
GT -> y : ascListUnion xs ys'
EQ -> x : ascListUnion xs' ys'
ascListDifference :: Ord k => [k] -> [k] -> [k]
ascListDifference [] _ = []
ascListDifference xs [] = xs
ascListDifference xs@(xk:xs') ys@(yk:ys') =
case compare xk yk of
LT -> xk : ascListDifference xs' ys
GT -> ascListDifference xs ys'
EQ -> ascListDifference xs' ys'
ascListIntersection :: Ord k => [k] -> [k] -> [k]
ascListIntersection [] _ = []
ascListIntersection _ [] = []
ascListIntersection xs@(xk:xs') ys@(yk:ys') =
case compare xk yk of
LT -> ascListIntersection xs' ys
GT -> ascListIntersection xs ys'
EQ -> xk : ascListIntersection xs' ys'
toAscList :: IntervalSet k -> [k]
toAscList set = toAscList' set []
toAscList' :: IntervalSet k -> [k] -> [k]
toAscList' m xs = foldr (:) xs m
toList :: IntervalSet k -> [k]
toList s = go s []
where
go Nil xs = xs
go (Node _ k _ l r) xs = k : go l (go r xs)
toDescList :: IntervalSet k -> [k]
toDescList m = foldl (flip (:)) [] m
fromList :: (Interval k e, Ord k) => [k] -> IntervalSet k
fromList xs = L.foldl' (flip insert) empty xs
fromAscList :: (Interval k e, Eq k) => [k] -> IntervalSet k
fromAscList xs = fromDistinctAscList (uniq xs)
uniq :: Eq k => [k] -> [k]
uniq [] = []
uniq (x:xs) = go x xs
where
go v [] = [v]
go v (y:ys) | v == y = go v ys
| otherwise = v : go y ys
data T2 a b = T2 !a !b
fromDistinctAscList :: (Interval k e) => [k] -> IntervalSet k
fromDistinctAscList lyst = case h (length lyst) lyst of
(T2 result []) -> result
_ -> error "fromDistinctAscList: list not fully consumed"
where
h n xs | n == 0 = T2 Nil xs
| isPerfect n = buildB n xs
| otherwise = buildR n (log2 n) xs
buildB n xs | xs `seq` n <= 0 = error "fromDictinctAscList: buildB 0"
| n == 1 = case xs of (k:xs') -> T2 (Node B k k Nil Nil) xs'
_ -> error "fromDictinctAscList: buildB 1"
| otherwise =
case n `quot` 2 of { n' ->
case buildB n' xs of { (T2 _ []) -> error "fromDictinctAscList: buildB n";
(T2 l (k:xs')) ->
case buildB n' xs' of { (T2 r xs'') ->
T2 (mNode B k l r) xs'' }}}
buildR n d xs | d `seq` xs `seq` n == 0 = T2 Nil xs
| n == 1 = case xs of (k:xs') -> T2 (Node (if d==0 then R else B) k k Nil Nil) xs'
_ -> error "fromDistinctAscList: buildR 1"
| otherwise =
case n `quot` 2 of { n' ->
case buildR n' (d-1) xs of { (T2 _ []) -> error "fromDistinctAscList: buildR n";
(T2 l (k:xs')) ->
case buildR (n - (n' + 1)) (d-1) xs' of { (T2 r xs'') ->
T2 (mNode B k l r) xs'' }}}
isPerfect :: Int -> Bool
isPerfect n = (n .&. (n + 1)) == 0
log2 :: Int -> Int
log2 m = h (-1) m
where
h r n | r `seq` n <= 0 = r
| otherwise = h (r + 1) (n `shiftR` 1)
elems :: IntervalSet k -> [k]
elems s = toAscList s
map :: (Interval b e2, Ord b) => (a -> b) -> IntervalSet a -> IntervalSet b
map f s = fromList [f x | x <- toList s]
mapMonotonic :: (Interval k2 e, Ord k2) => (k1 -> k2) -> IntervalSet k1 -> IntervalSet k2
mapMonotonic _ Nil = Nil
mapMonotonic f (Node c k _ l r) =
mNode c (f k) (mapMonotonic f l) (mapMonotonic f r)
filter :: (Interval k e) => (k -> Bool) -> IntervalSet k -> IntervalSet k
filter p s = fromDistinctAscList (L.filter p (toAscList s))
partition :: (Interval k e) => (k -> Bool) -> IntervalSet k -> (IntervalSet k, IntervalSet k)
partition p s = let (xs,ys) = L.partition p (toAscList s)
in (fromDistinctAscList xs, fromDistinctAscList ys)
split :: (Interval i k, Ord i) => i -> IntervalSet i -> (IntervalSet i, IntervalSet i)
split x m = (l, r)
where (l, _, r) = splitMember x m
splitMember :: (Interval i k, Ord i) => i -> IntervalSet i -> (IntervalSet i, Bool, IntervalSet i)
splitMember x s = case span (< x) (toAscList s) of
([], []) -> (empty, False, empty)
([], y:_) | y == x -> (empty, True, deleteMin s)
| otherwise -> (empty, False, s)
(_, []) -> (s, False, empty)
(lt, ge@(y:gt)) | y == x -> (fromDistinctAscList lt, True, fromDistinctAscList gt)
| otherwise -> (fromDistinctAscList lt, False, fromDistinctAscList ge)
data Union k = UEmpty | Union !(Union k) !(Union k)
| UCons !k !(Union k)
| UAppend !(IntervalSet k) !(Union k)
mkUnion :: Union a -> Union a -> Union a
mkUnion UEmpty u = u
mkUnion u UEmpty = u
mkUnion u1 u2 = Union u1 u2
fromUnion :: Interval k e => Union k -> IntervalSet k
fromUnion UEmpty = empty
fromUnion (UCons key UEmpty) = singleton key
fromUnion (UAppend set UEmpty) = turnBlack set
fromUnion x = fromDistinctAscList (unfold x [])
where
unfold UEmpty r = r
unfold (Union a b) r = unfold a (unfold b r)
unfold (UCons k u) r = k : unfold u r
unfold (UAppend s u) r = toAscList' s (unfold u r)
splitAt :: (Interval i k) => IntervalSet i -> k -> (IntervalSet i, IntervalSet i, IntervalSet i)
splitAt set p = (fromUnion (lower set), set `containing` p, fromUnion (higher set))
where
lower Nil = UEmpty
lower s@(Node _ k m l r)
| p `above` m = UAppend s UEmpty
| p `below` k = lower l
| p `inside` k = mkUnion (lower l) (lower r)
| otherwise = mkUnion (lower l) (UCons k (lower r))
higher Nil = UEmpty
higher (Node _ k m l r)
| p `above` m = UEmpty
| p `below` k = mkUnion (higher l) (UCons k (UAppend r UEmpty))
| otherwise = higher r
splitIntersecting :: (Interval i k, Ord i) => IntervalSet i -> i -> (IntervalSet i, IntervalSet i, IntervalSet i)
splitIntersecting set i = (fromUnion (lower set), set `intersecting` i, fromUnion (higher set))
where
lower Nil = UEmpty
lower s@(Node _ k m l r)
| i `after` m = UAppend s UEmpty
| i <= k = lower l
| i `overlaps` k = mkUnion (lower l) (lower r)
| otherwise = mkUnion (lower l) (UCons k (lower r))
higher Nil = UEmpty
higher (Node _ k m l r)
| i `after` m = UEmpty
| i `before` k = mkUnion (higher l) (UCons k (UAppend r UEmpty))
| otherwise = higher r
isSubsetOf :: (Ord k) => IntervalSet k -> IntervalSet k -> Bool
isSubsetOf set1 set2 = ascListSubset (toAscList set1) (toAscList set2)
ascListSubset :: (Ord a) => [a] -> [a] -> Bool
ascListSubset [] _ = True
ascListSubset (_:_) [] = False
ascListSubset s1@(k1:r1) (k2:r2) =
case compare k1 k2 of
GT -> ascListSubset s1 r2
EQ -> ascListSubset r1 r2
LT -> False
isProperSubsetOf :: (Ord k) => IntervalSet k -> IntervalSet k -> Bool
isProperSubsetOf set1 set2 = go (toAscList set1) (toAscList set2)
where
go [] (_:_) = True
go _ [] = False
go s1@(k1:r1) (k2:r2) =
case compare k1 k2 of
GT -> ascListSubset s1 r2
EQ -> go r1 r2
LT -> False
flattenWith :: (Ord a, Interval a e) => (a -> a -> Maybe a) -> IntervalSet a -> IntervalSet a
flattenWith combine set = fromList (combineSuccessive combine set)
flattenWithMonotonic :: (Interval a e) => (a -> a -> Maybe a) -> IntervalSet a -> IntervalSet a
flattenWithMonotonic combine set = fromDistinctAscList (combineSuccessive combine set)
combineSuccessive :: (a -> a -> Maybe a) -> IntervalSet a -> [a]
combineSuccessive combine set = go (toAscList set)
where
go (x : xs@(_:_)) = go1 x xs
go xs = xs
go1 x (y:ys) = case combine x y of
Nothing -> x : go1 y ys
Just x' -> go1 x' ys
go1 x [] = [x]
height :: IntervalSet k -> Int
height Nil = 0
height (Node _ _ _ l r) = 1 + max (height l) (height r)
maxHeight :: Int -> Int
maxHeight nodes = 2 * log2 (nodes + 1)
valid :: (Interval i k, Ord i) => IntervalSet i -> Bool
valid mp = test mp && height mp <= maxHeight (size mp) && validColor mp
where
test Nil = True
test n@(Node _ _ _ l r) = validOrder n && validMax n && test l && test r
validMax (Node _ k m lo hi) = m == maxUpper k lo hi
validMax Nil = True
validOrder (Node _ _ _ Nil Nil) = True
validOrder (Node _ k1 _ Nil (Node _ k2 _ _ _)) = k1 < k2
validOrder (Node _ k2 _ (Node _ k1 _ _ _) Nil) = k1 < k2
validOrder (Node _ k2 _ (Node _ k1 _ _ _) (Node _ k3 _ _ _)) = k1 < k2 && k2 < k3
validOrder Nil = True
validColor n = blackDepth n >= 0
blackDepth :: IntervalSet k -> Int
blackDepth Nil = 0
blackDepth (Node c _ _ l r) = case blackDepth l of
ld -> if ld < 0 then ld
else
case blackDepth r of
rd | rd < 0 -> rd
| rd /= ld || (c == R && (isRed l || isRed r)) -> -1
| c == B -> rd + 1
| otherwise -> rd