{-# LANGUAGE CPP #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE TypeFamilies #-}

{-# OPTIONS_HADDOCK not-home #-}

-----------------------------------------------------------------------------
-- |
-- Module      :  Data.Word64Set.Internal
-- Copyright   :  (c) Daan Leijen 2002
--                (c) Joachim Breitner 2011
-- License     :  BSD-style
-- Maintainer  :  libraries@haskell.org
-- Portability :  portable
--
-- = WARNING
--
-- This module is considered __internal__.
--
-- The Package Versioning Policy __does not apply__.
--
-- The contents of this module may change __in any way whatsoever__
-- and __without any warning__ between minor versions of this package.
--
-- Authors importing this module are expected to track development
-- closely.
--
-- = Description
--
-- An efficient implementation of integer sets.
--
-- These modules are intended to be imported qualified, to avoid name
-- clashes with Prelude functions, e.g.
--
-- >  import Data.Word64Set (Word64Set)
-- >  import qualified Data.Word64Set as Word64Set
--
-- The implementation is based on /big-endian patricia trees/.  This data
-- structure performs especially well on binary operations like 'union'
-- and 'intersection'.  However, my benchmarks show that it is also
-- (much) faster on insertions and deletions when compared to a generic
-- size-balanced set implementation (see "Data.Set").
--
--    * Chris Okasaki and Andy Gill,  \"/Fast Mergeable Integer Maps/\",
--      Workshop on ML, September 1998, pages 77-86,
--      <http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.37.5452>
--
--    * D.R. Morrison, \"/PATRICIA -- Practical Algorithm To Retrieve Information Coded In Alphanumeric/\",
--      Journal of the ACM, 15(4), October 1968, pages 514-534.
--
-- Additionally, this implementation places bitmaps in the leaves of the tree.
-- Their size is the natural size of a machine word (32 or 64 bits) and greatly
-- reduce memory footprint and execution times for dense sets, e.g. sets where
-- it is likely that many values lie close to each other. The asymptotics are
-- not affected by this optimization.
--
-- Many operations have a worst-case complexity of \(O(\min(n,W))\).
-- This means that the operation can become linear in the number of
-- elements with a maximum of \(W\) -- the number of bits in an 'Int'
-- (32 or 64).
--
-- @since 0.5.9
-----------------------------------------------------------------------------

-- [Note: INLINE bit fiddling]
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- It is essential that the bit fiddling functions like mask, zero, branchMask
-- etc are inlined. If they do not, the memory allocation skyrockets. The GHC
-- usually gets it right, but it is disastrous if it does not. Therefore we
-- explicitly mark these functions INLINE.


-- [Note: Local 'go' functions and capturing]
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- Care must be taken when using 'go' function which captures an argument.
-- Sometimes (for example when the argument is passed to a data constructor,
-- as in insert), GHC heap-allocates more than necessary. Therefore C-- code
-- must be checked for increased allocation when creating and modifying such
-- functions.


-- [Note: Order of constructors]
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- The order of constructors of Word64Set matters when considering performance.
-- Currently in GHC 7.0, when type has 3 constructors, they are matched from
-- the first to the last -- the best performance is achieved when the
-- constructors are ordered by frequency.
-- On GHC 7.0, reordering constructors from Nil | Tip | Bin to Bin | Tip | Nil
-- improves the benchmark by circa 10%.

module GHC.Data.Word64Set.Internal (
    -- * Set type
      Word64Set(..), Key -- instance Eq,Show
    , Prefix, Mask, BitMap

    -- * Operators
    , (\\)

    -- * Query
    , null
    , size
    , member
    , notMember
    , lookupLT
    , lookupGT
    , lookupLE
    , lookupGE
    , isSubsetOf
    , isProperSubsetOf
    , disjoint

    -- * Construction
    , empty
    , singleton
    , insert
    , delete
    , alterF

    -- * Combine
    , union
    , unions
    , difference
    , intersection

    -- * Filter
    , filter
    , partition

    , takeWhileAntitone
    , dropWhileAntitone
    , spanAntitone

    , split
    , splitMember
    , splitRoot

    -- * Map
    , map
    , mapMonotonic

    -- * Folds
    , foldr
    , foldl
    -- ** Strict folds
    , foldr'
    , foldl'
    -- ** Legacy folds
    , fold

    -- * Min\/Max
    , findMin
    , findMax
    , deleteMin
    , deleteMax
    , deleteFindMin
    , deleteFindMax
    , maxView
    , minView

    -- * Conversion

    -- ** List
    , elems
    , toList
    , fromList

    -- ** Ordered list
    , toAscList
    , toDescList
    , fromAscList
    , fromDistinctAscList

    -- * Debugging
    , showTree
    , showTreeWith

    -- * Internals
    , 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)
import Data.Semigroup (Semigroup(stimes, (<>)), stimesIdempotentMonoid)
import GHC.Prelude.Basic hiding
  (filter, foldr, foldl, foldl', null, map)
import Data.Word ( Word64 )

import GHC.Utils.Containers.Internal.BitUtil
import GHC.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
#endif

import qualified Data.Foldable as Foldable
import Data.Functor.Identity (Identity(..))

infixl 9 \\{-This comment teaches CPP correct behaviour -}

-- A "Nat" is a 64 bit machine word
type Nat = Word64

natFromInt :: Word64 -> Nat
natFromInt :: Mask -> Mask
natFromInt = Mask -> Mask
forall a. a -> a
id
{-# INLINE natFromInt #-}

intFromNat :: Nat -> Word64
intFromNat :: Mask -> Mask
intFromNat = Mask -> Mask
forall a. a -> a
id
{-# INLINE intFromNat #-}

{--------------------------------------------------------------------
  Operators
--------------------------------------------------------------------}
-- | \(O(n+m)\). See 'difference'.
(\\) :: Word64Set -> Word64Set -> Word64Set
Word64Set
m1 \\ :: Word64Set -> Word64Set -> Word64Set
\\ Word64Set
m2 = Word64Set -> Word64Set -> Word64Set
difference Word64Set
m1 Word64Set
m2

{--------------------------------------------------------------------
  Types
--------------------------------------------------------------------}

-- | A set of integers.

-- See Note: Order of constructors
data Word64Set = Bin {-# UNPACK #-} !Prefix {-# UNPACK #-} !Mask !Word64Set !Word64Set
-- Invariant: Nil is never found as a child of Bin.
-- Invariant: The Mask is a power of 2.  It is the largest bit position at which
--            two elements of the set differ.
-- Invariant: Prefix is the common high-order bits that all elements share to
--            the left of the Mask bit.
-- Invariant: In Bin prefix mask left right, left consists of the elements that
--            don't have the mask bit set; right is all the elements that do.
            | Tip {-# UNPACK #-} !Prefix {-# UNPACK #-} !BitMap
-- Invariant: The Prefix is zero for the last 6 bits. The values of the set
--            represented by a tip are the prefix plus the indices of the set
--            bits in the bit map.
            | Nil

-- A number stored in a set is stored as
-- * Prefix (all but last 6 bits) and
-- * BitMap (last 6 bits stored as a bitmask)
--   Last 6 bits are called a Suffix.

type Prefix = Word64
type Mask   = Word64
type BitMap = Word64
type Key    = Word64

instance Monoid Word64Set where
    mempty :: Word64Set
mempty  = Word64Set
empty
    mconcat :: [Word64Set] -> Word64Set
mconcat = [Word64Set] -> Word64Set
forall (f :: * -> *). Foldable f => f Word64Set -> Word64Set
unions
    mappend :: Word64Set -> Word64Set -> Word64Set
mappend = Word64Set -> Word64Set -> Word64Set
forall a. Semigroup a => a -> a -> a
(<>)

-- | @since 0.5.7
instance Semigroup Word64Set where
    <> :: Word64Set -> Word64Set -> Word64Set
(<>)    = Word64Set -> Word64Set -> Word64Set
union
    stimes :: forall b. Integral b => b -> Word64Set -> Word64Set
stimes  = b -> Word64Set -> Word64Set
forall b a. (Integral b, Monoid a) => b -> a -> a
stimesIdempotentMonoid

#if __GLASGOW_HASKELL__

{--------------------------------------------------------------------
  A Data instance
--------------------------------------------------------------------}

-- This instance preserves data abstraction at the cost of inefficiency.
-- We provide limited reflection services for the sake of data abstraction.

instance Data Word64Set where
  gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Word64Set -> c Word64Set
gfoldl forall d b. Data d => c (d -> b) -> d -> c b
f forall g. g -> c g
z Word64Set
is = ([Mask] -> Word64Set) -> c ([Mask] -> Word64Set)
forall g. g -> c g
z [Mask] -> Word64Set
fromList c ([Mask] -> Word64Set) -> [Mask] -> c Word64Set
forall d b. Data d => c (d -> b) -> d -> c b
`f` (Word64Set -> [Mask]
toList Word64Set
is)
  toConstr :: Word64Set -> Constr
toConstr Word64Set
_     = Constr
fromListConstr
  gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Word64Set
gunfold forall b r. Data b => c (b -> r) -> c r
k forall r. r -> c r
z Constr
c  = case Constr -> Int
constrIndex Constr
c of
    Int
1 -> c ([Mask] -> Word64Set) -> c Word64Set
forall b r. Data b => c (b -> r) -> c r
k (([Mask] -> Word64Set) -> c ([Mask] -> Word64Set)
forall r. r -> c r
z [Mask] -> Word64Set
fromList)
    Int
_ -> [Char] -> c Word64Set
forall a. HasCallStack => [Char] -> a
error [Char]
"gunfold"
  dataTypeOf :: Word64Set -> DataType
dataTypeOf Word64Set
_   = DataType
intSetDataType

fromListConstr :: Constr
fromListConstr :: Constr
fromListConstr = DataType -> [Char] -> [[Char]] -> Fixity -> Constr
mkConstr DataType
intSetDataType [Char]
"fromList" [] Fixity
Data.Data.Prefix

intSetDataType :: DataType
intSetDataType :: DataType
intSetDataType = [Char] -> [Constr] -> DataType
mkDataType [Char]
"Data.Word64Set.Internal.Word64Set" [Constr
fromListConstr]

#endif

{--------------------------------------------------------------------
  Query
--------------------------------------------------------------------}
-- | \(O(1)\). Is the set empty?
null :: Word64Set -> Bool
null :: Word64Set -> Bool
null Word64Set
Nil = Bool
True
null Word64Set
_   = Bool
False
{-# INLINE null #-}

-- | \(O(n)\). Cardinality of the set.
size :: Word64Set -> Int
size :: Word64Set -> Int
size = Int -> Word64Set -> Int
go Int
0
  where
    go :: Int -> Word64Set -> Int
go !Int
acc (Bin Mask
_ Mask
_ Word64Set
l Word64Set
r) = Int -> Word64Set -> Int
go (Int -> Word64Set -> Int
go Int
acc Word64Set
l) Word64Set
r
    go Int
acc (Tip Mask
_ Mask
bm) = Int
acc Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int -> Mask -> Int
bitcount Int
0 Mask
bm
    go Int
acc Word64Set
Nil = Int
acc

-- | \(O(\min(n,W))\). Is the value a member of the set?

-- See Note: Local 'go' functions and capturing.
member :: Key -> Word64Set -> Bool
member :: Mask -> Word64Set -> Bool
member !Mask
x = Word64Set -> Bool
go
  where
    go :: Word64Set -> Bool
go (Bin Mask
p Mask
m Word64Set
l Word64Set
r)
      | Mask -> Mask -> Mask -> Bool
nomatch Mask
x Mask
p Mask
m = Bool
False
      | Mask -> Mask -> Bool
zero Mask
x Mask
m      = Word64Set -> Bool
go Word64Set
l
      | Bool
otherwise     = Word64Set -> Bool
go Word64Set
r
    go (Tip Mask
y Mask
bm) = Mask -> Mask
prefixOf Mask
x Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
== Mask
y Bool -> Bool -> Bool
&& Mask -> Mask
bitmapOf Mask
x Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask
bm Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
/= Mask
0
    go Word64Set
Nil = Bool
False

-- | \(O(\min(n,W))\). Is the element not in the set?
notMember :: Key -> Word64Set -> Bool
notMember :: Mask -> Word64Set -> Bool
notMember Mask
k = Bool -> Bool
not (Bool -> Bool) -> (Word64Set -> Bool) -> Word64Set -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Mask -> Word64Set -> Bool
member Mask
k

-- | \(O(\min(n,W))\). Find largest element smaller than the given one.
--
-- > lookupLT 3 (fromList [3, 5]) == Nothing
-- > lookupLT 5 (fromList [3, 5]) == Just 3

-- See Note: Local 'go' functions and capturing.
lookupLT :: Key -> Word64Set -> Maybe Key
lookupLT :: Mask -> Word64Set -> Maybe Mask
lookupLT !Mask
x Word64Set
t = case Word64Set
t of
    Bin Mask
_ Mask
m Word64Set
l Word64Set
r | Mask
m Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
< Mask
0 -> if Mask
x Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
>= Mask
0 then Word64Set -> Word64Set -> Maybe Mask
go Word64Set
r Word64Set
l else Word64Set -> Word64Set -> Maybe Mask
go Word64Set
Nil Word64Set
r
    Word64Set
_ -> Word64Set -> Word64Set -> Maybe Mask
go Word64Set
Nil Word64Set
t
  where
    go :: Word64Set -> Word64Set -> Maybe Mask
go Word64Set
def (Bin Mask
p Mask
m Word64Set
l Word64Set
r) | Mask -> Mask -> Mask -> Bool
nomatch Mask
x Mask
p Mask
m = if Mask
x Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
< Mask
p then Word64Set -> Maybe Mask
unsafeFindMax Word64Set
def else Word64Set -> Maybe Mask
unsafeFindMax Word64Set
r
                         | Mask -> Mask -> Bool
zero Mask
x Mask
m  = Word64Set -> Word64Set -> Maybe Mask
go Word64Set
def Word64Set
l
                         | Bool
otherwise = Word64Set -> Word64Set -> Maybe Mask
go Word64Set
l Word64Set
r
    go Word64Set
def (Tip Mask
kx Mask
bm) | Mask -> Mask
prefixOf Mask
x Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
> Mask
kx = Mask -> Maybe Mask
forall a. a -> Maybe a
Just (Mask -> Maybe Mask) -> Mask -> Maybe Mask
forall a b. (a -> b) -> a -> b
$ Mask
kx Mask -> Mask -> Mask
forall a. Num a => a -> a -> a
+ Mask -> Mask
highestBitSet Mask
bm
                       | Mask -> Mask
prefixOf Mask
x Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
== Mask
kx Bool -> Bool -> Bool
&& Mask
maskLT Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
/= Mask
0 = Mask -> Maybe Mask
forall a. a -> Maybe a
Just (Mask -> Maybe Mask) -> Mask -> Maybe Mask
forall a b. (a -> b) -> a -> b
$ Mask
kx Mask -> Mask -> Mask
forall a. Num a => a -> a -> a
+ Mask -> Mask
highestBitSet Mask
maskLT
                       | Bool
otherwise = Word64Set -> Maybe Mask
unsafeFindMax Word64Set
def
                       where maskLT :: Mask
maskLT = (Mask -> Mask
bitmapOf Mask
x Mask -> Mask -> Mask
forall a. Num a => a -> a -> a
- Mask
1) Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask
bm
    go Word64Set
def Word64Set
Nil = Word64Set -> Maybe Mask
unsafeFindMax Word64Set
def


-- | \(O(\min(n,W))\). Find smallest element greater than the given one.
--
-- > lookupGT 4 (fromList [3, 5]) == Just 5
-- > lookupGT 5 (fromList [3, 5]) == Nothing

-- See Note: Local 'go' functions and capturing.
lookupGT :: Key -> Word64Set -> Maybe Key
lookupGT :: Mask -> Word64Set -> Maybe Mask
lookupGT !Mask
x Word64Set
t = case Word64Set
t of
    Bin Mask
_ Mask
m Word64Set
l Word64Set
r | Mask
m Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
< Mask
0 -> if Mask
x Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
>= Mask
0 then Word64Set -> Word64Set -> Maybe Mask
go Word64Set
Nil Word64Set
l else Word64Set -> Word64Set -> Maybe Mask
go Word64Set
l Word64Set
r
    Word64Set
_ -> Word64Set -> Word64Set -> Maybe Mask
go Word64Set
Nil Word64Set
t
  where
    go :: Word64Set -> Word64Set -> Maybe Mask
go Word64Set
def (Bin Mask
p Mask
m Word64Set
l Word64Set
r) | Mask -> Mask -> Mask -> Bool
nomatch Mask
x Mask
p Mask
m = if Mask
x Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
< Mask
p then Word64Set -> Maybe Mask
unsafeFindMin Word64Set
l else Word64Set -> Maybe Mask
unsafeFindMin Word64Set
def
                         | Mask -> Mask -> Bool
zero Mask
x Mask
m  = Word64Set -> Word64Set -> Maybe Mask
go Word64Set
r Word64Set
l
                         | Bool
otherwise = Word64Set -> Word64Set -> Maybe Mask
go Word64Set
def Word64Set
r
    go Word64Set
def (Tip Mask
kx Mask
bm) | Mask -> Mask
prefixOf Mask
x Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
< Mask
kx = Mask -> Maybe Mask
forall a. a -> Maybe a
Just (Mask -> Maybe Mask) -> Mask -> Maybe Mask
forall a b. (a -> b) -> a -> b
$ Mask
kx Mask -> Mask -> Mask
forall a. Num a => a -> a -> a
+ Mask -> Mask
lowestBitSet Mask
bm
                       | Mask -> Mask
prefixOf Mask
x Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
== Mask
kx Bool -> Bool -> Bool
&& Mask
maskGT Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
/= Mask
0 = Mask -> Maybe Mask
forall a. a -> Maybe a
Just (Mask -> Maybe Mask) -> Mask -> Maybe Mask
forall a b. (a -> b) -> a -> b
$ Mask
kx Mask -> Mask -> Mask
forall a. Num a => a -> a -> a
+ Mask -> Mask
lowestBitSet Mask
maskGT
                       | Bool
otherwise = Word64Set -> Maybe Mask
unsafeFindMin Word64Set
def
                       where maskGT :: Mask
maskGT = (- ((Mask -> Mask
bitmapOf Mask
x) Mask -> Int -> Mask
`shiftLL` Int
1)) Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask
bm
    go Word64Set
def Word64Set
Nil = Word64Set -> Maybe Mask
unsafeFindMin Word64Set
def


-- | \(O(\min(n,W))\). Find largest element smaller or equal to the given one.
--
-- > lookupLE 2 (fromList [3, 5]) == Nothing
-- > lookupLE 4 (fromList [3, 5]) == Just 3
-- > lookupLE 5 (fromList [3, 5]) == Just 5

-- See Note: Local 'go' functions and capturing.
lookupLE :: Key -> Word64Set -> Maybe Key
lookupLE :: Mask -> Word64Set -> Maybe Mask
lookupLE !Mask
x Word64Set
t = case Word64Set
t of
    Bin Mask
_ Mask
m Word64Set
l Word64Set
r | Mask
m Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
< Mask
0 -> if Mask
x Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
>= Mask
0 then Word64Set -> Word64Set -> Maybe Mask
go Word64Set
r Word64Set
l else Word64Set -> Word64Set -> Maybe Mask
go Word64Set
Nil Word64Set
r
    Word64Set
_ -> Word64Set -> Word64Set -> Maybe Mask
go Word64Set
Nil Word64Set
t
  where
    go :: Word64Set -> Word64Set -> Maybe Mask
go Word64Set
def (Bin Mask
p Mask
m Word64Set
l Word64Set
r) | Mask -> Mask -> Mask -> Bool
nomatch Mask
x Mask
p Mask
m = if Mask
x Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
< Mask
p then Word64Set -> Maybe Mask
unsafeFindMax Word64Set
def else Word64Set -> Maybe Mask
unsafeFindMax Word64Set
r
                         | Mask -> Mask -> Bool
zero Mask
x Mask
m  = Word64Set -> Word64Set -> Maybe Mask
go Word64Set
def Word64Set
l
                         | Bool
otherwise = Word64Set -> Word64Set -> Maybe Mask
go Word64Set
l Word64Set
r
    go Word64Set
def (Tip Mask
kx Mask
bm) | Mask -> Mask
prefixOf Mask
x Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
> Mask
kx = Mask -> Maybe Mask
forall a. a -> Maybe a
Just (Mask -> Maybe Mask) -> Mask -> Maybe Mask
forall a b. (a -> b) -> a -> b
$ Mask
kx Mask -> Mask -> Mask
forall a. Num a => a -> a -> a
+ Mask -> Mask
highestBitSet Mask
bm
                       | Mask -> Mask
prefixOf Mask
x Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
== Mask
kx Bool -> Bool -> Bool
&& Mask
maskLE Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
/= Mask
0 = Mask -> Maybe Mask
forall a. a -> Maybe a
Just (Mask -> Maybe Mask) -> Mask -> Maybe Mask
forall a b. (a -> b) -> a -> b
$ Mask
kx Mask -> Mask -> Mask
forall a. Num a => a -> a -> a
+ Mask -> Mask
highestBitSet Mask
maskLE
                       | Bool
otherwise = Word64Set -> Maybe Mask
unsafeFindMax Word64Set
def
                       where maskLE :: Mask
maskLE = (((Mask -> Mask
bitmapOf Mask
x) Mask -> Int -> Mask
`shiftLL` Int
1) Mask -> Mask -> Mask
forall a. Num a => a -> a -> a
- Mask
1) Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask
bm
    go Word64Set
def Word64Set
Nil = Word64Set -> Maybe Mask
unsafeFindMax Word64Set
def


-- | \(O(\min(n,W))\). Find smallest element greater or equal to the given one.
--
-- > lookupGE 3 (fromList [3, 5]) == Just 3
-- > lookupGE 4 (fromList [3, 5]) == Just 5
-- > lookupGE 6 (fromList [3, 5]) == Nothing

-- See Note: Local 'go' functions and capturing.
lookupGE :: Key -> Word64Set -> Maybe Key
lookupGE :: Mask -> Word64Set -> Maybe Mask
lookupGE !Mask
x Word64Set
t = case Word64Set
t of
    Bin Mask
_ Mask
m Word64Set
l Word64Set
r | Mask
m Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
< Mask
0 -> if Mask
x Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
>= Mask
0 then Word64Set -> Word64Set -> Maybe Mask
go Word64Set
Nil Word64Set
l else Word64Set -> Word64Set -> Maybe Mask
go Word64Set
l Word64Set
r
    Word64Set
_ -> Word64Set -> Word64Set -> Maybe Mask
go Word64Set
Nil Word64Set
t
  where
    go :: Word64Set -> Word64Set -> Maybe Mask
go Word64Set
def (Bin Mask
p Mask
m Word64Set
l Word64Set
r) | Mask -> Mask -> Mask -> Bool
nomatch Mask
x Mask
p Mask
m = if Mask
x Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
< Mask
p then Word64Set -> Maybe Mask
unsafeFindMin Word64Set
l else Word64Set -> Maybe Mask
unsafeFindMin Word64Set
def
                         | Mask -> Mask -> Bool
zero Mask
x Mask
m  = Word64Set -> Word64Set -> Maybe Mask
go Word64Set
r Word64Set
l
                         | Bool
otherwise = Word64Set -> Word64Set -> Maybe Mask
go Word64Set
def Word64Set
r
    go Word64Set
def (Tip Mask
kx Mask
bm) | Mask -> Mask
prefixOf Mask
x Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
< Mask
kx = Mask -> Maybe Mask
forall a. a -> Maybe a
Just (Mask -> Maybe Mask) -> Mask -> Maybe Mask
forall a b. (a -> b) -> a -> b
$ Mask
kx Mask -> Mask -> Mask
forall a. Num a => a -> a -> a
+ Mask -> Mask
lowestBitSet Mask
bm
                       | Mask -> Mask
prefixOf Mask
x Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
== Mask
kx Bool -> Bool -> Bool
&& Mask
maskGE Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
/= Mask
0 = Mask -> Maybe Mask
forall a. a -> Maybe a
Just (Mask -> Maybe Mask) -> Mask -> Maybe Mask
forall a b. (a -> b) -> a -> b
$ Mask
kx Mask -> Mask -> Mask
forall a. Num a => a -> a -> a
+ Mask -> Mask
lowestBitSet Mask
maskGE
                       | Bool
otherwise = Word64Set -> Maybe Mask
unsafeFindMin Word64Set
def
                       where maskGE :: Mask
maskGE = (- (Mask -> Mask
bitmapOf Mask
x)) Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask
bm
    go Word64Set
def Word64Set
Nil = Word64Set -> Maybe Mask
unsafeFindMin Word64Set
def



-- Helper function for lookupGE and lookupGT. It assumes that if a Bin node is
-- given, it has m > 0.
unsafeFindMin :: Word64Set -> Maybe Key
unsafeFindMin :: Word64Set -> Maybe Mask
unsafeFindMin Word64Set
Nil = Maybe Mask
forall a. Maybe a
Nothing
unsafeFindMin (Tip Mask
kx Mask
bm) = Mask -> Maybe Mask
forall a. a -> Maybe a
Just (Mask -> Maybe Mask) -> Mask -> Maybe Mask
forall a b. (a -> b) -> a -> b
$ Mask
kx Mask -> Mask -> Mask
forall a. Num a => a -> a -> a
+ Mask -> Mask
lowestBitSet Mask
bm
unsafeFindMin (Bin Mask
_ Mask
_ Word64Set
l Word64Set
_) = Word64Set -> Maybe Mask
unsafeFindMin Word64Set
l

-- Helper function for lookupLE and lookupLT. It assumes that if a Bin node is
-- given, it has m > 0.
unsafeFindMax :: Word64Set -> Maybe Key
unsafeFindMax :: Word64Set -> Maybe Mask
unsafeFindMax Word64Set
Nil = Maybe Mask
forall a. Maybe a
Nothing
unsafeFindMax (Tip Mask
kx Mask
bm) = Mask -> Maybe Mask
forall a. a -> Maybe a
Just (Mask -> Maybe Mask) -> Mask -> Maybe Mask
forall a b. (a -> b) -> a -> b
$ Mask
kx Mask -> Mask -> Mask
forall a. Num a => a -> a -> a
+ Mask -> Mask
highestBitSet Mask
bm
unsafeFindMax (Bin Mask
_ Mask
_ Word64Set
_ Word64Set
r) = Word64Set -> Maybe Mask
unsafeFindMax Word64Set
r

{--------------------------------------------------------------------
  Construction
--------------------------------------------------------------------}
-- | \(O(1)\). The empty set.
empty :: Word64Set
empty :: Word64Set
empty
  = Word64Set
Nil
{-# INLINE empty #-}

-- | \(O(1)\). A set of one element.
singleton :: Key -> Word64Set
singleton :: Mask -> Word64Set
singleton Mask
x
  = Mask -> Mask -> Word64Set
Tip (Mask -> Mask
prefixOf Mask
x) (Mask -> Mask
bitmapOf Mask
x)
{-# INLINE singleton #-}

{--------------------------------------------------------------------
  Insert
--------------------------------------------------------------------}
-- | \(O(\min(n,W))\). Add a value to the set. There is no left- or right bias for
-- Word64Sets.
insert :: Key -> Word64Set -> Word64Set
insert :: Mask -> Word64Set -> Word64Set
insert !Mask
x = Mask -> Mask -> Word64Set -> Word64Set
insertBM (Mask -> Mask
prefixOf Mask
x) (Mask -> Mask
bitmapOf Mask
x)

-- Helper function for insert and union.
insertBM :: Prefix -> BitMap -> Word64Set -> Word64Set
insertBM :: Mask -> Mask -> Word64Set -> Word64Set
insertBM !Mask
kx !Mask
bm t :: Word64Set
t@(Bin Mask
p Mask
m Word64Set
l Word64Set
r)
  | Mask -> Mask -> Mask -> Bool
nomatch Mask
kx Mask
p Mask
m = Mask -> Word64Set -> Mask -> Word64Set -> Word64Set
link Mask
kx (Mask -> Mask -> Word64Set
Tip Mask
kx Mask
bm) Mask
p Word64Set
t
  | Mask -> Mask -> Bool
zero Mask
kx Mask
m      = Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
Bin Mask
p Mask
m (Mask -> Mask -> Word64Set -> Word64Set
insertBM Mask
kx Mask
bm Word64Set
l) Word64Set
r
  | Bool
otherwise      = Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
Bin Mask
p Mask
m Word64Set
l (Mask -> Mask -> Word64Set -> Word64Set
insertBM Mask
kx Mask
bm Word64Set
r)
insertBM Mask
kx Mask
bm t :: Word64Set
t@(Tip Mask
kx' Mask
bm')
  | Mask
kx' Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
== Mask
kx = Mask -> Mask -> Word64Set
Tip Mask
kx' (Mask
bm Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.|. Mask
bm')
  | Bool
otherwise = Mask -> Word64Set -> Mask -> Word64Set -> Word64Set
link Mask
kx (Mask -> Mask -> Word64Set
Tip Mask
kx Mask
bm) Mask
kx' Word64Set
t
insertBM Mask
kx Mask
bm Word64Set
Nil = Mask -> Mask -> Word64Set
Tip Mask
kx Mask
bm

-- | \(O(\min(n,W))\). Delete a value in the set. Returns the
-- original set when the value was not present.
delete :: Key -> Word64Set -> Word64Set
delete :: Mask -> Word64Set -> Word64Set
delete !Mask
x = Mask -> Mask -> Word64Set -> Word64Set
deleteBM (Mask -> Mask
prefixOf Mask
x) (Mask -> Mask
bitmapOf Mask
x)

-- Deletes all values mentioned in the BitMap from the set.
-- Helper function for delete and difference.
deleteBM :: Prefix -> BitMap -> Word64Set -> Word64Set
deleteBM :: Mask -> Mask -> Word64Set -> Word64Set
deleteBM !Mask
kx !Mask
bm t :: Word64Set
t@(Bin Mask
p Mask
m Word64Set
l Word64Set
r)
  | Mask -> Mask -> Mask -> Bool
nomatch Mask
kx Mask
p Mask
m = Word64Set
t
  | Mask -> Mask -> Bool
zero Mask
kx Mask
m      = Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
bin Mask
p Mask
m (Mask -> Mask -> Word64Set -> Word64Set
deleteBM Mask
kx Mask
bm Word64Set
l) Word64Set
r
  | Bool
otherwise      = Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
bin Mask
p Mask
m Word64Set
l (Mask -> Mask -> Word64Set -> Word64Set
deleteBM Mask
kx Mask
bm Word64Set
r)
deleteBM Mask
kx Mask
bm t :: Word64Set
t@(Tip Mask
kx' Mask
bm')
  | Mask
kx' Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
== Mask
kx = Mask -> Mask -> Word64Set
tip Mask
kx (Mask
bm' Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask -> Mask
forall a. Bits a => a -> a
complement Mask
bm)
  | Bool
otherwise = Word64Set
t
deleteBM Mask
_ Mask
_ Word64Set
Nil = Word64Set
Nil

-- | \(O(\min(n,W))\). @('alterF' f x s)@ can delete or insert @x@ in @s@ depending
-- on whether it is already present in @s@.
--
-- In short:
--
-- @
-- 'member' x \<$\> 'alterF' f x s = f ('member' x s)
-- @
--
-- Note: 'alterF' is a variant of the @at@ combinator from "Control.Lens.At".
--
-- @since 0.6.3.1
alterF :: Functor f => (Bool -> f Bool) -> Key -> Word64Set -> f Word64Set
alterF :: forall (f :: * -> *).
Functor f =>
(Bool -> f Bool) -> Mask -> Word64Set -> f Word64Set
alterF Bool -> f Bool
f Mask
k Word64Set
s = (Bool -> Word64Set) -> f Bool -> f Word64Set
forall a b. (a -> b) -> f a -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Bool -> Word64Set
choose (Bool -> f Bool
f Bool
member_)
  where
    member_ :: Bool
member_ = Mask -> Word64Set -> Bool
member Mask
k Word64Set
s

    (Word64Set
inserted, Word64Set
deleted)
      | Bool
member_   = (Word64Set
s         , Mask -> Word64Set -> Word64Set
delete Mask
k Word64Set
s)
      | Bool
otherwise = (Mask -> Word64Set -> Word64Set
insert Mask
k Word64Set
s, Word64Set
s         )

    choose :: Bool -> Word64Set
choose Bool
True  = Word64Set
inserted
    choose Bool
False = Word64Set
deleted
#ifndef __GLASGOW_HASKELL__
{-# INLINE alterF #-}
#else
{-# INLINABLE [2] alterF #-}

{-# RULES
"alterF/Const" forall k (f :: Bool -> Const a Bool) . alterF f k = \s -> Const . getConst . f $ member k s
 #-}
#endif

{-# SPECIALIZE alterF :: (Bool -> Identity Bool) -> Key -> Word64Set -> Identity Word64Set #-}

{--------------------------------------------------------------------
  Union
--------------------------------------------------------------------}
-- | The union of a list of sets.
unions :: Foldable f => f Word64Set -> Word64Set
unions :: forall (f :: * -> *). Foldable f => f Word64Set -> Word64Set
unions f Word64Set
xs
  = (Word64Set -> Word64Set -> Word64Set)
-> Word64Set -> f Word64Set -> Word64Set
forall b a. (b -> a -> b) -> b -> f a -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
Foldable.foldl' Word64Set -> Word64Set -> Word64Set
union Word64Set
empty f Word64Set
xs


-- | \(O(n+m)\). The union of two sets.
union :: Word64Set -> Word64Set -> Word64Set
union :: Word64Set -> Word64Set -> Word64Set
union t1 :: Word64Set
t1@(Bin Mask
p1 Mask
m1 Word64Set
l1 Word64Set
r1) t2 :: Word64Set
t2@(Bin Mask
p2 Mask
m2 Word64Set
l2 Word64Set
r2)
  | Mask -> Mask -> Bool
shorter Mask
m1 Mask
m2  = Word64Set
union1
  | Mask -> Mask -> Bool
shorter Mask
m2 Mask
m1  = Word64Set
union2
  | Mask
p1 Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
== Mask
p2       = Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
Bin Mask
p1 Mask
m1 (Word64Set -> Word64Set -> Word64Set
union Word64Set
l1 Word64Set
l2) (Word64Set -> Word64Set -> Word64Set
union Word64Set
r1 Word64Set
r2)
  | Bool
otherwise      = Mask -> Word64Set -> Mask -> Word64Set -> Word64Set
link Mask
p1 Word64Set
t1 Mask
p2 Word64Set
t2
  where
    union1 :: Word64Set
union1  | Mask -> Mask -> Mask -> Bool
nomatch Mask
p2 Mask
p1 Mask
m1  = Mask -> Word64Set -> Mask -> Word64Set -> Word64Set
link Mask
p1 Word64Set
t1 Mask
p2 Word64Set
t2
            | Mask -> Mask -> Bool
zero Mask
p2 Mask
m1        = Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
Bin Mask
p1 Mask
m1 (Word64Set -> Word64Set -> Word64Set
union Word64Set
l1 Word64Set
t2) Word64Set
r1
            | Bool
otherwise         = Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
Bin Mask
p1 Mask
m1 Word64Set
l1 (Word64Set -> Word64Set -> Word64Set
union Word64Set
r1 Word64Set
t2)

    union2 :: Word64Set
union2  | Mask -> Mask -> Mask -> Bool
nomatch Mask
p1 Mask
p2 Mask
m2  = Mask -> Word64Set -> Mask -> Word64Set -> Word64Set
link Mask
p1 Word64Set
t1 Mask
p2 Word64Set
t2
            | Mask -> Mask -> Bool
zero Mask
p1 Mask
m2        = Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
Bin Mask
p2 Mask
m2 (Word64Set -> Word64Set -> Word64Set
union Word64Set
t1 Word64Set
l2) Word64Set
r2
            | Bool
otherwise         = Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
Bin Mask
p2 Mask
m2 Word64Set
l2 (Word64Set -> Word64Set -> Word64Set
union Word64Set
t1 Word64Set
r2)

union t :: Word64Set
t@(Bin Mask
_ Mask
_ Word64Set
_ Word64Set
_) (Tip Mask
kx Mask
bm) = Mask -> Mask -> Word64Set -> Word64Set
insertBM Mask
kx Mask
bm Word64Set
t
union t :: Word64Set
t@(Bin Mask
_ Mask
_ Word64Set
_ Word64Set
_) Word64Set
Nil = Word64Set
t
union (Tip Mask
kx Mask
bm) Word64Set
t = Mask -> Mask -> Word64Set -> Word64Set
insertBM Mask
kx Mask
bm Word64Set
t
union Word64Set
Nil Word64Set
t = Word64Set
t


{--------------------------------------------------------------------
  Difference
--------------------------------------------------------------------}
-- | \(O(n+m)\). Difference between two sets.
difference :: Word64Set -> Word64Set -> Word64Set
difference :: Word64Set -> Word64Set -> Word64Set
difference t1 :: Word64Set
t1@(Bin Mask
p1 Mask
m1 Word64Set
l1 Word64Set
r1) t2 :: Word64Set
t2@(Bin Mask
p2 Mask
m2 Word64Set
l2 Word64Set
r2)
  | Mask -> Mask -> Bool
shorter Mask
m1 Mask
m2  = Word64Set
difference1
  | Mask -> Mask -> Bool
shorter Mask
m2 Mask
m1  = Word64Set
difference2
  | Mask
p1 Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
== Mask
p2       = Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
bin Mask
p1 Mask
m1 (Word64Set -> Word64Set -> Word64Set
difference Word64Set
l1 Word64Set
l2) (Word64Set -> Word64Set -> Word64Set
difference Word64Set
r1 Word64Set
r2)
  | Bool
otherwise      = Word64Set
t1
  where
    difference1 :: Word64Set
difference1 | Mask -> Mask -> Mask -> Bool
nomatch Mask
p2 Mask
p1 Mask
m1  = Word64Set
t1
                | Mask -> Mask -> Bool
zero Mask
p2 Mask
m1        = Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
bin Mask
p1 Mask
m1 (Word64Set -> Word64Set -> Word64Set
difference Word64Set
l1 Word64Set
t2) Word64Set
r1
                | Bool
otherwise         = Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
bin Mask
p1 Mask
m1 Word64Set
l1 (Word64Set -> Word64Set -> Word64Set
difference Word64Set
r1 Word64Set
t2)

    difference2 :: Word64Set
difference2 | Mask -> Mask -> Mask -> Bool
nomatch Mask
p1 Mask
p2 Mask
m2  = Word64Set
t1
                | Mask -> Mask -> Bool
zero Mask
p1 Mask
m2        = Word64Set -> Word64Set -> Word64Set
difference Word64Set
t1 Word64Set
l2
                | Bool
otherwise         = Word64Set -> Word64Set -> Word64Set
difference Word64Set
t1 Word64Set
r2

difference t :: Word64Set
t@(Bin Mask
_ Mask
_ Word64Set
_ Word64Set
_) (Tip Mask
kx Mask
bm) = Mask -> Mask -> Word64Set -> Word64Set
deleteBM Mask
kx Mask
bm Word64Set
t
difference t :: Word64Set
t@(Bin Mask
_ Mask
_ Word64Set
_ Word64Set
_) Word64Set
Nil = Word64Set
t

difference t1 :: Word64Set
t1@(Tip Mask
kx Mask
bm) Word64Set
t2 = Word64Set -> Word64Set
differenceTip Word64Set
t2
  where differenceTip :: Word64Set -> Word64Set
differenceTip (Bin Mask
p2 Mask
m2 Word64Set
l2 Word64Set
r2) | Mask -> Mask -> Mask -> Bool
nomatch Mask
kx Mask
p2 Mask
m2 = Word64Set
t1
                                        | Mask -> Mask -> Bool
zero Mask
kx Mask
m2 = Word64Set -> Word64Set
differenceTip Word64Set
l2
                                        | Bool
otherwise = Word64Set -> Word64Set
differenceTip Word64Set
r2
        differenceTip (Tip Mask
kx2 Mask
bm2) | Mask
kx Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
== Mask
kx2 = Mask -> Mask -> Word64Set
tip Mask
kx (Mask
bm Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask -> Mask
forall a. Bits a => a -> a
complement Mask
bm2)
                                    | Bool
otherwise = Word64Set
t1
        differenceTip Word64Set
Nil = Word64Set
t1

difference Word64Set
Nil Word64Set
_     = Word64Set
Nil



{--------------------------------------------------------------------
  Intersection
--------------------------------------------------------------------}
-- | \(O(n+m)\). The intersection of two sets.
intersection :: Word64Set -> Word64Set -> Word64Set
intersection :: Word64Set -> Word64Set -> Word64Set
intersection t1 :: Word64Set
t1@(Bin Mask
p1 Mask
m1 Word64Set
l1 Word64Set
r1) t2 :: Word64Set
t2@(Bin Mask
p2 Mask
m2 Word64Set
l2 Word64Set
r2)
  | Mask -> Mask -> Bool
shorter Mask
m1 Mask
m2  = Word64Set
intersection1
  | Mask -> Mask -> Bool
shorter Mask
m2 Mask
m1  = Word64Set
intersection2
  | Mask
p1 Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
== Mask
p2       = Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
bin Mask
p1 Mask
m1 (Word64Set -> Word64Set -> Word64Set
intersection Word64Set
l1 Word64Set
l2) (Word64Set -> Word64Set -> Word64Set
intersection Word64Set
r1 Word64Set
r2)
  | Bool
otherwise      = Word64Set
Nil
  where
    intersection1 :: Word64Set
intersection1 | Mask -> Mask -> Mask -> Bool
nomatch Mask
p2 Mask
p1 Mask
m1  = Word64Set
Nil
                  | Mask -> Mask -> Bool
zero Mask
p2 Mask
m1        = Word64Set -> Word64Set -> Word64Set
intersection Word64Set
l1 Word64Set
t2
                  | Bool
otherwise         = Word64Set -> Word64Set -> Word64Set
intersection Word64Set
r1 Word64Set
t2

    intersection2 :: Word64Set
intersection2 | Mask -> Mask -> Mask -> Bool
nomatch Mask
p1 Mask
p2 Mask
m2  = Word64Set
Nil
                  | Mask -> Mask -> Bool
zero Mask
p1 Mask
m2        = Word64Set -> Word64Set -> Word64Set
intersection Word64Set
t1 Word64Set
l2
                  | Bool
otherwise         = Word64Set -> Word64Set -> Word64Set
intersection Word64Set
t1 Word64Set
r2

intersection t1 :: Word64Set
t1@(Bin Mask
_ Mask
_ Word64Set
_ Word64Set
_) (Tip Mask
kx2 Mask
bm2) = Word64Set -> Word64Set
intersectBM Word64Set
t1
  where intersectBM :: Word64Set -> Word64Set
intersectBM (Bin Mask
p1 Mask
m1 Word64Set
l1 Word64Set
r1) | Mask -> Mask -> Mask -> Bool
nomatch Mask
kx2 Mask
p1 Mask
m1 = Word64Set
Nil
                                      | Mask -> Mask -> Bool
zero Mask
kx2 Mask
m1       = Word64Set -> Word64Set
intersectBM Word64Set
l1
                                      | Bool
otherwise         = Word64Set -> Word64Set
intersectBM Word64Set
r1
        intersectBM (Tip Mask
kx1 Mask
bm1) | Mask
kx1 Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
== Mask
kx2 = Mask -> Mask -> Word64Set
tip Mask
kx1 (Mask
bm1 Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask
bm2)
                                  | Bool
otherwise = Word64Set
Nil
        intersectBM Word64Set
Nil = Word64Set
Nil

intersection (Bin Mask
_ Mask
_ Word64Set
_ Word64Set
_) Word64Set
Nil = Word64Set
Nil

intersection (Tip Mask
kx1 Mask
bm1) Word64Set
t2 = Word64Set -> Word64Set
intersectBM Word64Set
t2
  where intersectBM :: Word64Set -> Word64Set
intersectBM (Bin Mask
p2 Mask
m2 Word64Set
l2 Word64Set
r2) | Mask -> Mask -> Mask -> Bool
nomatch Mask
kx1 Mask
p2 Mask
m2 = Word64Set
Nil
                                      | Mask -> Mask -> Bool
zero Mask
kx1 Mask
m2       = Word64Set -> Word64Set
intersectBM Word64Set
l2
                                      | Bool
otherwise         = Word64Set -> Word64Set
intersectBM Word64Set
r2
        intersectBM (Tip Mask
kx2 Mask
bm2) | Mask
kx1 Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
== Mask
kx2 = Mask -> Mask -> Word64Set
tip Mask
kx1 (Mask
bm1 Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask
bm2)
                                  | Bool
otherwise = Word64Set
Nil
        intersectBM Word64Set
Nil = Word64Set
Nil

intersection Word64Set
Nil Word64Set
_ = Word64Set
Nil

{--------------------------------------------------------------------
  Subset
--------------------------------------------------------------------}
-- | \(O(n+m)\). Is this a proper subset? (ie. a subset but not equal).
isProperSubsetOf :: Word64Set -> Word64Set -> Bool
isProperSubsetOf :: Word64Set -> Word64Set -> Bool
isProperSubsetOf Word64Set
t1 Word64Set
t2
  = case Word64Set -> Word64Set -> Ordering
subsetCmp Word64Set
t1 Word64Set
t2 of
      Ordering
LT -> Bool
True
      Ordering
_  -> Bool
False

subsetCmp :: Word64Set -> Word64Set -> Ordering
subsetCmp :: Word64Set -> Word64Set -> Ordering
subsetCmp t1 :: Word64Set
t1@(Bin Mask
p1 Mask
m1 Word64Set
l1 Word64Set
r1) (Bin Mask
p2 Mask
m2 Word64Set
l2 Word64Set
r2)
  | Mask -> Mask -> Bool
shorter Mask
m1 Mask
m2  = Ordering
GT
  | Mask -> Mask -> Bool
shorter Mask
m2 Mask
m1  = case Ordering
subsetCmpLt of
                       Ordering
GT -> Ordering
GT
                       Ordering
_  -> Ordering
LT
  | Mask
p1 Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
== Mask
p2       = Ordering
subsetCmpEq
  | Bool
otherwise      = Ordering
GT  -- disjoint
  where
    subsetCmpLt :: Ordering
subsetCmpLt | Mask -> Mask -> Mask -> Bool
nomatch Mask
p1 Mask
p2 Mask
m2  = Ordering
GT
                | Mask -> Mask -> Bool
zero Mask
p1 Mask
m2        = Word64Set -> Word64Set -> Ordering
subsetCmp Word64Set
t1 Word64Set
l2
                | Bool
otherwise         = Word64Set -> Word64Set -> Ordering
subsetCmp Word64Set
t1 Word64Set
r2
    subsetCmpEq :: Ordering
subsetCmpEq = case (Word64Set -> Word64Set -> Ordering
subsetCmp Word64Set
l1 Word64Set
l2, Word64Set -> Word64Set -> Ordering
subsetCmp Word64Set
r1 Word64Set
r2) of
                    (Ordering
GT,Ordering
_ ) -> Ordering
GT
                    (Ordering
_ ,Ordering
GT) -> Ordering
GT
                    (Ordering
EQ,Ordering
EQ) -> Ordering
EQ
                    (Ordering, Ordering)
_       -> Ordering
LT

subsetCmp (Bin Mask
_ Mask
_ Word64Set
_ Word64Set
_) Word64Set
_  = Ordering
GT
subsetCmp (Tip Mask
kx1 Mask
bm1) (Tip Mask
kx2 Mask
bm2)
  | Mask
kx1 Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
/= Mask
kx2                  = Ordering
GT -- disjoint
  | Mask
bm1 Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
== Mask
bm2                  = Ordering
EQ
  | Mask
bm1 Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask -> Mask
forall a. Bits a => a -> a
complement Mask
bm2 Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
== Mask
0 = Ordering
LT
  | Bool
otherwise                   = Ordering
GT
subsetCmp t1 :: Word64Set
t1@(Tip Mask
kx Mask
_) (Bin Mask
p Mask
m Word64Set
l Word64Set
r)
  | Mask -> Mask -> Mask -> Bool
nomatch Mask
kx Mask
p Mask
m = Ordering
GT
  | Mask -> Mask -> Bool
zero Mask
kx Mask
m      = case Word64Set -> Word64Set -> Ordering
subsetCmp Word64Set
t1 Word64Set
l of Ordering
GT -> Ordering
GT ; Ordering
_ -> Ordering
LT
  | Bool
otherwise      = case Word64Set -> Word64Set -> Ordering
subsetCmp Word64Set
t1 Word64Set
r of Ordering
GT -> Ordering
GT ; Ordering
_ -> Ordering
LT
subsetCmp (Tip Mask
_ Mask
_) Word64Set
Nil = Ordering
GT -- disjoint
subsetCmp Word64Set
Nil Word64Set
Nil = Ordering
EQ
subsetCmp Word64Set
Nil Word64Set
_   = Ordering
LT

-- | \(O(n+m)\). Is this a subset?
-- @(s1 \`isSubsetOf\` s2)@ tells whether @s1@ is a subset of @s2@.

isSubsetOf :: Word64Set -> Word64Set -> Bool
isSubsetOf :: Word64Set -> Word64Set -> Bool
isSubsetOf t1 :: Word64Set
t1@(Bin Mask
p1 Mask
m1 Word64Set
l1 Word64Set
r1) (Bin Mask
p2 Mask
m2 Word64Set
l2 Word64Set
r2)
  | Mask -> Mask -> Bool
shorter Mask
m1 Mask
m2  = Bool
False
  | Mask -> Mask -> Bool
shorter Mask
m2 Mask
m1  = Mask -> Mask -> Mask -> Bool
match Mask
p1 Mask
p2 Mask
m2 Bool -> Bool -> Bool
&& (if Mask -> Mask -> Bool
zero Mask
p1 Mask
m2 then Word64Set -> Word64Set -> Bool
isSubsetOf Word64Set
t1 Word64Set
l2
                                                      else Word64Set -> Word64Set -> Bool
isSubsetOf Word64Set
t1 Word64Set
r2)
  | Bool
otherwise      = (Mask
p1Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
==Mask
p2) Bool -> Bool -> Bool
&& Word64Set -> Word64Set -> Bool
isSubsetOf Word64Set
l1 Word64Set
l2 Bool -> Bool -> Bool
&& Word64Set -> Word64Set -> Bool
isSubsetOf Word64Set
r1 Word64Set
r2
isSubsetOf (Bin Mask
_ Mask
_ Word64Set
_ Word64Set
_) Word64Set
_  = Bool
False
isSubsetOf (Tip Mask
kx1 Mask
bm1) (Tip Mask
kx2 Mask
bm2) = Mask
kx1 Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
== Mask
kx2 Bool -> Bool -> Bool
&& Mask
bm1 Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask -> Mask
forall a. Bits a => a -> a
complement Mask
bm2 Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
== Mask
0
isSubsetOf t1 :: Word64Set
t1@(Tip Mask
kx Mask
_) (Bin Mask
p Mask
m Word64Set
l Word64Set
r)
  | Mask -> Mask -> Mask -> Bool
nomatch Mask
kx Mask
p Mask
m = Bool
False
  | Mask -> Mask -> Bool
zero Mask
kx Mask
m      = Word64Set -> Word64Set -> Bool
isSubsetOf Word64Set
t1 Word64Set
l
  | Bool
otherwise      = Word64Set -> Word64Set -> Bool
isSubsetOf Word64Set
t1 Word64Set
r
isSubsetOf (Tip Mask
_ Mask
_) Word64Set
Nil = Bool
False
isSubsetOf Word64Set
Nil Word64Set
_         = Bool
True


{--------------------------------------------------------------------
  Disjoint
--------------------------------------------------------------------}
-- | \(O(n+m)\). Check whether two sets are disjoint (i.e. their intersection
--   is empty).
--
-- > disjoint (fromList [2,4,6])   (fromList [1,3])     == True
-- > disjoint (fromList [2,4,6,8]) (fromList [2,3,5,7]) == False
-- > disjoint (fromList [1,2])     (fromList [1,2,3,4]) == False
-- > disjoint (fromList [])        (fromList [])        == True
--
-- @since 0.5.11
disjoint :: Word64Set -> Word64Set -> Bool
disjoint :: Word64Set -> Word64Set -> Bool
disjoint t1 :: Word64Set
t1@(Bin Mask
p1 Mask
m1 Word64Set
l1 Word64Set
r1) t2 :: Word64Set
t2@(Bin Mask
p2 Mask
m2 Word64Set
l2 Word64Set
r2)
  | Mask -> Mask -> Bool
shorter Mask
m1 Mask
m2  = Bool
disjoint1
  | Mask -> Mask -> Bool
shorter Mask
m2 Mask
m1  = Bool
disjoint2
  | Mask
p1 Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
== Mask
p2       = Word64Set -> Word64Set -> Bool
disjoint Word64Set
l1 Word64Set
l2 Bool -> Bool -> Bool
&& Word64Set -> Word64Set -> Bool
disjoint Word64Set
r1 Word64Set
r2
  | Bool
otherwise      = Bool
True
  where
    disjoint1 :: Bool
disjoint1 | Mask -> Mask -> Mask -> Bool
nomatch Mask
p2 Mask
p1 Mask
m1  = Bool
True
              | Mask -> Mask -> Bool
zero Mask
p2 Mask
m1        = Word64Set -> Word64Set -> Bool
disjoint Word64Set
l1 Word64Set
t2
              | Bool
otherwise         = Word64Set -> Word64Set -> Bool
disjoint Word64Set
r1 Word64Set
t2

    disjoint2 :: Bool
disjoint2 | Mask -> Mask -> Mask -> Bool
nomatch Mask
p1 Mask
p2 Mask
m2  = Bool
True
              | Mask -> Mask -> Bool
zero Mask
p1 Mask
m2        = Word64Set -> Word64Set -> Bool
disjoint Word64Set
t1 Word64Set
l2
              | Bool
otherwise         = Word64Set -> Word64Set -> Bool
disjoint Word64Set
t1 Word64Set
r2

disjoint t1 :: Word64Set
t1@(Bin Mask
_ Mask
_ Word64Set
_ Word64Set
_) (Tip Mask
kx2 Mask
bm2) = Word64Set -> Bool
disjointBM Word64Set
t1
  where disjointBM :: Word64Set -> Bool
disjointBM (Bin Mask
p1 Mask
m1 Word64Set
l1 Word64Set
r1) | Mask -> Mask -> Mask -> Bool
nomatch Mask
kx2 Mask
p1 Mask
m1 = Bool
True
                                     | Mask -> Mask -> Bool
zero Mask
kx2 Mask
m1       = Word64Set -> Bool
disjointBM Word64Set
l1
                                     | Bool
otherwise         = Word64Set -> Bool
disjointBM Word64Set
r1
        disjointBM (Tip Mask
kx1 Mask
bm1) | Mask
kx1 Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
== Mask
kx2 = (Mask
bm1 Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask
bm2) Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
== Mask
0
                                 | Bool
otherwise = Bool
True
        disjointBM Word64Set
Nil = Bool
True

disjoint (Bin Mask
_ Mask
_ Word64Set
_ Word64Set
_) Word64Set
Nil = Bool
True

disjoint (Tip Mask
kx1 Mask
bm1) Word64Set
t2 = Word64Set -> Bool
disjointBM Word64Set
t2
  where disjointBM :: Word64Set -> Bool
disjointBM (Bin Mask
p2 Mask
m2 Word64Set
l2 Word64Set
r2) | Mask -> Mask -> Mask -> Bool
nomatch Mask
kx1 Mask
p2 Mask
m2 = Bool
True
                                     | Mask -> Mask -> Bool
zero Mask
kx1 Mask
m2       = Word64Set -> Bool
disjointBM Word64Set
l2
                                     | Bool
otherwise         = Word64Set -> Bool
disjointBM Word64Set
r2
        disjointBM (Tip Mask
kx2 Mask
bm2) | Mask
kx1 Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
== Mask
kx2 = (Mask
bm1 Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask
bm2) Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
== Mask
0
                                 | Bool
otherwise = Bool
True
        disjointBM Word64Set
Nil = Bool
True

disjoint Word64Set
Nil Word64Set
_ = Bool
True


{--------------------------------------------------------------------
  Filter
--------------------------------------------------------------------}
-- | \(O(n)\). Filter all elements that satisfy some predicate.
filter :: (Key -> Bool) -> Word64Set -> Word64Set
filter :: (Mask -> Bool) -> Word64Set -> Word64Set
filter Mask -> Bool
predicate Word64Set
t
  = case Word64Set
t of
      Bin Mask
p Mask
m Word64Set
l Word64Set
r
        -> Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
bin Mask
p Mask
m ((Mask -> Bool) -> Word64Set -> Word64Set
filter Mask -> Bool
predicate Word64Set
l) ((Mask -> Bool) -> Word64Set -> Word64Set
filter Mask -> Bool
predicate Word64Set
r)
      Tip Mask
kx Mask
bm
        -> Mask -> Mask -> Word64Set
tip Mask
kx (Mask -> (Mask -> Mask -> Mask) -> Mask -> Mask -> Mask
forall a. Mask -> (a -> Mask -> a) -> a -> Mask -> a
foldl'Bits Mask
0 (Mask -> Mask -> Mask -> Mask
bitPred Mask
kx) Mask
0 Mask
bm)
      Word64Set
Nil -> Word64Set
Nil
  where bitPred :: Mask -> Mask -> Mask -> Mask
bitPred Mask
kx Mask
bm Mask
bi | Mask -> Bool
predicate (Mask
kx Mask -> Mask -> Mask
forall a. Num a => a -> a -> a
+ Mask
bi) = Mask
bm Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.|. Mask -> Mask
bitmapOfSuffix Mask
bi
                         | Bool
otherwise           = Mask
bm
        {-# INLINE bitPred #-}

-- | \(O(n)\). partition the set according to some predicate.
partition :: (Key -> Bool) -> Word64Set -> (Word64Set,Word64Set)
partition :: (Mask -> Bool) -> Word64Set -> (Word64Set, Word64Set)
partition Mask -> Bool
predicate0 Word64Set
t0 = StrictPair Word64Set Word64Set -> (Word64Set, Word64Set)
forall a b. StrictPair a b -> (a, b)
toPair (StrictPair Word64Set Word64Set -> (Word64Set, Word64Set))
-> StrictPair Word64Set Word64Set -> (Word64Set, Word64Set)
forall a b. (a -> b) -> a -> b
$ (Mask -> Bool) -> Word64Set -> StrictPair Word64Set Word64Set
go Mask -> Bool
predicate0 Word64Set
t0
  where
    go :: (Mask -> Bool) -> Word64Set -> StrictPair Word64Set Word64Set
go Mask -> Bool
predicate Word64Set
t
      = case Word64Set
t of
          Bin Mask
p Mask
m Word64Set
l Word64Set
r
            -> let (Word64Set
l1 :*: Word64Set
l2) = (Mask -> Bool) -> Word64Set -> StrictPair Word64Set Word64Set
go Mask -> Bool
predicate Word64Set
l
                   (Word64Set
r1 :*: Word64Set
r2) = (Mask -> Bool) -> Word64Set -> StrictPair Word64Set Word64Set
go Mask -> Bool
predicate Word64Set
r
               in Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
bin Mask
p Mask
m Word64Set
l1 Word64Set
r1 Word64Set -> Word64Set -> StrictPair Word64Set Word64Set
forall a b. a -> b -> StrictPair a b
:*: Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
bin Mask
p Mask
m Word64Set
l2 Word64Set
r2
          Tip Mask
kx Mask
bm
            -> let bm1 :: Mask
bm1 = Mask -> (Mask -> Mask -> Mask) -> Mask -> Mask -> Mask
forall a. Mask -> (a -> Mask -> a) -> a -> Mask -> a
foldl'Bits Mask
0 (Mask -> Mask -> Mask -> Mask
bitPred Mask
kx) Mask
0 Mask
bm
               in  Mask -> Mask -> Word64Set
tip Mask
kx Mask
bm1 Word64Set -> Word64Set -> StrictPair Word64Set Word64Set
forall a b. a -> b -> StrictPair a b
:*: Mask -> Mask -> Word64Set
tip Mask
kx (Mask
bm Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
`xor` Mask
bm1)
          Word64Set
Nil -> (Word64Set
Nil Word64Set -> Word64Set -> StrictPair Word64Set Word64Set
forall a b. a -> b -> StrictPair a b
:*: Word64Set
Nil)
      where bitPred :: Mask -> Mask -> Mask -> Mask
bitPred Mask
kx Mask
bm Mask
bi | Mask -> Bool
predicate (Mask
kx Mask -> Mask -> Mask
forall a. Num a => a -> a -> a
+ Mask
bi) = Mask
bm Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.|. Mask -> Mask
bitmapOfSuffix Mask
bi
                             | Bool
otherwise           = Mask
bm
            {-# INLINE bitPred #-}

-- | \(O(\min(n,W))\). Take while a predicate on the elements holds.
-- The user is responsible for ensuring that for all @Int@s, @j \< k ==\> p j \>= p k@.
-- See note at 'spanAntitone'.
--
-- @
-- takeWhileAntitone p = 'fromDistinctAscList' . 'Data.List.takeWhile' p . 'toList'
-- takeWhileAntitone p = 'filter' p
-- @
--
-- @since 0.6.7
takeWhileAntitone :: (Key -> Bool) -> Word64Set -> Word64Set
takeWhileAntitone :: (Mask -> Bool) -> Word64Set -> Word64Set
takeWhileAntitone Mask -> Bool
predicate Word64Set
t =
  case Word64Set
t of
    Bin Mask
p Mask
m Word64Set
l Word64Set
r
      | Mask
m Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
< Mask
0 ->
        if Mask -> Bool
predicate Mask
0 -- handle negative numbers.
        then Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
bin Mask
p Mask
m ((Mask -> Bool) -> Word64Set -> Word64Set
go Mask -> Bool
predicate Word64Set
l) Word64Set
r
        else (Mask -> Bool) -> Word64Set -> Word64Set
go Mask -> Bool
predicate Word64Set
r
    Word64Set
_ -> (Mask -> Bool) -> Word64Set -> Word64Set
go Mask -> Bool
predicate Word64Set
t
  where
    go :: (Mask -> Bool) -> Word64Set -> Word64Set
go Mask -> Bool
predicate' (Bin Mask
p Mask
m Word64Set
l Word64Set
r)
      | Mask -> Bool
predicate' (Mask -> Bool) -> Mask -> Bool
forall a b. (a -> b) -> a -> b
$! Mask
pMask -> Mask -> Mask
forall a. Num a => a -> a -> a
+Mask
m = Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
bin Mask
p Mask
m Word64Set
l ((Mask -> Bool) -> Word64Set -> Word64Set
go Mask -> Bool
predicate' Word64Set
r)
      | Bool
otherwise         = (Mask -> Bool) -> Word64Set -> Word64Set
go Mask -> Bool
predicate' Word64Set
l
    go Mask -> Bool
predicate' (Tip Mask
kx Mask
bm) = Mask -> Mask -> Word64Set
tip Mask
kx (Mask -> (Mask -> Bool) -> Mask -> Mask
takeWhileAntitoneBits Mask
kx Mask -> Bool
predicate' Mask
bm)
    go Mask -> Bool
_ Word64Set
Nil = Word64Set
Nil

-- | \(O(\min(n,W))\). Drop while a predicate on the elements holds.
-- The user is responsible for ensuring that for all @Int@s, @j \< k ==\> p j \>= p k@.
-- See note at 'spanAntitone'.
--
-- @
-- dropWhileAntitone p = 'fromDistinctAscList' . 'Data.List.dropWhile' p . 'toList'
-- dropWhileAntitone p = 'filter' (not . p)
-- @
--
-- @since 0.6.7
dropWhileAntitone :: (Key -> Bool) -> Word64Set -> Word64Set
dropWhileAntitone :: (Mask -> Bool) -> Word64Set -> Word64Set
dropWhileAntitone Mask -> Bool
predicate Word64Set
t =
  case Word64Set
t of
    Bin Mask
p Mask
m Word64Set
l Word64Set
r
      | Mask
m Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
< Mask
0 ->
        if Mask -> Bool
predicate Mask
0 -- handle negative numbers.
        then (Mask -> Bool) -> Word64Set -> Word64Set
go Mask -> Bool
predicate Word64Set
l
        else Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
bin Mask
p Mask
m Word64Set
l ((Mask -> Bool) -> Word64Set -> Word64Set
go Mask -> Bool
predicate Word64Set
r)
    Word64Set
_ -> (Mask -> Bool) -> Word64Set -> Word64Set
go Mask -> Bool
predicate Word64Set
t
  where
    go :: (Mask -> Bool) -> Word64Set -> Word64Set
go Mask -> Bool
predicate' (Bin Mask
p Mask
m Word64Set
l Word64Set
r)
      | Mask -> Bool
predicate' (Mask -> Bool) -> Mask -> Bool
forall a b. (a -> b) -> a -> b
$! Mask
pMask -> Mask -> Mask
forall a. Num a => a -> a -> a
+Mask
m = (Mask -> Bool) -> Word64Set -> Word64Set
go Mask -> Bool
predicate' Word64Set
r
      | Bool
otherwise         = Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
bin Mask
p Mask
m ((Mask -> Bool) -> Word64Set -> Word64Set
go Mask -> Bool
predicate' Word64Set
l) Word64Set
r
    go Mask -> Bool
predicate' (Tip Mask
kx Mask
bm) = Mask -> Mask -> Word64Set
tip Mask
kx (Mask
bm Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
`xor` Mask -> (Mask -> Bool) -> Mask -> Mask
takeWhileAntitoneBits Mask
kx Mask -> Bool
predicate' Mask
bm)
    go Mask -> Bool
_ Word64Set
Nil = Word64Set
Nil

-- | \(O(\min(n,W))\). Divide a set at the point where a predicate on the elements stops holding.
-- The user is responsible for ensuring that for all @Int@s, @j \< k ==\> p j \>= p k@.
--
-- @
-- spanAntitone p xs = ('takeWhileAntitone' p xs, 'dropWhileAntitone' p xs)
-- spanAntitone p xs = 'partition' p xs
-- @
--
-- Note: if @p@ is not actually antitone, then @spanAntitone@ will split the set
-- at some /unspecified/ point.
--
-- @since 0.6.7
spanAntitone :: (Key -> Bool) -> Word64Set -> (Word64Set, Word64Set)
spanAntitone :: (Mask -> Bool) -> Word64Set -> (Word64Set, Word64Set)
spanAntitone Mask -> Bool
predicate Word64Set
t =
  case Word64Set
t of
    Bin Mask
p Mask
m Word64Set
l Word64Set
r
      | Mask
m Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
< Mask
0 ->
        if Mask -> Bool
predicate Mask
0 -- handle negative numbers.
        then
          case (Mask -> Bool) -> Word64Set -> StrictPair Word64Set Word64Set
go Mask -> Bool
predicate Word64Set
l of
            (Word64Set
lt :*: Word64Set
gt) ->
              let !lt' :: Word64Set
lt' = Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
bin Mask
p Mask
m Word64Set
lt Word64Set
r
              in (Word64Set
lt', Word64Set
gt)
        else
          case (Mask -> Bool) -> Word64Set -> StrictPair Word64Set Word64Set
go Mask -> Bool
predicate Word64Set
r of
            (Word64Set
lt :*: Word64Set
gt) ->
              let !gt' :: Word64Set
gt' = Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
bin Mask
p Mask
m Word64Set
l Word64Set
gt
              in (Word64Set
lt, Word64Set
gt')
    Word64Set
_ -> case (Mask -> Bool) -> Word64Set -> StrictPair Word64Set Word64Set
go Mask -> Bool
predicate Word64Set
t of
          (Word64Set
lt :*: Word64Set
gt) -> (Word64Set
lt, Word64Set
gt)
  where
    go :: (Mask -> Bool) -> Word64Set -> StrictPair Word64Set Word64Set
go Mask -> Bool
predicate' (Bin Mask
p Mask
m Word64Set
l Word64Set
r)
      | Mask -> Bool
predicate' (Mask -> Bool) -> Mask -> Bool
forall a b. (a -> b) -> a -> b
$! Mask
pMask -> Mask -> Mask
forall a. Num a => a -> a -> a
+Mask
m = case (Mask -> Bool) -> Word64Set -> StrictPair Word64Set Word64Set
go Mask -> Bool
predicate' Word64Set
r of (Word64Set
lt :*: Word64Set
gt) -> Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
bin Mask
p Mask
m Word64Set
l Word64Set
lt Word64Set -> Word64Set -> StrictPair Word64Set Word64Set
forall a b. a -> b -> StrictPair a b
:*: Word64Set
gt
      | Bool
otherwise         = case (Mask -> Bool) -> Word64Set -> StrictPair Word64Set Word64Set
go Mask -> Bool
predicate' Word64Set
l of (Word64Set
lt :*: Word64Set
gt) -> Word64Set
lt Word64Set -> Word64Set -> StrictPair Word64Set Word64Set
forall a b. a -> b -> StrictPair a b
:*: Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
bin Mask
p Mask
m Word64Set
gt Word64Set
r
    go Mask -> Bool
predicate' (Tip Mask
kx Mask
bm) = let bm' :: Mask
bm' = Mask -> (Mask -> Bool) -> Mask -> Mask
takeWhileAntitoneBits Mask
kx Mask -> Bool
predicate' Mask
bm
                                in (Mask -> Mask -> Word64Set
tip Mask
kx Mask
bm' Word64Set -> Word64Set -> StrictPair Word64Set Word64Set
forall a b. a -> b -> StrictPair a b
:*: Mask -> Mask -> Word64Set
tip Mask
kx (Mask
bm Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
`xor` Mask
bm'))
    go Mask -> Bool
_ Word64Set
Nil = (Word64Set
Nil Word64Set -> Word64Set -> StrictPair Word64Set Word64Set
forall a b. a -> b -> StrictPair a b
:*: Word64Set
Nil)

-- | \(O(\min(n,W))\). The expression (@'split' x set@) is a pair @(set1,set2)@
-- where @set1@ comprises the elements of @set@ less than @x@ and @set2@
-- comprises the elements of @set@ greater than @x@.
--
-- > split 3 (fromList [1..5]) == (fromList [1,2], fromList [4,5])
split :: Key -> Word64Set -> (Word64Set,Word64Set)
split :: Mask -> Word64Set -> (Word64Set, Word64Set)
split Mask
x Word64Set
t =
  case Word64Set
t of
    Bin Mask
p Mask
m Word64Set
l Word64Set
r
      | Mask
m Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
< Mask
0 ->
        if Mask
x Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
>= Mask
0  -- handle negative numbers.
        then
          case Mask -> Word64Set -> StrictPair Word64Set Word64Set
go Mask
x Word64Set
l of
            (Word64Set
lt :*: Word64Set
gt) ->
              let !lt' :: Word64Set
lt' = Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
bin Mask
p Mask
m Word64Set
lt Word64Set
r
              in (Word64Set
lt', Word64Set
gt)
        else
          case Mask -> Word64Set -> StrictPair Word64Set Word64Set
go Mask
x Word64Set
r of
            (Word64Set
lt :*: Word64Set
gt) ->
              let !gt' :: Word64Set
gt' = Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
bin Mask
p Mask
m Word64Set
l Word64Set
gt
              in (Word64Set
lt, Word64Set
gt')
    Word64Set
_ -> case Mask -> Word64Set -> StrictPair Word64Set Word64Set
go Mask
x Word64Set
t of
          (Word64Set
lt :*: Word64Set
gt) -> (Word64Set
lt, Word64Set
gt)
  where
    go :: Mask -> Word64Set -> StrictPair Word64Set Word64Set
go !Mask
x' t' :: Word64Set
t'@(Bin Mask
p Mask
m Word64Set
l Word64Set
r)
        | Mask -> Mask -> Mask -> Bool
nomatch Mask
x' Mask
p Mask
m = if Mask
x' Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
< Mask
p then (Word64Set
Nil Word64Set -> Word64Set -> StrictPair Word64Set Word64Set
forall a b. a -> b -> StrictPair a b
:*: Word64Set
t') else (Word64Set
t' Word64Set -> Word64Set -> StrictPair Word64Set Word64Set
forall a b. a -> b -> StrictPair a b
:*: Word64Set
Nil)
        | Mask -> Mask -> Bool
zero Mask
x' Mask
m      = case Mask -> Word64Set -> StrictPair Word64Set Word64Set
go Mask
x' Word64Set
l of (Word64Set
lt :*: Word64Set
gt) -> Word64Set
lt Word64Set -> Word64Set -> StrictPair Word64Set Word64Set
forall a b. a -> b -> StrictPair a b
:*: Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
bin Mask
p Mask
m Word64Set
gt Word64Set
r
        | Bool
otherwise      = case Mask -> Word64Set -> StrictPair Word64Set Word64Set
go Mask
x' Word64Set
r of (Word64Set
lt :*: Word64Set
gt) -> Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
bin Mask
p Mask
m Word64Set
l Word64Set
lt Word64Set -> Word64Set -> StrictPair Word64Set Word64Set
forall a b. a -> b -> StrictPair a b
:*: Word64Set
gt
    go Mask
x' t' :: Word64Set
t'@(Tip Mask
kx' Mask
bm)
        | Mask
kx' Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
> Mask
x'          = (Word64Set
Nil Word64Set -> Word64Set -> StrictPair Word64Set Word64Set
forall a b. a -> b -> StrictPair a b
:*: Word64Set
t')
          -- equivalent to kx' > prefixOf x'
        | Mask
kx' Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
< Mask -> Mask
prefixOf Mask
x' = (Word64Set
t' Word64Set -> Word64Set -> StrictPair Word64Set Word64Set
forall a b. a -> b -> StrictPair a b
:*: Word64Set
Nil)
        | Bool
otherwise = Mask -> Mask -> Word64Set
tip Mask
kx' (Mask
bm Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask
lowerBitmap) Word64Set -> Word64Set -> StrictPair Word64Set Word64Set
forall a b. a -> b -> StrictPair a b
:*: Mask -> Mask -> Word64Set
tip Mask
kx' (Mask
bm Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask
higherBitmap)
            where lowerBitmap :: Mask
lowerBitmap = Mask -> Mask
bitmapOf Mask
x' Mask -> Mask -> Mask
forall a. Num a => a -> a -> a
- Mask
1
                  higherBitmap :: Mask
higherBitmap = Mask -> Mask
forall a. Bits a => a -> a
complement (Mask
lowerBitmap Mask -> Mask -> Mask
forall a. Num a => a -> a -> a
+ Mask -> Mask
bitmapOf Mask
x')
    go Mask
_ Word64Set
Nil = (Word64Set
Nil Word64Set -> Word64Set -> StrictPair Word64Set Word64Set
forall a b. a -> b -> StrictPair a b
:*: Word64Set
Nil)

-- | \(O(\min(n,W))\). Performs a 'split' but also returns whether the pivot
-- element was found in the original set.
splitMember :: Key -> Word64Set -> (Word64Set,Bool,Word64Set)
splitMember :: Mask -> Word64Set -> (Word64Set, Bool, Word64Set)
splitMember Mask
x Word64Set
t =
  case Word64Set
t of
    Bin Mask
p Mask
m Word64Set
l Word64Set
r
      | Mask
m Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
< Mask
0 ->
        if Mask
x Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
>= Mask
0 -- handle negative numbers.
        then
          case Mask -> Word64Set -> (Word64Set, Bool, Word64Set)
go Mask
x Word64Set
l of
            (Word64Set
lt, Bool
fnd, Word64Set
gt) ->
              let !lt' :: Word64Set
lt' = Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
bin Mask
p Mask
m Word64Set
lt Word64Set
r
              in (Word64Set
lt', Bool
fnd, Word64Set
gt)
        else
          case Mask -> Word64Set -> (Word64Set, Bool, Word64Set)
go Mask
x Word64Set
r of
            (Word64Set
lt, Bool
fnd, Word64Set
gt) ->
              let !gt' :: Word64Set
gt' = Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
bin Mask
p Mask
m Word64Set
l Word64Set
gt
              in (Word64Set
lt, Bool
fnd, Word64Set
gt')
    Word64Set
_ -> Mask -> Word64Set -> (Word64Set, Bool, Word64Set)
go Mask
x Word64Set
t
  where
    go :: Mask -> Word64Set -> (Word64Set, Bool, Word64Set)
go Mask
x' t' :: Word64Set
t'@(Bin Mask
p Mask
m Word64Set
l Word64Set
r)
        | Mask -> Mask -> Mask -> Bool
nomatch Mask
x' Mask
p Mask
m = if Mask
x' Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
< Mask
p then (Word64Set
Nil, Bool
False, Word64Set
t') else (Word64Set
t', Bool
False, Word64Set
Nil)
        | Mask -> Mask -> Bool
zero Mask
x' Mask
m =
          case Mask -> Word64Set -> (Word64Set, Bool, Word64Set)
go Mask
x' Word64Set
l of
            (Word64Set
lt, Bool
fnd, Word64Set
gt) ->
              let !gt' :: Word64Set
gt' = Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
bin Mask
p Mask
m Word64Set
gt Word64Set
r
              in (Word64Set
lt, Bool
fnd, Word64Set
gt')
        | Bool
otherwise =
          case Mask -> Word64Set -> (Word64Set, Bool, Word64Set)
go Mask
x' Word64Set
r of
            (Word64Set
lt, Bool
fnd, Word64Set
gt) ->
              let !lt' :: Word64Set
lt' = Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
bin Mask
p Mask
m Word64Set
l Word64Set
lt
              in (Word64Set
lt', Bool
fnd, Word64Set
gt)
    go Mask
x' t' :: Word64Set
t'@(Tip Mask
kx' Mask
bm)
        | Mask
kx' Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
> Mask
x'          = (Word64Set
Nil, Bool
False, Word64Set
t')
          -- equivalent to kx' > prefixOf x'
        | Mask
kx' Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
< Mask -> Mask
prefixOf Mask
x' = (Word64Set
t', Bool
False, Word64Set
Nil)
        | Bool
otherwise = let !lt :: Word64Set
lt = Mask -> Mask -> Word64Set
tip Mask
kx' (Mask
bm Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask
lowerBitmap)
                          !found :: Bool
found = (Mask
bm Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask
bitmapOfx') Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
/= Mask
0
                          !gt :: Word64Set
gt = Mask -> Mask -> Word64Set
tip Mask
kx' (Mask
bm Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask
higherBitmap)
                      in (Word64Set
lt, Bool
found, Word64Set
gt)
            where bitmapOfx' :: Mask
bitmapOfx' = Mask -> Mask
bitmapOf Mask
x'
                  lowerBitmap :: Mask
lowerBitmap = Mask
bitmapOfx' Mask -> Mask -> Mask
forall a. Num a => a -> a -> a
- Mask
1
                  higherBitmap :: Mask
higherBitmap = Mask -> Mask
forall a. Bits a => a -> a
complement (Mask
lowerBitmap Mask -> Mask -> Mask
forall a. Num a => a -> a -> a
+ Mask
bitmapOfx')
    go Mask
_ Word64Set
Nil = (Word64Set
Nil, Bool
False, Word64Set
Nil)

{----------------------------------------------------------------------
  Min/Max
----------------------------------------------------------------------}

-- | \(O(\min(n,W))\). Retrieves the maximal key of the set, and the set
-- stripped of that element, or 'Nothing' if passed an empty set.
maxView :: Word64Set -> Maybe (Key, Word64Set)
maxView :: Word64Set -> Maybe (Mask, Word64Set)
maxView Word64Set
t =
  case Word64Set
t of Word64Set
Nil -> Maybe (Mask, Word64Set)
forall a. Maybe a
Nothing
            Bin Mask
p Mask
m Word64Set
l Word64Set
r | Mask
m Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
< Mask
0 -> case Word64Set -> (Mask, Word64Set)
go Word64Set
l of (Mask
result, Word64Set
l') -> (Mask, Word64Set) -> Maybe (Mask, Word64Set)
forall a. a -> Maybe a
Just (Mask
result, Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
bin Mask
p Mask
m Word64Set
l' Word64Set
r)
            Word64Set
_ -> (Mask, Word64Set) -> Maybe (Mask, Word64Set)
forall a. a -> Maybe a
Just (Word64Set -> (Mask, Word64Set)
go Word64Set
t)
  where
    go :: Word64Set -> (Mask, Word64Set)
go (Bin Mask
p Mask
m Word64Set
l Word64Set
r) = case Word64Set -> (Mask, Word64Set)
go Word64Set
r of (Mask
result, Word64Set
r') -> (Mask
result, Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
bin Mask
p Mask
m Word64Set
l Word64Set
r')
    go (Tip Mask
kx Mask
bm) = case Mask -> Mask
highestBitSet Mask
bm of Mask
bi -> (Mask
kx Mask -> Mask -> Mask
forall a. Num a => a -> a -> a
+ Mask
bi, Mask -> Mask -> Word64Set
tip Mask
kx (Mask
bm Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask -> Mask
forall a. Bits a => a -> a
complement (Mask -> Mask
bitmapOfSuffix Mask
bi)))
    go Word64Set
Nil = [Char] -> (Mask, Word64Set)
forall a. HasCallStack => [Char] -> a
error [Char]
"maxView Nil"

-- | \(O(\min(n,W))\). Retrieves the minimal key of the set, and the set
-- stripped of that element, or 'Nothing' if passed an empty set.
minView :: Word64Set -> Maybe (Key, Word64Set)
minView :: Word64Set -> Maybe (Mask, Word64Set)
minView Word64Set
t =
  case Word64Set
t of Word64Set
Nil -> Maybe (Mask, Word64Set)
forall a. Maybe a
Nothing
            Bin Mask
p Mask
m Word64Set
l Word64Set
r | Mask
m Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
< Mask
0 -> case Word64Set -> (Mask, Word64Set)
go Word64Set
r of (Mask
result, Word64Set
r') -> (Mask, Word64Set) -> Maybe (Mask, Word64Set)
forall a. a -> Maybe a
Just (Mask
result, Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
bin Mask
p Mask
m Word64Set
l Word64Set
r')
            Word64Set
_ -> (Mask, Word64Set) -> Maybe (Mask, Word64Set)
forall a. a -> Maybe a
Just (Word64Set -> (Mask, Word64Set)
go Word64Set
t)
  where
    go :: Word64Set -> (Mask, Word64Set)
go (Bin Mask
p Mask
m Word64Set
l Word64Set
r) = case Word64Set -> (Mask, Word64Set)
go Word64Set
l of (Mask
result, Word64Set
l') -> (Mask
result, Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
bin Mask
p Mask
m Word64Set
l' Word64Set
r)
    go (Tip Mask
kx Mask
bm) = case Mask -> Mask
lowestBitSet Mask
bm of Mask
bi -> (Mask
kx Mask -> Mask -> Mask
forall a. Num a => a -> a -> a
+ Mask
bi, Mask -> Mask -> Word64Set
tip Mask
kx (Mask
bm Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask -> Mask
forall a. Bits a => a -> a
complement (Mask -> Mask
bitmapOfSuffix Mask
bi)))
    go Word64Set
Nil = [Char] -> (Mask, Word64Set)
forall a. HasCallStack => [Char] -> a
error [Char]
"minView Nil"

-- | \(O(\min(n,W))\). Delete and find the minimal element.
--
-- > deleteFindMin set = (findMin set, deleteMin set)
deleteFindMin :: Word64Set -> (Key, Word64Set)
deleteFindMin :: Word64Set -> (Mask, Word64Set)
deleteFindMin = (Mask, Word64Set) -> Maybe (Mask, Word64Set) -> (Mask, Word64Set)
forall a. a -> Maybe a -> a
fromMaybe ([Char] -> (Mask, Word64Set)
forall a. HasCallStack => [Char] -> a
error [Char]
"deleteFindMin: empty set has no minimal element") (Maybe (Mask, Word64Set) -> (Mask, Word64Set))
-> (Word64Set -> Maybe (Mask, Word64Set))
-> Word64Set
-> (Mask, Word64Set)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word64Set -> Maybe (Mask, Word64Set)
minView

-- | \(O(\min(n,W))\). Delete and find the maximal element.
--
-- > deleteFindMax set = (findMax set, deleteMax set)
deleteFindMax :: Word64Set -> (Key, Word64Set)
deleteFindMax :: Word64Set -> (Mask, Word64Set)
deleteFindMax = (Mask, Word64Set) -> Maybe (Mask, Word64Set) -> (Mask, Word64Set)
forall a. a -> Maybe a -> a
fromMaybe ([Char] -> (Mask, Word64Set)
forall a. HasCallStack => [Char] -> a
error [Char]
"deleteFindMax: empty set has no maximal element") (Maybe (Mask, Word64Set) -> (Mask, Word64Set))
-> (Word64Set -> Maybe (Mask, Word64Set))
-> Word64Set
-> (Mask, Word64Set)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word64Set -> Maybe (Mask, Word64Set)
maxView


-- | \(O(\min(n,W))\). The minimal element of the set.
findMin :: Word64Set -> Key
findMin :: Word64Set -> Mask
findMin Word64Set
Nil = [Char] -> Mask
forall a. HasCallStack => [Char] -> a
error [Char]
"findMin: empty set has no minimal element"
findMin (Tip Mask
kx Mask
bm) = Mask
kx Mask -> Mask -> Mask
forall a. Num a => a -> a -> a
+ Mask -> Mask
lowestBitSet Mask
bm
findMin (Bin Mask
_ Mask
m Word64Set
l Word64Set
r)
  |   Mask
m Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
< Mask
0   = Word64Set -> Mask
find Word64Set
r
  | Bool
otherwise = Word64Set -> Mask
find Word64Set
l
    where find :: Word64Set -> Mask
find (Tip Mask
kx Mask
bm) = Mask
kx Mask -> Mask -> Mask
forall a. Num a => a -> a -> a
+ Mask -> Mask
lowestBitSet Mask
bm
          find (Bin Mask
_ Mask
_ Word64Set
l' Word64Set
_) = Word64Set -> Mask
find Word64Set
l'
          find Word64Set
Nil            = [Char] -> Mask
forall a. HasCallStack => [Char] -> a
error [Char]
"findMin Nil"

-- | \(O(\min(n,W))\). The maximal element of a set.
findMax :: Word64Set -> Key
findMax :: Word64Set -> Mask
findMax Word64Set
Nil = [Char] -> Mask
forall a. HasCallStack => [Char] -> a
error [Char]
"findMax: empty set has no maximal element"
findMax (Tip Mask
kx Mask
bm) = Mask
kx Mask -> Mask -> Mask
forall a. Num a => a -> a -> a
+ Mask -> Mask
highestBitSet Mask
bm
findMax (Bin Mask
_ Mask
m Word64Set
l Word64Set
r)
  |   Mask
m Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
< Mask
0   = Word64Set -> Mask
find Word64Set
l
  | Bool
otherwise = Word64Set -> Mask
find Word64Set
r
    where find :: Word64Set -> Mask
find (Tip Mask
kx Mask
bm) = Mask
kx Mask -> Mask -> Mask
forall a. Num a => a -> a -> a
+ Mask -> Mask
highestBitSet Mask
bm
          find (Bin Mask
_ Mask
_ Word64Set
_ Word64Set
r') = Word64Set -> Mask
find Word64Set
r'
          find Word64Set
Nil            = [Char] -> Mask
forall a. HasCallStack => [Char] -> a
error [Char]
"findMax Nil"


-- | \(O(\min(n,W))\). Delete the minimal element. Returns an empty set if the set is empty.
--
-- Note that this is a change of behaviour for consistency with 'Data.Set.Set' &#8211;
-- versions prior to 0.5 threw an error if the 'Word64Set' was already empty.
deleteMin :: Word64Set -> Word64Set
deleteMin :: Word64Set -> Word64Set
deleteMin = Word64Set
-> ((Mask, Word64Set) -> Word64Set)
-> Maybe (Mask, Word64Set)
-> Word64Set
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Word64Set
Nil (Mask, Word64Set) -> Word64Set
forall a b. (a, b) -> b
snd (Maybe (Mask, Word64Set) -> Word64Set)
-> (Word64Set -> Maybe (Mask, Word64Set)) -> Word64Set -> Word64Set
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word64Set -> Maybe (Mask, Word64Set)
minView

-- | \(O(\min(n,W))\). Delete the maximal element. Returns an empty set if the set is empty.
--
-- Note that this is a change of behaviour for consistency with 'Data.Set.Set' &#8211;
-- versions prior to 0.5 threw an error if the 'Word64Set' was already empty.
deleteMax :: Word64Set -> Word64Set
deleteMax :: Word64Set -> Word64Set
deleteMax = Word64Set
-> ((Mask, Word64Set) -> Word64Set)
-> Maybe (Mask, Word64Set)
-> Word64Set
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Word64Set
Nil (Mask, Word64Set) -> Word64Set
forall a b. (a, b) -> b
snd (Maybe (Mask, Word64Set) -> Word64Set)
-> (Word64Set -> Maybe (Mask, Word64Set)) -> Word64Set -> Word64Set
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word64Set -> Maybe (Mask, Word64Set)
maxView

{----------------------------------------------------------------------
  Map
----------------------------------------------------------------------}

-- | \(O(n \min(n,W))\).
-- @'map' f s@ is the set obtained by applying @f@ to each element of @s@.
--
-- It's worth noting that the size of the result may be smaller if,
-- for some @(x,y)@, @x \/= y && f x == f y@

map :: (Key -> Key) -> Word64Set -> Word64Set
map :: (Mask -> Mask) -> Word64Set -> Word64Set
map Mask -> Mask
f = [Mask] -> Word64Set
fromList ([Mask] -> Word64Set)
-> (Word64Set -> [Mask]) -> Word64Set -> Word64Set
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Mask -> Mask) -> [Mask] -> [Mask]
forall a b. (a -> b) -> [a] -> [b]
List.map Mask -> Mask
f ([Mask] -> [Mask]) -> (Word64Set -> [Mask]) -> Word64Set -> [Mask]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word64Set -> [Mask]
toList

-- | \(O(n)\). The
--
-- @'mapMonotonic' f s == 'map' f s@, but works only when @f@ is strictly increasing.
-- /The precondition is not checked./
-- Semi-formally, we have:
--
-- > and [x < y ==> f x < f y | x <- ls, y <- ls]
-- >                     ==> mapMonotonic f s == map f s
-- >     where ls = toList s
--
-- @since 0.6.3.1

-- Note that for now the test is insufficient to support any fancier implementation.
mapMonotonic :: (Key -> Key) -> Word64Set -> Word64Set
mapMonotonic :: (Mask -> Mask) -> Word64Set -> Word64Set
mapMonotonic Mask -> Mask
f = [Mask] -> Word64Set
fromDistinctAscList ([Mask] -> Word64Set)
-> (Word64Set -> [Mask]) -> Word64Set -> Word64Set
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Mask -> Mask) -> [Mask] -> [Mask]
forall a b. (a -> b) -> [a] -> [b]
List.map Mask -> Mask
f ([Mask] -> [Mask]) -> (Word64Set -> [Mask]) -> Word64Set -> [Mask]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word64Set -> [Mask]
toAscList


{--------------------------------------------------------------------
  Fold
--------------------------------------------------------------------}
-- | \(O(n)\). Fold the elements in the set using the given right-associative
-- binary operator. This function is an equivalent of 'foldr' and is present
-- for compatibility only.
--
-- /Please note that fold will be deprecated in the future and removed./
fold :: (Key -> b -> b) -> b -> Word64Set -> b
fold :: forall b. (Mask -> b -> b) -> b -> Word64Set -> b
fold = (Mask -> b -> b) -> b -> Word64Set -> b
forall b. (Mask -> b -> b) -> b -> Word64Set -> b
foldr
{-# INLINE fold #-}

-- | \(O(n)\). Fold the elements in the set using the given right-associative
-- binary operator, such that @'foldr' f z == 'Prelude.foldr' f z . 'toAscList'@.
--
-- For example,
--
-- > toAscList set = foldr (:) [] set
foldr :: (Key -> b -> b) -> b -> Word64Set -> b
foldr :: forall b. (Mask -> b -> b) -> b -> Word64Set -> b
foldr Mask -> b -> b
f b
z = \Word64Set
t ->      -- Use lambda t to be inlinable with two arguments only.
  case Word64Set
t of Bin Mask
_ Mask
m Word64Set
l Word64Set
r | Mask
m Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
< Mask
0 -> b -> Word64Set -> b
go (b -> Word64Set -> b
go b
z Word64Set
l) Word64Set
r -- put negative numbers before
                        | Bool
otherwise -> b -> Word64Set -> b
go (b -> Word64Set -> b
go b
z Word64Set
r) Word64Set
l
            Word64Set
_ -> b -> Word64Set -> b
go b
z Word64Set
t
  where
    go :: b -> Word64Set -> b
go b
z' Word64Set
Nil           = b
z'
    go b
z' (Tip Mask
kx Mask
bm)   = Mask -> (Mask -> b -> b) -> b -> Mask -> b
forall a. Mask -> (Mask -> a -> a) -> a -> Mask -> a
foldrBits Mask
kx Mask -> b -> b
f b
z' Mask
bm
    go b
z' (Bin Mask
_ Mask
_ Word64Set
l Word64Set
r) = b -> Word64Set -> b
go (b -> Word64Set -> b
go b
z' Word64Set
r) Word64Set
l
{-# INLINE foldr #-}

-- | \(O(n)\). A strict version of 'foldr'. Each application of the operator is
-- evaluated before using the result in the next application. This
-- function is strict in the starting value.
foldr' :: (Key -> b -> b) -> b -> Word64Set -> b
foldr' :: forall b. (Mask -> b -> b) -> b -> Word64Set -> b
foldr' Mask -> b -> b
f b
z = \Word64Set
t ->      -- Use lambda t to be inlinable with two arguments only.
  case Word64Set
t of Bin Mask
_ Mask
m Word64Set
l Word64Set
r | Mask
m Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
< Mask
0 -> b -> Word64Set -> b
go (b -> Word64Set -> b
go b
z Word64Set
l) Word64Set
r -- put negative numbers before
                        | Bool
otherwise -> b -> Word64Set -> b
go (b -> Word64Set -> b
go b
z Word64Set
r) Word64Set
l
            Word64Set
_ -> b -> Word64Set -> b
go b
z Word64Set
t
  where
    go :: b -> Word64Set -> b
go !b
z' Word64Set
Nil           = b
z'
    go b
z' (Tip Mask
kx Mask
bm)   = Mask -> (Mask -> b -> b) -> b -> Mask -> b
forall a. Mask -> (Mask -> a -> a) -> a -> Mask -> a
foldr'Bits Mask
kx Mask -> b -> b
f b
z' Mask
bm
    go b
z' (Bin Mask
_ Mask
_ Word64Set
l Word64Set
r) = b -> Word64Set -> b
go (b -> Word64Set -> b
go b
z' Word64Set
r) Word64Set
l
{-# INLINE foldr' #-}

-- | \(O(n)\). Fold the elements in the set using the given left-associative
-- binary operator, such that @'foldl' f z == 'Prelude.foldl' f z . 'toAscList'@.
--
-- For example,
--
-- > toDescList set = foldl (flip (:)) [] set
foldl :: (a -> Key -> a) -> a -> Word64Set -> a
foldl :: forall a. (a -> Mask -> a) -> a -> Word64Set -> a
foldl a -> Mask -> a
f a
z = \Word64Set
t ->      -- Use lambda t to be inlinable with two arguments only.
  case Word64Set
t of Bin Mask
_ Mask
m Word64Set
l Word64Set
r | Mask
m Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
< Mask
0 -> a -> Word64Set -> a
go (a -> Word64Set -> a
go a
z Word64Set
r) Word64Set
l -- put negative numbers before
                        | Bool
otherwise -> a -> Word64Set -> a
go (a -> Word64Set -> a
go a
z Word64Set
l) Word64Set
r
            Word64Set
_ -> a -> Word64Set -> a
go a
z Word64Set
t
  where
    go :: a -> Word64Set -> a
go a
z' Word64Set
Nil           = a
z'
    go a
z' (Tip Mask
kx Mask
bm)   = Mask -> (a -> Mask -> a) -> a -> Mask -> a
forall a. Mask -> (a -> Mask -> a) -> a -> Mask -> a
foldlBits Mask
kx a -> Mask -> a
f a
z' Mask
bm
    go a
z' (Bin Mask
_ Mask
_ Word64Set
l Word64Set
r) = a -> Word64Set -> a
go (a -> Word64Set -> a
go a
z' Word64Set
l) Word64Set
r
{-# INLINE foldl #-}

-- | \(O(n)\). A strict version of 'foldl'. Each application of the operator is
-- evaluated before using the result in the next application. This
-- function is strict in the starting value.
foldl' :: (a -> Key -> a) -> a -> Word64Set -> a
foldl' :: forall a. (a -> Mask -> a) -> a -> Word64Set -> a
foldl' a -> Mask -> a
f a
z = \Word64Set
t ->      -- Use lambda t to be inlinable with two arguments only.
  case Word64Set
t of Bin Mask
_ Mask
m Word64Set
l Word64Set
r | Mask
m Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
< Mask
0 -> a -> Word64Set -> a
go (a -> Word64Set -> a
go a
z Word64Set
r) Word64Set
l -- put negative numbers before
                        | Bool
otherwise -> a -> Word64Set -> a
go (a -> Word64Set -> a
go a
z Word64Set
l) Word64Set
r
            Word64Set
_ -> a -> Word64Set -> a
go a
z Word64Set
t
  where
    go :: a -> Word64Set -> a
go !a
z' Word64Set
Nil           = a
z'
    go a
z' (Tip Mask
kx Mask
bm)   = Mask -> (a -> Mask -> a) -> a -> Mask -> a
forall a. Mask -> (a -> Mask -> a) -> a -> Mask -> a
foldl'Bits Mask
kx a -> Mask -> a
f a
z' Mask
bm
    go a
z' (Bin Mask
_ Mask
_ Word64Set
l Word64Set
r) = a -> Word64Set -> a
go (a -> Word64Set -> a
go a
z' Word64Set
l) Word64Set
r
{-# INLINE foldl' #-}

{--------------------------------------------------------------------
  List variations
--------------------------------------------------------------------}
-- | \(O(n)\). An alias of 'toAscList'. The elements of a set in ascending order.
-- Subject to list fusion.
elems :: Word64Set -> [Key]
elems :: Word64Set -> [Mask]
elems
  = Word64Set -> [Mask]
toAscList

{--------------------------------------------------------------------
  Lists
--------------------------------------------------------------------}

#ifdef __GLASGOW_HASKELL__
-- | @since 0.5.6.2
instance GHC.Exts.IsList Word64Set where
  type Item Word64Set = Key
  fromList :: [Item Word64Set] -> Word64Set
fromList = [Mask] -> Word64Set
[Item Word64Set] -> Word64Set
fromList
  toList :: Word64Set -> [Item Word64Set]
toList   = Word64Set -> [Mask]
Word64Set -> [Item Word64Set]
toList
#endif

-- | \(O(n)\). Convert the set to a list of elements. Subject to list fusion.
toList :: Word64Set -> [Key]
toList :: Word64Set -> [Mask]
toList
  = Word64Set -> [Mask]
toAscList

-- | \(O(n)\). Convert the set to an ascending list of elements. Subject to list
-- fusion.
toAscList :: Word64Set -> [Key]
toAscList :: Word64Set -> [Mask]
toAscList = (Mask -> [Mask] -> [Mask]) -> [Mask] -> Word64Set -> [Mask]
forall b. (Mask -> b -> b) -> b -> Word64Set -> b
foldr (:) []

-- | \(O(n)\). Convert the set to a descending list of elements. Subject to list
-- fusion.
toDescList :: Word64Set -> [Key]
toDescList :: Word64Set -> [Mask]
toDescList = ([Mask] -> Mask -> [Mask]) -> [Mask] -> Word64Set -> [Mask]
forall a. (a -> Mask -> a) -> a -> Word64Set -> a
foldl ((Mask -> [Mask] -> [Mask]) -> [Mask] -> Mask -> [Mask]
forall a b c. (a -> b -> c) -> b -> a -> c
flip (:)) []

-- List fusion for the list generating functions.
#if __GLASGOW_HASKELL__
-- The foldrFB and foldlFB are foldr and foldl equivalents, used for list fusion.
-- They are important to convert unfused to{Asc,Desc}List back, see mapFB in prelude.
foldrFB :: (Key -> b -> b) -> b -> Word64Set -> b
foldrFB :: forall b. (Mask -> b -> b) -> b -> Word64Set -> b
foldrFB = (Mask -> b -> b) -> b -> Word64Set -> b
forall b. (Mask -> b -> b) -> b -> Word64Set -> b
foldr
{-# INLINE[0] foldrFB #-}
foldlFB :: (a -> Key -> a) -> a -> Word64Set -> a
foldlFB :: forall a. (a -> Mask -> a) -> a -> Word64Set -> a
foldlFB = (a -> Mask -> a) -> a -> Word64Set -> a
forall a. (a -> Mask -> a) -> a -> Word64Set -> a
foldl
{-# INLINE[0] foldlFB #-}

-- Inline elems and toList, so that we need to fuse only toAscList.
{-# INLINE elems #-}
{-# INLINE toList #-}

-- The fusion is enabled up to phase 2 included. If it does not succeed,
-- convert in phase 1 the expanded to{Asc,Desc}List calls back to
-- to{Asc,Desc}List.  In phase 0, we inline fold{lr}FB (which were used in
-- a list fusion, otherwise it would go away in phase 1), and let compiler do
-- whatever it wants with to{Asc,Desc}List -- it was forbidden to inline it
-- before phase 0, otherwise the fusion rules would not fire at all.
{-# NOINLINE[0] toAscList #-}
{-# NOINLINE[0] toDescList #-}
{-# RULES "Word64Set.toAscList" [~1] forall s . toAscList s = GHC.Exts.build (\c n -> foldrFB c n s) #-}
{-# RULES "Word64Set.toAscListBack" [1] foldrFB (:) [] = toAscList #-}
{-# RULES "Word64Set.toDescList" [~1] forall s . toDescList s = GHC.Exts.build (\c n -> foldlFB (\xs x -> c x xs) n s) #-}
{-# RULES "Word64Set.toDescListBack" [1] foldlFB (\xs x -> x : xs) [] = toDescList #-}
#endif


-- | \(O(n \min(n,W))\). Create a set from a list of integers.
fromList :: [Key] -> Word64Set
fromList :: [Mask] -> Word64Set
fromList [Mask]
xs
  = (Word64Set -> Mask -> Word64Set)
-> Word64Set -> [Mask] -> Word64Set
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
Foldable.foldl' Word64Set -> Mask -> Word64Set
ins Word64Set
empty [Mask]
xs
  where
    ins :: Word64Set -> Mask -> Word64Set
ins Word64Set
t Mask
x  = Mask -> Word64Set -> Word64Set
insert Mask
x Word64Set
t

-- | \(O(n)\). Build a set from an ascending list of elements.
-- /The precondition (input list is ascending) is not checked./
fromAscList :: [Key] -> Word64Set
fromAscList :: [Mask] -> Word64Set
fromAscList = [Mask] -> Word64Set
fromMonoList
{-# NOINLINE fromAscList #-}

-- | \(O(n)\). Build a set from an ascending list of distinct elements.
-- /The precondition (input list is strictly ascending) is not checked./
fromDistinctAscList :: [Key] -> Word64Set
fromDistinctAscList :: [Mask] -> Word64Set
fromDistinctAscList = [Mask] -> Word64Set
fromAscList
{-# INLINE fromDistinctAscList #-}

-- | \(O(n)\). Build a set from a monotonic list of elements.
--
-- The precise conditions under which this function works are subtle:
-- For any branch mask, keys with the same prefix w.r.t. the branch
-- mask must occur consecutively in the list.
fromMonoList :: [Key] -> Word64Set
fromMonoList :: [Mask] -> Word64Set
fromMonoList []         = Word64Set
Nil
fromMonoList (Mask
kx : [Mask]
zs1) = Mask -> Mask -> [Mask] -> Word64Set
addAll' (Mask -> Mask
prefixOf Mask
kx) (Mask -> Mask
bitmapOf Mask
kx) [Mask]
zs1
  where
    -- `addAll'` collects all keys with the prefix `px` into a single
    -- bitmap, and then proceeds with `addAll`.
    addAll' :: Mask -> Mask -> [Mask] -> Word64Set
addAll' !Mask
px !Mask
bm []
        = Mask -> Mask -> Word64Set
Tip Mask
px Mask
bm
    addAll' !Mask
px !Mask
bm (Mask
ky : [Mask]
zs)
        | Mask
px Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
== Mask -> Mask
prefixOf Mask
ky
        = Mask -> Mask -> [Mask] -> Word64Set
addAll' Mask
px (Mask
bm Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.|. Mask -> Mask
bitmapOf Mask
ky) [Mask]
zs
        -- inlined: | otherwise = addAll px (Tip px bm) (ky : zs)
        | Mask
py <- Mask -> Mask
prefixOf Mask
ky
        , Mask
m <- Mask -> Mask -> Mask
branchMask Mask
px Mask
py
        , Inserted Word64Set
ty [Mask]
zs' <- Mask -> Mask -> Mask -> [Mask] -> Inserted
addMany' Mask
m Mask
py (Mask -> Mask
bitmapOf Mask
ky) [Mask]
zs
        = Mask -> Word64Set -> [Mask] -> Word64Set
addAll Mask
px (Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
linkWithMask Mask
m Mask
py Word64Set
ty {-px-} (Mask -> Mask -> Word64Set
Tip Mask
px Mask
bm)) [Mask]
zs'

    -- for `addAll` and `addMany`, px is /a/ prefix inside the tree `tx`
    -- `addAll` consumes the rest of the list, adding to the tree `tx`
    addAll :: Mask -> Word64Set -> [Mask] -> Word64Set
addAll !Mask
_px !Word64Set
tx []
        = Word64Set
tx
    addAll !Mask
px !Word64Set
tx (Mask
ky : [Mask]
zs)
        | Mask
py <- Mask -> Mask
prefixOf Mask
ky
        , Mask
m <- Mask -> Mask -> Mask
branchMask Mask
px Mask
py
        , Inserted Word64Set
ty [Mask]
zs' <- Mask -> Mask -> Mask -> [Mask] -> Inserted
addMany' Mask
m Mask
py (Mask -> Mask
bitmapOf Mask
ky) [Mask]
zs
        = Mask -> Word64Set -> [Mask] -> Word64Set
addAll Mask
px (Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
linkWithMask Mask
m Mask
py Word64Set
ty {-px-} Word64Set
tx) [Mask]
zs'

    -- `addMany'` is similar to `addAll'`, but proceeds with `addMany'`.
    addMany' :: Mask -> Mask -> Mask -> [Mask] -> Inserted
addMany' !Mask
_m !Mask
px !Mask
bm []
        = Word64Set -> [Mask] -> Inserted
Inserted (Mask -> Mask -> Word64Set
Tip Mask
px Mask
bm) []
    addMany' !Mask
m !Mask
px !Mask
bm zs0 :: [Mask]
zs0@(Mask
ky : [Mask]
zs)
        | Mask
px Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
== Mask -> Mask
prefixOf Mask
ky
        = Mask -> Mask -> Mask -> [Mask] -> Inserted
addMany' Mask
m Mask
px (Mask
bm Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.|. Mask -> Mask
bitmapOf Mask
ky) [Mask]
zs
        -- inlined: | otherwise = addMany m px (Tip px bm) (ky : zs)
        | Mask -> Mask -> Mask
mask Mask
px Mask
m Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
/= Mask -> Mask -> Mask
mask Mask
ky Mask
m
        = Word64Set -> [Mask] -> Inserted
Inserted (Mask -> Mask -> Word64Set
Tip (Mask -> Mask
prefixOf Mask
px) Mask
bm) [Mask]
zs0
        | Mask
py <- Mask -> Mask
prefixOf Mask
ky
        , Mask
mxy <- Mask -> Mask -> Mask
branchMask Mask
px Mask
py
        , Inserted Word64Set
ty [Mask]
zs' <- Mask -> Mask -> Mask -> [Mask] -> Inserted
addMany' Mask
mxy Mask
py (Mask -> Mask
bitmapOf Mask
ky) [Mask]
zs
        = Mask -> Mask -> Word64Set -> [Mask] -> Inserted
addMany Mask
m Mask
px (Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
linkWithMask Mask
mxy Mask
py Word64Set
ty {-px-} (Mask -> Mask -> Word64Set
Tip Mask
px Mask
bm)) [Mask]
zs'

    -- `addAll` adds to `tx` all keys whose prefix w.r.t. `m` agrees with `px`.
    addMany :: Mask -> Mask -> Word64Set -> [Mask] -> Inserted
addMany !Mask
_m !Mask
_px Word64Set
tx []
        = Word64Set -> [Mask] -> Inserted
Inserted Word64Set
tx []
    addMany !Mask
m !Mask
px Word64Set
tx zs0 :: [Mask]
zs0@(Mask
ky : [Mask]
zs)
        | Mask -> Mask -> Mask
mask Mask
px Mask
m Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
/= Mask -> Mask -> Mask
mask Mask
ky Mask
m
        = Word64Set -> [Mask] -> Inserted
Inserted Word64Set
tx [Mask]
zs0
        | Mask
py <- Mask -> Mask
prefixOf Mask
ky
        , Mask
mxy <- Mask -> Mask -> Mask
branchMask Mask
px Mask
py
        , Inserted Word64Set
ty [Mask]
zs' <- Mask -> Mask -> Mask -> [Mask] -> Inserted
addMany' Mask
mxy Mask
py (Mask -> Mask
bitmapOf Mask
ky) [Mask]
zs
        = Mask -> Mask -> Word64Set -> [Mask] -> Inserted
addMany Mask
m Mask
px (Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
linkWithMask Mask
mxy Mask
py Word64Set
ty {-px-} Word64Set
tx) [Mask]
zs'
{-# INLINE fromMonoList #-}

data Inserted = Inserted !Word64Set ![Key]

{--------------------------------------------------------------------
  Eq
--------------------------------------------------------------------}
instance Eq Word64Set where
  Word64Set
t1 == :: Word64Set -> Word64Set -> Bool
== Word64Set
t2  = Word64Set -> Word64Set -> Bool
equal Word64Set
t1 Word64Set
t2
  Word64Set
t1 /= :: Word64Set -> Word64Set -> Bool
/= Word64Set
t2  = Word64Set -> Word64Set -> Bool
nequal Word64Set
t1 Word64Set
t2

equal :: Word64Set -> Word64Set -> Bool
equal :: Word64Set -> Word64Set -> Bool
equal (Bin Mask
p1 Mask
m1 Word64Set
l1 Word64Set
r1) (Bin Mask
p2 Mask
m2 Word64Set
l2 Word64Set
r2)
  = (Mask
m1 Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
== Mask
m2) Bool -> Bool -> Bool
&& (Mask
p1 Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
== Mask
p2) Bool -> Bool -> Bool
&& (Word64Set -> Word64Set -> Bool
equal Word64Set
l1 Word64Set
l2) Bool -> Bool -> Bool
&& (Word64Set -> Word64Set -> Bool
equal Word64Set
r1 Word64Set
r2)
equal (Tip Mask
kx1 Mask
bm1) (Tip Mask
kx2 Mask
bm2)
  = Mask
kx1 Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
== Mask
kx2 Bool -> Bool -> Bool
&& Mask
bm1 Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
== Mask
bm2
equal Word64Set
Nil Word64Set
Nil = Bool
True
equal Word64Set
_   Word64Set
_   = Bool
False

nequal :: Word64Set -> Word64Set -> Bool
nequal :: Word64Set -> Word64Set -> Bool
nequal (Bin Mask
p1 Mask
m1 Word64Set
l1 Word64Set
r1) (Bin Mask
p2 Mask
m2 Word64Set
l2 Word64Set
r2)
  = (Mask
m1 Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
/= Mask
m2) Bool -> Bool -> Bool
|| (Mask
p1 Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
/= Mask
p2) Bool -> Bool -> Bool
|| (Word64Set -> Word64Set -> Bool
nequal Word64Set
l1 Word64Set
l2) Bool -> Bool -> Bool
|| (Word64Set -> Word64Set -> Bool
nequal Word64Set
r1 Word64Set
r2)
nequal (Tip Mask
kx1 Mask
bm1) (Tip Mask
kx2 Mask
bm2)
  = Mask
kx1 Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
/= Mask
kx2 Bool -> Bool -> Bool
|| Mask
bm1 Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
/= Mask
bm2
nequal Word64Set
Nil Word64Set
Nil = Bool
False
nequal Word64Set
_   Word64Set
_   = Bool
True

{--------------------------------------------------------------------
  Ord
--------------------------------------------------------------------}

instance Ord Word64Set where
    compare :: Word64Set -> Word64Set -> Ordering
compare Word64Set
s1 Word64Set
s2 = [Mask] -> [Mask] -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Word64Set -> [Mask]
toAscList Word64Set
s1) (Word64Set -> [Mask]
toAscList Word64Set
s2)
    -- tentative implementation. See if more efficient exists.

{--------------------------------------------------------------------
  Show
--------------------------------------------------------------------}
instance Show Word64Set where
  showsPrec :: Int -> Word64Set -> ShowS
showsPrec Int
p Word64Set
xs = Bool -> ShowS -> ShowS
showParen (Int
p Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
10) (ShowS -> ShowS) -> ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$
    [Char] -> ShowS
showString [Char]
"fromList " ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Mask] -> ShowS
forall a. Show a => a -> ShowS
shows (Word64Set -> [Mask]
toList Word64Set
xs)

{--------------------------------------------------------------------
  Read
--------------------------------------------------------------------}
instance Read Word64Set where
#ifdef __GLASGOW_HASKELL__
  readPrec :: ReadPrec Word64Set
readPrec = ReadPrec Word64Set -> ReadPrec Word64Set
forall a. ReadPrec a -> ReadPrec a
parens (ReadPrec Word64Set -> ReadPrec Word64Set)
-> ReadPrec Word64Set -> ReadPrec Word64Set
forall a b. (a -> b) -> a -> b
$ Int -> ReadPrec Word64Set -> ReadPrec Word64Set
forall a. Int -> ReadPrec a -> ReadPrec a
prec Int
10 (ReadPrec Word64Set -> ReadPrec Word64Set)
-> ReadPrec Word64Set -> ReadPrec Word64Set
forall a b. (a -> b) -> a -> b
$ do
    Ident "fromList" <- ReadPrec Lexeme
lexP
    xs <- readPrec
    return (fromList xs)

  readListPrec :: ReadPrec [Word64Set]
readListPrec = ReadPrec [Word64Set]
forall a. Read a => ReadPrec [a]
readListPrecDefault
#else
  readsPrec p = readParen (p > 10) $ \ r -> do
    ("fromList",s) <- lex r
    (xs,t) <- reads s
    return (fromList xs,t)
#endif

{--------------------------------------------------------------------
  NFData
--------------------------------------------------------------------}

-- The Word64Set constructors consist only of strict fields of Ints and
-- Word64Sets, thus the default NFData instance which evaluates to whnf
-- should suffice
instance NFData Word64Set where rnf :: Word64Set -> ()
rnf Word64Set
x = Word64Set -> () -> ()
forall a b. a -> b -> b
seq Word64Set
x ()

{--------------------------------------------------------------------
  Debugging
--------------------------------------------------------------------}
-- | \(O(n \min(n,W))\). Show the tree that implements the set. The tree is shown
-- in a compressed, hanging format.
showTree :: Word64Set -> String
showTree :: Word64Set -> [Char]
showTree Word64Set
s
  = Bool -> Bool -> Word64Set -> [Char]
showTreeWith Bool
True Bool
False Word64Set
s


{- | \(O(n \min(n,W))\). The expression (@'showTreeWith' hang wide map@) shows
 the tree that implements the set. If @hang@ is
 'True', a /hanging/ tree is shown otherwise a rotated tree is shown. If
 @wide@ is 'True', an extra wide version is shown.
-}
showTreeWith :: Bool -> Bool -> Word64Set -> String
showTreeWith :: Bool -> Bool -> Word64Set -> [Char]
showTreeWith Bool
hang Bool
wide Word64Set
t
  | Bool
hang      = (Bool -> [[Char]] -> Word64Set -> ShowS
showsTreeHang Bool
wide [] Word64Set
t) [Char]
""
  | Bool
otherwise = (Bool -> [[Char]] -> [[Char]] -> Word64Set -> ShowS
showsTree Bool
wide [] [] Word64Set
t) [Char]
""

showsTree :: Bool -> [String] -> [String] -> Word64Set -> ShowS
showsTree :: Bool -> [[Char]] -> [[Char]] -> Word64Set -> ShowS
showsTree Bool
wide [[Char]]
lbars [[Char]]
rbars Word64Set
t
  = case Word64Set
t of
      Bin Mask
p Mask
m Word64Set
l Word64Set
r
          -> Bool -> [[Char]] -> [[Char]] -> Word64Set -> ShowS
showsTree Bool
wide ([[Char]] -> [[Char]]
withBar [[Char]]
rbars) ([[Char]] -> [[Char]]
withEmpty [[Char]]
rbars) Word64Set
r ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
             Bool -> [[Char]] -> ShowS
showWide Bool
wide [[Char]]
rbars ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
             [[Char]] -> ShowS
showsBars [[Char]]
lbars ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> ShowS
showString (Mask -> Mask -> [Char]
showBin Mask
p Mask
m) ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> ShowS
showString [Char]
"\n" ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
             Bool -> [[Char]] -> ShowS
showWide Bool
wide [[Char]]
lbars ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
             Bool -> [[Char]] -> [[Char]] -> Word64Set -> ShowS
showsTree Bool
wide ([[Char]] -> [[Char]]
withEmpty [[Char]]
lbars) ([[Char]] -> [[Char]]
withBar [[Char]]
lbars) Word64Set
l
      Tip Mask
kx Mask
bm
          -> [[Char]] -> ShowS
showsBars [[Char]]
lbars ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> ShowS
showString [Char]
" " ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Mask -> ShowS
forall a. Show a => a -> ShowS
shows Mask
kx ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> ShowS
showString [Char]
" + " ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
                                                Mask -> ShowS
showsBitMap Mask
bm ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> ShowS
showString [Char]
"\n"
      Word64Set
Nil -> [[Char]] -> ShowS
showsBars [[Char]]
lbars ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> ShowS
showString [Char]
"|\n"

showsTreeHang :: Bool -> [String] -> Word64Set -> ShowS
showsTreeHang :: Bool -> [[Char]] -> Word64Set -> ShowS
showsTreeHang Bool
wide [[Char]]
bars Word64Set
t
  = case Word64Set
t of
      Bin Mask
p Mask
m Word64Set
l Word64Set
r
          -> [[Char]] -> ShowS
showsBars [[Char]]
bars ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> ShowS
showString (Mask -> Mask -> [Char]
showBin Mask
p Mask
m) ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> ShowS
showString [Char]
"\n" ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
             Bool -> [[Char]] -> ShowS
showWide Bool
wide [[Char]]
bars ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
             Bool -> [[Char]] -> Word64Set -> ShowS
showsTreeHang Bool
wide ([[Char]] -> [[Char]]
withBar [[Char]]
bars) Word64Set
l ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
             Bool -> [[Char]] -> ShowS
showWide Bool
wide [[Char]]
bars ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
             Bool -> [[Char]] -> Word64Set -> ShowS
showsTreeHang Bool
wide ([[Char]] -> [[Char]]
withEmpty [[Char]]
bars) Word64Set
r
      Tip Mask
kx Mask
bm
          -> [[Char]] -> ShowS
showsBars [[Char]]
bars ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> ShowS
showString [Char]
" " ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Mask -> ShowS
forall a. Show a => a -> ShowS
shows Mask
kx ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> ShowS
showString [Char]
" + " ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
                                               Mask -> ShowS
showsBitMap Mask
bm ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> ShowS
showString [Char]
"\n"
      Word64Set
Nil -> [[Char]] -> ShowS
showsBars [[Char]]
bars ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> ShowS
showString [Char]
"|\n"

showBin :: Prefix -> Mask -> String
showBin :: Mask -> Mask -> [Char]
showBin Mask
_ Mask
_
  = [Char]
"*" -- ++ show (p,m)

showWide :: Bool -> [String] -> String -> String
showWide :: Bool -> [[Char]] -> ShowS
showWide Bool
wide [[Char]]
bars
  | Bool
wide      = [Char] -> ShowS
showString ([[Char]] -> [Char]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[Char]] -> [[Char]]
forall a. [a] -> [a]
reverse [[Char]]
bars)) ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> ShowS
showString [Char]
"|\n"
  | Bool
otherwise = ShowS
forall a. a -> a
id

showsBars :: [String] -> ShowS
showsBars :: [[Char]] -> ShowS
showsBars [] = ShowS
forall a. a -> a
id
showsBars ([Char]
_ : [[Char]]
tl) = [Char] -> ShowS
showString ([[Char]] -> [Char]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[Char]] -> [[Char]]
forall a. [a] -> [a]
reverse [[Char]]
tl)) ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> ShowS
showString [Char]
node

showsBitMap :: Word64 -> ShowS
showsBitMap :: Mask -> ShowS
showsBitMap = [Char] -> ShowS
showString ([Char] -> ShowS) -> (Mask -> [Char]) -> Mask -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Mask -> [Char]
showBitMap

showBitMap :: Word64 -> String
showBitMap :: Mask -> [Char]
showBitMap Mask
w = [Mask] -> [Char]
forall a. Show a => a -> [Char]
show ([Mask] -> [Char]) -> [Mask] -> [Char]
forall a b. (a -> b) -> a -> b
$ Mask -> (Mask -> [Mask] -> [Mask]) -> [Mask] -> Mask -> [Mask]
forall a. Mask -> (Mask -> a -> a) -> a -> Mask -> a
foldrBits Mask
0 (:) [] Mask
w

node :: String
node :: [Char]
node           = [Char]
"+--"

withBar, withEmpty :: [String] -> [String]
withBar :: [[Char]] -> [[Char]]
withBar [[Char]]
bars   = [Char]
"|  "[Char] -> [[Char]] -> [[Char]]
forall a. a -> [a] -> [a]
:[[Char]]
bars
withEmpty :: [[Char]] -> [[Char]]
withEmpty [[Char]]
bars = [Char]
"   "[Char] -> [[Char]] -> [[Char]]
forall a. a -> [a] -> [a]
:[[Char]]
bars


{--------------------------------------------------------------------
  Helpers
--------------------------------------------------------------------}
{--------------------------------------------------------------------
  Link
--------------------------------------------------------------------}
link :: Prefix -> Word64Set -> Prefix -> Word64Set -> Word64Set
link :: Mask -> Word64Set -> Mask -> Word64Set -> Word64Set
link Mask
p1 Word64Set
t1 Mask
p2 Word64Set
t2 = Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
linkWithMask (Mask -> Mask -> Mask
branchMask Mask
p1 Mask
p2) Mask
p1 Word64Set
t1 {-p2-} Word64Set
t2
{-# INLINE link #-}

-- `linkWithMask` is useful when the `branchMask` has already been computed
linkWithMask :: Mask -> Prefix -> Word64Set -> Word64Set -> Word64Set
linkWithMask :: Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
linkWithMask Mask
m Mask
p1 Word64Set
t1 {-p2-} Word64Set
t2
  | Mask -> Mask -> Bool
zero Mask
p1 Mask
m = Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
Bin Mask
p Mask
m Word64Set
t1 Word64Set
t2
  | Bool
otherwise = Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
Bin Mask
p Mask
m Word64Set
t2 Word64Set
t1
  where
    p :: Mask
p = Mask -> Mask -> Mask
mask Mask
p1 Mask
m
{-# INLINE linkWithMask #-}

{--------------------------------------------------------------------
  @bin@ assures that we never have empty trees within a tree.
--------------------------------------------------------------------}
bin :: Prefix -> Mask -> Word64Set -> Word64Set -> Word64Set
bin :: Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
bin Mask
_ Mask
_ Word64Set
l Word64Set
Nil = Word64Set
l
bin Mask
_ Mask
_ Word64Set
Nil Word64Set
r = Word64Set
r
bin Mask
p Mask
m Word64Set
l Word64Set
r   = Mask -> Mask -> Word64Set -> Word64Set -> Word64Set
Bin Mask
p Mask
m Word64Set
l Word64Set
r
{-# INLINE bin #-}

{--------------------------------------------------------------------
  @tip@ assures that we never have empty bitmaps within a tree.
--------------------------------------------------------------------}
tip :: Prefix -> BitMap -> Word64Set
tip :: Mask -> Mask -> Word64Set
tip Mask
_ Mask
0 = Word64Set
Nil
tip Mask
kx Mask
bm = Mask -> Mask -> Word64Set
Tip Mask
kx Mask
bm
{-# INLINE tip #-}


{----------------------------------------------------------------------
  Functions that generate Prefix and BitMap of a Key or a Suffix.
----------------------------------------------------------------------}

suffixBitMask :: Word64
suffixBitMask :: Mask
suffixBitMask = Int -> Mask
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Mask -> Int
forall b. FiniteBits b => b -> Int
finiteBitSize (Mask
forall a. HasCallStack => a
undefined::Word64)) Mask -> Mask -> Mask
forall a. Num a => a -> a -> a
- Mask
1
{-# INLINE suffixBitMask #-}

prefixBitMask :: Word64
prefixBitMask :: Mask
prefixBitMask = Mask -> Mask
forall a. Bits a => a -> a
complement Mask
suffixBitMask
{-# INLINE prefixBitMask #-}

prefixOf :: Word64 -> Prefix
prefixOf :: Mask -> Mask
prefixOf Mask
x = Mask
x Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask
prefixBitMask
{-# INLINE prefixOf #-}

suffixOf :: Word64 -> Word64
suffixOf :: Mask -> Mask
suffixOf Mask
x = Mask
x Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask
suffixBitMask
{-# INLINE suffixOf #-}

bitmapOfSuffix :: Word64 -> BitMap
bitmapOfSuffix :: Mask -> Mask
bitmapOfSuffix Mask
s = Mask
1 Mask -> Int -> Mask
`shiftLL` Mask -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Mask
s
{-# INLINE bitmapOfSuffix #-}

bitmapOf :: Word64 -> BitMap
bitmapOf :: Mask -> Mask
bitmapOf Mask
x = Mask -> Mask
bitmapOfSuffix (Mask -> Mask
suffixOf Mask
x)
{-# INLINE bitmapOf #-}


{--------------------------------------------------------------------
  Endian independent bit twiddling
--------------------------------------------------------------------}
-- Returns True iff the bits set in i and the Mask m are disjoint.
zero :: Word64 -> Mask -> Bool
zero :: Mask -> Mask -> Bool
zero Mask
i Mask
m
  = (Mask -> Mask
natFromInt Mask
i) Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. (Mask -> Mask
natFromInt Mask
m) Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
== Mask
0
{-# INLINE zero #-}

nomatch,match :: Word64 -> Prefix -> Mask -> Bool
nomatch :: Mask -> Mask -> Mask -> Bool
nomatch Mask
i Mask
p Mask
m
  = (Mask -> Mask -> Mask
mask Mask
i Mask
m) Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
/= Mask
p
{-# INLINE nomatch #-}

match :: Mask -> Mask -> Mask -> Bool
match Mask
i Mask
p Mask
m
  = (Mask -> Mask -> Mask
mask Mask
i Mask
m) Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
== Mask
p
{-# INLINE match #-}

-- Suppose a is largest such that 2^a divides 2*m.
-- Then mask i m is i with the low a bits zeroed out.
mask :: Word64 -> Mask -> Prefix
mask :: Mask -> Mask -> Mask
mask Mask
i Mask
m
  = Mask -> Mask -> Mask
maskW (Mask -> Mask
natFromInt Mask
i) (Mask -> Mask
natFromInt Mask
m)
{-# INLINE mask #-}

{--------------------------------------------------------------------
  Big endian operations
--------------------------------------------------------------------}
maskW :: Nat -> Nat -> Prefix
maskW :: Mask -> Mask -> Mask
maskW Mask
i Mask
m
  = Mask -> Mask
intFromNat (Mask
i Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. (Mask -> Mask
forall a. Bits a => a -> a
complement (Mask
mMask -> Mask -> Mask
forall a. Num a => a -> a -> a
-Mask
1) Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
`xor` Mask
m))
{-# INLINE maskW #-}

shorter :: Mask -> Mask -> Bool
shorter :: Mask -> Mask -> Bool
shorter Mask
m1 Mask
m2
  = (Mask -> Mask
natFromInt Mask
m1) Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
> (Mask -> Mask
natFromInt Mask
m2)
{-# INLINE shorter #-}

branchMask :: Prefix -> Prefix -> Mask
branchMask :: Mask -> Mask -> Mask
branchMask Mask
p1 Mask
p2
  = Mask -> Mask
intFromNat (Mask -> Mask
highestBitMask (Mask -> Mask
natFromInt Mask
p1 Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
`xor` Mask -> Mask
natFromInt Mask
p2))
{-# INLINE branchMask #-}

{----------------------------------------------------------------------
  To get best performance, we provide fast implementations of
  lowestBitSet, highestBitSet and fold[lr][l]Bits for GHC.
  If the intel bsf and bsr instructions ever become GHC primops,
  this code should be reimplemented using these.

  Performance of this code is crucial for folds, toList, filter, partition.

  The signatures of methods in question are placed after this comment.
----------------------------------------------------------------------}

lowestBitSet :: Nat -> Word64
highestBitSet :: Nat -> Word64
foldlBits :: Word64 -> (a -> Word64 -> a) -> a -> Nat -> a
foldl'Bits :: Word64 -> (a -> Word64 -> a) -> a -> Nat -> a
foldrBits :: Word64 -> (Word64 -> a -> a) -> a -> Nat -> a
foldr'Bits :: Word64 -> (Word64 -> a -> a) -> a -> Nat -> a
takeWhileAntitoneBits :: Word64 -> (Word64 -> Bool) -> Nat -> Nat

{-# INLINE lowestBitSet #-}
{-# INLINE highestBitSet #-}
{-# INLINE foldlBits #-}
{-# INLINE foldl'Bits #-}
{-# INLINE foldrBits #-}
{-# INLINE foldr'Bits #-}
{-# INLINE takeWhileAntitoneBits #-}

#if defined(__GLASGOW_HASKELL__)
indexOfTheOnlyBit :: Nat -> Word64
{-# INLINE indexOfTheOnlyBit #-}
indexOfTheOnlyBit :: Mask -> Mask
indexOfTheOnlyBit Mask
bitmask = Int -> Mask
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Mask) -> Int -> Mask
forall a b. (a -> b) -> a -> b
$ Mask -> Int
forall b. FiniteBits b => b -> Int
countTrailingZeros Mask
bitmask

lowestBitSet :: Mask -> Mask
lowestBitSet Mask
x = Int -> Mask
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Mask) -> Int -> Mask
forall a b. (a -> b) -> a -> b
$ Mask -> Int
forall b. FiniteBits b => b -> Int
countTrailingZeros Mask
x

highestBitSet :: Mask -> Mask
highestBitSet Mask
x = Int -> Mask
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Mask) -> Int -> Mask
forall a b. (a -> b) -> a -> b
$ Int
63 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Mask -> Int
forall b. FiniteBits b => b -> Int
countLeadingZeros Mask
x

lowestBitMask :: Nat -> Nat
lowestBitMask :: Mask -> Mask
lowestBitMask Mask
x = Mask
x Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask -> Mask
forall a. Num a => a -> a
negate Mask
x
{-# INLINE lowestBitMask #-}

-- Reverse the order of bits in the Nat.
revNat :: Nat -> Nat
revNat :: Mask -> Mask
revNat Mask
x1 = case ((Mask
x1 Mask -> Int -> Mask
`shiftRL` Int
1) Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask
0x5555555555555555) Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.|. ((Mask
x1 Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask
0x5555555555555555) Mask -> Int -> Mask
`shiftLL` Int
1) of
              Mask
x2 -> case ((Mask
x2 Mask -> Int -> Mask
`shiftRL` Int
2) Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask
0x3333333333333333) Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.|. ((Mask
x2 Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask
0x3333333333333333) Mask -> Int -> Mask
`shiftLL` Int
2) of
                 Mask
x3 -> case ((Mask
x3 Mask -> Int -> Mask
`shiftRL` Int
4) Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask
0x0F0F0F0F0F0F0F0F) Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.|. ((Mask
x3 Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask
0x0F0F0F0F0F0F0F0F) Mask -> Int -> Mask
`shiftLL` Int
4) of
                   Mask
x4 -> case ((Mask
x4 Mask -> Int -> Mask
`shiftRL` Int
8) Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask
0x00FF00FF00FF00FF) Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.|. ((Mask
x4 Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask
0x00FF00FF00FF00FF) Mask -> Int -> Mask
`shiftLL` Int
8) of
                     Mask
x5 -> case ((Mask
x5 Mask -> Int -> Mask
`shiftRL` Int
16) Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask
0x0000FFFF0000FFFF) Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.|. ((Mask
x5 Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask
0x0000FFFF0000FFFF) Mask -> Int -> Mask
`shiftLL` Int
16) of
                       Mask
x6 -> ( Mask
x6 Mask -> Int -> Mask
`shiftRL` Int
32             ) Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.|. ( Mask
x6               Mask -> Int -> Mask
`shiftLL` Int
32);

foldlBits :: forall a. Mask -> (a -> Mask -> a) -> a -> Mask -> a
foldlBits Mask
prefix a -> Mask -> a
f a
z Mask
bitmap = Mask -> a -> a
go Mask
bitmap a
z
  where go :: Mask -> a -> a
go Mask
0 a
acc = a
acc
        go Mask
bm a
acc = Mask -> a -> a
go (Mask
bm Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
`xor` Mask
bitmask) ((a -> Mask -> a
f a
acc) (Mask -> a) -> Mask -> a
forall a b. (a -> b) -> a -> b
$! (Mask
prefixMask -> Mask -> Mask
forall a. Num a => a -> a -> a
+Mask
bi))
          where
            !bitmask :: Mask
bitmask = Mask -> Mask
lowestBitMask Mask
bm
            !bi :: Mask
bi = Mask -> Mask
indexOfTheOnlyBit Mask
bitmask

foldl'Bits :: forall a. Mask -> (a -> Mask -> a) -> a -> Mask -> a
foldl'Bits Mask
prefix a -> Mask -> a
f a
z Mask
bitmap = Mask -> a -> a
go Mask
bitmap a
z
  where go :: Mask -> a -> a
go Mask
0 a
acc = a
acc
        go Mask
bm !a
acc = Mask -> a -> a
go (Mask
bm Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
`xor` Mask
bitmask) ((a -> Mask -> a
f a
acc) (Mask -> a) -> Mask -> a
forall a b. (a -> b) -> a -> b
$! (Mask
prefixMask -> Mask -> Mask
forall a. Num a => a -> a -> a
+Mask
bi))
          where !bitmask :: Mask
bitmask = Mask -> Mask
lowestBitMask Mask
bm
                !bi :: Mask
bi = Mask -> Mask
indexOfTheOnlyBit Mask
bitmask

foldrBits :: forall a. Mask -> (Mask -> a -> a) -> a -> Mask -> a
foldrBits Mask
prefix Mask -> a -> a
f a
z Mask
bitmap = Mask -> a -> a
go (Mask -> Mask
revNat Mask
bitmap) a
z
  where go :: Mask -> a -> a
go Mask
0 a
acc = a
acc
        go Mask
bm a
acc = Mask -> a -> a
go (Mask
bm Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
`xor` Mask
bitmask) ((Mask -> a -> a
f (Mask -> a -> a) -> Mask -> a -> a
forall a b. (a -> b) -> a -> b
$! (Mask
prefixMask -> Mask -> Mask
forall a. Num a => a -> a -> a
+Mask
63Mask -> Mask -> Mask
forall a. Num a => a -> a -> a
-Mask
bi)) a
acc)
          where !bitmask :: Mask
bitmask = Mask -> Mask
lowestBitMask Mask
bm
                !bi :: Mask
bi = Mask -> Mask
indexOfTheOnlyBit Mask
bitmask


foldr'Bits :: forall a. Mask -> (Mask -> a -> a) -> a -> Mask -> a
foldr'Bits Mask
prefix Mask -> a -> a
f a
z Mask
bitmap = Mask -> a -> a
go (Mask -> Mask
revNat Mask
bitmap) a
z
  where go :: Mask -> a -> a
go Mask
0 a
acc = a
acc
        go Mask
bm !a
acc = Mask -> a -> a
go (Mask
bm Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
`xor` Mask
bitmask) ((Mask -> a -> a
f (Mask -> a -> a) -> Mask -> a -> a
forall a b. (a -> b) -> a -> b
$! (Mask
prefixMask -> Mask -> Mask
forall a. Num a => a -> a -> a
+Mask
63Mask -> Mask -> Mask
forall a. Num a => a -> a -> a
-Mask
bi)) a
acc)
          where !bitmask :: Mask
bitmask = Mask -> Mask
lowestBitMask Mask
bm
                !bi :: Mask
bi = Mask -> Mask
indexOfTheOnlyBit Mask
bitmask

takeWhileAntitoneBits :: Mask -> (Mask -> Bool) -> Mask -> Mask
takeWhileAntitoneBits Mask
prefix Mask -> Bool
predicate Mask
bitmap =
  -- Binary search for the first index where the predicate returns false, but skip a predicate
  -- call if the high half of the current range is empty. This ensures
  -- min (log2 64 + 1 = 7) (popcount bitmap) predicate calls.
  let next :: Int -> Mask -> (Mask, Int) -> (Mask, Int)
next Int
d Mask
h (Mask
n',Int
b') =
        if Mask
n' Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask
h Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
/= Mask
0 Bool -> Bool -> Bool
&& (Mask -> Bool
predicate (Mask -> Bool) -> Mask -> Bool
forall a b. (a -> b) -> a -> b
$! Mask
prefix Mask -> Mask -> Mask
forall a. Num a => a -> a -> a
+ Int -> Mask
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
b'Int -> Int -> Int
forall a. Num a => a -> a -> a
+Int
d)) then (Mask
n' Mask -> Int -> Mask
`shiftRL` Int
d, Int
b'Int -> Int -> Int
forall a. Num a => a -> a -> a
+Int
d) else (Mask
n',Int
b')
      {-# INLINE next #-}
      (Mask
_,Int
b) = Int -> Mask -> (Mask, Int) -> (Mask, Int)
next Int
1  Mask
0x2 ((Mask, Int) -> (Mask, Int)) -> (Mask, Int) -> (Mask, Int)
forall a b. (a -> b) -> a -> b
$
              Int -> Mask -> (Mask, Int) -> (Mask, Int)
next Int
2  Mask
0xC ((Mask, Int) -> (Mask, Int)) -> (Mask, Int) -> (Mask, Int)
forall a b. (a -> b) -> a -> b
$
              Int -> Mask -> (Mask, Int) -> (Mask, Int)
next Int
4  Mask
0xF0 ((Mask, Int) -> (Mask, Int)) -> (Mask, Int) -> (Mask, Int)
forall a b. (a -> b) -> a -> b
$
              Int -> Mask -> (Mask, Int) -> (Mask, Int)
next Int
8  Mask
0xFF00 ((Mask, Int) -> (Mask, Int)) -> (Mask, Int) -> (Mask, Int)
forall a b. (a -> b) -> a -> b
$
              Int -> Mask -> (Mask, Int) -> (Mask, Int)
next Int
16 Mask
0xFFFF0000 ((Mask, Int) -> (Mask, Int)) -> (Mask, Int) -> (Mask, Int)
forall a b. (a -> b) -> a -> b
$
              Int -> Mask -> (Mask, Int) -> (Mask, Int)
next Int
32 Mask
0xFFFFFFFF00000000 ((Mask, Int) -> (Mask, Int)) -> (Mask, Int) -> (Mask, Int)
forall a b. (a -> b) -> a -> b
$
              (Mask
bitmap,Int
0)
      m :: Mask
m = if Int
b Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0 Bool -> Bool -> Bool
|| (Mask
bitmap Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask
0x1 Mask -> Mask -> Bool
forall a. Eq a => a -> a -> Bool
/= Mask
0 Bool -> Bool -> Bool
&& Mask -> Bool
predicate Mask
prefix)
          then ((Mask
2 Mask -> Int -> Mask
`shiftLL` Int
b) Mask -> Mask -> Mask
forall a. Num a => a -> a -> a
- Mask
1)
          else ((Mask
1 Mask -> Int -> Mask
`shiftLL` Int
b) Mask -> Mask -> Mask
forall a. Num a => a -> a -> a
- Mask
1)
  in Mask
bitmap Mask -> Mask -> Mask
forall a. Bits a => a -> a -> a
.&. Mask
m

#else
{----------------------------------------------------------------------
  In general case we use logarithmic implementation of
  lowestBitSet and highestBitSet, which works up to bit sizes of 64.

  Folds are linear scans.
----------------------------------------------------------------------}

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)

takeWhileAntitoneBits prefix predicate = foldl'Bits prefix f 0 -- Does not use antitone property
  where
    f acc bi | predicate bi = acc .|. bitmapOf bi
             | otherwise    = acc

#endif


{--------------------------------------------------------------------
  Utilities
--------------------------------------------------------------------}

-- | \(O(1)\).  Decompose a set into pieces based on the structure of the underlying
-- tree.  This function is useful for consuming a set in parallel.
--
-- No guarantee is made as to the sizes of the pieces; an internal, but
-- deterministic process determines this.  However, it is guaranteed that the
-- pieces returned will be in ascending order (all elements in the first submap
-- less than all elements in the second, and so on).
--
-- Examples:
--
-- > splitRoot (fromList [1..120]) == [fromList [1..63],fromList [64..120]]
-- > splitRoot empty == []
--
--  Note that the current implementation does not return more than two subsets,
--  but you should not depend on this behaviour because it can change in the
--  future without notice. Also, the current version does not continue
--  splitting all the way to individual singleton sets -- it stops at some
--  point.
splitRoot :: Word64Set -> [Word64Set]
splitRoot :: Word64Set -> [Word64Set]
splitRoot Word64Set
Nil = []
-- NOTE: we don't currently split below Tip, but we could.
splitRoot x :: Word64Set
x@(Tip Mask
_ Mask
_) = [Word64Set
x]
splitRoot (Bin Mask
_ Mask
m Word64Set
l Word64Set
r) | Mask
m Mask -> Mask -> Bool
forall a. Ord a => a -> a -> Bool
< Mask
0 = [Word64Set
r, Word64Set
l]
                        | Bool
otherwise = [Word64Set
l, Word64Set
r]
{-# INLINE splitRoot #-}