summaryrefslogtreecommitdiff
path: root/packages/base/src/Data/Packed/Internal
diff options
context:
space:
mode:
authorAlberto Ruiz <aruiz@um.es>2015-06-05 16:53:45 +0200
committerAlberto Ruiz <aruiz@um.es>2015-06-05 16:53:45 +0200
commita5d14b70e70a93b2dec29fc0dfa7940488dc264a (patch)
tree2e1d698ca261a1ec492a2b47680a9de9723b482c /packages/base/src/Data/Packed/Internal
parentba04d65298266a2f6a37061bedaca4ea3cf7fae6 (diff)
move internal vector
Diffstat (limited to 'packages/base/src/Data/Packed/Internal')
-rw-r--r--packages/base/src/Data/Packed/Internal/Vector.hs496
1 files changed, 0 insertions, 496 deletions
diff --git a/packages/base/src/Data/Packed/Internal/Vector.hs b/packages/base/src/Data/Packed/Internal/Vector.hs
deleted file mode 100644
index 8cb77b0..0000000
--- a/packages/base/src/Data/Packed/Internal/Vector.hs
+++ /dev/null
@@ -1,496 +0,0 @@
1{-# LANGUAGE MagicHash, CPP, UnboxedTuples, BangPatterns, FlexibleContexts #-}
2-- |
3-- Module : Data.Packed.Internal.Vector
4-- Copyright : (c) Alberto Ruiz 2007
5-- License : BSD3
6-- Maintainer : Alberto Ruiz
7-- Stability : provisional
8--
9-- Vector implementation
10--
11--------------------------------------------------------------------------------
12
13module Data.Packed.Internal.Vector (
14 Vector, dim,
15 fromList, toList, (|>),
16 vjoin, (@>), safe, at, at', subVector, takesV,
17 mapVector, mapVectorWithIndex, zipVectorWith, unzipVectorWith,
18 mapVectorM, mapVectorM_, mapVectorWithIndexM, mapVectorWithIndexM_,
19 foldVector, foldVectorG, foldLoop, foldVectorWithIndex,
20 createVector, vec,
21 asComplex, asReal, float2DoubleV, double2FloatV, double2IntV, int2DoubleV, float2IntV, int2floatV,
22 stepF, stepD, stepI, condF, condD, condI,
23 conjugateQ, conjugateC,
24 cloneVector,
25 unsafeToForeignPtr,
26 unsafeFromForeignPtr,
27 unsafeWith,
28 CInt, I
29) where
30
31import Data.Packed.Internal.Common
32import Data.Packed.Internal.Signatures
33import Foreign.Marshal.Array(peekArray, copyArray, advancePtr)
34import Foreign.ForeignPtr(ForeignPtr, castForeignPtr)
35import Foreign.Ptr(Ptr)
36import Foreign.Storable(Storable, peekElemOff, pokeElemOff, sizeOf)
37import Foreign.C.Types
38import Data.Complex
39import System.IO.Unsafe(unsafePerformIO)
40
41#if __GLASGOW_HASKELL__ >= 605
42import GHC.ForeignPtr (mallocPlainForeignPtrBytes)
43#else
44import Foreign.ForeignPtr (mallocForeignPtrBytes)
45#endif
46
47import GHC.Base
48#if __GLASGOW_HASKELL__ < 612
49import GHC.IOBase hiding (liftIO)
50#endif
51
52import qualified Data.Vector.Storable as Vector
53import Data.Vector.Storable(Vector,
54 fromList,
55 unsafeToForeignPtr,
56 unsafeFromForeignPtr,
57 unsafeWith)
58
59type I = CInt
60
61-- | Number of elements
62dim :: (Storable t) => Vector t -> Int
63dim = Vector.length
64
65
66-- C-Haskell vector adapter
67-- vec :: Adapt (CInt -> Ptr t -> r) (Vector t) r
68vec :: (Storable t) => Vector t -> (((CInt -> Ptr t -> t1) -> t1) -> IO b) -> IO b
69vec x f = unsafeWith x $ \p -> do
70 let v g = do
71 g (fi $ dim x) p
72 f v
73{-# INLINE vec #-}
74
75
76-- allocates memory for a new vector
77createVector :: Storable a => Int -> IO (Vector a)
78createVector n = do
79 when (n < 0) $ error ("trying to createVector of negative dim: "++show n)
80 fp <- doMalloc undefined
81 return $ unsafeFromForeignPtr fp 0 n
82 where
83 --
84 -- Use the much cheaper Haskell heap allocated storage
85 -- for foreign pointer space we control
86 --
87 doMalloc :: Storable b => b -> IO (ForeignPtr b)
88 doMalloc dummy = do
89#if __GLASGOW_HASKELL__ >= 605
90 mallocPlainForeignPtrBytes (n * sizeOf dummy)
91#else
92 mallocForeignPtrBytes (n * sizeOf dummy)
93#endif
94
95{- | creates a Vector from a list:
96
97@> fromList [2,3,5,7]
984 |> [2.0,3.0,5.0,7.0]@
99
100-}
101
102safeRead v = inlinePerformIO . unsafeWith v
103{-# INLINE safeRead #-}
104
105inlinePerformIO :: IO a -> a
106inlinePerformIO (IO m) = case m realWorld# of (# _, r #) -> r
107{-# INLINE inlinePerformIO #-}
108
109{- extracts the Vector elements to a list
110
111>>> toList (linspace 5 (1,10))
112[1.0,3.25,5.5,7.75,10.0]
113
114-}
115toList :: Storable a => Vector a -> [a]
116toList v = safeRead v $ peekArray (dim v)
117
118{- | Create a vector from a list of elements and explicit dimension. The input
119 list is explicitly truncated if it is too long, so it may safely
120 be used, for instance, with infinite lists.
121
122>>> 5 |> [1..]
123fromList [1.0,2.0,3.0,4.0,5.0]
124
125-}
126(|>) :: (Storable a) => Int -> [a] -> Vector a
127infixl 9 |>
128n |> l = if length l' == n
129 then fromList l'
130 else error "list too short for |>"
131 where l' = take n l
132
133
134-- | access to Vector elements without range checking
135at' :: Storable a => Vector a -> Int -> a
136at' v n = safeRead v $ flip peekElemOff n
137{-# INLINE at' #-}
138
139--
140-- turn off bounds checking with -funsafe at configure time.
141-- ghc will optimise away the salways true case at compile time.
142--
143#if defined(UNSAFE)
144safe :: Bool
145safe = False
146#else
147safe = True
148#endif
149
150-- | access to Vector elements with range checking.
151at :: Storable a => Vector a -> Int -> a
152at v n
153 | safe = if n >= 0 && n < dim v
154 then at' v n
155 else error "vector index out of range"
156 | otherwise = at' v n
157{-# INLINE at #-}
158
159{- | takes a number of consecutive elements from a Vector
160
161>>> subVector 2 3 (fromList [1..10])
162fromList [3.0,4.0,5.0]
163
164-}
165subVector :: Storable t => Int -- ^ index of the starting element
166 -> Int -- ^ number of elements to extract
167 -> Vector t -- ^ source
168 -> Vector t -- ^ result
169subVector = Vector.slice
170
171
172{- | Reads a vector position:
173
174>>> fromList [0..9] @> 7
1757.0
176
177-}
178(@>) :: Storable t => Vector t -> Int -> t
179infixl 9 @>
180(@>) = at
181
182
183{- | concatenate a list of vectors
184
185>>> vjoin [fromList [1..5::Double], konst 1 3]
186fromList [1.0,2.0,3.0,4.0,5.0,1.0,1.0,1.0]
187
188-}
189vjoin :: Storable t => [Vector t] -> Vector t
190vjoin [] = fromList []
191vjoin [v] = v
192vjoin as = unsafePerformIO $ do
193 let tot = sum (map dim as)
194 r <- createVector tot
195 unsafeWith r $ \ptr ->
196 joiner as tot ptr
197 return r
198 where joiner [] _ _ = return ()
199 joiner (v:cs) _ p = do
200 let n = dim v
201 unsafeWith v $ \pb -> copyArray p pb n
202 joiner cs 0 (advancePtr p n)
203
204
205{- | Extract consecutive subvectors of the given sizes.
206
207>>> takesV [3,4] (linspace 10 (1,10::Double))
208[fromList [1.0,2.0,3.0],fromList [4.0,5.0,6.0,7.0]]
209
210-}
211takesV :: Storable t => [Int] -> Vector t -> [Vector t]
212takesV ms w | sum ms > dim w = error $ "takesV " ++ show ms ++ " on dim = " ++ (show $ dim w)
213 | otherwise = go ms w
214 where go [] _ = []
215 go (n:ns) v = subVector 0 n v
216 : go ns (subVector n (dim v - n) v)
217
218---------------------------------------------------------------
219
220-- | transforms a complex vector into a real vector with alternating real and imaginary parts
221asReal :: (RealFloat a, Storable a) => Vector (Complex a) -> Vector a
222asReal v = unsafeFromForeignPtr (castForeignPtr fp) (2*i) (2*n)
223 where (fp,i,n) = unsafeToForeignPtr v
224
225-- | transforms a real vector into a complex vector with alternating real and imaginary parts
226asComplex :: (RealFloat a, Storable a) => Vector a -> Vector (Complex a)
227asComplex v = unsafeFromForeignPtr (castForeignPtr fp) (i `div` 2) (n `div` 2)
228 where (fp,i,n) = unsafeToForeignPtr v
229
230---------------------------------------------------------------
231
232float2DoubleV :: Vector Float -> Vector Double
233float2DoubleV = tog c_float2double
234
235double2FloatV :: Vector Double -> Vector Float
236double2FloatV = tog c_double2float
237
238double2IntV :: Vector Double -> Vector CInt
239double2IntV = tog c_double2int
240
241int2DoubleV :: Vector CInt -> Vector Double
242int2DoubleV = tog c_int2double
243
244float2IntV :: Vector Float -> Vector CInt
245float2IntV = tog c_float2int
246
247int2floatV :: Vector CInt -> Vector Float
248int2floatV = tog c_int2float
249
250
251tog f v = unsafePerformIO $ do
252 r <- createVector (dim v)
253 app2 f vec v vec r "tog"
254 return r
255
256foreign import ccall unsafe "float2double" c_float2double :: TFV
257foreign import ccall unsafe "double2float" c_double2float :: TVF
258foreign import ccall unsafe "int2double" c_int2double :: CV CInt (CV Double (IO CInt))
259foreign import ccall unsafe "double2int" c_double2int :: CV Double (CV CInt (IO CInt))
260foreign import ccall unsafe "int2float" c_int2float :: CV CInt (CV Float (IO CInt))
261foreign import ccall unsafe "float2int" c_float2int :: CV Float (CV CInt (IO CInt))
262
263
264---------------------------------------------------------------
265
266step f v = unsafePerformIO $ do
267 r <- createVector (dim v)
268 app2 f vec v vec r "step"
269 return r
270
271stepD :: Vector Double -> Vector Double
272stepD = step c_stepD
273
274stepF :: Vector Float -> Vector Float
275stepF = step c_stepF
276
277stepI :: Vector CInt -> Vector CInt
278stepI = step c_stepI
279
280foreign import ccall unsafe "stepF" c_stepF :: TFF
281foreign import ccall unsafe "stepD" c_stepD :: TVV
282foreign import ccall unsafe "stepI" c_stepI :: CV CInt (CV CInt (IO CInt))
283
284---------------------------------------------------------------
285
286condF :: Vector Float -> Vector Float -> Vector Float -> Vector Float -> Vector Float -> Vector Float
287condF = condg c_condF
288
289condD :: Vector Double -> Vector Double -> Vector Double -> Vector Double -> Vector Double -> Vector Double
290condD = condg c_condD
291
292condI :: Vector CInt -> Vector CInt -> Vector CInt -> Vector CInt -> Vector CInt -> Vector CInt
293condI = condg c_condI
294
295
296condg f x y l e g = unsafePerformIO $ do
297 r <- createVector (dim x)
298 app6 f vec x vec y vec l vec e vec g vec r "cond"
299 return r
300
301
302foreign import ccall unsafe "condF" c_condF :: CInt -> PF -> CInt -> PF -> CInt -> PF -> TFFF
303foreign import ccall unsafe "condD" c_condD :: CInt -> PD -> CInt -> PD -> CInt -> PD -> TVVV
304foreign import ccall unsafe "condI" c_condI :: CV CInt (CV CInt (CV CInt (CV CInt (CV CInt (CV CInt (IO CInt))))))
305
306--------------------------------------------------------------------------------
307
308conjugateAux fun x = unsafePerformIO $ do
309 v <- createVector (dim x)
310 app2 fun vec x vec v "conjugateAux"
311 return v
312
313conjugateQ :: Vector (Complex Float) -> Vector (Complex Float)
314conjugateQ = conjugateAux c_conjugateQ
315foreign import ccall unsafe "conjugateQ" c_conjugateQ :: TQVQV
316
317conjugateC :: Vector (Complex Double) -> Vector (Complex Double)
318conjugateC = conjugateAux c_conjugateC
319foreign import ccall unsafe "conjugateC" c_conjugateC :: TCVCV
320
321--------------------------------------------------------------------------------
322
323cloneVector :: Storable t => Vector t -> IO (Vector t)
324cloneVector v = do
325 let n = dim v
326 r <- createVector n
327 let f _ s _ d = copyArray d s n >> return 0
328 app2 f vec v vec r "cloneVector"
329 return r
330
331------------------------------------------------------------------
332
333-- | map on Vectors
334mapVector :: (Storable a, Storable b) => (a-> b) -> Vector a -> Vector b
335mapVector f v = unsafePerformIO $ do
336 w <- createVector (dim v)
337 unsafeWith v $ \p ->
338 unsafeWith w $ \q -> do
339 let go (-1) = return ()
340 go !k = do x <- peekElemOff p k
341 pokeElemOff q k (f x)
342 go (k-1)
343 go (dim v -1)
344 return w
345{-# INLINE mapVector #-}
346
347-- | zipWith for Vectors
348zipVectorWith :: (Storable a, Storable b, Storable c) => (a-> b -> c) -> Vector a -> Vector b -> Vector c
349zipVectorWith f u v = unsafePerformIO $ do
350 let n = min (dim u) (dim v)
351 w <- createVector n
352 unsafeWith u $ \pu ->
353 unsafeWith v $ \pv ->
354 unsafeWith w $ \pw -> do
355 let go (-1) = return ()
356 go !k = do x <- peekElemOff pu k
357 y <- peekElemOff pv k
358 pokeElemOff pw k (f x y)
359 go (k-1)
360 go (n -1)
361 return w
362{-# INLINE zipVectorWith #-}
363
364-- | unzipWith for Vectors
365unzipVectorWith :: (Storable (a,b), Storable c, Storable d)
366 => ((a,b) -> (c,d)) -> Vector (a,b) -> (Vector c,Vector d)
367unzipVectorWith f u = unsafePerformIO $ do
368 let n = dim u
369 v <- createVector n
370 w <- createVector n
371 unsafeWith u $ \pu ->
372 unsafeWith v $ \pv ->
373 unsafeWith w $ \pw -> do
374 let go (-1) = return ()
375 go !k = do z <- peekElemOff pu k
376 let (x,y) = f z
377 pokeElemOff pv k x
378 pokeElemOff pw k y
379 go (k-1)
380 go (n-1)
381 return (v,w)
382{-# INLINE unzipVectorWith #-}
383
384foldVector :: Storable a => (a -> b -> b) -> b -> Vector a -> b
385foldVector f x v = unsafePerformIO $
386 unsafeWith v $ \p -> do
387 let go (-1) s = return s
388 go !k !s = do y <- peekElemOff p k
389 go (k-1::Int) (f y s)
390 go (dim v -1) x
391{-# INLINE foldVector #-}
392
393-- the zero-indexed index is passed to the folding function
394foldVectorWithIndex :: Storable a => (Int -> a -> b -> b) -> b -> Vector a -> b
395foldVectorWithIndex f x v = unsafePerformIO $
396 unsafeWith v $ \p -> do
397 let go (-1) s = return s
398 go !k !s = do y <- peekElemOff p k
399 go (k-1::Int) (f k y s)
400 go (dim v -1) x
401{-# INLINE foldVectorWithIndex #-}
402
403foldLoop f s0 d = go (d - 1) s0
404 where
405 go 0 s = f (0::Int) s
406 go !j !s = go (j - 1) (f j s)
407
408foldVectorG f s0 v = foldLoop g s0 (dim v)
409 where g !k !s = f k (at' v) s
410 {-# INLINE g #-} -- Thanks to Ryan Ingram (http://permalink.gmane.org/gmane.comp.lang.haskell.cafe/46479)
411{-# INLINE foldVectorG #-}
412
413-------------------------------------------------------------------
414
415-- | monadic map over Vectors
416-- the monad @m@ must be strict
417mapVectorM :: (Storable a, Storable b, Monad m) => (a -> m b) -> Vector a -> m (Vector b)
418mapVectorM f v = do
419 w <- return $! unsafePerformIO $! createVector (dim v)
420 mapVectorM' w 0 (dim v -1)
421 return w
422 where mapVectorM' w' !k !t
423 | k == t = do
424 x <- return $! inlinePerformIO $! unsafeWith v $! \p -> peekElemOff p k
425 y <- f x
426 return $! inlinePerformIO $! unsafeWith w' $! \q -> pokeElemOff q k y
427 | otherwise = do
428 x <- return $! inlinePerformIO $! unsafeWith v $! \p -> peekElemOff p k
429 y <- f x
430 _ <- return $! inlinePerformIO $! unsafeWith w' $! \q -> pokeElemOff q k y
431 mapVectorM' w' (k+1) t
432{-# INLINE mapVectorM #-}
433
434-- | monadic map over Vectors
435mapVectorM_ :: (Storable a, Monad m) => (a -> m ()) -> Vector a -> m ()
436mapVectorM_ f v = do
437 mapVectorM' 0 (dim v -1)
438 where mapVectorM' !k !t
439 | k == t = do
440 x <- return $! inlinePerformIO $! unsafeWith v $! \p -> peekElemOff p k
441 f x
442 | otherwise = do
443 x <- return $! inlinePerformIO $! unsafeWith v $! \p -> peekElemOff p k
444 _ <- f x
445 mapVectorM' (k+1) t
446{-# INLINE mapVectorM_ #-}
447
448-- | monadic map over Vectors with the zero-indexed index passed to the mapping function
449-- the monad @m@ must be strict
450mapVectorWithIndexM :: (Storable a, Storable b, Monad m) => (Int -> a -> m b) -> Vector a -> m (Vector b)
451mapVectorWithIndexM f v = do
452 w <- return $! unsafePerformIO $! createVector (dim v)
453 mapVectorM' w 0 (dim v -1)
454 return w
455 where mapVectorM' w' !k !t
456 | k == t = do
457 x <- return $! inlinePerformIO $! unsafeWith v $! \p -> peekElemOff p k
458 y <- f k x
459 return $! inlinePerformIO $! unsafeWith w' $! \q -> pokeElemOff q k y
460 | otherwise = do
461 x <- return $! inlinePerformIO $! unsafeWith v $! \p -> peekElemOff p k
462 y <- f k x
463 _ <- return $! inlinePerformIO $! unsafeWith w' $! \q -> pokeElemOff q k y
464 mapVectorM' w' (k+1) t
465{-# INLINE mapVectorWithIndexM #-}
466
467-- | monadic map over Vectors with the zero-indexed index passed to the mapping function
468mapVectorWithIndexM_ :: (Storable a, Monad m) => (Int -> a -> m ()) -> Vector a -> m ()
469mapVectorWithIndexM_ f v = do
470 mapVectorM' 0 (dim v -1)
471 where mapVectorM' !k !t
472 | k == t = do
473 x <- return $! inlinePerformIO $! unsafeWith v $! \p -> peekElemOff p k
474 f k x
475 | otherwise = do
476 x <- return $! inlinePerformIO $! unsafeWith v $! \p -> peekElemOff p k
477 _ <- f k x
478 mapVectorM' (k+1) t
479{-# INLINE mapVectorWithIndexM_ #-}
480
481
482mapVectorWithIndex :: (Storable a, Storable b) => (Int -> a -> b) -> Vector a -> Vector b
483--mapVectorWithIndex g = head . mapVectorWithIndexM (\a b -> [g a b])
484mapVectorWithIndex f v = unsafePerformIO $ do
485 w <- createVector (dim v)
486 unsafeWith v $ \p ->
487 unsafeWith w $ \q -> do
488 let go (-1) = return ()
489 go !k = do x <- peekElemOff p k
490 pokeElemOff q k (f k x)
491 go (k-1)
492 go (dim v -1)
493 return w
494{-# INLINE mapVectorWithIndex #-}
495
496