packages feed

numeric-prelude-0.4: test/Test/MathObj/Matrix.hs

{-# 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))) :
-}
      []