如何在Haskell中的Integer上执行无符号/逻辑移位?

时间:2015-03-05 05:57:43

标签: haskell bit-shift

Data.Bits中的

shiftRIntegers执行算术移位。是否有标准的方法来进行逻辑转换?

我可以想到两个方法来做到这一点。取2 ^ n的商:

unsignedShiftR i n = i `quot` (2 ^ n)

另一种方法是在算术移位后屏蔽上n位(尽管我不确定你能获得掩码的位置)。

2 个答案:

答案 0 :(得分:3)

Int而言,标准的做法是将其转换为无符号类型并将其转移到那里:

import Data.Word

ushiftR :: Int -> Int -> Int
ushiftR n k = fromIntegral (fromIntegral n `shiftR` k :: Word)

答案 1 :(得分:2)

由于某些原因,它不包含在Data.Bits中,但有GHC primopuncheckedIShiftRL#。此外,GHC.Base会将更安全的版本导出为iShiftRL#

iShiftRL# :: Int# -> Int# -> Int#
a `iShiftRL#` b | isTrue# (b >=# WORD_SIZE_IN_BITS#) = 0#
                | otherwise                          = a `uncheckedIShiftRL#` b

我们可以使用不同数量的检查来包装GHC.Base版本或primop:

{-# 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"