X-Git-Url: http://gitweb.michael.orlitzky.com/?a=blobdiff_plain;f=src%2FLinear%2FMatrix.hs;h=d166e44367e626b9d87979a4b0e9ab7b2b24e7d9;hb=3cb0f69fa38e5f46a2374d48168acf69bfc9e910;hp=7452007990e0e015c45610b03605cf6cfc642aad;hpb=1f64a1a33b2636ef2e863a0b577c8d8d50233580;p=numerical-analysis.git diff --git a/src/Linear/Matrix.hs b/src/Linear/Matrix.hs index 7452007..d166e44 100644 --- a/src/Linear/Matrix.hs +++ b/src/Linear/Matrix.hs @@ -17,6 +17,7 @@ where import Data.List (intercalate) import Data.Vector.Fixed ( + (!), N1, N2, N3, @@ -33,6 +34,7 @@ import Data.Vector.Fixed ( import qualified Data.Vector.Fixed as V ( and, fromList, + head, length, map, maximum, @@ -41,7 +43,7 @@ import qualified Data.Vector.Fixed as V ( zipWith ) import Data.Vector.Fixed.Boxed (Vec) -import Data.Vector.Fixed.Internal (Arity, arity) +import Data.Vector.Fixed.Cont (Arity, arity) import Linear.Vector import Normed @@ -340,13 +342,21 @@ class (Eq a, Ring.C a) => Determined p a where determinant :: (p a) -> a instance (Eq a, Ring.C a) => Determined (Mat (S Z) (S Z)) a where - determinant m = m !!! (0,0) + determinant (Mat rows) = (V.head . V.head) rows -instance (Eq a, Ring.C a, Arity m) => Determined (Mat m m) a where - determinant _ = undefined - -instance (Eq a, Ring.C a, Arity n) +instance (Eq a, + Ring.C a, + Arity n, + Determined (Mat (S n) (S n)) a) => Determined (Mat (S (S n)) (S (S n))) a where + -- | The recursive definition with a special-case for triangular matrices. + -- + -- Examples: + -- + -- >>> let m = fromList [[1,2],[3,4]] :: Mat2 Int + -- >>> determinant m + -- -1 + -- determinant m | is_triangular m = product [ m !!! (i,i) | i <- [0..(nrows m)-1] ] | otherwise = determinant_recursive @@ -356,13 +366,12 @@ instance (Eq a, Ring.C a, Arity n) det_minor i j = determinant (minor m i j) determinant_recursive = - sum [ (-1)^(1+(toInteger j)) NP.* (m' 0 j) NP.* (det_minor 0 j) + sum [ (-1)^(toInteger j) NP.* (m' 0 j) NP.* (det_minor 0 j) | j <- [0..(ncols m)-1] ] --- | Matrix multiplication. Our 'Num' instance doesn't define one, and --- we need additional restrictions on the result type anyway. +-- | Matrix multiplication. -- -- Examples: -- @@ -408,9 +417,8 @@ instance (Ring.C a, Arity m, Arity n) => Module.C a (Mat m n a) where instance (Algebraic.C a, ToRational.C a, - Arity m, - Arity n) - => Normed (Mat (S m) (S n) a) where + Arity m) + => Normed (Mat (S m) N1 a) where -- | Generic p-norms. The usual norm in R^n is (norm_p 2). We treat -- all matrices as big vectors. -- @@ -423,7 +431,7 @@ instance (Algebraic.C a, -- 5.0 -- norm_p p (Mat rows) = - (root p') $ sum [(fromRational' $ toRational x)^p' | x <- xs] + (root p') $ sum [fromRational' (toRational x)^p' | x <- xs] where p' = toInteger p xs = concat $ V.toList $ V.map V.toList rows @@ -512,3 +520,93 @@ angle v1 v2 = where theta = (recip norms) NP.* (v1 `dot` v2) norms = (norm v1) NP.* (norm v2) + + + +-- | Given a square @matrix@, return a new matrix of the same size +-- containing only the on-diagonal entries of @matrix@. The +-- off-diagonal entries are set to zero. +-- +-- Examples: +-- +-- >>> let m = fromList [[1,2,3],[4,5,6],[7,8,9]] :: Mat3 Int +-- >>> diagonal_part m +-- ((1,0,0),(0,5,0),(0,0,9)) +-- +diagonal_part :: (Arity m, Ring.C a) + => Mat m m a + -> Mat m m a +diagonal_part matrix = + construct lambda + where + lambda i j = if i == j then matrix !!! (i,j) else 0 + + +-- | Given a square @matrix@, return a new matrix of the same size +-- containing only the on-diagonal and below-diagonal entries of +-- @matrix@. The above-diagonal entries are set to zero. +-- +-- Examples: +-- +-- >>> let m = fromList [[1,2,3],[4,5,6],[7,8,9]] :: Mat3 Int +-- >>> lt_part m +-- ((1,0,0),(4,5,0),(7,8,9)) +-- +lt_part :: (Arity m, Ring.C a) + => Mat m m a + -> Mat m m a +lt_part matrix = + construct lambda + where + lambda i j = if i >= j then matrix !!! (i,j) else 0 + + +-- | Given a square @matrix@, return a new matrix of the same size +-- containing only the below-diagonal entries of @matrix@. The on- +-- and above-diagonal entries are set to zero. +-- +-- Examples: +-- +-- >>> let m = fromList [[1,2,3],[4,5,6],[7,8,9]] :: Mat3 Int +-- >>> lt_part_strict m +-- ((0,0,0),(4,0,0),(7,8,0)) +-- +lt_part_strict :: (Arity m, Ring.C a) + => Mat m m a + -> Mat m m a +lt_part_strict matrix = + construct lambda + where + lambda i j = if i > j then matrix !!! (i,j) else 0 + + +-- | Given a square @matrix@, return a new matrix of the same size +-- containing only the on-diagonal and above-diagonal entries of +-- @matrix@. The below-diagonal entries are set to zero. +-- +-- Examples: +-- +-- >>> let m = fromList [[1,2,3],[4,5,6],[7,8,9]] :: Mat3 Int +-- >>> ut_part m +-- ((1,2,3),(0,5,6),(0,0,9)) +-- +ut_part :: (Arity m, Ring.C a) + => Mat m m a + -> Mat m m a +ut_part = transpose . lt_part . transpose + + +-- | Given a square @matrix@, return a new matrix of the same size +-- containing only the above-diagonal entries of @matrix@. The on- +-- and below-diagonal entries are set to zero. +-- +-- Examples: +-- +-- >>> let m = fromList [[1,2,3],[4,5,6],[7,8,9]] :: Mat3 Int +-- >>> ut_part_strict m +-- ((0,2,3),(0,0,6),(0,0,0)) +-- +ut_part_strict :: (Arity m, Ring.C a) + => Mat m m a + -> Mat m m a +ut_part_strict = transpose . lt_part_strict . transpose