summaryrefslogtreecommitdiff
path: root/packages/hmatrix/src/Numeric/IO.hs
diff options
context:
space:
mode:
authorAlberto Ruiz <aruiz@um.es>2014-05-08 08:48:12 +0200
committerAlberto Ruiz <aruiz@um.es>2014-05-08 08:48:12 +0200
commit1925c123d7d8184a1d2ddc0a413e0fd2776e1083 (patch)
treefad79f909d9c3be53d68e6ebd67202650536d387 /packages/hmatrix/src/Numeric/IO.hs
parenteb3f702d065a4a967bb754977233e6eec408fd1f (diff)
empty hmatrix-base
Diffstat (limited to 'packages/hmatrix/src/Numeric/IO.hs')
-rw-r--r--packages/hmatrix/src/Numeric/IO.hs165
1 files changed, 165 insertions, 0 deletions
diff --git a/packages/hmatrix/src/Numeric/IO.hs b/packages/hmatrix/src/Numeric/IO.hs
new file mode 100644
index 0000000..836f352
--- /dev/null
+++ b/packages/hmatrix/src/Numeric/IO.hs
@@ -0,0 +1,165 @@
1-----------------------------------------------------------------------------
2-- |
3-- Module : Numeric.IO
4-- Copyright : (c) Alberto Ruiz 2010
5-- License : GPL
6--
7-- Maintainer : Alberto Ruiz <aruiz@um.es>
8-- Stability : provisional
9-- Portability : portable
10--
11-- Display, formatting and IO functions for numeric 'Vector' and 'Matrix'
12--
13-----------------------------------------------------------------------------
14
15module Numeric.IO (
16 dispf, disps, dispcf, vecdisp, latexFormat, format,
17 loadMatrix, saveMatrix, fromFile, fileDimensions,
18 readMatrix, fromArray2D,
19 fscanfVector, fprintfVector, freadVector, fwriteVector
20) where
21
22import Data.Packed
23import Data.Packed.Internal
24import System.Process(readProcess)
25import Text.Printf(printf)
26import Data.List(intersperse)
27import Data.Complex
28
29{- | Creates a string from a matrix given a separator and a function to show each entry. Using
30this function the user can easily define any desired display function:
31
32@import Text.Printf(printf)@
33
34@disp = putStr . format \" \" (printf \"%.2f\")@
35
36-}
37format :: (Element t) => String -> (t -> String) -> Matrix t -> String
38format sep f m = table sep . map (map f) . toLists $ m
39
40{- | Show a matrix with \"autoscaling\" and a given number of decimal places.
41
42>>> putStr . disps 2 $ 120 * (3><4) [1..]
433x4 E3
44 0.12 0.24 0.36 0.48
45 0.60 0.72 0.84 0.96
46 1.08 1.20 1.32 1.44
47
48-}
49disps :: Int -> Matrix Double -> String
50disps d x = sdims x ++ " " ++ formatScaled d x
51
52{- | Show a matrix with a given number of decimal places.
53
54>>> dispf 2 (1/3 + ident 3)
55"3x3\n1.33 0.33 0.33\n0.33 1.33 0.33\n0.33 0.33 1.33\n"
56
57>>> putStr . dispf 2 $ (3><4)[1,1.5..]
583x4
591.00 1.50 2.00 2.50
603.00 3.50 4.00 4.50
615.00 5.50 6.00 6.50
62
63>>> putStr . unlines . tail . lines . dispf 2 . asRow $ linspace 10 (0,1)
640.00 0.11 0.22 0.33 0.44 0.56 0.67 0.78 0.89 1.00
65
66-}
67dispf :: Int -> Matrix Double -> String
68dispf d x = sdims x ++ "\n" ++ formatFixed (if isInt x then 0 else d) x
69
70sdims x = show (rows x) ++ "x" ++ show (cols x)
71
72formatFixed d x = format " " (printf ("%."++show d++"f")) $ x
73
74isInt = all lookslikeInt . toList . flatten
75
76formatScaled dec t = "E"++show o++"\n" ++ ss
77 where ss = format " " (printf fmt. g) t
78 g x | o >= 0 = x/10^(o::Int)
79 | otherwise = x*10^(-o)
80 o | rows t == 0 || cols t == 0 = 0
81 | otherwise = floor $ maximum $ map (logBase 10 . abs) $ toList $ flatten t
82 fmt = '%':show (dec+3) ++ '.':show dec ++"f"
83
84{- | Show a vector using a function for showing matrices.
85
86>>> putStr . vecdisp (dispf 2) $ linspace 10 (0,1)
8710 |> 0.00 0.11 0.22 0.33 0.44 0.56 0.67 0.78 0.89 1.00
88
89-}
90vecdisp :: (Element t) => (Matrix t -> String) -> Vector t -> String
91vecdisp f v
92 = ((show (dim v) ++ " |> ") ++) . (++"\n")
93 . unwords . lines . tail . dropWhile (not . (`elem` " \n"))
94 . f . trans . reshape 1
95 $ v
96
97{- | Tool to display matrices with latex syntax.
98
99>>> latexFormat "bmatrix" (dispf 2 $ ident 2)
100"\\begin{bmatrix}\n1 & 0\n\\\\\n0 & 1\n\\end{bmatrix}"
101
102-}
103latexFormat :: String -- ^ type of braces: \"matrix\", \"bmatrix\", \"pmatrix\", etc.
104 -> String -- ^ Formatted matrix, with elements separated by spaces and newlines
105 -> String
106latexFormat del tab = "\\begin{"++del++"}\n" ++ f tab ++ "\\end{"++del++"}"
107 where f = unlines . intersperse "\\\\" . map unwords . map (intersperse " & " . words) . tail . lines
108
109-- | Pretty print a complex number with at most n decimal digits.
110showComplex :: Int -> Complex Double -> String
111showComplex d (a:+b)
112 | isZero a && isZero b = "0"
113 | isZero b = sa
114 | isZero a && isOne b = s2++"i"
115 | isZero a = sb++"i"
116 | isOne b = sa++s3++"i"
117 | otherwise = sa++s1++sb++"i"
118 where
119 sa = shcr d a
120 sb = shcr d b
121 s1 = if b<0 then "" else "+"
122 s2 = if b<0 then "-" else ""
123 s3 = if b<0 then "-" else "+"
124
125shcr d a | lookslikeInt a = printf "%.0f" a
126 | otherwise = printf ("%."++show d++"f") a
127
128
129lookslikeInt x = show (round x :: Int) ++".0" == shx || "-0.0" == shx
130 where shx = show x
131
132isZero x = show x `elem` ["0.0","-0.0"]
133isOne x = show x `elem` ["1.0","-1.0"]
134
135-- | Pretty print a complex matrix with at most n decimal digits.
136dispcf :: Int -> Matrix (Complex Double) -> String
137dispcf d m = sdims m ++ "\n" ++ format " " (showComplex d) m
138
139--------------------------------------------------------------------
140
141-- | reads a matrix from a string containing a table of numbers.
142readMatrix :: String -> Matrix Double
143readMatrix = fromLists . map (map read). map words . filter (not.null) . lines
144
145{- | obtains the number of rows and columns in an ASCII data file
146 (provisionally using unix's wc).
147-}
148fileDimensions :: FilePath -> IO (Int,Int)
149fileDimensions fname = do
150 wcres <- readProcess "wc" ["-w",fname] ""
151 contents <- readFile fname
152 let tot = read . head . words $ wcres
153 c = length . head . dropWhile null . map words . lines $ contents
154 if tot > 0
155 then return (tot `div` c, c)
156 else return (0,0)
157
158-- | Loads a matrix from an ASCII file formatted as a 2D table.
159loadMatrix :: FilePath -> IO (Matrix Double)
160loadMatrix file = fromFile file =<< fileDimensions file
161
162-- | Loads a matrix from an ASCII file (the number of rows and columns must be known in advance).
163fromFile :: FilePath -> (Int,Int) -> IO (Matrix Double)
164fromFile filename (r,c) = reshape c `fmap` fscanfVector filename (r*c)
165