numeric-prelude-0.2.1: test/Test/MathObj/Matrix.hs
{-# LANGUAGE RebindableSyntax #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
module Test.MathObj.Matrix where
import qualified MathObj.Matrix as Matrix
import qualified Algebra.Ring as Ring
import qualified Algebra.Laws as Laws
import qualified Number.NonNegative as NonNeg
import qualified System.Random as Random
import Data.Function.HT (nest, )
import Test.NumericPrelude.Utility (testUnit, )
import Test.QuickCheck (quickCheck, )
import qualified Test.HUnit as HUnit
import NumericPrelude.Base as P
import NumericPrelude.Numeric as NP
type Seed = Int
type Dimension = NonNeg.Int
random :: Dimension -> Dimension -> Seed -> Matrix.T Integer
random mn nn seed =
fst $
Matrix.random (NonNeg.toNumber mn) (NonNeg.toNumber nn) $
Random.mkStdGen seed
tests :: HUnit.Test
tests =
HUnit.TestLabel "matrix" $
HUnit.TestList $
map testUnit $
("dimension",
quickCheck (\m n a ->
(NonNeg.toNumber m, NonNeg.toNumber n) == Matrix.dimension (random m n a))) :
("to and from rows",
quickCheck (\m n a' ->
let a = random m n a'
in a == Matrix.fromRows (NonNeg.toNumber m) (NonNeg.toNumber n) (Matrix.rows a))) :
("to and from columns",
quickCheck (\m n a' ->
let a = random m n a'
in a == Matrix.fromColumns (NonNeg.toNumber m) (NonNeg.toNumber n) (Matrix.columns a))) :
("transpose, rows, columns",
quickCheck (\m n a' ->
let a = random m n a'
in Matrix.rows a == Matrix.columns (Matrix.transpose a))) :
("transpose, columns, rows",
quickCheck (\m n a' ->
let a = random m n a'
in Matrix.columns a == Matrix.rows (Matrix.transpose a))) :
("addition, zero",
quickCheck (\m n a ->
Laws.identity (+) (Matrix.zero (NonNeg.toNumber m) (NonNeg.toNumber n)) (random m n a))) :
("addition, commutative",
quickCheck (\m n a b ->
Laws.commutative (+) (random m n a) (random m n b))) :
("addition, associative",
quickCheck (\m n a b c ->
Laws.associative (+) (random m n a) (random m n b) (random m n c))) :
("addition, transpose",
quickCheck (\m n a b ->
Laws.homomorphism Matrix.transpose (+) (+) (random m n a) (random m n b))) :
("one, diagonal",
quickCheck (\n' ->
let n = NonNeg.toNumber n'
in Matrix.one n == (Matrix.diagonal $ replicate n Ring.one :: Matrix.T Integer))) :
("multiplication, one left",
quickCheck (\m n a ->
Laws.leftIdentity (*) (Matrix.one (NonNeg.toNumber m)) (random m n a))) :
("multiplication, one right",
quickCheck (\m n a ->
Laws.rightIdentity (*) (Matrix.one (NonNeg.toNumber n)) (random m n a))) :
("multiplication, associative",
quickCheck (\k l m n a b c ->
Laws.associative (*) (random k l a) (random l m b) (random m n c))) :
("multiplication and addition, distributive left",
quickCheck (\l m n a b c ->
Laws.leftDistributive (*) (+) (random n l a) (random m n b) (random m n c))) :
("multiplication and addition, distributive right",
quickCheck (\l m n a b c ->
Laws.rightDistributive (*) (+) (random l m a) (random m n b) (random m n c))) :
("multiplication, transpose",
quickCheck (\l m n a b ->
Laws.homomorphism Matrix.transpose (*) (flip (*)) (random l m a) (random m n b))) :
("multiplication vs. power",
quickCheck (\m a n0 ->
let x = random m m a
n = mod n0 10
in x^n == nest (fromInteger n) (x*) (Matrix.one (NonNeg.toNumber m)))) :
{-
("division", quickCheck (\x -> Integral.propInverse (x :: Poly.T Rational))) :
-}
[]