-- Copyright 2023,2024 Lennart Augustsson -- See LICENSE file for full license. module Data.Word.Word32(Word32, byteSwap32, bitReverse32) where import qualified Prelude() -- do not import Prelude import Primitives import Control.Error import Data.Bits.Base import Data.Bool import Data.Bounded import Data.Char import Data.Coerce import Data.Enum import Data.Eq import Data.Function --import Data.Int() -- instances only import Data.Integer_Type import Data.Integral import Data.List import Data.Maybe_Type import Data.Num import Data.Ord import Data.Ratio_Type import Data.Real import {-# SOURCE #-} Data.Typeable import Data.Word.Word import Numeric.Show import Text.Show newtype Word32 = W32 Word deriving (Typeable, Eq, Ord) unW32 :: Word32 -> Word unW32 (W32 x) = x w32 :: Word -> Word32 w32 w = if _wordSize == 32 then W32 w else W32 (w .&. 0xffffffff) bin32 :: (Word -> Word -> Word) -> (Word32 -> Word32 -> Word32) bin32 op (W32 x) (W32 y) = w32 (x `op` y) bini32 :: (Word -> Int -> Word) -> (Word32 -> Int -> Word32) bini32 op (W32 x) y = w32 (x `op` y) una32 :: (Word -> Word) -> (Word32 -> Word32) una32 op (W32 x) = w32 (op x) instance Num Word32 where (+) = bin32 primWordAdd (-) = bin32 primWordSub (*) = bin32 primWordMul abs x = x signum x = if x == 0 then 0 else 1 fromInteger i = w32 (_integerToWord i) instance Integral Word32 where quot = bin32 primWordQuot rem = bin32 primWordRem toInteger = _wordToInteger . unW32 instance Bounded Word32 where minBound = w32 0 maxBound = w32 0xffffffff instance Real Word32 where toRational = _integerToRational . _wordToInteger . unW32 instance Show Word32 where showsPrec = showIntegral {- in Text.Read.Internal instance Read Word32 where readsPrec = readIntegral -} instance Enum Word32 where succ x = if x == maxBound then error "Word32.succ: overflow" else x + 1 pred x = if x == minBound then error "Word32.pred: underflow" else x - 1 toEnum = w32 . primIntToWord fromEnum = primWordToInt . unW32 enumFrom n = enumFromTo n maxBound enumFromThen n m | m >= n = enumFromThenTo n m maxBound | otherwise = enumFromThenTo n m minBound enumFromTo = coerce (enumFromTo @Word) enumFromThenTo = coerce (enumFromThenTo @Word) instance Bits Word32 where (.&.) = bin32 primWordAnd (.|.) = bin32 primWordOr xor = bin32 primWordXor complement = una32 primWordInv x `shiftL` i | i < 0 = _overflowError | i >= 32 = 0 | otherwise = x `unsafeShiftL` i unsafeShiftL = bini32 primWordShl x `shiftR` i | i < 0 = _overflowError | i >= 32 = 0 | otherwise = x `unsafeShiftR` i unsafeShiftR = bini32 primWordShr bitSizeMaybe _ = Just 32 bitSize _ = 32 bit = bitDefault testBit = testBitDefault popCount = primWordPopcount . unW32 zeroBits = 0 isSigned _ = False instance FiniteBits Word32 where finiteBitSize _ = 32 countLeadingZeros (W32 x) = primWordClz x - (_wordSize - 32) countTrailingZeros (W32 x) = if x == 0 then 32 else primWordCtz x byteSwap32 :: Word32 -> Word32 byteSwap32 w = (w <<< 24) .|. (w <<< 8 .&. 0x00ff0000) .|. (w >>> 8 .&. 0x0000ff00) .|. (w >>> 24) where (<<<) = unsafeShiftL (>>>) = unsafeShiftR bitReverse32 :: Word32 -> Word32 bitReverse32 x0 = x5 where (<<<) = unsafeShiftL (>>>) = unsafeShiftR x1 = ((x0 .&. 0x55555555) <<< 1) .|. ((x0 .&. 0xAAAAAAAA) >>> 1) x2 = ((x1 .&. 0x33333333) <<< 2) .|. ((x1 .&. 0xCCCCCCCC) >>> 2) x3 = ((x2 .&. 0x0F0F0F0F) <<< 4) .|. ((x2 .&. 0xF0F0F0F0) >>> 4) x4 = ((x3 .&. 0x00FF00FF) <<< 8) .|. ((x3 .&. 0xFF00FF00) >>> 8) x5 = ((x4 .&. 0x0000FFFF) <<< 16) .|. ((x4 .&. 0xFFFF0000) >>> 16)