radix-tree-1.0.0.0: src/Radix/Word/Foundation.hs
module Radix.Word.Foundation
( Key
, Prefix
, Mask
, beyond
, upper
, lower
, zeroBit
, mask
, branchingBit
) where
import Data.Bits
-- | Key as stored in the data structure.
type Key = Word
-- | Part of the 'Key' from the largest bit to the 'Mask' bit, plus the 'Mask' bit.
type Prefix = Word
{-# INLINE beyond #-}
-- | \(\mathcal{O}(1)\).
-- Whether the key does not match the prefix.
beyond :: Prefix -> Key -> Bool
beyond p k = (k `xor` p) .&. (p `xor` negate p) /= 0
{-# INLINE upper #-}
-- | \(\mathcal{O}(1)\).
-- Largest key that can reside under this prefix.
upper :: Prefix -> Key
upper p = p .|. (p - 1)
{-# INLINE lower #-}
-- | \(\mathcal{O}(1)\).
-- Smallest key that can reside under this prefix.
lower :: Prefix -> Key
lower p = p .&. (p - 1)
-- | Masking bit.
type Mask = Word
{-# INLINE zeroBit #-}
-- | \(\mathcal{O}(1)\).
-- Get the state of the masked bit from the 'Key'.
zeroBit :: Key -> Mask -> Bool
zeroBit k m = (k .&. m) == 0
{-# INLINE mask #-}
-- | \(\mathcal{O}(1)\).
-- Trim the 'Key' down to the masking bit.
mask :: Key -> Mask -> Word
mask k m = k .&. (negate m `xor` m)
{-# INLINE branchingBit #-}
-- | \(\mathcal{O}(1)\).
-- Find the bit two 'Prefix'es disagree on.
--
-- Note that using this function on two equal integers yields @1 << (-1)@,
-- which results in undefined behavior.
branchingBit :: Prefix -> Prefix -> Mask
branchingBit p o =
1 `unsafeShiftL` (finiteBitSize (0 :: Word) - 1 - countLeadingZeros (p `xor` o))