packages feed

repa 2.1.1.6 → 2.2.0.1

raw patch · 8 files changed

+144/−78 lines, 8 filesdep ~vector

Dependency ranges changed: vector

Files

Data/Array/Repa.hs view
@@ -9,6 +9,12 @@ --   There is a draft tutorial at <http://www.haskell.org/haskellwiki/Numeric_Haskell:_A_Repa_Tutorial> -- -- @Release Notes:+--  For 2.2.0.1:+--   * Added unsafeFromForeignPtr, which helps use foreign source+--     arrays without intermediate copying.+--   * Added forceWith and forceWith2, which can be used to force+--     arrays into foreign result buffers without intermediate copying.+-- --  For 2.1.0.1: --   * The fold and foldAll functions now run in parallel and require the --     starting element to be neutral with respect to the reduction operator.@@ -46,10 +52,12 @@ 	, fromFunction 	, fromVector 	, fromList+	, unsafeFromForeignPtr  	-- from Data.Array.Repa.Interlals.Forcing ------------------- 	-- * Forcing-	, force, force2+	, force,  forceWith+	, force2, forceWith2 	, toVector 	, toList 
Data/Array/Repa/Internals/Base.hs view
@@ -22,13 +22,17 @@ 	-- * Construction 	, fromFunction 	, fromVector-	, fromList)+	, fromList+	, unsafeFromForeignPtr) where import Data.Array.Repa.Index import Data.Array.Repa.Internals.Elt import Data.Array.Repa.Shape			as S import qualified Data.Vector.Unboxed		as V import Data.Vector.Unboxed			(Vector)+import Foreign.ForeignPtr+import Foreign.Storable+import System.IO.Unsafe  stage	= "Data.Array.Repa.Array" @@ -366,7 +370,6 @@ 	  Array sh [Region RangeAll (GenManifest vec)]  --- Conversion ------------------------------------------------------------------------------------- -- | Convert a list to an array. --	The length of the list must be exactly the `size` of the extent given, else `error`. fromList@@ -387,4 +390,21 @@ 	= Array sh [Region RangeAll (GenManifest vec)]  	where	vec	= V.fromList xx+++-- | Convert a `Ptr` to an `Array`. +--   The data is used directly, and not copied.+--   You promise not to modify the pointed-to data any further.+--   +unsafeFromForeignPtr+        :: (Shape sh, Elt a, Storable a)+        => sh+        -> ForeignPtr a   +        -> Array sh a++unsafeFromForeignPtr sh fptr+ = fromFunction sh +        (\ix -> unsafePerformIO +             $  withForeignPtr fptr+                        (\ptr -> peekElemOff ptr $ toIndex sh ix)) 
Data/Array/Repa/Internals/EvalBlockwise.hs view
@@ -1,4 +1,7 @@ {-# LANGUAGE BangPatterns #-}++-- | Old non-cursored, blockwise filling functions.+--   NOTE: this isn't currently used. module Data.Array.Repa.Internals.EvalBlockwise 	( fillVectorBlockwiseP 	, fillVectorBlock
Data/Array/Repa/Internals/EvalChunked.hs view
@@ -5,42 +5,37 @@ 	( fillChunkedS 	, fillChunkedP) where-import Data.Array.Repa.Internals.Elt import Data.Array.Repa.Internals.Gang-import Data.Vector.Unboxed			as V-import Data.Vector.Unboxed.Mutable		as VM import GHC.Base					(remInt, quotInt) import Prelude					as P  --- | Fill a vector sequentially.+-- | Fill something sequentially. fillChunkedS-	:: Elt a- 	=> IOVector a	-- ^ Vector to fill.-	-> (Int -> a)	-- ^ Fn to get the value at a given index.+	:: Int                  -- ^ Number of elements+	-> (Int -> a -> IO ())	-- ^ Update function to write into result buffer+	-> (Int -> a)	        -- ^ Fn to get the value at a given index. 	-> IO ()  {-# INLINE [0] fillChunkedS #-}-fillChunkedS !vec !getElem+fillChunkedS !len !write !getElem  = fill 0- where 	!len	= VM.length vec--	fill !ix+ where	fill !ix 	 | ix >= len	= return () 	 | otherwise-	 = do	VM.unsafeWrite vec ix (getElem ix)+	 = do	write ix (getElem ix) 		fill (ix + 1)  --- | Fill a vector in parallel.+-- | Fill something in parallel. fillChunkedP-	:: Unbox a-	=> IOVector a	-- ^ Vector to fill.-	-> (Int -> a)	-- ^ Fn to get the value at a given index.+        :: Int                  -- ^ Number of elements+	-> (Int -> a -> IO ())	-- ^ Update function to write into result buffer+	-> (Int -> a)	        -- ^ Fn to get the value at a given index. 	-> IO ()  {-# INLINE [0] fillChunkedP #-}-fillChunkedP !vec !getElem+fillChunkedP !len !write !getElem  = 	gangIO theGang 	 $  \thread -> fill (splitIx thread) (splitIx (thread + 1)) @@ -49,7 +44,6 @@ 	-- If the length of the vector doesn't divide evenly among the threads, 	-- then the first few get an extra element. 	!threads 	= gangSize theGang-	!len		= VM.length vec 	!chunkLen 	= len `quotInt` threads 	!chunkLeftover	= len `remInt`  threads @@ -63,6 +57,6 @@ 	fill !ix !end 	 | ix >= end		= return () 	 | otherwise-	 = do	VM.unsafeWrite vec ix (getElem ix)+	 = do	write ix (getElem ix) 		fill (ix + 1) end 
Data/Array/Repa/Internals/EvalCursored.hs view
@@ -7,7 +7,6 @@ import Data.Array.Repa.Index import Data.Array.Repa.Internals.Elt import Data.Array.Repa.Internals.Gang-import Data.Vector.Unboxed.Mutable		as VM import GHC.Base					(remInt, quotInt) import Prelude					as P @@ -18,7 +17,7 @@ --   We divide the block into columns, and give one column to each thread. fillCursoredBlock2P 	:: Elt a-	=> IOVector a		-- ^ vector to write elements into+	=> (Int -> a -> IO ())		-- ^ Update function to write into result buffer 	-> (DIM2   -> cursor)		-- ^ make a cursor to a particular element 	-> (DIM2   -> cursor -> cursor)	-- ^ shift the cursor by an offset 	-> (cursor -> a)		-- ^ fn to evaluate an element at the given index.@@ -31,7 +30,7 @@  {-# INLINE [0] fillCursoredBlock2P #-} fillCursoredBlock2P-	!vec+	!write 	!makeCursorFCB !shiftCursorFCB !getElemFCB 	!imageWidth !x0 !y0 !x1 !y1  = 	gangIO theGang fillBlock@@ -59,7 +58,7 @@ 		!y0'	= y0 		!y1'	= y1 	   in	fillCursoredBlock2-			vec+			write 			makeCursorFCB shiftCursorFCB getElemFCB 			imageWidth x0' y0' x1' y1' @@ -68,7 +67,7 @@ --   Coordinates given are of the filled edges of the block. fillCursoredBlock2 	:: Elt a-	=> IOVector a			-- ^ vector to write elements into.+	=> (Int -> a -> IO ())		-- ^ Update function to write into result buffer 	-> (DIM2   -> cursor)		-- ^ make a cursor to a particular element 	-> (DIM2   -> cursor -> cursor)	-- ^ shift the cursor by an offset 	-> (cursor -> a)		-- ^ fn to evaluate an element at the given index.@@ -81,7 +80,7 @@  {-# INLINE [0] fillCursoredBlock2 #-} fillCursoredBlock2-	!vec+	!write 	!makeCursor !shiftCursor !getElem 	!imageWidth !x0 !y0 !x1 !y1 @@ -122,16 +121,16 @@  			-- Compute cursor into destination array. 			let !dstCur0	= x + y * imageWidth-			VM.unsafeWrite vec (dstCur0)     val0-			VM.unsafeWrite vec (dstCur0 + 1) val1-			VM.unsafeWrite vec (dstCur0 + 2) val2-			VM.unsafeWrite vec (dstCur0 + 3) val3+			write (dstCur0)     val0+			write (dstCur0 + 1) val1+			write (dstCur0 + 2) val2+			write (dstCur0 + 3) val3 			fillLine4 (x + 4)  		{-# INLINE fillLine1 #-} 		fillLine1 !x  	   	 | x > x1		= return () 	   	 | otherwise-	   	 = do	VM.unsafeWrite vec (x + y * imageWidth) (getElem $ makeCursor (Z :. y :. x))+	   	 = do	write (x + y * imageWidth) (getElem $ makeCursor (Z :. y :. x)) 			fillLine1 (x + 1) 
Data/Array/Repa/Internals/Forcing.hs view
@@ -2,7 +2,8 @@ module Data.Array.Repa.Internals.Forcing 	( toVector 	, toList-	, force, force2)+	, force,  forceWith+	, force2, forceWith2) where import Data.Array.Repa.Internals.EvalChunked import Data.Array.Repa.Internals.EvalCursored@@ -63,11 +64,28 @@  		Array sh _ 		 -> do	mvec	<- VM.unsafeNew (S.size sh)-			fillChunkedP mvec (\ix -> arr' `unsafeIndex` fromIndex sh ix)+                        forceWith (VM.unsafeWrite mvec) arr' 			vec	<- V.unsafeFreeze mvec 			return	(sh, vec)  +-- | Force an array, passing elements to the provided update function.+--   Provide something like @(Foreign.Ptr.pokeElemOff ptr)@ to write elements into a buffer.+--   The array is split into linear chunks and each chunk is evaluated in parallel.+forceWith+        :: (Shape sh, Elt a)+        => (Int -> a -> IO ())+        -> Array sh a+        -> IO ()++{-# INLINE [2] forceWith #-}        +forceWith !update arr@(Array sh _)+        = fillChunkedP  +                (S.size sh)+		update+		(\ix -> arr `unsafeIndex` fromIndex sh ix)++ -- | Force an array, so that it becomes `Manifest`. --   This forcing function is specialised for DIM2 arrays, and does blockwise filling. force2	:: Elt a => Array DIM2 a -> Array DIM2 a@@ -86,30 +104,46 @@ 	 	 -> 	return (sh, vec)  		-- Create a vector to hold the new array and load in the regions.-		-- NOTE We must specialise this for the common case of two regions to enable-		--      fusion for them. If we just have the next case (arbitrary region list)-		--      the worker won't fuse with the filling / evaluation code.-		Array sh [r1]+		Array sh _ 		 -> do	mvec	<- VM.new (S.size sh)-			fillRegion2P mvec sh r1-			vec	<- V.unsafeFreeze mvec-			return (sh, vec)+                        forceWith2 (VM.unsafeWrite mvec) arr'+                        vec     <- V.unsafeFreeze mvec+                        return (sh, vec) -		Array sh [r1, r2]-	 	 -> do	mvec	<- VM.new (S.size sh)-			fillRegion2P mvec sh r1-			fillRegion2P mvec sh r2-			vec	<- V.unsafeFreeze mvec-			return (sh, vec) -		-- Create a vector to hold the new array and load in the regions.-		Array sh regions-	 	 -> do	mvec	<- VM.new (S.size sh)-			mapM_ (fillRegion2P mvec sh) regions-			vec	<- V.unsafeFreeze mvec-			return (sh, vec)+-- | Force an array, passing elements to the provided update function.+--   Provide something like @(Foreign.Ptr.pokeElemOff ptr)@ to write elements into a buffer.+--   This forcing function is specialised for DIM2 arrays, and does blockwise filling.+forceWith2+        :: Elt a+        => (Int -> a -> IO ())+        -> Array DIM2 a+        -> IO () +{-# INLINE [2] forceWith2 #-}+forceWith2 !write arr+ = arr `deepSeqArray`+   case arr of+	-- If the array is already manifest then copy it into the buffer.+	-- We don't need a particular traversal order just for a copy.+	Array _ [Region RangeAll (GenManifest _)]+ 	 -> forceWith write arr +	-- NOTE We must specialise this for common numbers of regions so that+	--      we get fusion for them. If we just have the last case (arbitrary+	--      region list) then the worker won't fuse with the filling /+	--      evaluation code.+	Array sh [r1]+	 -> do	fillRegion2P write sh r1++	Array sh [r1, r2]+ 	 -> do	fillRegion2P write sh r1+		fillRegion2P write sh r2++	Array sh regions+ 	 -> do	mapM_ (fillRegion2P write sh) regions++ -- FillRegion2P ----------------------------------------------------------------------------------- -- | Fill an array region into a vector. --   This is specialised for DIM2 regions.@@ -120,54 +154,62 @@ -- fillRegion2P 	:: Elt a-	=> VM.IOVector a	-- ^ Vector to write elements into.+	=> (Int -> a -> IO ())	-- ^ Update function to write into result buffer 	-> DIM2			-- ^ Extent of entire array. 	-> Region DIM2 a	-- ^ Region to fill. 	-> IO ()  {-# INLINE [1] fillRegion2P #-}-fillRegion2P mvec sh@(_ :. height :. width) (Region range gen)- = mvec `seq` height `seq` width `seq`+fillRegion2P write sh@(_ :. height :. width) (Region range gen)+ = write `seq` height `seq` width `seq`    case range of 	RangeAll-	 -> fillRect2 mvec sh gen+	 -> fillRect2 write sh gen 		(Rect 	(Z :. 0          :. 0) 			(Z :. height - 1 :. width - 1)) -	RangeRects _ [rect]-	 -> fillRect2 mvec sh gen rect+	RangeRects _ [r1]+	 -> do  fillRect2 write sh gen r1 -	-- Specialise for the common case of 4 rectangles so we get fusion.-	-- The following case with mapM_ doesn't fuse because mapM_ isn't completely unrolled.+	RangeRects _ [r1, r2]+	 -> do	fillRect2 write sh gen r1+		fillRect2 write sh gen r2++	RangeRects _ [r1, r2, r3]+	 -> do	fillRect2 write sh gen r1+		fillRect2 write sh gen r2+		fillRect2 write sh gen r3+ 	RangeRects _ [r1, r2, r3, r4]-	 -> do	fillRect2 mvec sh gen r1-		fillRect2 mvec sh gen r2-		fillRect2 mvec sh gen r3-		fillRect2 mvec sh gen r4+	 -> do	fillRect2 write sh gen r1+		fillRect2 write sh gen r2+		fillRect2 write sh gen r3+		fillRect2 write sh gen r4  	RangeRects _ rects-	 -> mapM_ (fillRect2 mvec sh gen) rects+	 -> mapM_ (fillRect2 write sh gen) rects   -- | Fill a rectangle in a vector. fillRect2 	:: Elt a-	=> VM.IOVector a	-- ^ Vector to write elements into.+	=> (Int -> a -> IO ())	-- ^ Update function to write into result buffer 	-> DIM2 		-- ^ Extent of entire array. 	-> Generator DIM2 a	-- ^ Generator for array elements. 	-> Rect DIM2		-- ^ Rectangle to fill. 	-> IO ()  {-# INLINE fillRect2 #-}-fillRect2 mvec (_ :. _ :. width) gen (Rect (Z :. y0 :. x0) (Z :. y1 :. x1))- = mvec `seq` width `seq` y0 `seq` x0 `seq` y1 `seq` x1 `seq`+fillRect2 write sh@(_ :. _ :. width) gen (Rect (Z :. y0 :. x0) (Z :. y1 :. x1))+ = write `seq` width `seq` y0 `seq` x0 `seq` y1 `seq` x1 `seq`    case gen of-	GenManifest{}-	 -> error "fillRegion2P: GenManifest, copy elements."+	GenManifest vec+	 -> fillCursoredBlock2P write+		id addDim (\ix -> vec `V.unsafeIndex` toIndex sh ix)+		width x0 y0 x1 y1  	-- Cursor based arrays. 	GenCursor makeCursor shiftCursor loadElem-         -> fillCursoredBlock2P mvec+         -> fillCursoredBlock2P write 		makeCursor shiftCursor loadElem 		width x0 y0 x1 y1-
Data/Array/Repa/Internals/Gang.hs view
@@ -13,7 +13,7 @@ where import GHC.IO import GHC.ST-import GHC.Conc                  (forkOnIO)+import GHC.Conc                  (forkOn)  import Control.Concurrent.MVar import Control.Exception         (assert)@@ -141,7 +141,7 @@ 	mapM_ (\var -> addMVarFinalizer var (finaliseWorker var)) mvs  	-- Create all the worker threads-	zipWithM_ forkOnIO [0..]+	zipWithM_ forkOn [0..] 		$ zipWith gangWorker [0 .. n-1] mvs  	-- The gang is currently idle.
repa.cabal view
@@ -1,5 +1,5 @@ Name:                repa-Version:             2.1.1.6+Version:             2.2.0.1 License:             BSD3 License-file:        LICENSE Author:              The DPH Team@@ -25,7 +25,7 @@   Build-Depends:          base                 == 4.4.*,         ghc-prim             == 0.2.*,-        vector               >= 0.7 && < 0.8,+        vector               == 0.9.*,         QuickCheck           >= 2.3 && < 2.5,         template-haskell     >= 2.5 && < 2.7