Commits

Iago Abal committed 16d7723

Generalize indexing functions to `Integral' types plus a few aliases

Comments (0)

Files changed (1)

Data/BitVector.hs

   , (<.), (<=.), (>.), (>=.)
   , slt, sle, sgt, sge
     -- * Indexing
-  , (@.), (@@)
+  , (@.), index
+  , (@@), extract
   , (!.)
   , least, most
   , msb, lsb, msb1
   , sdiv, srem, smod
   , lg2
   -- * List-like operations
-  , (#)
+  , (#), cat
   , zeroExtend, signExtend
   , foldl_, foldr_
   , reverse_
   -- * Bitwise operations
   , module Data.Bits
   , not_, nand, nor, xnor
-  , (<<.), (>>.), ashr, (<<<.), (>>>.)
+  , (<<.), shl, (>>.), shr, ashr
+  , (<<<.), rol, (>>>.), ror
   -- * Conversion
   , fromBits
   , toBits
 -- >>> [4]2 @. 1
 -- True
 --
-(@.) :: BV -> Int -> Bool
-(BV _ a) @. i = testBit a i
-{-# INLINE (@.) #-}
+(@.) :: Integral ix => BV -> ix -> Bool
+(BV _ a) @. i = testBit a (fromIntegral i)
+{-# SPECIALIZE (@.) :: BV -> Int     -> Bool #-}
+{-# SPECIALIZE (@.) :: BV -> Integer -> Bool #-}
+{-# INLINE[1] (@.) #-}
+
+-- | @index i a == a \@. i@
+--
+index :: Integral ix => ix -> BV -> Bool
+index = flip (@.)
+{-# INLINE index #-}
 
 -- | Bit-string extraction.
 --
 -- >>> [4]7 @@ (3,1)
 -- [3]3
 --
-(@@) :: BV -> (Int,Int) -> BV
+(@@) :: Integral ix => BV -> (ix,ix) -> BV
 (BV _ a) @@ (j,i) = assert (i >= 0 && j >= i) $
-    BV m $ (a `shiftR` i) `mod` 2^m
-  where m = j - i + 1
+    BV m $ (a `shiftR` i') `mod` 2^m
+  where i' = fromIntegral i
+        m  = fromIntegral $ j - i + 1
+{-# SPECIALIZE (@@) :: BV -> (Int,Int)         -> BV #-}
+{-# SPECIALIZE (@@) :: BV -> (Integer,Integer) -> BV #-}
+
+-- | @extract j i a == a \@\@ (j,i)@
+--
+extract :: Integral ix => ix -> ix -> BV -> BV
+extract j i = (@@ (j,i))
+{-# INLINE extract #-}
 
 -- | Reverse bit-indexing.
 --
 -- >>> [3]3 !. 0
 -- False
 --
-(!.) :: BV -> Int -> Bool
-(BV n a) !. i = assert (i < n) $ testBit a (n-i-1)
-{-# INLINE (!.) #-}
+(!.) :: Integral ix => BV -> ix -> Bool
+(BV n a) !. i = assert (i' < n) $ testBit a (n-i'-1)
+  where i' = fromIntegral i
+{-# SPECIALIZE (!.) :: BV -> Int     -> Bool #-}
+{-# SPECIALIZE (!.) :: BV -> Integer -> Bool #-}
+{-# INLINE[1] (!.) #-}
 
 -- | Take least significant bits.
 --
 -- @least m u == u \@\@ (m-1,0)@
 --
-least :: Int -> BV -> BV
+least :: Integral ix => ix -> BV -> BV
 least m (BV _ a) = assert (m >= 1) $
-  BV m $ a `mod` 2^m
+  BV m' $ a `mod` 2^m
+  where m' = fromIntegral m
+{-# SPECIALIZE least :: Int     -> BV -> BV #-}
+{-# SPECIALIZE least :: Integer -> BV -> BV #-}
 
 -- | Take most significant bits.
 --
 -- @most m u == u \@\@ (n-1,n-m)@
 --
-most :: Int -> BV -> BV
-most m (BV n a) = assert (m >= 1 && m <= n) $
-  BV m $ a `shiftR` (n-m)
+most :: Integral ix => ix -> BV -> BV
+most m (BV n a) = assert (m' >= 1 && m' <= n) $
+  BV m' $ a `shiftR` (n-m')
+  where m' = fromIntegral m
+{-# SPECIALIZE most :: Int     -> BV -> BV #-}
+{-# SPECIALIZE most :: Integer -> BV -> BV #-}
 
 -- | Most significant bit.
 --
 -- @msb u == u !. 0@
 --
 msb :: BV -> Bool
-msb = (!. 0)
+msb = (!. (0::Int))
 {-# INLINE msb #-}
 
 -- | Least significant bit.
 -- @lsb u == u \@. 0@
 --
 lsb :: BV -> Bool
-lsb = (@. 0)
+lsb = (@. (0::Int))
 {-# INLINE lsb #-}
 
 -- | Most significant 1-bit.
 (BV n a) # (BV m b) = BV (n + m) ((a `shiftL` m) + b)
 {-# INLINABLE (#) #-}
 
+-- | An alias for '(#)'.
+--
+cat :: BV -> BV -> BV
+cat = (#)
+
 -- | Logical extension.
 --
 -- >>> zeroExtend 3 [1]1
 -- [4]1
 --
-zeroExtend :: Int -> BV -> BV
-zeroExtend d (BV n a) = BV (n+d) a
-{-# INLINE zeroExtend #-}
+zeroExtend :: Integral size => size -> BV -> BV
+zeroExtend d (BV n a) = BV (n+d') a
+  where d' = fromIntegral d
+{-# SPECIALIZE zeroExtend :: Int     -> BV -> BV #-}
+{-# SPECIALIZE zeroExtend :: Integer -> BV -> BV #-}
+{-# INLINE[1] zeroExtend #-}
 
 -- | Arithmetic extension.
 --
 -- >>> signExtend 2 [2]3
 -- [4]15
 --
-signExtend :: Int -> BV -> BV
+signExtend :: Integral size => size -> BV -> BV
 signExtend d (BV n a)
-  | testBit a (n-1) = BV (n+d) $ (maxNat d `shiftL` n) + a
-  | otherwise       = BV (n+d) a
+  | testBit a (n-1) = BV (n+d') $ (maxNat d `shiftL` n) + a
+  | otherwise       = BV (n+d') a
+  where d' = fromIntegral d
+{-# SPECIALIZE signExtend :: Int     -> BV -> BV #-}
+{-# SPECIALIZE signExtend :: Integer -> BV -> BV #-}
+{-# INLINE[1] signExtend #-}
 
 -- |
 -- @foldl_ f z (fromBits [un, ..., u1, u0]) == ((((z \`f\` un) \`f\` ...) \`f\` u1) \`f\` u0)@
 --
 -- @replicate_ n == fromBits . concat . replicate n . toBits @
 --
-replicate_ :: Int -> BV -> BV
+replicate_ :: Integral size => size -> BV -> BV
 replicate_ 0 _ = error "Data.BitVector.replicate_: cannot replicate 0-times"
 replicate_ n u = go (n-1) u
   where go 0 !acc = acc
         go k !acc = go (k-1) (u # acc)
+{-# SPECIALIZE replicate_ :: Int     -> BV -> BV #-}
+{-# SPECIALIZE replicate_ :: Integer -> BV -> BV #-}
 
 -- | Split a bit-vector /k/ times.
 --
 -- >>> split 3 [4]15
 -- [[2]0,[2]3,[2]3]
 --
-split :: Int -> BV -> [BV]
+split :: Integral times => times -> BV -> [BV]
 split k (BV n a) = assert (k > 0) $
-  map (BV s) $ splitInteger s k a
-  where (q,r) = divMod n k
+  map (BV s) $ splitInteger s k' a
+  where k' = fromIntegral k
+        (q,r) = divMod n k'
         s = q + signum r
 
 -- | Split a bit-vector into /n/-wide pieces.
 -- >>> group_ 3 [4]15
 -- [[3]1,[3]7]
 --
-group_ :: Int -> BV -> [BV]
+group_ :: Integral size => size -> BV -> [BV]
 group_ s (BV n a) = assert (s > 0) $
-  map (BV s) $ splitInteger s k a
-  where (q,r) = divMod n s
+  map (BV s') $ splitInteger s' k a
+  where s' = fromIntegral s
+        (q,r) = divMod n s'
         k = q + signum r
 
-splitInteger :: Int -> Int -> Integer -> [Integer]
+splitInteger :: (Integral size, Integral times) => 
+                    size -> times -> Integer -> [Integer]
 splitInteger n = go []
-  where go acc 0 _ = acc
+  where n' = fromIntegral n
+        go acc 0 _ = acc
         go acc k a = go (v:acc) (k-1) a'
           where v  = a `mod` 2^n
-                a' = a `shiftR` n
-{-# INLINE splitInteger #-}
+                a' = a `shiftR` n'
+{-# SPECIALIZE splitInteger :: Int     -> Int     -> Integer -> [Integer] #-}
+{-# SPECIALIZE splitInteger :: Integer -> Integer -> Integer -> [Integer] #-}
+{-# INLINE[1] splitInteger #-}
 
 -- | Concatenate a list of bit-vectors.
 --
   | otherwise            = bv `shiftL` (fromIntegral k)
 {-# INLINE (<<.) #-}
 
+-- | Left shift.
+--
+shl :: BV -> BV -> BV
+shl = (<<.)
+{-# INLINE shl #-}
+
 -- | Logical right shift.
 --
 (>>.) :: BV -> BV -> BV
   | otherwise            = bv `shiftR` (fromIntegral k)
 {-# INLINE (>>.) #-}
 
+-- | Logical right shift.
+--
+shr :: BV -> BV -> BV
+shr = (>>.)
+{-# INLINE shr #-}
+
 -- | Arithmetic right shift
 --
 ashr :: BV -> BV -> BV
   where n' = fromIntegral n
 {-# INLINE (<<<.) #-}
 
+-- | Rotate left.
+--
+rol :: BV -> BV -> BV
+rol = (<<<.)
+{-# INLINE rol #-}
+
 -- | Rotate right.
 --
 (>>>.) :: BV -> BV -> BV
   where n' = fromIntegral n
 {-# INLINE (>>>.) #-}
 
+-- | Rotate right.
+--
+ror :: BV -> BV -> BV
+ror = (>>>.)
+{-# INLINE ror #-}
+
 ----------------------------------------------------------------------
 --- Conversion
 
 -- | Show a bit-vector in octal form.
 --
 showOct :: BV -> String
-showOct = ("0o" ++) . map (hexChar . nat) . group_ 3
+showOct = ("0o" ++) . map (hexChar . nat) . group_ (3::Int)
 
 -- | Show a bit-vector in hexadecimal form.
 --
 showHex :: BV -> String
-showHex = ("0x" ++) . map (hexChar . nat) . group_ 4
+showHex = ("0x" ++) . map (hexChar . nat) . group_ (4::Int)
 
 ----------------------------------------------------------------------
 --- Utilities
 
 -- | Greatest natural number representable with /n/ bits.
 --
-maxNat :: Integral a => Int -> a
+maxNat :: (Integral a, Integral b) => a -> b
 maxNat n = 2^n - 1
 {-# INLINE maxNat #-}
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.