diff options
Diffstat (limited to 'lib/Numeric/LinearAlgebra/Algorithms.hs')
-rw-r--r-- | lib/Numeric/LinearAlgebra/Algorithms.hs | 73 |
1 files changed, 47 insertions, 26 deletions
diff --git a/lib/Numeric/LinearAlgebra/Algorithms.hs b/lib/Numeric/LinearAlgebra/Algorithms.hs index 0f3ff0e..28063a9 100644 --- a/lib/Numeric/LinearAlgebra/Algorithms.hs +++ b/lib/Numeric/LinearAlgebra/Algorithms.hs | |||
@@ -61,9 +61,10 @@ module Numeric.LinearAlgebra.Algorithms ( | |||
61 | nullspacePrec, | 61 | nullspacePrec, |
62 | nullVector, | 62 | nullVector, |
63 | nullspaceSVD, | 63 | nullspaceSVD, |
64 | -- * Norms | ||
65 | Normed(..), NormType(..), | ||
64 | -- * Misc | 66 | -- * Misc |
65 | eps, peps, i, | 67 | eps, peps, i, |
66 | Normed(..), NormType(..), | ||
67 | -- * Util | 68 | -- * Util |
68 | haussholder, | 69 | haussholder, |
69 | unpackQR, unpackHess, | 70 | unpackQR, unpackHess, |
@@ -172,9 +173,6 @@ thinSVD = {-# SCC "thinSVD" #-} thinSVD' | |||
172 | singularValues :: Field t => Matrix t -> Vector Double | 173 | singularValues :: Field t => Matrix t -> Vector Double |
173 | singularValues = {-# SCC "singularValues" #-} sv' | 174 | singularValues = {-# SCC "singularValues" #-} sv' |
174 | 175 | ||
175 | instance (Field t, RealOf t ~ Double) => Norm2 Matrix t where | ||
176 | norm2 m = singularValues m @> 0 | ||
177 | |||
178 | -- | A version of 'svd' which returns an appropriate diagonal matrix with the singular values. | 176 | -- | A version of 'svd' which returns an appropriate diagonal matrix with the singular values. |
179 | -- | 177 | -- |
180 | -- If @(u,d,v) = fullSVD m@ then @m == u \<> d \<> trans v@. | 178 | -- If @(u,d,v) = fullSVD m@ then @m == u \<> d \<> trans v@. |
@@ -546,7 +544,7 @@ epslist = [ (fromIntegral k, golubeps k k) | k <- [1..]] | |||
546 | geps delta = head [ k | (k,g) <- epslist, g<delta] | 544 | geps delta = head [ k | (k,g) <- epslist, g<delta] |
547 | 545 | ||
548 | expGolub m = iterate msq f !! j | 546 | expGolub m = iterate msq f !! j |
549 | where j = max 0 $ floor $ log2 $ normInf m | 547 | where j = max 0 $ floor $ log2 $ pnorm Infinity m |
550 | log2 x = log x / log 2 | 548 | log2 x = log x / log 2 |
551 | a = m */ fromIntegral ((2::Int)^j) | 549 | a = m */ fromIntegral ((2::Int)^j) |
552 | q = geps eps -- 7 steps | 550 | q = geps eps -- 7 steps |
@@ -569,7 +567,7 @@ expGolub m = iterate msq f !! j | |||
569 | {- | Matrix exponential. It uses a direct translation of Algorithm 11.3.1 in Golub & Van Loan, | 567 | {- | Matrix exponential. It uses a direct translation of Algorithm 11.3.1 in Golub & Van Loan, |
570 | based on a scaled Pade approximation. | 568 | based on a scaled Pade approximation. |
571 | -} | 569 | -} |
572 | expm :: (Norm Vector t, Field t) => Matrix t -> Matrix t | 570 | expm :: (Normed (Matrix t), Field t) => Matrix t -> Matrix t |
573 | expm = expGolub | 571 | expm = expGolub |
574 | 572 | ||
575 | -------------------------------------------------------------- | 573 | -------------------------------------------------------------- |
@@ -585,11 +583,11 @@ It only works with invertible matrices that have a real solution. For diagonaliz | |||
585 | [ 2.0, 2.25 | 583 | [ 2.0, 2.25 |
586 | , 0.0, 2.0 ]@ | 584 | , 0.0, 2.0 ]@ |
587 | -} | 585 | -} |
588 | sqrtm :: (Norm Vector t, Field t) => Matrix t -> Matrix t | 586 | sqrtm :: (Normed (Matrix t), Field t) => Matrix t -> Matrix t |
589 | sqrtm = sqrtmInv | 587 | sqrtm = sqrtmInv |
590 | 588 | ||
591 | sqrtmInv x = fst $ fixedPoint $ iterate f (x, ident (rows x)) | 589 | sqrtmInv x = fst $ fixedPoint $ iterate f (x, ident (rows x)) |
592 | where fixedPoint (a:b:rest) | norm1 (fst a |-| fst b) < peps = a | 590 | where fixedPoint (a:b:rest) | pnorm PNorm1 (fst a |-| fst b) < peps = a |
593 | | otherwise = fixedPoint (b:rest) | 591 | | otherwise = fixedPoint (b:rest) |
594 | fixedPoint _ = error "fixedpoint with impossible inputs" | 592 | fixedPoint _ = error "fixedpoint with impossible inputs" |
595 | f (y,z) = (0.5 .* (y |+| inv z), | 593 | f (y,z) = (0.5 .* (y |+| inv z), |
@@ -632,33 +630,56 @@ luFact (l_u,perm) | r <= c = (l ,u ,p, s) | |||
632 | 630 | ||
633 | --------------------------------------------------------------------------- | 631 | --------------------------------------------------------------------------- |
634 | 632 | ||
635 | data NormType = Infinity | PNorm1 | PNorm2 | 633 | data NormType = Infinity | PNorm1 | PNorm2 | Frobenius |
636 | 634 | ||
637 | -- | Old class | ||
638 | class Normed t where | 635 | class Normed t where |
639 | pnorm :: NormType -> t -> Double | 636 | pnorm :: NormType -> t -> Double |
640 | 637 | ||
641 | instance Norm Vector t => Normed (Vector t) where | 638 | instance Normed (Vector Double) where |
642 | pnorm PNorm1 = realToFrac . norm1 | 639 | pnorm PNorm1 = norm1 |
643 | pnorm PNorm2 = realToFrac . normFrob | 640 | pnorm PNorm2 = norm2 |
644 | pnorm Infinity = realToFrac . normInf | 641 | pnorm Infinity = normInf |
642 | pnorm Frobenius = normInf | ||
643 | |||
644 | instance Normed (Vector (Complex Double)) where | ||
645 | pnorm PNorm1 = realPart . norm1 | ||
646 | pnorm PNorm2 = realPart . norm2 | ||
647 | pnorm Infinity = realPart . normInf | ||
648 | pnorm Frobenius = realPart . normInf | ||
649 | |||
650 | instance Normed (Vector Float) where | ||
651 | pnorm PNorm1 = realToFrac . norm1 | ||
652 | pnorm PNorm2 = realToFrac . norm2 | ||
653 | pnorm Infinity = realToFrac . normInf | ||
654 | pnorm Frobenius = realToFrac . normInf | ||
655 | |||
656 | instance Normed (Vector (Complex Float)) where | ||
657 | pnorm PNorm1 = realToFrac . realPart . norm1 | ||
658 | pnorm PNorm2 = realToFrac . realPart . norm2 | ||
659 | pnorm Infinity = realToFrac . realPart . normInf | ||
660 | pnorm Frobenius = realToFrac . realPart . normInf | ||
661 | |||
645 | 662 | ||
646 | instance Normed (Matrix Double) where | 663 | instance Normed (Matrix Double) where |
647 | pnorm PNorm1 = norm1 | 664 | pnorm PNorm1 = maximum . map norm1 . toColumns |
648 | pnorm PNorm2 = norm2 | 665 | pnorm PNorm2 = (@>0) . singularValues |
649 | pnorm Infinity = normInf | 666 | pnorm Infinity = pnorm PNorm1 . trans |
667 | pnorm Frobenius = norm2 . flatten | ||
650 | 668 | ||
651 | instance Normed (Matrix (Complex Double)) where | 669 | instance Normed (Matrix (Complex Double)) where |
652 | pnorm PNorm1 = norm1 | 670 | pnorm PNorm1 = maximum . map (realPart.norm1) . toColumns |
653 | pnorm PNorm2 = norm2 | 671 | pnorm PNorm2 = (@>0) . singularValues |
654 | pnorm Infinity = normInf | 672 | pnorm Infinity = pnorm PNorm1 . trans |
673 | pnorm Frobenius = realPart . norm2 . flatten | ||
655 | 674 | ||
656 | instance Normed (Matrix Float) where | 675 | instance Normed (Matrix Float) where |
657 | pnorm PNorm1 = realToFrac . norm1 | 676 | pnorm PNorm1 = realToFrac . maximum . map norm1 . toColumns |
658 | pnorm PNorm2 = norm2 . double -- not yet optimized for Float | 677 | pnorm PNorm2 = realToFrac . (@>0) . singularValues . double |
659 | pnorm Infinity = realToFrac . normInf | 678 | pnorm Infinity = realToFrac . pnorm PNorm1 . trans |
679 | pnorm Frobenius = realToFrac . norm2 . flatten | ||
660 | 680 | ||
661 | instance Normed (Matrix (Complex Float)) where | 681 | instance Normed (Matrix (Complex Float)) where |
662 | pnorm PNorm1 = realToFrac . norm1 | 682 | pnorm PNorm1 = realToFrac . maximum . map (realPart.norm1) . toColumns |
663 | pnorm PNorm2 = norm2 . double -- not yet optimized for Float | 683 | pnorm PNorm2 = realToFrac . (@>0) . singularValues . double |
664 | pnorm Infinity = realToFrac . normInf | 684 | pnorm Infinity = realToFrac . pnorm PNorm1 . trans |
685 | pnorm Frobenius = realToFrac . realPart . norm2 . flatten | ||