camfort-0.900: tests/Camfort/Specification/Stencils/ModelSpec.hs
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ImplicitParams #-}
module Camfort.Specification.Stencils.ModelSpec (spec) where
import Camfort.Helpers.Vec
import Camfort.Specification.Stencils
import Camfort.Specification.Stencils.Synthesis
import Camfort.Specification.Stencils.Model
import Camfort.Specification.Stencils.Syntax hiding (Spec)
import qualified Camfort.Specification.Stencils.Syntax as Syn
import Camfort.Analysis.Annotations
import qualified Language.Fortran.AST as F
import Language.Fortran.Util.Position
import Data.Bits
import Data.List
import Data.Set (toList)
import Test.Hspec
import Test.QuickCheck
import Test.Hspec.QuickCheck
spec :: Spec
spec = do
describe "Consistency of model vs access patterns" $ do
let singleOneDimSpec = Single $ Exact $ Spatial $ Sum
[ Product [ Forward 1 1 True ] ]
it "1D readOnce - positive" $ do
let acs = Single [[0], [1]]
consistent acs singleOneDimSpec `shouldBe` True
it "1D readOnce - negative" $ do
let acs = Multiple [[0], [1]]
consistent acs singleOneDimSpec `shouldBe` False
let reflCentOneDimSpec = Single $ Exact $ Spatial $ Sum
[ Product [ Centered 1 1 False ] ]
it "1D centered irreflexive - positive" $ do
let acs = Single [[-1], [1]]
consistent acs reflCentOneDimSpec `shouldBe` True
let centeredAcs = Single [[-1], [0], [1]]
it "1D centered irreflexive - negative" $
consistent centeredAcs reflCentOneDimSpec `shouldBe` False
it "1D centered irreflexive lower bound - positive" $ do
let spec = Single $ Bound
(Just $ Spatial $ Sum [ Product [ Centered 1 1 False ] ])
Nothing
consistent centeredAcs spec `shouldBe` True
it "1D centered irreflexive upper bound - negative" $ do
let spec = Single $ Bound
Nothing
(Just $ Spatial $ Sum [ Product [ Centered 1 1 False ] ])
consistent centeredAcs spec `shouldBe` False
it "1D double bounded" $ do
let acs = Single [ [-3], [-2], [-1], [0], [1], [3] ]
let spec = Single $ Bound
(Just $ Spatial $ Sum [ Product [ Centered 1 1 True ] ])
(Just $ Spatial $ Sum [ Product [ Centered 1 3 True ] ])
consistent acs spec `shouldBe` True
it "1D spec 3D access" $ do
let acs = Single [ [0,1,-2], [absoluteRep, 2,3] ]
let spec = Single $ Exact $
Spatial $ Sum [ Product [ Forward 2 2 False ] ]
consistent acs spec `shouldBe` True
let twoDimSpec = Single $ Exact $
Spatial $ Sum [ Product [ Centered 0 1 True, Forward 1 2 True ] ]
it "2 dimensional spec example" $ do
let acs = Single [ [0,0], [0,1] ]
consistent acs twoDimSpec `shouldBe` True
it "Constant access not allowed in otherwise fine access pattern" $ do
let acs = Single [ [0,0], [0,1], [absoluteRep, absoluteRep] ]
consistent acs twoDimSpec `shouldBe` False
describe "Stencils - Model" $ do
describe "Test soundness of model 1" modelHasLeftInverse
describe "Test soundness of model 2" $ modelHasApproxLeftInverse variations2
describe "Test soundness of model 3" $ modelHasApproxLeftInverse variations3
describe "Consistency of model with paper" $ do
describe "Quickcheck" $ it "" $ property propPairwisePerm
describe "Manual for absolute rep" $ do
it "Check absolute rep (0)" $
sort (pp [1,2,absoluteRep] [5,1,7])
`shouldBe` sort (pairwisePerm [1,2,absoluteRep] [5,1,7])
it "Check absolute rep (1)" $
sort (pp [1,absoluteRep] [5,1])
`shouldBe` sort (pairwisePerm [1,absoluteRep] [5,1])
it "Check absolute rep (2)" $
sort (pp [absoluteRep,2,absoluteRep] [absoluteRep,1,7])
`shouldBe` sort (pairwisePerm [absoluteRep,2,absoluteRep] [absoluteRep,1,7])
propPairwisePerm :: [Int] -> [Int] -> Bool
propPairwisePerm x y =
if length x == length y && length x < 16
then (sort . nub $ pp x y) == (sort . nub $ pairwisePerm x y)
else True
pp :: [Int] -> [Int] -> [[Int]]
pp x y =
let n = length x
in map (\i ->
map (\j -> ((x !! j) `times` not (testBit i j))
`plus`
((y !! j) `times` testBit i j)
) [0..(n-1)]
) [0 :: Int .. ((2^n)-1)]
where times x True = x
times x False = 0
plus x y = x + y
variations :: [([[Int]], Syn.Multiplicity (Syn.Approximation Spatial))]
variations =
[ ([ [1], [0] ],
Multiple $ Exact $ Spatial (Sum [Product [Forward 1 1 True]]))
, ([ [absoluteRep,1], [absoluteRep,0] ],
Multiple $ Exact $ Spatial (Sum [Product [Forward 1 2 True]]))
, ([ [1,1], [0,1], [1,0], [0,0] ],
Multiple $ Exact $ Spatial (Sum [Product [Forward 1 1 True, Forward 1 2 True]]))
, ([ [-1, 1], [0, 1] ],
Multiple $ Exact $ Spatial (Sum [Product [Backward 1 1 True, Forward 1 2 False]]))
, ([ [-1], [0] ],
Multiple $ Exact $ Spatial (Sum [Product [Backward 1 1 True]]))
, ([ [absoluteRep,-1], [absoluteRep,0] ],
Multiple $ Exact $ Spatial (Sum [Product [Backward 1 2 True]]))
, ([ [-1,-1], [0,-1], [-1,0], [0,0] ],
Multiple $ Exact $ Spatial (Sum [Product [Backward 1 1 True, Backward 1 2 True]]))
, ( [ [0,-1], [1,-1], [0,0], [1,0], [1,1], [0,1], [2,-1], [2,0], [2,1] ],
Multiple $ Exact $ Spatial
(Sum [Product [ Forward 2 1 True, Centered 1 2 True ] ] ))
, ( [ [-1,0], [-1,1], [0,0], [0,1], [1,1], [1,0], [-1,2], [0,2], [1,2] ],
Multiple $ Exact $ Spatial
(Sum [Product [ Forward 2 2 True, Centered 1 1 True ] ] ))
]
variations2 :: [( Syn.Multiplicity (Syn.Approximation [[Int]])
, Int
, Syn.Multiplicity (Syn.Approximation Spatial) )]
variations2 =
[
-- Stencil which has some absolute component (not represented in the spec)
( Multiple $ Exact [ [0, absoluteRep], [1, absoluteRep] ]
, 2
, Multiple $ Exact $ Spatial (Sum [Product [Forward 1 1 True]])
)
-- Spec on bounds
, ( Multiple $ Bound Nothing (Just [ [0, absoluteRep], [1, absoluteRep]
, [2, absoluteRep] ])
, 2
, Multiple $ Bound Nothing
(Just $ Spatial (Sum [Product [Forward 2 1 True]]))
)
]
variations3 :: [( Syn.Multiplicity (Syn.Approximation [[Int]])
, Int
, Syn.Multiplicity (Syn.Approximation Spatial) )]
variations3 =
[
-- Spec on bounds
( Multiple $
Bound Nothing (Just [ [0, absoluteRep, 0], [1, absoluteRep, 0]
, [2, absoluteRep, 0], [0, absoluteRep, 1]
, [1, absoluteRep, 1], [2, absoluteRep, 1]])
, 3
, Multiple $
Bound Nothing (Just $ Spatial (Sum [Product [ Forward 1 3 True
, Forward 2 1 True ]]))
)
]
modelHasLeftInverse = mapM_ check (zip variations [0..])
where
check ((ixs, spec), n) =
it ("("++show n++")") $
sort mdl `shouldBe` sort ixs
where
mdl = toList . fromExact . fromMult . model' $ spec
model' = flip model $ length . head $ ixs
modelHasApproxLeftInverse vars = mapM_ check (zip vars [(0 :: Int)..])
where
check ((ixs, dims, spec), n) =
it ("("++show n++")") $ mdl `shouldBe` fmap sort <$> ixs
where
mdl =
let ?globalDimensionality = dims
in fmap (sort . toList) <$> mkModel spec