packages feed

bits 0.5.3 → 0.6

raw patch · 4 files changed

+92/−10 lines, 4 filesdep ~mtldep ~transformersPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: mtl, transformers

API changes (from Hackage documentation)

+ Data.Bits.Extras: unsafeOneBits :: Bits b => b
+ Data.Bits.Extras: word32Log2 :: Word32 -> Int
- Data.Bits.Extras: oneBits :: Bits b => b
+ Data.Bits.Extras: oneBits :: FiniteBits b => b

Files

CHANGELOG.markdown view
@@ -1,3 +1,14 @@+0.6 [2021.11.07]+----------------+* Allow building with GHC 9.2.1.+* The `Data.Bits.Extras.oneBits` function now matches the implementation of the+  `oneBits` function from `base`'s `Data.Bits` module. This is a breaking+  change since the constraint has been strengthened from `Bits` to+  `FiniteBits`. If you need to invoke `oneBits` on a data type that does not+  have a `FiniteBits` instance (e.g., `Integer`), use the newly added+  `unsafeOneBits` function instead.+* Generalize `log2` to all `Integral` types with `base` >= 4.15 (GHC >= 9.0).+ 0.5.3 [2021.02.17] ------------------ * The build-type has been changed from `Custom` to `Simple`.
bits.cabal view
@@ -1,6 +1,6 @@ name:          bits category:      Data, Serialization-version:       0.5.3+version:       0.6 license:       BSD3 cabal-version: >= 1.10 license-file:  LICENSE@@ -17,8 +17,10 @@              , GHC == 8.2.2              , GHC == 8.4.4              , GHC == 8.6.5-             , GHC == 8.8.3-             , GHC == 8.10.1+             , GHC == 8.8.4+             , GHC == 8.10.7+             , GHC == 9.0.1+             , GHC == 9.2.1 synopsis:      Various bit twiddling and bitwise serialization primitives description:   Various bit twiddling and bitwise serialization primitives. 
src/Data/Bits/Coded.hs view
@@ -46,7 +46,7 @@ } deriving (Eq, Ord, Read, Show, Num, Integral, Real, Enum)  ones :: Integer-ones = oneBits `unsafeShiftL` 1+ones = unsafeOneBits `unsafeShiftL` 1 instance Integral n => Coded (Unary n) where   encode (Unary n) = putBitsFrom (fromIntegral n) ones   decode = do b <- getBit
src/Data/Bits/Extras.hs view
@@ -20,6 +20,11 @@ module Data.Bits.Extras   ( Ranked(..)   , log2+#if __GLASGOW_HASKELL__ >= 900+  , integerLog2+  , wordLog2+#endif+  , word32Log2   , msb   , w8   , w16@@ -28,6 +33,7 @@   , assignBit   , zeroBits   , oneBits+  , unsafeOneBits   , srl   ) where @@ -37,10 +43,49 @@ import Foreign.Ptr import Foreign.Storable import GHC.Base+#if __GLASGOW_HASKELL__ >= 900+import Control.Exception+import GHC.Integer.Logarithms+#endif --- TODO: generalize to 64 bits, etc.+-- $setup+-- >>> import Data.Bits (Bits(..))+-- >>> import Data.Word (Word)++#if __GLASGOW_HASKELL__ >= 900++-- | Calculate the integer base 2 logarithm. The argument must be strictly+-- positive. On GHC 9.0 or later, the argument type is generalized from+-- 'Word32' to any 'Integral' type.+log2 :: Integral a => a -> Int+log2 = integerLog2 . toInteger+{-# NOINLINE [1] log2 #-}+{-# RULES+"log2/Integer->Int" log2 = integerLog2 :: Integer -> Int+"log2/Word->Int" log2 = wordLog2 :: Word -> Int+"log2/Word32->Int" log2 = word32Log2 :: Word32 -> Int+  #-}++integerLog2 :: Integer -> Int+integerLog2 n+  | n > 0 = I# (integerLog2# n)+  | otherwise = throw Overflow+{-# INLINE integerLog2 #-}++wordLog2 :: Word -> Int+wordLog2 (W# n) = I# (wordLog2# n)+{-# INLINE wordLog2 #-}++#else+ log2 :: Word32 -> Int-log2 !n0 = fromIntegral $ go (unsafeShiftR (n5 * 0x7C4ACDD) 27) where+log2 = word32Log2+{-# INLINE log2 #-}++#endif++word32Log2 :: Word32 -> Int+word32Log2 !n0 = fromIntegral $ go (unsafeShiftR (n5 * 0x7C4ACDD) 27) where   go :: Word32 -> Word8   go !i = inlinePerformIO $ peekElemOff debruijn_log32 (fromIntegral i)   !n1 = n0 .|. unsafeShiftR n0 1@@ -48,7 +93,7 @@   !n3 = n2 .|. unsafeShiftR n2 4   !n4 = n3 .|. unsafeShiftR n3 8   !n5 = n4 .|. unsafeShiftR n4 16-{-# INLINE log2 #-}+{-# INLINE word32Log2 #-}  class (Num t, FiniteBits t) => Ranked t where   -- | Calculate the least significant set bit using a debruijn multiplication table.@@ -200,14 +245,38 @@ assignBit b n False = b `clearBit` n {-# INLINE assignBit #-} -oneBits :: Bits b => b-oneBits  = complement zeroBits+#if !(MIN_VERSION_base(4,16,0))+-- | A more concise version of @complement zeroBits@.+--+-- >>> complement (zeroBits :: Word) == (oneBits :: Word)+-- True+--+-- >>> complement (oneBits :: Word) == (zeroBits :: Word)+-- True+--+-- = Note+--+-- The constraint on 'oneBits' is arguably too strong. However, as some types+-- (such as 'Natural') have undefined 'complement', this is the only safe+-- choice.+oneBits :: FiniteBits b => b+oneBits = unsafeOneBits+#endif +-- | A version of 'oneBits' that weakens the context from 'FiniteBits' to+-- 'Bits'. This is unsafe because there are some data types with 'Bits'+-- instances that have undefined 'complement', such as 'Natural'. Nevertheless,+-- it is sometimes useful to call this function on data types without+-- 'FiniteBits' instances (e.g., 'Integer'), so this function is provided as a+-- convenience.+unsafeOneBits :: Bits b => b+unsafeOneBits = complement zeroBits+ -- | Shift Right Logical (i.e., without sign extension) -- -- /NB:/ When used on negative 'Integer's, hilarity may ensue. srl :: Bits b => b -> Int -> b-srl b n = (b `shiftR` n) .&. rotateR (oneBits `shiftL` n) n+srl b n = (b `shiftR` n) .&. rotateR (unsafeOneBits `shiftL` n) n {-# INLINE srl #-}  ------------------------------------------------------------------------------