module Data.Bits.Extras (
ExtraBits(..)
) where
import Data.Bits
import Data.Word
import Data.Int
class Bits x => ExtraBits x where
lowestBitPlus1 :: x -> Word32
leadingZeros :: x -> Word32
trailingZeros :: x -> Word32
populationCount :: x -> Word32
parity :: x -> Word32
byteSwap :: x -> x
instance ExtraBits Word where
lowestBitPlus1 = c_ffsl
leadingZeros = c_clzl
trailingZeros = c_ctzl
populationCount = c_popcountl
parity = c_parityl
byteSwap = if bitSize (undefined :: Word) == 32
then fromIntegral . c_bswap32 . fromIntegral
else fromIntegral . c_bswap64 . fromIntegral
instance ExtraBits Word8 where
lowestBitPlus1 = c_ffs . fromIntegral
leadingZeros w = (c_clz $ fromIntegral w) 24
trailingZeros = c_ctz . (0xff00 .|.) . fromIntegral
populationCount = c_popcount . fromIntegral
parity = c_parity . fromIntegral
byteSwap = id
instance ExtraBits Word16 where
lowestBitPlus1 = c_ffs . fromIntegral
leadingZeros w = (c_clz $ fromIntegral w) 16
trailingZeros = c_ctz . (0xffff0000 .|.) . fromIntegral
populationCount = c_popcount . fromIntegral
parity = c_parity . fromIntegral
byteSwap w = w `shiftR` 8 .|. w `shiftL` 8
instance ExtraBits Word32 where
lowestBitPlus1 = c_ffs
leadingZeros = c_clz
trailingZeros = c_ctz
populationCount = c_popcount
parity = c_parity
byteSwap = c_bswap32
instance ExtraBits Word64 where
lowestBitPlus1 = c_ffsll
leadingZeros = c_clzll
trailingZeros = c_ctzll
populationCount = c_popcountll
parity = c_parityll
byteSwap = c_bswap64
instance ExtraBits Int where
lowestBitPlus1 = c_ffsl . fromIntegral
leadingZeros = c_clzl . fromIntegral
trailingZeros = c_ctzl . fromIntegral
populationCount = c_popcountl . fromIntegral
parity = c_parityl . fromIntegral
byteSwap = if bitSize (undefined :: Int) == 32
then fromIntegral . c_bswap32 . fromIntegral
else fromIntegral . c_bswap64 . fromIntegral
instance ExtraBits Int8 where
lowestBitPlus1 i = lowestBitPlus1 (fromIntegral i :: Word8)
leadingZeros i = leadingZeros (fromIntegral i :: Word8)
trailingZeros i = trailingZeros (fromIntegral i :: Word8)
populationCount = c_popcount . fromIntegral
parity = c_parity . fromIntegral
byteSwap = id
instance ExtraBits Int16 where
lowestBitPlus1 i = lowestBitPlus1 (fromIntegral i :: Word16)
leadingZeros i = leadingZeros (fromIntegral i :: Word16)
trailingZeros i = trailingZeros (fromIntegral i :: Word16)
populationCount = c_popcount . fromIntegral
parity = c_parity . fromIntegral
byteSwap i = fromIntegral . byteSwap $ (fromIntegral i :: Word16)
instance ExtraBits Int32 where
lowestBitPlus1 = c_ffs . fromIntegral
leadingZeros = c_clz . fromIntegral
trailingZeros = c_ctz . fromIntegral
populationCount = c_popcount . fromIntegral
parity = c_parity . fromIntegral
byteSwap = fromIntegral . c_bswap32 . fromIntegral
instance ExtraBits Int64 where
lowestBitPlus1 = fromIntegral . c_ffsll . fromIntegral
leadingZeros = fromIntegral . c_clzll . fromIntegral
trailingZeros = fromIntegral . c_ctzll . fromIntegral
populationCount = fromIntegral . c_popcountll . fromIntegral
parity = fromIntegral . c_parityll . fromIntegral
byteSwap = fromIntegral . c_bswap64 . fromIntegral
foreign import ccall unsafe "bitops-gcc.h ffs"
c_ffs :: Word32 -> Word32
foreign import ccall unsafe "bitops-gcc.h clz"
c_clz :: Word32 -> Word32
foreign import ccall unsafe "bitops-gcc.h ctz"
c_ctz :: Word32 -> Word32
foreign import ccall unsafe "bitops-gcc.h popcount"
c_popcount :: Word32 -> Word32
foreign import ccall unsafe "bitops-gcc.h parity"
c_parity :: Word32 -> Word32
foreign import ccall unsafe "bitops-gcc.h bswap32"
c_bswap32 :: Word32 -> Word32
foreign import ccall unsafe "bitops-gcc.h ffsll"
c_ffsll :: Word64 -> Word32
foreign import ccall unsafe "bitops-gcc.h clzll"
c_clzll :: Word64 -> Word32
foreign import ccall unsafe "bitops-gcc.h ctzll"
c_ctzll :: Word64 -> Word32
foreign import ccall unsafe "bitops-gcc.h popcountll"
c_popcountll :: Word64 -> Word32
foreign import ccall unsafe "bitops-gcc.h parityll"
c_parityll :: Word64 -> Word32
foreign import ccall unsafe "bitops-gcc.h bswap64"
c_bswap64 :: Word64 -> Word64
foreign import ccall unsafe "bitops-gcc.h ffsl"
c_ffsl :: Word -> Word32
foreign import ccall unsafe "bitops-gcc.h clzl"
c_clzl :: Word -> Word32
foreign import ccall unsafe "bitops-gcc.h ctzl"
c_ctzl :: Word -> Word32
foreign import ccall unsafe "bitops-gcc.h popcountl"
c_popcountl :: Word -> Word32
foreign import ccall unsafe "bitops-gcc.h parityl"
c_parityl :: Word -> Word32