massiv-0.3.0.0: tests/Data/Massiv/Array/MutableSpec.hs
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MonoLocalBinds #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
module Data.Massiv.Array.MutableSpec (spec) where
import Control.Concurrent.Async
import Control.Monad.ST
import Data.Functor.Identity
import Data.List as L
import Data.Massiv.Array.Mutable.Atomic
import Data.Massiv.Array.Unsafe
import Data.Massiv.CoreArbitrary as A
import Data.Proxy
prop_MapMapM :: (Show (Array r ix Int), Eq (Array r ix Int), Mutable r ix Int) =>
r -> Proxy ix -> Fun Int Int -> ArrTiny D ix Int -> Property
prop_MapMapM r _ f (ArrTiny arr) =
computeAs r (A.map (apply f) arr) === runIdentity (A.mapMR r (return . apply f) arr)
prop_iMapiMapM :: (Show (Array r ix Int), Eq (Array r ix Int), Mutable r ix Int) =>
r -> Proxy ix -> Fun (ix, Int) Int -> ArrTiny D ix Int -> Property
prop_iMapiMapM r _ f (ArrTiny arr) =
computeAs r (A.imap (curry (apply f)) arr) ===
runIdentity (A.imapMR r (\ix e -> return $ apply f (ix, e)) arr)
prop_generateMakeST ::
(Show (Array r ix Int), Eq (Array r ix Int), Mutable r ix Int)
=> r
-> Proxy ix
-> Arr r ix Int
-> Property
prop_generateMakeST _ _ (Arr arr) =
arr === runST (generateArrayS (getComp arr) (size arr) (return . evaluate' arr))
prop_generateMakeIO :: (Show (Array r ix Int), Eq (Array r ix Int), Mutable r ix Int) =>
r -> Proxy ix -> Arr r ix Int -> Property
prop_generateMakeIO _ _ (Arr arr) = monadicIO $ do
arr' <- run $ generateArray (getComp arr) (size arr) (evaluateM arr)
return (arr === arr')
prop_atomicModifyIntArrayMany :: ArrIx P Ix2 Int -> Array B Ix1 Int -> Property
prop_atomicModifyIntArrayMany (ArrIx arr ix) barr =
monadicIO $ do
xs <-
run $ do
marr <- thaw arr
mbarr' <- mapConcurrently (atomicModifyIntArray marr ix . const) barr
x <- A.read' marr ix
let xs = maybe (error "atomicModifyIntArray read'") toList (Prelude.sequenceA mbarr')
pure (x : xs)
return (L.sort (index' arr ix : toList barr) === L.sort xs)
prop_atomicReadIntArrayMany :: Array P Ix2 Int -> Array B Ix1 Ix2 -> Property
prop_atomicReadIntArrayMany arr bix = monadicIO $ do
run $ do
marr <- thaw arr
as :: Array N Ix1 (Maybe Int) <- forM bix (A.read marr)
as' <- forM bix (atomicReadIntArray marr)
pure (as === as')
prop_atomicWriteIntArrayMany :: Array P Ix2 Int -> Array B Ix1 Ix2 -> (Fun Ix2 Int) -> Property
prop_atomicWriteIntArrayMany arr bix f =
monadicIO $
run $ do
marr <- thaw arr
marr' <- unsafeThaw arr
bs :: Array N Ix1 Bool <- forM bix (\ix -> write marr ix (apply f ix))
bs' <- forM bix (\ix -> atomicWriteIntArray marr' ix (apply f ix))
arrRes <- unsafeFreeze (getComp arr) marr
arrRes' <- unsafeFreeze (getComp arr) marr'
pure (bs === bs' .&&. arrRes === arrRes')
prop_unfoldrList :: Sz1 -> Fun Word (Int, Word) -> Word -> Property
prop_unfoldrList sz1 f i =
conjoin $
L.zipWith
(===)
(A.toList (runST $ unfoldrPrimM_ @P Seq sz1 (pure . apply f) i))
(L.unfoldr (Just . apply f) i)
prop_unfoldrReverseUnfoldl :: Sz1 -> Fun Word (Int, Word) -> Word -> Property
prop_unfoldrReverseUnfoldl sz1 f i =
runST (unfoldrPrimM_ @P Seq sz1 (pure . apply f) i) ===
rev (runST (unfoldlPrimM_ @P Seq sz1 (pure . swapTuple . apply f) i))
where swapTuple (x, y) = (y, x)
rev a = computeAs P $ backpermute' sz1 (\ix1 -> unSz sz1 - ix1 - 1) a
mutableSpec ::
( Show r
, Show (Array r Ix3 Int)
, Show (Array r Ix1 Int)
, Show (Array r Ix2 Int)
, Eq (Array r Ix3 Int)
, Eq (Array r Ix1 Int)
, Eq (Array r Ix2 Int)
, Mutable r Ix3 Int
, Mutable r Ix1 Int
, Mutable r Ix2 Int
, Construct r Ix3 Int
, Construct r Ix1 Int
, Construct r Ix2 Int
)
=> r
-> SpecWith ()
mutableSpec r =
describe (show r) $ do
describe "map == mapM" $ do
it "Ix1" $ property $ prop_MapMapM r (Proxy :: Proxy Ix1)
it "Ix2" $ property $ prop_MapMapM r (Proxy :: Proxy Ix2)
it "Ix3" $ property $ prop_MapMapM r (Proxy :: Proxy Ix3)
describe "imap == imapM" $ do
it "Ix1" $ property $ prop_iMapiMapM r (Proxy :: Proxy Ix1)
it "Ix2T" $ property $ prop_iMapiMapM r (Proxy :: Proxy Ix2)
it "Ix3T" $ property $ prop_iMapiMapM r (Proxy :: Proxy Ix3)
describe "makeArray == generateArrayST" $ do
it "Ix1" $ property $ prop_generateMakeST r (Proxy :: Proxy Ix1)
it "Ix2" $ property $ prop_generateMakeST r (Proxy :: Proxy Ix2)
it "Ix3" $ property $ prop_generateMakeST r (Proxy :: Proxy Ix3)
describe "makeArray == generateArrayIO" $ do
it "Ix1" $ property $ prop_generateMakeIO r (Proxy :: Proxy Ix1)
it "Ix2" $ property $ prop_generateMakeIO r (Proxy :: Proxy Ix2)
it "Ix3" $ property $ prop_generateMakeIO r (Proxy :: Proxy Ix3)
generateSpec :: Spec
generateSpec = do
mutableSpec P
mutableSpec S
mutableSpec U
mutableSpec B
mutableSpec N
spec :: Spec
spec = do
describe "GenerateM" generateSpec
describe "AtomicIntArraySpec" $ do
it "atomicReadIntArrayMany" $ property prop_atomicReadIntArrayMany
it "atomicWriteIntArrayMany" $ property prop_atomicWriteIntArrayMany
it "atomicModifyIntArrayMany" $ property prop_atomicModifyIntArrayMany
describe "Unfolding" $ do
it "unfoldrList" $ property prop_unfoldrList
it "unfoldrReverseUnfoldl" $ property prop_unfoldrReverseUnfoldl