Aelve Codesearch

grep over package repositories
carray-0.1.6.8
tests/tests.hs
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
import qualified Test.QuickCheck as QC
import Test.QuickCheck (Property, (==>))
import Control.Arrow ((&&&), (***))
import Control.Monad (liftM2)
import Text.Show.Functions ()
import Data.Array.CArray
          (CArray, flatten, ixmapWithInd, rank, reshape, shape, size, sliceWith)
import Data.Ix.Shapable (shapeToStride)
import Data.Array.Unboxed
          (IArray, Ix, UArray,
           accum, amap, bounds, elems, ixmap, listArray, rangeSize)
import Data.Word (Word32)
import Foreign.Storable (Storable)
import Text.Printf (printf)
import System.Environment (getArgs)
-- import System.Random


-- cf. storablevector/test
class Model a b where model :: a -> b

instance (Ix i, IArray a e, Model i i', Model e e') => Model (a i e) ((i',i'),[e']) where
    model = (model . bounds &&& map model . elems)
instance (Model i i', Model e e', Ix i', IArray a e') => Model ((i,i),[e]) (a i' e') where
    model = uncurry listArray . (model *** map model)
instance (Ix i, Ix i', Model i i', Model e e', Storable e, IArray UArray e')
    => Model (CArray i e) (UArray i' e') where
    model = uncurry listArray . (model . bounds &&& map model . elems)
instance (Ix i, Ix i', Model i i', Model e e', Storable e', IArray UArray e)
    => Model (UArray i e) (CArray i' e') where
    model = uncurry listArray . (model . bounds &&& map model . elems)

-- Types are trivially modeled by themselves
instance Model Bool  Bool         where model = id
instance Model Int   Int          where model = id
instance Model Float Float        where model = id
instance Model Double Double      where model = id
instance (Model a a', Model b b') => Model (a,b) (a',b') where
    model (a,b) = (model a, model b)
instance (Model a a', Model b b', Model c c') => Model (a,b,c) (a',b',c') where
    model (a,b,c) = (model a, model b, model c)
instance (Model a a', Model b b', Model c c', Model d d') => Model (a,b,c,d) (a',b',c',d') where
    model (a,b,c,d) = (model a, model b, model c, model d)

(=||=) ::
   (Model x1 y1, Model x y, Eq y) =>
   (x2 -> x1 -> x) -> (x2 -> y1 -> y) -> x2 -> x1 -> Bool

(=|||=) ::
   (Model x2 y2, Model x y, Eq y) =>
   (x3 -> x2 -> x1 -> x) -> (x3 -> y2 -> x1 -> y) -> x3 -> x2 -> x1 -> Bool


infix 1 =||=, =|||=

f =||= g = \a b       ->
    model (f a b)       == g a (model b)
f =|||= g = \a b c     ->
    model (f a b c)     == g a (model b) c

(===) :: (Eq b) => (a -> b) -> (a -> b) -> a -> Bool
(f === g) x = f x == g x
infixl 1 ===

transposeArray :: CArray (Int,Int) Double -> CArray (Int,Int) Double
transposeArray a = ixmap ((swap *** swap) (bounds a)) swap a
    where swap = (\(i,j) -> (j,i))


type Test2D = CArray (Int,Int) Double -> Bool

prop_flatten_flatten, prop_reshape_flatten, prop_rank,
    prop_shape_size, prop_size, prop_shape_stride_last, prop_transpose :: Test2D

prop_flatten_flatten = flatten . flatten === flatten
prop_reshape_flatten a = reshape (0, size a - 1) a == flatten a
prop_rank = length . shape === rank
prop_shape_size = product . shape === size
prop_size = size === rangeSize . bounds
prop_shape_stride_last = last . shapeToStride . shape === const 1
prop_transpose = transposeArray . transposeArray === id

ca_tests :: [(String, CArray (Int,Int) Double -> Bool)]
ca_tests =
    ("flatten flatten"   , prop_flatten_flatten) :
    ("reshape flatten"   , prop_reshape_flatten) :
    ("rank"              , prop_rank) :
    ("shape size"        , prop_shape_size) :
    ("size"              , prop_size) :
    ("shape stride last" , prop_shape_stride_last) :
    ("transpose^2"       , prop_transpose) :
    []

prop_amap :: (Int -> Double) -> CArray Int Int -> Bool
prop_amap =    (amap :: (Int -> Double) -> CArray Int Int -> CArray Int Double)
          =||= (amap :: (Int -> Double) -> UArray Int Int -> UArray Int Double)

prop_slice_all :: (Int -> Double) -> CArray (Int,Int) Int -> Property
prop_slice_all f a = size a > 0 ==> sliceWith (bounds a) (bounds a) f a == amap f a
prop_ixmapWithInd_amap :: (Int -> Double) -> CArray (Int,Int) Int -> Property
prop_ixmapWithInd_amap f a = size a > 0 ==> ixmapWithInd (bounds a) id (\_ e _ -> f e) a == amap f a

type Acc = Word32
prop_accum :: (Int -> Acc -> Int) -> CArray Int Int -> Property
prop_accum f a =
    QC.forAll (QC.listOf $ liftM2 (,) (QC.choose (bounds a)) QC.arbitrary) $ \ies ->
        (      (accum :: (Int -> Acc -> Int) -> CArray Int Int -> [(Int, Acc)] -> CArray Int Int)
         =|||= (accum :: (Int -> Acc -> Int) -> UArray Int Int -> [(Int, Acc)] -> UArray Int Int)) f a ies

type Transform = CArray Int Int -> CArray Int Int

prop_composeAssoc ::
    Transform -> Transform -> Transform -> CArray Int Int -> Bool
prop_composeAssoc f g h = (f . g) . h === f . (g . h)

main :: IO ()
main = do
    args <- getArgs
    n <- case args of [] -> return 100; str:_ -> readIO str
    let mycheck (s,a) =
            printf "%-25s: " s >>
            QC.quickCheckWith (QC.stdArgs {QC.maxSuccess = n}) a
    mapM_ mycheck ca_tests
    mapM_ mycheck [ ("amap"        , prop_amap) ]
    mapM_ mycheck [ ("accum"       , prop_accum) ]
    mapM_ mycheck [ ("composeAssoc", prop_composeAssoc) ]
    mapM_ mycheck [ ("slice all"         , prop_slice_all)
                  , ("ixmapWithInd amap" , prop_ixmapWithInd_amap) ]

-- arb n k = generate n (mkStdGen k) arbitrary