-----------------------------------------------------------------------------
-- |
-- Module      :  Internal.IO
-- Copyright   :  (c) Alberto Ruiz 2010
-- License     :  BSD3
--
-- Maintainer  :  Alberto Ruiz
-- Stability   :  provisional
--
-- Display, formatting and IO functions for numeric 'Vector' and 'Matrix'
--
-----------------------------------------------------------------------------

module Internal.IO (
    dispf, disps, dispcf, vecdisp, latexFormat, format,
    loadMatrix, loadMatrix', saveMatrix
) where

import Internal.Devel
import Internal.Vector
import Internal.Matrix
import Internal.Vectorized
import Text.Printf(printf, PrintfArg, PrintfType)
import Data.List(intersperse,transpose)
import Data.Complex


-- | Formatting tool
table :: String -> [[String]] -> String
table :: FilePath -> [[FilePath]] -> FilePath
table FilePath
sep [[FilePath]]
as = [FilePath] -> FilePath
unlines ([FilePath] -> FilePath)
-> ([[FilePath]] -> [FilePath]) -> [[FilePath]] -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([FilePath] -> FilePath) -> [[FilePath]] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map [FilePath] -> FilePath
unwords' ([[FilePath]] -> FilePath) -> [[FilePath]] -> FilePath
forall a b. (a -> b) -> a -> b
$ [[FilePath]] -> [[FilePath]]
forall a. [[a]] -> [[a]]
transpose [[FilePath]]
mtp
  where
    mt :: [[FilePath]]
mt = [[FilePath]] -> [[FilePath]]
forall a. [[a]] -> [[a]]
transpose [[FilePath]]
as
    longs :: [Int]
longs = ([FilePath] -> Int) -> [[FilePath]] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map ([Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum ([Int] -> Int) -> ([FilePath] -> [Int]) -> [FilePath] -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FilePath -> Int) -> [FilePath] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map FilePath -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length) [[FilePath]]
mt
    mtp :: [[FilePath]]
mtp = (Int -> [FilePath] -> [FilePath])
-> [Int] -> [[FilePath]] -> [[FilePath]]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (\Int
a [FilePath]
b -> (FilePath -> FilePath) -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map (Int -> FilePath -> FilePath
pad Int
a) [FilePath]
b) [Int]
longs [[FilePath]]
mt
    pad :: Int -> FilePath -> FilePath
pad Int
n FilePath
str = Int -> Char -> FilePath
forall a. Int -> a -> [a]
replicate (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- FilePath -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length FilePath
str) Char
' ' FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
str
    unwords' :: [FilePath] -> FilePath
unwords' = [FilePath] -> FilePath
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([FilePath] -> FilePath)
-> ([FilePath] -> [FilePath]) -> [FilePath] -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> [FilePath] -> [FilePath]
forall a. a -> [a] -> [a]
intersperse FilePath
sep



{- | Creates a string from a matrix given a separator and a function to show each entry. Using
this function the user can easily define any desired display function:

@import Text.Printf(printf)@

@disp = putStr . format \"  \" (printf \"%.2f\")@

-}
format :: (Element t) => String -> (t -> String) -> Matrix t -> String
format :: forall t.
Element t =>
FilePath -> (t -> FilePath) -> Matrix t -> FilePath
format FilePath
sep t -> FilePath
f Matrix t
m = FilePath -> [[FilePath]] -> FilePath
table FilePath
sep ([[FilePath]] -> FilePath)
-> (Matrix t -> [[FilePath]]) -> Matrix t -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([t] -> [FilePath]) -> [[t]] -> [[FilePath]]
forall a b. (a -> b) -> [a] -> [b]
map ((t -> FilePath) -> [t] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map t -> FilePath
f) ([[t]] -> [[FilePath]])
-> (Matrix t -> [[t]]) -> Matrix t -> [[FilePath]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Matrix t -> [[t]]
forall t. Element t => Matrix t -> [[t]]
toLists (Matrix t -> FilePath) -> Matrix t -> FilePath
forall a b. (a -> b) -> a -> b
$ Matrix t
m

{- | Show a matrix with \"autoscaling\" and a given number of decimal places.

>>> putStr . disps 2 $ 120 * (3><4) [1..]
3x4  E3
 0.12  0.24  0.36  0.48
 0.60  0.72  0.84  0.96
 1.08  1.20  1.32  1.44

-}
disps :: Int -> Matrix Double -> String
disps :: Int -> Matrix Double -> FilePath
disps Int
d Matrix Double
x = Matrix Double -> FilePath
forall t. Matrix t -> FilePath
sdims Matrix Double
x FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"  " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ Int -> Matrix Double -> FilePath
forall b t.
(PrintfArg b, RealFrac b, Floating b, Num t, Element b, Show t) =>
t -> Matrix b -> FilePath
formatScaled Int
d Matrix Double
x

{- | Show a matrix with a given number of decimal places.

>>> dispf 2 (1/3 + ident 3)
"3x3\n1.33  0.33  0.33\n0.33  1.33  0.33\n0.33  0.33  1.33\n"

>>> putStr . dispf 2 $ (3><4)[1,1.5..]
3x4
1.00  1.50  2.00  2.50
3.00  3.50  4.00  4.50
5.00  5.50  6.00  6.50

>>> putStr . unlines . tail . lines . dispf 2 . asRow $ linspace 10 (0,1)
0.00  0.11  0.22  0.33  0.44  0.56  0.67  0.78  0.89  1.00

-}
dispf :: Int -> Matrix Double -> String
dispf :: Int -> Matrix Double -> FilePath
dispf Int
d Matrix Double
x = Matrix Double -> FilePath
forall t. Matrix t -> FilePath
sdims Matrix Double
x FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\n" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ Int -> Matrix Double -> FilePath
forall a t.
(Show a, PrintfArg t, Element t) =>
a -> Matrix t -> FilePath
formatFixed (if Matrix Double -> Bool
isInt Matrix Double
x then Int
0 else Int
d) Matrix Double
x

sdims :: Matrix t -> [Char]
sdims :: forall t. Matrix t -> FilePath
sdims Matrix t
x = Int -> FilePath
forall a. Show a => a -> FilePath
show (Matrix t -> Int
forall t. Matrix t -> Int
rows Matrix t
x) FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"x" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ Int -> FilePath
forall a. Show a => a -> FilePath
show (Matrix t -> Int
forall t. Matrix t -> Int
cols Matrix t
x)

formatFixed :: (Show a, Text.Printf.PrintfArg t, Element t)
            => a -> Matrix t -> String
formatFixed :: forall a t.
(Show a, PrintfArg t, Element t) =>
a -> Matrix t -> FilePath
formatFixed a
d Matrix t
x = FilePath -> (t -> FilePath) -> Matrix t -> FilePath
forall t.
Element t =>
FilePath -> (t -> FilePath) -> Matrix t -> FilePath
format FilePath
"  " (FilePath -> t -> FilePath
forall r. PrintfType r => FilePath -> r
printf (FilePath
"%."FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++a -> FilePath
forall a. Show a => a -> FilePath
show a
dFilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++FilePath
"f")) (Matrix t -> FilePath) -> Matrix t -> FilePath
forall a b. (a -> b) -> a -> b
$ Matrix t
x

isInt :: Matrix Double -> Bool
isInt :: Matrix Double -> Bool
isInt = (Double -> Bool) -> [Double] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Double -> Bool
forall a. (Show a, RealFrac a) => a -> Bool
lookslikeInt ([Double] -> Bool)
-> (Matrix Double -> [Double]) -> Matrix Double -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Vector Double -> [Double]
forall a. Storable a => Vector a -> [a]
toList (Vector Double -> [Double])
-> (Matrix Double -> Vector Double) -> Matrix Double -> [Double]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Matrix Double -> Vector Double
forall t. Element t => Matrix t -> Vector t
flatten

formatScaled :: (Text.Printf.PrintfArg b, RealFrac b, Floating b, Num t, Element b, Show t)
             => t -> Matrix b -> [Char]
formatScaled :: forall b t.
(PrintfArg b, RealFrac b, Floating b, Num t, Element b, Show t) =>
t -> Matrix b -> FilePath
formatScaled t
dec Matrix b
t = FilePath
"E"FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++Int -> FilePath
forall a. Show a => a -> FilePath
show Int
oFilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++FilePath
"\n" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
ss
    where ss :: FilePath
ss = FilePath -> (b -> FilePath) -> Matrix b -> FilePath
forall t.
Element t =>
FilePath -> (t -> FilePath) -> Matrix t -> FilePath
format FilePath
" " (FilePath -> b -> FilePath
forall r. PrintfType r => FilePath -> r
printf FilePath
fmt(b -> FilePath) -> (b -> b) -> b -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> b
forall {a}. Fractional a => a -> a
g) Matrix b
t
          g :: a -> a
g a
x | Int
o Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0    = a
xa -> a -> a
forall a. Fractional a => a -> a -> a
/a
10a -> Int -> a
forall a b. (Num a, Integral b) => a -> b -> a
^(Int
o::Int)
              | Bool
otherwise = a
xa -> a -> a
forall a. Num a => a -> a -> a
*a
10a -> Int -> a
forall a b. (Num a, Integral b) => a -> b -> a
^(-Int
o)
          o :: Int
o | Matrix b -> Int
forall t. Matrix t -> Int
rows Matrix b
t Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 Bool -> Bool -> Bool
|| Matrix b -> Int
forall t. Matrix t -> Int
cols Matrix b
t Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = Int
0
            | Bool
otherwise = b -> Int
forall b. Integral b => b -> b
forall a b. (RealFrac a, Integral b) => a -> b
floor (b -> Int) -> b -> Int
forall a b. (a -> b) -> a -> b
$ [b] -> b
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum ([b] -> b) -> [b] -> b
forall a b. (a -> b) -> a -> b
$ (b -> b) -> [b] -> [b]
forall a b. (a -> b) -> [a] -> [b]
map (b -> b -> b
forall a. Floating a => a -> a -> a
logBase b
10 (b -> b) -> (b -> b) -> b -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> b
forall a. Num a => a -> a
abs) ([b] -> [b]) -> [b] -> [b]
forall a b. (a -> b) -> a -> b
$ Vector b -> [b]
forall a. Storable a => Vector a -> [a]
toList (Vector b -> [b]) -> Vector b -> [b]
forall a b. (a -> b) -> a -> b
$ Matrix b -> Vector b
forall t. Element t => Matrix t -> Vector t
flatten Matrix b
t
          fmt :: FilePath
fmt = Char
'%'Char -> FilePath -> FilePath
forall a. a -> [a] -> [a]
:t -> FilePath
forall a. Show a => a -> FilePath
show (t
dect -> t -> t
forall a. Num a => a -> a -> a
+t
3) FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ Char
'.'Char -> FilePath -> FilePath
forall a. a -> [a] -> [a]
:t -> FilePath
forall a. Show a => a -> FilePath
show t
dec FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++FilePath
"f"

{- | Show a vector using a function for showing matrices.

>>> putStr . vecdisp (dispf 2) $ linspace 10 (0,1)
10 |> 0.00  0.11  0.22  0.33  0.44  0.56  0.67  0.78  0.89  1.00

-}
vecdisp :: (Element t) => (Matrix t -> String) -> Vector t -> String
vecdisp :: forall t.
Element t =>
(Matrix t -> FilePath) -> Vector t -> FilePath
vecdisp Matrix t -> FilePath
f Vector t
v
    = ((Int -> FilePath
forall a. Show a => a -> FilePath
show (Vector t -> Int
forall t. Storable t => Vector t -> Int
dim Vector t
v) FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
" |> ") FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++) (FilePath -> FilePath)
-> (Vector t -> FilePath) -> Vector t -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++FilePath
"\n")
    (FilePath -> FilePath)
-> (Vector t -> FilePath) -> Vector t -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [FilePath] -> FilePath
unwords ([FilePath] -> FilePath)
-> (Vector t -> [FilePath]) -> Vector t -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> [FilePath]
lines (FilePath -> [FilePath])
-> (Vector t -> FilePath) -> Vector t -> [FilePath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.  FilePath -> FilePath
forall a. HasCallStack => [a] -> [a]
tail (FilePath -> FilePath)
-> (Vector t -> FilePath) -> Vector t -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> FilePath -> FilePath
forall a. (a -> Bool) -> [a] -> [a]
dropWhile (Bool -> Bool
not (Bool -> Bool) -> (Char -> Bool) -> Char -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> FilePath -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` FilePath
" \n"))
    (FilePath -> FilePath)
-> (Vector t -> FilePath) -> Vector t -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Matrix t -> FilePath
f (Matrix t -> FilePath)
-> (Vector t -> Matrix t) -> Vector t -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Matrix t -> Matrix t
forall t. Matrix t -> Matrix t
trans (Matrix t -> Matrix t)
-> (Vector t -> Matrix t) -> Vector t -> Matrix t
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Vector t -> Matrix t
forall t. Storable t => Int -> Vector t -> Matrix t
reshape Int
1
    (Vector t -> FilePath) -> Vector t -> FilePath
forall a b. (a -> b) -> a -> b
$ Vector t
v

{- | Tool to display matrices with latex syntax.

>>>  latexFormat "bmatrix" (dispf 2 $ ident 2)
"\\begin{bmatrix}\n1  &  0\n\\\\\n0  &  1\n\\end{bmatrix}"

-}
latexFormat :: String -- ^ type of braces: \"matrix\", \"bmatrix\", \"pmatrix\", etc.
            -> String -- ^ Formatted matrix, with elements separated by spaces and newlines
            -> String
latexFormat :: FilePath -> FilePath -> FilePath
latexFormat FilePath
del FilePath
tab = FilePath
"\\begin{"FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++FilePath
delFilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++FilePath
"}\n" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath -> FilePath
f FilePath
tab FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\\end{"FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++FilePath
delFilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++FilePath
"}"
    where f :: FilePath -> FilePath
f = [FilePath] -> FilePath
unlines ([FilePath] -> FilePath)
-> (FilePath -> [FilePath]) -> FilePath -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> [FilePath] -> [FilePath]
forall a. a -> [a] -> [a]
intersperse FilePath
"\\\\" ([FilePath] -> [FilePath])
-> (FilePath -> [FilePath]) -> FilePath -> [FilePath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([FilePath] -> FilePath) -> [[FilePath]] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map [FilePath] -> FilePath
unwords ([[FilePath]] -> [FilePath])
-> (FilePath -> [[FilePath]]) -> FilePath -> [FilePath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FilePath -> [FilePath]) -> [FilePath] -> [[FilePath]]
forall a b. (a -> b) -> [a] -> [b]
map (FilePath -> [FilePath] -> [FilePath]
forall a. a -> [a] -> [a]
intersperse FilePath
" & " ([FilePath] -> [FilePath])
-> (FilePath -> [FilePath]) -> FilePath -> [FilePath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> [FilePath]
words) ([FilePath] -> [[FilePath]])
-> (FilePath -> [FilePath]) -> FilePath -> [[FilePath]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [FilePath] -> [FilePath]
forall a. HasCallStack => [a] -> [a]
tail ([FilePath] -> [FilePath])
-> (FilePath -> [FilePath]) -> FilePath -> [FilePath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> [FilePath]
lines

-- | Pretty print a complex number with at most n decimal digits.
showComplex :: Int -> Complex Double -> String
showComplex :: Int -> Complex Double -> FilePath
showComplex Int
d (Double
a:+Double
b)
    | Double -> Bool
forall a. Show a => a -> Bool
isZero Double
a Bool -> Bool -> Bool
&& Double -> Bool
forall a. Show a => a -> Bool
isZero Double
b = FilePath
"0"
    | Double -> Bool
forall a. Show a => a -> Bool
isZero Double
b = FilePath
sa
    | Double -> Bool
forall a. Show a => a -> Bool
isZero Double
a Bool -> Bool -> Bool
&& Double -> Bool
forall a. Show a => a -> Bool
isOne Double
b = FilePath
s2FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++FilePath
"i"
    | Double -> Bool
forall a. Show a => a -> Bool
isZero Double
a = FilePath
sbFilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++FilePath
"i"
    | Double -> Bool
forall a. Show a => a -> Bool
isOne Double
b = FilePath
saFilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++FilePath
s3FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++FilePath
"i"
    | Bool
otherwise = FilePath
saFilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++FilePath
s1FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++FilePath
sbFilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++FilePath
"i"
  where
    sa :: FilePath
sa = Int -> Double -> FilePath
forall a t1 t.
(Show a, Show t1, PrintfType t, PrintfArg t1, RealFrac t1) =>
a -> t1 -> t
shcr Int
d Double
a
    sb :: FilePath
sb = Int -> Double -> FilePath
forall a t1 t.
(Show a, Show t1, PrintfType t, PrintfArg t1, RealFrac t1) =>
a -> t1 -> t
shcr Int
d Double
b
    s1 :: FilePath
s1 = if Double
bDouble -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<Double
0 then FilePath
"" else FilePath
"+"
    s2 :: FilePath
s2 = if Double
bDouble -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<Double
0 then FilePath
"-" else FilePath
""
    s3 :: FilePath
s3 = if Double
bDouble -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<Double
0 then FilePath
"-" else FilePath
"+"

shcr :: (Show a, Show t1, Text.Printf.PrintfType t, Text.Printf.PrintfArg t1, RealFrac t1)
     => a -> t1 -> t
shcr :: forall a t1 t.
(Show a, Show t1, PrintfType t, PrintfArg t1, RealFrac t1) =>
a -> t1 -> t
shcr a
d t1
a | t1 -> Bool
forall a. (Show a, RealFrac a) => a -> Bool
lookslikeInt t1
a = FilePath -> t1 -> t
forall r. PrintfType r => FilePath -> r
printf FilePath
"%.0f" t1
a
         | Bool
otherwise      = FilePath -> t1 -> t
forall r. PrintfType r => FilePath -> r
printf (FilePath
"%."FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++a -> FilePath
forall a. Show a => a -> FilePath
show a
dFilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++FilePath
"f") t1
a

lookslikeInt :: (Show a, RealFrac a) => a -> Bool
lookslikeInt :: forall a. (Show a, RealFrac a) => a -> Bool
lookslikeInt a
x = Int -> FilePath
forall a. Show a => a -> FilePath
show (a -> Int
forall b. Integral b => a -> b
forall a b. (RealFrac a, Integral b) => a -> b
round a
x :: Int) FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++FilePath
".0" FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== FilePath
shx Bool -> Bool -> Bool
|| FilePath
"-0.0" FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== FilePath
shx
   where shx :: FilePath
shx = a -> FilePath
forall a. Show a => a -> FilePath
show a
x

isZero :: Show a => a -> Bool
isZero :: forall a. Show a => a -> Bool
isZero a
x = a -> FilePath
forall a. Show a => a -> FilePath
show a
x FilePath -> [FilePath] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [FilePath
"0.0",FilePath
"-0.0"]
isOne :: Show a => a -> Bool
isOne :: forall a. Show a => a -> Bool
isOne  a
x = a -> FilePath
forall a. Show a => a -> FilePath
show a
x FilePath -> [FilePath] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [FilePath
"1.0",FilePath
"-1.0"]

-- | Pretty print a complex matrix with at most n decimal digits.
dispcf :: Int -> Matrix (Complex Double) -> String
dispcf :: Int -> Matrix (Complex Double) -> FilePath
dispcf Int
d Matrix (Complex Double)
m = Matrix (Complex Double) -> FilePath
forall t. Matrix t -> FilePath
sdims Matrix (Complex Double)
m FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\n" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
-> (Complex Double -> FilePath)
-> Matrix (Complex Double)
-> FilePath
forall t.
Element t =>
FilePath -> (t -> FilePath) -> Matrix t -> FilePath
format FilePath
"  " (Int -> Complex Double -> FilePath
showComplex Int
d) Matrix (Complex Double)
m

--------------------------------------------------------------------

apparentCols :: FilePath -> IO Int
apparentCols :: FilePath -> IO Int
apparentCols FilePath
s = [[FilePath]] -> Int
forall {t :: * -> *} {a}. Foldable t => [t a] -> Int
f ([[FilePath]] -> Int)
-> (FilePath -> [[FilePath]]) -> FilePath -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([FilePath] -> Bool) -> [[FilePath]] -> [[FilePath]]
forall a. (a -> Bool) -> [a] -> [a]
dropWhile [FilePath] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null ([[FilePath]] -> [[FilePath]])
-> (FilePath -> [[FilePath]]) -> FilePath -> [[FilePath]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FilePath -> [FilePath]) -> [FilePath] -> [[FilePath]]
forall a b. (a -> b) -> [a] -> [b]
map FilePath -> [FilePath]
words ([FilePath] -> [[FilePath]])
-> (FilePath -> [FilePath]) -> FilePath -> [[FilePath]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> [FilePath]
lines (FilePath -> Int) -> IO FilePath -> IO Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> IO FilePath
readFile FilePath
s
  where
    f :: [t a] -> Int
f [] = Int
0
    f (t a
x:[t a]
_) = t a -> Int
forall a. t a -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length t a
x


-- | load a matrix from an ASCII file formatted as a 2D table.
loadMatrix :: FilePath -> IO (Matrix Double)
loadMatrix :: FilePath -> IO (Matrix Double)
loadMatrix FilePath
f = do
    Vector Double
v <- FilePath -> IO (Vector Double)
vectorScan FilePath
f
    Int
c <- FilePath -> IO Int
apparentCols FilePath
f
    if (Vector Double -> Int
forall t. Storable t => Vector t -> Int
dim Vector Double
v Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
c Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0)
      then
        FilePath -> IO (Matrix Double)
forall a. HasCallStack => FilePath -> a
error (FilePath -> IO (Matrix Double)) -> FilePath -> IO (Matrix Double)
forall a b. (a -> b) -> a -> b
$ FilePath -> Int -> Int -> FilePath -> FilePath
forall r. PrintfType r => FilePath -> r
printf FilePath
"loadMatrix: %d elements and %d columns in file %s"
                       (Vector Double -> Int
forall t. Storable t => Vector t -> Int
dim Vector Double
v) Int
c FilePath
f
      else
        Matrix Double -> IO (Matrix Double)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Int -> Vector Double -> Matrix Double
forall t. Storable t => Int -> Vector t -> Matrix t
reshape Int
c Vector Double
v)

loadMatrix' :: FilePath -> IO (Maybe (Matrix Double))
loadMatrix' :: FilePath -> IO (Maybe (Matrix Double))
loadMatrix' FilePath
name = IO (Matrix Double) -> IO (Maybe (Matrix Double))
forall x. IO x -> IO (Maybe x)
mbCatch (FilePath -> IO (Matrix Double)
loadMatrix FilePath
name)