packages feed

knead-0.5: test/Test/Array.hs

module Test.Array where

import qualified Data.Array.Knead.Parameterized.Render as Render
import qualified Data.Array.Knead.Simple.Symbolic as Symb
import qualified Data.Array.Knead.Simple.Slice as Slice
import qualified Data.Array.Knead.Expression as Expr
import qualified Data.Array.Knead.Shape as Shape
import qualified Data.Array.Comfort.Storable as Array
import qualified Data.Array.Comfort.Shape as ComfortShape
import Data.Array.Comfort.Storable (Array)

import qualified LLVM.Extra.Storable as Storable
import qualified LLVM.Extra.Marshal as Marshal
import qualified LLVM.Extra.Multi.Value as MultiValue

import qualified LLVM.Core as LLVM

import qualified Type.Data.Num.Decimal as TypeNum

import Foreign.Storable (Storable)

import qualified Data.List.HT as ListHT
import Data.Int (Int32, Int64)

import Control.Applicative ((<$>))

import qualified Test.QuickCheck.Monadic as QCMon
import qualified Test.QuickCheck as QC


type Dim = ComfortShape.ZeroBased Int64
type Dim2 = (Dim, Dim)

genArray :: (QC.Arbitrary a, Storable a) => QC.Gen (Array Dim2 a)
genArray = do
   m <- QC.choose (1,10)
   n <- QC.choose (1,10)
   let shape = (Shape.ZeroBased m, Shape.ZeroBased n)
   Array.fromList shape <$> QC.vector (ComfortShape.size shape)


rowSumSymb ::
   (Shape.C sh0, Shape.C sh1, MultiValue.Additive a) =>
   Symb.Array (sh0,sh1) a -> Symb.Array sh0 a
rowSumSymb = Symb.fold1 Expr.add

columnSumSymb ::
   (Shape.C sh0, Shape.C sh1, MultiValue.Additive a) =>
   Symb.Array (sh0,sh1) a -> Symb.Array sh1 a
columnSumSymb = Symb.fold1 Expr.add . Slice.apply Slice.transpose


getRows ::
   (ComfortShape.C sh0, ComfortShape.C sh1, Storable a) =>
   Array (sh0,sh1) a -> [[a]]
getRows x =
   ListHT.sliceVertical
      (ComfortShape.size $ snd $ Array.shape x)
      (Array.toList x)

rowPred ::
   (Num a, Eq a, Storable a,
    ComfortShape.C sh0, ComfortShape.C sh1) =>
   Array (sh0, sh1) a -> Array sh0 a -> Bool
rowPred x y  =  Array.toList y == map sum (getRows x)

columnPred ::
   (Num a, Eq a, Storable a,
    ComfortShape.C sh0, ComfortShape.C sh1) =>
   Array (sh0, sh1) a -> Array sh1 a -> Bool
columnPred x y  =  Array.toList y == foldl1 (zipWith (+)) (getRows x)

run ::
   (Shape.C sh0, Marshal.MV sh0, Show sh0,
    Shape.C sh1, Marshal.MV sh1, Show sh1,
    Show a, Num a, Eq a, Storable.C a) =>
   QC.Gen (Array sh0 a) ->
   (Symb.Array sh0 a -> Symb.Array sh1 a) ->
   (Array sh0 a -> Array sh1 a -> Bool) ->
   IO QC.Property
run qcgen code predicate = do
   act <- Render.run code
   return $ QC.forAll qcgen $ \x ->
      QCMon.monadicIO $ do
         y <- QCMon.run $ act x
         QCMon.assert $ predicate x y


tests :: [(String, IO QC.Property)]
tests =
   ("rowSum",
      run (genArray :: QC.Gen (Array Dim2 Int32)) rowSumSymb rowPred) :
   ("columnSum",
      run (genArray :: QC.Gen (Array Dim2 Int32)) columnSumSymb columnPred) :
   ("rowSumV3",
      run (genArray :: QC.Gen (Array Dim2 (LLVM.Vector TypeNum.D3 Int32)))
         rowSumSymb rowPred) :
   ("columnSumV3",
      run (genArray :: QC.Gen (Array Dim2 (LLVM.Vector TypeNum.D3 Int32)))
         columnSumSymb columnPred) :
   []