packages feed

repa (empty) → 1.0.0.0

raw patch · 8 files changed

+1074/−0 lines, 8 filesdep +QuickCheckdep +basedep +dph-prim-parsetup-changed

Dependencies added: QuickCheck, base, dph-prim-par, dph-prim-seq

Files

+ Data/Array/Repa.hs view
@@ -0,0 +1,629 @@+{-# LANGUAGE PatternGuards, PackageImports #-}+{-# LANGUAGE ScopedTypeVariables, RankNTypes #-}+{-# LANGUAGE TypeOperators, FlexibleContexts #-}++-- | See the repa-examples package for examples.+--   +--   More information is also at http://code.haskell.org/trac/repa  +-- +--   NOTE: 	To get decent performance you must use GHC head branch > 6.13.20100309.+--+--   WARNING: 	Most of the functions that operate on indices don't perform bounds checks.+--		Doing these checks would interfere with code optimisation and reduce performance.		+--		Indexing outside arrays, or failing to meet the stated obligations will+--		likely cause heap corruption.+--+--   +module Data.Array.Repa+	( module Data.Array.Repa.Shape+	, module Data.Array.Repa.Index+	, module Data.Array.Repa.Slice+	+	, Array	(..)++	 -- * Constructors+	, fromUArray+	, fromFunction+	, unit++	 -- * Projections+	, extent+	, delay+	, toUArray+	, index, (!:)+	, toScalar++	 -- * Basic Operations+	, force+	, isManifest+	, deepSeqArray+	+	 -- * Conversion+	, fromList+	, toList++	 -- * Index space transformations+	, reshape+	, append, (+:+)+	, transpose+	, replicate+	, slice+	, backpermute+	, backpermuteDft++         -- * Structure preserving operations+	, map+	, zipWith++	 -- * Reductions+	, fold+	, sum+	, sumAll+	+	 -- * Generic traversal+	, traverse+	, traverse2+		+	 -- * Testing+	, arbitrarySmallArray+	, props_DataArrayRepa)+where+import Data.Array.Repa.Index+import Data.Array.Repa.Slice+import Data.Array.Repa.Shape+import Data.Array.Repa.QuickCheck+import qualified Data.Array.Repa.Shape	as S++import "dph-prim-par" Data.Array.Parallel.Unlifted			(Elt)+import qualified "dph-prim-par" Data.Array.Parallel.Unlifted		as U+import qualified "dph-prim-seq" Data.Array.Parallel.Unlifted.Sequential	as USeq++import Test.QuickCheck+import Prelude				hiding (sum, map, zipWith, replicate)	+import qualified Prelude		as P++stage	= "Data.Array.Repa"+	+-- | Possibly delayed arrays.+data Array sh a+	= -- | An array represented as some concrete unboxed data.+	  Manifest sh (U.Array a)++          -- | An array represented as a function that computes each element.+	| Delayed  sh (sh -> a)++-- Constructors ----------------------------------------------------------------------------------++-- | Create a `Manifest` array from an unboxed `U.Array`. +--	The elements are in row-major order.+fromUArray+	:: Shape sh+	=> sh+	-> U.Array a+	-> Array sh a++{-# INLINE fromUArray #-}+fromUArray sh uarr+	= sh   `S.deepSeq` +	  uarr `seq`+	  Manifest sh uarr+++-- | Create a `Delayed` array from a function.+fromFunction +	:: Shape sh+	=> sh+	-> (sh -> a)+	-> Array sh a+	+{-# INLINE fromFunction #-}+fromFunction sh fnElems+	= sh `S.deepSeq` Delayed sh fnElems+++-- | Wrap a scalar into a singleton array.+unit :: Elt a => a -> Array Z a+{-# INLINE unit #-}+unit 	= Delayed Z . const+++-- Projections ------------------------------------------------------------------------------------++-- | Take the extent of an array.+extent	:: Array sh a -> sh+{-# INLINE extent #-}+extent arr+ = case arr of+	Manifest sh _	-> sh+	Delayed  sh _	-> sh++-- | Unpack an array into delayed form.+delay 	:: (Shape sh, Elt a) +	=> Array sh a +	-> (sh, sh -> a)++{-# INLINE delay #-}	+delay arr+ = case arr of+	Manifest sh uarr	-> (sh, \i -> uarr U.!: S.toIndex sh i)+	Delayed  sh fn		-> (sh, fn)+++-- | Convert an array to an unboxed `U.Array`, forcing it if required.+--	The elements come out in row-major order.+toUArray +	:: (Shape sh, Elt a)+	=> Array sh a +	-> U.Array a+{-# INLINE toUArray #-}+toUArray arr+ = case force arr of+	Manifest _ uarr	-> uarr+	_		-> error $ stage ++ ".toList: force failed"+++-- | Get an indexed element from an array.+--+--   OBLIGATION: The index must be within the array. +--+-- 	@inRange zeroDim (shape arr) ix == True@+--+index, (!:)+	:: forall sh a+	.  (Shape sh, Elt a)+	=> Array sh a+	-> sh +	-> a++{-# INLINE index #-}+index arr ix+ = case arr of+	Delayed  _  fn		-> fn ix+	Manifest sh uarr	-> uarr U.!: (S.toIndex sh ix)++{-# INLINE (!:) #-}+(!:) arr ix = index arr ix+++-- | Take the scalar value from a singleton array.+toScalar :: Elt a => Array Z a -> a+{-# INLINE toScalar #-}+toScalar arr+ = case arr of+	Delayed  _ fn		-> fn Z+	Manifest _ uarr		-> uarr U.!: 0+++-- Basic Operations -------------------------------------------------------------------------------++-- | Force an array, so that it becomes `Manifest`.+force	:: (Shape sh, Elt a)+	=> Array sh a -> Array sh a+	+{-# INLINE force #-}+force arr+ = case arr of+	Manifest sh uarr+	 -> sh `S.deepSeq` uarr `seq` +	    Manifest sh uarr++	Delayed sh fn+	 -> let uarr	=  U.map (fn . S.fromIndex sh) +			$! U.enumFromTo (0 :: Int) (S.size sh - 1)+	    in	sh `S.deepSeq` uarr `seq`+		Manifest sh uarr+		++isManifest :: Array sh a -> Array sh a+{-# INLINE isManifest #-}+isManifest arr+ = case arr of+	Manifest{}	-> arr+	_		-> error "not manifest"+	+	+-- | Ensure an array's structure is fully evaluated.+--	This evaluates the extent and outer constructor, but does not `force` the elements.+infixr 0 `deepSeqArray`+deepSeqArray +	:: Shape sh+	=> Array sh a +	-> b -> b++{-# INLINE deepSeqArray #-}+deepSeqArray arr x + = case arr of+	Delayed  sh _		-> sh `S.deepSeq` x+	Manifest sh uarr	-> sh `S.deepSeq` uarr `seq` x+++-- Conversion -------------------------------------------------------------------------------------+-- | Convert a list to an array.+--	The length of the list must be exactly the `size` of the extent given, else `error`.+--+fromList+	:: (Shape sh, Elt a)+	=> sh+	-> [a]+	-> Array sh a+	+{-# INLINE fromList #-}+fromList sh xx+	| U.length uarr /= S.size sh+	= error $ unlines+	 	[ stage ++ ".fromList: size of array shape does not match size of list"+		, "        size of shape = " ++ (show $ S.size sh) 	++ "\n"+		, "        size of list  = " ++ (show $ U.length uarr) 	++ "\n" ]+	+	| otherwise+	= Manifest sh uarr++	where	uarr	= U.fromList xx+	+	+-- | Convert an array to a list.+toList 	:: (Shape sh, Elt a)+	=> Array sh a+	-> [a]++{-# INLINE toList #-}+toList arr+ = case force arr of+	Manifest _ uarr	-> U.toList uarr+	_		-> error $ stage ++ ".toList: force failed"+++-- Instances --------------------------------------------------------------------------------------++-- Show+instance (Shape sh, Elt a, Show a) => Show (Array sh a) where+ 	show arr = show $ toList arr++-- Eq+instance (Shape sh, Elt a, Eq a) => Eq (Array sh a) where++	{-# INLINE (==) #-}+	(==) arr1  arr2 +		= toScalar +		$ fold (&&) True +		$ (flip reshape) (Z :. (S.size $ extent arr1)) +		$ zipWith (==) arr1 arr2+		+	{-# INLINE (/=) #-}+	(/=) a1 a2 +		= not $ (==) a1 a2++-- Num+-- All operators apply elementwise.+instance (Shape sh, Elt a, Num a) => Num (Array sh a) where+	(+)		= zipWith (+)+	(-)		= zipWith (-)+	(*)		= zipWith (*)+	negate  	= map negate+	abs		= map abs+	signum 		= map signum++	fromInteger n	 = Delayed failShape (\_ -> fromInteger n) +	 where failShape = error $ stage ++ ".fromInteger: Constructed array has no shape."+++-- Index space transformations --------------------------------------------------------------------+-- | Impose a new shape on the elements of an array.+--	The new extent must be the same size as the original, else `error`.+--+reshape	:: (Shape sh, Shape sh', Elt a) +	=> Array sh a+	-> sh'+	-> Array sh' a++{-# INLINE reshape #-}+reshape arr newExtent+	| not $ S.size newExtent == S.size (extent arr)+	= error $ stage ++ ".reshape: reshaped array will not match size of the original"+	+	| otherwise+	= Delayed newExtent+	$ ((arr !:) . (S.fromIndex (extent arr)) . (S.toIndex newExtent))+++-- | Append two arrays.+--+--   OBLIGATION: The higher dimensions of both arrays must have the same extent.+--+--   @tail (listOfShape (shape arr1)) == tail (listOfShape (shape arr2))@+--+append, (+:+)	+	:: (Shape sh, Elt a)+	=> Array (sh :. Int) a+	-> Array (sh :. Int) a+	-> Array (sh :. Int) a++{-# INLINE append #-}+append arr1 arr2 + = traverse2 arr1 arr2 fnExtent fnElem+ where+ 	(_ :. n) 	= extent arr1++	fnExtent (sh :. i) (_  :. j) +		= sh :. (i + j)++	fnElem f1 f2 (sh :. i)+      		| i < n		= f1 (sh :. i)+  		| otherwise	= f2 (sh :. (i - n))++{-# INLINE (+:+) #-}+(+:+) arr1 arr2 = append arr1 arr2+++-- | Transpose the lowest two dimensions of an array. +--	Transposing an array twice yields the original.+transpose +	:: (Shape sh, Elt a) +	=> Array (sh :. Int :. Int) a+	-> Array (sh :. Int :. Int) a++{-# INLINE transpose #-}+transpose arr + = traverse arr+	(\(sh :. m :. n) 	-> (sh :. n :.m))+	(\f -> \(sh :. i :. j) 	-> f (sh :. j :. i))+++-- | Replicate an array, according to a given slice specification.+replicate+	:: ( Slice sl+	   , Shape (FullShape sl)+	   , Shape (SliceShape sl)+	   , Elt e)+	=> sl+	-> Array (SliceShape sl) e+	-> Array (FullShape sl) e++{-# INLINE replicate #-}+replicate sl arr+	= backpermute +		(fullOfSlice sl (extent arr)) +		(sliceOfFull sl)+		arr++-- | Take a slice from an array, according to a given specification.+slice	:: ( Slice sl+	   , Shape (FullShape sl)+	   , Shape (SliceShape sl)+	   , Elt e)+	=> Array (FullShape sl) e+	-> sl+	-> Array (SliceShape sl) e++{-# INLINE slice #-}+slice arr sl+	= backpermute +		(sliceOfFull sl (extent arr))+		(fullOfSlice sl)+		arr+++-- | Backwards permutation of an array's elements.+--	The result array has the same extent as the original.+backpermute+	:: forall sh sh' a+	.  (Shape sh, Shape sh', Elt a) +	=> sh' 				-- ^ Extent of result array.+	-> (sh' -> sh) 			-- ^ Function mapping each index in the result array+					--	to an index of the source array.+	-> Array sh a 			-- ^ Source array.+	-> Array sh' a++{-# INLINE backpermute #-}+backpermute newExtent perm arr+	= traverse arr (const newExtent) (. perm) +	++-- | Default backwards permutation of an array's elements.+--	If the function returns `Nothing` then the value at that index is taken+--	from the default array (@arrDft@)+backpermuteDft+	:: forall sh sh' a+	.  (Shape sh, Shape sh', Elt a) +	=> Array sh' a			-- ^ Default values (@arrDft@)+	-> (sh' -> Maybe sh) 		-- ^ Function mapping each index in the result array+					--	to an index in the source array.+	-> Array sh  a			-- ^ Source array.+	-> Array sh' a++{-# INLINE backpermuteDft #-}+backpermuteDft arrDft fnIndex arrSrc+	= Delayed (extent arrDft) fnElem+	where	fnElem ix	+		 = case fnIndex ix of+			Just ix'	-> arrSrc !: ix'+			Nothing		-> arrDft !: ix+				++-- Structure Preserving Operations ----------------------------------------------------------------+-- | Apply a worker function to each element of an array, +--	yielding a new array with the same extent.+map	:: (Shape sh, Elt a, Elt b) +	=> (a -> b)+	-> Array sh a+	-> Array sh b++{-# INLINE map #-}+map f arr+	= Delayed (extent arr) (f . (arr !:))+++-- | Combine two arrays, element-wise, with a binary operator.+--	If the extent of the two array arguments differ, +--	then the resulting array's extent is their intersection.+zipWith :: (Shape sh, Elt a, Elt b, Elt c) +	=> (a -> b -> c) +	-> Array sh a+	-> Array sh b+	-> Array sh c++{-# INLINE zipWith #-}+zipWith f arr1 arr2+ 	= arr1 `deepSeqArray` +	  arr2 `deepSeqArray`+	  Delayed	(S.intersectDim (extent arr1) (extent arr2))+			(\ix -> f (arr1 !: ix) (arr2 !: ix))+++-- Reductions -------------------------------------------------------------------------------------++-- IMPORTANT: +--	These reductions use the sequential version of foldU, mapU and enumFromToU.+--	If we use parallel versions then we'll end up with nested parallelism+--	and the gang will abort at runtime.++-- | Fold the innermost dimension of an array.+--	Combine this with `transpose` to fold any other dimension.+fold 	:: (Shape sh, Elt a)+	=> (a -> a -> a)+	-> a +	-> Array (sh :. Int) a+	-> Array sh a++{-# INLINE fold #-}+fold f x arr+ = x `seq` arr `deepSeqArray` +   let	sh' :. n	= extent arr+	elemFn i 	= USeq.foldU f x+			$ USeq.mapU+				(\ix -> arr !: (i :. ix)) +				(USeq.enumFromToU 0 (n - 1))+   in	Delayed sh' elemFn+++-- | Sum the innermost dimension of an array.+sum	:: (Shape sh, Elt a, Num a)+	=> Array (sh :. Int) a+	-> Array sh a++{-# INLINE sum #-}+sum arr	= fold (+) 0 arr+++-- | Sum all the elements of an array.+sumAll	:: (Shape sh, Elt a, Num a)+	=> Array sh a+	-> a++{-# INLINE sumAll #-}+sumAll arr+	= USeq.foldU (+) 0+	$ USeq.mapU ((arr !:) . (S.fromIndex (extent arr)))+	$ USeq.enumFromToU+		0+		((S.size $ extent arr) - 1)+++-- Generic Traversal -----------------------------------------------------------------------------+-- | Unstructured traversal.+traverse+	:: forall sh sh' a b+	.  (Shape sh, Shape sh', Elt a)+	=> Array sh a				-- ^ Source array.+	-> (sh  -> sh')				-- ^ Function to produce the extent of the result.+	-> ((sh -> a) -> sh' -> b)		-- ^ Function to produce elements of the result. +	 					--   It is passed a lookup function to get elements of the source.+	-> Array sh' b+	+{-# INLINE traverse #-}+traverse arr transExtent newElem+	= arr `deepSeqArray`+	  Delayed +		(transExtent (extent arr)) +		(newElem     (arr !:))+++-- | Unstructured traversal over two arrays at once.+traverse2+	:: forall sh sh' sh'' a b c+	.  ( Shape sh, Shape sh', Shape sh''+	   , Elt a,    Elt b,     Elt c)+        => Array sh a 				-- ^ First source array.+	-> Array sh' b				-- ^ Second source array.+        -> (sh -> sh' -> sh'')			-- ^ Function to produce the extent of the result.+        -> ((sh -> a) -> (sh' -> b) 		+                      -> (sh'' -> c))		-- ^ Function to produce elements of the result.+						--   It is passed lookup functions to get elements of the +						--   source arrays.+        -> Array sh'' c ++{-# INLINE traverse2 #-}+traverse2 arrA arrB transExtent newElem+	= arrA `deepSeqArray` arrB `deepSeqArray`+   	  Delayed +		(transExtent (extent arrA) (extent arrB)) +		(newElem     ((!:) arrA) ((!:) arrB))++++-- Arbitrary --------------------------------------------------------------------------------------+-- | Create an arbitrary small array, restricting the size of each of the dimensions to some value.+arbitrarySmallArray +	:: (Shape sh, Elt a, Arbitrary sh, Arbitrary a)+	=> Int+	-> Gen (Array (sh :. Int) a)++arbitrarySmallArray maxDim+ = do	sh	<- arbitrarySmallShape maxDim+	xx	<- arbitraryListOfLength (S.size sh)+	return	$ fromList sh xx++++-- Properties -------------------------------------------------------------------------------------++-- | QuickCheck properties for this module and its children.+props_DataArrayRepa :: [(String, Property)]+props_DataArrayRepa+ =  props_DataArrayRepaIndex+ ++ [(stage ++ "." ++ name, test) | (name, test)+    <-	[ ("id_force/DIM5",			property prop_id_force_DIM5)+	, ("id_toScalarUnit",			property prop_id_toScalarUnit)+	, ("id_toListFromList/DIM3",		property prop_id_toListFromList_DIM3) +	, ("id_transpose/DIM4",			property prop_id_transpose_DIM4)+	, ("reshapeTransposeSize/DIM3",		property prop_reshapeTranspose_DIM3)+	, ("appendIsAppend/DIM3",		property prop_appendIsAppend_DIM3)+	, ("sumAllIsSum/DIM3",			property prop_sumAllIsSum_DIM3) ]]+	++-- The Eq instance uses fold and zipWith.+prop_id_force_DIM5+ = 	forAll (arbitrarySmallArray 10)			$ \(arr :: Array DIM5 Int) ->+	arr == force arr+	+prop_id_toScalarUnit (x :: Int)+ =	toScalar (unit x) == x++-- Conversions ------------------------+prop_id_toListFromList_DIM3+ =	forAll (arbitrarySmallShape 10)			$ \(sh :: DIM3) ->+	forAll (arbitraryListOfLength (S.size sh))	$ \(xx :: [Int]) ->+	toList (fromList sh xx) == xx++-- Index Space Transforms -------------+prop_id_transpose_DIM4+ = 	forAll (arbitrarySmallArray 20)			$ \(arr :: Array DIM3 Int) ->+	transpose (transpose arr) == arr++-- A reshaped array has the same size and sum as the original+prop_reshapeTranspose_DIM3+ = 	forAll (arbitrarySmallArray 20)			$ \(arr :: Array DIM3 Int) ->+   let	arr'	= transpose arr+   	sh'	= extent arr'+   in	(S.size $ extent arr) == S.size (extent (reshape arr sh'))+     && (sumAll arr          == sumAll arr')++prop_appendIsAppend_DIM3+ = 	forAll (arbitrarySmallArray 20)			$ \(arr1 :: Array DIM3 Int) ->+	sumAll (append arr1 arr1) == (2 * sumAll arr1)++-- Reductions --------------------------+prop_sumAllIsSum_DIM3+ = 	forAll (arbitrarySmallShape 100)		$ \(sh :: DIM2) ->+	forAll (arbitraryListOfLength (S.size sh))	$ \(xx :: [Int]) -> +	sumAll (fromList sh xx) == P.sum xx
+ Data/Array/Repa/Index.hs view
@@ -0,0 +1,218 @@+{-# LANGUAGE TypeOperators, FlexibleInstances, ScopedTypeVariables #-}++-- | Index types.+module Data.Array.Repa.Index+	( +	-- * Index types+	  Z	(..)+	, (:.)	(..)++	-- * Common dimensions.+	, DIM0+	, DIM1+	, DIM2+	, DIM3+	, DIM4+	, DIM5 +	+	-- * Testing+	, arbitraryShape+	, arbitrarySmallShape+	, props_DataArrayRepaIndex)+where+import Data.Array.Repa.Shape+import Test.QuickCheck+import Control.Monad+import GHC.Base 		(quotInt, remInt)++stage	= "Data.Array.Repa.Index"++-- | An index of dimension zero+data Z	= Z+	deriving (Show, Eq, Ord)++-- | Our index type, used for both shapes and indices.+infixl 3 :.+data tail :. head+	= tail :. head+	deriving (Show, Eq, Ord)++-- Common dimensions+type DIM0	= Z+type DIM1	= DIM0 :. Int+type DIM2	= DIM1 :. Int+type DIM3	= DIM2 :. Int+type DIM4	= DIM3 :. Int+type DIM5	= DIM4 :. Int+++-- Shape ------------------------------------------------------------------------------------------+instance Shape Z where+	dim _			= 0+	zeroDim			= Z+	unitDim			= Z+	intersectDim _ _	= Z++	size _			= 1+	sizeIsValid _		= True++	toIndex _ _		= 0+	fromIndex _ _		= Z++	inRange Z Z Z		= True++	listOfShape _		= []+	shapeOfList []		= Z+	shapeOfList _		= error $ stage ++ ".fromList: non-empty list when converting to Z."++	deepSeq Z x		= x++	+instance Shape sh => Shape (sh :. Int) where+	{-# INLINE dim #-}+	dim   (sh  :. _)+		= dim sh + 1++	{-# INLINE zeroDim #-}+	zeroDim = zeroDim :. 0++	{-# INLINE unitDim #-}+	unitDim = unitDim :. 1++	{-# INLINE intersectDim #-}+	intersectDim (sh1 :. n1) (sh2 :. n2) +		= (intersectDim sh1 sh2 :. (min n1 n2))++	{-# INLINE size #-}+	size  (sh1 :. n)+		= size sh1 * n++	{-# INLINE sizeIsValid #-}+	sizeIsValid (sh1 :. n)+		| size sh1 > 0+		= n <= maxBound `div` size sh1+		+		| otherwise+		= False+		+	{-# INLINE toIndex #-}+	toIndex (sh1 :. sh2) (sh1' :. sh2') +		= toIndex sh1 sh1' * sh2 + sh2'++	{-# INLINE fromIndex #-}+	fromIndex (ds :. d) n +	 	= fromIndex ds (n `quotInt` d) :. r+		where+		-- If we assume that the index is in range, there is no point+		-- in computing the remainder for the highest dimension since+		-- n < d must hold. This saves one remInt per element access which+		-- is quite a big deal.+		r 	| dim ds == 0	= n+			| otherwise	= n `remInt` d++	{-# INLINE inRange #-}+	inRange (zs :. z) (sh1 :. n1) (sh2 :. n2) +		= (n2 >= z) && (n2 < n1) && (inRange zs sh1 sh2)+++       	listOfShape (sh :. n)+	 = n : listOfShape sh++	shapeOfList xx+	 = case xx of+		[]	-> error $ stage ++ ".toList: empty list when converting to  (_ :. Int)"+		x:xs	-> shapeOfList xs :. x			++	{-# INLINE deepSeq #-} +	deepSeq (sh :. n) x = deepSeq sh (n `seq` x)+++++-- Arbitrary --------------------------------------------------------------------------------------+instance Arbitrary Z where+	arbitrary	= return Z++-- | Generate an arbitrary index, which may have 0's for some components.+instance (Shape sh, Arbitrary sh) => Arbitrary (sh :. Int)  where+	arbitrary +	 = do	sh1		<- arbitrary+		let sh1Unit	= if size sh1 == 0 then unitDim else sh1+		+		-- Make sure not to create an index so big that we get+		--	integer overflow when converting it to the linear form.+		n		<- liftM abs $ arbitrary+		let nMax	= maxBound `div` (size sh1Unit)+		let nMaxed	= n `mod` nMax+		+		return	$ sh1 :. nMaxed ++-- | Generate an aribrary shape that does not have 0's for any component.+arbitraryShape +	:: (Shape sh, Arbitrary sh) +	=> Gen (sh :. Int)++arbitraryShape + = do	sh1		<- arbitrary+	let sh1Unit	= if size sh1 == 0 then unitDim else sh1++	-- Make sure not to create an index so big that we get+	--	integer overflow when converting it to the linear form.+	n		<- liftM abs $ arbitrary+	let nMax	= maxBound `div` size sh1Unit+	let nMaxed	= n `mod` nMax+	let nClamped	= if nMaxed == 0 then 1 else nMaxed+	+	return $ sh1Unit :. nClamped+	+	+-- | Generate an arbitrary shape where each dimension is more than zero, +--	but less than a specific value.+arbitrarySmallShape +	:: (Shape sh, Arbitrary sh)+	=> Int+	-> Gen (sh :. Int)++arbitrarySmallShape maxDim+ = do	sh		<- arbitraryShape+	let dims	= listOfShape sh++	let clamp x+		= case x `mod` maxDim of+			0	-> 1+			n	-> n+						+	return	$ if True +			then shapeOfList $ map clamp dims+			else sh+++genInShape2 :: DIM2 -> Gen DIM2+genInShape2 (Z :. yMax :. xMax)+ = do	y	<- liftM (`mod` yMax) $ arbitrary+	x	<- liftM (`mod` xMax) $ arbitrary+	return	$ Z :. y :. x+++-- Properties -------------------------------------------------------------------------------------+-- | QuickCheck properties for this module.+props_DataArrayRepaIndex :: [(String, Property)]+props_DataArrayRepaIndex+  = [(stage ++ "." ++ name, test) | (name, test)+     <-	[ ("toIndexFromIndex/DIM1", 	property prop_toIndexFromIndex_DIM1) +	, ("toIndexFromIndex/DIM2", 	property prop_toIndexFromIndex_DIM2) ]]++prop_toIndexFromIndex_DIM1 sh ix+	=   (sizeIsValid sh)+	==> (inShape sh ix)+	==> fromIndex sh (toIndex sh ix) == ix+	where	_types	= ( sh :: DIM1+			  , ix :: DIM1)++prop_toIndexFromIndex_DIM2+ =	forAll arbitraryShape   $ \(sh :: DIM2) ->+   	forAll (genInShape2 sh) $ \(ix :: DIM2) ->+	fromIndex sh (toIndex sh ix) == ix+++
+ Data/Array/Repa/QuickCheck.hs view
@@ -0,0 +1,21 @@++-- Utils to help with testing. Not exported.+module Data.Array.Repa.QuickCheck+	(arbitraryListOfLength)+where+import Test.QuickCheck+	+	+arbitraryListOfLength +	:: Arbitrary a+	=> Int -> Gen [a]++arbitraryListOfLength n+	| n == 0		= return []+	| otherwise+	= do	i	<- arbitrary+		rest	<- arbitraryListOfLength (n - 1)+		return	$ i : rest+	+	+	
+ Data/Array/Repa/Shape.hs view
@@ -0,0 +1,71 @@+{-# LANGUAGE RankNTypes #-}++-- | Class of types that can be used as array shapes and indices.+module Data.Array.Repa.Shape+	( Shape(..)+	, inShape )+where+	+-- Shape ------------------------------------------------------------------------------------------	+-- | Class of types that can be used as array shapes and indices.+class Eq sh => Shape sh where++	-- | Get the number of dimensions in a shape.+	dim	:: sh -> Int           ++	-- | The shape of an array of size zero, with a particular dimensionality.+	zeroDim	:: sh++	-- | The shape of an array with size one, with a particular dimensionality.+	unitDim :: sh++	-- | Compute the intersection of two shapes.+	intersectDim :: sh -> sh -> sh+++	-- | Get the total number of elements in an array with this shape.+	size	:: sh -> Int           ++	-- | Check whether this shape is small enough so that its flat+	--	indices an be represented as `Int`. If this returns `False` then your+	--	array is too big. Mostly used for writing QuickCheck tests.+	sizeIsValid :: sh -> Bool+++	-- | Convert an index into its equivalent flat, linear, row-major version.+	toIndex :: sh	-- ^ Shape of the array.+		-> sh 	-- ^ Index into the array.+		-> Int     ++	-- | Inverse of `toIndex`.+	fromIndex +		:: sh 	-- ^ Shape of the array.+		-> Int 	-- ^ Index into linear representation.+		-> sh   ++	-- | Check whether an index is within a given shape.+	inRange	:: sh 	-- ^ Start index for range.+		-> sh 	-- ^ Final index for range.+		-> sh 	-- ^ Index to check for.+		-> Bool++	-- | Convert a shape into its list of dimensions.+	listOfShape	:: sh -> [Int]+	+	-- | Convert a list of dimensions to a shape+	shapeOfList	:: [Int] -> sh++	-- | Ensure that a shape is completely evaluated.+	infixr 0 `deepSeq`+	deepSeq :: sh -> a -> a+++-- | Check whether an index is a part of a given shape.+inShape :: forall sh+	.  Shape sh +	=> sh 		-- ^ Shape of the array.+	-> sh		-- ^ Index.+	-> Bool++inShape sh ix+	= inRange zeroDim sh ix
+ Data/Array/Repa/Slice.hs view
@@ -0,0 +1,77 @@+{-# LANGUAGE TypeFamilies, TypeOperators, FlexibleInstances #-}+++-- | Index space transformation between arrays and slices.+module Data.Array.Repa.Slice+	( All		(..)+	, Any		(..)+	, FullShape+	, SliceShape+	, Slice		(..))+where+import Data.Array.Repa.Index+import Prelude					hiding (replicate, drop)+++-- | Select all indices at a certain position.+data All 	= All+++-- | Place holder for any possible shape.+data Any sh	= Any+++-- | Map a type of the index in the full shape, to the type of the index in the slice.+type family FullShape ss+type instance FullShape Z		= Z+type instance FullShape (Any sh)	= sh+type instance FullShape (sl :. Int)	= FullShape sl :. Int+type instance FullShape (sl :. All)	= FullShape sl :. Int+++-- | Map the type of an index in the slice, to the type of the index in the full shape.+type family SliceShape ss+type instance SliceShape Z		= Z+type instance SliceShape (Any sh)	= sh+type instance SliceShape (sl :. Int)	= SliceShape sl+type instance SliceShape (sl :. All)	= SliceShape sl :. Int+++-- | Class of index types that can map to slices.+class Slice ss where+	-- | Map an index of a full shape onto an index of some slice.+	sliceOfFull	:: ss -> FullShape ss  -> SliceShape ss++	-- | Map an index of a slice onto an index of the full shape.+	fullOfSlice	:: ss -> SliceShape ss -> FullShape  ss+		++instance Slice Z  where+	sliceOfFull _ _		= Z+	fullOfSlice _ _		= Z+	+	+instance Slice (Any sh) where+	sliceOfFull _ sh	= sh+	fullOfSlice _ sh	= sh+	++instance Slice sl => Slice (sl :. Int) where+	sliceOfFull (fsl :. _) (ssl :. _)	+		= sliceOfFull fsl ssl++	fullOfSlice (fsl :. n) ssl		+		= fullOfSlice fsl ssl :. n+	+	+instance Slice sl => Slice (sl :. All) where	+	sliceOfFull (fsl :. All) (ssl :. s)+		= sliceOfFull fsl ssl :. s++	fullOfSlice (fsl :. All) (ssl :. s)+		= fullOfSlice fsl ssl :. s+	+	++	+	
+ LICENSE view
@@ -0,0 +1,13 @@+Copyright (c) 2010 The DPH Team++ Permission is hereby granted, free of charge, to any person+ obtaining a copy of this software and associated documentation+ files (the "Software"), to deal in the Software without+ restriction, including without limitation the rights to use,+ copy, modify, merge, publish, distribute, sublicense, and/or sell+ copies of the Software, and to permit persons to whom the+ Software is furnished to do so, subject to the following+ condition:++ The above copyright notice and this permission notice shall be+ included in all copies or substantial portions of the Software.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ repa.cabal view
@@ -0,0 +1,43 @@+Name:                repa+Version:             1.0.0.0+License:             MIT+License-file:        LICENSE+Author:              The DPH Team+Maintainer:          Ben Lippmeier <benl@ouroborus.net>+Build-Type:          Simple+Cabal-Version:       >=1.6+Stability:           experimental+Category:            Data Structures+Homepage:            http://trac.haskell.org/repa+Bug-reports:         http://trac.haskell.org/repa/newticket+Description:+        NOTE: You must use the GHC head branch > 6.13.20100309 to get decent performance.+        Repa provides high performance, regular, multi-dimensional, shape polymorphic parallel arrays.+        All numeric data is stored unboxed. Functions written with the Repa combinators+        are automatically parallel provided you supply +RTS -Nwhatever on the command+        line when running the program.++Synopsis:+        High performance, regular, shape polymorphic parallel arrays.++Tested-with: GHC == 6.13.20100309, GHC == 6.12.1++Library+  Build-Depends: +        base                 >= 4       && < 5,+        dph-prim-par         >= 0.4.0   && < 0.5.0,+        dph-prim-seq         >= 0.4.0   && < 0.5.0,+        QuickCheck           >= 2.1.0.3 && < 2.2.0.0++  ghc-options:+        -Odph -Wall -fno-warn-missing-signatures++  Exposed-modules:+        Data.Array.Repa+        Data.Array.Repa.Index+        Data.Array.Repa.Shape+        Data.Array.Repa.Slice++  Other-modules:+        Data.Array.Repa.QuickCheck+