module Math.SetCover.BitMap (
Map(..),
fromSet,
add, inc,
sub, dec,
intersectionSet,
differenceSet,
minimumSet,
) where
import qualified Math.SetCover.BitSet as BitSet
import qualified Math.SetCover.Bit as Bit
import Math.SetCover.BitSet (Set(Set))
import Math.SetCover.Bit (difference, xor, (.|.), (.&.))
import qualified Data.List.Reverse.StrictSpine as ListRev
import Data.Monoid (Monoid, mempty, mappend)
newtype Map bits = Map {unMap :: [bits]} deriving (Show)
instance (Bit.C bits) => Monoid (Map bits) where
mempty = Map []
mappend = add
fromSet :: Bit.C bits => Set bits -> Map bits
fromSet (Set x) = Map [x]
add :: Bit.C bits => Map bits -> Map bits -> Map bits
add (Map xs0) (Map ys0) =
let go c xs [] = unMap $ inc (Set c) (Map xs)
go c [] ys = unMap $ inc (Set c) (Map ys)
go c (x:xs) (y:ys) =
xor c (xor x y) : go (c.&.(x.|.y) .|. x.&.y) xs ys
in Map $ go Bit.empty xs0 ys0
inc :: Bit.C bits => Set bits -> Map bits -> Map bits
inc (Set xs0) (Map ys0) =
let go c [] = if c==Bit.empty then [] else [c]
go c (x:xs) = xor c x : go (c .&. x) xs
in Map $ go xs0 ys0
sub :: Bit.C bits => Map bits -> Map bits -> Map bits
sub (Map xs0) (Map ys0) =
let go c xs [] = normalize $ unMap $ dec (Set c) (Map xs)
go c [] ys =
if c==Bit.empty && all (==Bit.empty) ys
then []
else error "sub: underflow"
go c (x:xs) (y:ys) =
xor c (xor x y) : go (difference (c.|.y) x .|. c.&.y) xs ys
in Map $ go Bit.empty xs0 ys0
dec :: Bit.C bits => Set bits -> Map bits -> Map bits
dec (Set xs0) (Map ys0) =
let go c [] = if c==Bit.empty then [] else error "dec: underflow"
go c (x:xs) = xor c x : go (difference c x) xs
in Map $ go xs0 ys0
intersectionSet :: (Bit.C bits) => Map bits -> Set bits -> Map bits
intersectionSet (Map xs) (Set y) = Map $ normalize $ map (y.&.) xs
differenceSet :: (Bit.C bits) => Map bits -> Set bits -> Map bits
differenceSet (Map xs) (Set y) = Map $ normalize $ map (flip difference y) xs
normalize :: (Bit.C bits) => [bits] -> [bits]
normalize = ListRev.dropWhile (Bit.empty==)
minimumSet :: Bit.C bits => Set bits -> Map bits -> Set bits
minimumSet baseSet (Map xs) =
foldr
(\x mins ->
case BitSet.difference mins $ Set x of
newMins ->
if BitSet.null newMins
then mins
else newMins)
baseSet xs