massiv-test-0.1.3: tests/Test/Massiv/VectorSpec.hs
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MonoLocalBinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
module Test.Massiv.VectorSpec (spec) where
import Control.Exception
import Data.Bits
import Data.Massiv.Array as A
import Data.Massiv.Vector as V
import qualified Data.Vector.Primitive as VP
import Data.Word
import Test.Massiv.Core
import System.Random.MWC as MWC
infix 4 !==!, !!==!!
sizeException :: SizeException -> Bool
sizeException _ = True
(!==!) :: (Eq e, Show e, Prim e, Load r Ix1 e) => V.Vector r e -> VP.Vector e -> Property
(!==!) arr vec = toPrimitiveVector (convert arr) === vec
(!!==!!) :: (Eq e, Show e, Prim e, Source r Ix1 e) => V.Vector r e -> VP.Vector e -> Property
(!!==!!) arr vec = property $ do
eRes <- try (pure $! vec)
case eRes of
Right vec' -> toPrimitiveVector (computeSource arr) `shouldBe` vec'
Left (_exc :: ErrorCall) ->
shouldThrow (pure $! toPrimitiveVector (computeSource arr)) sizeException
newtype SeedVector = SeedVector (VP.Vector Word32) deriving (Eq, Show)
instance Arbitrary SeedVector where
arbitrary = SeedVector . VP.fromList <$> arbitrary
withSeed :: forall a. SeedVector -> (forall s. MWC.Gen s -> ST s a) -> a
withSeed (SeedVector seed) f = runST $ do
gen <- MWC.initialize seed
f gen
prop_sreplicateM :: SeedVector -> Int -> Property
prop_sreplicateM seed k =
withSeed @(V.Vector DS Word) seed (V.sreplicateM (Sz k) . uniform)
!==! withSeed seed (VP.replicateM k . uniform)
prop_sgenerateM :: SeedVector -> Int -> Fun Int Word -> Property
prop_sgenerateM seed k f =
withSeed @(V.Vector DS Word) seed (genWith (V.sgenerateM (Sz k)))
!==! withSeed seed (genWith (VP.generateM k))
where
genWith :: PrimMonad f => ((Int -> f Word) -> t) -> MWC.Gen (PrimState f) -> t
genWith genM gen = genM (\i -> xor (apply f i) <$> uniform gen)
prop_siterateNM :: SeedVector -> Int -> Word -> Property
prop_siterateNM seed k a =
withSeed @(V.Vector DS Word) seed (genWith (\action -> V.siterateNM (Sz k) action a))
!==! withSeed seed (genWith (\action -> VP.iterateNM k action a))
where
genWith :: PrimMonad f => ((Word -> f Word) -> t) -> MWC.Gen (PrimState f) -> t
genWith genM gen = genM (\prev -> xor prev <$> uniform gen)
spec :: Spec
spec = do
describe "Vector" $ do
describe "same-as-vector-package" $ do
describe "Accessors" $ do
describe "Slicing" $ do
prop "slice'" $ \i sz (arr :: Array P Ix1 Word) ->
V.slice' i sz arr !!==!! VP.slice i (unSz sz) (toPrimitiveVector arr)
prop "init'" $ \(arr :: Array P Ix1 Word) ->
V.init' arr !!==!! VP.init (toPrimitiveVector arr)
prop "tail'" $ \(arr :: Array P Ix1 Word) ->
V.tail' arr !!==!! VP.tail (toPrimitiveVector arr)
prop "take" $ \n (arr :: Array P Ix1 Word) ->
V.take (Sz n) arr !==! VP.take n (toPrimitiveVector arr)
prop "stake" $ \n (arr :: Array P Ix1 Word) ->
V.stake (Sz n) arr !==! VP.take n (toPrimitiveVector arr)
prop "drop" $ \n (arr :: Array P Ix1 Word) ->
V.drop (Sz n) arr !==! VP.drop n (toPrimitiveVector arr)
prop "sdrop" $ \n (arr :: Array P Ix1 Word) ->
V.sdrop (Sz n) arr !==! VP.drop n (toPrimitiveVector arr)
prop "sliceAt" $ \sz (arr :: Array P Ix1 Word) ->
let (larr, rarr) = V.sliceAt (Sz sz) arr
(lvec, rvec) = VP.splitAt sz (toPrimitiveVector arr)
in (larr !==! lvec) .&&. (rarr !==! rvec)
describe "Constructors" $ do
describe "Initialization" $ do
it "empty" $ toPrimitiveVector (V.empty :: V.Vector P Word) `shouldBe` VP.empty
prop "singleton" $ \e -> (V.singleton e :: V.Vector P Word) !==! VP.singleton e
prop "ssingleton" $ \(e :: Word) -> V.ssingleton e !==! VP.singleton e
prop "replicate" $ \comp k (e :: Word) -> V.replicate comp (Sz k) e !==! VP.replicate k e
prop "sreplicate" $ \k (e :: Word) -> V.sreplicate (Sz k) e !==! VP.replicate k e
prop "generate" $ \comp k (f :: Fun Int Word) ->
V.generate comp (Sz k) (apply f) !==! VP.generate k (apply f)
prop "sgenerate" $ \k (f :: Fun Int Word) ->
V.sgenerate (Sz k) (apply f) !==! VP.generate k (apply f)
prop "siterateN" $ \n (f :: Fun Word Word) a ->
V.siterateN (Sz n) (apply f) a !==! VP.iterateN n (apply f) a
describe "Monadic initialization" $ do
prop "sreplicateM" prop_sreplicateM
prop "sgenerateM" prop_sgenerateM
prop "siterateNM" prop_siterateNM
describe "Unfolding" $ do
prop "sunfoldr" $ \(a :: Word) ->
let f b
| b > 10000 || b `div` 17 == 0 = Nothing
| otherwise = Just (b * b, b + 1)
in V.sunfoldr f a !==! VP.unfoldr f a
prop "sunfoldrN" $ \n (a :: Word) ->
let f b
| b > 10000 || b `div` 19 == 0 = Nothing
| otherwise = Just (b * b, b + 1)
in V.sunfoldrN (Sz n) f a !==! VP.unfoldrN n f a