{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
{-# OPTIONS_GHC -fno-warn-unused-top-binds #-}

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

module Numeric.GSL.Vector (
    randomVector,
    saveMatrix,
    fwriteVector, freadVector, fprintfVector, fscanfVector
) where

import Numeric.LinearAlgebra.HMatrix hiding(randomVector, saveMatrix)
import Numeric.GSL.Internal hiding (TV,TM,TCV,TCM)

import Foreign.Marshal.Alloc(free)
import Foreign.Ptr(Ptr)
import Foreign.C.Types
import Foreign.C.String(newCString)
import System.IO.Unsafe(unsafePerformIO)

fromei :: a -> CInt
fromei x :: a
x = Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral (a -> Int
forall a. Enum a => a -> Int
fromEnum a
x) :: CInt

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

-- | Obtains a vector of pseudorandom elements from the the mt19937 generator in GSL, with a given seed. Use randomIO to get a random seed.
randomVector :: Int      -- ^ seed
             -> RandDist -- ^ distribution
             -> Int      -- ^ vector size
             -> Vector Double
randomVector :: Int -> RandDist -> Int -> Vector Double
randomVector seed :: Int
seed dist :: RandDist
dist n :: Int
n = IO (Vector Double) -> Vector Double
forall a. IO a -> a
unsafePerformIO (IO (Vector Double) -> Vector Double)
-> IO (Vector Double) -> Vector Double
forall a b. (a -> b) -> a -> b
$ do
    Vector Double
r <- Int -> IO (Vector Double)
forall a. Storable a => Int -> IO (Vector a)
createVector Int
n
    (Vector Double
r Vector Double
-> (IO CInt -> IO CInt)
-> TransRaw (Vector Double) (IO CInt)
-> IO CInt
forall c b r.
TransArray c =>
c -> (b -> IO r) -> TransRaw c b -> IO r
`applyRaw` IO CInt -> IO CInt
forall a. a -> a
id) (CInt -> CInt -> TV
c_random_vector_GSL (Int -> CInt
fi Int
seed) ((Int -> CInt
fi(Int -> CInt) -> (RandDist -> Int) -> RandDist -> CInt
forall b c a. (b -> c) -> (a -> b) -> a -> c
.RandDist -> Int
forall a. Enum a => a -> Int
fromEnum) RandDist
dist)) IO CInt -> String -> IO ()
#|"randomVectorGSL"
    Vector Double -> IO (Vector Double)
forall (m :: * -> *) a. Monad m => a -> m a
return Vector Double
r

foreign import ccall unsafe "random_vector_GSL" c_random_vector_GSL :: CInt -> CInt -> TV

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

-- | Saves a matrix as 2D ASCII table.
saveMatrix :: FilePath
           -> String     -- ^ format (%f, %g, %e)
           -> Matrix Double
           -> IO ()
saveMatrix :: String -> String -> Matrix Double -> IO ()
saveMatrix filename :: String
filename fmt :: String
fmt m :: Matrix Double
m = do
    CString
charname <- String -> IO CString
newCString String
filename
    CString
charfmt <- String -> IO CString
newCString String
fmt
    let o :: CInt
o = if Matrix Double -> MatrixOrder
forall t. Matrix t -> MatrixOrder
orderOf Matrix Double
m MatrixOrder -> MatrixOrder -> Bool
forall a. Eq a => a -> a -> Bool
== MatrixOrder
RowMajor then 1 else 0
    (Matrix Double
m Matrix Double
-> (IO CInt -> IO CInt)
-> TransRaw (Matrix Double) (IO CInt)
-> IO CInt
forall c b r.
TransArray c =>
c -> (b -> IO r) -> TransRaw c b -> IO r
`applyRaw` IO CInt -> IO CInt
forall a. a -> a
id) (CString -> CString -> CInt -> CInt -> TV
matrix_fprintf CString
charname CString
charfmt CInt
o) IO CInt -> String -> IO ()
#|"matrix_fprintf"
    CString -> IO ()
forall a. Ptr a -> IO ()
free CString
charname
    CString -> IO ()
forall a. Ptr a -> IO ()
free CString
charfmt

foreign import ccall unsafe "matrix_fprintf" matrix_fprintf :: Ptr CChar -> Ptr CChar -> CInt -> TM

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

-- | Loads a vector from an ASCII file (the number of elements must be known in advance).
fscanfVector :: FilePath -> Int -> IO (Vector Double)
fscanfVector :: String -> Int -> IO (Vector Double)
fscanfVector filename :: String
filename n :: Int
n = do
    CString
charname <- String -> IO CString
newCString String
filename
    Vector Double
res <- Int -> IO (Vector Double)
forall a. Storable a => Int -> IO (Vector a)
createVector Int
n
    (Vector Double
res Vector Double
-> (IO CInt -> IO CInt)
-> TransRaw (Vector Double) (IO CInt)
-> IO CInt
forall c b r.
TransArray c =>
c -> (b -> IO r) -> TransRaw c b -> IO r
`applyRaw` IO CInt -> IO CInt
forall a. a -> a
id) (CString -> TV
gsl_vector_fscanf CString
charname) IO CInt -> String -> IO ()
#|"gsl_vector_fscanf"
    CString -> IO ()
forall a. Ptr a -> IO ()
free CString
charname
    Vector Double -> IO (Vector Double)
forall (m :: * -> *) a. Monad m => a -> m a
return Vector Double
res

foreign import ccall unsafe "vector_fscanf" gsl_vector_fscanf:: Ptr CChar -> TV

-- | Saves the elements of a vector, with a given format (%f, %e, %g), to an ASCII file.
fprintfVector :: FilePath -> String -> Vector Double -> IO ()
fprintfVector :: String -> String -> Vector Double -> IO ()
fprintfVector filename :: String
filename fmt :: String
fmt v :: Vector Double
v = do
    CString
charname <- String -> IO CString
newCString String
filename
    CString
charfmt <- String -> IO CString
newCString String
fmt
    (Vector Double
v Vector Double
-> (IO CInt -> IO CInt)
-> TransRaw (Vector Double) (IO CInt)
-> IO CInt
forall c b r.
TransArray c =>
c -> (b -> IO r) -> TransRaw c b -> IO r
`applyRaw` IO CInt -> IO CInt
forall a. a -> a
id) (CString -> CString -> TV
gsl_vector_fprintf CString
charname CString
charfmt) IO CInt -> String -> IO ()
#|"gsl_vector_fprintf"
    CString -> IO ()
forall a. Ptr a -> IO ()
free CString
charname
    CString -> IO ()
forall a. Ptr a -> IO ()
free CString
charfmt

foreign import ccall unsafe "vector_fprintf" gsl_vector_fprintf :: Ptr CChar -> Ptr CChar -> TV

-- | Loads a vector from a binary file (the number of elements must be known in advance).
freadVector :: FilePath -> Int -> IO (Vector Double)
freadVector :: String -> Int -> IO (Vector Double)
freadVector filename :: String
filename n :: Int
n = do
    CString
charname <- String -> IO CString
newCString String
filename
    Vector Double
res <- Int -> IO (Vector Double)
forall a. Storable a => Int -> IO (Vector a)
createVector Int
n
    (Vector Double
res Vector Double
-> (IO CInt -> IO CInt)
-> TransRaw (Vector Double) (IO CInt)
-> IO CInt
forall c b r.
TransArray c =>
c -> (b -> IO r) -> TransRaw c b -> IO r
`applyRaw` IO CInt -> IO CInt
forall a. a -> a
id) (CString -> TV
gsl_vector_fread CString
charname) IO CInt -> String -> IO ()
#|"gsl_vector_fread"
    CString -> IO ()
forall a. Ptr a -> IO ()
free CString
charname
    Vector Double -> IO (Vector Double)
forall (m :: * -> *) a. Monad m => a -> m a
return Vector Double
res

foreign import ccall unsafe "vector_fread" gsl_vector_fread:: Ptr CChar -> TV

-- | Saves the elements of a vector to a binary file.
fwriteVector :: FilePath -> Vector Double -> IO ()
fwriteVector :: String -> Vector Double -> IO ()
fwriteVector filename :: String
filename v :: Vector Double
v = do
    CString
charname <- String -> IO CString
newCString String
filename
    (Vector Double
v Vector Double
-> (IO CInt -> IO CInt)
-> TransRaw (Vector Double) (IO CInt)
-> IO CInt
forall c b r.
TransArray c =>
c -> (b -> IO r) -> TransRaw c b -> IO r
`applyRaw` IO CInt -> IO CInt
forall a. a -> a
id) (CString -> TV
gsl_vector_fwrite CString
charname) IO CInt -> String -> IO ()
#|"gsl_vector_fwrite"
    CString -> IO ()
forall a. Ptr a -> IO ()
free CString
charname

foreign import ccall unsafe "vector_fwrite" gsl_vector_fwrite :: Ptr CChar -> TV

type PD = Ptr Double                            --
type TV = CInt -> PD -> IO CInt                 --
type TM = CInt -> CInt -> PD -> IO CInt         --