Skip to content

Commit 0f4f623

Browse files
committed
Avoid range checks due to bit, clearBit, testBit
…and bring back array indices.
1 parent e88d075 commit 0f4f623

File tree

1 file changed

+14
-11
lines changed

1 file changed

+14
-11
lines changed

Data/HashMap/Internal.hs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ import Control.DeepSeq (NFData (..), NFData1 (..), NFData2 (..))
144144
import Control.Monad.ST (ST, runST)
145145
import Data.Bifoldable (Bifoldable (..))
146146
import Data.Bits (complement, popCount, unsafeShiftL,
147-
unsafeShiftR, (.&.), (.|.))
147+
unsafeShiftR, (.&.), (.|.), countTrailingZeros)
148148
import Data.Coerce (coerce)
149149
import Data.Data (Constr, Data (..), DataType)
150150
import Data.Functor.Classes (Eq1 (..), Eq2 (..), Ord1 (..), Ord2 (..),
@@ -1627,21 +1627,24 @@ unionArrayBy f !b1 !b2 !ary1 !ary2 = A.run $ do
16271627
-- iterate over nonzero bits of b1 .|. b2
16281628
-- it would be nice if we could shift m by more than 1 each time
16291629
let ba = b1 .&. b2
1630-
go !i !i1 !i2 !m
1631-
| m > b' = return ()
1632-
| b' .&. m == 0 = go i i1 i2 (m `unsafeShiftL` 1)
1633-
| ba .&. m /= 0 = do
1630+
go !i !i1 !i2 !b
1631+
| b == 0 = return ()
1632+
| testBit ba = do
16341633
x1 <- A.indexM ary1 i1
16351634
x2 <- A.indexM ary2 i2
16361635
A.write mary i $! f x1 x2
1637-
go (i+1) (i1+1) (i2+1) (m `unsafeShiftL` 1)
1638-
| b1 .&. m /= 0 = do
1636+
go (i+1) (i1+1) (i2+1) b''
1637+
| testBit b1 = do
16391638
A.write mary i =<< A.indexM ary1 i1
1640-
go (i+1) (i1+1) i2 (m `unsafeShiftL` 1)
1641-
| otherwise = do
1639+
go (i+1) (i1+1) i2 b''
1640+
| otherwise = do
16421641
A.write mary i =<< A.indexM ary2 i2
1643-
go (i+1) i1 (i2+1) (m `unsafeShiftL` 1)
1644-
go 0 0 0 (b' .&. negate b') -- XXX: b' must be non-zero
1642+
go (i+1) i1 (i2+1) b''
1643+
where
1644+
m = 1 `unsafeShiftL` (countTrailingZeros b)
1645+
testBit x = x .&. m /= 0
1646+
b'' = b .&. complement m
1647+
go 0 0 0 b'
16451648
return mary
16461649
-- TODO: For the case where b1 .&. b2 == b1, i.e. when one is a
16471650
-- subset of the other, we could use a slightly simpler algorithm,

0 commit comments

Comments
 (0)