@@ -144,7 +144,7 @@ import Control.DeepSeq (NFData (..), NFData1 (..), NFData2 (..))
144
144
import Control.Monad.ST (ST , runST )
145
145
import Data.Bifoldable (Bifoldable (.. ))
146
146
import Data.Bits (complement , popCount , unsafeShiftL ,
147
- unsafeShiftR , (.&.) , (.|.) )
147
+ unsafeShiftR , (.&.) , (.|.) , countTrailingZeros )
148
148
import Data.Coerce (coerce )
149
149
import Data.Data (Constr , Data (.. ), DataType )
150
150
import Data.Functor.Classes (Eq1 (.. ), Eq2 (.. ), Ord1 (.. ), Ord2 (.. ),
@@ -1627,21 +1627,24 @@ unionArrayBy f !b1 !b2 !ary1 !ary2 = A.run $ do
1627
1627
-- iterate over nonzero bits of b1 .|. b2
1628
1628
-- it would be nice if we could shift m by more than 1 each time
1629
1629
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
1634
1633
x1 <- A. indexM ary1 i1
1635
1634
x2 <- A. indexM ary2 i2
1636
1635
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
1639
1638
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
1642
1641
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'
1645
1648
return mary
1646
1649
-- TODO: For the case where b1 .&. b2 == b1, i.e. when one is a
1647
1650
-- subset of the other, we could use a slightly simpler algorithm,
0 commit comments