-- | -- Module : Statistics.Matrix.Types -- Copyright : 2014 Bryan O'Sullivan -- License : BSD3 -- -- Basic matrix operations. -- -- There isn't a widely used matrix package for Haskell yet, so -- we implement the necessary minimum here. module Statistics.Matrix.Types ( Vector , MVector , Matrix(..) , MMatrix(..) , debug ) where import Data.Char (isSpace) import Numeric (showFFloat) import qualified Data.Vector.Unboxed as U import qualified Data.Vector.Unboxed.Mutable as M type Vector = U.Vector Double type MVector s = M.MVector s Double -- | Two-dimensional matrix, stored in row-major order. data Matrix = Matrix { rows :: {-# UNPACK #-} !Int -- ^ Rows of matrix. , cols :: {-# UNPACK #-} !Int -- ^ Columns of matrix. , exponent :: {-# UNPACK #-} !Int -- ^ In order to avoid overflows during matrix multiplication, a -- large exponent is stored separately. , _vector :: !Vector -- ^ Matrix data. } deriving (Eq) -- | Two-dimensional mutable matrix, stored in row-major order. data MMatrix s = MMatrix {-# UNPACK #-} !Int {-# UNPACK #-} !Int {-# UNPACK #-} !Int !(MVector s) -- The Show instance is useful only for debugging. instance Show Matrix where show = debug debug :: Matrix -> String debug (Matrix r c _ vs) = unlines \$ zipWith (++) (hdr0 : repeat hdr) rrows where rrows = map (cleanEnd . unwords) . split \$ zipWith (++) ldone tdone hdr0 = show (r,c) ++ " " hdr = replicate (length hdr0) ' ' pad plus k xs = replicate (k - length xs) ' ' `plus` xs ldone = map (pad (++) (longest lstr)) lstr tdone = map (pad (flip (++)) (longest tstr)) tstr (lstr, tstr) = unzip . map (break (=='.') . render) . U.toList \$ vs longest = maximum . map length render k = reverse . dropWhile (=='.') . dropWhile (=='0') . reverse . showFFloat (Just 4) k \$ "" split [] = [] split xs = i : split rest where (i, rest) = splitAt c xs cleanEnd = reverse . dropWhile isSpace . reverse