{-# LANGUAGE CPP #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# OPTIONS_GHC -Wall #-}
#if !HAVE_VECTOR
module Test.QuickCheck.Classes.MVector where
#else
module Test.QuickCheck.Classes.MVector
( muvectorLaws
) where
import Control.Applicative
import Control.Monad (when)
import Control.Monad.ST
import Data.Functor
import Data.Proxy (Proxy)
import qualified Data.Vector.Generic.Mutable as MU (basicInitialize)
import qualified Data.Vector.Unboxed.Mutable as MU
import Test.QuickCheck hiding ((.&.))
import Test.QuickCheck.Property (Property)
import Test.QuickCheck.Classes.Common (Laws(..))
muvectorLaws :: (Eq a, MU.Unbox a, Arbitrary a, Show a) => Proxy a -> Laws
muvectorLaws p = Laws "Vector.Unboxed.MVector"
[ ("New-Length", newLength p)
, ("Replicate-Length", replicateLength p)
, ("Slice-Length", sliceLength p)
, ("Grow-Length", growLength p)
, ("Write-Read", writeRead p)
, ("Set-Read", setRead p)
, ("Replicate-Read", replicateRead p)
, ("Slice-Overlaps", sliceOverlaps p)
, ("Write-Copy-Read", writeCopyRead p)
, ("Write-Move-Read", writeMoveRead p)
, ("Write-Grow-Read", writeGrowRead p)
, ("Sliced-Write-Copy-Read", slicedWriteCopyRead p)
, ("Sliced-Write-Move-Read", slicedWriteMoveRead p)
, ("Sliced-Write-Grow-Read", slicedWriteGrowRead p)
, ("Write-InitializeAround-Read", writeInitializeAroundRead p)
, ("Write-ClearAround-Read", writeClearAroundRead p)
, ("Write-SetAround-Read", writeSetAroundRead p)
, ("Write-WriteAround-Read", writeWriteAroundRead p)
, ("Write-CopyAround-Read", writeCopyAroundRead p)
, ("Write-MoveAround-Read", writeMoveAroundRead p)
]
newLength :: forall a. (Eq a, MU.Unbox a, Arbitrary a, Show a) => Proxy a -> Property
newLength _ = property $ \(NonNegative len) -> do
(=== len) (runST $ MU.length <$> (MU.new len :: ST s (MU.MVector s a)))
replicateLength :: forall a. (Eq a, MU.Unbox a, Arbitrary a, Show a) => Proxy a -> Property
replicateLength _ = property $ \(a :: a) (NonNegative len) -> do
(=== len) (runST $ MU.length <$> MU.replicate len a)
sliceLength :: forall a. (Eq a, MU.Unbox a, Arbitrary a, Show a) => Proxy a -> Property
sliceLength _ = property $ \(NonNegative ix) (NonNegative subLen) (Positive excess) -> do
(=== subLen) (runST $ MU.length . MU.slice ix subLen <$> (MU.new (ix + subLen + excess) :: ST s (MU.MVector s a)))
growLength :: forall a. (Eq a, MU.Unbox a, Arbitrary a, Show a) => Proxy a -> Property
growLength _ = property $ \(Positive len) (Positive by) -> do
(=== len + by) $ runST $ do
arr <- MU.new len :: ST s (MU.MVector s a)
MU.length <$> MU.grow arr by
writeRead :: forall a. (Eq a, MU.Unbox a, Arbitrary a, Show a) => Proxy a -> Property
writeRead _ = property $ \(a :: a) (NonNegative ix) (Positive excess) -> do
(=== a) $ runST $ do
arr <- MU.new (ix + excess)
MU.write arr ix a
MU.read arr ix
setRead :: forall a. (Eq a, MU.Unbox a, Arbitrary a, Show a) => Proxy a -> Property
setRead _ = property $ \(a :: a) (NonNegative ix) (Positive excess) -> do
(=== a) $ runST $ do
arr <- MU.new (ix + excess)
MU.set arr a
MU.read arr ix
replicateRead :: forall a. (Eq a, MU.Unbox a, Arbitrary a, Show a) => Proxy a -> Property
replicateRead _ = property $ \(a :: a) (NonNegative ix) (Positive excess) -> do
(=== a) $ runST $ do
arr <- MU.replicate (ix + excess) a
MU.read arr ix
sliceOverlaps :: forall a. (Eq a, MU.Unbox a, Arbitrary a, Show a) => Proxy a -> Property
sliceOverlaps _ = property $ \(NonNegative i) (NonNegative ij) (NonNegative jk) (NonNegative kl) (NonNegative lm) -> do
let j = i + ij
k = j + jk
l = k + kl
m = l + lm
property $ runST $ do
arr <- MU.new (m + 1) :: ST s (MU.MVector s a)
let slice1 = MU.slice i (k - i + 1) arr
slice2 = MU.slice j (l - j + 1) arr
pure $ MU.overlaps slice1 slice2
writeCopyRead :: forall a. (Eq a, MU.Unbox a, Arbitrary a, Show a) => Proxy a -> Property
writeCopyRead _ = property $ \(a :: a) (NonNegative ix) (Positive excess) -> do
(=== a) $ runST $ do
src <- MU.new (ix + excess)
MU.write src ix a
dst <- MU.new (ix + excess)
MU.copy dst src
MU.clear src
MU.read dst ix
writeMoveRead :: forall a. (Eq a, MU.Unbox a, Arbitrary a, Show a) => Proxy a -> Property
writeMoveRead _ = property $ \(a :: a) (NonNegative ix) (Positive excess) -> do
(=== a) $ runST $ do
src <- MU.new (ix + excess)
MU.write src ix a
dst <- MU.new (ix + excess)
MU.move dst src
MU.clear src
MU.read dst ix
writeGrowRead :: forall a. (Eq a, MU.Unbox a, Arbitrary a, Show a) => Proxy a -> Property
writeGrowRead _ = property $ \(a :: a) (NonNegative ix) (Positive excess) (Positive by) -> do
(=== a) $ runST $ do
src <- MU.new (ix + excess)
MU.write src ix a
dst <- MU.grow src by
MU.clear src
MU.read dst ix
slicedWriteCopyRead :: forall a. (Eq a, MU.Unbox a, Arbitrary a, Show a) => Proxy a -> Property
slicedWriteCopyRead _ = property $ \(a :: a) (NonNegative ix) (Positive excess) beforeSrc afterSrc beforeDst afterDst -> do
(=== a) $ runST $ do
src <- newSlice beforeSrc afterSrc (ix + excess)
MU.write src ix a
dst <- newSlice beforeDst afterDst (ix + excess)
MU.copy dst src
MU.clear src
MU.read dst ix
slicedWriteMoveRead :: forall a. (Eq a, MU.Unbox a, Arbitrary a, Show a) => Proxy a -> Property
slicedWriteMoveRead _ = property $ \(a :: a) (NonNegative ix) (Positive excess) beforeSrc afterSrc beforeDst afterDst -> do
(=== a) $ runST $ do
src <- newSlice beforeSrc afterSrc (ix + excess)
MU.write src ix a
dst <- newSlice beforeDst afterDst (ix + excess)
MU.move dst src
MU.clear src
MU.read dst ix
slicedWriteGrowRead :: forall a. (Eq a, MU.Unbox a, Arbitrary a, Show a) => Proxy a -> Property
slicedWriteGrowRead _ = property $ \(a :: a) (NonNegative ix) (Positive excess) (Positive by) beforeSrc afterSrc -> do
(=== a) $ runST $ do
src <- newSlice beforeSrc afterSrc (ix + excess)
MU.write src ix a
dst <- MU.grow src by
MU.clear src
MU.read dst ix
writeInitializeAroundRead :: forall a. (Eq a, MU.Unbox a, Arbitrary a, Show a) => Proxy a -> Property
writeInitializeAroundRead _ = property $ \(a :: a) (NonNegative ix) (Positive excess) -> do
(=== a) $ runST $ do
arr <- MU.new (ix + excess)
MU.write arr ix a
when (ix > 0) $
MU.basicInitialize (MU.slice 0 ix arr)
when (excess > 1) $
MU.basicInitialize (MU.slice (ix + 1) (excess - 1) arr)
MU.read arr ix
writeClearAroundRead :: forall a. (Eq a, MU.Unbox a, Arbitrary a, Show a) => Proxy a -> Property
writeClearAroundRead _ = property $ \(a :: a) (NonNegative ix) (Positive excess) -> do
(=== a) $ runST $ do
arr <- MU.new (ix + excess)
MU.write arr ix a
when (ix > 0) $
MU.clear (MU.slice 0 ix arr)
when (excess > 1) $
MU.clear (MU.slice (ix + 1) (excess - 1) arr)
MU.read arr ix
writeSetAroundRead :: forall a. (Eq a, MU.Unbox a, Arbitrary a, Show a) => Proxy a -> Property
writeSetAroundRead _ = property $ \(a :: a) (b :: a) (NonNegative ix) (Positive excess) -> do
(=== a) $ runST $ do
arr <- MU.new (ix + excess)
MU.write arr ix a
when (ix > 0) $
MU.set (MU.slice 0 ix arr) b
when (excess > 1) $
MU.set (MU.slice (ix + 1) (excess - 1) arr) b
MU.read arr ix
writeWriteAroundRead :: forall a. (Eq a, MU.Unbox a, Arbitrary a, Show a) => Proxy a -> Property
writeWriteAroundRead _ = property $ \(a :: a) (b :: a) (NonNegative ix) (Positive excess) -> do
(=== a) $ runST $ do
arr <- MU.new (ix + excess)
MU.write arr ix a
when (ix > 0) $
MU.write arr (ix - 1) b
when (excess > 1) $
MU.write arr (ix + 1) b
MU.read arr ix
writeCopyAroundRead :: forall a. (Eq a, MU.Unbox a, Arbitrary a, Show a) => Proxy a -> Property
writeCopyAroundRead _ = property $ \(a :: a) (NonNegative ix) (Positive excess) -> do
(=== a) $ runST $ do
src <- MU.new (ix + excess)
dst <- MU.new (ix + excess)
MU.write dst ix a
when (ix > 0) $
MU.copy (MU.slice 0 ix dst) (MU.slice 0 ix src)
when (excess > 1) $
MU.copy (MU.slice (ix + 1) (excess - 1) dst) (MU.slice (ix + 1) (excess - 1) src)
MU.read dst ix
writeMoveAroundRead :: forall a. (Eq a, MU.Unbox a, Arbitrary a, Show a) => Proxy a -> Property
writeMoveAroundRead _ = property $ \(a :: a) (NonNegative ix) (Positive excess) -> do
(=== a) $ runST $ do
src <- MU.new (ix + excess)
dst <- MU.new (ix + excess)
MU.write dst ix a
when (ix > 0) $
MU.move (MU.slice 0 ix dst) (MU.slice 0 ix src)
when (excess > 1) $
MU.move (MU.slice (ix + 1) (excess - 1) dst) (MU.slice (ix + 1) (excess - 1) src)
MU.read dst ix
newSlice :: MU.Unbox a => NonNegative Int -> NonNegative Int -> Int -> ST s (MU.MVector s a)
newSlice (NonNegative before) (NonNegative after) len = do
arr <- MU.new (before + len + after)
pure $ MU.slice before len arr
#endif