1 {-# OPTIONS -fno-implicit-prelude #-}
2 -----------------------------------------------------------------------------
5 -- Copyright : (c) The University of Glasgow 2001
6 -- License : BSD-style (see the file libraries/base/LICENSE)
8 -- Maintainer : libraries@haskell.org
9 -- Stability : experimental
10 -- Portability : portable
12 -- This module defines bitwise operations for signed and unsigned
13 -- integers. Instances of the class 'Bits' for the 'Int' and
14 -- 'Integer' types are available from this module, and instances for
15 -- explicitly sized integral types are available from the
16 -- "Int" and "Word" modules.
18 -----------------------------------------------------------------------------
23 (.&.), (.|.), xor, -- :: a -> a -> a
24 complement, -- :: a -> a
25 shift, -- :: a -> Int -> a
26 rotate, -- :: a -> Int -> a
28 setBit, -- :: a -> Int -> a
29 clearBit, -- :: a -> Int -> a
30 complementBit, -- :: a -> Int -> a
31 testBit, -- :: a -> Int -> Bool
32 bitSize, -- :: a -> Int
33 isSigned, -- :: a -> Bool
35 -- * Shifts and rotates
37 shiftL, shiftR, -- :: Bits a => a -> Int -> a
38 rotateL, rotateR -- :: Bits a => a -> Int -> a
42 -- instance Bits Integer
45 -- Defines the @Bits@ class containing bit-based operations.
46 -- See library document for details on the semantics of the
47 -- individual operations.
49 #ifdef __GLASGOW_HASKELL__
56 infixl 8 `shift`, `rotate`, `shiftL`, `shiftR`, `rotateL`, `rotateR`
62 The 'Bits' class defines bitwise operations over integral types.
64 * Bits are numbered from 0 with bit 0 being the least
67 class Num a => Bits a where
77 {-| Reverse all the bits in the argument -}
80 {-| Signed shift the argument left by the specified number of bits.
81 Right shifts are specified by giving a negative value. -}
82 shift :: a -> Int -> a
84 -- An instance can define either this unified shift or shiftL+shiftR,
85 -- depending on which is more convenient for the type in question.
86 x `shift` i | i<0 = x `shiftR` (-i)
90 {-| Signed rotate the argument left by the specified number of bits.
91 Right rotates are specified by giving a negative value.
93 'rotate' is well defined only if 'bitSize' is also well defined
94 ('bitSize' is undefined for 'Integer', for example).
96 rotate :: a -> Int -> a
99 -- Rotation can be implemented in terms of two shifts, but care is
100 -- needed for negative values. This suggested implementation assumes
101 -- 2's-complement arithmetic. It is commented out because it would
102 -- require an extra context (Ord a) on the signature of 'rotate'.
103 x `rotate` i | i<0 && isSigned x && x<0
104 = let left = i+bitSize x in
105 ((x `shift` i) .&. complement ((-1) `shift` left))
107 | i<0 = (x `shift` i) .|. (x `shift` (i+bitSize x))
109 | i>0 = (x `shift` i) .|. (x `shift` (i-bitSize x))
112 -- | @bit i@ is a value with the @i@th bit set
115 -- | @x \`setBit\` i@ is the same as @x .|. bit i@
116 setBit :: a -> Int -> a
118 -- | @x \`clearBit\` i@ is the same as @x .&. complement (bit i)@
119 clearBit :: a -> Int -> a
121 -- | @x \`complementBit\` i@ is the same as @x \`xor\` bit i@
122 complementBit :: a -> Int -> a
124 -- | Return 'True' if the @n@th bit of the argument is 1
125 testBit :: a -> Int -> Bool
127 {-| Return the number of bits in the type of the argument. The actual
128 value of the argument is ignored -}
131 {-| Return 'True' if the argument is a signed type. The actual
132 value of the argument is ignored -}
133 isSigned :: a -> Bool
136 x `setBit` i = x .|. bit i
137 x `clearBit` i = x .&. complement (bit i)
138 x `complementBit` i = x `xor` bit i
139 x `testBit` i = (x .&. bit i) /= 0
142 -- These functions might sometimes be more convenient than the unified
143 -- versions 'shift' and 'rotate'.
145 shiftL, shiftR :: a -> Int -> a
146 rotateL, rotateR :: a -> Int -> a
147 x `shiftL` i = x `shift` i
148 x `shiftR` i = x `shift` (-i)
149 x `rotateL` i = x `rotate` i
150 x `rotateR` i = x `rotate` (-i)
152 #ifdef __GLASGOW_HASKELL__
153 instance Bits Int where
154 (I# x#) .&. (I# y#) = I# (word2Int# (int2Word# x# `and#` int2Word# y#))
155 (I# x#) .|. (I# y#) = I# (word2Int# (int2Word# x# `or#` int2Word# y#))
156 (I# x#) `xor` (I# y#) = I# (word2Int# (int2Word# x# `xor#` int2Word# y#))
157 complement (I# x#) = I# (word2Int# (int2Word# x# `xor#` int2Word# (-1#)))
158 (I# x#) `shift` (I# i#)
159 | i# >=# 0# = I# (x# `iShiftL#` i#)
160 | otherwise = I# (x# `iShiftRA#` negateInt# i#)
161 (I# x#) `rotate` (I# i#) =
162 I# (word2Int# ((x'# `shiftL#` i'#) `or#`
163 (x'# `shiftRL#` (wsib -# i'#))))
166 i'# = word2Int# (int2Word# i# `and#` int2Word# (wsib -# 1#))
167 wsib = WORD_SIZE_IN_BITS# {- work around preprocessor problem (??) -}
168 bitSize _ = WORD_SIZE_IN_BITS
171 instance Bits Integer where
172 (S# x) .&. (S# y) = S# (word2Int# (int2Word# x `and#` int2Word# y))
173 x@(S# _) .&. y = toBig x .&. y
174 x .&. y@(S# _) = x .&. toBig y
175 (J# s1 d1) .&. (J# s2 d2) =
176 case andInteger# s1 d1 s2 d2 of
179 (S# x) .|. (S# y) = S# (word2Int# (int2Word# x `or#` int2Word# y))
180 x@(S# _) .|. y = toBig x .|. y
181 x .|. y@(S# _) = x .|. toBig y
182 (J# s1 d1) .|. (J# s2 d2) =
183 case orInteger# s1 d1 s2 d2 of
186 (S# x) `xor` (S# y) = S# (word2Int# (int2Word# x `xor#` int2Word# y))
187 x@(S# _) `xor` y = toBig x `xor` y
188 x `xor` y@(S# _) = x `xor` toBig y
189 (J# s1 d1) `xor` (J# s2 d2) =
190 case xorInteger# s1 d1 s2 d2 of
193 complement (S# x) = S# (word2Int# (int2Word# x `xor#` int2Word# (0# -# 1#)))
194 complement (J# s d) = case complementInteger# s d of (# s, d #) -> J# s d
196 shift x i | i >= 0 = x * 2^i
197 | otherwise = x `div` 2^(-i)
199 rotate x i = shift x i -- since an Integer never wraps around
201 bitSize _ = error "Bits.bitSize(Integer)"
206 instance Bits Int where
207 (.&.) = nhc_primIntAnd
208 (.|.) = nhc_primIntOr
210 complement = nhc_primIntCompl
211 shiftL = nhc_primIntLsh
212 shiftR = nhc_primIntRsh
216 foreign import ccall nhc_primIntAnd :: Int -> Int -> Int
217 foreign import ccall nhc_primIntOr :: Int -> Int -> Int
218 foreign import ccall nhc_primIntXor :: Int -> Int -> Int
219 foreign import ccall nhc_primIntLsh :: Int -> Int -> Int
220 foreign import ccall nhc_primIntRsh :: Int -> Int -> Int
221 foreign import ccall nhc_primIntCompl :: Int -> Int
223 instance Bits Integer where
224 -- (.&.) a b = undefined
225 -- (.|.) a b = undefined
226 -- xor a b = undefined
228 x `shift` i | i<0 = x `div` (2^(-i))
231 x `rotate` i = x `shift` i -- an Integer never wraps
232 bitSize _ = error "Data.Bits: bitSize :: Integer -> Int"