packages feed

bitvec-1.0.0.0: test/Tests/SetOps.hs

module Tests.SetOps where

import Support ()

import Data.Bit
import Data.Bits
import Data.List.NonEmpty (NonEmpty(..))
import qualified Data.Vector.Unboxed as U
import Test.Tasty
import Test.Tasty.QuickCheck hiding ((.&.))

setOpTests :: TestTree
setOpTests = testGroup "Set operations"
    [ testProperty "union"          prop_union_def
    , testProperty "intersection"   prop_intersection_def
    , testProperty "difference"     prop_difference_def
    , testProperty "symDiff"        prop_symDiff_def

    , testProperty "unions"         prop_unions_def
    , testProperty "intersections"  prop_unions_def

    , testProperty "invert"         prop_invert_def

    , testProperty "select"         prop_select_def
    , testProperty "exclude"        prop_exclude_def

    , testProperty "selectBits"     prop_selectBits_def
    , testProperty "excludeBits"    prop_excludeBits_def

    , testProperty "countBits"      prop_countBits_def
    ]

union :: U.Vector Bit -> U.Vector Bit -> U.Vector Bit
union = zipBits (.|.)

prop_union_def :: U.Vector Bit -> U.Vector Bit -> Property
prop_union_def xs ys
    =  U.toList (union xs ys)
    === zipWith (.|.) (U.toList xs) (U.toList ys)

intersection :: U.Vector Bit -> U.Vector Bit -> U.Vector Bit
intersection = zipBits (.&.)

prop_intersection_def :: U.Vector Bit -> U.Vector Bit -> Property
prop_intersection_def xs ys
    =  U.toList (intersection xs ys)
    === zipWith (.&.) (U.toList xs) (U.toList ys)

difference :: U.Vector Bit -> U.Vector Bit -> U.Vector Bit
difference = zipBits (\a b -> a .&. complement b)

prop_difference_def :: U.Vector Bit -> U.Vector Bit -> Property
prop_difference_def xs ys
    =  U.toList (difference xs ys)
    === zipWith diff (U.toList xs) (U.toList ys)
    where
        diff x y = x .&. complement y

symDiff :: U.Vector Bit -> U.Vector Bit -> U.Vector Bit
symDiff = zipBits xor

prop_symDiff_def :: U.Vector Bit -> U.Vector Bit -> Property
prop_symDiff_def xs ys
    =  U.toList (symDiff xs ys)
    === zipWith xor (U.toList xs) (U.toList ys)

unions :: NonEmpty (U.Vector Bit) -> U.Vector Bit
unions (x :| xs) = U.slice 0 l $ U.modify (go xs) x
    where
        l = minimum $ fmap U.length (x :| xs)
        go [] _ = pure ()
        go (y : ys) acc = do
            zipInPlace (.|.) y acc
            go ys acc

prop_unions_def :: U.Vector Bit -> [U.Vector Bit] -> Property
prop_unions_def xs xss
    =   unions (xs :| xss)
    === foldr union xs xss

intersections :: NonEmpty (U.Vector Bit) -> U.Vector Bit
intersections (x :| xs) = U.slice 0 l $ U.modify (go xs) x
    where
        l = minimum $ fmap U.length (x :| xs)
        go [] _ = pure ()
        go (y : ys) acc = do
            zipInPlace (.&.) y acc
            go ys acc

prop_intersections_def :: U.Vector Bit -> [U.Vector Bit] -> Property
prop_intersections_def xs xss
    =   intersections (xs :| xss)
    === foldr intersection xs xss

prop_invert_def :: U.Vector Bit -> Bool
prop_invert_def xs
    =  U.toList (U.modify invertInPlace xs)
    == map complement (U.toList xs)

select :: U.Unbox a => U.Vector Bit -> U.Vector a -> [a]
select mask ws = U.toList (U.map snd (U.filter (unBit . fst) (U.zip mask ws)))

prop_select_def :: U.Vector Bit -> U.Vector Word -> Bool
prop_select_def xs ys
    =  select xs ys
    == [ x | (Bit True, x) <- zip (U.toList xs) (U.toList ys)]

exclude :: U.Unbox a => U.Vector Bit -> U.Vector a -> [a]
exclude mask ws = U.toList (U.map snd (U.filter (not . unBit . fst) (U.zip mask ws)))

prop_exclude_def :: U.Vector Bit -> U.Vector Word -> Bool
prop_exclude_def xs ys
    =  exclude xs ys
    == [ x | (Bit False, x) <- zip (U.toList xs) (U.toList ys)]

prop_selectBits_def :: U.Vector Bit -> U.Vector Bit -> Bool
prop_selectBits_def xs ys
    =  selectBits xs ys
    == U.fromList (select xs ys)

prop_excludeBits_def :: U.Vector Bit -> U.Vector Bit -> Bool
prop_excludeBits_def xs ys
    =  excludeBits xs ys
    == U.fromList (exclude xs ys)

prop_countBits_def :: U.Vector Bit -> Bool
prop_countBits_def xs
    =  countBits xs
    == U.length (selectBits xs xs)