diff options
-rw-r--r-- | lib/Numeric/LinearAlgebra/Algorithms.hs | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/lib/Numeric/LinearAlgebra/Algorithms.hs b/lib/Numeric/LinearAlgebra/Algorithms.hs index b7e208a..16ea32a 100644 --- a/lib/Numeric/LinearAlgebra/Algorithms.hs +++ b/lib/Numeric/LinearAlgebra/Algorithms.hs | |||
@@ -39,6 +39,7 @@ module Numeric.LinearAlgebra.Algorithms ( | |||
39 | schur, | 39 | schur, |
40 | -- * Matrix functions | 40 | -- * Matrix functions |
41 | expm, | 41 | expm, |
42 | sqrtm, | ||
42 | matFunc, | 43 | matFunc, |
43 | -- * Nullspace | 44 | -- * Nullspace |
44 | nullspacePrec, | 45 | nullspacePrec, |
@@ -380,7 +381,10 @@ diagonalize m = if rank v == n | |||
380 | then let (l',v') = eigSH m in (real l', v') | 381 | then let (l',v') = eigSH m in (real l', v') |
381 | else eig m | 382 | else eig m |
382 | 383 | ||
383 | -- | Generic matrix functions for diagonalizable matrices. | 384 | -- | Generic matrix functions for diagonalizable matrices. For instance: |
385 | -- | ||
386 | -- @logm = matFunc log@ | ||
387 | -- | ||
384 | matFunc :: Field t => (Complex Double -> Complex Double) -> Matrix t -> Matrix (Complex Double) | 388 | matFunc :: Field t => (Complex Double -> Complex Double) -> Matrix t -> Matrix (Complex Double) |
385 | matFunc f m = case diagonalize (complex m) of | 389 | matFunc f m = case diagonalize (complex m) of |
386 | Just (l,v) -> v `mXm` diag (liftVector f l) `mXm` inv v | 390 | Just (l,v) -> v `mXm` diag (liftVector f l) `mXm` inv v |
@@ -422,3 +426,28 @@ expGolub m = iterate msq f !! j | |||
422 | -} | 426 | -} |
423 | expm :: Field t => Matrix t -> Matrix t | 427 | expm :: Field t => Matrix t -> Matrix t |
424 | expm = expGolub | 428 | expm = expGolub |
429 | |||
430 | -------------------------------------------------------------- | ||
431 | |||
432 | {- | Matrix square root. Currently it uses a simple iterative algorithm described in Wikipedia. | ||
433 | It only works with invertible matrices that have a real solution. For diagonalizable matrices you can try @matFunc sqrt@. | ||
434 | |||
435 | @m = (2><2) [4,9 | ||
436 | ,0,4] :: Matrix Double@ | ||
437 | |||
438 | @\>sqrtm m | ||
439 | (2><2) | ||
440 | [ 2.0, 2.25 | ||
441 | , 0.0, 2.0 ]@ | ||
442 | -} | ||
443 | sqrtm :: Field t => Matrix t -> Matrix t | ||
444 | sqrtm = sqrtmInv | ||
445 | |||
446 | sqrtmInv a = fst $ fixedPoint $ iterate f (a, ident (rows a)) | ||
447 | where fixedPoint (a:b:rest) | pnorm PNorm1 (fst a |-| fst b) < eps = a | ||
448 | | otherwise = fixedPoint (b:rest) | ||
449 | f (y,z) = (0.5 .* (y |+| inv z), | ||
450 | 0.5 .* (inv y |+| z)) | ||
451 | (.*) = scale | ||
452 | (|+|) = add | ||
453 | (|-|) = sub | ||