{-# LANGUAGE CPP #-}
{-# LANGUAGE BangPatterns #-}
module Data.Bits.Compat (
    popCount,
    zeroBits,
    finiteBitSize,
    countLeadingZeros,
    ) where

import Data.Bits

#if !MIN_VERSION_base(4,7,0)
#define FiniteBits Bits
#endif

#if !MIN_VERSION_base(4,5,0)
popCount :: Bits a => a -> Int
popCount = go 0
 where
   go !c 0 = c
   go c w = go (c+1) (w .&. (w - 1)) -- clear the least significant
{-# INLINE popCount #-}
#endif

#if !MIN_VERSION_base(4,7,0)
zeroBits :: Bits a => a
zeroBits = clearBit (bit 0) 0
{-# INLINE zeroBits #-}

finiteBitSize :: Bits a => a -> Int
finiteBitSize = bitSize
{-# INLINE finiteBitSize #-}
#endif

#if !MIN_VERSION_base(4,8,0)
countLeadingZeros :: FiniteBits b => b -> Int
countLeadingZeros x = (w-1) - go (w-1)
  where
    go i | i < 0       = i -- no bit set
         | testBit x i = i
         | otherwise   = go (i-1)

    w = finiteBitSize x
{-# INLINE countLeadingZeros #-}
#endif