module Data.Packed.Internal.Vector (
Vector, dim,
fromList, toList, (|>),
Data.Packed.Internal.Vector.join, (@>), safe, at, at', subVector, takesV,
mapVector, mapVectorWithIndex, zipVectorWith, unzipVectorWith,
mapVectorM, mapVectorM_, mapVectorWithIndexM, mapVectorWithIndexM_,
foldVector, foldVectorG, foldLoop, foldVectorWithIndex,
createVector, vec,
asComplex, asReal, float2DoubleV, double2FloatV,
stepF, stepD, condF, condD,
conjugateQ, conjugateC,
fwriteVector, freadVector, fprintfVector, fscanfVector,
cloneVector,
unsafeToForeignPtr,
unsafeFromForeignPtr,
unsafeWith
) where
import Data.Packed.Internal.Common
import Data.Packed.Internal.Signatures
import Foreign.Marshal.Alloc(free)
import Foreign.Marshal.Array(peekArray, copyArray, advancePtr)
import Foreign.ForeignPtr(ForeignPtr, castForeignPtr)
import Foreign.Ptr(Ptr)
import Foreign.Storable(Storable, peekElemOff, pokeElemOff, sizeOf)
import Foreign.C.String
import Foreign.C.Types
import Data.Complex
import Control.Monad(when)
import System.IO.Unsafe(unsafePerformIO)
#if __GLASGOW_HASKELL__ >= 605
import GHC.ForeignPtr (mallocPlainForeignPtrBytes)
#else
import Foreign.ForeignPtr (mallocForeignPtrBytes)
#endif
import GHC.Base
#if __GLASGOW_HASKELL__ < 612
import GHC.IOBase hiding (liftIO)
#endif
import qualified Data.Vector.Storable as Vector
import Data.Vector.Storable(Vector,
fromList,
unsafeToForeignPtr,
unsafeFromForeignPtr,
unsafeWith)
dim :: (Storable t) => Vector t -> Int
dim = Vector.length
vec :: (Storable t) => Vector t -> (((CInt -> Ptr t -> t1) -> t1) -> IO b) -> IO b
vec x f = unsafeWith x $ \p -> do
let v g = do
g (fi $ dim x) p
f v
createVector :: Storable a => Int -> IO (Vector a)
createVector n = do
when (n <= 0) $ error ("trying to createVector of dim "++show n)
fp <- doMalloc undefined
return $ unsafeFromForeignPtr fp 0 n
where
doMalloc :: Storable b => b -> IO (ForeignPtr b)
doMalloc dummy = do
#if __GLASGOW_HASKELL__ >= 605
mallocPlainForeignPtrBytes (n * sizeOf dummy)
#else
mallocForeignPtrBytes (n * sizeOf dummy)
#endif
safeRead v = inlinePerformIO . unsafeWith v
inlinePerformIO :: IO a -> a
inlinePerformIO (IO m) = case m realWorld# of (# _, r #) -> r
toList :: Storable a => Vector a -> [a]
toList v = safeRead v $ peekArray (dim v)
(|>) :: (Storable a) => Int -> [a] -> Vector a
infixl 9 |>
n |> l = if length l' == n
then fromList l'
else error "list too short for |>"
where l' = take n l
at' :: Storable a => Vector a -> Int -> a
at' v n = safeRead v $ flip peekElemOff n
#if defined(UNSAFE)
safe :: Bool
safe = False
#else
safe = True
#endif
at :: Storable a => Vector a -> Int -> a
at v n
| safe = if n >= 0 && n < dim v
then at' v n
else error "vector index out of range"
| otherwise = at' v n
subVector :: Storable t => Int
-> Int
-> Vector t
-> Vector t
subVector = Vector.slice
(@>) :: Storable t => Vector t -> Int -> t
infixl 9 @>
(@>) = at
join :: Storable t => [Vector t] -> Vector t
join [] = error "joining zero vectors"
join [v] = v
join as = unsafePerformIO $ do
let tot = sum (map dim as)
r <- createVector tot
unsafeWith r $ \ptr ->
joiner as tot ptr
return r
where joiner [] _ _ = return ()
joiner (v:cs) _ p = do
let n = dim v
unsafeWith v $ \pb -> copyArray p pb n
joiner cs 0 (advancePtr p n)
takesV :: Storable t => [Int] -> Vector t -> [Vector t]
takesV ms w | sum ms > dim w = error $ "takesV " ++ show ms ++ " on dim = " ++ (show $ dim w)
| otherwise = go ms w
where go [] _ = []
go (n:ns) v = subVector 0 n v
: go ns (subVector n (dim v n) v)
asReal :: (RealFloat a, Storable a) => Vector (Complex a) -> Vector a
asReal v = unsafeFromForeignPtr (castForeignPtr fp) (2*i) (2*n)
where (fp,i,n) = unsafeToForeignPtr v
asComplex :: (RealFloat a, Storable a) => Vector a -> Vector (Complex a)
asComplex v = unsafeFromForeignPtr (castForeignPtr fp) (i `div` 2) (n `div` 2)
where (fp,i,n) = unsafeToForeignPtr v
float2DoubleV :: Vector Float -> Vector Double
float2DoubleV v = unsafePerformIO $ do
r <- createVector (dim v)
app2 c_float2double vec v vec r "float2double"
return r
double2FloatV :: Vector Double -> Vector Float
double2FloatV v = unsafePerformIO $ do
r <- createVector (dim v)
app2 c_double2float vec v vec r "double2float2"
return r
foreign import ccall unsafe "float2double" c_float2double:: TFV
foreign import ccall unsafe "double2float" c_double2float:: TVF
stepF :: Vector Float -> Vector Float
stepF v = unsafePerformIO $ do
r <- createVector (dim v)
app2 c_stepF vec v vec r "stepF"
return r
stepD :: Vector Double -> Vector Double
stepD v = unsafePerformIO $ do
r <- createVector (dim v)
app2 c_stepD vec v vec r "stepD"
return r
foreign import ccall unsafe "stepF" c_stepF :: TFF
foreign import ccall unsafe "stepD" c_stepD :: TVV
condF :: Vector Float -> Vector Float -> Vector Float -> Vector Float -> Vector Float -> Vector Float
condF x y l e g = unsafePerformIO $ do
r <- createVector (dim x)
app6 c_condF vec x vec y vec l vec e vec g vec r "condF"
return r
condD :: Vector Double -> Vector Double -> Vector Double -> Vector Double -> Vector Double -> Vector Double
condD x y l e g = unsafePerformIO $ do
r <- createVector (dim x)
app6 c_condD vec x vec y vec l vec e vec g vec r "condD"
return r
foreign import ccall unsafe "condF" c_condF :: CInt -> PF -> CInt -> PF -> CInt -> PF -> TFFF
foreign import ccall unsafe "condD" c_condD :: CInt -> PD -> CInt -> PD -> CInt -> PD -> TVVV
conjugateAux fun x = unsafePerformIO $ do
v <- createVector (dim x)
app2 fun vec x vec v "conjugateAux"
return v
conjugateQ :: Vector (Complex Float) -> Vector (Complex Float)
conjugateQ = conjugateAux c_conjugateQ
foreign import ccall unsafe "conjugateQ" c_conjugateQ :: TQVQV
conjugateC :: Vector (Complex Double) -> Vector (Complex Double)
conjugateC = conjugateAux c_conjugateC
foreign import ccall unsafe "conjugateC" c_conjugateC :: TCVCV
cloneVector :: Storable t => Vector t -> IO (Vector t)
cloneVector v = do
let n = dim v
r <- createVector n
let f _ s _ d = copyArray d s n >> return 0
app2 f vec v vec r "cloneVector"
return r
mapVector :: (Storable a, Storable b) => (a-> b) -> Vector a -> Vector b
mapVector f v = unsafePerformIO $ do
w <- createVector (dim v)
unsafeWith v $ \p ->
unsafeWith w $ \q -> do
let go (1) = return ()
go !k = do x <- peekElemOff p k
pokeElemOff q k (f x)
go (k1)
go (dim v 1)
return w
zipVectorWith :: (Storable a, Storable b, Storable c) => (a-> b -> c) -> Vector a -> Vector b -> Vector c
zipVectorWith f u v = unsafePerformIO $ do
let n = min (dim u) (dim v)
w <- createVector n
unsafeWith u $ \pu ->
unsafeWith v $ \pv ->
unsafeWith w $ \pw -> do
let go (1) = return ()
go !k = do x <- peekElemOff pu k
y <- peekElemOff pv k
pokeElemOff pw k (f x y)
go (k1)
go (n 1)
return w
unzipVectorWith :: (Storable (a,b), Storable c, Storable d)
=> ((a,b) -> (c,d)) -> Vector (a,b) -> (Vector c,Vector d)
unzipVectorWith f u = unsafePerformIO $ do
let n = dim u
v <- createVector n
w <- createVector n
unsafeWith u $ \pu ->
unsafeWith v $ \pv ->
unsafeWith w $ \pw -> do
let go (1) = return ()
go !k = do z <- peekElemOff pu k
let (x,y) = f z
pokeElemOff pv k x
pokeElemOff pw k y
go (k1)
go (n1)
return (v,w)
foldVector :: Storable a => (a -> b -> b) -> b -> Vector a -> b
foldVector f x v = unsafePerformIO $
unsafeWith v $ \p -> do
let go (1) s = return s
go !k !s = do y <- peekElemOff p k
go (k1::Int) (f y s)
go (dim v 1) x
foldVectorWithIndex :: Storable a => (Int -> a -> b -> b) -> b -> Vector a -> b
foldVectorWithIndex f x v = unsafePerformIO $
unsafeWith v $ \p -> do
let go (1) s = return s
go !k !s = do y <- peekElemOff p k
go (k1::Int) (f k y s)
go (dim v 1) x
foldLoop f s0 d = go (d 1) s0
where
go 0 s = f (0::Int) s
go !j !s = go (j 1) (f j s)
foldVectorG f s0 v = foldLoop g s0 (dim v)
where g !k !s = f k (at' v) s
mapVectorM :: (Storable a, Storable b, Monad m) => (a -> m b) -> Vector a -> m (Vector b)
mapVectorM f v = do
w <- return $! unsafePerformIO $! createVector (dim v)
mapVectorM' w 0 (dim v 1)
return w
where mapVectorM' w' !k !t
| k == t = do
x <- return $! inlinePerformIO $! unsafeWith v $! \p -> peekElemOff p k
y <- f x
return $! inlinePerformIO $! unsafeWith w' $! \q -> pokeElemOff q k y
| otherwise = do
x <- return $! inlinePerformIO $! unsafeWith v $! \p -> peekElemOff p k
y <- f x
_ <- return $! inlinePerformIO $! unsafeWith w' $! \q -> pokeElemOff q k y
mapVectorM' w' (k+1) t
mapVectorM_ :: (Storable a, Monad m) => (a -> m ()) -> Vector a -> m ()
mapVectorM_ f v = do
mapVectorM' 0 (dim v 1)
where mapVectorM' !k !t
| k == t = do
x <- return $! inlinePerformIO $! unsafeWith v $! \p -> peekElemOff p k
f x
| otherwise = do
x <- return $! inlinePerformIO $! unsafeWith v $! \p -> peekElemOff p k
_ <- f x
mapVectorM' (k+1) t
mapVectorWithIndexM :: (Storable a, Storable b, Monad m) => (Int -> a -> m b) -> Vector a -> m (Vector b)
mapVectorWithIndexM f v = do
w <- return $! unsafePerformIO $! createVector (dim v)
mapVectorM' w 0 (dim v 1)
return w
where mapVectorM' w' !k !t
| k == t = do
x <- return $! inlinePerformIO $! unsafeWith v $! \p -> peekElemOff p k
y <- f k x
return $! inlinePerformIO $! unsafeWith w' $! \q -> pokeElemOff q k y
| otherwise = do
x <- return $! inlinePerformIO $! unsafeWith v $! \p -> peekElemOff p k
y <- f k x
_ <- return $! inlinePerformIO $! unsafeWith w' $! \q -> pokeElemOff q k y
mapVectorM' w' (k+1) t
mapVectorWithIndexM_ :: (Storable a, Monad m) => (Int -> a -> m ()) -> Vector a -> m ()
mapVectorWithIndexM_ f v = do
mapVectorM' 0 (dim v 1)
where mapVectorM' !k !t
| k == t = do
x <- return $! inlinePerformIO $! unsafeWith v $! \p -> peekElemOff p k
f k x
| otherwise = do
x <- return $! inlinePerformIO $! unsafeWith v $! \p -> peekElemOff p k
_ <- f k x
mapVectorM' (k+1) t
mapVectorWithIndex :: (Storable a, Storable b) => (Int -> a -> b) -> Vector a -> Vector b
mapVectorWithIndex f v = unsafePerformIO $ do
w <- createVector (dim v)
unsafeWith v $ \p ->
unsafeWith w $ \q -> do
let go (1) = return ()
go !k = do x <- peekElemOff p k
pokeElemOff q k (f k x)
go (k1)
go (dim v 1)
return w
fscanfVector :: FilePath -> Int -> IO (Vector Double)
fscanfVector filename n = do
charname <- newCString filename
res <- createVector n
app1 (gsl_vector_fscanf charname) vec res "gsl_vector_fscanf"
free charname
return res
foreign import ccall unsafe "vector_fscanf" gsl_vector_fscanf:: Ptr CChar -> TV
fprintfVector :: FilePath -> String -> Vector Double -> IO ()
fprintfVector filename fmt v = do
charname <- newCString filename
charfmt <- newCString fmt
app1 (gsl_vector_fprintf charname charfmt) vec v "gsl_vector_fprintf"
free charname
free charfmt
foreign import ccall unsafe "vector_fprintf" gsl_vector_fprintf :: Ptr CChar -> Ptr CChar -> TV
freadVector :: FilePath -> Int -> IO (Vector Double)
freadVector filename n = do
charname <- newCString filename
res <- createVector n
app1 (gsl_vector_fread charname) vec res "gsl_vector_fread"
free charname
return res
foreign import ccall unsafe "vector_fread" gsl_vector_fread:: Ptr CChar -> TV
fwriteVector :: FilePath -> Vector Double -> IO ()
fwriteVector filename v = do
charname <- newCString filename
app1 (gsl_vector_fwrite charname) vec v "gsl_vector_fwrite"
free charname
foreign import ccall unsafe "vector_fwrite" gsl_vector_fwrite :: Ptr CChar -> TV