Commit f1c593e0 authored by tibbe's avatar tibbe
Browse files

Add unsafeShift to Data.Bits

This allows shifting by a non-statically known amount without
introducing a branch (to check for "overflow").
parent c7e5902d
......@@ -33,6 +33,7 @@ module Data.Bits (
bitSize, -- :: a -> Int
isSigned, -- :: a -> Bool
shiftL, shiftR, -- :: a -> Int -> a
unsafeShiftL, unsafeShiftR, -- :: a -> Int -> a
rotateL, rotateR, -- :: a -> Int -> a
popCount -- :: a -> Int
)
......@@ -175,8 +176,19 @@ class (Eq a, Num a) => Bits a where
{-# INLINE shiftL #-}
x `shiftL` i = x `shift` i
{-| Shift the first argument right by the specified number of bits
(which must be non-negative).
{-| Shift the argument left by the specified number of bits. The
result is undefined for negative shift amounts and shift amounts
greater or equal to the 'bitSize'.
Defaults to 'shiftL' unless defined explicitly by an instance. -}
unsafeShiftL :: a -> Int -> a
{-# INLINE unsafeShiftL #-}
x `unsafeShiftL` i = x `shiftL` i
{-| Shift the first argument right by the specified number of bits. The
result is undefined for negative shift amounts and shift amounts
greater or equal to the 'bitSize'.
Right shifts perform sign extension on signed number types;
i.e. they fill the top bits with 1 if the @x@ is negative
and with 0 otherwise.
......@@ -188,6 +200,18 @@ class (Eq a, Num a) => Bits a where
{-# INLINE shiftR #-}
x `shiftR` i = x `shift` (-i)
{-| Shift the first argument right by the specified number of bits, which
must be non-negative an smaller than the number of bits in the type.
Right shifts perform sign extension on signed number types;
i.e. they fill the top bits with 1 if the @x@ is negative
and with 0 otherwise.
Defaults to 'shiftR' unless defined explicitly by an instance. -}
unsafeShiftR :: a -> Int -> a
{-# INLINE unsafeShiftR #-}
x `unsafeShiftR` i = x `shiftR` i
{-| Rotate the argument left by the specified number of bits
(which must be non-negative).
......@@ -235,7 +259,9 @@ instance Bits Int where
| i# >=# 0# = I# (x# `iShiftL#` i#)
| otherwise = I# (x# `iShiftRA#` negateInt# i#)
(I# x#) `shiftL` (I# i#) = I# (x# `iShiftL#` i#)
(I# x#) `unsafeShiftL` (I# i#) = I# (x# `uncheckedIShiftL#` i#)
(I# x#) `shiftR` (I# i#) = I# (x# `iShiftRA#` i#)
(I# x#) `unsafeShiftR` (I# i#) = I# (x# `uncheckedIShiftRA#` i#)
{-# INLINE rotate #-} -- See Note [Constant folding for rotate]
(I# x#) `rotate` (I# i#) =
......
......@@ -138,7 +138,9 @@ instance Bits Int8 where
| i# >=# 0# = I8# (narrow8Int# (x# `iShiftL#` i#))
| otherwise = I8# (x# `iShiftRA#` negateInt# i#)
(I8# x#) `shiftL` (I# i#) = I8# (narrow8Int# (x# `iShiftL#` i#))
(I8# x#) `unsafeShiftL` (I# i#) = I8# (narrow8Int# (x# `uncheckedIShiftL#` i#))
(I8# x#) `shiftR` (I# i#) = I8# (x# `iShiftRA#` i#)
(I8# x#) `unsafeShiftR` (I# i#) = I8# (x# `uncheckedIShiftRA#` i#)
(I8# x#) `rotate` (I# i#)
| i'# ==# 0#
= I8# x#
......@@ -283,7 +285,9 @@ instance Bits Int16 where
| i# >=# 0# = I16# (narrow16Int# (x# `iShiftL#` i#))
| otherwise = I16# (x# `iShiftRA#` negateInt# i#)
(I16# x#) `shiftL` (I# i#) = I16# (narrow16Int# (x# `iShiftL#` i#))
(I16# x#) `unsafeShiftL` (I# i#) = I16# (narrow16Int# (x# `uncheckedIShiftL#` i#))
(I16# x#) `shiftR` (I# i#) = I16# (x# `iShiftRA#` i#)
(I16# x#) `unsafeShiftR` (I# i#) = I16# (x# `uncheckedIShiftRA#` i#)
(I16# x#) `rotate` (I# i#)
| i'# ==# 0#
= I16# x#
......@@ -434,7 +438,10 @@ instance Bits Int32 where
| i# >=# 0# = I32# (narrow32Int# (x# `iShiftL#` i#))
| otherwise = I32# (x# `iShiftRA#` negateInt# i#)
(I32# x#) `shiftL` (I# i#) = I32# (narrow32Int# (x# `iShiftL#` i#))
(I32# x#) `unsafeShiftL` (I# i#) =
I32# (narrow32Int# (x# `uncheckedIShiftL#` i#))
(I32# x#) `shiftR` (I# i#) = I32# (x# `iShiftRA#` i#)
(I32# x#) `unsafeShiftR` (I# i#) = I32# (x# `uncheckedIShiftRA#` i#)
(I32# x#) `rotate` (I# i#)
| i'# ==# 0#
= I32# x#
......@@ -618,7 +625,9 @@ instance Bits Int64 where
| i# >=# 0# = I64# (x# `iShiftL64#` i#)
| otherwise = I64# (x# `iShiftRA64#` negateInt# i#)
(I64# x#) `shiftL` (I# i#) = I64# (x# `iShiftL64#` i#)
(I64# x#) `unsafeShiftL` (I# i#) = I64# (x# `uncheckedIShiftL64#` i#)
(I64# x#) `shiftR` (I# i#) = I64# (x# `iShiftRA64#` i#)
(I64# x#) `unsafeShiftR` (I# i#) = I64# (x# `uncheckedIShiftRA64#` i#)
(I64# x#) `rotate` (I# i#)
| i'# ==# 0#
= I64# x#
......@@ -745,7 +754,9 @@ instance Bits Int64 where
| i# >=# 0# = I64# (x# `iShiftL#` i#)
| otherwise = I64# (x# `iShiftRA#` negateInt# i#)
(I64# x#) `shiftL` (I# i#) = I64# (x# `iShiftL#` i#)
(I64# x#) `unsafeShiftL` (I# i#) = I64# (x# `uncheckedIShiftL#` i#)
(I64# x#) `shiftR` (I# i#) = I64# (x# `iShiftRA#` i#)
(I64# x#) `unsafeShiftR` (I# i#) = I64# (x# `uncheckedIShiftRA#` i#)
(I64# x#) `rotate` (I# i#)
| i'# ==# 0#
= I64# x#
......
......@@ -147,7 +147,9 @@ instance Bits Word where
| i# >=# 0# = W# (x# `shiftL#` i#)
| otherwise = W# (x# `shiftRL#` negateInt# i#)
(W# x#) `shiftL` (I# i#) = W# (x# `shiftL#` i#)
(W# x#) `unsafeShiftL` (I# i#) = W# (x# `uncheckedShiftL#` i#)
(W# x#) `shiftR` (I# i#) = W# (x# `shiftRL#` i#)
(W# x#) `unsafeShiftR` (I# i#) = W# (x# `uncheckedShiftRL#` i#)
(W# x#) `rotate` (I# i#)
| i'# ==# 0# = W# x#
| otherwise = W# ((x# `uncheckedShiftL#` i'#) `or#` (x# `uncheckedShiftRL#` (wsib -# i'#)))
......@@ -254,7 +256,10 @@ instance Bits Word8 where
| i# >=# 0# = W8# (narrow8Word# (x# `shiftL#` i#))
| otherwise = W8# (x# `shiftRL#` negateInt# i#)
(W8# x#) `shiftL` (I# i#) = W8# (narrow8Word# (x# `shiftL#` i#))
(W8# x#) `unsafeShiftL` (I# i#) =
W8# (narrow8Word# (x# `uncheckedShiftL#` i#))
(W8# x#) `shiftR` (I# i#) = W8# (x# `shiftRL#` i#)
(W8# x#) `unsafeShiftR` (I# i#) = W8# (x# `uncheckedShiftRL#` i#)
(W8# x#) `rotate` (I# i#)
| i'# ==# 0# = W8# x#
| otherwise = W8# (narrow8Word# ((x# `uncheckedShiftL#` i'#) `or#`
......@@ -388,7 +393,10 @@ instance Bits Word16 where
| i# >=# 0# = W16# (narrow16Word# (x# `shiftL#` i#))
| otherwise = W16# (x# `shiftRL#` negateInt# i#)
(W16# x#) `shiftL` (I# i#) = W16# (narrow16Word# (x# `shiftL#` i#))
(W16# x#) `unsafeShiftL` (I# i#) =
W16# (narrow16Word# (x# `uncheckedShiftL#` i#))
(W16# x#) `shiftR` (I# i#) = W16# (x# `shiftRL#` i#)
(W16# x#) `unsafeShiftR` (I# i#) = W16# (x# `uncheckedShiftRL#` i#)
(W16# x#) `rotate` (I# i#)
| i'# ==# 0# = W16# x#
| otherwise = W16# (narrow16Word# ((x# `uncheckedShiftL#` i'#) `or#`
......@@ -563,7 +571,10 @@ instance Bits Word32 where
| i# >=# 0# = W32# (narrow32Word# (x# `shiftL#` i#))
| otherwise = W32# (x# `shiftRL#` negateInt# i#)
(W32# x#) `shiftL` (I# i#) = W32# (narrow32Word# (x# `shiftL#` i#))
(W32# x#) `unsafeShiftL` (I# i#) =
W32# (narrow32Word# (x# `uncheckedShiftL#` i#))
(W32# x#) `shiftR` (I# i#) = W32# (x# `shiftRL#` i#)
(W32# x#) `unsafeShiftR` (I# i#) = W32# (x# `uncheckedShiftRL#` i#)
(W32# x#) `rotate` (I# i#)
| i'# ==# 0# = W32# x#
| otherwise = W32# (narrow32Word# ((x# `uncheckedShiftL#` i'#) `or#`
......@@ -690,7 +701,9 @@ instance Bits Word64 where
| i# >=# 0# = W64# (x# `shiftL64#` i#)
| otherwise = W64# (x# `shiftRL64#` negateInt# i#)
(W64# x#) `shiftL` (I# i#) = W64# (x# `shiftL64#` i#)
(W64# x#) `unsafeShiftL` (I# i#) = W64# (x# `uncheckedShiftL64#` i#)
(W64# x#) `shiftR` (I# i#) = W64# (x# `shiftRL64#` i#)
(W64# x#) `unsafeShiftR` (I# i#) = W64# (x# `uncheckedShiftRL64#` i#)
(W64# x#) `rotate` (I# i#)
| i'# ==# 0# = W64# x#
| otherwise = W64# ((x# `uncheckedShiftL64#` i'#) `or64#`
......@@ -797,7 +810,9 @@ instance Bits Word64 where
| i# >=# 0# = W64# (x# `shiftL#` i#)
| otherwise = W64# (x# `shiftRL#` negateInt# i#)
(W64# x#) `shiftL` (I# i#) = W64# (x# `shiftL#` i#)
(W64# x#) `unsafeShiftL` (I# i#) = W64# (x# `uncheckedShiftL#` i#)
(W64# x#) `shiftR` (I# i#) = W64# (x# `shiftRL#` i#)
(W64# x#) `unsafeShiftR` (I# i#) = W64# (x# `uncheckedShiftRL#` i#)
(W64# x#) `rotate` (I# i#)
| i'# ==# 0# = W64# x#
| otherwise = W64# ((x# `uncheckedShiftL#` i'#) `or#`
......
......@@ -101,6 +101,8 @@ instance Bits T where { \
(T x) `xor` (T y) = T (x `xor` y) ; \
complement (T x) = T (complement x) ; \
shift (T x) n = T (shift x n) ; \
unsafeShiftL (T x) n = T (unsafeShiftL x n) ; \
unsafeShiftR (T x) n = T (unsafeShiftR x n) ; \
rotate (T x) n = T (rotate x n) ; \
bit n = T (bit n) ; \
setBit (T x) n = T (setBit x n) ; \
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment