Skip to content

Commit 5662a47

Browse files
authored
Optimize indexing in arrays of length 2 (#528)
This also incorporates the switch from `A.index` to `A.index#` proposed in #538. Additionally, we remove some dead alternatives: when performing a deletion from a `BitmapIndexed` node with a single subtree, the result cannot be `Empty`. There must be at least one Leaf or Collision node left.
1 parent fb4ce18 commit 5662a47

File tree

1 file changed

+35
-35
lines changed

1 file changed

+35
-35
lines changed

Data/HashMap/Internal.hs

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,15 +1121,12 @@ deleteFromSubtree h k s t@(BitmapIndexed b ary)
11211121
in if st' `ptrEq` st
11221122
then t
11231123
else case st' of
1124-
Empty | A.length ary == 1 -> Empty
1125-
| A.length ary == 2 ->
1126-
case (i, A.index ary 0, A.index ary 1) of
1127-
(0, _, l) | isLeafOrCollision l -> l
1128-
(1, l, _) | isLeafOrCollision l -> l
1129-
_ -> bIndexed
1130-
| otherwise -> bIndexed
1131-
where
1132-
bIndexed = BitmapIndexed (b .&. complement m) (A.delete ary i)
1124+
Empty | A.length ary == 2
1125+
, (# l #) <- A.index# ary (otherOfOneOrZero i)
1126+
, isLeafOrCollision l
1127+
-> l
1128+
| otherwise
1129+
-> BitmapIndexed (b .&. complement m) (A.delete ary i)
11331130
l | isLeafOrCollision l && A.length ary == 1 -> l
11341131
_ -> BitmapIndexed b (A.update ary i st')
11351132
where m = mask h s
@@ -1149,10 +1146,9 @@ deleteFromSubtree h k s t@(Full ary) =
11491146
deleteFromSubtree h k _ t@(Collision hy v)
11501147
| h == hy = case indexOf k v of
11511148
Just i
1152-
| A.length v == 2 ->
1153-
if i == 0
1154-
then Leaf h (A.index v 1)
1155-
else Leaf h (A.index v 0)
1149+
| A.length v == 2
1150+
, (# l #) <- A.index# v (otherOfOneOrZero i)
1151+
-> Leaf h l
11561152
| otherwise -> Collision h (A.delete v i)
11571153
Nothing -> t
11581154
| otherwise = t
@@ -1172,15 +1168,12 @@ deleteKeyExists !collPos0 !h0 !k0 !m0 = go collPos0 h0 k0 m0
11721168
let !st = A.index ary i
11731169
!st' = go collPos (nextSH shiftedHash) k st
11741170
in case st' of
1175-
Empty | A.length ary == 1 -> Empty
1176-
| A.length ary == 2 ->
1177-
case (i, A.index ary 0, A.index ary 1) of
1178-
(0, _, l) | isLeafOrCollision l -> l
1179-
(1, l, _) | isLeafOrCollision l -> l
1180-
_ -> bIndexed
1181-
| otherwise -> bIndexed
1182-
where
1183-
bIndexed = BitmapIndexed (b .&. complement m) (A.delete ary i)
1171+
Empty | A.length ary == 2
1172+
, (# l #) <- A.index# ary (otherOfOneOrZero i)
1173+
, isLeafOrCollision l
1174+
-> l
1175+
| otherwise
1176+
-> BitmapIndexed (b .&. complement m) (A.delete ary i)
11841177
l | isLeafOrCollision l && A.length ary == 1 -> l
11851178
_ -> BitmapIndexed b (A.update ary i st')
11861179
where m = maskSH shiftedHash
@@ -1197,9 +1190,8 @@ deleteKeyExists !collPos0 !h0 !k0 !m0 = go collPos0 h0 k0 m0
11971190
where i = indexSH shiftedHash
11981191
go collPos _shiftedHash _k (Collision h v)
11991192
| A.length v == 2
1200-
= if collPos == 0
1201-
then Leaf h (A.index v 1)
1202-
else Leaf h (A.index v 0)
1193+
, (# l #) <- A.index# v (otherOfOneOrZero collPos)
1194+
= Leaf h l
12031195
| otherwise = Collision h (A.delete v collPos)
12041196
go !_ !_ !_ Empty = Empty -- error "Internal error: deleteKeyExists empty"
12051197
{-# NOINLINE deleteKeyExists #-}
@@ -1818,16 +1810,12 @@ difference = go_difference 0
18181810
| otherwise =
18191811
let (# !st #) = A.index# ary1 i1
18201812
in case go_difference (nextShift s) st t2 of
1821-
Empty {- | A.length ary1 == 1 -> Empty -- Impossible! -}
1822-
| A.length ary1 == 2 ->
1823-
case (i1, A.index ary1 0, A.index ary1 1) of
1824-
(0, _, l) | isLeafOrCollision l -> l
1825-
(1, l, _) | isLeafOrCollision l -> l
1826-
_ -> bIndexed
1827-
| otherwise -> bIndexed
1828-
where
1829-
bIndexed
1830-
= BitmapIndexed (b1 .&. complement m) (A.delete ary1 i1)
1813+
Empty | A.length ary1 == 2
1814+
, (# l #) <- A.index# ary1 (otherOfOneOrZero i1)
1815+
, isLeafOrCollision l
1816+
-> l
1817+
| otherwise
1818+
-> BitmapIndexed (b1 .&. complement m) (A.delete ary1 i1)
18311819
st' | isLeafOrCollision st' && A.length ary1 == 1 -> st'
18321820
| st `ptrEq` st' -> t1
18331821
| otherwise -> BitmapIndexed b1 (A.update ary1 i1 st')
@@ -2639,6 +2627,18 @@ ptrEq :: a -> a -> Bool
26392627
ptrEq x y = Exts.isTrue# (Exts.reallyUnsafePtrEquality# x y ==# 1#)
26402628
{-# INLINE ptrEq #-}
26412629

2630+
------------------------------------------------------------------------
2631+
-- Array index arithmetic
2632+
2633+
-- |
2634+
-- >>> otherOfOneOrZero 0
2635+
-- 1
2636+
-- >>> otherOfOneOrZero 1
2637+
-- 0
2638+
otherOfOneOrZero :: Int -> Int
2639+
otherOfOneOrZero i = 1 - i
2640+
{-# INLINE otherOfOneOrZero #-}
2641+
26422642
------------------------------------------------------------------------
26432643
-- IsList instance
26442644
instance (Eq k, Hashable k) => Exts.IsList (HashMap k v) where

0 commit comments

Comments
 (0)