{-# LANGUAGE CPP #-}
#ifdef __GLASGOW_HASKELL__
{-# LANGUAGE DeriveLift #-}
{-# LANGUAGE StandaloneDeriving #-}
#endif
module Data.IntSet.Internal.IntTreeCommons
( Key
, Prefix(..)
, nomatch
, left
, signBranch
, TreeTreeBranch(..)
, treeTreeBranch
, mask
, branchMask
, i2w
, Order(..)
) where
import Data.Bits (Bits(..), countLeadingZeros)
import Utils.Containers.Internal.BitUtil (wordSize)
#ifdef __GLASGOW_HASKELL__
import Language.Haskell.TH.Syntax (Lift)
import Language.Haskell.TH ()
#endif
type Key = Int
newtype Prefix = Prefix { Prefix -> Int
unPrefix :: Int }
deriving Prefix -> Prefix -> Bool
(Prefix -> Prefix -> Bool)
-> (Prefix -> Prefix -> Bool) -> Eq Prefix
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Prefix -> Prefix -> Bool
== :: Prefix -> Prefix -> Bool
$c/= :: Prefix -> Prefix -> Bool
/= :: Prefix -> Prefix -> Bool
Eq
#ifdef __GLASGOW_HASKELL__
deriving instance Lift Prefix
#endif
nomatch :: Int -> Prefix -> Bool
nomatch :: Int -> Prefix -> Bool
nomatch Int
i Prefix
p = (Int
i Int -> Int -> Int
forall a. Bits a => a -> a -> a
`xor` Int
px) Int -> Int -> Int
forall a. Bits a => a -> a -> a
.&. Int
prefixMask Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0
where
px :: Int
px = Prefix -> Int
unPrefix Prefix
p
prefixMask :: Int
prefixMask = Int
px Int -> Int -> Int
forall a. Bits a => a -> a -> a
`xor` (-Int
px)
{-# INLINE nomatch #-}
left :: Int -> Prefix -> Bool
left :: Int -> Prefix -> Bool
left Int
i Prefix
p = Int -> Word
i2w Int
i Word -> Word -> Bool
forall a. Ord a => a -> a -> Bool
< Int -> Word
i2w (Prefix -> Int
unPrefix Prefix
p)
{-# INLINE left #-}
data TreeTreeBranch
= ABL
| ABR
| BAL
| BAR
| EQL
| NOM
treeTreeBranch :: Prefix -> Prefix -> TreeTreeBranch
treeTreeBranch :: Prefix -> Prefix -> TreeTreeBranch
treeTreeBranch Prefix
p1 Prefix
p2 = case Word -> Word -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Word
pw1 Word
pw2 of
Ordering
LT | Word
pw2 Word -> Word -> Bool
forall a. Ord a => a -> a -> Bool
<= Word -> Word
forall {a}. (Bits a, Num a) => a -> a
greatest Word
pw1 -> TreeTreeBranch
ABR
| Word -> Word
forall {a}. (Bits a, Num a) => a -> a
smallest Word
pw2 Word -> Word -> Bool
forall a. Ord a => a -> a -> Bool
<= Word
pw1 -> TreeTreeBranch
BAL
| Bool
otherwise -> TreeTreeBranch
NOM
Ordering
GT | Word
pw1 Word -> Word -> Bool
forall a. Ord a => a -> a -> Bool
<= Word -> Word
forall {a}. (Bits a, Num a) => a -> a
greatest Word
pw2 -> TreeTreeBranch
BAR
| Word -> Word
forall {a}. (Bits a, Num a) => a -> a
smallest Word
pw1 Word -> Word -> Bool
forall a. Ord a => a -> a -> Bool
<= Word
pw2 -> TreeTreeBranch
ABL
| Bool
otherwise -> TreeTreeBranch
NOM
Ordering
EQ -> TreeTreeBranch
EQL
where
pw1 :: Word
pw1 = Int -> Word
i2w (Prefix -> Int
unPrefix Prefix
p1)
pw2 :: Word
pw2 = Int -> Word
i2w (Prefix -> Int
unPrefix Prefix
p2)
greatest :: a -> a
greatest a
pw = a
pw a -> a -> a
forall a. Bits a => a -> a -> a
.|. (a
pwa -> a -> a
forall a. Num a => a -> a -> a
-a
1)
smallest :: a -> a
smallest a
pw = a
pw a -> a -> a
forall a. Bits a => a -> a -> a
.&. (a
pwa -> a -> a
forall a. Num a => a -> a -> a
-a
1)
{-# INLINE treeTreeBranch #-}
signBranch :: Prefix -> Bool
signBranch :: Prefix -> Bool
signBranch Prefix
p = Prefix -> Int
unPrefix Prefix
p Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== (Int
forall a. Bounded a => a
minBound :: Int)
{-# INLINE signBranch #-}
mask :: Key -> Int -> Int
mask :: Int -> Int -> Int
mask Int
i Int
m = Int
i Int -> Int -> Int
forall a. Bits a => a -> a -> a
.&. ((-Int
m) Int -> Int -> Int
forall a. Bits a => a -> a -> a
`xor` Int
m)
{-# INLINE mask #-}
branchMask :: Int -> Int -> Int
branchMask :: Int -> Int -> Int
branchMask Int
p1 Int
p2 =
Int -> Int -> Int
forall a. Bits a => a -> Int -> a
unsafeShiftL Int
1 (Int
wordSize Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int -> Int
forall b. FiniteBits b => b -> Int
countLeadingZeros (Int
p1 Int -> Int -> Int
forall a. Bits a => a -> a -> a
`xor` Int
p2))
{-# INLINE branchMask #-}
i2w :: Int -> Word
i2w :: Int -> Word
i2w = Int -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral
{-# INLINE i2w #-}
data Order
= A_LT_B
| A_Prefix_B
| A_EQ_B
| B_Prefix_A
| A_GT_B