{-# LANGUAGE Strict #-}
module Effectful.Internal.Utils.Word64Map
( Word64Map
, empty
, lookup
, insert
, delete
, updateLookupWithKey
) where
import Data.Bits
import Data.Word
import Prelude hiding (lookup)
data Word64Map a
= Bin Prefix (Word64Map a) (Word64Map a)
| Tip Word64 a
| Nil
newtype Prefix = Prefix Word64
unPrefix :: Prefix -> Word64
unPrefix :: Prefix -> Word64
unPrefix (Prefix Word64
p) = Word64
p
empty :: Word64Map a
empty :: forall a. Word64Map a
empty = Word64Map a
forall a. Word64Map a
Nil
lookup :: Word64 -> Word64Map a -> Maybe a
lookup :: forall a. Word64 -> Word64Map a -> Maybe a
lookup Word64
k = Word64Map a -> Maybe a
go
where
go :: Word64Map a -> Maybe a
go (Bin Prefix
p Word64Map a
l Word64Map a
r) | Word64 -> Prefix -> Bool
left Word64
k Prefix
p = Word64Map a -> Maybe a
go Word64Map a
l
| Bool
otherwise = Word64Map a -> Maybe a
go Word64Map a
r
go (Tip Word64
kx a
x) | Word64
k Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
kx = a -> Maybe a
forall a. a -> Maybe a
Just a
x
| Bool
otherwise = Maybe a
forall a. Maybe a
Nothing
go Word64Map a
Nil = Maybe a
forall a. Maybe a
Nothing
insert :: Word64 -> a -> Word64Map a -> Word64Map a
insert :: forall a. Word64 -> a -> Word64Map a -> Word64Map a
insert Word64
k a
x = Word64Map a -> Word64Map a
go
where
go :: Word64Map a -> Word64Map a
go t :: Word64Map a
t@(Bin Prefix
p Word64Map a
l Word64Map a
r)
| Word64 -> Prefix -> Bool
nomatch Word64
k Prefix
p = Word64 -> Word64Map a -> Prefix -> Word64Map a -> Word64Map a
forall a.
Word64 -> Word64Map a -> Prefix -> Word64Map a -> Word64Map a
linkKey Word64
k (Word64 -> a -> Word64Map a
forall a. Word64 -> a -> Word64Map a
Tip Word64
k a
x) Prefix
p Word64Map a
t
| Word64 -> Prefix -> Bool
left Word64
k Prefix
p = Prefix -> Word64Map a -> Word64Map a -> Word64Map a
forall a. Prefix -> Word64Map a -> Word64Map a -> Word64Map a
Bin Prefix
p (Word64Map a -> Word64Map a
go Word64Map a
l) Word64Map a
r
| Bool
otherwise = Prefix -> Word64Map a -> Word64Map a -> Word64Map a
forall a. Prefix -> Word64Map a -> Word64Map a -> Word64Map a
Bin Prefix
p Word64Map a
l (Word64Map a -> Word64Map a
go Word64Map a
r)
go t :: Word64Map a
t@(Tip Word64
ky a
_)
| Word64
k Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
ky = Word64 -> a -> Word64Map a
forall a. Word64 -> a -> Word64Map a
Tip Word64
k a
x
| Bool
otherwise = Word64 -> Word64Map a -> Word64 -> Word64Map a -> Word64Map a
forall a.
Word64 -> Word64Map a -> Word64 -> Word64Map a -> Word64Map a
link Word64
k (Word64 -> a -> Word64Map a
forall a. Word64 -> a -> Word64Map a
Tip Word64
k a
x) Word64
ky Word64Map a
t
go Word64Map a
Nil = Word64 -> a -> Word64Map a
forall a. Word64 -> a -> Word64Map a
Tip Word64
k a
x
delete :: Word64 -> Word64Map a -> Word64Map a
delete :: forall a. Word64 -> Word64Map a -> Word64Map a
delete Word64
k = Word64Map a -> Word64Map a
go
where
go :: Word64Map a -> Word64Map a
go t :: Word64Map a
t@(Bin Prefix
p Word64Map a
l Word64Map a
r)
| Word64 -> Prefix -> Bool
nomatch Word64
k Prefix
p = Word64Map a
t
| Word64 -> Prefix -> Bool
left Word64
k Prefix
p = Prefix -> Word64Map a -> Word64Map a -> Word64Map a
forall a. Prefix -> Word64Map a -> Word64Map a -> Word64Map a
binCheckLeft Prefix
p (Word64Map a -> Word64Map a
go Word64Map a
l) Word64Map a
r
| Bool
otherwise = Prefix -> Word64Map a -> Word64Map a -> Word64Map a
forall a. Prefix -> Word64Map a -> Word64Map a -> Word64Map a
binCheckRight Prefix
p Word64Map a
l (Word64Map a -> Word64Map a
go Word64Map a
r)
go t :: Word64Map a
t@(Tip Word64
ky a
_)
| Word64
k Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
ky = Word64Map a
forall a. Word64Map a
Nil
| Bool
otherwise = Word64Map a
t
go Word64Map a
Nil = Word64Map a
forall a. Word64Map a
Nil
updateLookupWithKey
:: (Word64 -> a -> Maybe a)
-> Word64
-> Word64Map a
-> (Maybe a, Word64Map a)
updateLookupWithKey :: forall a.
(Word64 -> a -> Maybe a)
-> Word64 -> Word64Map a -> (Maybe a, Word64Map a)
updateLookupWithKey Word64 -> a -> Maybe a
f Word64
k = Word64Map a -> (Maybe a, Word64Map a)
go
where
go :: Word64Map a -> (Maybe a, Word64Map a)
go t :: Word64Map a
t@(Bin Prefix
p Word64Map a
l Word64Map a
r)
| Word64 -> Prefix -> Bool
nomatch Word64
k Prefix
p = (Maybe a
forall a. Maybe a
Nothing, Word64Map a
t)
| Word64 -> Prefix -> Bool
left Word64
k Prefix
p = let (Maybe a
found, Word64Map a
l') = Word64Map a -> (Maybe a, Word64Map a)
go Word64Map a
l in (Maybe a
found, Prefix -> Word64Map a -> Word64Map a -> Word64Map a
forall a. Prefix -> Word64Map a -> Word64Map a -> Word64Map a
binCheckLeft Prefix
p Word64Map a
l' Word64Map a
r)
| Bool
otherwise = let (Maybe a
found, Word64Map a
r') = Word64Map a -> (Maybe a, Word64Map a)
go Word64Map a
r in (Maybe a
found, Prefix -> Word64Map a -> Word64Map a -> Word64Map a
forall a. Prefix -> Word64Map a -> Word64Map a -> Word64Map a
binCheckRight Prefix
p Word64Map a
l Word64Map a
r')
go t :: Word64Map a
t@(Tip Word64
ky a
y)
| Word64
k Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
== Word64
ky = case Word64 -> a -> Maybe a
f Word64
ky a
y of
Just a
y' -> (a -> Maybe a
forall a. a -> Maybe a
Just a
y, Word64 -> a -> Word64Map a
forall a. Word64 -> a -> Word64Map a
Tip Word64
ky a
y')
Maybe a
Nothing -> (a -> Maybe a
forall a. a -> Maybe a
Just a
y, Word64Map a
forall a. Word64Map a
Nil)
| Bool
otherwise = (Maybe a
forall a. Maybe a
Nothing, Word64Map a
t)
go Word64Map a
Nil = (Maybe a
forall a. Maybe a
Nothing, Word64Map a
forall a. Word64Map a
Nil)
nomatch :: Word64 -> Prefix -> Bool
nomatch :: Word64 -> Prefix -> Bool
nomatch Word64
i (Prefix Word64
p) = (Word64
i Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
`xor` Word64
p) Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.&. Word64
prefixMask Word64 -> Word64 -> Bool
forall a. Eq a => a -> a -> Bool
/= Word64
0
where
prefixMask :: Word64
prefixMask = Word64
p Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
`xor` (-Word64
p)
left :: Word64 -> Prefix -> Bool
left :: Word64 -> Prefix -> Bool
left Word64
i Prefix
p = Word64
i Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
< Prefix -> Word64
unPrefix Prefix
p
linkKey :: Word64 -> Word64Map a -> Prefix -> Word64Map a -> Word64Map a
linkKey :: forall a.
Word64 -> Word64Map a -> Prefix -> Word64Map a -> Word64Map a
linkKey Word64
k1 Word64Map a
t1 Prefix
p2 Word64Map a
t2 = Word64 -> Word64Map a -> Word64 -> Word64Map a -> Word64Map a
forall a.
Word64 -> Word64Map a -> Word64 -> Word64Map a -> Word64Map a
link Word64
k1 Word64Map a
t1 (Prefix -> Word64
unPrefix Prefix
p2) Word64Map a
t2
link :: Word64 -> Word64Map a -> Word64 -> Word64Map a -> Word64Map a
link :: forall a.
Word64 -> Word64Map a -> Word64 -> Word64Map a -> Word64Map a
link Word64
k1 Word64Map a
t1 Word64
k2 Word64Map a
t2 = Word64
-> Word64 -> Word64Map a -> Word64 -> Word64Map a -> Word64Map a
forall a.
Word64
-> Word64 -> Word64Map a -> Word64 -> Word64Map a -> Word64Map a
linkWithMask (Word64 -> Word64 -> Word64
branchMask Word64
k1 Word64
k2) Word64
k1 Word64Map a
t1 Word64
k2 Word64Map a
t2
linkWithMask :: Word64 -> Word64 -> Word64Map a -> Word64 -> Word64Map a -> Word64Map a
linkWithMask :: forall a.
Word64
-> Word64 -> Word64Map a -> Word64 -> Word64Map a -> Word64Map a
linkWithMask Word64
m Word64
k1 Word64Map a
t1 Word64
k2 Word64Map a
t2
| Word64
k1 Word64 -> Word64 -> Bool
forall a. Ord a => a -> a -> Bool
< Word64
k2 = Prefix -> Word64Map a -> Word64Map a -> Word64Map a
forall a. Prefix -> Word64Map a -> Word64Map a -> Word64Map a
Bin Prefix
p Word64Map a
t1 Word64Map a
t2
| Bool
otherwise = Prefix -> Word64Map a -> Word64Map a -> Word64Map a
forall a. Prefix -> Word64Map a -> Word64Map a -> Word64Map a
Bin Prefix
p Word64Map a
t2 Word64Map a
t1
where
p :: Prefix
p = Word64 -> Prefix
Prefix (Word64 -> Word64 -> Word64
mask Word64
k1 Word64
m Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.|. Word64
m)
mask :: Word64 -> Word64 -> Word64
mask :: Word64 -> Word64 -> Word64
mask Word64
i Word64
m = Word64
i Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
.&. (Word64
m Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
`xor` (-Word64
m))
branchMask :: Word64 -> Word64 -> Word64
branchMask :: Word64 -> Word64 -> Word64
branchMask Word64
k1 Word64
k2 =
Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
unsafeShiftL Word64
1 (Word64 -> Int
forall b. FiniteBits b => b -> Int
finiteBitSize (Word64
0 :: Word64) Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Word64 -> Int
forall b. FiniteBits b => b -> Int
countLeadingZeros (Word64
k1 Word64 -> Word64 -> Word64
forall a. Bits a => a -> a -> a
`xor` Word64
k2))
binCheckLeft :: Prefix -> Word64Map a -> Word64Map a -> Word64Map a
binCheckLeft :: forall a. Prefix -> Word64Map a -> Word64Map a -> Word64Map a
binCheckLeft Prefix
_ Word64Map a
Nil Word64Map a
r = Word64Map a
r
binCheckLeft Prefix
p Word64Map a
l Word64Map a
r = Prefix -> Word64Map a -> Word64Map a -> Word64Map a
forall a. Prefix -> Word64Map a -> Word64Map a -> Word64Map a
Bin Prefix
p Word64Map a
l Word64Map a
r
binCheckRight :: Prefix -> Word64Map a -> Word64Map a -> Word64Map a
binCheckRight :: forall a. Prefix -> Word64Map a -> Word64Map a -> Word64Map a
binCheckRight Prefix
_ Word64Map a
l Word64Map a
Nil = Word64Map a
l
binCheckRight Prefix
p Word64Map a
l Word64Map a
r = Prefix -> Word64Map a -> Word64Map a -> Word64Map a
forall a. Prefix -> Word64Map a -> Word64Map a -> Word64Map a
Bin Prefix
p Word64Map a
l Word64Map a
r