1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
|
-----------------------------------------------------------------------------
-- |
-- Module : Data.Packed.Matrix
-- Copyright : (c) Alberto Ruiz 2007
-- License : GPL-style
--
-- Maintainer : Alberto Ruiz <aruiz@um.es>
-- Stability : provisional
-- Portability : portable
--
-- Matrices
--
-----------------------------------------------------------------------------
module Data.Packed.Matrix (
Field,
Matrix,rows,cols,
(><), reshape, flatten,
fromLists, toLists,
(@@>),
trans, conjTrans,
asRow, asColumn,
fromRows, toRows, fromColumns, toColumns,
fromBlocks, joinVert, joinHoriz,
flipud, fliprl,
subMatrix, takeRows, dropRows, takeColumns, dropColumns,
ident, diag, diagRect, takeDiag,
liftMatrix, liftMatrix2,
) where
import Data.Packed.Internal
import Foreign(Storable)
import Complex
import Data.Packed.Vector
-- | creates a matrix from a vertical list of matrices
joinVert :: Field t => [Matrix t] -> Matrix t
joinVert ms = case common cols ms of
Nothing -> error "joinVert on matrices with different number of columns"
Just c -> reshape c $ join (map cdat ms)
-- | creates a matrix from a horizontal list of matrices
joinHoriz :: Field t => [Matrix t] -> Matrix t
joinHoriz ms = trans. joinVert . map trans $ ms
{- | Creates a matrix from blocks given as a list of lists of matrices:
@\> let a = 'diag' $ 'fromList' [5,7,2]
\> let b = 'reshape' 4 $ 'constant' (-1) 12
\> fromBlocks [[a,b],[b,a]]
(6><7)
[ 5.0, 0.0, 0.0, -1.0, -1.0, -1.0, -1.0
, 0.0, 7.0, 0.0, -1.0, -1.0, -1.0, -1.0
, 0.0, 0.0, 2.0, -1.0, -1.0, -1.0, -1.0
, -1.0, -1.0, -1.0, -1.0, 5.0, 0.0, 0.0
, -1.0, -1.0, -1.0, -1.0, 0.0, 7.0, 0.0
, -1.0, -1.0, -1.0, -1.0, 0.0, 0.0, 2.0 ]@
-}
fromBlocks :: Field t => [[Matrix t]] -> Matrix t
fromBlocks = joinVert . map joinHoriz
-- | Reverse rows
flipud :: Field t => Matrix t -> Matrix t
flipud m = fromRows . reverse . toRows $ m
-- | Reverse columns
fliprl :: Field t => Matrix t -> Matrix t
fliprl m = fromColumns . reverse . toColumns $ m
------------------------------------------------------------
{- | creates a rectangular diagonal matrix
@> diagRect (constant 5 3) 3 4
(3><4)
[ 5.0, 0.0, 0.0, 0.0
, 0.0, 5.0, 0.0, 0.0
, 0.0, 0.0, 5.0, 0.0 ]@
-}
diagRect :: (Field t, Num t) => Vector t -> Int -> Int -> Matrix t
diagRect s r c
| dim s < min r c = error "diagRect"
| r == c = diag s
| r < c = trans $ diagRect s c r
| r > c = joinVert [diag s , zeros (r-c,c)]
where zeros (r,c) = reshape c $ constantD 0 (r*c)
-- | extracts the diagonal from a rectangular matrix
takeDiag :: (Field t) => Matrix t -> Vector t
takeDiag m = fromList [cdat m `at` (k*cols m+k) | k <- [0 .. min (rows m) (cols m) -1]]
-- | creates the identity matrix of given dimension
ident :: Int -> Matrix Double
ident n = diag (constant 1 n)
------------------------------------------------------------
{- | An easy way to create a matrix:
@\> (2><3)[1..6]
(2><3)
[ 1.0, 2.0, 3.0
, 4.0, 5.0, 6.0 ]@
This is the format produced by the instances of Show (Matrix a), which
can also be used for input.
-}
(><) :: (Field a) => Int -> Int -> [a] -> Matrix a
r >< c = f where
f l | dim v == r*c = matrixFromVector RowMajor c v
| otherwise = error $ "inconsistent list size = "
++show (dim v) ++" in ("++show r++"><"++show c++")"
where v = fromList l
----------------------------------------------------------------
-- | Creates a matrix with the first n rows of another matrix
takeRows :: Field t => Int -> Matrix t -> Matrix t
takeRows n mat = subMatrix (0,0) (n, cols mat) mat
-- | Creates a copy of a matrix without the first n rows
dropRows :: Field t => Int -> Matrix t -> Matrix t
dropRows n mat = subMatrix (n,0) (rows mat - n, cols mat) mat
-- |Creates a matrix with the first n columns of another matrix
takeColumns :: Field t => Int -> Matrix t -> Matrix t
takeColumns n mat = subMatrix (0,0) (rows mat, n) mat
-- | Creates a copy of a matrix without the first n columns
dropColumns :: Field t => Int -> Matrix t -> Matrix t
dropColumns n mat = subMatrix (0,n) (rows mat, cols mat - n) mat
----------------------------------------------------------------
{- | Creates a vector by concatenation of rows
@\> flatten ('ident' 3)
9 |> [1.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,1.0]@
-}
flatten :: Field t => Matrix t -> Vector t
flatten = cdat
{- | Creates a 'Matrix' from a list of lists (considered as rows).
@\> fromLists [[1,2],[3,4],[5,6]]
(3><2)
[ 1.0, 2.0
, 3.0, 4.0
, 5.0, 6.0 ]@
-}
fromLists :: Field t => [[t]] -> Matrix t
fromLists = fromRows . map fromList
-- | conjugate transpose
conjTrans :: Matrix (Complex Double) -> Matrix (Complex Double)
conjTrans = trans . liftMatrix conj
-- | creates a 1-row matrix from a vector
asRow :: Field a => Vector a -> Matrix a
asRow v = reshape (dim v) v
-- | creates a 1-column matrix from a vector
asColumn :: Field a => Vector a -> Matrix a
asColumn v = reshape 1 v
------------------------------------------------
|