{-# LANGUAGE NoImplicitPrelude #-} {-# 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 System.Random as Random import Data.Function.HT (nest, ) import Test.NumericPrelude.Utility (testUnit, ) import Test.QuickCheck (Arbitrary(arbitrary), quickCheck, ) import qualified Test.QuickCheck as QC import qualified Test.HUnit as HUnit import NumericPrelude.Base as P import NumericPrelude.Numeric as NP type Seed = Int newtype Dimension = Dimension {unDim :: Int} deriving (Show) instance Arbitrary Dimension where arbitrary = fmap Dimension $ QC.choose (0,20) random :: Dimension -> Dimension -> Seed -> Matrix.T Integer random mn nn seed = fst $ Matrix.random (unDim mn) (unDim nn) $ Random.mkStdGen seed tests :: HUnit.Test tests = HUnit.TestLabel "matrix" $ HUnit.TestList $ map testUnit $ ("dimension", quickCheck (\m n a -> (unDim m, unDim 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 (unDim m) (unDim n) (Matrix.rows a))) : ("to and from columns", quickCheck (\m n a' -> let a = random m n a' in a == Matrix.fromColumns (unDim m) (unDim 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 (unDim m) (unDim 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 = unDim 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 (unDim m)) (random m n a))) : ("multiplication, one right", quickCheck (\m n a -> Laws.rightIdentity (*) (Matrix.one (unDim 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 (unDim m)))) : {- ("division", quickCheck (\x -> Integral.propInverse (x :: Poly.T Rational))) : -} []