blas-0.4: tests/TriMatrix.hs
{-# OPTIONS -fglasgow-exts -fno-excess-precision -cpp #-}
-----------------------------------------------------------------------------
-- |
-- Copyright : Copyright (c) 2008, Patrick Perry <patperry@stanford.edu>
-- License : BSD3
-- Maintainer : Patrick Perry <patperry@stanford.edu>
-- Stability : experimental
--
import System.Environment ( getArgs )
import Test.QuickCheck.Parallel hiding ( vector )
import qualified Test.QuickCheck as QC
import Data.Complex ( Complex(..) )
import qualified BLAS.Elem as E
import Data.Vector.Dense
import Data.Matrix.Dense
import Data.Matrix.Tri.Dense
import Data.AEq
import Numeric.IEEE
import Test.QuickCheck.Complex
import Test.QuickCheck.Matrix.Tri.Dense
isUndefR x = isNaN x || isInfinite x
isUndefC (x :+ y) = isUndefR x || isUndefR y
#ifdef COMPLEX
field = "Complex Double"
type E = Complex Double
isUndef = isUndefC
#else
field = "Double"
type E = Double
isUndef = isUndefR
#endif
type V = Vector Int E
type M = Matrix (Int,Int) E
type TM = Tri (Matrix) (Int,Int) E
instance (Arbitrary e, RealFloat e) => Arbitrary (Complex e) where
arbitrary = arbitrary >>= \(TestComplex x) -> return x
coarbitrary = coarbitrary . TestComplex
prop_tri_apply (TriMatrixMV u d (a :: M) x) =
case (u,d) of
(Lower, NonUnit) -> (lower a) <*> x ~== a <*> x
(Lower, Unit ) -> (lowerU a) <*> x ~== a <*> x + x
(Upper, NonUnit) -> (upper a) <*> x ~== a <*> x
(Upper, Unit ) -> (upperU a) <*> x ~== a <*> x + x
prop_herm_tri_apply (TriMatrixMV u d (a :: M) x) =
case (u,d) of
(Lower, NonUnit) -> (herm $ lower a) <*> x ~== herm a <*> x
(Lower, Unit ) -> (herm $ lowerU a) <*> x ~== herm a <*> x + x
(Upper, NonUnit) -> (herm $ upper a) <*> x ~== herm a <*> x
(Upper, Unit ) -> (herm $ upperU a) <*> x ~== herm a <*> x + x
prop_scale_tri_apply k (TriMatrixMV u d (a :: M) x) =
case (u,d) of
(Lower, NonUnit) -> (k *> lower a) <*> x ~== (k *> a) <*> x
(Lower, Unit ) -> (k *> lowerU a) <*> x ~== (k *> a) <*> x + (k *> x)
(Upper, NonUnit) -> (k *> upper a) <*> x ~== (k *> a) <*> x
(Upper, Unit ) -> (k *> upperU a) <*> x ~== (k *> a) <*> x + (k *> x)
prop_scale_herm_tri_apply k (TriMatrixMV u d (a :: M) x) =
case (u,d) of
(Lower, NonUnit) -> (k *> (herm $ lower a)) <*> x ~== (k *> herm a) <*> x
(Lower, Unit ) -> (k *> (herm $ lowerU a)) <*> x ~== (k *> herm a) <*> x + (k *> x)
(Upper, NonUnit) -> (k *> (herm $ upper a)) <*> x ~== (k *> herm a) <*> x
(Upper, Unit ) -> (k *> (herm $ upperU a)) <*> x ~== (k *> herm a) <*> x + (k *> x)
prop_herm_scale_tri_apply k (TriMatrixMV u d (a :: M) x) =
case (u,d) of
(Lower, NonUnit) -> (herm $ k *> lower a) <*> x ~== (herm $ k *> a) <*> x
(Lower, Unit ) -> (herm $ k *> lowerU a) <*> x ~== (herm $ k *> a) <*> x + ((E.conj k) *> x)
(Upper, NonUnit) -> (herm $ k *> upper a) <*> x ~== (herm $ k *> a) <*> x
(Upper, Unit ) -> (herm $ k *> upperU a) <*> x ~== (herm $ k *> a) <*> x + ((E.conj k) *> x)
prop_tri_compose (TriMatrixMM u d (a :: M) b) =
case (u,d) of
(Lower, NonUnit) -> (lower a) <**> b ~== a <**> b
(Lower, Unit ) -> (lowerU a) <**> b ~== a <**> b + b
(Upper, NonUnit) -> (upper a) <**> b ~== a <**> b
(Upper, Unit ) -> (upperU a) <**> b ~== a <**> b + b
prop_herm_tri_compose (TriMatrixMM u d (a :: M) b) =
case (u,d) of
(Lower, NonUnit) -> (herm $ lower a) <**> b ~== herm a <**> b
(Lower, Unit ) -> (herm $ lowerU a) <**> b ~== herm a <**> b + b
(Upper, NonUnit) -> (herm $ upper a) <**> b ~== herm a <**> b
(Upper, Unit ) -> (herm $ upperU a) <**> b ~== herm a <**> b + b
prop_scale_tri_compose k (TriMatrixMM u d (a :: M) b) =
case (u,d) of
(Lower, NonUnit) -> (k *> lower a) <**> b ~== (k *> a) <**> b
(Lower, Unit ) -> (k *> lowerU a) <**> b ~== (k *> a) <**> b + (k *> b)
(Upper, NonUnit) -> (k *> upper a) <**> b ~== (k *> a) <**> b
(Upper, Unit ) -> (k *> upperU a) <**> b ~== (k *> a) <**> b + (k *> b)
prop_scale_herm_tri_compose k (TriMatrixMM u d (a :: M) b) =
case (u,d) of
(Lower, NonUnit) -> (k *> (herm $ lower a)) <**> b ~== (k *> herm a) <**> b
(Lower, Unit ) -> (k *> (herm $ lowerU a)) <**> b ~== (k *> herm a) <**> b + (k *> b)
(Upper, NonUnit) -> (k *> (herm $ upper a)) <**> b ~== (k *> herm a) <**> b
(Upper, Unit ) -> (k *> (herm $ upperU a)) <**> b ~== (k *> herm a) <**> b + (k *> b)
prop_herm_scale_tri_compose k (TriMatrixMM u d (a :: M) b) =
case (u,d) of
(Lower, NonUnit) -> (herm $ k *> lower a) <**> b ~== (herm $ k *> a) <**> b
(Lower, Unit ) -> (herm $ k *> lowerU a) <**> b ~== (herm $ k *> a) <**> b + ((E.conj k) *> b)
(Upper, NonUnit) -> (herm $ k *> upper a) <**> b ~== (herm $ k *> a) <**> b
(Upper, Unit ) -> (herm $ k *> upperU a) <**> b ~== (herm $ k *> a) <**> b + ((E.conj k) *> b)
prop_tri_solve (TriMatrixSV (t :: TM) y) =
let x = t <\> y
in t <*> x ~== y || (any isUndef $ elems x)
prop_tri_invCompose (TriMatrixSM (t :: TM) b) =
let a = t <\\> b
in t <**> a ~== b || (any isUndef $ elems a)
properties =
[ ("tri apply" , pDet prop_tri_apply)
, ("scale tri apply" , pDet prop_scale_tri_apply)
, ("herm tri apply" , pDet prop_herm_tri_apply)
, ("scale herm tri apply" , pDet prop_scale_herm_tri_apply)
, ("herm scale tri apply" , pDet prop_herm_scale_tri_apply)
, ("tri compose" , pDet prop_tri_compose)
, ("scale tri compose" , pDet prop_scale_tri_compose)
, ("herm tri compose" , pDet prop_herm_tri_compose)
, ("scale herm tri compose", pDet prop_scale_herm_tri_compose)
, ("herm scale tri compose", pDet prop_herm_scale_tri_compose)
, ("tri solve" , pDet prop_tri_solve)
, ("tri invCompose" , pDet prop_tri_invCompose)
]
main = do
args <- getArgs
n <- case args of
(a:_) -> readIO a
_ -> return 1
main' n
main' n = do
putStrLn $ "Running tests for " ++ field
pRun n 400 properties