{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE ViewPatterns #-}
module Data.Array.Accelerate.Data.Bits (
Bits(..),
FiniteBits(..),
) where
import Data.Array.Accelerate.Array.Data
import Data.Array.Accelerate.Language
import Data.Array.Accelerate.Smart
import Data.Array.Accelerate.Sugar.Elt
import Data.Array.Accelerate.Type
import Data.Array.Accelerate.Classes.Eq
import Data.Array.Accelerate.Classes.Ord
import Data.Array.Accelerate.Classes.Integral ()
import Prelude ( (.), ($), undefined, otherwise )
import qualified Data.Bits as B
infixl 8 `shift`, `rotate`, `shiftL`, `shiftR`, `rotateL`, `rotateR`
infixl 7 .&.
infixl 6 `xor`
infixl 5 .|.
class Eq a => Bits a where
{-# MINIMAL (.&.), (.|.), xor, complement,
(shift | (shiftL, shiftR)),
(rotate | (rotateL, rotateR)),
isSigned, testBit, bit, popCount #-}
(.&.) :: Exp a -> Exp a -> Exp a
(.|.) :: Exp a -> Exp a -> Exp a
xor :: Exp a -> Exp a -> Exp a
complement :: Exp a -> Exp a
shift :: Exp a -> Exp Int -> Exp a
shift x i
= cond (i < 0) (x `shiftR` (-i))
$ cond (i > 0) (x `shiftL` i)
$ x
rotate :: Exp a -> Exp Int -> Exp a
rotate x i
= cond (i < 0) (x `rotateR` (-i))
$ cond (i > 0) (x `rotateL` i)
$ x
zeroBits :: Exp a
zeroBits = clearBit (bit 0) 0
bit :: Exp Int -> Exp a
setBit :: Exp a -> Exp Int -> Exp a
setBit x i = x .|. bit i
clearBit :: Exp a -> Exp Int -> Exp a
clearBit x i = x .&. complement (bit i)
complementBit :: Exp a -> Exp Int -> Exp a
complementBit x i = x `xor` bit i
testBit :: Exp a -> Exp Int -> Exp Bool
isSigned :: Exp a -> Exp Bool
shiftL :: Exp a -> Exp Int -> Exp a
shiftL x i = x `shift` i
unsafeShiftL :: Exp a -> Exp Int -> Exp a
unsafeShiftL = shiftL
shiftR :: Exp a -> Exp Int -> Exp a
shiftR x i = x `shift` (-i)
unsafeShiftR :: Exp a -> Exp Int -> Exp a
unsafeShiftR = shiftR
rotateL :: Exp a -> Exp Int -> Exp a
rotateL x i = x `rotate` i
rotateR :: Exp a -> Exp Int -> Exp a
rotateR x i = x `rotate` (-i)
popCount :: Exp a -> Exp Int
class Bits b => FiniteBits b where
finiteBitSize :: Exp b -> Exp Int
countLeadingZeros :: Exp b -> Exp Int
countTrailingZeros :: Exp b -> Exp Int
instance Bits Bool where
(.&.) = (&&)
(.|.) = (||)
xor = (/=)
complement = not
shift x i = cond (i == 0) x (constant False)
testBit x i = cond (i == 0) x (constant False)
rotate x _ = x
bit i = i == 0
isSigned = isSignedDefault
popCount = boolToInt
instance Bits Int where
(.&.) = mkBAnd
(.|.) = mkBOr
xor = mkBXor
complement = mkBNot
bit = bitDefault
testBit = testBitDefault
shift = shiftDefault
shiftL = shiftLDefault
shiftR = shiftRDefault
unsafeShiftL = mkBShiftL
unsafeShiftR = mkBShiftR
rotate = rotateDefault
rotateL = rotateLDefault
rotateR = rotateRDefault
isSigned = isSignedDefault
popCount = mkPopCount
instance Bits Int8 where
(.&.) = mkBAnd
(.|.) = mkBOr
xor = mkBXor
complement = mkBNot
bit = bitDefault
testBit = testBitDefault
shift = shiftDefault
shiftL = shiftLDefault
shiftR = shiftRDefault
unsafeShiftL = mkBShiftL
unsafeShiftR = mkBShiftR
rotate = rotateDefault
rotateL = rotateLDefault
rotateR = rotateRDefault
isSigned = isSignedDefault
popCount = mkPopCount
instance Bits Int16 where
(.&.) = mkBAnd
(.|.) = mkBOr
xor = mkBXor
complement = mkBNot
bit = bitDefault
testBit = testBitDefault
shift = shiftDefault
shiftL = shiftLDefault
shiftR = shiftRDefault
unsafeShiftL = mkBShiftL
unsafeShiftR = mkBShiftR
rotate = rotateDefault
rotateL = rotateLDefault
rotateR = rotateRDefault
isSigned = isSignedDefault
popCount = mkPopCount
instance Bits Int32 where
(.&.) = mkBAnd
(.|.) = mkBOr
xor = mkBXor
complement = mkBNot
bit = bitDefault
testBit = testBitDefault
shift = shiftDefault
shiftL = shiftLDefault
shiftR = shiftRDefault
unsafeShiftL = mkBShiftL
unsafeShiftR = mkBShiftR
rotate = rotateDefault
rotateL = rotateLDefault
rotateR = rotateRDefault
isSigned = isSignedDefault
popCount = mkPopCount
instance Bits Int64 where
(.&.) = mkBAnd
(.|.) = mkBOr
xor = mkBXor
complement = mkBNot
bit = bitDefault
testBit = testBitDefault
shift = shiftDefault
shiftL = shiftLDefault
shiftR = shiftRDefault
unsafeShiftL = mkBShiftL
unsafeShiftR = mkBShiftR
rotate = rotateDefault
rotateL = rotateLDefault
rotateR = rotateRDefault
isSigned = isSignedDefault
popCount = mkPopCount
instance Bits Word where
(.&.) = mkBAnd
(.|.) = mkBOr
xor = mkBXor
complement = mkBNot
bit = bitDefault
testBit = testBitDefault
shift = shiftDefault
shiftL = shiftLDefault
shiftR = shiftRDefault
unsafeShiftL = mkBShiftL
unsafeShiftR = mkBShiftR
rotate = rotateDefault
rotateL = rotateLDefault
rotateR = rotateRDefault
isSigned = isSignedDefault
popCount = mkPopCount
instance Bits Word8 where
(.&.) = mkBAnd
(.|.) = mkBOr
xor = mkBXor
complement = mkBNot
bit = bitDefault
testBit = testBitDefault
shift = shiftDefault
shiftL = shiftLDefault
shiftR = shiftRDefault
unsafeShiftL = mkBShiftL
unsafeShiftR = mkBShiftR
rotate = rotateDefault
rotateL = rotateLDefault
rotateR = rotateRDefault
isSigned = isSignedDefault
popCount = mkPopCount
instance Bits Word16 where
(.&.) = mkBAnd
(.|.) = mkBOr
xor = mkBXor
complement = mkBNot
bit = bitDefault
testBit = testBitDefault
shift = shiftDefault
shiftL = shiftLDefault
shiftR = shiftRDefault
unsafeShiftL = mkBShiftL
unsafeShiftR = mkBShiftR
rotate = rotateDefault
rotateL = rotateLDefault
rotateR = rotateRDefault
isSigned = isSignedDefault
popCount = mkPopCount
instance Bits Word32 where
(.&.) = mkBAnd
(.|.) = mkBOr
xor = mkBXor
complement = mkBNot
bit = bitDefault
testBit = testBitDefault
shift = shiftDefault
shiftL = shiftLDefault
shiftR = shiftRDefault
unsafeShiftL = mkBShiftL
unsafeShiftR = mkBShiftR
rotate = rotateDefault
rotateL = rotateLDefault
rotateR = rotateRDefault
isSigned = isSignedDefault
popCount = mkPopCount
instance Bits Word64 where
(.&.) = mkBAnd
(.|.) = mkBOr
xor = mkBXor
complement = mkBNot
bit = bitDefault
testBit = testBitDefault
shift = shiftDefault
shiftL = shiftLDefault
shiftR = shiftRDefault
unsafeShiftL = mkBShiftL
unsafeShiftR = mkBShiftR
rotate = rotateDefault
rotateL = rotateLDefault
rotateR = rotateRDefault
isSigned = isSignedDefault
popCount = mkPopCount
instance Bits CInt where
(.&.) = mkBAnd
(.|.) = mkBOr
xor = mkBXor
complement = mkBNot
bit = mkBitcast . bitDefault @Int32
testBit b = testBitDefault (mkBitcast @Int32 b)
shift = shiftDefault
shiftL = shiftLDefault
shiftR = shiftRDefault
unsafeShiftL = mkBShiftL
unsafeShiftR = mkBShiftR
rotate = rotateDefault
rotateL = rotateLDefault
rotateR = rotateRDefault
isSigned = isSignedDefault
popCount = mkPopCount . mkBitcast @Int32
instance Bits CUInt where
(.&.) = mkBAnd
(.|.) = mkBOr
xor = mkBXor
complement = mkBNot
bit = mkBitcast . bitDefault @Word32
testBit b = testBitDefault (mkBitcast @Word32 b)
shift = shiftDefault
shiftL = shiftLDefault
shiftR = shiftRDefault
unsafeShiftL = mkBShiftL
unsafeShiftR = mkBShiftR
rotate = rotateDefault
rotateL = rotateLDefault
rotateR = rotateRDefault
isSigned = isSignedDefault
popCount = mkPopCount . mkBitcast @Word32
instance Bits CLong where
(.&.) = mkBAnd
(.|.) = mkBOr
xor = mkBXor
complement = mkBNot
bit = mkBitcast . bitDefault @HTYPE_CLONG
testBit b = testBitDefault (mkBitcast @HTYPE_CLONG b)
shift = shiftDefault
shiftL = shiftLDefault
shiftR = shiftRDefault
unsafeShiftL = mkBShiftL
unsafeShiftR = mkBShiftR
rotate = rotateDefault
rotateL = rotateLDefault
rotateR = rotateRDefault
isSigned = isSignedDefault
popCount = mkPopCount . mkBitcast @HTYPE_CLONG
instance Bits CULong where
(.&.) = mkBAnd
(.|.) = mkBOr
xor = mkBXor
complement = mkBNot
bit = mkBitcast . bitDefault @HTYPE_CULONG
testBit b = testBitDefault (mkBitcast @HTYPE_CULONG b)
shift = shiftDefault
shiftL = shiftLDefault
shiftR = shiftRDefault
unsafeShiftL = mkBShiftL
unsafeShiftR = mkBShiftR
rotate = rotateDefault
rotateL = rotateLDefault
rotateR = rotateRDefault
isSigned = isSignedDefault
popCount = mkPopCount . mkBitcast @HTYPE_CULONG
instance Bits CLLong where
(.&.) = mkBAnd
(.|.) = mkBOr
xor = mkBXor
complement = mkBNot
bit = mkBitcast . bitDefault @Int64
testBit b = testBitDefault (mkBitcast @Int64 b)
shift = shiftDefault
shiftL = shiftLDefault
shiftR = shiftRDefault
unsafeShiftL = mkBShiftL
unsafeShiftR = mkBShiftR
rotate = rotateDefault
rotateL = rotateLDefault
rotateR = rotateRDefault
isSigned = isSignedDefault
popCount = mkPopCount . mkBitcast @Int64
instance Bits CULLong where
(.&.) = mkBAnd
(.|.) = mkBOr
xor = mkBXor
complement = mkBNot
bit = mkBitcast . bitDefault @Word64
testBit b = testBitDefault (mkBitcast @Word64 b)
shift = shiftDefault
shiftL = shiftLDefault
shiftR = shiftRDefault
unsafeShiftL = mkBShiftL
unsafeShiftR = mkBShiftR
rotate = rotateDefault
rotateL = rotateLDefault
rotateR = rotateRDefault
isSigned = isSignedDefault
popCount = mkPopCount . mkBitcast @Word64
instance Bits CShort where
(.&.) = mkBAnd
(.|.) = mkBOr
xor = mkBXor
complement = mkBNot
bit = mkBitcast . bitDefault @Int16
testBit b = testBitDefault (mkBitcast @Int16 b)
shift = shiftDefault
shiftL = shiftLDefault
shiftR = shiftRDefault
unsafeShiftL = mkBShiftL
unsafeShiftR = mkBShiftR
rotate = rotateDefault
rotateL = rotateLDefault
rotateR = rotateRDefault
isSigned = isSignedDefault
popCount = mkPopCount . mkBitcast @Int16
instance Bits CUShort where
(.&.) = mkBAnd
(.|.) = mkBOr
xor = mkBXor
complement = mkBNot
bit = mkBitcast . bitDefault @Word16
testBit b = testBitDefault (mkBitcast @Word16 b)
shift = shiftDefault
shiftL = shiftLDefault
shiftR = shiftRDefault
unsafeShiftL = mkBShiftL
unsafeShiftR = mkBShiftR
rotate = rotateDefault
rotateL = rotateLDefault
rotateR = rotateRDefault
isSigned = isSignedDefault
popCount = mkPopCount . mkBitcast @Word16
instance Bits CChar where
(.&.) = mkBAnd
(.|.) = mkBOr
xor = mkBXor
complement = mkBNot
bit = mkBitcast . bitDefault @HTYPE_CCHAR
testBit b = testBitDefault (mkBitcast @HTYPE_CCHAR b)
shift = shiftDefault
shiftL = shiftLDefault
shiftR = shiftRDefault
unsafeShiftL = mkBShiftL
unsafeShiftR = mkBShiftR
rotate = rotateDefault
rotateL = rotateLDefault
rotateR = rotateRDefault
isSigned = isSignedDefault
popCount = mkPopCount . mkBitcast @HTYPE_CCHAR
instance Bits CSChar where
(.&.) = mkBAnd
(.|.) = mkBOr
xor = mkBXor
complement = mkBNot
bit = mkBitcast . bitDefault @Int8
testBit b = testBitDefault (mkBitcast @Int8 b)
shift = shiftDefault
shiftL = shiftLDefault
shiftR = shiftRDefault
unsafeShiftL = mkBShiftL
unsafeShiftR = mkBShiftR
rotate = rotateDefault
rotateL = rotateLDefault
rotateR = rotateRDefault
isSigned = isSignedDefault
popCount = mkPopCount . mkBitcast @Int8
instance Bits CUChar where
(.&.) = mkBAnd
(.|.) = mkBOr
xor = mkBXor
complement = mkBNot
bit = mkBitcast . bitDefault @Word8
testBit b = testBitDefault (mkBitcast @Word8 b)
shift = shiftDefault
shiftL = shiftLDefault
shiftR = shiftRDefault
unsafeShiftL = mkBShiftL
unsafeShiftR = mkBShiftR
rotate = rotateDefault
rotateL = rotateLDefault
rotateR = rotateRDefault
isSigned = isSignedDefault
popCount = mkPopCount . mkBitcast @Word8
instance FiniteBits Bool where
finiteBitSize _ = constInt 8
countLeadingZeros x = cond x 0 1
countTrailingZeros x = cond x 0 1
instance FiniteBits Int where
finiteBitSize _ = constInt (B.finiteBitSize (undefined::Int))
countLeadingZeros = mkCountLeadingZeros
countTrailingZeros = mkCountTrailingZeros
instance FiniteBits Int8 where
finiteBitSize _ = constInt (B.finiteBitSize (undefined::Int8))
countLeadingZeros = mkCountLeadingZeros
countTrailingZeros = mkCountTrailingZeros
instance FiniteBits Int16 where
finiteBitSize _ = constInt (B.finiteBitSize (undefined::Int16))
countLeadingZeros = mkCountLeadingZeros
countTrailingZeros = mkCountTrailingZeros
instance FiniteBits Int32 where
finiteBitSize _ = constInt (B.finiteBitSize (undefined::Int32))
countLeadingZeros = mkCountLeadingZeros
countTrailingZeros = mkCountTrailingZeros
instance FiniteBits Int64 where
finiteBitSize _ = constInt (B.finiteBitSize (undefined::Int64))
countLeadingZeros = mkCountLeadingZeros
countTrailingZeros = mkCountTrailingZeros
instance FiniteBits Word where
finiteBitSize _ = constInt (B.finiteBitSize (undefined::Word))
countLeadingZeros = mkCountLeadingZeros
countTrailingZeros = mkCountTrailingZeros
instance FiniteBits Word8 where
finiteBitSize _ = constInt (B.finiteBitSize (undefined::Word8))
countLeadingZeros = mkCountLeadingZeros
countTrailingZeros = mkCountTrailingZeros
instance FiniteBits Word16 where
finiteBitSize _ = constInt (B.finiteBitSize (undefined::Word16))
countLeadingZeros = mkCountLeadingZeros
countTrailingZeros = mkCountTrailingZeros
instance FiniteBits Word32 where
finiteBitSize _ = constInt (B.finiteBitSize (undefined::Word32))
countLeadingZeros = mkCountLeadingZeros
countTrailingZeros = mkCountTrailingZeros
instance FiniteBits Word64 where
finiteBitSize _ = constInt (B.finiteBitSize (undefined::Word64))
countLeadingZeros = mkCountLeadingZeros
countTrailingZeros = mkCountTrailingZeros
instance FiniteBits CInt where
finiteBitSize _ = constInt (B.finiteBitSize (undefined::CInt))
countLeadingZeros = mkCountLeadingZeros . mkBitcast @Int32
countTrailingZeros = mkCountTrailingZeros . mkBitcast @Int32
instance FiniteBits CUInt where
finiteBitSize _ = constInt (B.finiteBitSize (undefined::CUInt))
countLeadingZeros = mkCountLeadingZeros . mkBitcast @Word32
countTrailingZeros = mkCountTrailingZeros . mkBitcast @Word32
instance FiniteBits CLong where
finiteBitSize _ = constInt (B.finiteBitSize (undefined::CLong))
countLeadingZeros = mkCountLeadingZeros . mkBitcast @HTYPE_CLONG
countTrailingZeros = mkCountTrailingZeros . mkBitcast @HTYPE_CLONG
instance FiniteBits CULong where
finiteBitSize _ = constInt (B.finiteBitSize (undefined::CULong))
countLeadingZeros = mkCountLeadingZeros . mkBitcast @HTYPE_CULONG
countTrailingZeros = mkCountTrailingZeros . mkBitcast @HTYPE_CULONG
instance FiniteBits CLLong where
finiteBitSize _ = constInt (B.finiteBitSize (undefined::CLLong))
countLeadingZeros = mkCountLeadingZeros . mkBitcast @Int64
countTrailingZeros = mkCountTrailingZeros . mkBitcast @Int64
instance FiniteBits CULLong where
finiteBitSize _ = constInt (B.finiteBitSize (undefined::CULLong))
countLeadingZeros = mkCountLeadingZeros . mkBitcast @Word64
countTrailingZeros = mkCountTrailingZeros . mkBitcast @Word64
instance FiniteBits CShort where
finiteBitSize _ = constInt (B.finiteBitSize (undefined::CShort))
countLeadingZeros = mkCountLeadingZeros . mkBitcast @Int16
countTrailingZeros = mkCountTrailingZeros . mkBitcast @Int16
instance FiniteBits CUShort where
finiteBitSize _ = constInt (B.finiteBitSize (undefined::CUShort))
countLeadingZeros = mkCountLeadingZeros . mkBitcast @Word16
countTrailingZeros = mkCountTrailingZeros . mkBitcast @Word16
instance FiniteBits CChar where
finiteBitSize _ = constInt (B.finiteBitSize (undefined::CChar))
countLeadingZeros = mkCountLeadingZeros . mkBitcast @HTYPE_CCHAR
countTrailingZeros = mkCountTrailingZeros . mkBitcast @HTYPE_CCHAR
instance FiniteBits CSChar where
finiteBitSize _ = constInt (B.finiteBitSize (undefined::CSChar))
countLeadingZeros = mkCountLeadingZeros . mkBitcast @Int8
countTrailingZeros = mkCountTrailingZeros . mkBitcast @Int8
instance FiniteBits CUChar where
finiteBitSize _ = constInt (B.finiteBitSize (undefined::CUChar))
countLeadingZeros = mkCountLeadingZeros . mkBitcast @Word8
countTrailingZeros = mkCountTrailingZeros . mkBitcast @Word8
bitDefault :: (IsIntegral (EltR t), Bits t) => Exp Int -> Exp t
bitDefault x = constInt 1 `shiftL` x
testBitDefault :: (IsIntegral (EltR t), Bits t) => Exp t -> Exp Int -> Exp Bool
testBitDefault x i = (x .&. bit i) /= constInt 0
shiftDefault :: (FiniteBits t, IsIntegral (EltR t), B.Bits t) => Exp t -> Exp Int -> Exp t
shiftDefault x i
= cond (i >= 0) (shiftLDefault x i)
(shiftRDefault x (-i))
shiftLDefault :: (FiniteBits t, IsIntegral (EltR t)) => Exp t -> Exp Int -> Exp t
shiftLDefault x i
= cond (i >= finiteBitSize x) (constInt 0)
$ mkBShiftL x i
shiftRDefault :: forall t. (B.Bits t, FiniteBits t, IsIntegral (EltR t)) => Exp t -> Exp Int -> Exp t
shiftRDefault
| B.isSigned (undefined::t) = shiftRADefault
| otherwise = shiftRLDefault
shiftRADefault :: (FiniteBits t, IsIntegral (EltR t)) => Exp t -> Exp Int -> Exp t
shiftRADefault x i
= cond (i >= finiteBitSize x) (cond (mkLt x (constInt 0)) (constInt (-1)) (constInt 0))
$ mkBShiftR x i
shiftRLDefault :: (FiniteBits t, IsIntegral (EltR t)) => Exp t -> Exp Int -> Exp t
shiftRLDefault x i
= cond (i >= finiteBitSize x) (constInt 0)
$ mkBShiftR x i
rotateDefault :: forall t. (FiniteBits t, IsIntegral (EltR t)) => Exp t -> Exp Int -> Exp t
rotateDefault x i
= cond (i < 0) (mkBRotateR x (-i))
$ cond (i > 0) (mkBRotateL x i)
$ x
rotateLDefault :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp Int -> Exp t
rotateLDefault x i
= cond (i == 0) x
$ mkBRotateL x i
rotateRDefault :: (Elt t, IsIntegral (EltR t)) => Exp t -> Exp Int -> Exp t
rotateRDefault x i
= cond (i == 0) x
$ mkBRotateR x i
isSignedDefault :: forall b. B.Bits b => Exp b -> Exp Bool
isSignedDefault _ = constant (B.isSigned (undefined::b))
constInt :: IsIntegral (EltR e) => EltR e -> Exp e
constInt = mkExp . Const (SingleScalarType (NumSingleType (IntegralNumType integralType)))