diff options
author | Alberto Ruiz <aruiz@um.es> | 2007-09-30 10:38:59 +0000 |
---|---|---|
committer | Alberto Ruiz <aruiz@um.es> | 2007-09-30 10:38:59 +0000 |
commit | 13dfe14e171941b3ca82cd858973e3681d7b254e (patch) | |
tree | c3e65613af8d5301f67aeac66c560aaf997fa04a /lib/LinearAlgebra/LAPACK.hs | |
parent | c54d047956412dafc8e2a11f5c5f11733d330d68 (diff) |
move LAPACK under LinearAlgebra
Diffstat (limited to 'lib/LinearAlgebra/LAPACK.hs')
-rw-r--r-- | lib/LinearAlgebra/LAPACK.hs | 335 |
1 files changed, 335 insertions, 0 deletions
diff --git a/lib/LinearAlgebra/LAPACK.hs b/lib/LinearAlgebra/LAPACK.hs new file mode 100644 index 0000000..2861061 --- /dev/null +++ b/lib/LinearAlgebra/LAPACK.hs | |||
@@ -0,0 +1,335 @@ | |||
1 | {-# OPTIONS_GHC -fglasgow-exts #-} | ||
2 | ----------------------------------------------------------------------------- | ||
3 | -- | | ||
4 | -- Module : LinearAlgebra.LAPACK | ||
5 | -- Copyright : (c) Alberto Ruiz 2006-7 | ||
6 | -- License : GPL-style | ||
7 | -- | ||
8 | -- Maintainer : Alberto Ruiz (aruiz at um dot es) | ||
9 | -- Stability : provisional | ||
10 | -- Portability : portable (uses FFI) | ||
11 | -- | ||
12 | -- Wrappers for a few LAPACK functions (<http://www.netlib.org/lapack>). | ||
13 | -- | ||
14 | ----------------------------------------------------------------------------- | ||
15 | |||
16 | module LinearAlgebra.LAPACK ( | ||
17 | svdR, svdRdd, svdC, | ||
18 | eigC, eigR, eigS, eigH, | ||
19 | linearSolveR, linearSolveC, | ||
20 | linearSolveLSR, linearSolveLSC, | ||
21 | linearSolveSVDR, linearSolveSVDC, | ||
22 | cholS, cholH, | ||
23 | qrR, qrC | ||
24 | ) where | ||
25 | |||
26 | import Data.Packed.Internal | ||
27 | import Data.Packed.Internal.Vector | ||
28 | import Data.Packed.Internal.Matrix | ||
29 | import Data.Packed.Vector | ||
30 | import Data.Packed.Matrix | ||
31 | import GSL.Vector(vectorMapValR, FunCodeSV(Scale)) | ||
32 | import Complex | ||
33 | import Foreign | ||
34 | |||
35 | ----------------------------------------------------------------------------- | ||
36 | foreign import ccall "LAPACK/lapack-aux.h svd_l_R" dgesvd :: TMMVM | ||
37 | |||
38 | -- | Wrapper for LAPACK's /dgesvd/, which computes the full svd decomposition of a real matrix. | ||
39 | -- | ||
40 | -- @(u,s,v)=full svdR m@ so that @m=u \<\> s \<\> 'trans' v@. | ||
41 | svdR :: Matrix Double -> (Matrix Double, Vector Double, Matrix Double) | ||
42 | svdR x = unsafePerformIO $ do | ||
43 | u <- createMatrix ColumnMajor r r | ||
44 | s <- createVector (min r c) | ||
45 | v <- createMatrix ColumnMajor c c | ||
46 | dgesvd // mat fdat x // mat dat u // vec s // mat dat v // check "svdR" [fdat x] | ||
47 | return (u,s,trans v) | ||
48 | where r = rows x | ||
49 | c = cols x | ||
50 | ----------------------------------------------------------------------------- | ||
51 | foreign import ccall "LAPACK/lapack-aux.h svd_l_Rdd" dgesdd :: TMMVM | ||
52 | |||
53 | -- | Wrapper for LAPACK's /dgesvd/, which computes the full svd decomposition of a real matrix. | ||
54 | -- | ||
55 | -- @(u,s,v)=full svdRdd m@ so that @m=u \<\> s \<\> 'trans' v@. | ||
56 | svdRdd :: Matrix Double -> (Matrix Double, Vector Double, Matrix Double) | ||
57 | svdRdd x = unsafePerformIO $ do | ||
58 | u <- createMatrix ColumnMajor r r | ||
59 | s <- createVector (min r c) | ||
60 | v <- createMatrix ColumnMajor c c | ||
61 | dgesdd // mat fdat x // mat dat u // vec s // mat dat v // check "svdRdd" [fdat x] | ||
62 | return (u,s,trans v) | ||
63 | where r = rows x | ||
64 | c = cols x | ||
65 | |||
66 | ----------------------------------------------------------------------------- | ||
67 | foreign import ccall "LAPACK/lapack-aux.h svd_l_C" zgesvd :: TCMCMVCM | ||
68 | |||
69 | -- | Wrapper for LAPACK's /zgesvd/, which computes the full svd decomposition of a complex matrix. | ||
70 | -- | ||
71 | -- @(u,s,v)=full svdC m@ so that @m=u \<\> comp s \<\> 'trans' v@. | ||
72 | svdC :: Matrix (Complex Double) -> (Matrix (Complex Double), Vector Double, Matrix (Complex Double)) | ||
73 | svdC x = unsafePerformIO $ do | ||
74 | u <- createMatrix ColumnMajor r r | ||
75 | s <- createVector (min r c) | ||
76 | v <- createMatrix ColumnMajor c c | ||
77 | zgesvd // mat fdat x // mat dat u // vec s // mat dat v // check "svdC" [fdat x] | ||
78 | return (u,s,trans v) | ||
79 | where r = rows x | ||
80 | c = cols x | ||
81 | |||
82 | |||
83 | ----------------------------------------------------------------------------- | ||
84 | foreign import ccall "LAPACK/lapack-aux.h eig_l_C" zgeev :: TCMCMCVCM | ||
85 | |||
86 | -- | Wrapper for LAPACK's /zgeev/, which computes the eigenvalues and right eigenvectors of a general complex matrix: | ||
87 | -- | ||
88 | -- if @(l,v)=eigC m@ then @m \<\> v = v \<\> diag l@. | ||
89 | -- | ||
90 | -- The eigenvectors are the columns of v. | ||
91 | -- The eigenvalues are not sorted. | ||
92 | eigC :: Matrix (Complex Double) -> (Vector (Complex Double), Matrix (Complex Double)) | ||
93 | eigC m | ||
94 | | r == 1 = (fromList [cdat m `at` 0], singleton 1) | ||
95 | | otherwise = unsafePerformIO $ do | ||
96 | l <- createVector r | ||
97 | v <- createMatrix ColumnMajor r r | ||
98 | dummy <- createMatrix ColumnMajor 1 1 | ||
99 | zgeev // mat fdat m // mat dat dummy // vec l // mat dat v // check "eigC" [fdat m] | ||
100 | return (l,v) | ||
101 | where r = rows m | ||
102 | |||
103 | ----------------------------------------------------------------------------- | ||
104 | foreign import ccall "LAPACK/lapack-aux.h eig_l_R" dgeev :: TMMCVM | ||
105 | |||
106 | -- | Wrapper for LAPACK's /dgeev/, which computes the eigenvalues and right eigenvectors of a general real matrix: | ||
107 | -- | ||
108 | -- if @(l,v)=eigR m@ then @m \<\> v = v \<\> diag l@. | ||
109 | -- | ||
110 | -- The eigenvectors are the columns of v. | ||
111 | -- The eigenvalues are not sorted. | ||
112 | eigR :: Matrix Double -> (Vector (Complex Double), Matrix (Complex Double)) | ||
113 | eigR m = (s', v'') | ||
114 | where (s,v) = eigRaux m | ||
115 | s' = toComplex (subVector 0 r (asReal s), subVector r r (asReal s)) | ||
116 | v' = toRows $ trans v | ||
117 | v'' = fromColumns $ fixeig (toList s') v' | ||
118 | r = rows m | ||
119 | |||
120 | eigRaux :: Matrix Double -> (Vector (Complex Double), Matrix Double) | ||
121 | eigRaux m | ||
122 | | r == 1 = (fromList [(cdat m `at` 0):+0], singleton 1) | ||
123 | | otherwise = unsafePerformIO $ do | ||
124 | l <- createVector r | ||
125 | v <- createMatrix ColumnMajor r r | ||
126 | dummy <- createMatrix ColumnMajor 1 1 | ||
127 | dgeev // mat fdat m // mat dat dummy // vec l // mat dat v // check "eigR" [fdat m] | ||
128 | return (l,v) | ||
129 | where r = rows m | ||
130 | |||
131 | fixeig [] _ = [] | ||
132 | fixeig [r] [v] = [comp v] | ||
133 | fixeig ((r1:+i1):(r2:+i2):r) (v1:v2:vs) | ||
134 | | r1 == r2 && i1 == (-i2) = toComplex (v1,v2) : toComplex (v1,scale (-1) v2) : fixeig r vs | ||
135 | | otherwise = comp v1 : fixeig ((r2:+i2):r) (v2:vs) | ||
136 | where scale = vectorMapValR Scale | ||
137 | |||
138 | ----------------------------------------------------------------------------- | ||
139 | foreign import ccall "LAPACK/lapack-aux.h eig_l_S" dsyev :: TMVM | ||
140 | |||
141 | -- | Wrapper for LAPACK's /dsyev/, which computes the eigenvalues and right eigenvectors of a symmetric real matrix: | ||
142 | -- | ||
143 | -- if @(l,v)=eigSl m@ then @m \<\> v = v \<\> diag l@. | ||
144 | -- | ||
145 | -- The eigenvectors are the columns of v. | ||
146 | -- The eigenvalues are sorted in descending order (use eigS' for ascending order). | ||
147 | eigS :: Matrix Double -> (Vector Double, Matrix Double) | ||
148 | eigS m = (s', fliprl v) | ||
149 | where (s,v) = eigS' m | ||
150 | s' = fromList . reverse . toList $ s | ||
151 | |||
152 | eigS' m | ||
153 | | r == 1 = (fromList [cdat m `at` 0], singleton 1) | ||
154 | | otherwise = unsafePerformIO $ do | ||
155 | l <- createVector r | ||
156 | v <- createMatrix ColumnMajor r r | ||
157 | dsyev // mat fdat m // vec l // mat dat v // check "eigS" [fdat m] | ||
158 | return (l,v) | ||
159 | where r = rows m | ||
160 | |||
161 | ----------------------------------------------------------------------------- | ||
162 | foreign import ccall "LAPACK/lapack-aux.h eig_l_H" zheev :: TCMVCM | ||
163 | |||
164 | -- | Wrapper for LAPACK's /zheev/, which computes the eigenvalues and right eigenvectors of a hermitian complex matrix: | ||
165 | -- | ||
166 | -- if @(l,v)=eigH m@ then @m \<\> s v = v \<\> diag l@. | ||
167 | -- | ||
168 | -- The eigenvectors are the columns of v. | ||
169 | -- The eigenvalues are sorted in descending order. | ||
170 | eigH :: Matrix (Complex Double) -> (Vector Double, Matrix (Complex Double)) | ||
171 | eigH m = (s', fliprl v) | ||
172 | where (s,v) = eigH' m | ||
173 | s' = fromList . reverse . toList $ s | ||
174 | |||
175 | eigH' m | ||
176 | | r == 1 = (fromList [realPart (cdat m `at` 0)], singleton 1) | ||
177 | | otherwise = unsafePerformIO $ do | ||
178 | l <- createVector r | ||
179 | v <- createMatrix ColumnMajor r r | ||
180 | zheev // mat fdat m // vec l // mat dat v // check "eigH" [fdat m] | ||
181 | return (l,v) | ||
182 | where r = rows m | ||
183 | |||
184 | ----------------------------------------------------------------------------- | ||
185 | foreign import ccall "LAPACK/lapack-aux.h linearSolveR_l" dgesv :: TMMM | ||
186 | |||
187 | -- | Wrapper for LAPACK's /dgesv/, which solves a general real linear system (for several right-hand sides) internally using the lu decomposition. | ||
188 | linearSolveR :: Matrix Double -> Matrix Double -> Matrix Double | ||
189 | linearSolveR a b | ||
190 | | n1==n2 && n1==r = unsafePerformIO $ do | ||
191 | s <- createMatrix ColumnMajor r c | ||
192 | dgesv // mat fdat a // mat fdat b // mat dat s // check "linearSolveR" [fdat a, fdat b] | ||
193 | return s | ||
194 | | otherwise = error "linearSolveR of nonsquare matrix" | ||
195 | where n1 = rows a | ||
196 | n2 = cols a | ||
197 | r = rows b | ||
198 | c = cols b | ||
199 | |||
200 | ----------------------------------------------------------------------------- | ||
201 | foreign import ccall "LAPACK/lapack-aux.h linearSolveC_l" zgesv :: TCMCMCM | ||
202 | |||
203 | -- | Wrapper for LAPACK's /zgesv/, which solves a general complex linear system (for several right-hand sides) internally using the lu decomposition. | ||
204 | linearSolveC :: Matrix (Complex Double) -> Matrix (Complex Double) -> Matrix (Complex Double) | ||
205 | linearSolveC a b | ||
206 | | n1==n2 && n1==r = unsafePerformIO $ do | ||
207 | s <- createMatrix ColumnMajor r c | ||
208 | zgesv // mat fdat a // mat fdat b // mat dat s // check "linearSolveC" [fdat a, fdat b] | ||
209 | return s | ||
210 | | otherwise = error "linearSolveC of nonsquare matrix" | ||
211 | where n1 = rows a | ||
212 | n2 = cols a | ||
213 | r = rows b | ||
214 | c = cols b | ||
215 | |||
216 | ----------------------------------------------------------------------------------- | ||
217 | foreign import ccall "LAPACK/lapack-aux.h linearSolveLSR_l" dgels :: TMMM | ||
218 | |||
219 | -- | Wrapper for LAPACK's /dgels/, which obtains the least squared error solution of an overconstrained real linear system or the minimum norm solution of an underdetermined system, for several right-hand sides. For rank deficient systems use 'linearSolveSVDR'. | ||
220 | linearSolveLSR :: Matrix Double -> Matrix Double -> Matrix Double | ||
221 | linearSolveLSR a b = subMatrix (0,0) (cols a, cols b) $ linearSolveLSR_l a b | ||
222 | |||
223 | linearSolveLSR_l a b = unsafePerformIO $ do | ||
224 | r <- createMatrix ColumnMajor (max m n) nrhs | ||
225 | dgels // mat fdat a // mat fdat b // mat dat r // check "linearSolveLSR" [fdat a, fdat b] | ||
226 | return r | ||
227 | where m = rows a | ||
228 | n = cols a | ||
229 | nrhs = cols b | ||
230 | |||
231 | ----------------------------------------------------------------------------------- | ||
232 | foreign import ccall "LAPACK/lapack-aux.h linearSolveLSC_l" zgels :: TCMCMCM | ||
233 | |||
234 | -- | Wrapper for LAPACK's /zgels/, which obtains the least squared error solution of an overconstrained complex linear system or the minimum norm solution of an underdetermined system, for several right-hand sides. For rank deficient systems use 'linearSolveSVDC'. | ||
235 | linearSolveLSC :: Matrix (Complex Double) -> Matrix (Complex Double) -> Matrix (Complex Double) | ||
236 | linearSolveLSC a b = subMatrix (0,0) (cols a, cols b) $ linearSolveLSC_l a b | ||
237 | |||
238 | linearSolveLSC_l a b = unsafePerformIO $ do | ||
239 | r <- createMatrix ColumnMajor (max m n) nrhs | ||
240 | zgels // mat fdat a // mat fdat b // mat dat r // check "linearSolveLSC" [fdat a, fdat b] | ||
241 | return r | ||
242 | where m = rows a | ||
243 | n = cols a | ||
244 | nrhs = cols b | ||
245 | |||
246 | ----------------------------------------------------------------------------------- | ||
247 | foreign import ccall "LAPACK/lapack-aux.h linearSolveSVDR_l" dgelss :: Double -> TMMM | ||
248 | |||
249 | -- | Wrapper for LAPACK's /dgelss/, which obtains the minimum norm solution to a real linear least squares problem Ax=B using the svd, for several right-hand sides. Admits rank deficient systems but it is slower than 'linearSolveLSR'. The effective rank of A is determined by treating as zero those singular valures which are less than rcond times the largest singular value. If rcond == Nothing machine precision is used. | ||
250 | linearSolveSVDR :: Maybe Double -- ^ rcond | ||
251 | -> Matrix Double -- ^ coefficient matrix | ||
252 | -> Matrix Double -- ^ right hand sides (as columns) | ||
253 | -> Matrix Double -- ^ solution vectors (as columns) | ||
254 | linearSolveSVDR (Just rcond) a b = subMatrix (0,0) (cols a, cols b) $ linearSolveSVDR_l rcond a b | ||
255 | linearSolveSVDR Nothing a b = linearSolveSVDR (Just (-1)) a b | ||
256 | |||
257 | linearSolveSVDR_l rcond a b = unsafePerformIO $ do | ||
258 | r <- createMatrix ColumnMajor (max m n) nrhs | ||
259 | dgelss rcond // mat fdat a // mat fdat b // mat dat r // check "linearSolveSVDR" [fdat a, fdat b] | ||
260 | return r | ||
261 | where m = rows a | ||
262 | n = cols a | ||
263 | nrhs = cols b | ||
264 | |||
265 | ----------------------------------------------------------------------------------- | ||
266 | foreign import ccall "LAPACK/lapack-aux.h linearSolveSVDC_l" zgelss :: Double -> TCMCMCM | ||
267 | |||
268 | -- | Wrapper for LAPACK's /zgelss/, which obtains the minimum norm solution to a complex linear least squares problem Ax=B using the svd, for several right-hand sides. Admits rank deficient systems but it is slower than 'linearSolveLSC'. The effective rank of A is determined by treating as zero those singular valures which are less than rcond times the largest singular value. If rcond == Nothing machine precision is used. | ||
269 | linearSolveSVDC :: Maybe Double -- ^ rcond | ||
270 | -> Matrix (Complex Double) -- ^ coefficient matrix | ||
271 | -> Matrix (Complex Double) -- ^ right hand sides (as columns) | ||
272 | -> Matrix (Complex Double) -- ^ solution vectors (as columns) | ||
273 | linearSolveSVDC (Just rcond) a b = subMatrix (0,0) (cols a, cols b) $ linearSolveSVDC_l rcond a b | ||
274 | linearSolveSVDC Nothing a b = linearSolveSVDC (Just (-1)) a b | ||
275 | |||
276 | linearSolveSVDC_l rcond a b = unsafePerformIO $ do | ||
277 | r <- createMatrix ColumnMajor (max m n) nrhs | ||
278 | zgelss rcond // mat fdat a // mat fdat b // mat dat r // check "linearSolveSVDC" [fdat a, fdat b] | ||
279 | return r | ||
280 | where m = rows a | ||
281 | n = cols a | ||
282 | nrhs = cols b | ||
283 | |||
284 | ----------------------------------------------------------------------------------- | ||
285 | foreign import ccall "LAPACK/lapack-aux.h chol_l_H" zpotrf :: TCMCM | ||
286 | |||
287 | -- | Wrapper for LAPACK's /zpotrf/,which computes the Cholesky factorization of a | ||
288 | -- complex Hermitian positive definite matrix. | ||
289 | cholH :: Matrix (Complex Double) -> Matrix (Complex Double) | ||
290 | cholH a = unsafePerformIO $ do | ||
291 | r <- createMatrix ColumnMajor n n | ||
292 | zpotrf // mat fdat a // mat dat r // check "cholH" [fdat a] | ||
293 | return r | ||
294 | where n = rows a | ||
295 | |||
296 | ----------------------------------------------------------------------------------- | ||
297 | foreign import ccall "LAPACK/lapack-aux.h chol_l_S" dpotrf :: TMM | ||
298 | |||
299 | -- | Wrapper for LAPACK's /dpotrf/,which computes the Cholesky factorization of a | ||
300 | -- real symmetric positive definite matrix. | ||
301 | cholS :: Matrix Double -> Matrix Double | ||
302 | cholS a = unsafePerformIO $ do | ||
303 | r <- createMatrix ColumnMajor n n | ||
304 | dpotrf // mat fdat a // mat dat r // check "cholS" [fdat a] | ||
305 | return r | ||
306 | where n = rows a | ||
307 | |||
308 | ----------------------------------------------------------------------------------- | ||
309 | foreign import ccall "LAPACK/lapack-aux.h qr_l_R" dgeqr2 :: TMVM | ||
310 | |||
311 | -- | Wrapper for LAPACK's /dgeqr2/,which computes a QR factorization of a real matrix. | ||
312 | qrR :: Matrix Double -> (Matrix Double, Vector Double) | ||
313 | qrR a = unsafePerformIO $ do | ||
314 | r <- createMatrix ColumnMajor m n | ||
315 | tau <- createVector mn | ||
316 | dgeqr2 // mat fdat a // vec tau // mat dat r // check "qrR" [fdat a] | ||
317 | return (r,tau) | ||
318 | where m = rows a | ||
319 | n = cols a | ||
320 | mn = min m n | ||
321 | |||
322 | ----------------------------------------------------------------------------------- | ||
323 | foreign import ccall "LAPACK/lapack-aux.h qr_l_C" zgeqr2 :: TCMCVCM | ||
324 | |||
325 | -- | Wrapper for LAPACK's /zgeqr2/,which computes a QR factorization of a complex matrix. | ||
326 | qrC :: Matrix (Complex Double) -> (Matrix (Complex Double), Vector (Complex Double)) | ||
327 | qrC a = unsafePerformIO $ do | ||
328 | r <- createMatrix ColumnMajor m n | ||
329 | tau <- createVector mn | ||
330 | zgeqr2 // mat fdat a // vec tau // mat dat r // check "qrC" [fdat a] | ||
331 | return (r,tau) | ||
332 | where m = rows a | ||
333 | n = cols a | ||
334 | mn = min m n | ||
335 | |||