-- | -- Module : Data.Array.Accelerate.Data.Colour.Internal.Pack -- Copyright : [2016..2020] Trevor L. McDonell -- License : BSD3 -- -- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com> -- Stability : experimental -- Portability : non-portable (GHC extensions) -- module Data.Array.Accelerate.Data.Colour.Internal.Pack where import Data.Array.Accelerate as A import Data.Array.Accelerate.Data.Bits as A -- | Pack the given four bytes into a single 4-byte word. The first argument -- will appear at the lowest address on a little-endian architecture with -- one-byte addressing: -- -- >>> pack8 0x0d 0x0c 0x0b 0x0a = 0x0a0b0c0d -- -- This function is equivalent to: -- -- >>> alloca $ \(p :: Ptr Word32) -> -- >>> pokeByteOff p 0 (0x0d :: Word8) -- >>> pokeByteOff p 1 (0x0c :: Word8) -- >>> pokeByteOff p 2 (0x0b :: Word8) -- >>> pokeByteOff p 3 (0x0a :: Word8) -- -- Where 'p' would then point to the value '0x0a0b0c0d' -- pack8 :: Exp Word8 -> Exp Word8 -> Exp Word8 -> Exp Word8 -> Exp Word32 pack8 x y z w = A.fromIntegral w `A.shiftL` 24 .|. A.fromIntegral z `A.shiftL` 16 .|. A.fromIntegral y `A.shiftL` 8 .|. A.fromIntegral x -- | Inverse of 'pack'. On a little-endian architecture: -- -- >>> unpack8 0x0a0b0c0d = (0x0d, 0x0c, 0x0b, 0x0a) -- unpack8 :: Exp Word32 -> Exp (Word8, Word8, Word8, Word8) unpack8 xyzw = let w = A.fromIntegral (xyzw `A.shiftR` 24) z = A.fromIntegral (xyzw `A.shiftR` 16) y = A.fromIntegral (xyzw `A.shiftR` 8) x = A.fromIntegral xyzw in lift (x,y,z,w) word8OfFloat :: Exp Float -> Exp Word8 word8OfFloat x = A.truncate (x * 255)