module Data.Packed.Internal.Vector where
import Data.Packed.Internal.Common
import Foreign
import Foreign.C.String
import Foreign.C.Types(CInt,CChar)
import Complex
import Control.Monad(when)
#if __GLASGOW_HASKELL__ >= 605
import GHC.ForeignPtr (mallocPlainForeignPtrBytes)
#else
import Foreign.ForeignPtr (mallocForeignPtrBytes)
#endif
import GHC.Base
import GHC.IOBase
data Vector t =
V { dim :: !Int
, fptr :: !(ForeignPtr t)
}
vec :: Adapt (CInt -> Ptr t -> r) (Vector t) r
vec = withVector
withVector (V n fp) f = withForeignPtr fp $ \p -> do
let v g = do
g (fi n) 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 $ V n fp
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
fromList :: Storable a => [a] -> Vector a
fromList l = unsafePerformIO $ do
v <- createVector (length l)
let f _ p = pokeArray p l >> return 0
app1 f vec v "fromList"
return v
safeRead v = inlinePerformIO . withForeignPtr (fptr 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 k l (v@V {dim=n})
| k<0 || k >= n || k+l > n || l < 0 = error "subVector out of range"
| otherwise = unsafePerformIO $ do
r <- createVector l
let f _ s _ d = copyArray d (advancePtr s k) l >> return 0
app2 f vec v vec r "subVector"
return r
(@>) :: Storable t => Vector t -> Int -> t
infixl 9 @>
(@>) = at
join :: Storable t => [Vector t] -> Vector t
join [] = error "joining zero vectors"
join as = unsafePerformIO $ do
let tot = sum (map dim as)
r@V {fptr = p} <- createVector tot
withForeignPtr p $ \ptr ->
joiner as tot ptr
return r
where joiner [] _ _ = return ()
joiner (V {dim = n, fptr = b} : cs) _ p = do
withForeignPtr b $ \pb -> copyArray p pb n
joiner cs 0 (advancePtr p n)
asReal :: Vector (Complex Double) -> Vector Double
asReal v = V { dim = 2*dim v, fptr = castForeignPtr (fptr v) }
asComplex :: Vector Double -> Vector (Complex Double)
asComplex v = V { dim = dim v `div` 2, fptr = castForeignPtr (fptr v) }
liftVector f x = mapVector f x
liftVector2 f u v = zipVector f u v
cloneVector :: Storable t => Vector t -> IO (Vector t)
cloneVector (v@V {dim=n}) = do
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)
withForeignPtr (fptr v) $ \p ->
withForeignPtr (fptr 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
zipVector :: (Storable a, Storable b, Storable c) => (a-> b -> c) -> Vector a -> Vector b -> Vector c
zipVector f u v = unsafePerformIO $ do
let n = min (dim u) (dim v)
w <- createVector n
withForeignPtr (fptr u) $ \pu ->
withForeignPtr (fptr v) $ \pv ->
withForeignPtr (fptr 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
foldVector f x v = unsafePerformIO $
withForeignPtr (fptr (v::Vector Double)) $ \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
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
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 "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 "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 "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 "vector_fwrite" gsl_vector_fwrite :: Ptr CChar -> TV