packages feed

blas-0.6: tests/STMatrix.hs

{-# LANGUAGE Rank2Types, PatternSignatures #-}
module STMatrix ( tests_STMatrix ) where


import BLAS.Elem
import Data.Matrix.Dense
import Data.Matrix.Dense.ST

import qualified Generators.Matrix.Dense as Test

import Driver



-------------------------- Creating Matrices --------------------------------

newMatrix_S = matrix

prop_NewMatrix (Assocs2 mn ijes) =
    newMatrix mn ijes `equivalent` newMatrix_S mn ijes

newListMatrix_S = listMatrix

prop_NewListMatrix (Nat2 mn) es =
    newListMatrix mn es `equivalent` newListMatrix_S mn es

---------------------- Reading and Writing Elements --------------------------

getSize_S a = ( size a, a )
prop_GetSize = getSize `implements` getSize_S

readElem_S a ij = ( a!ij, a )
prop_ReadElem (Index2 ij mn) =
    implementsFor mn (`readElem` ij) (`readElem_S` ij)

canModifyElem_S a ij = ( True, a )
prop_CanModifyElem ij = (`canModifyElem` ij) `implements` (`canModifyElem_S` ij)

writeElem_S a ij e = ( (), a // [(ij,e)] )
prop_WriteElem (Index2 ij mn) e =
    implementsFor mn (\a -> writeElem a ij e) (\a -> writeElem_S a ij e)

modifyElem_S a ij f = writeElem_S a ij $ f (a!ij)
prop_ModifyElem (Index2 ij mn) f =
    implementsFor mn (\a -> modifyElem a ij f) (\a -> modifyElem_S a ij f)

getIndices_S a = ( indices a, a )

prop_GetIndicesLazy   = getIndices `implements`  getIndices_S
prop_GetIndicesStrict = getIndices' `implements` getIndices_S
    
getElemsLazyModifyWith_S f a = ( elems a', a' ) where a' = tmap f a
prop_GetElemsLazyModifyWith f =
    (\a -> do { es <- getElems a ; modifyWith f a ; return es })
    `implements `
    (getElemsLazyModifyWith_S f)

getElemsStrictModifyWith_S f a = ( elems a, a' ) where a' = tmap f a
prop_GetElemsStrictModifyWith f =
    (\a -> do { es <- getElems' a ; modifyWith f a ; return es })
    `implements `
    (getElemsStrictModifyWith_S f)

getAssocsLazyModifyWith_S f a = ( assocs a', a' ) where a' = tmap f a
prop_GetAssocsLazyModifyWith f =
    (\a -> do { ijes <- getAssocs a ; modifyWith f a ; return ijes })
    `implements` 
    getAssocsLazyModifyWith_S f

getAssocsStrictModifyWith_S f a = ( assocs a, a' ) where a' = tmap f a
prop_GetAssocsStrictModifyWith f =
    (\a -> do { ijes <- getAssocs' a ; modifyWith f a ; return ijes })
    `implements` 
    getAssocsStrictModifyWith_S f


----------------------------- Special Matrices --------------------------------

newZeroMatrix_S = zeroMatrix
prop_NewZeroMatrix (Nat2 mn) = 
    newZeroMatrix mn `equivalent` newZeroMatrix_S mn

setZeroMatrix_S a = ( (), newZeroMatrix_S (shape a) )
prop_SetZeroMatrix = setZeroMatrix `implements` setZeroMatrix_S

newConstantMatrix_S mn e = constantMatrix mn e
prop_NewConstantMatrix (Nat2 mn) e = 
    newConstantMatrix mn e `equivalent` newConstantMatrix_S mn e

setConstantMatrix_S e a = ( (), newConstantMatrix_S (shape a) e )
prop_SetConstantMatrix e = setConstantMatrix e `implements` setConstantMatrix_S e

newIdentityMatrix_S = identityMatrix
prop_NewIdentityMatrix (Nat2 mn) = 
    newIdentityMatrix mn `equivalent` newIdentityMatrix_S mn

setIdentityMatrix_S a = ( (), newIdentityMatrix_S (shape a) )
prop_SetIdentityMatrix =
    setIdentityMatrix `implements` setIdentityMatrix_S


---------------------------- Copying Matrices --------------------------------

newCopyMatrix_S a = ( a, a )
prop_NewCopyMatrix = 
    (\a -> newCopyMatrix a >>= abstract) `implements` newCopyMatrix_S

copyMatrix_S a b = ( (), b, b )
prop_CopyMatrix = copyMatrix `implements2` copyMatrix_S

swapMatrix_S a b = ( (), b, a )
prop_SwapMatrix = swapMatrix `implements2` swapMatrix_S


-------------------------- Unsary Matrix Operations --------------------------

doConj_S x = ( (), tmap conj x )
prop_DoConj = doConj `implements` doConj_S

scaleBy_S k x = ( (), tmap (k*) x )
prop_ScaleBy k = scaleBy k `implements` scaleBy_S k

shiftBy_S k x = ( (), tmap (k+) x )
prop_ShiftBy k = shiftBy k `implements` shiftBy_S k

modifyWith_S f x = ( (), tmap f x )
prop_ModifyWith f = modifyWith f `implements` modifyWith_S f

getConjMatrix_S x = ( tmap conj x, x )
prop_GetConjMatrix = 
    (\x -> getConjMatrix x >>= abstract) `implements` getConjMatrix_S

getScaledMatrix_S k x = ( tmap (k*) x, x )
prop_GetScaledMatrix k = 
    (\x -> getScaledMatrix k x >>= abstract) `implements` (getScaledMatrix_S k)

getShiftedMatrix_S k x = ( tmap (k+) x, x )
prop_GetShiftedMatrix k = 
    (\x -> getShiftedMatrix k x >>= abstract) `implements` (getShiftedMatrix_S k)


------------------------- Binary Matrix Operations ---------------------------

addMatrix_S x y = ( (), x + y, y )
prop_AddMatrix = addMatrix `implements2` addMatrix_S

subMatrix_S x y = ( (), x - y, y )
prop_SubMatrix = subMatrix `implements2` subMatrix_S

axpyMatrix_S alpha x y = ( (), x, alpha *> x + y )
prop_AxpyMatrix alpha = axpyMatrix alpha `implements2` axpyMatrix_S alpha

mulMatrix_S x y = ( (), x * y, y )
prop_MulMatrix = mulMatrix `implements2` mulMatrix_S

divMatrix_S x y = ( (), x / y, y )
prop_DivMatrix = divMatrix `implements2` divMatrix_S

getAddMatrix_S x y = ( x + y, x, y )
prop_GetAddMatrix =
    (\x y -> getAddMatrix x y >>= abstract) `implements2` getAddMatrix_S

getSubMatrix_S x y = ( x - y, x, y )
prop_GetSubMatrix =
    (\x y -> getSubMatrix x y >>= abstract) `implements2` getSubMatrix_S

getMulMatrix_S x y = ( x * y, x, y )
prop_GetMulMatrix =
    (\x y -> getMulMatrix x y >>= abstract) `implements2` getMulMatrix_S

getDivMatrix_S x y = ( x / y, x, y )
prop_GetDivMatrix =
    (\x y -> getDivMatrix x y >>= abstract) `implements2` getDivMatrix_S


------------------------------------------------------------------------
-- 
-- The specification language
--
    
abstract :: (BLAS1 e) => STMatrix s (m,n) e -> ST s (Matrix (m,n) e)
abstract = freezeMatrix

commutes :: (AEq a, Show a, AEq e, BLAS1 e) =>
    STMatrix s (m,n) e -> (STMatrix s (m,n) e -> ST s a) ->
        (Matrix (m,n) e -> (a,Matrix (m,n) e)) -> ST s Bool
commutes x a f = do
    old <- abstract x
    r <- a x
    new <- abstract x
    let s      = f old
        s'     = (r,new)
        passed = s ~== s'
        
    when (not passed) $
        trace (printf ("expected `%s' but got `%s'") (show s) (show s'))
              return ()
              
    return passed

commutes2 :: (AEq a, Show a, AEq e, BLAS1 e) =>
    STMatrix s (m,n) e -> STMatrix s (m,n) e -> 
    (STMatrix s (m,n) e ->  STMatrix s (m,n) e -> ST s a) ->
        (Matrix (m,n) e -> Matrix (m,n) e -> (a,Matrix (m,n) e,Matrix (m,n) e)) -> ST s Bool
commutes2 x y a f = do
    oldX <- abstract x
    oldY <- abstract y
    r <- a x y
    newX <- abstract x
    newY <- abstract y
    let s      = f oldX oldY
        s'     = (r,newX,newY)
        passed = s ~== s'
        
    when (not passed) $
        trace (printf ("expected `%s' but got `%s'") (show s) (show s'))
            return ()
            
    return passed

equivalent :: (forall s . ST s (STMatrix s (m,n) E)) -> Matrix (m,n) E -> Bool
equivalent x s = runST $ do
    x' <- (x >>= abstract)
    when (not $ x' === s) $
        trace (printf ("expected `%s' but got `%s'") (show s) (show x'))
            return ()
    return (x' === s)
    
implements :: (AEq a, Show a) =>
    (forall s . STMatrix s (m,n) E -> ST s a) ->
    (Matrix (m,n) E -> (a,Matrix (m,n) E)) -> 
        Property
a `implements` f =
    forAll arbitrary $ \(Nat2 mn) ->
        implementsFor mn a f

implements2 :: (AEq a, Show a) =>
    (forall s . STMatrix s (m,n) E -> STMatrix s (m,n) E -> ST s a) ->
    (Matrix (m,n) E -> Matrix (m,n) E -> (a,Matrix (m,n) E,Matrix (m,n) E)) -> 
        Property
a `implements2` f =
    forAll arbitrary $ \(Nat2 mn) ->
        implementsFor2 mn a f

implementsFor :: (AEq a, Show a) =>
    (Int,Int) ->
    (forall s . STMatrix s (m,n) E -> ST s a) ->
    (Matrix (m,n) E -> (a,Matrix (m,n) E)) -> 
        Property
implementsFor mn a f =
    forAll (Test.matrix mn) $ \x ->
        runST $ do
            commutes (unsafeThawMatrix x) a f

implementsFor2 :: (AEq a, Show a) =>
    (Int,Int) ->
    (forall s . STMatrix s (m,n) E -> STMatrix s (m,n) E -> ST s a) ->
    (Matrix (m,n) E -> Matrix (m,n) E -> (a,Matrix (m,n) E,Matrix (m,n) E)) -> 
        Property
implementsFor2 mn a f =
    forAll (Test.matrix mn) $ \x ->
    forAll (Test.matrix mn) $ \y ->
        runST $ do
            commutes2 (unsafeThawMatrix x) (unsafeThawMatrix y) a f


implementsIf :: (AEq a, Show a) =>
    (forall s . STMatrix s (m,n) E -> ST s Bool) ->
    (forall s . STMatrix s (m,n) E -> ST s a) ->
    (Matrix (m,n) E -> (a,Matrix (m,n) E)) -> 
        Property
implementsIf pre a f =
    forAll arbitrary $ \(Nat2 mn) ->
    forAll (Test.matrix mn) $ \x ->
        runST ( do
            x' <- thawMatrix x
            pre x') ==>
        runST ( do
            commutes (unsafeThawMatrix x) a f )

implementsIf2 :: (AEq a, Show a) =>
    (forall s . STMatrix s (m,n) E -> STMatrix s (m,n) E -> ST s Bool) ->
    (forall s . STMatrix s (m,n) E -> STMatrix s (m,n) E -> ST s a) ->
    (Matrix (m,n) E -> Matrix (m,n) E -> (a,Matrix (m,n) E,Matrix (m,n) E)) -> 
        Property
implementsIf2 pre a f =
    forAll arbitrary $ \(Nat2 mn) ->
    forAll (Test.matrix mn) $ \x ->
    forAll (Test.matrix mn) $ \y ->
        runST ( do
            x' <- thawMatrix x
            y' <- thawMatrix y
            pre x' y') ==>
        runST ( do
            commutes2 (unsafeThawMatrix x) (unsafeThawMatrix y) a f )
            
------------------------------------------------------------------------

tests_STMatrix =
    [ ("newMatrix", mytest prop_NewMatrix)
    , ("newListMatrix", mytest prop_NewListMatrix)
    
    , ("getSize", mytest prop_GetSize)
    , ("readElem", mytest prop_ReadElem)
    , ("canModifyElem", mytest prop_CanModifyElem)
    , ("writeElem", mytest prop_WriteElem)
    , ("modifyElem", mytest prop_ModifyElem)

    , ("getIndices", mytest prop_GetIndicesLazy)
    , ("getIndices'", mytest prop_GetIndicesStrict)
    , ("getElems", mytest prop_GetElemsLazyModifyWith)
    , ("getElems'", mytest prop_GetElemsStrictModifyWith)
    , ("getAssocs", mytest prop_GetAssocsLazyModifyWith)
    , ("getAssocs'", mytest prop_GetAssocsStrictModifyWith)

    , ("newZeroMatrix", mytest prop_NewZeroMatrix)
    , ("setZeroMatrix", mytest prop_SetZeroMatrix)
    , ("newConstantMatrix", mytest prop_NewConstantMatrix)
    , ("setConstantMatrix", mytest prop_SetConstantMatrix)
    , ("newIdentityMatrix", mytest prop_NewIdentityMatrix)
    , ("setIdentityMatrix", mytest prop_SetIdentityMatrix)
    
    , ("newCopyMatrix", mytest prop_NewCopyMatrix)
    , ("copyMatrix", mytest prop_CopyMatrix)
    , ("swapMatrix", mytest prop_SwapMatrix)

    , ("doConj", mytest prop_DoConj)
    , ("scaleBy", mytest prop_ScaleBy)
    , ("shiftBy", mytest prop_ShiftBy)
    , ("modifyWith", mytest prop_ModifyWith)
    
    , ("getConjMatrix", mytest prop_GetConjMatrix)
    , ("getScaledMatrix", mytest prop_GetScaledMatrix)
    , ("getShiftedMatrix", mytest prop_GetShiftedMatrix)

    , ("axpyMatrix", mytest prop_AxpyMatrix)
    , ("addMatrix", mytest prop_AddMatrix)
    , ("subMatrix", mytest prop_SubMatrix)
    , ("mulMatrix", mytest prop_MulMatrix)
    , ("divMatrix", mytest prop_DivMatrix)
    
    , ("getAddMatrix", mytest prop_GetAddMatrix)
    , ("getSubMatrix", mytest prop_GetSubMatrix)
    , ("getMulMatrix", mytest prop_GetMulMatrix)
    , ("getDivMatrix", mytest prop_GetDivMatrix)

    ]