#if __GLASGOW_HASKELL__
#endif
#if !defined(TESTING) && defined(__GLASGOW_HASKELL__)
#endif
#if __GLASGOW_HASKELL__ >= 708
#endif
#include "containers.h"
module Data.IntSet.Internal (
IntSet(..), Key
, Prefix, Mask, BitMap
, (\\)
, null
, size
, member
, notMember
, lookupLT
, lookupGT
, lookupLE
, lookupGE
, isSubsetOf
, isProperSubsetOf
, disjoint
, empty
, singleton
, insert
, delete
, alterF
, union
, unions
, difference
, intersection
, filter
, partition
, split
, splitMember
, splitRoot
, map
, mapMonotonic
, foldr
, foldl
, foldr'
, foldl'
, fold
, findMin
, findMax
, deleteMin
, deleteMax
, deleteFindMin
, deleteFindMax
, maxView
, minView
, elems
, toList
, fromList
, toAscList
, toDescList
, fromAscList
, fromDistinctAscList
, showTree
, showTreeWith
, match
, suffixBitMask
, prefixBitMask
, bitmapOf
, zero
) where
import Control.Applicative (Const(..))
import Control.DeepSeq (NFData(rnf))
import Data.Bits
import qualified Data.List as List
import Data.Maybe (fromMaybe)
#if !MIN_VERSION_base(4,8,0)
import Data.Monoid (Monoid(..))
import Data.Word (Word)
#endif
#if MIN_VERSION_base(4,9,0)
import Data.Semigroup (Semigroup(stimes))
#endif
#if !(MIN_VERSION_base(4,11,0)) && MIN_VERSION_base(4,9,0)
import Data.Semigroup (Semigroup((<>)))
#endif
#if MIN_VERSION_base(4,9,0)
import Data.Semigroup (stimesIdempotentMonoid)
#endif
import Data.Typeable
import Prelude hiding (filter, foldr, foldl, null, map)
import Utils.Containers.Internal.BitUtil
import Utils.Containers.Internal.StrictPair
#if __GLASGOW_HASKELL__
import Data.Data (Data(..), Constr, mkConstr, constrIndex, DataType, mkDataType)
import qualified Data.Data
import Text.Read
#endif
#if __GLASGOW_HASKELL__
import qualified GHC.Exts
#if !(MIN_VERSION_base(4,8,0) && (WORD_SIZE_IN_BITS==64))
import qualified GHC.Int
#endif
#endif
import qualified Data.Foldable as Foldable
#if MIN_VERSION_base(4,8,0)
import Data.Functor.Identity (Identity(..))
#else
import Data.Foldable (Foldable())
#endif
infixl 9 \\
type Nat = Word
natFromInt :: Int -> Nat
natFromInt i = fromIntegral i
intFromNat :: Nat -> Int
intFromNat w = fromIntegral w
(\\) :: IntSet -> IntSet -> IntSet
m1 \\ m2 = difference m1 m2
data IntSet = Bin !Prefix !Mask !IntSet !IntSet
| Tip !Prefix !BitMap
| Nil
type Prefix = Int
type Mask = Int
type BitMap = Word
type Key = Int
instance Monoid IntSet where
mempty = empty
mconcat = unions
#if !(MIN_VERSION_base(4,9,0))
mappend = union
#else
mappend = (<>)
instance Semigroup IntSet where
(<>) = union
stimes = stimesIdempotentMonoid
#endif
#if __GLASGOW_HASKELL__
instance Data IntSet where
gfoldl f z is = z fromList `f` (toList is)
toConstr _ = fromListConstr
gunfold k z c = case constrIndex c of
1 -> k (z fromList)
_ -> error "gunfold"
dataTypeOf _ = intSetDataType
fromListConstr :: Constr
fromListConstr = mkConstr intSetDataType "fromList" [] Data.Data.Prefix
intSetDataType :: DataType
intSetDataType = mkDataType "Data.IntSet.Internal.IntSet" [fromListConstr]
#endif
null :: IntSet -> Bool
null Nil = True
null _ = False
size :: IntSet -> Int
size = go 0
where
go !acc (Bin _ _ l r) = go (go acc l) r
go acc (Tip _ bm) = acc + bitcount 0 bm
go acc Nil = acc
member :: Key -> IntSet -> Bool
member !x = go
where
go (Bin p m l r)
| nomatch x p m = False
| zero x m = go l
| otherwise = go r
go (Tip y bm) = prefixOf x == y && bitmapOf x .&. bm /= 0
go Nil = False
notMember :: Key -> IntSet -> Bool
notMember k = not . member k
lookupLT :: Key -> IntSet -> Maybe Key
lookupLT !x t = case t of
Bin _ m l r | m < 0 -> if x >= 0 then go r l else go Nil r
_ -> go Nil t
where
go def (Bin p m l r) | nomatch x p m = if x < p then unsafeFindMax def else unsafeFindMax r
| zero x m = go def l
| otherwise = go l r
go def (Tip kx bm) | prefixOf x > kx = Just $ kx + highestBitSet bm
| prefixOf x == kx && maskLT /= 0 = Just $ kx + highestBitSet maskLT
| otherwise = unsafeFindMax def
where maskLT = (bitmapOf x 1) .&. bm
go def Nil = unsafeFindMax def
lookupGT :: Key -> IntSet -> Maybe Key
lookupGT !x t = case t of
Bin _ m l r | m < 0 -> if x >= 0 then go Nil l else go l r
_ -> go Nil t
where
go def (Bin p m l r) | nomatch x p m = if x < p then unsafeFindMin l else unsafeFindMin def
| zero x m = go r l
| otherwise = go def r
go def (Tip kx bm) | prefixOf x < kx = Just $ kx + lowestBitSet bm
| prefixOf x == kx && maskGT /= 0 = Just $ kx + lowestBitSet maskGT
| otherwise = unsafeFindMin def
where maskGT = ( ((bitmapOf x) `shiftLL` 1)) .&. bm
go def Nil = unsafeFindMin def
lookupLE :: Key -> IntSet -> Maybe Key
lookupLE !x t = case t of
Bin _ m l r | m < 0 -> if x >= 0 then go r l else go Nil r
_ -> go Nil t
where
go def (Bin p m l r) | nomatch x p m = if x < p then unsafeFindMax def else unsafeFindMax r
| zero x m = go def l
| otherwise = go l r
go def (Tip kx bm) | prefixOf x > kx = Just $ kx + highestBitSet bm
| prefixOf x == kx && maskLE /= 0 = Just $ kx + highestBitSet maskLE
| otherwise = unsafeFindMax def
where maskLE = (((bitmapOf x) `shiftLL` 1) 1) .&. bm
go def Nil = unsafeFindMax def
lookupGE :: Key -> IntSet -> Maybe Key
lookupGE !x t = case t of
Bin _ m l r | m < 0 -> if x >= 0 then go Nil l else go l r
_ -> go Nil t
where
go def (Bin p m l r) | nomatch x p m = if x < p then unsafeFindMin l else unsafeFindMin def
| zero x m = go r l
| otherwise = go def r
go def (Tip kx bm) | prefixOf x < kx = Just $ kx + lowestBitSet bm
| prefixOf x == kx && maskGE /= 0 = Just $ kx + lowestBitSet maskGE
| otherwise = unsafeFindMin def
where maskGE = ( (bitmapOf x)) .&. bm
go def Nil = unsafeFindMin def
unsafeFindMin :: IntSet -> Maybe Key
unsafeFindMin Nil = Nothing
unsafeFindMin (Tip kx bm) = Just $ kx + lowestBitSet bm
unsafeFindMin (Bin _ _ l _) = unsafeFindMin l
unsafeFindMax :: IntSet -> Maybe Key
unsafeFindMax Nil = Nothing
unsafeFindMax (Tip kx bm) = Just $ kx + highestBitSet bm
unsafeFindMax (Bin _ _ _ r) = unsafeFindMax r
empty :: IntSet
empty
= Nil
singleton :: Key -> IntSet
singleton x
= Tip (prefixOf x) (bitmapOf x)
insert :: Key -> IntSet -> IntSet
insert !x = insertBM (prefixOf x) (bitmapOf x)
insertBM :: Prefix -> BitMap -> IntSet -> IntSet
insertBM !kx !bm t@(Bin p m l r)
| nomatch kx p m = link kx (Tip kx bm) p t
| zero kx m = Bin p m (insertBM kx bm l) r
| otherwise = Bin p m l (insertBM kx bm r)
insertBM kx bm t@(Tip kx' bm')
| kx' == kx = Tip kx' (bm .|. bm')
| otherwise = link kx (Tip kx bm) kx' t
insertBM kx bm Nil = Tip kx bm
delete :: Key -> IntSet -> IntSet
delete !x = deleteBM (prefixOf x) (bitmapOf x)
deleteBM :: Prefix -> BitMap -> IntSet -> IntSet
deleteBM !kx !bm t@(Bin p m l r)
| nomatch kx p m = t
| zero kx m = bin p m (deleteBM kx bm l) r
| otherwise = bin p m l (deleteBM kx bm r)
deleteBM kx bm t@(Tip kx' bm')
| kx' == kx = tip kx (bm' .&. complement bm)
| otherwise = t
deleteBM _ _ Nil = Nil
alterF :: Functor f => (Bool -> f Bool) -> Key -> IntSet -> f IntSet
alterF f k s = fmap choose (f member_)
where
member_ = member k s
(inserted, deleted)
| member_ = (s , delete k s)
| otherwise = (insert k s, s )
choose True = inserted
choose False = deleted
#ifndef __GLASGOW_HASKELL__
#else
#endif
#if MIN_VERSION_base(4,8,0)
#endif
unions :: Foldable f => f IntSet -> IntSet
unions xs
= Foldable.foldl' union empty xs
union :: IntSet -> IntSet -> IntSet
union t1@(Bin p1 m1 l1 r1) t2@(Bin p2 m2 l2 r2)
| shorter m1 m2 = union1
| shorter m2 m1 = union2
| p1 == p2 = Bin p1 m1 (union l1 l2) (union r1 r2)
| otherwise = link p1 t1 p2 t2
where
union1 | nomatch p2 p1 m1 = link p1 t1 p2 t2
| zero p2 m1 = Bin p1 m1 (union l1 t2) r1
| otherwise = Bin p1 m1 l1 (union r1 t2)
union2 | nomatch p1 p2 m2 = link p1 t1 p2 t2
| zero p1 m2 = Bin p2 m2 (union t1 l2) r2
| otherwise = Bin p2 m2 l2 (union t1 r2)
union t@(Bin _ _ _ _) (Tip kx bm) = insertBM kx bm t
union t@(Bin _ _ _ _) Nil = t
union (Tip kx bm) t = insertBM kx bm t
union Nil t = t
difference :: IntSet -> IntSet -> IntSet
difference t1@(Bin p1 m1 l1 r1) t2@(Bin p2 m2 l2 r2)
| shorter m1 m2 = difference1
| shorter m2 m1 = difference2
| p1 == p2 = bin p1 m1 (difference l1 l2) (difference r1 r2)
| otherwise = t1
where
difference1 | nomatch p2 p1 m1 = t1
| zero p2 m1 = bin p1 m1 (difference l1 t2) r1
| otherwise = bin p1 m1 l1 (difference r1 t2)
difference2 | nomatch p1 p2 m2 = t1
| zero p1 m2 = difference t1 l2
| otherwise = difference t1 r2
difference t@(Bin _ _ _ _) (Tip kx bm) = deleteBM kx bm t
difference t@(Bin _ _ _ _) Nil = t
difference t1@(Tip kx bm) t2 = differenceTip t2
where differenceTip (Bin p2 m2 l2 r2) | nomatch kx p2 m2 = t1
| zero kx m2 = differenceTip l2
| otherwise = differenceTip r2
differenceTip (Tip kx2 bm2) | kx == kx2 = tip kx (bm .&. complement bm2)
| otherwise = t1
differenceTip Nil = t1
difference Nil _ = Nil
intersection :: IntSet -> IntSet -> IntSet
intersection t1@(Bin p1 m1 l1 r1) t2@(Bin p2 m2 l2 r2)
| shorter m1 m2 = intersection1
| shorter m2 m1 = intersection2
| p1 == p2 = bin p1 m1 (intersection l1 l2) (intersection r1 r2)
| otherwise = Nil
where
intersection1 | nomatch p2 p1 m1 = Nil
| zero p2 m1 = intersection l1 t2
| otherwise = intersection r1 t2
intersection2 | nomatch p1 p2 m2 = Nil
| zero p1 m2 = intersection t1 l2
| otherwise = intersection t1 r2
intersection t1@(Bin _ _ _ _) (Tip kx2 bm2) = intersectBM t1
where intersectBM (Bin p1 m1 l1 r1) | nomatch kx2 p1 m1 = Nil
| zero kx2 m1 = intersectBM l1
| otherwise = intersectBM r1
intersectBM (Tip kx1 bm1) | kx1 == kx2 = tip kx1 (bm1 .&. bm2)
| otherwise = Nil
intersectBM Nil = Nil
intersection (Bin _ _ _ _) Nil = Nil
intersection (Tip kx1 bm1) t2 = intersectBM t2
where intersectBM (Bin p2 m2 l2 r2) | nomatch kx1 p2 m2 = Nil
| zero kx1 m2 = intersectBM l2
| otherwise = intersectBM r2
intersectBM (Tip kx2 bm2) | kx1 == kx2 = tip kx1 (bm1 .&. bm2)
| otherwise = Nil
intersectBM Nil = Nil
intersection Nil _ = Nil
isProperSubsetOf :: IntSet -> IntSet -> Bool
isProperSubsetOf t1 t2
= case subsetCmp t1 t2 of
LT -> True
_ -> False
subsetCmp :: IntSet -> IntSet -> Ordering
subsetCmp t1@(Bin p1 m1 l1 r1) (Bin p2 m2 l2 r2)
| shorter m1 m2 = GT
| shorter m2 m1 = case subsetCmpLt of
GT -> GT
_ -> LT
| p1 == p2 = subsetCmpEq
| otherwise = GT
where
subsetCmpLt | nomatch p1 p2 m2 = GT
| zero p1 m2 = subsetCmp t1 l2
| otherwise = subsetCmp t1 r2
subsetCmpEq = case (subsetCmp l1 l2, subsetCmp r1 r2) of
(GT,_ ) -> GT
(_ ,GT) -> GT
(EQ,EQ) -> EQ
_ -> LT
subsetCmp (Bin _ _ _ _) _ = GT
subsetCmp (Tip kx1 bm1) (Tip kx2 bm2)
| kx1 /= kx2 = GT
| bm1 == bm2 = EQ
| bm1 .&. complement bm2 == 0 = LT
| otherwise = GT
subsetCmp t1@(Tip kx _) (Bin p m l r)
| nomatch kx p m = GT
| zero kx m = case subsetCmp t1 l of GT -> GT ; _ -> LT
| otherwise = case subsetCmp t1 r of GT -> GT ; _ -> LT
subsetCmp (Tip _ _) Nil = GT
subsetCmp Nil Nil = EQ
subsetCmp Nil _ = LT
isSubsetOf :: IntSet -> IntSet -> Bool
isSubsetOf t1@(Bin p1 m1 l1 r1) (Bin p2 m2 l2 r2)
| shorter m1 m2 = False
| shorter m2 m1 = match p1 p2 m2 && (if zero p1 m2 then isSubsetOf t1 l2
else isSubsetOf t1 r2)
| otherwise = (p1==p2) && isSubsetOf l1 l2 && isSubsetOf r1 r2
isSubsetOf (Bin _ _ _ _) _ = False
isSubsetOf (Tip kx1 bm1) (Tip kx2 bm2) = kx1 == kx2 && bm1 .&. complement bm2 == 0
isSubsetOf t1@(Tip kx _) (Bin p m l r)
| nomatch kx p m = False
| zero kx m = isSubsetOf t1 l
| otherwise = isSubsetOf t1 r
isSubsetOf (Tip _ _) Nil = False
isSubsetOf Nil _ = True
disjoint :: IntSet -> IntSet -> Bool
disjoint t1@(Bin p1 m1 l1 r1) t2@(Bin p2 m2 l2 r2)
| shorter m1 m2 = disjoint1
| shorter m2 m1 = disjoint2
| p1 == p2 = disjoint l1 l2 && disjoint r1 r2
| otherwise = True
where
disjoint1 | nomatch p2 p1 m1 = True
| zero p2 m1 = disjoint l1 t2
| otherwise = disjoint r1 t2
disjoint2 | nomatch p1 p2 m2 = True
| zero p1 m2 = disjoint t1 l2
| otherwise = disjoint t1 r2
disjoint t1@(Bin _ _ _ _) (Tip kx2 bm2) = disjointBM t1
where disjointBM (Bin p1 m1 l1 r1) | nomatch kx2 p1 m1 = True
| zero kx2 m1 = disjointBM l1
| otherwise = disjointBM r1
disjointBM (Tip kx1 bm1) | kx1 == kx2 = (bm1 .&. bm2) == 0
| otherwise = True
disjointBM Nil = True
disjoint (Bin _ _ _ _) Nil = True
disjoint (Tip kx1 bm1) t2 = disjointBM t2
where disjointBM (Bin p2 m2 l2 r2) | nomatch kx1 p2 m2 = True
| zero kx1 m2 = disjointBM l2
| otherwise = disjointBM r2
disjointBM (Tip kx2 bm2) | kx1 == kx2 = (bm1 .&. bm2) == 0
| otherwise = True
disjointBM Nil = True
disjoint Nil _ = True
filter :: (Key -> Bool) -> IntSet -> IntSet
filter predicate t
= case t of
Bin p m l r
-> bin p m (filter predicate l) (filter predicate r)
Tip kx bm
-> tip kx (foldl'Bits 0 (bitPred kx) 0 bm)
Nil -> Nil
where bitPred kx bm bi | predicate (kx + bi) = bm .|. bitmapOfSuffix bi
| otherwise = bm
partition :: (Key -> Bool) -> IntSet -> (IntSet,IntSet)
partition predicate0 t0 = toPair $ go predicate0 t0
where
go predicate t
= case t of
Bin p m l r
-> let (l1 :*: l2) = go predicate l
(r1 :*: r2) = go predicate r
in bin p m l1 r1 :*: bin p m l2 r2
Tip kx bm
-> let bm1 = foldl'Bits 0 (bitPred kx) 0 bm
in tip kx bm1 :*: tip kx (bm `xor` bm1)
Nil -> (Nil :*: Nil)
where bitPred kx bm bi | predicate (kx + bi) = bm .|. bitmapOfSuffix bi
| otherwise = bm
split :: Key -> IntSet -> (IntSet,IntSet)
split x t =
case t of
Bin _ m l r
| m < 0 -> if x >= 0
then case go x l of (lt :*: gt) -> let !lt' = union lt r
in (lt', gt)
else case go x r of (lt :*: gt) -> let !gt' = union gt l
in (lt, gt')
_ -> case go x t of
(lt :*: gt) -> (lt, gt)
where
go !x' t'@(Bin p m l r)
| match x' p m = if zero x' m
then case go x' l of
(lt :*: gt) -> lt :*: union gt r
else case go x' r of
(lt :*: gt) -> union lt l :*: gt
| otherwise = if x' < p then (Nil :*: t')
else (t' :*: Nil)
go x' t'@(Tip kx' bm)
| kx' > x' = (Nil :*: t')
| kx' < prefixOf x' = (t' :*: Nil)
| otherwise = tip kx' (bm .&. lowerBitmap) :*: tip kx' (bm .&. higherBitmap)
where lowerBitmap = bitmapOf x' 1
higherBitmap = complement (lowerBitmap + bitmapOf x')
go _ Nil = (Nil :*: Nil)
splitMember :: Key -> IntSet -> (IntSet,Bool,IntSet)
splitMember x t =
case t of
Bin _ m l r | m < 0 -> if x >= 0
then case go x l of
(lt, fnd, gt) -> let !lt' = union lt r
in (lt', fnd, gt)
else case go x r of
(lt, fnd, gt) -> let !gt' = union gt l
in (lt, fnd, gt')
_ -> go x t
where
go x' t'@(Bin p m l r)
| match x' p m = if zero x' m
then case go x' l of
(lt, fnd, gt) -> (lt, fnd, union gt r)
else case go x' r of
(lt, fnd, gt) -> (union lt l, fnd, gt)
| otherwise = if x' < p then (Nil, False, t') else (t', False, Nil)
go x' t'@(Tip kx' bm)
| kx' > x' = (Nil, False, t')
| kx' < prefixOf x' = (t', False, Nil)
| otherwise = let !lt = tip kx' (bm .&. lowerBitmap)
!found = (bm .&. bitmapOfx') /= 0
!gt = tip kx' (bm .&. higherBitmap)
in (lt, found, gt)
where bitmapOfx' = bitmapOf x'
lowerBitmap = bitmapOfx' 1
higherBitmap = complement (lowerBitmap + bitmapOfx')
go _ Nil = (Nil, False, Nil)
maxView :: IntSet -> Maybe (Key, IntSet)
maxView t =
case t of Nil -> Nothing
Bin p m l r | m < 0 -> case go l of (result, l') -> Just (result, bin p m l' r)
_ -> Just (go t)
where
go (Bin p m l r) = case go r of (result, r') -> (result, bin p m l r')
go (Tip kx bm) = case highestBitSet bm of bi -> (kx + bi, tip kx (bm .&. complement (bitmapOfSuffix bi)))
go Nil = error "maxView Nil"
minView :: IntSet -> Maybe (Key, IntSet)
minView t =
case t of Nil -> Nothing
Bin p m l r | m < 0 -> case go r of (result, r') -> Just (result, bin p m l r')
_ -> Just (go t)
where
go (Bin p m l r) = case go l of (result, l') -> (result, bin p m l' r)
go (Tip kx bm) = case lowestBitSet bm of bi -> (kx + bi, tip kx (bm .&. complement (bitmapOfSuffix bi)))
go Nil = error "minView Nil"
deleteFindMin :: IntSet -> (Key, IntSet)
deleteFindMin = fromMaybe (error "deleteFindMin: empty set has no minimal element") . minView
deleteFindMax :: IntSet -> (Key, IntSet)
deleteFindMax = fromMaybe (error "deleteFindMax: empty set has no maximal element") . maxView
findMin :: IntSet -> Key
findMin Nil = error "findMin: empty set has no minimal element"
findMin (Tip kx bm) = kx + lowestBitSet bm
findMin (Bin _ m l r)
| m < 0 = find r
| otherwise = find l
where find (Tip kx bm) = kx + lowestBitSet bm
find (Bin _ _ l' _) = find l'
find Nil = error "findMin Nil"
findMax :: IntSet -> Key
findMax Nil = error "findMax: empty set has no maximal element"
findMax (Tip kx bm) = kx + highestBitSet bm
findMax (Bin _ m l r)
| m < 0 = find l
| otherwise = find r
where find (Tip kx bm) = kx + highestBitSet bm
find (Bin _ _ _ r') = find r'
find Nil = error "findMax Nil"
deleteMin :: IntSet -> IntSet
deleteMin = maybe Nil snd . minView
deleteMax :: IntSet -> IntSet
deleteMax = maybe Nil snd . maxView
map :: (Key -> Key) -> IntSet -> IntSet
map f = fromList . List.map f . toList
mapMonotonic :: (Key -> Key) -> IntSet -> IntSet
mapMonotonic f = fromDistinctAscList . List.map f . toAscList
fold :: (Key -> b -> b) -> b -> IntSet -> b
fold = foldr
foldr :: (Key -> b -> b) -> b -> IntSet -> b
foldr f z = \t ->
case t of Bin _ m l r | m < 0 -> go (go z l) r
| otherwise -> go (go z r) l
_ -> go z t
where
go z' Nil = z'
go z' (Tip kx bm) = foldrBits kx f z' bm
go z' (Bin _ _ l r) = go (go z' r) l
foldr' :: (Key -> b -> b) -> b -> IntSet -> b
foldr' f z = \t ->
case t of Bin _ m l r | m < 0 -> go (go z l) r
| otherwise -> go (go z r) l
_ -> go z t
where
go !z' Nil = z'
go z' (Tip kx bm) = foldr'Bits kx f z' bm
go z' (Bin _ _ l r) = go (go z' r) l
foldl :: (a -> Key -> a) -> a -> IntSet -> a
foldl f z = \t ->
case t of Bin _ m l r | m < 0 -> go (go z r) l
| otherwise -> go (go z l) r
_ -> go z t
where
go z' Nil = z'
go z' (Tip kx bm) = foldlBits kx f z' bm
go z' (Bin _ _ l r) = go (go z' l) r
foldl' :: (a -> Key -> a) -> a -> IntSet -> a
foldl' f z = \t ->
case t of Bin _ m l r | m < 0 -> go (go z r) l
| otherwise -> go (go z l) r
_ -> go z t
where
go !z' Nil = z'
go z' (Tip kx bm) = foldl'Bits kx f z' bm
go z' (Bin _ _ l r) = go (go z' l) r
elems :: IntSet -> [Key]
elems
= toAscList
#if __GLASGOW_HASKELL__ >= 708
instance GHC.Exts.IsList IntSet where
type Item IntSet = Key
fromList = fromList
toList = toList
#endif
toList :: IntSet -> [Key]
toList
= toAscList
toAscList :: IntSet -> [Key]
toAscList = foldr (:) []
toDescList :: IntSet -> [Key]
toDescList = foldl (flip (:)) []
#if __GLASGOW_HASKELL__
foldrFB :: (Key -> b -> b) -> b -> IntSet -> b
foldrFB = foldr
foldlFB :: (a -> Key -> a) -> a -> IntSet -> a
foldlFB = foldl
#endif
fromList :: [Key] -> IntSet
fromList xs
= Foldable.foldl' ins empty xs
where
ins t x = insert x t
fromAscList :: [Key] -> IntSet
fromAscList = fromMonoList
fromDistinctAscList :: [Key] -> IntSet
fromDistinctAscList = fromAscList
fromMonoList :: [Key] -> IntSet
fromMonoList [] = Nil
fromMonoList (kx : zs1) = addAll' (prefixOf kx) (bitmapOf kx) zs1
where
addAll' !px !bm []
= Tip px bm
addAll' !px !bm (ky : zs)
| px == prefixOf ky
= addAll' px (bm .|. bitmapOf ky) zs
| py <- prefixOf ky
, m <- branchMask px py
, Inserted ty zs' <- addMany' m py (bitmapOf ky) zs
= addAll px (linkWithMask m py ty (Tip px bm)) zs'
addAll !_px !tx []
= tx
addAll !px !tx (ky : zs)
| py <- prefixOf ky
, m <- branchMask px py
, Inserted ty zs' <- addMany' m py (bitmapOf ky) zs
= addAll px (linkWithMask m py ty tx) zs'
addMany' !_m !px !bm []
= Inserted (Tip px bm) []
addMany' !m !px !bm zs0@(ky : zs)
| px == prefixOf ky
= addMany' m px (bm .|. bitmapOf ky) zs
| mask px m /= mask ky m
= Inserted (Tip (prefixOf px) bm) zs0
| py <- prefixOf ky
, mxy <- branchMask px py
, Inserted ty zs' <- addMany' mxy py (bitmapOf ky) zs
= addMany m px (linkWithMask mxy py ty (Tip px bm)) zs'
addMany !_m !_px tx []
= Inserted tx []
addMany !m !px tx zs0@(ky : zs)
| mask px m /= mask ky m
= Inserted tx zs0
| py <- prefixOf ky
, mxy <- branchMask px py
, Inserted ty zs' <- addMany' mxy py (bitmapOf ky) zs
= addMany m px (linkWithMask mxy py ty tx) zs'
data Inserted = Inserted !IntSet ![Key]
instance Eq IntSet where
t1 == t2 = equal t1 t2
t1 /= t2 = nequal t1 t2
equal :: IntSet -> IntSet -> Bool
equal (Bin p1 m1 l1 r1) (Bin p2 m2 l2 r2)
= (m1 == m2) && (p1 == p2) && (equal l1 l2) && (equal r1 r2)
equal (Tip kx1 bm1) (Tip kx2 bm2)
= kx1 == kx2 && bm1 == bm2
equal Nil Nil = True
equal _ _ = False
nequal :: IntSet -> IntSet -> Bool
nequal (Bin p1 m1 l1 r1) (Bin p2 m2 l2 r2)
= (m1 /= m2) || (p1 /= p2) || (nequal l1 l2) || (nequal r1 r2)
nequal (Tip kx1 bm1) (Tip kx2 bm2)
= kx1 /= kx2 || bm1 /= bm2
nequal Nil Nil = False
nequal _ _ = True
instance Ord IntSet where
compare Nil Nil = EQ
compare Nil _ = LT
compare _ Nil = GT
compare t1@(Tip _ _) t2@(Tip _ _)
= orderingOf $ relateTipTip t1 t2
compare xs ys
| (xsNeg, xsNonNeg) <- splitSign xs
, (ysNeg, ysNonNeg) <- splitSign ys
= case relate xsNeg ysNeg of
Less -> LT
Prefix -> if null xsNonNeg then LT else GT
Equals -> orderingOf (relate xsNonNeg ysNonNeg)
FlipPrefix -> if null ysNonNeg then GT else LT
Greater -> GT
data Relation
= Less
| Prefix
| Equals
| FlipPrefix
| Greater
deriving (Show, Eq)
orderingOf :: Relation -> Ordering
orderingOf r = case r of
Less -> LT
Prefix -> LT
Equals -> EQ
FlipPrefix -> GT
Greater -> GT
relate :: IntSet -> IntSet -> Relation
relate Nil Nil = Equals
relate Nil _t2 = Prefix
relate _t1 Nil = FlipPrefix
relate t1@Tip{} t2@Tip{} = relateTipTip t1 t2
relate t1@(Bin _p1 m1 l1 r1) t2@(Bin _p2 m2 l2 r2)
| succUpperbound t1 <= lowerbound t2 = Less
| lowerbound t1 >= succUpperbound t2 = Greater
| otherwise = case compare (natFromInt m1) (natFromInt m2) of
GT -> combine_left (relate l1 t2)
EQ -> combine (relate l1 l2) (relate r1 r2)
LT -> combine_right (relate t1 l2)
relate t1@(Bin _p1 m1 l1 _r1) t2@(Tip p2 _bm2)
| succUpperbound t1 <= lowerbound t2 = Less
| lowerbound t1 >= succUpperbound t2 = Greater
| 0 == (m1 .&. p2) = combine_left (relate l1 t2)
| otherwise = Less
relate t1@(Tip p1 _bm1) t2@(Bin _p2 m2 l2 _r2)
| succUpperbound t1 <= lowerbound t2 = Less
| lowerbound t1 >= succUpperbound t2 = Greater
| 0 == (p1 .&. m2) = combine_right (relate t1 l2)
| otherwise = Greater
relateTipTip :: IntSet -> IntSet -> Relation
relateTipTip (Tip p1 bm1) (Tip p2 bm2) = case compare p1 p2 of
LT -> Less
EQ -> relateBM bm1 bm2
GT -> Greater
relateTipTip _ _ = error "relateTipTip"
relateBM :: BitMap -> BitMap -> Relation
relateBM w1 w2 | w1 == w2 = Equals
relateBM w1 w2 =
let delta = xor w1 w2
lowest_diff_mask = delta .&. complement (delta1)
prefix = (complement lowest_diff_mask + 1)
.&. (complement lowest_diff_mask)
in if 0 == lowest_diff_mask .&. w1
then if 0 == w1 .&. prefix
then Prefix else Greater
else if 0 == w2 .&. prefix
then FlipPrefix else Less
combine :: Relation -> Relation -> Relation
combine r eq = case r of
Less -> Less
Prefix -> Greater
Equals -> eq
FlipPrefix -> Less
Greater -> Greater
combine_left :: Relation -> Relation
combine_left r = case r of
Less -> Less
Prefix -> Greater
Equals -> FlipPrefix
FlipPrefix -> FlipPrefix
Greater -> Greater
combine_right :: Relation -> Relation
combine_right r = case r of
Less -> Less
Prefix -> Prefix
Equals -> Prefix
FlipPrefix -> Less
Greater -> Greater
lowerbound :: IntSet -> Int
lowerbound Nil = error "lowerbound: Nil"
lowerbound (Tip p _) = p
lowerbound (Bin p _ _ _) = p
succUpperbound :: IntSet -> Int
succUpperbound Nil = error "succUpperbound: Nil"
succUpperbound (Tip p _) = p + wordSize
succUpperbound (Bin p m _ _) = p + shiftR m 1
splitSign :: IntSet -> (IntSet,IntSet)
splitSign t@(Tip kx _)
| kx >= 0 = (Nil, t)
| otherwise = (t, Nil)
splitSign t@(Bin p m l r)
| m < 0 = (r, l)
| p < 0 = (t, Nil)
| otherwise = (Nil, t)
splitSign Nil = (Nil, Nil)
instance Show IntSet where
showsPrec p xs = showParen (p > 10) $
showString "fromList " . shows (toList xs)
instance Read IntSet where
#ifdef __GLASGOW_HASKELL__
readPrec = parens $ prec 10 $ do
Ident "fromList" <- lexP
xs <- readPrec
return (fromList xs)
readListPrec = readListPrecDefault
#else
readsPrec p = readParen (p > 10) $ \ r -> do
("fromList",s) <- lex r
(xs,t) <- reads s
return (fromList xs,t)
#endif
INSTANCE_TYPEABLE0(IntSet)
instance NFData IntSet where rnf x = seq x ()
showTree :: IntSet -> String
showTree s
= showTreeWith True False s
showTreeWith :: Bool -> Bool -> IntSet -> String
showTreeWith hang wide t
| hang = (showsTreeHang wide [] t) ""
| otherwise = (showsTree wide [] [] t) ""
showsTree :: Bool -> [String] -> [String] -> IntSet -> ShowS
showsTree wide lbars rbars t
= case t of
Bin p m l r
-> showsTree wide (withBar rbars) (withEmpty rbars) r .
showWide wide rbars .
showsBars lbars . showString (showBin p m) . showString "\n" .
showWide wide lbars .
showsTree wide (withEmpty lbars) (withBar lbars) l
Tip kx bm
-> showsBars lbars . showString " " . shows kx . showString " + " .
showsBitMap bm . showString "\n"
Nil -> showsBars lbars . showString "|\n"
showsTreeHang :: Bool -> [String] -> IntSet -> ShowS
showsTreeHang wide bars t
= case t of
Bin p m l r
-> showsBars bars . showString (showBin p m) . showString "\n" .
showWide wide bars .
showsTreeHang wide (withBar bars) l .
showWide wide bars .
showsTreeHang wide (withEmpty bars) r
Tip kx bm
-> showsBars bars . showString " " . shows kx . showString " + " .
showsBitMap bm . showString "\n"
Nil -> showsBars bars . showString "|\n"
showBin :: Prefix -> Mask -> String
showBin _ _
= "*"
showWide :: Bool -> [String] -> String -> String
showWide wide bars
| wide = showString (concat (reverse bars)) . showString "|\n"
| otherwise = id
showsBars :: [String] -> ShowS
showsBars [] = id
showsBars bars = showString (concat (reverse (tail bars))) . showString node
showsBitMap :: Word -> ShowS
showsBitMap = showString . showBitMap
showBitMap :: Word -> String
showBitMap w = show $ foldrBits 0 (:) [] w
node :: String
node = "+--"
withBar, withEmpty :: [String] -> [String]
withBar bars = "| ":bars
withEmpty bars = " ":bars
link :: Prefix -> IntSet -> Prefix -> IntSet -> IntSet
link p1 t1 p2 t2 = linkWithMask (branchMask p1 p2) p1 t1 t2
linkWithMask :: Mask -> Prefix -> IntSet -> IntSet -> IntSet
linkWithMask m p1 t1 t2
| zero p1 m = Bin p m t1 t2
| otherwise = Bin p m t2 t1
where
p = mask p1 m
bin :: Prefix -> Mask -> IntSet -> IntSet -> IntSet
bin _ _ l Nil = l
bin _ _ Nil r = r
bin p m l r = Bin p m l r
tip :: Prefix -> BitMap -> IntSet
tip _ 0 = Nil
tip kx bm = Tip kx bm
suffixBitMask :: Int
#if MIN_VERSION_base(4,7,0)
suffixBitMask = finiteBitSize (undefined::Word) 1
#else
suffixBitMask = bitSize (undefined::Word) 1
#endif
prefixBitMask :: Int
prefixBitMask = complement suffixBitMask
prefixOf :: Int -> Prefix
prefixOf x = x .&. prefixBitMask
suffixOf :: Int -> Int
suffixOf x = x .&. suffixBitMask
bitmapOfSuffix :: Int -> BitMap
bitmapOfSuffix s = 1 `shiftLL` s
bitmapOf :: Int -> BitMap
bitmapOf x = bitmapOfSuffix (suffixOf x)
zero :: Int -> Mask -> Bool
zero i m
= (natFromInt i) .&. (natFromInt m) == 0
nomatch,match :: Int -> Prefix -> Mask -> Bool
nomatch i p m
= (mask i m) /= p
match i p m
= (mask i m) == p
mask :: Int -> Mask -> Prefix
mask i m
= maskW (natFromInt i) (natFromInt m)
maskW :: Nat -> Nat -> Prefix
maskW i m
= intFromNat (i .&. (complement (m1) `xor` m))
shorter :: Mask -> Mask -> Bool
shorter m1 m2
= (natFromInt m1) > (natFromInt m2)
branchMask :: Prefix -> Prefix -> Mask
branchMask p1 p2
= intFromNat (highestBitMask (natFromInt p1 `xor` natFromInt p2))
lowestBitSet :: Nat -> Int
highestBitSet :: Nat -> Int
foldlBits :: Int -> (a -> Int -> a) -> a -> Nat -> a
foldl'Bits :: Int -> (a -> Int -> a) -> a -> Nat -> a
foldrBits :: Int -> (Int -> a -> a) -> a -> Nat -> a
foldr'Bits :: Int -> (Int -> a -> a) -> a -> Nat -> a
#if defined(__GLASGOW_HASKELL__) && (WORD_SIZE_IN_BITS==32 || WORD_SIZE_IN_BITS==64)
indexOfTheOnlyBit :: Nat -> Int
#if MIN_VERSION_base(4,8,0) && (WORD_SIZE_IN_BITS==64)
indexOfTheOnlyBit bitmask = countTrailingZeros bitmask
lowestBitSet x = countTrailingZeros x
highestBitSet x = WORD_SIZE_IN_BITS 1 countLeadingZeros x
#else
indexOfTheOnlyBit bitmask =
fromIntegral (GHC.Int.I8# (lsbArray `GHC.Exts.indexInt8OffAddr#` unboxInt (intFromNat ((bitmask * magic) `shiftRL` offset))))
where unboxInt (GHC.Exts.I# i) = i
#if WORD_SIZE_IN_BITS==32
magic = 0x077CB531
offset = 27
!lsbArray = "\0\1\28\2\29\14\24\3\30\22\20\15\25\17\4\8\31\27\13\23\21\19\16\7\26\12\18\6\11\5\10\9"#
#else
magic = 0x07EDD5E59A4E28C2
offset = 58
!lsbArray = "\63\0\58\1\59\47\53\2\60\39\48\27\54\33\42\3\61\51\37\40\49\18\28\20\55\30\34\11\43\14\22\4\62\57\46\52\38\26\32\41\50\36\17\19\29\10\13\21\56\45\25\31\35\16\9\12\44\24\15\8\23\7\6\5"#
#endif
lowestBitSet x = indexOfTheOnlyBit (lowestBitMask x)
highestBitSet x = indexOfTheOnlyBit (highestBitMask x)
#endif
lowestBitMask :: Nat -> Nat
lowestBitMask x = x .&. negate x
revNat :: Nat -> Nat
#if WORD_SIZE_IN_BITS==32
revNat x1 = case ((x1 `shiftRL` 1) .&. 0x55555555) .|. ((x1 .&. 0x55555555) `shiftLL` 1) of
x2 -> case ((x2 `shiftRL` 2) .&. 0x33333333) .|. ((x2 .&. 0x33333333) `shiftLL` 2) of
x3 -> case ((x3 `shiftRL` 4) .&. 0x0F0F0F0F) .|. ((x3 .&. 0x0F0F0F0F) `shiftLL` 4) of
x4 -> case ((x4 `shiftRL` 8) .&. 0x00FF00FF) .|. ((x4 .&. 0x00FF00FF) `shiftLL` 8) of
x5 -> ( x5 `shiftRL` 16 ) .|. ( x5 `shiftLL` 16);
#else
revNat x1 = case ((x1 `shiftRL` 1) .&. 0x5555555555555555) .|. ((x1 .&. 0x5555555555555555) `shiftLL` 1) of
x2 -> case ((x2 `shiftRL` 2) .&. 0x3333333333333333) .|. ((x2 .&. 0x3333333333333333) `shiftLL` 2) of
x3 -> case ((x3 `shiftRL` 4) .&. 0x0F0F0F0F0F0F0F0F) .|. ((x3 .&. 0x0F0F0F0F0F0F0F0F) `shiftLL` 4) of
x4 -> case ((x4 `shiftRL` 8) .&. 0x00FF00FF00FF00FF) .|. ((x4 .&. 0x00FF00FF00FF00FF) `shiftLL` 8) of
x5 -> case ((x5 `shiftRL` 16) .&. 0x0000FFFF0000FFFF) .|. ((x5 .&. 0x0000FFFF0000FFFF) `shiftLL` 16) of
x6 -> ( x6 `shiftRL` 32 ) .|. ( x6 `shiftLL` 32);
#endif
foldlBits prefix f z bitmap = go bitmap z
where go 0 acc = acc
go bm acc = go (bm `xor` bitmask) ((f acc) $! (prefix+bi))
where
!bitmask = lowestBitMask bm
!bi = indexOfTheOnlyBit bitmask
foldl'Bits prefix f z bitmap = go bitmap z
where go 0 acc = acc
go bm !acc = go (bm `xor` bitmask) ((f acc) $! (prefix+bi))
where !bitmask = lowestBitMask bm
!bi = indexOfTheOnlyBit bitmask
foldrBits prefix f z bitmap = go (revNat bitmap) z
where go 0 acc = acc
go bm acc = go (bm `xor` bitmask) ((f $! (prefix+(WORD_SIZE_IN_BITS1)bi)) acc)
where !bitmask = lowestBitMask bm
!bi = indexOfTheOnlyBit bitmask
foldr'Bits prefix f z bitmap = go (revNat bitmap) z
where go 0 acc = acc
go bm !acc = go (bm `xor` bitmask) ((f $! (prefix+(WORD_SIZE_IN_BITS1)bi)) acc)
where !bitmask = lowestBitMask bm
!bi = indexOfTheOnlyBit bitmask
#else
lowestBitSet n0 =
let (n1,b1) = if n0 .&. 0xFFFFFFFF /= 0 then (n0,0) else (n0 `shiftRL` 32, 32)
(n2,b2) = if n1 .&. 0xFFFF /= 0 then (n1,b1) else (n1 `shiftRL` 16, 16+b1)
(n3,b3) = if n2 .&. 0xFF /= 0 then (n2,b2) else (n2 `shiftRL` 8, 8+b2)
(n4,b4) = if n3 .&. 0xF /= 0 then (n3,b3) else (n3 `shiftRL` 4, 4+b3)
(n5,b5) = if n4 .&. 0x3 /= 0 then (n4,b4) else (n4 `shiftRL` 2, 2+b4)
b6 = if n5 .&. 0x1 /= 0 then b5 else 1+b5
in b6
highestBitSet n0 =
let (n1,b1) = if n0 .&. 0xFFFFFFFF00000000 /= 0 then (n0 `shiftRL` 32, 32) else (n0,0)
(n2,b2) = if n1 .&. 0xFFFF0000 /= 0 then (n1 `shiftRL` 16, 16+b1) else (n1,b1)
(n3,b3) = if n2 .&. 0xFF00 /= 0 then (n2 `shiftRL` 8, 8+b2) else (n2,b2)
(n4,b4) = if n3 .&. 0xF0 /= 0 then (n3 `shiftRL` 4, 4+b3) else (n3,b3)
(n5,b5) = if n4 .&. 0xC /= 0 then (n4 `shiftRL` 2, 2+b4) else (n4,b4)
b6 = if n5 .&. 0x2 /= 0 then 1+b5 else b5
in b6
foldlBits prefix f z bm = let lb = lowestBitSet bm
in go (prefix+lb) z (bm `shiftRL` lb)
where go !_ acc 0 = acc
go bi acc n | n `testBit` 0 = go (bi + 1) (f acc bi) (n `shiftRL` 1)
| otherwise = go (bi + 1) acc (n `shiftRL` 1)
foldl'Bits prefix f z bm = let lb = lowestBitSet bm
in go (prefix+lb) z (bm `shiftRL` lb)
where go !_ !acc 0 = acc
go bi acc n | n `testBit` 0 = go (bi + 1) (f acc bi) (n `shiftRL` 1)
| otherwise = go (bi + 1) acc (n `shiftRL` 1)
foldrBits prefix f z bm = let lb = lowestBitSet bm
in go (prefix+lb) (bm `shiftRL` lb)
where go !_ 0 = z
go bi n | n `testBit` 0 = f bi (go (bi + 1) (n `shiftRL` 1))
| otherwise = go (bi + 1) (n `shiftRL` 1)
foldr'Bits prefix f z bm = let lb = lowestBitSet bm
in go (prefix+lb) (bm `shiftRL` lb)
where
go !_ 0 = z
go bi n | n `testBit` 0 = f bi $! go (bi + 1) (n `shiftRL` 1)
| otherwise = go (bi + 1) (n `shiftRL` 1)
#endif
splitRoot :: IntSet -> [IntSet]
splitRoot Nil = []
splitRoot x@(Tip _ _) = [x]
splitRoot (Bin _ m l r) | m < 0 = [r, l]
| otherwise = [l, r]