{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE TypeApplications #-}

module Data.Set.Word8
  ( Set
  , member
  , null
  , size
  , empty
  , singleton
  , union
  , insert
  ) where

import Prelude hiding (lookup, null)

import Data.Bits (bit, popCount, testBit, (.|.))
import Data.WideWord (Word256)
import Data.Word (Word8)

-- | A map whose keys are 8-bit words.
newtype Set = Set Word256

-- | Is the passed map empty?
null :: Set -> Bool
null :: Set -> Bool
null Set
m = Set -> Int
size Set
m Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0

-- | The number of elements the passed map contains.
size :: Set -> Int
size :: Set -> Int
size (Set Word256
keys) = Word256 -> Int
forall a. Bits a => a -> Int
popCount Word256
keys

empty :: Set
empty :: Set
empty = Word256 -> Set
Set Word256
0

singleton :: Word8 -> Set
singleton :: Word8 -> Set
singleton !Word8
k = Word256 -> Set
Set (Int -> Word256
forall a. Bits a => Int -> a
bit (forall a b. (Integral a, Num b) => a -> b
fromIntegral @Word8 @Int Word8
k))

member :: Word8 -> Set -> Bool
member :: Word8 -> Set -> Bool
member Word8
k (Set Word256
keys) =
  Word256 -> Int -> Bool
forall a. Bits a => a -> Int -> Bool
testBit Word256
keys (forall a b. (Integral a, Num b) => a -> b
fromIntegral @Word8 @Int Word8
k)

union :: Set -> Set -> Set
union :: Set -> Set -> Set
union (Set Word256
x) (Set Word256
y) = Word256 -> Set
Set (Word256
x Word256 -> Word256 -> Word256
forall a. Bits a => a -> a -> a
.|. Word256
y)

insert :: Word8 -> Set -> Set
insert :: Word8 -> Set -> Set
insert Word8
k Set
s = Set -> Set -> Set
union (Word8 -> Set
singleton Word8
k) Set
s