1 {-# LANGUAGE TemplateHaskell #-}
2 module Test
.IndexedMatrix
where
3 import Control
.Applicative
((<$>), (<*>))
4 import Data
.Eq
.Approximate
5 import Data
.Function
(on
)
6 import Data
.Maybe (fromJust, isJust, isNothing)
8 import qualified Data
.Set
as Set
10 import Numeric
.Matrix
(MatrixElement
)
11 import qualified Numeric
.Matrix
as Matrix
12 import Test
.QuickCheck
13 import Test
.QuickCheck
.All
15 import TypeLevel
.NaturalNumber
16 import Util
.Function
((.:))
17 import Util
.Set
(allSet
)
19 type ApproximateDouble
= AbsolutelyApproximateValue
(Digits Eight
) Double
20 wrapAD
:: Double -> ApproximateDouble
21 wrapAD
= AbsolutelyApproximateValue
22 unwrapAD
:: ApproximateDouble
-> Double
23 unwrapAD
= unwrapAbsolutelyApproximateValue
26 class ApproxEq a
where
27 (~
=) :: a
-> a
-> Bool
29 instance ApproxEq
Double where
30 (~
=) = (==) `on` wrapAD
32 instance ApproxEq a
=> ApproxEq
(Maybe a
) where
33 Nothing ~
= Nothing
= True
34 Just x ~
= Just y
= x ~
= y
37 instance (Ord r
, Ord c
, MatrixElement e
, ApproxEq e
) =>
38 ApproxEq
(IndexedMatrix r c e
) where
44 && columnIndices b
== cs
45 && (flip allSet rs
$ \r -> flip allSet cs
$ \c
-> at a r c ~
= at b r c
)
48 ( Arbitrary r
, CoArbitrary r
, Ord r
49 , Arbitrary c
, CoArbitrary c
, Ord c
50 , Arbitrary e
, MatrixElement e
51 ) => Arbitrary
(IndexedMatrix r c e
) where
52 arbitrary
= indexedMatrix
53 <$> arbitrarySetOfSizeSqrt
54 <*> arbitrarySetOfSizeSqrt
57 arbitrarySquareMatrix
::
58 ( Arbitrary r
, CoArbitrary r
, Ord r
59 , Arbitrary c
, CoArbitrary c
, Ord c
60 , Arbitrary e
, MatrixElement e
61 ) => Gen
(IndexedMatrix r c e
)
62 arbitrarySquareMatrix
= do
63 rs
<- arbitrarySetOfSizeSqrt
64 cs
<- arbitrarySetOfExactSize
$ Set
.size rs
65 indexedMatrix rs cs
<$> arbitrary
67 prop_valid_indexedMatrix
:: (Ord r
, Ord c
, MatrixElement e
) =>
68 IndexedMatrix r c e
-> Bool
69 prop_valid_indexedMatrix m
= let m
' = stripIndices m
70 in Set
.size
(rowIndices m
) == Matrix
.numRows m
'
71 && Set
.size
(columnIndices m
) == Matrix
.numCols m
'
72 && m
== indexedMatrix
(rowIndices m
) (columnIndices m
) (at
' m
)
74 withIndicesIn
:: (Ord r
, Show r
, Ord c
, Show c
, Testable p
) =>
75 IndexedMatrix r c e
-> (r
-> c
-> p
) -> Property
76 withIndicesIn m f
= withArbitraryElement
(rowIndices m
) $
77 withArbitraryElement
(columnIndices m
) . f
79 prop_at_in
:: (Ord r
, Show r
, Ord c
, Show c
, MatrixElement e
) =>
80 IndexedMatrix r c e
-> Property
81 prop_at_in m
= withIndicesIn m
$ isJust .: at m
83 prop_at_out
:: (Ord r
, Ord c
, MatrixElement e
) =>
84 IndexedMatrix r c e
-> r
-> c
-> Property
86 not (Set
.member r
(rowIndices m
) && Set
.member c
(columnIndices m
)) ==>
89 prop_firstMinorMatrix_valid_indexedMatrix
::
90 (Ord r
, Show r
, Ord c
, Show c
, MatrixElement e
) =>
91 IndexedMatrix r c e
-> Property
92 prop_firstMinorMatrix_valid_indexedMatrix m
= withIndicesIn m
$
93 (prop_valid_indexedMatrix
. fromJust) .: firstMinorMatrix m
95 prop_firstMinorMatrix_size
:: (Ord r
, Show r
, Ord c
, Show c
, MatrixElement e
) =>
96 IndexedMatrix r c e
-> Property
97 prop_firstMinorMatrix_size m
= withIndicesIn m
$ \r c
->
98 let m
' = fromJust $ firstMinorMatrix m r c
in
99 rowIndices m
' == Set
.delete r
(rowIndices m
) &&
100 columnIndices m
' == Set
.delete c
(columnIndices m
)
102 prop_firstMinorMatrix_entries
::
103 (Ord r
, Show r
, Ord c
, Show c
, MatrixElement e
) =>
104 IndexedMatrix r c e
-> Property
105 prop_firstMinorMatrix_entries m
= withIndicesIn m
$ \r c
->
106 let m
' = fromJust $ firstMinorMatrix m r c
in
107 withIndicesIn m
' $ \r' c
'
108 -> at m
' r
' c
' == at m r
' c
'
109 && (isJust $ at m
' r
' c
')
110 && (isNothing $ at m
' r c
')
111 && (isNothing $ at m
' r
' c
)
112 && (isNothing $ at m
' r c
)
115 ( Arbitrary r
, CoArbitrary r
, Ord r
, Show r
116 , Arbitrary c
, CoArbitrary c
, Ord c
, Show c
117 , Arbitrary e
, MatrixElement e
, Show e
119 ) => (IndexedMatrix r c e
-> p
) -> Property
120 squareMatrixTest
= forAll arbitrarySquareMatrix
122 squareMatrixTestDouble
:: Testable p
=>
123 (IndexedMatrix
Integer Integer Double -> p
) -> Property
124 squareMatrixTestDouble
= squareMatrixTest
126 squareMatrixTestRational
:: Testable p
=>
127 (IndexedMatrix
Integer Integer Rational -> p
) -> Property
128 squareMatrixTestRational
= squareMatrixTest
130 prop_invertible_Double
:: Property
131 prop_invertible_Double
= squareMatrixTestDouble invertible
133 prop_invertible_Rational
:: Property
134 prop_invertible_Rational
= squareMatrixTestRational invertible
136 inverse_valid_indexedMatrix
:: (Ord r
, Ord c
, MatrixElement e
) =>
137 IndexedMatrix r c e
-> Property
138 inverse_valid_indexedMatrix m
=
139 invertible m
==> prop_valid_indexedMatrix
$ fromJust $ inverse m
141 prop_inverse_valid_indexedMatrix_Double
:: Property
142 prop_inverse_valid_indexedMatrix_Double
=
143 squareMatrixTestDouble inverse_valid_indexedMatrix
145 prop_inverse_valid_indexedMatrix_Rational
:: Property
146 prop_inverse_valid_indexedMatrix_Rational
=
147 squareMatrixTestRational inverse_valid_indexedMatrix
149 inverse_times_eq_id
:: (Eq r
, Eq c
, MatrixElement e
) =>
150 IndexedMatrix r c e
-> Property
151 inverse_times_eq_id m
= invertible m
152 ==> m `times` m
' == Just
(identity
$ rowIndices m
)
153 && m
' `times` m
== Just
(identity
$ columnIndices m
)
154 where m
' = fromJust $ inverse m
156 inverse_times_approxeq_id
:: (Ord r
, Ord c
, MatrixElement e
, ApproxEq e
) =>
157 IndexedMatrix r c e
-> Property
158 inverse_times_approxeq_id m
= invertible m
159 ==> m `times` m
' ~
= Just
(identity
$ rowIndices m
)
160 && m
' `times` m ~
= Just
(identity
$ columnIndices m
)
161 where m
' = fromJust $ inverse m
163 prop_inverse_times_approxeq_id_Double
:: Property
164 prop_inverse_times_approxeq_id_Double
=
165 squareMatrixTestDouble inverse_times_approxeq_id
167 prop_inverse_times_eq_id_Rational
:: Property
168 prop_inverse_times_eq_id_Rational
= squareMatrixTestRational inverse_times_eq_id
170 allIndexedMatrixTests
:: IO Bool
171 allIndexedMatrixTests
= $(quickCheckAll
)