packages feed

bitwise-enum 1.0.0.1 → 1.0.0.2

raw patch · 4 files changed

+58/−28 lines, 4 filesdep ~aesonPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: aeson

API changes (from Hackage documentation)

Files

Data/Enum/Set/Base.hs view
@@ -157,7 +157,7 @@     deriving (Eq, Ord, Data, Storable, NFData, P.Prim, Unbox)
 
 newtype instance MVector s (EnumSet word a) = MV_EnumSet (P.MVector s (EnumSet word a))
-newtype instance Vector    (EnumSet word a) = V_EnumSet (P.Vector (EnumSet word a))
+newtype instance Vector    (EnumSet word a) = V_EnumSet  (P.Vector    (EnumSet word a))
 
 instance P.Prim word => M.MVector MVector (EnumSet word a) where
     basicLength (MV_EnumSet v) = M.basicLength v
@@ -566,13 +566,13 @@ -- | /O(1)/. The minimal element of a non-empty set.
 minimum :: ∀ w a. (FiniteBits w, Num w, Enum a)
         => EnumSet w a -> a
-minimum (EnumSet 0) = error "empty EnumSet"
+minimum (EnumSet 0) = errorEmpty
 minimum (EnumSet w) = toEnum $ lsb w
 
 -- | /O(1)/. The maximal element of a non-empty set.
 maximum :: ∀ w a. (FiniteBits w, Num w, Enum a)
         => EnumSet w a -> a
-maximum (EnumSet 0) = error "empty EnumSet"
+maximum (EnumSet 0) = errorEmpty
 maximum (EnumSet w) = toEnum $ msb w
 
 -- | /O(1)/. Delete the minimal element.
@@ -623,30 +623,21 @@   Utility functions
 --------------------------------------------------------------------}
 
+-- | Least significant bit. 
 lsb :: ∀ w. (FiniteBits w, Num w) => w -> Int
-lsb n0 = go 0 n0 $ finiteBitSize n0 `quot` 2
-  where
-    go b n 1 = case n .&. 1 of
-        0 -> 1 + b
-        _ -> b
-    go b n i = case n .&. (bit i - 1) of
-        0 -> go (i + b) (n `unsafeShiftR` i) (i `quot` 2)
-        _ -> go b       n                    (i `quot` 2)
+lsb = countTrailingZeros
 {-# INLINE lsb #-}
 
+-- | Most significant bit.
 msb :: ∀ w. (FiniteBits w, Num w) => w -> Int
-msb n0 = go 0 n0 $ finiteBitSize n0 `quot` 2
-  where
-    go b n 1 = case n .&. 2 of
-        0 -> b
-        _ -> 1 + b
-    go b n i = case n .&. (bit (i * 2) - bit i) of
-        0 -> go b       n                    (i `quot` 2)
-        _ -> go (i + b) (n `unsafeShiftR` i) (i `quot` 2)
+msb w = finiteBitSize w - 1 - countLeadingZeros w
 {-# INLINE msb #-}
 
+-- These folding algorithms are similar to those of [IntSet](https://hackage.haskell.org/package/containers-0.6.0.1/docs/src/Data.IntSet.Internal.html), but generalized to work with any FiniteBits type.
+
+-- | Left fold over bits.
 foldlBits :: ∀ w a. (FiniteBits w, Num w) => (a -> Int -> a) -> a -> w -> a
-foldlBits  f z w = let lb = lsb w in go lb z (w `unsafeShiftR` lb)
+foldlBits f z w = let lb = lsb w in go lb z (w `unsafeShiftR` lb)
   where
     go !_ acc 0 = acc
     go bi acc n
@@ -654,6 +645,7 @@       | otherwise     = go (bi + 1)    acc     (n `unsafeShiftR` 1)
 {-# INLINE foldlBits #-}
 
+-- | Left fold over bits. The accumulator is evaluated to WHNF at every step.
 foldlBits' :: ∀ w a. (FiniteBits w, Num w) => (a -> Int -> a) -> a -> w -> a
 foldlBits' f z w = let lb = lsb w in go lb z (w `unsafeShiftR` lb)
   where
@@ -663,6 +655,7 @@       | otherwise     = go (bi + 1)    acc     (n `unsafeShiftR` 1)
 {-# INLINE foldlBits' #-}
 
+-- | Right fold over bits.
 foldrBits :: ∀ w a. (FiniteBits w, Num w) => (Int -> a -> a) -> a -> w -> a
 foldrBits f z w = let lb = lsb w in go lb (w `unsafeShiftR` lb)
   where
@@ -672,6 +665,7 @@       | otherwise     =       go (bi + 1) (n `unsafeShiftR` 1)
 {-# INLINE foldrBits #-}
 
+-- | Right fold over bits. The accumulator is evaluated to WHNF at every step.
 foldrBits' :: ∀ w a. (FiniteBits w, Num w) => (Int -> a -> a) -> a -> w -> a
 foldrBits' f z w = let lb = lsb w in go lb (w `unsafeShiftR` lb)
   where
@@ -683,8 +677,11 @@ 
 fold1Aux :: ∀ w a. (Bits w, Num w, Enum a)
          => (w -> Int) -> (a -> w -> a) -> EnumSet w a -> a
-fold1Aux _      _ (EnumSet 0) = error "empty EnumSet"
+fold1Aux _      _ (EnumSet 0) = errorEmpty
 fold1Aux getBit f (EnumSet w) = f (toEnum gotBit) (clearBit w gotBit)
   where
     gotBit = getBit w
 {-# INLINE fold1Aux #-}
+
+errorEmpty :: a
+errorEmpty = error "Data.Enum.Set: empty EnumSet"
+ README.md view
@@ -0,0 +1,2 @@+# bitwise-enum+Bitwise operations on bounded enumerations.
bitwise-enum.cabal view
@@ -1,13 +1,13 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.31.2.+-- This file has been generated from package.yaml by hpack version 0.33.0. -- -- see: https://github.com/sol/hpack ----- hash: 9b82c027b0aa45bb8bc26748d7718c70bcdfee8ba5cd2f213ea3af492e424074+-- hash: 9237fd9d9cd252842f0b67b2fd19ebd650593bdbba3be2567dee83b5ff6288f2  name:           bitwise-enum-version:        1.0.0.1+version:        1.0.0.2 synopsis:       Bitwise operations on bounded enumerations description:    Bitwise operations on bounded enumerations.                 .@@ -38,7 +38,7 @@       ./   ghc-options: -Wall -Wcompat -Widentities -Wincomplete-uni-patterns -Wincomplete-record-updates -ferror-spans -funbox-small-strict-fields -O2   build-depends:-      aeson >=0.11 && <1.4.8+      aeson >=0.11 && <1.5.5     , array >=0.5.1 && <0.5.5     , base >=4.5 && <5     , deepseq >=1.1 && <1.4.5@@ -56,7 +56,7 @@   ghc-options: -Wall -Wcompat -Widentities -Wincomplete-uni-patterns -Wincomplete-record-updates -ferror-spans -funbox-small-strict-fields   build-depends:       QuickCheck >=2.13.2-    , aeson >=0.11 && <1.4.8+    , aeson >=0.11 && <1.5.5     , array >=0.5.1 && <0.5.5     , base     , bitwise-enum@@ -76,7 +76,7 @@       benchmarks   ghc-options: -Wall -Wcompat -Widentities -Wincomplete-uni-patterns -Wincomplete-record-updates -ferror-spans -funbox-small-strict-fields -rtsopts -threaded -with-rtsopts=-N -O2   build-depends:-      aeson >=0.11 && <1.4.8+      aeson >=0.11 && <1.5.5     , array >=0.5.1 && <0.5.5     , base     , bitwise-enum
tests/set-properties.hs view
@@ -1,9 +1,13 @@ {-# OPTIONS_GHC -fno-warn-orphans #-}
+{-# LANGUAGE BlockArguments             #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE MonadComprehensions        #-}
 
 import Prelude
 
-import Data.List ((\\), foldl', nub, sort)
+import Control.Applicative ((<|>))
+import Data.Foldable (foldl', foldr')
+import Data.List ((\\), nub, sort)
 import Data.Bits
 import Test.Framework
 import Test.Framework.Providers.QuickCheck2
@@ -42,6 +46,10 @@     , testProperty "foldl'" prop_foldl'
     , testProperty "foldr" prop_foldr
     , testProperty "foldr'" prop_foldr'
+    , testProperty "foldl_origin" prop_foldl_origin
+    , testProperty "foldl'_origin" prop_foldl'_origin
+    , testProperty "foldr_origin" prop_foldr_origin
+    , testProperty "foldr'_origin" prop_foldr'_origin
       -- Special folds
     , testProperty "foldMap" prop_foldMap
     , testProperty "traverse" prop_traverse
@@ -192,6 +200,18 @@ prop_foldr' :: ES -> Bool
 prop_foldr' s = E.foldr' (:) [] s == E.toList s
 
+prop_foldl_origin :: Fun Key Bool -> ES -> Bool
+prop_foldl_origin = originHelper id E.foldl foldl
+
+prop_foldl'_origin :: Fun Key Bool -> ES -> Bool
+prop_foldl'_origin = originHelper id E.foldl' foldl'
+
+prop_foldr_origin :: Fun Key Bool -> ES -> Bool
+prop_foldr_origin = originHelper flip E.foldr foldr
+
+prop_foldr'_origin :: Fun Key Bool -> ES -> Bool
+prop_foldr'_origin = originHelper flip E.foldr' foldr'
+
 -- * Special folds
 
 prop_all :: Fun Key Bool -> ES -> Property
@@ -234,3 +254,14 @@ 
 prop_readShow :: ES -> Bool
 prop_readShow s = s == read (show s)
+
+-- * Utility functions
+
+originHelper :: ((Maybe Key -> Key -> Maybe Key) -> f)
+             -> (f -> Maybe Key -> ES -> Maybe Key)
+             -> (f -> Maybe Key -> [Key] -> Maybe Key)
+             -> Fun Key Bool -> ES -> Bool
+originHelper reorder fSet fList p s = 
+    fSet f Nothing s == fList f Nothing (E.toList s)
+  where
+    f = reorder \acc x -> acc <|> [x | apply p x]