summaryrefslogtreecommitdiff
path: root/lib/Numeric
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Numeric')
-rw-r--r--lib/Numeric/LinearAlgebra/Algorithms.hs31
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--
384matFunc :: Field t => (Complex Double -> Complex Double) -> Matrix t -> Matrix (Complex Double) 388matFunc :: Field t => (Complex Double -> Complex Double) -> Matrix t -> Matrix (Complex Double)
385matFunc f m = case diagonalize (complex m) of 389matFunc 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-}
423expm :: Field t => Matrix t -> Matrix t 427expm :: Field t => Matrix t -> Matrix t
424expm = expGolub 428expm = expGolub
429
430--------------------------------------------------------------
431
432{- | Matrix square root. Currently it uses a simple iterative algorithm described in Wikipedia.
433It 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-}
443sqrtm :: Field t => Matrix t -> Matrix t
444sqrtm = sqrtmInv
445
446sqrtmInv 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