packages feed

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