shiftR
in Data.Bits does an arithmetic shift for Integers
. Is there a standard way to do a logical shift right?
I can think of two round about ways to do this. Take the quotient by 2^n:
unsignedShiftR i n = i `quot` (2 ^ n)
Another way would be to mask the upper n bits after an arithmetic shift (although I'm not sure you can get the position for the mask).
As far as Int
goes, the standard way of doing it is converting it to an unsigned type and shifting it there:
import Data.Word
ushiftR :: Int -> Int -> Int
ushiftR n k = fromIntegral (fromIntegral n `shiftR` k :: Word)
For some reason it's not included in Data.Bits
, but there's a GHC primop: uncheckedIShiftRL#
. Also, GHC.Base
exports a safer version as iShiftRL#
:
iShiftRL# :: Int# -> Int# -> Int#
a `iShiftRL#` b | isTrue# (b >=# WORD_SIZE_IN_BITS#) = 0#
| otherwise = a `uncheckedIShiftRL#` b
We can wrap either the GHC.Base
version or the primop with varying amounts of checking:
{-# LANGUAGE MagicHash #-}
import GHC.Base
import GHC.Prim
uncheckedIShiftRL :: Int -> Int -> Int
uncheckedIShiftRL (I# n) (I# i) = I# (uncheckedIShiftRL# n i)
unsafeIShiftRL :: Int -> Int -> Int
unsafeIShiftRL (I# n) (I# i) = I# (iShiftRL# n i)
iShiftRL :: Int -> Int -> Int
iShiftRL (I# n) (I# i)
| isTrue# (i >=# 0#) = I# (iShiftRL# n i)
| otherwise = error "shift by negative amount"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With