module Data.Array.Diff (
IOToDiffArray,
DiffArray,
DiffUArray,
module Data.Array.IArray,
newDiffArray, readDiffArray, replaceDiffArray
)
where
import Prelude
import Data.Ix
import Data.Array.Base
import Data.Array.IArray
import Data.Array.IO
import Foreign.Ptr ( Ptr, FunPtr )
import Foreign.StablePtr ( StablePtr )
import Data.Int ( Int8, Int16, Int32, Int64 )
import Data.Word ( Word, Word8, Word16, Word32, Word64 )
import System.IO.Unsafe ( unsafePerformIO )
import Control.Exception ( evaluate )
import Control.Concurrent.MVar ( MVar, newMVar, takeMVar, putMVar, readMVar )
newtype IOToDiffArray a i e =
DiffArray {varDiffArray :: MVar (DiffArrayData a i e)}
data DiffArrayData a i e = Current (a i e)
| Diff (IOToDiffArray a i e) [(Int, e)]
type DiffArray = IOToDiffArray IOArray
type DiffUArray = IOToDiffArray IOUArray
instance (Ix ix, Show ix, Show e) => Show (DiffArray ix e) where
showsPrec = showsIArray
instance (Ix ix, Show ix) => Show (DiffUArray ix Char) where
showsPrec = showsIArray
instance (Ix ix, Show ix) => Show (DiffUArray ix Int) where
showsPrec = showsIArray
instance (Ix ix, Show ix) => Show (DiffUArray ix Word) where
showsPrec = showsIArray
instance (Ix ix, Show ix) => Show (DiffUArray ix Float) where
showsPrec = showsIArray
instance (Ix ix, Show ix) => Show (DiffUArray ix Double) where
showsPrec = showsIArray
instance (Ix ix, Show ix) => Show (DiffUArray ix Int8) where
showsPrec = showsIArray
instance (Ix ix, Show ix) => Show (DiffUArray ix Int16) where
showsPrec = showsIArray
instance (Ix ix, Show ix) => Show (DiffUArray ix Int32) where
showsPrec = showsIArray
instance (Ix ix, Show ix) => Show (DiffUArray ix Int64) where
showsPrec = showsIArray
instance (Ix ix, Show ix) => Show (DiffUArray ix Word8) where
showsPrec = showsIArray
instance (Ix ix, Show ix) => Show (DiffUArray ix Word16) where
showsPrec = showsIArray
instance (Ix ix, Show ix) => Show (DiffUArray ix Word32) where
showsPrec = showsIArray
instance (Ix ix, Show ix) => Show (DiffUArray ix Word64) where
showsPrec = showsIArray
instance IArray (IOToDiffArray IOArray) e where
bounds a = unsafePerformIO $ boundsDiffArray a
numElements a = unsafePerformIO $ numElementsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray1` ies
instance IArray (IOToDiffArray IOUArray) Char where
bounds a = unsafePerformIO $ boundsDiffArray a
numElements a = unsafePerformIO $ numElementsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray2` ies
instance IArray (IOToDiffArray IOUArray) Int where
bounds a = unsafePerformIO $ boundsDiffArray a
numElements a = unsafePerformIO $ numElementsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray2` ies
instance IArray (IOToDiffArray IOUArray) Word where
bounds a = unsafePerformIO $ boundsDiffArray a
numElements a = unsafePerformIO $ numElementsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray2` ies
instance IArray (IOToDiffArray IOUArray) (Ptr a) where
bounds a = unsafePerformIO $ boundsDiffArray a
numElements a = unsafePerformIO $ numElementsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray2` ies
instance IArray (IOToDiffArray IOUArray) (FunPtr a) where
bounds a = unsafePerformIO $ boundsDiffArray a
numElements a = unsafePerformIO $ numElementsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray2` ies
instance IArray (IOToDiffArray IOUArray) Float where
bounds a = unsafePerformIO $ boundsDiffArray a
numElements a = unsafePerformIO $ numElementsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray2` ies
instance IArray (IOToDiffArray IOUArray) Double where
bounds a = unsafePerformIO $ boundsDiffArray a
numElements a = unsafePerformIO $ numElementsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray2` ies
instance IArray (IOToDiffArray IOUArray) (StablePtr a) where
bounds a = unsafePerformIO $ boundsDiffArray a
numElements a = unsafePerformIO $ numElementsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray2` ies
instance IArray (IOToDiffArray IOUArray) Int8 where
bounds a = unsafePerformIO $ boundsDiffArray a
numElements a = unsafePerformIO $ numElementsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray2` ies
instance IArray (IOToDiffArray IOUArray) Int16 where
bounds a = unsafePerformIO $ boundsDiffArray a
numElements a = unsafePerformIO $ numElementsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray2` ies
instance IArray (IOToDiffArray IOUArray) Int32 where
bounds a = unsafePerformIO $ boundsDiffArray a
numElements a = unsafePerformIO $ numElementsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray2` ies
instance IArray (IOToDiffArray IOUArray) Int64 where
bounds a = unsafePerformIO $ boundsDiffArray a
numElements a = unsafePerformIO $ numElementsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray2` ies
instance IArray (IOToDiffArray IOUArray) Word8 where
bounds a = unsafePerformIO $ boundsDiffArray a
numElements a = unsafePerformIO $ numElementsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray2` ies
instance IArray (IOToDiffArray IOUArray) Word16 where
bounds a = unsafePerformIO $ boundsDiffArray a
numElements a = unsafePerformIO $ numElementsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray2` ies
instance IArray (IOToDiffArray IOUArray) Word32 where
bounds a = unsafePerformIO $ boundsDiffArray a
numElements a = unsafePerformIO $ numElementsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray2` ies
instance IArray (IOToDiffArray IOUArray) Word64 where
bounds a = unsafePerformIO $ boundsDiffArray a
numElements a = unsafePerformIO $ numElementsDiffArray a
unsafeArray lu ies = unsafePerformIO $ newDiffArray lu ies
unsafeAt a i = unsafePerformIO $ a `readDiffArray` i
unsafeReplace a ies = unsafePerformIO $ a `replaceDiffArray2` ies
newDiffArray :: (MArray a e IO, Ix i)
=> (i,i)
-> [(Int, e)]
-> IO (IOToDiffArray a i e)
newDiffArray (l,u) ies = do
a <- newArray_ (l,u)
sequence_ [unsafeWrite a i e | (i, e) <- ies]
var <- newMVar (Current a)
return (DiffArray var)
readDiffArray :: (MArray a e IO, Ix i)
=> IOToDiffArray a i e
-> Int
-> IO e
a `readDiffArray` i = do
d <- readMVar (varDiffArray a)
case d of
Current a' -> unsafeRead a' i
Diff a' ies -> maybe (readDiffArray a' i) return (lookup i ies)
replaceDiffArray :: (MArray a e IO, Ix i)
=> IOToDiffArray a i e
-> [(Int, e)]
-> IO (IOToDiffArray a i e)
a `replaceDiffArray` ies = do
d <- takeMVar (varDiffArray a)
case d of
Current a' -> case ies of
[] -> do
putMVar (varDiffArray a) d
return a
_:_ -> do
diff <- sequence [do e <- unsafeRead a' i; return (i, e)
| (i, _) <- ies]
sequence_ [unsafeWrite a' i e | (i, e) <- ies]
var' <- newMVar (Current a')
putMVar (varDiffArray a) (Diff (DiffArray var') diff)
return (DiffArray var')
Diff _ _ -> do
putMVar (varDiffArray a) d
a' <- thawDiffArray a
sequence_ [unsafeWrite a' i e | (i, e) <- ies]
var' <- newMVar (Current a')
return (DiffArray var')
replaceDiffArray1 :: (MArray a e IO, Ix i)
=> IOToDiffArray a i e
-> [(Int, e)]
-> IO (IOToDiffArray a i e)
a `replaceDiffArray1` ies = do
mapM_ (evaluate . fst) ies
a `replaceDiffArray` ies
replaceDiffArray2 :: (MArray a e IO, Ix i)
=> IOToDiffArray a i e
-> [(Int, e)]
-> IO (IOToDiffArray a i e)
a `replaceDiffArray2` ies = do
mapM_ (\(a,b) -> do evaluate a; evaluate b) ies
a `replaceDiffArray` ies
boundsDiffArray :: (MArray a e IO, Ix ix)
=> IOToDiffArray a ix e
-> IO (ix,ix)
boundsDiffArray a = do
d <- readMVar (varDiffArray a)
case d of
Current a' -> getBounds a'
Diff a' _ -> boundsDiffArray a'
numElementsDiffArray :: (MArray a e IO, Ix ix)
=> IOToDiffArray a ix e
-> IO Int
numElementsDiffArray a
= do d <- readMVar (varDiffArray a)
case d of
Current a' -> getNumElements a'
Diff a' _ -> numElementsDiffArray a'
freezeDiffArray :: (MArray a e IO, Ix ix)
=> a ix e
-> IO (IOToDiffArray a ix e)
freezeDiffArray a = do
(l,u) <- getBounds a
a' <- newArray_ (l,u)
sequence_ [unsafeRead a i >>= unsafeWrite a' i | i <- [0 .. rangeSize (l,u) 1]]
var <- newMVar (Current a')
return (DiffArray var)
unsafeFreezeDiffArray :: (MArray a e IO, Ix ix)
=> a ix e
-> IO (IOToDiffArray a ix e)
unsafeFreezeDiffArray a = do
var <- newMVar (Current a)
return (DiffArray var)
thawDiffArray :: (MArray a e IO, Ix ix)
=> IOToDiffArray a ix e
-> IO (a ix e)
thawDiffArray a = do
d <- readMVar (varDiffArray a)
case d of
Current a' -> do
(l,u) <- getBounds a'
a'' <- newArray_ (l,u)
sequence_ [unsafeRead a' i >>= unsafeWrite a'' i | i <- [0 .. rangeSize (l,u) 1]]
return a''
Diff a' ies -> do
a'' <- thawDiffArray a'
sequence_ [unsafeWrite a'' i e | (i, e) <- ies]
return a''
unsafeThawDiffArray :: (MArray a e IO, Ix ix)
=> IOToDiffArray a ix e
-> IO (a ix e)
unsafeThawDiffArray a = do
d <- readMVar (varDiffArray a)
case d of
Current a' -> return a'
Diff a' ies -> do
a'' <- unsafeThawDiffArray a'
sequence_ [unsafeWrite a'' i e | (i, e) <- ies]
return a''