summaryrefslogtreecommitdiff
path: root/lib/Numeric/GSL/Matrix.hs
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Numeric/GSL/Matrix.hs')
-rw-r--r--lib/Numeric/GSL/Matrix.hs302
1 files changed, 302 insertions, 0 deletions
diff --git a/lib/Numeric/GSL/Matrix.hs b/lib/Numeric/GSL/Matrix.hs
new file mode 100644
index 0000000..eb1931a
--- /dev/null
+++ b/lib/Numeric/GSL/Matrix.hs
@@ -0,0 +1,302 @@
1-----------------------------------------------------------------------------
2-- |
3-- Module : Numeric.GSL.Matrix
4-- Copyright : (c) Alberto Ruiz 2007
5-- License : GPL-style
6--
7-- Maintainer : Alberto Ruiz <aruiz@um.es>
8-- Stability : provisional
9-- Portability : portable (uses FFI)
10--
11-- A few linear algebra computations based on the Numeric.GSL (<http://www.gnu.org/software/Numeric.GSL>).
12--
13-----------------------------------------------------------------------------
14-- #hide
15
16module Numeric.GSL.Matrix(
17 eigSg, eigHg,
18 svdg,
19 qr,
20 cholR, -- cholC,
21 luSolveR, luSolveC,
22 luR, luC
23) where
24
25import Data.Packed.Internal
26import Data.Packed.Matrix(fromLists,ident,takeDiag)
27import Numeric.GSL.Vector
28import Foreign
29import Complex
30
31{- | eigendecomposition of a real symmetric matrix using /gsl_eigen_symmv/.
32
33> > let (l,v) = eigS $ 'fromLists' [[1,2],[2,1]]
34> > l
35> 3.000 -1.000
36>
37> > v
38> 0.707 -0.707
39> 0.707 0.707
40>
41> > v <> diag l <> trans v
42> 1.000 2.000
43> 2.000 1.000
44
45-}
46eigSg :: Matrix Double -> (Vector Double, Matrix Double)
47eigSg m
48 | r == 1 = (fromList [cdat m `at` 0], singleton 1)
49 | otherwise = unsafePerformIO $ do
50 l <- createVector r
51 v <- createMatrix RowMajor r r
52 c_eigS // mat cdat m // vec l // mat dat v // check "eigSg" [cdat m]
53 return (l,v)
54 where r = rows m
55foreign import ccall "gsl-aux.h eigensystemR" c_eigS :: TMVM
56
57------------------------------------------------------------------
58
59
60
61{- | eigendecomposition of a complex hermitian matrix using /gsl_eigen_hermv/
62
63> > let (l,v) = eigH $ 'fromLists' [[1,2+i],[2-i,3]]
64>
65> > l
66> 4.449 -0.449
67>
68> > v
69> -0.544 0.839
70> (-0.751,0.375) (-0.487,0.243)
71>
72> > v <> diag l <> (conjTrans) v
73> 1.000 (2.000,1.000)
74> (2.000,-1.000) 3.000
75
76-}
77eigHg :: Matrix (Complex Double)-> (Vector Double, Matrix (Complex Double))
78eigHg m
79 | r == 1 = (fromList [realPart $ cdat m `at` 0], singleton 1)
80 | otherwise = unsafePerformIO $ do
81 l <- createVector r
82 v <- createMatrix RowMajor r r
83 c_eigH // mat cdat m // vec l // mat dat v // check "eigHg" [cdat m]
84 return (l,v)
85 where r = rows m
86foreign import ccall "gsl-aux.h eigensystemC" c_eigH :: TCMVCM
87
88
89{- | Singular value decomposition of a real matrix, using /gsl_linalg_SV_decomp_mod/:
90
91@\> let (u,s,v) = svdg $ 'fromLists' [[1,2,3],[-4,1,7]]
92\
93\> u
940.310 -0.951
950.951 0.310
96\
97\> s
988.497 2.792
99\
100\> v
101-0.411 -0.785
102 0.185 -0.570
103 0.893 -0.243
104\
105\> u \<\> 'diag' s \<\> 'trans' v
106 1. 2. 3.
107-4. 1. 7.@
108
109-}
110svdg :: Matrix Double -> (Matrix Double, Vector Double, Matrix Double)
111svdg x = if rows x >= cols x
112 then svd' x
113 else (v, s, u) where (u,s,v) = svd' (trans x)
114
115svd' x = unsafePerformIO $ do
116 u <- createMatrix RowMajor r c
117 s <- createVector c
118 v <- createMatrix RowMajor c c
119 c_svd // mat cdat x // mat dat u // vec s // mat dat v // check "svdg" [cdat x]
120 return (u,s,v)
121 where r = rows x
122 c = cols x
123foreign import ccall "gsl-aux.h svd" c_svd :: TMMVM
124
125{- | QR decomposition of a real matrix using /gsl_linalg_QR_decomp/ and /gsl_linalg_QR_unpack/.
126
127@\> let (q,r) = qr $ 'fromLists' [[1,3,5,7],[2,0,-2,4]]
128\
129\> q
130-0.447 -0.894
131-0.894 0.447
132\
133\> r
134-2.236 -1.342 -0.447 -6.708
135 0. -2.683 -5.367 -4.472
136\
137\> q \<\> r
1381.000 3.000 5.000 7.000
1392.000 0. -2.000 4.000@
140
141-}
142qr :: Matrix Double -> (Matrix Double, Matrix Double)
143qr x = unsafePerformIO $ do
144 q <- createMatrix RowMajor r r
145 rot <- createMatrix RowMajor r c
146 c_qr // mat cdat x // mat dat q // mat dat rot // check "qr" [cdat x]
147 return (q,rot)
148 where r = rows x
149 c = cols x
150foreign import ccall "gsl-aux.h QR" c_qr :: TMMM
151
152{- | Cholesky decomposition of a symmetric positive definite real matrix using /gsl_linalg_cholesky_decomp/.
153
154@\> chol $ (2><2) [1,2,
155 2,9::Double]
156(2><2)
157 [ 1.0, 0.0
158 , 2.0, 2.23606797749979 ]@
159
160-}
161cholR :: Matrix Double -> Matrix Double
162cholR x = unsafePerformIO $ do
163 res <- createMatrix RowMajor r r
164 c_cholR // mat cdat x // mat dat res // check "cholR" [cdat x]
165 return res
166 where r = rows x
167foreign import ccall "gsl-aux.h cholR" c_cholR :: TMM
168
169cholC :: Matrix (Complex Double) -> Matrix (Complex Double)
170cholC x = unsafePerformIO $ do
171 res <- createMatrix RowMajor r r
172 c_cholC // mat cdat x // mat dat res // check "cholC" [cdat x]
173 return res
174 where r = rows x
175foreign import ccall "gsl-aux.h cholC" c_cholC :: TCMCM
176
177
178--------------------------------------------------------
179
180{- -| efficient multiplication by the inverse of a matrix (for real matrices)
181-}
182luSolveR :: Matrix Double -> Matrix Double -> Matrix Double
183luSolveR a b
184 | n1==n2 && n1==r = unsafePerformIO $ do
185 s <- createMatrix RowMajor r c
186 c_luSolveR // mat cdat a // mat cdat b // mat dat s // check "luSolveR" [cdat a, cdat b]
187 return s
188 | otherwise = error "luSolveR of nonsquare matrix"
189 where n1 = rows a
190 n2 = cols a
191 r = rows b
192 c = cols b
193foreign import ccall "gsl-aux.h luSolveR" c_luSolveR :: TMMM
194
195{- -| efficient multiplication by the inverse of a matrix (for complex matrices).
196-}
197luSolveC :: Matrix (Complex Double) -> Matrix (Complex Double) -> Matrix (Complex Double)
198luSolveC a b
199 | n1==n2 && n1==r = unsafePerformIO $ do
200 s <- createMatrix RowMajor r c
201 c_luSolveC // mat cdat a // mat cdat b // mat dat s // check "luSolveC" [cdat a, cdat b]
202 return s
203 | otherwise = error "luSolveC of nonsquare matrix"
204 where n1 = rows a
205 n2 = cols a
206 r = rows b
207 c = cols b
208foreign import ccall "gsl-aux.h luSolveC" c_luSolveC :: TCMCMCM
209
210{- | lu decomposition of real matrix (packed as a vector including l, u, the permutation and sign)
211-}
212luRaux :: Matrix Double -> Vector Double
213luRaux x = unsafePerformIO $ do
214 res <- createVector (r*r+r+1)
215 c_luRaux // mat cdat x // vec res // check "luRaux" [cdat x]
216 return res
217 where r = rows x
218 c = cols x
219foreign import ccall "gsl-aux.h luRaux" c_luRaux :: TMV
220
221{- | lu decomposition of complex matrix (packed as a vector including l, u, the permutation and sign)
222-}
223luCaux :: Matrix (Complex Double) -> Vector (Complex Double)
224luCaux x = unsafePerformIO $ do
225 res <- createVector (r*r+r+1)
226 c_luCaux // mat cdat x // vec res // check "luCaux" [cdat x]
227 return res
228 where r = rows x
229 c = cols x
230foreign import ccall "gsl-aux.h luCaux" c_luCaux :: TCMCV
231
232{- | The LU decomposition of a square matrix. Is based on /gsl_linalg_LU_decomp/ and /gsl_linalg_complex_LU_decomp/ as described in <http://www.gnu.org/software/Numeric.GSL/manual/Numeric.GSL-ref_13.html#SEC223>.
233
234@\> let m = 'fromLists' [[1,2,-3],[2+3*i,-7,0],[1,-i,2*i]]
235\> let (l,u,p,s) = luR m@
236
237L is the lower triangular:
238
239@\> l
240 1. 0. 0.
2410.154-0.231i 1. 0.
2420.154-0.231i 0.624-0.522i 1.@
243
244U is the upper triangular:
245
246@\> u
2472.+3.i -7. 0.
248 0. 3.077-1.615i -3.
249 0. 0. 1.873+0.433i@
250
251p is a permutation:
252
253@\> p
254[1,0,2]@
255
256L \* U obtains a permuted version of the original matrix:
257
258@\> extractRows p m
259 2.+3.i -7. 0.
260 1. 2. -3.
261 1. -1.i 2.i
262\
263\> l \<\> u
264 2.+3.i -7. 0.
265 1. 2. -3.
266 1. -1.i 2.i@
267
268s is the sign of the permutation, required to obtain sign of the determinant:
269
270@\> s * product ('toList' $ 'takeDiag' u)
271(-18.0) :+ (-16.000000000000004)
272\> 'LinearAlgebra.Algorithms.det' m
273(-18.0) :+ (-16.000000000000004)@
274
275 -}
276luR :: Matrix Double -> (Matrix Double, Matrix Double, [Int], Double)
277luR m = (l,u,p, fromIntegral s') where
278 r = rows m
279 v = luRaux m
280 lu = reshape r $ subVector 0 (r*r) v
281 s':p = map round . toList . subVector (r*r) (r+1) $ v
282 u = triang r r 0 1`mul` lu
283 l = (triang r r 0 0 `mul` lu) `add` ident r
284 add = liftMatrix2 $ vectorZipR Add
285 mul = liftMatrix2 $ vectorZipR Mul
286
287-- | Complex version of 'luR'.
288luC :: Matrix (Complex Double) -> (Matrix (Complex Double), Matrix (Complex Double), [Int], Complex Double)
289luC m = (l,u,p, fromIntegral s') where
290 r = rows m
291 v = luCaux m
292 lu = reshape r $ subVector 0 (r*r) v
293 s':p = map (round.realPart) . toList . subVector (r*r) (r+1) $ v
294 u = triang r r 0 1 `mul` lu
295 l = (triang r r 0 0 `mul` lu) `add` liftMatrix comp (ident r)
296 add = liftMatrix2 $ vectorZipC Add
297 mul = liftMatrix2 $ vectorZipC Mul
298
299{- auxiliary function to get triangular matrices
300-}
301triang r c h v = reshape c $ fromList [el i j | i<-[0..r-1], j<-[0..c-1]]
302 where el i j = if j-i>=h then v else 1 - v