diff options
Diffstat (limited to 'lib/Numeric/LinearAlgebra/Algorithms.hs')
-rw-r--r-- | lib/Numeric/LinearAlgebra/Algorithms.hs | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/lib/Numeric/LinearAlgebra/Algorithms.hs b/lib/Numeric/LinearAlgebra/Algorithms.hs index dd93db2..83464f4 100644 --- a/lib/Numeric/LinearAlgebra/Algorithms.hs +++ b/lib/Numeric/LinearAlgebra/Algorithms.hs | |||
@@ -31,7 +31,8 @@ module Numeric.LinearAlgebra.Algorithms ( | |||
31 | linearSolveLS, | 31 | linearSolveLS, |
32 | linearSolveSVD, | 32 | linearSolveSVD, |
33 | inv, pinv, | 33 | inv, pinv, |
34 | det, rank, rcond, | 34 | det, invlndet, |
35 | rank, rcond, | ||
35 | -- * Matrix factorizations | 36 | -- * Matrix factorizations |
36 | -- ** Singular value decomposition | 37 | -- ** Singular value decomposition |
37 | svd, | 38 | svd, |
@@ -166,6 +167,8 @@ vertical m = rows m >= cols m | |||
166 | 167 | ||
167 | exactHermitian m = m `equal` ctrans m | 168 | exactHermitian m = m `equal` ctrans m |
168 | 169 | ||
170 | shSize m = "(" ++ show (rows m) ++"><"++ show (cols m)++")" | ||
171 | |||
169 | -------------------------------------------------------------- | 172 | -------------------------------------------------------------- |
170 | 173 | ||
171 | -- | Full singular value decomposition. | 174 | -- | Full singular value decomposition. |
@@ -341,12 +344,25 @@ chol m | exactHermitian m = cholSH m | |||
341 | | otherwise = error "chol requires positive definite complex hermitian or real symmetric matrix" | 344 | | otherwise = error "chol requires positive definite complex hermitian or real symmetric matrix" |
342 | 345 | ||
343 | 346 | ||
347 | -- | Joint computation of inverse and logarithm of determinant of a square matrix. | ||
348 | invlndet :: (Floating t, Field t) | ||
349 | => Matrix t | ||
350 | -> (Matrix t, (t, t)) -- ^ (inverse, (log abs det, sign or phase of det)) | ||
351 | invlndet m | square m = (im,(ladm,sdm)) | ||
352 | | otherwise = error $ "invlndet of nonsquare "++ shSize m ++ " matrix" | ||
353 | where | ||
354 | lp@(lup,perm) = luPacked m | ||
355 | s = signlp (rows m) perm | ||
356 | dg = toList $ takeDiag $ lup | ||
357 | ladm = sum $ map (log.abs) dg | ||
358 | sdm = s* product (map signum dg) | ||
359 | im = luSolve lp (ident (rows m)) | ||
344 | 360 | ||
345 | 361 | ||
346 | -- | Determinant of a square matrix. | 362 | -- | Determinant of a square matrix. To avoid possible overflow or underflow use 'invlndet'. |
347 | det :: Field t => Matrix t -> t | 363 | det :: Field t => Matrix t -> t |
348 | det m | square m = {-# SCC "det" #-} s * (product $ toList $ takeDiag $ lup) | 364 | det m | square m = {-# SCC "det" #-} s * (product $ toList $ takeDiag $ lup) |
349 | | otherwise = error "det of nonsquare matrix" | 365 | | otherwise = error $ "det of nonsquare "++ shSize m ++ " matrix" |
350 | where (lup,perm) = luPacked m | 366 | where (lup,perm) = luPacked m |
351 | s = signlp (rows m) perm | 367 | s = signlp (rows m) perm |
352 | 368 | ||
@@ -357,10 +373,10 @@ det m | square m = {-# SCC "det" #-} s * (product $ toList $ takeDiag $ lup) | |||
357 | lu :: Field t => Matrix t -> (Matrix t, Matrix t, Matrix t, t) | 373 | lu :: Field t => Matrix t -> (Matrix t, Matrix t, Matrix t, t) |
358 | lu = luFact . luPacked | 374 | lu = luFact . luPacked |
359 | 375 | ||
360 | -- | Inverse of a square matrix. | 376 | -- | Inverse of a square matrix. See also 'invlndet'. |
361 | inv :: Field t => Matrix t -> Matrix t | 377 | inv :: Field t => Matrix t -> Matrix t |
362 | inv m | square m = m `linearSolve` ident (rows m) | 378 | inv m | square m = m `linearSolve` ident (rows m) |
363 | | otherwise = error "inv of nonsquare matrix" | 379 | | otherwise = error $ "inv of nonsquare "++ shSize m ++ " matrix" |
364 | 380 | ||
365 | -- | Pseudoinverse of a general matrix. | 381 | -- | Pseudoinverse of a general matrix. |
366 | pinv :: Field t => Matrix t -> Matrix t | 382 | pinv :: Field t => Matrix t -> Matrix t |
@@ -697,3 +713,4 @@ relativeError :: (Normed c t, Container c t) => c t -> c t -> Int | |||
697 | relativeError x y = dig (norm (x `sub` y) / norm x) | 713 | relativeError x y = dig (norm (x `sub` y) / norm x) |
698 | where norm = pnorm Infinity | 714 | where norm = pnorm Infinity |
699 | dig r = round $ -logBase 10 (realToFrac r :: Double) | 715 | dig r = round $ -logBase 10 (realToFrac r :: Double) |
716 | |||