-----------------------------------------------------------------------------
-- |
-- Module      :  Numeric.GSL.IO
-- Copyright   :  (c) Alberto Ruiz 2007-14
-- License     :  GPL
-- Maintainer  :  Alberto Ruiz
-- Stability   :  provisional
--
-----------------------------------------------------------------------------

module Numeric.GSL.IO (
    saveMatrix,
    fwriteVector, freadVector, fprintfVector, fscanfVector,
    fileDimensions, loadMatrix, fromFile
) where

import Numeric.LinearAlgebra.HMatrix hiding(saveMatrix, loadMatrix)
import Numeric.GSL.Vector
import System.Process(readProcess)


{- |  obtains the number of rows and columns in an ASCII data file
      (provisionally using unix's wc).
-}
fileDimensions :: FilePath -> IO (Int,Int)
fileDimensions :: FilePath -> IO (Int, Int)
fileDimensions fname :: FilePath
fname = do
    FilePath
wcres <- FilePath -> [FilePath] -> FilePath -> IO FilePath
readProcess "wc" ["-w",FilePath
fname] ""
    FilePath
contents <- FilePath -> IO FilePath
readFile FilePath
fname
    let tot :: Int
tot = FilePath -> Int
forall a. Read a => FilePath -> a
read (FilePath -> Int) -> (FilePath -> FilePath) -> FilePath -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [FilePath] -> FilePath
forall a. [a] -> a
head ([FilePath] -> FilePath)
-> (FilePath -> [FilePath]) -> FilePath -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> [FilePath]
words (FilePath -> Int) -> FilePath -> Int
forall a b. (a -> b) -> a -> b
$ FilePath
wcres
        c :: Int
c   = [FilePath] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([FilePath] -> Int) -> (FilePath -> [FilePath]) -> FilePath -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[FilePath]] -> [FilePath]
forall a. [a] -> a
head ([[FilePath]] -> [FilePath])
-> (FilePath -> [[FilePath]]) -> FilePath -> [FilePath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([FilePath] -> Bool) -> [[FilePath]] -> [[FilePath]]
forall a. (a -> Bool) -> [a] -> [a]
dropWhile [FilePath] -> 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) -> FilePath -> Int
forall a b. (a -> b) -> a -> b
$ FilePath
contents
    if Int
tot Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> 0
        then (Int, Int) -> IO (Int, Int)
forall (m :: * -> *) a. Monad m => a -> m a
return (Int
tot Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
c, Int
c)
        else (Int, Int) -> IO (Int, Int)
forall (m :: * -> *) a. Monad m => a -> m a
return (0,0)

-- | Loads a matrix from an ASCII file formatted as a 2D table.
loadMatrix :: FilePath -> IO (Matrix Double)
loadMatrix :: FilePath -> IO (Matrix Double)
loadMatrix file :: FilePath
file = FilePath -> (Int, Int) -> IO (Matrix Double)
fromFile FilePath
file ((Int, Int) -> IO (Matrix Double))
-> IO (Int, Int) -> IO (Matrix Double)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< FilePath -> IO (Int, Int)
fileDimensions FilePath
file

-- | Loads a matrix from an ASCII file (the number of rows and columns must be known in advance).
fromFile :: FilePath -> (Int,Int) -> IO (Matrix Double)
fromFile :: FilePath -> (Int, Int) -> IO (Matrix Double)
fromFile filename :: FilePath
filename (r :: Int
r,c :: Int
c) = Int -> Vector Double -> Matrix Double
forall t. Storable t => Int -> Vector t -> Matrix t
reshape Int
c (Vector Double -> Matrix Double)
-> IO (Vector Double) -> IO (Matrix Double)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` FilePath -> Int -> IO (Vector Double)
fscanfVector FilePath
filename (Int
rInt -> Int -> Int
forall a. Num a => a -> a -> a
*Int
c)