{-# LANGUAGE CPP, NoImplicitPrelude #-}
{-# LANGUAGE BangPatterns, PatternGuards #-}
module Data.Bits.Compat (
module Base
, bitDefault
, testBitDefault
, popCountDefault
#if MIN_VERSION_base(4,7,0)
, toIntegralSized
#endif
) where
import Data.Bits as Base
#if !(MIN_VERSION_base(4,8,0))
import Prelude
#endif
#if !(MIN_VERSION_base(4,6,0))
bitDefault :: (Bits a, Num a) => Int -> a
bitDefault = \i -> 1 `shiftL` i
{-# INLINE bitDefault #-}
testBitDefault :: (Bits a, Num a) => a -> Int -> Bool
testBitDefault = \x i -> (x .&. bit i) /= 0
{-# INLINE testBitDefault #-}
popCountDefault :: (Bits a, Num a) => a -> Int
popCountDefault = go 0
where
go !c 0 = c
go c w = go (c+1) (w .&. (w - 1))
{-# INLINABLE popCountDefault #-}
#endif
#if MIN_VERSION_base(4,7,0) && !(MIN_VERSION_base(4,8,0))
toIntegralSized :: (Integral a, Integral b, Bits a, Bits b) => a -> Maybe b
toIntegralSized x
| maybe True (<= x) yMinBound
, maybe True (x <=) yMaxBound = Just y
| otherwise = Nothing
where
y = fromIntegral x
xWidth = bitSizeMaybe x
yWidth = bitSizeMaybe y
yMinBound
| isBitSubType x y = Nothing
| isSigned x, not (isSigned y) = Just 0
| isSigned x, isSigned y
, Just yW <- yWidth = Just (negate $ bit (yW-1))
| otherwise = Nothing
yMaxBound
| isBitSubType x y = Nothing
| isSigned x, not (isSigned y)
, Just xW <- xWidth, Just yW <- yWidth
, xW <= yW+1 = Nothing
| Just yW <- yWidth = if isSigned y
then Just (bit (yW-1)-1)
else Just (bit yW-1)
| otherwise = Nothing
{-# INLINEABLE toIntegralSized #-}
isBitSubType :: (Bits a, Bits b) => a -> b -> Bool
isBitSubType x y
| xWidth == yWidth, xSigned == ySigned = True
| ySigned, Nothing == yWidth = True
| not xSigned, not ySigned, Nothing == yWidth = True
| xSigned == ySigned, Just xW <- xWidth, Just yW <- yWidth = xW <= yW
| not xSigned, ySigned, Just xW <- xWidth, Just yW <- yWidth = xW < yW
| otherwise = False
where
xWidth = bitSizeMaybe x
xSigned = isSigned x
yWidth = bitSizeMaybe y
ySigned = isSigned y
{-# INLINE isBitSubType #-}
#endif