Skip to content

Use countTrailingZeros for indexOfTheOnlyBit #379

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 24, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions containers/src/Data/IntSet/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1414,6 +1414,16 @@ foldr'Bits :: Int -> (Int -> a -> a) -> a -> Nat -> a
{-# INLINE foldr'Bits #-}

#if defined(__GLASGOW_HASKELL__) && (WORD_SIZE_IN_BITS==32 || WORD_SIZE_IN_BITS==64)
indexOfTheOnlyBit :: Nat -> Int
{-# INLINE indexOfTheOnlyBit #-}
#if MIN_VERSION_base(4,8,0) && (WORD_SIZE_IN_BITS==64)
indexOfTheOnlyBit bitmask = countTrailingZeros bitmask

lowestBitSet x = countTrailingZeros x

highestBitSet x = WORD_SIZE_IN_BITS - 1 - countLeadingZeros x

#else
{----------------------------------------------------------------------
For lowestBitSet we use wordsize-dependant implementation based on
multiplication and DeBrujn indeces, which was proposed by Edward Kmett
Expand All @@ -1427,8 +1437,6 @@ foldr'Bits :: Int -> (Int -> a -> a) -> a -> Nat -> a
before changing this code.
----------------------------------------------------------------------}

indexOfTheOnlyBit :: Nat -> Int
{-# INLINE indexOfTheOnlyBit #-}
indexOfTheOnlyBit bitmask =
I# (lsbArray `indexInt8OffAddr#` unboxInt (intFromNat ((bitmask * magic) `shiftRL` offset)))
where unboxInt (I# i) = i
Expand All @@ -1448,6 +1456,12 @@ indexOfTheOnlyBit bitmask =
-- is 48B on 32-bit and 56B on 64-bit architectures -- so the 32B and 64B array
-- is actually improvement on 32-bit and only a 8B size increase on 64-bit.

lowestBitSet x = indexOfTheOnlyBit (lowestBitMask x)

highestBitSet x = indexOfTheOnlyBit (highestBitMask x)

#endif

lowestBitMask :: Nat -> Nat
lowestBitMask x = x .&. negate x
{-# INLINE lowestBitMask #-}
Expand All @@ -1469,10 +1483,6 @@ revNat x1 = case ((x1 `shiftRL` 1) .&. 0x5555555555555555) .|. ((x1 .&. 0x555555
x6 -> ( x6 `shiftRL` 32 ) .|. ( x6 `shiftLL` 32);
#endif

lowestBitSet x = indexOfTheOnlyBit (lowestBitMask x)

highestBitSet x = indexOfTheOnlyBit (highestBitMask x)

foldlBits prefix f z bitmap = go bitmap z
where go 0 acc = acc
go bm acc = go (bm `xor` bitmask) ((f acc) $! (prefix+bi))
Expand Down