1 module IndexedMatrix
where
2 import Control
.Monad
(liftM)
3 import Data
.Maybe (fromMaybe, isJust)
5 import qualified Data
.Set
as Set
6 import Numeric
.Matrix
(Matrix
, MatrixElement
)
7 import qualified Numeric
.Matrix
as Matrix
8 import Util
.Function
((...))
9 import qualified Util
.Set
as Set
11 data IndexedMatrix r c e
= IndexedMatrix
13 , columnIndices
:: Set c
14 , stripIndices
:: Matrix e
17 indexedMatrix
:: MatrixElement e
=>
18 Set r
-> Set c
-> (r
-> c
-> e
) -> IndexedMatrix r c e
19 indexedMatrix rs cs f
= IndexedMatrix
22 , stripIndices
= Matrix
.matrix
(Set
.size rs
, Set
.size cs
) $ \(i
, j
) ->
23 f
(Set
.elemAt
(i
- 1) rs
) $ Set
.elemAt
(j
- 1) cs
26 maybeInRange
:: (Ord r
, Ord c
) =>
27 (IndexedMatrix r c e
-> r
-> c
-> a
) ->
28 IndexedMatrix r c e
-> r
-> c
-> Maybe a
29 maybeInRange f m r c
=
30 if (Set
.member r
(rowIndices m
) && Set
.member c
(columnIndices m
))
34 at
:: (Ord r
, Ord c
, MatrixElement e
) =>
35 IndexedMatrix r c e
-> r
-> c
-> Maybe e
36 at
= maybeInRange
$ \m r c
-> Matrix
.at
(stripIndices m
)
37 (Set
.findIndex r
(rowIndices m
) + 1, Set
.findIndex c
(columnIndices m
) + 1)
39 at
' :: (Ord r
, Ord c
, MatrixElement e
) => IndexedMatrix r c e
-> r
-> c
-> e
40 at
' = fromMaybe 0 ... at
42 firstMinorMatrix
:: (Ord r
, Ord c
, MatrixElement e
) =>
43 IndexedMatrix r c e
-> r
-> c
-> Maybe (IndexedMatrix r c e
)
44 firstMinorMatrix
= maybeInRange
$ \m r c
->
50 { rowIndices
= Set
.delete r rs
51 , columnIndices
= Set
.delete c cs
52 , stripIndices
= Matrix
.minorMatrix
(stripIndices m
)
53 (Set
.findIndex r rs
+ 1, Set
.findIndex c cs
+ 1)
56 inverse :: MatrixElement e
=> IndexedMatrix r c e
-> Maybe (IndexedMatrix c r e
)
57 inverse m
= flip liftM (Matrix
.inv
$ stripIndices m
) $ \m
' -> IndexedMatrix
58 { rowIndices
= columnIndices m
59 , columnIndices
= rowIndices m
63 invertible
:: MatrixElement e
=> IndexedMatrix r c e
-> Bool
64 invertible
= isJust . inverse
66 identity
:: MatrixElement e
=> Set i
-> IndexedMatrix i i e
67 identity i
= IndexedMatrix
70 , stripIndices
= Matrix
.unit
$ Set
.size i
73 times
:: (Eq j
, MatrixElement e
) =>
74 IndexedMatrix i j e
-> IndexedMatrix j k e
-> Maybe (IndexedMatrix i k e
)
76 if columnIndices m
== rowIndices n
77 then Just
$ IndexedMatrix
78 { rowIndices
= rowIndices m
79 , columnIndices
= columnIndices n
80 , stripIndices
= stripIndices m
* stripIndices n
84 numRows
:: IndexedMatrix r c e
-> Integer
85 numRows
= toInteger . Set
.size
. rowIndices
87 numColumns
:: IndexedMatrix r c e
-> Integer
88 numColumns
= toInteger . Set
.size
. columnIndices