module Data.ZCache (
ZSet(..), ZMap(..), zSet, zMap,
flipPos, zArray) where
import Data.Array.Unboxed
import Data.Word
import Data.Bits
import System.Random.Mersenne.Pure64
import Data.Set (Set)
import qualified Data.Set as Set
import Data.Map (Map)
import Data.List
import qualified Data.Map as Map
type ZArray a = UArray a Word64
makeRandom :: (PureMT,Int) -> Maybe (Word64,(PureMT,Int))
makeRandom (_,0) = Nothing
makeRandom (p,i) = Just (w,(p',i1)) where
(w,p') = randomWord64 p
zArray :: Ix a => Word64 -> (a,a) -> Int -> ZArray a
zArray seed dim l = listArray dim (unfoldr makeRandom (pureMT seed,l))
data ZSet a = ZSet Word64 (ZArray a) (Set Word64) deriving (Eq, Show)
zSet :: Ix a =>
Word64
-> (a,a)
-> Int
-> ZSet a
zSet seed dim l = ZSet (0::Word64) (zArray seed dim l) Set.empty
flipPos :: Ix a =>
a
-> ZSet a
-> Maybe (ZSet a)
flipPos x (ZSet c a s) = if Set.member c' s then Nothing else Just$ ZSet c' a (Set.insert c' s) where
c' = xor c (a!x)
data ZMap k v = ZMap Word64 (ZArray k) (Map Word64 v) deriving (Eq, Show)
zMap :: forall a b . Ix a =>
Word64
-> (a,a)
-> Int
-> ZMap a b
zMap seed dim l = ZMap (0::Word64) (zArray seed dim l) Map.empty
storePos :: Ix a =>
a
-> b
-> (ZMap a b)
-> Maybe (ZMap a b)
storePos k v (ZMap c a m) = if Map.member c' m then Nothing else Just$ ZMap c' a (Map.insert c' v m) where
c' = xor c (a!k)