{-# LANGUAGE CPP #-}
{-# LANGUAGE UnicodeSyntax #-}
#if __GLASGOW_HASKELL__ >= 705
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnboxedTuples #-}
{-# LANGUAGE BangPatterns #-}
#endif
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
#include "MachDeps.h"
module Data.BinaryWord
( BinaryWord(..)
, lMsb
, lLsb
) where
import Data.Int
import Data.Word
import Data.Bits (Bits(..))
#if MIN_VERSION_base(4,7,0)
import Data.Bits (FiniteBits(..))
#endif
#if __GLASGOW_HASKELL__ >= 705
import GHC.Prim (plusWord2#, timesWord2#)
# if __GLASGOW_HASKELL__ >= 904
import GHC.Prim (word64ToWord#, wordToWord64#)
# endif
# if WORD_SIZE_IN_BITS == 32
import GHC.Word (Word32(..))
# endif
# if WORD_SIZE_IN_BITS == 64
import GHC.Word (Word64(..))
# endif
#endif
#if MIN_VERSION_base(4,7,0)
class (FiniteBits w, FiniteBits (UnsignedWord w), FiniteBits (SignedWord w))
#else
class (Bits w, Bits (UnsignedWord w), Bits (SignedWord w))
#endif
⇒ BinaryWord w where
type UnsignedWord w
type SignedWord w
unsignedWord ∷ w → UnsignedWord w
signedWord ∷ w → SignedWord w
unwrappedAdd ∷ w → w → (w, UnsignedWord w)
unwrappedMul ∷ w → w → (w, UnsignedWord w)
leadingZeroes ∷ w → Int
trailingZeroes ∷ w → Int
allZeroes ∷ w
allOnes ∷ w
msb ∷ w
lsb ∷ w
lsb = forall a. Bits a => Int -> a
bit Int
0
{-# INLINE lsb #-}
testMsb ∷ w → Bool
testLsb ∷ w → Bool
testLsb = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a. Bits a => a -> Int -> Bool
testBit Int
0
{-# INLINE testLsb #-}
setMsb ∷ w → w
setLsb ∷ w → w
setLsb = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a. Bits a => a -> Int -> a
setBit Int
0
{-# INLINE setLsb #-}
clearMsb ∷ w → w
clearLsb ∷ w → w
clearLsb = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a. Bits a => a -> Int -> a
clearBit Int
0
{-# INLINE clearLsb #-}
lMsb ∷ (Functor f, BinaryWord w) ⇒ (Bool → f Bool) → w → f w
lMsb :: forall (f :: * -> *) w.
(Functor f, BinaryWord w) =>
(Bool -> f Bool) -> w -> f w
lMsb Bool -> f Bool
f w
w = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\Bool
x → if Bool
x then forall w. BinaryWord w => w -> w
setMsb w
w else forall w. BinaryWord w => w -> w
clearMsb w
w) (Bool -> f Bool
f (forall w. BinaryWord w => w -> Bool
testMsb w
w))
lLsb ∷ (Functor f, BinaryWord w) ⇒ (Bool → f Bool) → w → f w
lLsb :: forall (f :: * -> *) w.
(Functor f, BinaryWord w) =>
(Bool -> f Bool) -> w -> f w
lLsb Bool -> f Bool
f w
w = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\Bool
x → if Bool
x then forall w. BinaryWord w => w -> w
setLsb w
w else forall w. BinaryWord w => w -> w
clearLsb w
w) (Bool -> f Bool
f (forall w. BinaryWord w => w -> Bool
testLsb w
w))
instance BinaryWord Word8 where
type UnsignedWord Word8 = Word8
type SignedWord Word8 = Int8
unsignedWord :: Word8 -> UnsignedWord Word8
unsignedWord = forall a. a -> a
id
{-# INLINE unsignedWord #-}
signedWord :: Word8 -> SignedWord Word8
signedWord = forall a b. (Integral a, Num b) => a -> b
fromIntegral
{-# INLINE signedWord #-}
unwrappedAdd :: Word8 -> Word8 -> (Word8, UnsignedWord Word8)
unwrappedAdd Word8
x Word8
y = Word8
hi seq :: forall a b. a -> b -> b
`seq` Word8
lo seq :: forall a b. a -> b -> b
`seq` (Word8
hi, Word8
lo)
where s :: Word16
s = forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
x forall a. Num a => a -> a -> a
+ forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
y ∷ Word16
lo :: Word8
lo = forall a b. (Integral a, Num b) => a -> b
fromIntegral Word16
s
hi :: Word8
hi = forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bits a => a -> Int -> a
shiftR Word16
s Int
8)
{-# INLINE unwrappedAdd #-}
unwrappedMul :: Word8 -> Word8 -> (Word8, UnsignedWord Word8)
unwrappedMul Word8
x Word8
y = Word8
hi seq :: forall a b. a -> b -> b
`seq` Word8
lo seq :: forall a b. a -> b -> b
`seq` (Word8
hi, Word8
lo)
where p :: Word16
p = forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
x forall a. Num a => a -> a -> a
* forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
y ∷ Word16
lo :: Word8
lo = forall a b. (Integral a, Num b) => a -> b
fromIntegral Word16
p
hi :: Word8
hi = forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bits a => a -> Int -> a
shiftR Word16
p Int
8)
{-# INLINE unwrappedMul #-}
#if MIN_VERSION_base(4,8,0)
leadingZeroes :: Word8 -> Int
leadingZeroes = forall b. FiniteBits b => b -> Int
countLeadingZeros
{-# INLINE leadingZeroes #-}
trailingZeroes :: Word8 -> Int
trailingZeroes = forall b. FiniteBits b => b -> Int
countTrailingZeros
{-# INLINE trailingZeroes #-}
#else
leadingZeroes w | w .&. 0xF0 == 0 = go4 4 w
| otherwise = go4 0 (shiftR w 4)
where go4 off w' | w' .&. 8 /= 0 = off
| w' .&. 4 /= 0 = off + 1
| w' .&. 2 /= 0 = off + 2
| w' .&. 1 /= 0 = off + 3
| otherwise = off + 4
trailingZeroes w | w .&. 0x0F == 0 = go4 4 (shiftR w 4)
| otherwise = go4 0 w
where go4 off w' | w' .&. 1 /= 0 = off
| w' .&. 2 /= 0 = off + 1
| w' .&. 4 /= 0 = off + 2
| w' .&. 8 /= 0 = off + 3
| otherwise = off + 4
#endif
allZeroes :: Word8
allZeroes = Word8
0
{-# INLINE allZeroes #-}
allOnes :: Word8
allOnes = Word8
0xFF
{-# INLINE allOnes #-}
msb :: Word8
msb = Word8
0x80
{-# INLINE msb #-}
lsb :: Word8
lsb = Word8
1
{-# INLINE lsb #-}
testMsb :: Word8 -> Bool
testMsb Word8
x = forall a. Bits a => a -> Int -> Bool
testBit Word8
x Int
7
{-# INLINE testMsb #-}
setMsb :: Word8 -> Word8
setMsb Word8
x = forall a. Bits a => a -> Int -> a
setBit Word8
x Int
7
{-# INLINE setMsb #-}
clearMsb :: Word8 -> Word8
clearMsb Word8
x = forall a. Bits a => a -> Int -> a
clearBit Word8
x Int
7
{-# INLINE clearMsb #-}
instance BinaryWord Word16 where
type UnsignedWord Word16 = Word16
type SignedWord Word16 = Int16
unsignedWord :: Word16 -> UnsignedWord Word16
unsignedWord = forall a. a -> a
id
{-# INLINE unsignedWord #-}
signedWord :: Word16 -> SignedWord Word16
signedWord = forall a b. (Integral a, Num b) => a -> b
fromIntegral
{-# INLINE signedWord #-}
unwrappedAdd :: Word16 -> Word16 -> (Word16, UnsignedWord Word16)
unwrappedAdd Word16
x Word16
y = Word16
hi seq :: forall a b. a -> b -> b
`seq` Word16
lo seq :: forall a b. a -> b -> b
`seq` (Word16
hi, Word16
lo)
where s :: Word32
s = forall a b. (Integral a, Num b) => a -> b
fromIntegral Word16
x forall a. Num a => a -> a -> a
+ forall a b. (Integral a, Num b) => a -> b
fromIntegral Word16
y ∷ Word32
lo :: Word16
lo = forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
s
hi :: Word16
hi = forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bits a => a -> Int -> a
shiftR Word32
s Int
16)
{-# INLINE unwrappedAdd #-}
unwrappedMul :: Word16 -> Word16 -> (Word16, UnsignedWord Word16)
unwrappedMul Word16
x Word16
y = Word16
hi seq :: forall a b. a -> b -> b
`seq` Word16
lo seq :: forall a b. a -> b -> b
`seq` (Word16
hi, Word16
lo)
where p :: Word32
p = forall a b. (Integral a, Num b) => a -> b
fromIntegral Word16
x forall a. Num a => a -> a -> a
* forall a b. (Integral a, Num b) => a -> b
fromIntegral Word16
y ∷ Word32
lo :: Word16
lo = forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
p
hi :: Word16
hi = forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bits a => a -> Int -> a
shiftR Word32
p Int
16)
{-# INLINE unwrappedMul #-}
#if MIN_VERSION_base(4,8,0)
leadingZeroes :: Word16 -> Int
leadingZeroes = forall b. FiniteBits b => b -> Int
countLeadingZeros
{-# INLINE leadingZeroes #-}
trailingZeroes :: Word16 -> Int
trailingZeroes = forall b. FiniteBits b => b -> Int
countTrailingZeros
{-# INLINE trailingZeroes #-}
#else
leadingZeroes w | w .&. 0xFF00 == 0 = go8 8 w
| otherwise = go8 0 (shiftR w 8)
where
go8 off w' | w' .&. 0xF0 == 0 = go4 (off + 4) w'
| otherwise = go4 off (shiftR w' 4)
go4 off w' | w' .&. 8 /= 0 = off
| w' .&. 4 /= 0 = off + 1
| w' .&. 2 /= 0 = off + 2
| w' .&. 1 /= 0 = off + 3
| otherwise = off + 4
trailingZeroes w | w .&. 0x00FF == 0 = go8 8 (shiftR w 8)
| otherwise = go8 0 w
where
go8 off w' | w' .&. 0x0F == 0 = go4 (off + 4) (shiftR w' 4)
| otherwise = go4 off w'
go4 off w' | w' .&. 1 /= 0 = off
| w' .&. 2 /= 0 = off + 1
| w' .&. 4 /= 0 = off + 2
| w' .&. 8 /= 0 = off + 3
| otherwise = off + 4
#endif
allZeroes :: Word16
allZeroes = Word16
0
{-# INLINE allZeroes #-}
allOnes :: Word16
allOnes = Word16
0xFFFF
{-# INLINE allOnes #-}
msb :: Word16
msb = Word16
0x8000
{-# INLINE msb #-}
lsb :: Word16
lsb = Word16
1
{-# INLINE lsb #-}
testMsb :: Word16 -> Bool
testMsb Word16
x = forall a. Bits a => a -> Int -> Bool
testBit Word16
x Int
15
{-# INLINE testMsb #-}
setMsb :: Word16 -> Word16
setMsb Word16
x = forall a. Bits a => a -> Int -> a
setBit Word16
x Int
15
{-# INLINE setMsb #-}
clearMsb :: Word16 -> Word16
clearMsb Word16
x = forall a. Bits a => a -> Int -> a
clearBit Word16
x Int
15
{-# INLINE clearMsb #-}
instance BinaryWord Word32 where
type UnsignedWord Word32 = Word32
type SignedWord Word32 = Int32
unsignedWord :: Word32 -> UnsignedWord Word32
unsignedWord = forall a. a -> a
id
{-# INLINE unsignedWord #-}
signedWord :: Word32 -> SignedWord Word32
signedWord = forall a b. (Integral a, Num b) => a -> b
fromIntegral
{-# INLINE signedWord #-}
#if __GLASGOW_HASKELL__ >= 705 && WORD_SIZE_IN_BITS == 32
unwrappedAdd (W32# x) (W32# y) = hi `seq` lo `seq` (hi, lo)
where !(# hi', lo' #) = plusWord2# x y
lo = W32# lo'
hi = W32# hi'
#else
unwrappedAdd :: Word32 -> Word32 -> (Word32, UnsignedWord Word32)
unwrappedAdd Word32
x Word32
y = Word32
hi seq :: forall a b. a -> b -> b
`seq` Word32
lo seq :: forall a b. a -> b -> b
`seq` (Word32
hi, Word32
lo)
where s :: Word64
s = forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
x forall a. Num a => a -> a -> a
+ forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
y ∷ Word64
lo :: Word32
lo = forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
s
hi :: Word32
hi = forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bits a => a -> Int -> a
shiftR Word64
s Int
32)
#endif
{-# INLINE unwrappedAdd #-}
#if __GLASGOW_HASKELL__ >= 705 && WORD_SIZE_IN_BITS == 32
unwrappedMul (W32# x) (W32# y) = hi `seq` lo `seq` (hi, lo)
where !(# hi', lo' #) = timesWord2# x y
lo = W32# lo'
hi = W32# hi'
#else
unwrappedMul :: Word32 -> Word32 -> (Word32, UnsignedWord Word32)
unwrappedMul Word32
x Word32
y = Word32
hi seq :: forall a b. a -> b -> b
`seq` Word32
lo seq :: forall a b. a -> b -> b
`seq` (Word32
hi, Word32
lo)
where p :: Word64
p = forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
x forall a. Num a => a -> a -> a
* forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
y ∷ Word64
lo :: Word32
lo = forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
p
hi :: Word32
hi = forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bits a => a -> Int -> a
shiftR Word64
p Int
32)
#endif
{-# INLINE unwrappedMul #-}
#if MIN_VERSION_base(4,8,0)
leadingZeroes :: Word32 -> Int
leadingZeroes = forall b. FiniteBits b => b -> Int
countLeadingZeros
{-# INLINE leadingZeroes #-}
trailingZeroes :: Word32 -> Int
trailingZeroes = forall b. FiniteBits b => b -> Int
countTrailingZeros
{-# INLINE trailingZeroes #-}
#else
leadingZeroes w | w .&. 0xFFFF0000 == 0 = go16 16 w
| otherwise = go16 0 (shiftR w 16)
where
go16 off w' | w' .&. 0xFF00 == 0 = go8 (off + 8) w'
| otherwise = go8 off (shiftR w' 8)
go8 off w' | w' .&. 0xF0 == 0 = go4 (off + 4) w'
| otherwise = go4 off (shiftR w' 4)
go4 off w' | w' .&. 8 /= 0 = off
| w' .&. 4 /= 0 = off + 1
| w' .&. 2 /= 0 = off + 2
| w' .&. 1 /= 0 = off + 3
| otherwise = off + 4
trailingZeroes w | w .&. 0x0000FFFF == 0 = go16 16 (shiftR w 16)
| otherwise = go16 0 w
where
go16 off w' | w' .&. 0x00FF == 0 = go8 (off + 8) (shiftR w' 8)
| otherwise = go8 off w'
go8 off w' | w' .&. 0x0F == 0 = go4 (off + 4) (shiftR w' 4)
| otherwise = go4 off w'
go4 off w' | w' .&. 1 /= 0 = off
| w' .&. 2 /= 0 = off + 1
| w' .&. 4 /= 0 = off + 2
| w' .&. 8 /= 0 = off + 3
| otherwise = off + 4
#endif
allZeroes :: Word32
allZeroes = Word32
0
{-# INLINE allZeroes #-}
allOnes :: Word32
allOnes = Word32
0xFFFFFFFF
{-# INLINE allOnes #-}
msb :: Word32
msb = Word32
0x80000000
{-# INLINE msb #-}
lsb :: Word32
lsb = Word32
1
{-# INLINE lsb #-}
testMsb :: Word32 -> Bool
testMsb Word32
x = forall a. Bits a => a -> Int -> Bool
testBit Word32
x Int
31
{-# INLINE testMsb #-}
setMsb :: Word32 -> Word32
setMsb Word32
x = forall a. Bits a => a -> Int -> a
setBit Word32
x Int
31
{-# INLINE setMsb #-}
clearMsb :: Word32 -> Word32
clearMsb Word32
x = forall a. Bits a => a -> Int -> a
clearBit Word32
x Int
31
{-# INLINE clearMsb #-}
instance BinaryWord Word64 where
type UnsignedWord Word64 = Word64
type SignedWord Word64 = Int64
unsignedWord :: Word64 -> UnsignedWord Word64
unsignedWord = forall a. a -> a
id
{-# INLINE unsignedWord #-}
signedWord :: Word64 -> SignedWord Word64
signedWord = forall a b. (Integral a, Num b) => a -> b
fromIntegral
{-# INLINE signedWord #-}
#if __GLASGOW_HASKELL__ >= 705 && WORD_SIZE_IN_BITS == 64
unwrappedAdd :: Word64 -> Word64 -> (Word64, UnsignedWord Word64)
unwrappedAdd (W64# Word#
x) (W64# Word#
y) = Word64
hi seq :: forall a b. a -> b -> b
`seq` Word64
lo seq :: forall a b. a -> b -> b
`seq` (Word64
hi, Word64
lo)
# if __GLASGOW_HASKELL__ >= 904
where !(# hi', lo' #) = plusWord2# (word64ToWord# x) (word64ToWord# y)
lo = W64# (wordToWord64# lo')
hi = W64# (wordToWord64# hi')
# else
where !(# Word#
hi', Word#
lo' #) = Word# -> Word# -> (# Word#, Word# #)
plusWord2# Word#
x Word#
y
lo :: Word64
lo = Word# -> Word64
W64# Word#
lo'
hi :: Word64
hi = Word# -> Word64
W64# Word#
hi'
# endif
{-# INLINE unwrappedAdd #-}
#else
unwrappedAdd x y = hi `seq` lo `seq` (hi, lo)
where lo = x + y
hi = if lo < x then 1 else 0
{-# INLINABLE unwrappedAdd #-}
#endif
#if __GLASGOW_HASKELL__ >= 705 && WORD_SIZE_IN_BITS == 64
unwrappedMul :: Word64 -> Word64 -> (Word64, UnsignedWord Word64)
unwrappedMul (W64# Word#
x) (W64# Word#
y) = Word64
hi seq :: forall a b. a -> b -> b
`seq` Word64
lo seq :: forall a b. a -> b -> b
`seq` (Word64
hi, Word64
lo)
# if __GLASGOW_HASKELL__ >= 904
where !(# hi', lo' #) = timesWord2# (word64ToWord# x) (word64ToWord# y)
lo = W64# (wordToWord64# lo')
hi = W64# (wordToWord64# hi')
# else
where !(# Word#
hi', Word#
lo' #) = Word# -> Word# -> (# Word#, Word# #)
timesWord2# Word#
x Word#
y
lo :: Word64
lo = Word# -> Word64
W64# Word#
lo'
hi :: Word64
hi = Word# -> Word64
W64# Word#
hi'
# endif
{-# INLINE unwrappedMul #-}
#else
unwrappedMul x y = hi `seq` lo `seq` (hi, lo)
where xHi = shiftR x 32
xLo = x .&. 0xFFFFFFFF
yHi = shiftR y 32
yLo = y .&. 0xFFFFFFFF
hi0 = xHi * yHi
lo0 = xLo * yLo
p1 = xHi * yLo
p2 = xLo * yHi
hi = hi0 + fromIntegral (uHi1 ∷ Word32) + fromIntegral uHi2 +
shiftR p1 32 + shiftR p2 32
lo = shiftL (fromIntegral lo') 32 .|. (lo0 .&. 0xFFFFFFFF)
(uHi1, uLo) = unwrappedAdd (fromIntegral p1) (fromIntegral p2)
(uHi2, lo') = unwrappedAdd (fromIntegral (shiftR lo0 32)) uLo
#endif
#if MIN_VERSION_base(4,8,0)
leadingZeroes :: Word64 -> Int
leadingZeroes = forall b. FiniteBits b => b -> Int
countLeadingZeros
{-# INLINE leadingZeroes #-}
trailingZeroes :: Word64 -> Int
trailingZeroes = forall b. FiniteBits b => b -> Int
countTrailingZeros
{-# INLINE trailingZeroes #-}
#else
# if WORD_SIZE_IN_BITS == 64
leadingZeroes w | w .&. 0xFFFFFFFF00000000 == 0 = go32 32 w
| otherwise = go32 0 (shiftR w 32)
where
go32 off w' | w' .&. 0xFFFF0000 == 0 = go16 (off + 16) w'
| otherwise = go16 off (shiftR w' 16)
go16 off w' | w' .&. 0xFF00 == 0 = go8 (off + 8) w'
| otherwise = go8 off (shiftR w' 8)
go8 off w' | w' .&. 0xF0 == 0 = go4 (off + 4) w'
| otherwise = go4 off (shiftR w' 4)
go4 off w' | w' .&. 8 /= 0 = off
| w' .&. 4 /= 0 = off + 1
| w' .&. 2 /= 0 = off + 2
| w' .&. 1 /= 0 = off + 3
| otherwise = off + 4
trailingZeroes w | w .&. 0x00000000FFFFFFFF == 0 = go32 32 (shiftR w 32)
| otherwise = go32 0 w
where
go32 off w' | w' .&. 0x0000FFFF == 0 = go16 (off + 16) (shiftR w' 16)
| otherwise = go16 off w'
go16 off w' | w' .&. 0x00FF == 0 = go8 (off + 8) (shiftR w' 8)
| otherwise = go8 off w'
go8 off w' | w' .&. 0x0F == 0 = go4 (off + 4) (shiftR w' 4)
| otherwise = go4 off w'
go4 off w' | w' .&. 1 /= 0 = off
| w' .&. 2 /= 0 = off + 1
| w' .&. 4 /= 0 = off + 2
| w' .&. 8 /= 0 = off + 3
| otherwise = off + 4
# else
leadingZeroes w | hiZeroes == 32 = 32 + leadingZeroes lo
| otherwise = hiZeroes
where lo = fromIntegral w ∷ Word32
hi = fromIntegral (shiftR w 32) ∷ Word32
hiZeroes = leadingZeroes hi
trailingZeroes w | loZeroes == 32 = 32 + trailingZeroes hi
| otherwise = loZeroes
where lo = fromIntegral w ∷ Word32
hi = fromIntegral (shiftR w 32) ∷ Word32
loZeroes = trailingZeroes lo
# endif
#endif
allZeroes :: Word64
allZeroes = Word64
0
{-# INLINE allZeroes #-}
allOnes :: Word64
allOnes = Word64
0xFFFFFFFFFFFFFFFF
{-# INLINE allOnes #-}
msb :: Word64
msb = Word64
0x8000000000000000
{-# INLINE msb #-}
lsb :: Word64
lsb = Word64
1
{-# INLINE lsb #-}
testMsb :: Word64 -> Bool
testMsb Word64
x = forall a. Bits a => a -> Int -> Bool
testBit Word64
x Int
63
{-# INLINE testMsb #-}
setMsb :: Word64 -> Word64
setMsb Word64
x = forall a. Bits a => a -> Int -> a
setBit Word64
x Int
63
{-# INLINE setMsb #-}
clearMsb :: Word64 -> Word64
clearMsb Word64
x = forall a. Bits a => a -> Int -> a
clearBit Word64
x Int
63
{-# INLINE clearMsb #-}
instance BinaryWord Int8 where
type UnsignedWord Int8 = Word8
type SignedWord Int8 = Int8
unsignedWord :: Int8 -> UnsignedWord Int8
unsignedWord = forall a b. (Integral a, Num b) => a -> b
fromIntegral
{-# INLINE unsignedWord #-}
signedWord :: Int8 -> SignedWord Int8
signedWord = forall a. a -> a
id
{-# INLINE signedWord #-}
unwrappedAdd :: Int8 -> Int8 -> (Int8, UnsignedWord Int8)
unwrappedAdd Int8
x Int8
y = Int8
hi seq :: forall a b. a -> b -> b
`seq` Word8
lo seq :: forall a b. a -> b -> b
`seq` (Int8
hi, Word8
lo)
where s :: Int16
s = forall a b. (Integral a, Num b) => a -> b
fromIntegral Int8
x forall a. Num a => a -> a -> a
+ forall a b. (Integral a, Num b) => a -> b
fromIntegral Int8
y ∷ Int16
lo :: Word8
lo = forall a b. (Integral a, Num b) => a -> b
fromIntegral Int16
s
hi :: Int8
hi = forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bits a => a -> Int -> a
shiftR Int16
s Int
8)
{-# INLINE unwrappedAdd #-}
unwrappedMul :: Int8 -> Int8 -> (Int8, UnsignedWord Int8)
unwrappedMul Int8
x Int8
y = Int8
hi seq :: forall a b. a -> b -> b
`seq` Word8
lo seq :: forall a b. a -> b -> b
`seq` (Int8
hi, Word8
lo)
where p :: Int16
p = forall a b. (Integral a, Num b) => a -> b
fromIntegral Int8
x forall a. Num a => a -> a -> a
* forall a b. (Integral a, Num b) => a -> b
fromIntegral Int8
y ∷ Int16
lo :: Word8
lo = forall a b. (Integral a, Num b) => a -> b
fromIntegral Int16
p
hi :: Int8
hi = forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bits a => a -> Int -> a
shiftR Int16
p Int
8)
{-# INLINE unwrappedMul #-}
leadingZeroes :: Int8 -> Int
leadingZeroes = forall w. BinaryWord w => w -> Int
leadingZeroes forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall w. BinaryWord w => w -> UnsignedWord w
unsignedWord
{-# INLINE leadingZeroes #-}
trailingZeroes :: Int8 -> Int
trailingZeroes = forall w. BinaryWord w => w -> Int
trailingZeroes forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall w. BinaryWord w => w -> UnsignedWord w
unsignedWord
{-# INLINE trailingZeroes #-}
allZeroes :: Int8
allZeroes = Int8
0
{-# INLINE allZeroes #-}
allOnes :: Int8
allOnes = -Int8
1
{-# INLINE allOnes #-}
msb :: Int8
msb = forall a. Bounded a => a
minBound
{-# INLINE msb #-}
lsb :: Int8
lsb = Int8
1
{-# INLINE lsb #-}
testMsb :: Int8 -> Bool
testMsb Int8
x = forall a. Bits a => a -> Int -> Bool
testBit Int8
x Int
7
{-# INLINE testMsb #-}
setMsb :: Int8 -> Int8
setMsb Int8
x = forall a. Bits a => a -> Int -> a
setBit Int8
x Int
7
{-# INLINE setMsb #-}
clearMsb :: Int8 -> Int8
clearMsb Int8
x = forall a. Bits a => a -> Int -> a
clearBit Int8
x Int
7
{-# INLINE clearMsb #-}
instance BinaryWord Int16 where
type UnsignedWord Int16 = Word16
type SignedWord Int16 = Int16
unsignedWord :: Int16 -> UnsignedWord Int16
unsignedWord = forall a b. (Integral a, Num b) => a -> b
fromIntegral
{-# INLINE unsignedWord #-}
signedWord :: Int16 -> SignedWord Int16
signedWord = forall a. a -> a
id
{-# INLINE signedWord #-}
unwrappedAdd :: Int16 -> Int16 -> (Int16, UnsignedWord Int16)
unwrappedAdd Int16
x Int16
y = Int16
hi seq :: forall a b. a -> b -> b
`seq` Word16
lo seq :: forall a b. a -> b -> b
`seq` (Int16
hi, Word16
lo)
where s :: Int32
s = forall a b. (Integral a, Num b) => a -> b
fromIntegral Int16
x forall a. Num a => a -> a -> a
+ forall a b. (Integral a, Num b) => a -> b
fromIntegral Int16
y ∷ Int32
lo :: Word16
lo = forall a b. (Integral a, Num b) => a -> b
fromIntegral Int32
s
hi :: Int16
hi = forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bits a => a -> Int -> a
shiftR Int32
s Int
16)
{-# INLINE unwrappedAdd #-}
unwrappedMul :: Int16 -> Int16 -> (Int16, UnsignedWord Int16)
unwrappedMul Int16
x Int16
y = Int16
hi seq :: forall a b. a -> b -> b
`seq` Word16
lo seq :: forall a b. a -> b -> b
`seq` (Int16
hi, Word16
lo)
where p :: Int32
p = forall a b. (Integral a, Num b) => a -> b
fromIntegral Int16
x forall a. Num a => a -> a -> a
* forall a b. (Integral a, Num b) => a -> b
fromIntegral Int16
y ∷ Int32
lo :: Word16
lo = forall a b. (Integral a, Num b) => a -> b
fromIntegral Int32
p
hi :: Int16
hi = forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bits a => a -> Int -> a
shiftR Int32
p Int
16)
{-# INLINE unwrappedMul #-}
leadingZeroes :: Int16 -> Int
leadingZeroes = forall w. BinaryWord w => w -> Int
leadingZeroes forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall w. BinaryWord w => w -> UnsignedWord w
unsignedWord
{-# INLINE leadingZeroes #-}
trailingZeroes :: Int16 -> Int
trailingZeroes = forall w. BinaryWord w => w -> Int
trailingZeroes forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall w. BinaryWord w => w -> UnsignedWord w
unsignedWord
{-# INLINE trailingZeroes #-}
allZeroes :: Int16
allZeroes = Int16
0
{-# INLINE allZeroes #-}
allOnes :: Int16
allOnes = -Int16
1
{-# INLINE allOnes #-}
msb :: Int16
msb = forall a. Bounded a => a
minBound
{-# INLINE msb #-}
lsb :: Int16
lsb = Int16
1
{-# INLINE lsb #-}
testMsb :: Int16 -> Bool
testMsb Int16
x = forall a. Bits a => a -> Int -> Bool
testBit Int16
x Int
15
{-# INLINE testMsb #-}
setMsb :: Int16 -> Int16
setMsb Int16
x = forall a. Bits a => a -> Int -> a
setBit Int16
x Int
15
{-# INLINE setMsb #-}
clearMsb :: Int16 -> Int16
clearMsb Int16
x = forall a. Bits a => a -> Int -> a
clearBit Int16
x Int
15
{-# INLINE clearMsb #-}
instance BinaryWord Int32 where
type UnsignedWord Int32 = Word32
type SignedWord Int32 = Int32
unsignedWord :: Int32 -> UnsignedWord Int32
unsignedWord = forall a b. (Integral a, Num b) => a -> b
fromIntegral
{-# INLINE unsignedWord #-}
signedWord :: Int32 -> SignedWord Int32
signedWord = forall a. a -> a
id
{-# INLINE signedWord #-}
#if WORD_SIZE_IN_BITS == 32
unwrappedAdd x y = hi `seq` lo `seq` (hi, lo)
where extX = if x < 0 then maxBound else 0
extY = if y < 0 then maxBound else 0
(hi', lo) = unsignedWord x `unwrappedAdd` unsignedWord y
hi = signedWord $ hi' + extX + extY
unwrappedMul x y = hi `seq` lo `seq` (hi, lo)
where extX = if x < 0 then negate y else 0
extY = if y < 0 then negate x else 0
(hi', lo) = unsignedWord x `unwrappedMul` unsignedWord y
hi = signedWord hi' + extX + extY
#else
unwrappedAdd :: Int32 -> Int32 -> (Int32, UnsignedWord Int32)
unwrappedAdd Int32
x Int32
y = Int32
hi seq :: forall a b. a -> b -> b
`seq` Word32
lo seq :: forall a b. a -> b -> b
`seq` (Int32
hi, Word32
lo)
where s :: Int64
s = forall a b. (Integral a, Num b) => a -> b
fromIntegral Int32
x forall a. Num a => a -> a -> a
+ forall a b. (Integral a, Num b) => a -> b
fromIntegral Int32
y ∷ Int64
lo :: Word32
lo = forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
s
hi :: Int32
hi = forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bits a => a -> Int -> a
shiftR Int64
s Int
32)
{-# INLINE unwrappedAdd #-}
unwrappedMul :: Int32 -> Int32 -> (Int32, UnsignedWord Int32)
unwrappedMul Int32
x Int32
y = Int32
hi seq :: forall a b. a -> b -> b
`seq` Word32
lo seq :: forall a b. a -> b -> b
`seq` (Int32
hi, Word32
lo)
where p :: Int64
p = forall a b. (Integral a, Num b) => a -> b
fromIntegral Int32
x forall a. Num a => a -> a -> a
* forall a b. (Integral a, Num b) => a -> b
fromIntegral Int32
y ∷ Int64
lo :: Word32
lo = forall a b. (Integral a, Num b) => a -> b
fromIntegral Int64
p
hi :: Int32
hi = forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bits a => a -> Int -> a
shiftR Int64
p Int
32)
{-# INLINE unwrappedMul #-}
#endif
leadingZeroes :: Int32 -> Int
leadingZeroes = forall w. BinaryWord w => w -> Int
leadingZeroes forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall w. BinaryWord w => w -> UnsignedWord w
unsignedWord
{-# INLINE leadingZeroes #-}
trailingZeroes :: Int32 -> Int
trailingZeroes = forall w. BinaryWord w => w -> Int
trailingZeroes forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall w. BinaryWord w => w -> UnsignedWord w
unsignedWord
{-# INLINE trailingZeroes #-}
allZeroes :: Int32
allZeroes = Int32
0
{-# INLINE allZeroes #-}
allOnes :: Int32
allOnes = -Int32
1
{-# INLINE allOnes #-}
msb :: Int32
msb = forall a. Bounded a => a
minBound
{-# INLINE msb #-}
lsb :: Int32
lsb = Int32
1
{-# INLINE lsb #-}
testMsb :: Int32 -> Bool
testMsb Int32
x = forall a. Bits a => a -> Int -> Bool
testBit Int32
x Int
31
{-# INLINE testMsb #-}
setMsb :: Int32 -> Int32
setMsb Int32
x = forall a. Bits a => a -> Int -> a
setBit Int32
x Int
31
{-# INLINE setMsb #-}
clearMsb :: Int32 -> Int32
clearMsb Int32
x = forall a. Bits a => a -> Int -> a
clearBit Int32
x Int
31
{-# INLINE clearMsb #-}
instance BinaryWord Int64 where
type UnsignedWord Int64 = Word64
type SignedWord Int64 = Int64
unsignedWord :: Int64 -> UnsignedWord Int64
unsignedWord = forall a b. (Integral a, Num b) => a -> b
fromIntegral
{-# INLINE unsignedWord #-}
signedWord :: Int64 -> SignedWord Int64
signedWord = forall a. a -> a
id
{-# INLINE signedWord #-}
unwrappedAdd :: Int64 -> Int64 -> (Int64, UnsignedWord Int64)
unwrappedAdd Int64
x Int64
y = SignedWord Word64
hi seq :: forall a b. a -> b -> b
`seq` UnsignedWord Word64
lo seq :: forall a b. a -> b -> b
`seq` (SignedWord Word64
hi, UnsignedWord Word64
lo)
where extX :: Word64
extX = if Int64
x forall a. Ord a => a -> a -> Bool
< Int64
0 then forall a. Bounded a => a
maxBound else Word64
0
extY :: Word64
extY = if Int64
y forall a. Ord a => a -> a -> Bool
< Int64
0 then forall a. Bounded a => a
maxBound else Word64
0
(Word64
hi', UnsignedWord Word64
lo) = forall w. BinaryWord w => w -> UnsignedWord w
unsignedWord Int64
x forall w. BinaryWord w => w -> w -> (w, UnsignedWord w)
`unwrappedAdd` forall w. BinaryWord w => w -> UnsignedWord w
unsignedWord Int64
y
hi :: SignedWord Word64
hi = forall w. BinaryWord w => w -> SignedWord w
signedWord forall a b. (a -> b) -> a -> b
$ Word64
hi' forall a. Num a => a -> a -> a
+ Word64
extX forall a. Num a => a -> a -> a
+ Word64
extY
unwrappedMul :: Int64 -> Int64 -> (Int64, UnsignedWord Int64)
unwrappedMul Int64
x Int64
y = Int64
hi seq :: forall a b. a -> b -> b
`seq` UnsignedWord Word64
lo seq :: forall a b. a -> b -> b
`seq` (Int64
hi, UnsignedWord Word64
lo)
where extX :: Int64
extX = if Int64
x forall a. Ord a => a -> a -> Bool
< Int64
0 then forall a. Num a => a -> a
negate Int64
y else Int64
0
extY :: Int64
extY = if Int64
y forall a. Ord a => a -> a -> Bool
< Int64
0 then forall a. Num a => a -> a
negate Int64
x else Int64
0
(Word64
hi', UnsignedWord Word64
lo) = forall w. BinaryWord w => w -> UnsignedWord w
unsignedWord Int64
x forall w. BinaryWord w => w -> w -> (w, UnsignedWord w)
`unwrappedMul` forall w. BinaryWord w => w -> UnsignedWord w
unsignedWord Int64
y
hi :: Int64
hi = forall w. BinaryWord w => w -> SignedWord w
signedWord Word64
hi' forall a. Num a => a -> a -> a
+ Int64
extX forall a. Num a => a -> a -> a
+ Int64
extY
leadingZeroes :: Int64 -> Int
leadingZeroes = forall w. BinaryWord w => w -> Int
leadingZeroes forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall w. BinaryWord w => w -> UnsignedWord w
unsignedWord
{-# INLINE leadingZeroes #-}
trailingZeroes :: Int64 -> Int
trailingZeroes = forall w. BinaryWord w => w -> Int
trailingZeroes forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall w. BinaryWord w => w -> UnsignedWord w
unsignedWord
{-# INLINE trailingZeroes #-}
allZeroes :: Int64
allZeroes = Int64
0
{-# INLINE allZeroes #-}
allOnes :: Int64
allOnes = -Int64
1
{-# INLINE allOnes #-}
msb :: Int64
msb = forall a. Bounded a => a
minBound
{-# INLINE msb #-}
lsb :: Int64
lsb = Int64
1
{-# INLINE lsb #-}
testMsb :: Int64 -> Bool
testMsb Int64
x = forall a. Bits a => a -> Int -> Bool
testBit Int64
x Int
63
{-# INLINE testMsb #-}
setMsb :: Int64 -> Int64
setMsb Int64
x = forall a. Bits a => a -> Int -> a
setBit Int64
x Int
63
{-# INLINE setMsb #-}
clearMsb :: Int64 -> Int64
clearMsb Int64
x = forall a. Bits a => a -> Int -> a
clearBit Int64
x Int
63
{-# INLINE clearMsb #-}