dph-lifted-vseg (empty) → 0.6.0.1
raw patch · 37 files changed
+7671/−0 lines, 37 filesdep +arraydep +basedep +containerssetup-changed
Dependencies added: array, base, containers, dph-base, dph-lifted-base, dph-prim-par, ghc, pretty, random, template-haskell, vector
Files
- Data/Array/Parallel.hs +227/−0
- Data/Array/Parallel/Lifted.hs +15/−0
- Data/Array/Parallel/Lifted/Closure.hs +460/−0
- Data/Array/Parallel/Lifted/Combinators.hs +232/−0
- Data/Array/Parallel/PArray.hs +547/−0
- Data/Array/Parallel/PArray/PData.hs +53/−0
- Data/Array/Parallel/PArray/PData/Base.hs +273/−0
- Data/Array/Parallel/PArray/PData/Double.hs +167/−0
- Data/Array/Parallel/PArray/PData/Int.hs +159/−0
- Data/Array/Parallel/PArray/PData/Nested.hs +718/−0
- Data/Array/Parallel/PArray/PData/Sum2.hs +516/−0
- Data/Array/Parallel/PArray/PData/Tuple2.hs +251/−0
- Data/Array/Parallel/PArray/PData/Tuple3.hs +242/−0
- Data/Array/Parallel/PArray/PData/Tuple4.hs +279/−0
- Data/Array/Parallel/PArray/PData/Tuple5.hs +304/−0
- Data/Array/Parallel/PArray/PData/Unit.hs +164/−0
- Data/Array/Parallel/PArray/PData/Void.hs +166/−0
- Data/Array/Parallel/PArray/PData/Word8.hs +168/−0
- Data/Array/Parallel/PArray/PData/Wrap.hs +150/−0
- Data/Array/Parallel/PArray/PRepr.hs +57/−0
- Data/Array/Parallel/PArray/PRepr/Base.hs +312/−0
- Data/Array/Parallel/PArray/PRepr/Instances.hs +203/−0
- Data/Array/Parallel/PArray/PRepr/Nested.hs +106/−0
- Data/Array/Parallel/PArray/PRepr/Tuple.hs +156/−0
- Data/Array/Parallel/PArray/Scalar.hs +313/−0
- Data/Array/Parallel/Prelude.hs +17/−0
- Data/Array/Parallel/Prelude/Base.hs +46/−0
- Data/Array/Parallel/Prelude/Bool.hs +135/−0
- Data/Array/Parallel/Prelude/Double.hs +256/−0
- Data/Array/Parallel/Prelude/Int.hs +197/−0
- Data/Array/Parallel/Prelude/Ordering.hs +55/−0
- Data/Array/Parallel/Prelude/Tuple.hs +32/−0
- Data/Array/Parallel/Prelude/Word8.hs +195/−0
- Data/Array/Parallel/Prim.hs +358/−0
- LICENSE +36/−0
- Setup.hs +3/−0
- dph-lifted-vseg.cabal +103/−0
+ Data/Array/Parallel.hs view
@@ -0,0 +1,227 @@+{-# LANGUAGE ParallelArrays #-}+{-# OPTIONS_GHC -fvectorise #-}++-- | User level interface to vectorised parallel arrays.+--+-- /WARNING:/ In the current implementation, the functionality provided in+-- this module is tied to the vectoriser pass of GHC, invoked by `-fvectorise`.+-- These functions will not work at all in unvectorised code. To operate on+-- parallel arrays in unvectorised code, use the functions in+-- "Data.Array.Parallel.PArray" and convert between array representations by+-- using `fromPArrayP` and `toPArrayP` from /vectorised/ code.+---+-- The semantic difference between standard Haskell arrays (aka "lazy+-- arrays") and parallel arrays (aka "strict arrays") is that the evaluation+-- of two different elements of a lazy array is independent, whereas in a+-- strict array either non or all elements are evaluated.+-- In other words, when a parallel array is evaluated to WHNF, all its elements+-- will be evaluated to WHNF. The name parallel array indicates that all array+-- elements may, in general, be evaluated to WHNF in parallel without any+-- need to resort to speculative evaluation. This parallel evaluation+-- semantics is also beneficial in the sequential case, as it facilitates+-- loop-based array processing as known from classic array-based languages,+-- such as Fortran.+--+-- The interface of this module is essentially a variant of the list+-- component of the Prelude, but also includes some functions (such as+-- permutations) that are not provided for lists. The following list of+-- operations are not supported on parallel arrays, as they would require the+-- infinite parallel arrays: `iterate', `repeat', and `cycle'.+--+-- UGLY HACK ALERT: +-- Same ugly hack as in 'base:GHC.PArr'! We could do without in this module by+-- using the type synonym 'PArr' instead of '[::]', but that would lead to+-- significantly worse error message for end users.+--+module Data.Array.Parallel + ( module Data.Array.Parallel.Prelude++ -- * Conversions+ , PArray+ , fromPArrayP+ , toPArrayP+ , fromNestedPArrayP+ + -- * Constructors+ , emptyP+ , singletonP+ , replicateP+ , appendP, (+:+)+ , concatP+ + -- * Projections+ , lengthP+ , indexP, (!:)+ , sliceP+ + -- * Traversals+ , mapP+ , zipWithP+ , crossMapP++ -- * Filtering+ , filterP+ + -- * Ziping and Unzipping+ , zipP+ , unzipP)+where+-- Primitives needed by the vectoriser.+import Data.Array.Parallel.Prim () ++import Data.Array.Parallel.PArr+import Data.Array.Parallel.Prelude+import Data.Array.Parallel.Lifted+import Data.Array.Parallel.PArray.PData.Base (PArray(..))+++-------------------------------------------------------------------------------+-- IMPORTANT:+-- We only define the signatures of operations on parallel arrays, and give+-- and bodies that convince GHC that these functions don't just diverge.+-- The vectoriser rewrites them to entirely the code given in the VECTORISE+-- pragmas.+--+-- The functions must be eta-expanded, so the right of the binding is+-- something of the final return type. The vectoriser takes the type of the+-- body to determine what PA dictionary to pass.+--+-- We also put bangs (!) on the arguments to indicate to the GHC strictness+-- analyser that these paramters will really be used in the vectorised code.+--+-- This won't work: mapP = undefined+-- You need this: mapP !_ !_ = [::]+--+-- The bindings have NOINLINE pragmas because we never want to use the+-- actual body code (because it's fake anyway).+--++-- Conversions ----------------------------------------------------------------+-- | O(1). Convert between `PArray` and [::] array representations.+fromPArrayP :: PArray a -> [:a:]+fromPArrayP !_ = emptyP+{-# NOINLINE fromPArrayP #-}+{-# VECTORISE fromPArrayP = fromPArrayPP #-}+++-- | O(1). Convert between `PArray` and [::] array representations.+toPArrayP :: [:a:] -> PArray a+toPArrayP !_ = PArray 0# (error "toPArrayP: unvectorised")+{-# NOINLINE toPArrayP #-}+{-# VECTORISE toPArrayP = toPArrayPP #-}+++-- | O(1). Convert between `PArray` and [::] array representations.+fromNestedPArrayP :: PArray (PArray a) -> [:[:a:]:]+fromNestedPArrayP !_ = emptyP+{-# NOINLINE fromNestedPArrayP #-}+{-# VECTORISE fromNestedPArrayP = fromNestedPArrayPP #-}+++-- Constructors ---------------------------------------------------------------+-- | Construct an empty array, with no elements.+emptyP :: [:a:]+emptyP = emptyPArr+{-# NOINLINE emptyP #-}+{-# VECTORISE emptyP = emptyPP #-}+++-- | Construct an array with a single element.+singletonP :: a -> [:a:]+singletonP = singletonPArr+{-# NOINLINE singletonP #-}+{-# VECTORISE singletonP = singletonPP #-}+++-- | Construct an array by replicating the given element some number of times.+replicateP :: Int -> a -> [:a:]+replicateP = replicatePArr+{-# NOINLINE replicateP #-}+{-# VECTORISE replicateP = replicatePP #-}+++-- | Append two arrays.+appendP, (+:+) :: [:a:] -> [:a:] -> [:a:]+(+:+) !_ !_ = emptyP+{-# NOINLINE (+:+) #-}+{-# VECTORISE (+:+) = appendPP #-}++appendP !_ !_ = emptyP+{-# NOINLINE appendP #-}+{-# VECTORISE appendP = appendPP #-}+++-- | Concatenate an array of arrays.+concatP :: [:[:a:]:] -> [:a:]+concatP !_ = emptyP+{-# NOINLINE concatP #-}+{-# VECTORISE concatP = concatPP #-}+++-- Projections ----------------------------------------------------------------+-- | Take the length of an array.+lengthP :: [:a:] -> Int+lengthP = lengthPArr+{-# NOINLINE lengthP #-}+{-# VECTORISE lengthP = lengthPP #-}++-- | Lookup a single element from the source array.+indexP, (!:) :: [:a:] -> Int -> a+(!:) = indexPArr+{-# NOINLINE (!:) #-}+{-# VECTORISE (!:) = indexPP #-}++indexP = indexPArr+{-# NOINLINE indexP #-}+{-# VECTORISE indexP = indexPP #-}+++-- | Extract a slice from an array.+sliceP :: Int -> Int -> [:a:] -> [:a:]+sliceP !_ !_ !_ = emptyP+{-# NOINLINE sliceP #-}+{-# VECTORISE sliceP = slicePP #-}+++-- Traversals -----------------------------------------------------------------+-- | Apply a worker function to every element of an array.+mapP :: (a -> b) -> [:a:] -> [:b:]+mapP !_ !_ = emptyP+{-# NOINLINE mapP #-}+{-# VECTORISE mapP = mapPP #-}++-- | Apply a worker function to every pair of two arrays.+zipWithP :: (a -> b -> c) -> [:a:] -> [:b:] -> [:c:]+zipWithP !_ !_ !_ = emptyP+{-# NOINLINE zipWithP #-}+{-# VECTORISE zipWithP = zipWithPP #-}++-- | For every element 'a' apply the function to get an array of 'b' then,+-- and return an array of all the 'a's and 'b's.+crossMapP :: [:a:] -> (a -> [:b:]) -> [:(a, b):]+{-# NOINLINE crossMapP #-}+crossMapP !_ !_ = emptyP+{-# VECTORISE crossMapP = crossMapPP #-}+++-- Filtering -----------------------------------------------------------------+-- | Filter an array, keeping only those elements that match the given predicate.+filterP :: (a -> Bool) -> [:a:] -> [:a:]+filterP !_ !_ = emptyP+{-# NOINLINE filterP #-}+{-# VECTORISE filterP = filterPP #-}+++-- Zipping and Unzipping ------------------------------------------------------+-- | Zip a pair of arrays into an array of pairs.+zipP :: [:a:] -> [:b:] -> [:(a, b):]+zipP !_ !_ = emptyP+{-# NOINLINE zipP #-}+{-# VECTORISE zipP = zipPP #-}+++-- | Unzip an array of pairs into a pair of arrays.+unzipP :: [:(a, b):] -> ([:a:], [:b:])+unzipP !_ = (emptyP, emptyP)+{-# NOINLINE unzipP #-}+{-# VECTORISE unzipP = unzipPP #-}
+ Data/Array/Parallel/Lifted.hs view
@@ -0,0 +1,15 @@++-- | Closures and closure converted lifted array combinators.+module Data.Array.Parallel.Lifted + ( module Data.Array.Parallel.Lifted.Closure+ , module Data.Array.Parallel.Lifted.Combinators)+where+import Data.Array.Parallel.Lifted.Closure+import Data.Array.Parallel.Lifted.Combinators++++ + + +
+ Data/Array/Parallel/Lifted/Closure.hs view
@@ -0,0 +1,460 @@+{-# LANGUAGE CPP #-}+#include "fusion-phases.h"++-- | Closures.+-- Used when closure converting the source program during vectorisation.+module Data.Array.Parallel.Lifted.Closure + ( -- * Closures.+ (:->)(..)+ , ($:)++ -- * Array Closures.+ , PData(..)+ , ($:^), liftedApply++ -- * Closure Construction.+ , closure1, closure2, closure3, closure4, closure5+ , closure1', closure2', closure3', closure4', closure5')+where+import Data.Array.Parallel.Pretty+import Data.Array.Parallel.PArray.PData.Base+import Data.Array.Parallel.PArray.PData.Unit+import Data.Array.Parallel.PArray.PData.Tuple2+import Data.Array.Parallel.PArray.PData.Tuple3+import Data.Array.Parallel.PArray.PData.Tuple4+import Data.Array.Parallel.PArray.PRepr+import qualified Data.Vector as V+import GHC.Exts+++-- Closures -------------------------------------------------------------------+-- | Define the fixity of the closure type constructor.+infixr 0 :->+infixl 1 $:, $:^++-- | The type of closures.+-- This bundles up:+--- 1) the 'vectorised' version of the function that takes an explicit environment+-- 2) the 'lifted' version, that works on arrays.+-- The first parameter of the lifted version is the 'lifting context'+-- that gives the length of the arrays being operated on.+-- 3) the environment of the closure.+-- +-- The vectoriser closure-converts the source program so that all functions+-- are expressed in this form.+data (a :-> b)+ = forall env. PA env+ => Clo (env -> a -> b)+ (Int -> PData env -> PData a -> PData b)+ env++-- | Closure application.+($:) :: (a :-> b) -> a -> b+($:) (Clo fv _fl env) x = fv env x+{-# INLINE_CLOSURE ($:) #-}+++-- Array Closures -------------------------------------------------------------+-- | Arrays of closures (aka array closures)+-- We need to represent arrays of closures when vectorising partial applications.+--+-- For example, consider:+-- @mapP (+) xs :: [: Int -> Int :]@+--+-- Representing this an array of thunks doesn't work because we can't evaluate+-- it in a data parallel manner. Instead, we want *one* function applied to many+-- array elements.+-- +-- Instead, such an array of closures is represented as the vectorised and+-- lifted versions of (+), along with an environment array xs that contains the+-- partially applied arguments.+--+-- @mapP (+) xs ==> AClo plus_v plus_l xs@+--+data instance PData (a :-> b)+ = forall env. PA env+ => AClo (env -> a -> b)+ (Int -> PData env -> PData a -> PData b)+ (PData env)++data instance PDatas (a :-> b)+ = forall env. PA env+ => AClos (env -> a -> b)+ (Int -> PData env -> PData a -> PData b)+ (PDatas env)+++-- | Lifted closure application.+($:^) :: PArray (a :-> b) -> PArray a -> PArray b+PArray n# (AClo _ f es) $:^ PArray _ as + = PArray n# (f (I# n#) es as)+{-# INLINE ($:^) #-}+++-- | Lifted closure application, taking an explicit lifting context.+liftedApply :: Int -> PData (a :-> b) -> PData a -> PData b+liftedApply n (AClo _ fl envs) as+ = fl n envs as+{-# INLINE_CLOSURE liftedApply #-}+++-- Closure Construction -------------------------------------------------------+-- These functions are used for building closure representations of primitive+-- functions. They're used in D.A.P.Lifted.Combinators where we define the +-- closure converted lifted array combinators that vectorised code uses.++-- | Construct an arity-1 closure,+-- from unlifted and lifted versions of a primitive function.+closure1 + :: (a -> b)+ -> (Int -> PData a -> PData b)+ -> (a :-> b)++closure1 fv fl + = Clo (\_env -> fv)+ (\n _env -> fl n)+ ()+{-# INLINE_CLOSURE closure1 #-}+++-- | Construct an arity-2 closure,+-- from lifted and unlifted versions of a primitive function.+closure2 + :: forall a b c. PA a+ => (a -> b -> c)+ -> (Int -> PData a -> PData b -> PData c)+ -> (a :-> b :-> c)++closure2 fv fl+ = let fv_1 _ xa = Clo fv fl xa+ fl_1 _ _ xs = AClo fv fl xs+ + in Clo fv_1 fl_1 ()+{-# INLINE_CLOSURE closure2 #-}+++-- | Construct an arity-3 closure+-- from lifted and unlifted versions of a primitive function.+closure3 + :: forall a b c d. (PA a, PA b)+ => (a -> b -> c -> d)+ -> (Int -> PData a -> PData b -> PData c -> PData d)+ -> (a :-> b :-> c :-> d)+ +closure3 fv fl+ = let fv_1 _ xa = Clo fv_2 fl_2 xa+ fl_1 _ _ xs = AClo fv_2 fl_2 xs++ -----+ fv_2 xa yb = Clo fv_3 fl_3 (xa, yb)+ fl_2 _ xs ys = AClo fv_3 fl_3 (PTuple2 xs ys)++ -----+ fv_3 (xa, yb) zc = fv xa yb zc+ fl_3 n (PTuple2 xs ys) zs = fl n xs ys zs++ in Clo fv_1 fl_1 ()+{-# INLINE_CLOSURE closure3 #-}+++-- | Construct an arity-4 closure+-- from lifted and unlifted versions of a primitive function.+closure4 + :: forall a b c d e. (PA a, PA b, PA c)+ => (a -> b -> c -> d -> e)+ -> (Int -> PData a -> PData b -> PData c -> PData d -> PData e)+ -> (a :-> b :-> c :-> d :-> e)+ +closure4 fv fl+ = let fv_1 _ xa = Clo fv_2 fl_2 xa+ fl_1 _ _ xs = AClo fv_2 fl_2 xs++ fv_2 xa yb = Clo fv_3 fl_3 (xa, yb)+ fl_2 _ xs ys = AClo fv_3 fl_3 (PTuple2 xs ys)++ fv_3 (xa, yb) zc = Clo fv_4 fl_4 (xa, yb, zc)+ fl_3 _ (PTuple2 xs ys) zs = AClo fv_4 fl_4 (PTuple3 xs ys zs)++ fv_4 (xa, yb, zc) ad = fv xa yb zc ad+ fl_4 n (PTuple3 xs ys zs) as = fl n xs ys zs as++ in Clo fv_1 fl_1 ()+{-# INLINE_CLOSURE closure4 #-}+++-- | Construct an arity-5 closure+-- from lifted and unlifted versions of a primitive function.+closure5+ :: forall a b c d e f. (PA a, PA b, PA c, PA d)+ => (a -> b -> c -> d -> e -> f)+ -> (Int -> PData a -> PData b -> PData c -> PData d -> PData e -> PData f)+ -> (a :-> b :-> c :-> d :-> e :-> f)+ +closure5 fv fl+ = let fv_1 _ xa = Clo fv_2 fl_2 xa+ fl_1 _ _ xs = AClo fv_2 fl_2 xs++ fv_2 xa yb = Clo fv_3 fl_3 (xa, yb)+ fl_2 _ xs ys = AClo fv_3 fl_3 (PTuple2 xs ys)++ fv_3 (xa, yb) zc = Clo fv_4 fl_4 (xa, yb, zc)+ fl_3 _ (PTuple2 xs ys) zs = AClo fv_4 fl_4 (PTuple3 xs ys zs)++ fv_4 (xa, yb, zc) ad = Clo fv_5 fl_5 (xa, yb, zc, ad)+ fl_4 _ (PTuple3 xs ys zs) as = AClo fv_5 fl_5 (PTuple4 xs ys zs as)++ fv_5 (xa, yb, zc, ad) be = fv xa yb zc ad be+ fl_5 n (PTuple4 xs ys zs as) bs = fl n xs ys zs as bs++ in Clo fv_1 fl_1 ()+{-# INLINE_CLOSURE closure5 #-}+++-- Closure constructors that take PArrays -------------------------------------+-- These versions are useful when defining prelude functions such as in +-- D.A.P.Prelude.Int. They let us promote functions that work on PArrays +-- to closures, while inferring the lifting context from the first argument.++-- | Construct an arity-1 closure.+closure1'+ :: forall a b+ . (a -> b)+ -> (PArray a -> PArray b)+ -> (a :-> b)++closure1' fv fl + = let {-# INLINE fl' #-}+ fl' (I# n#) pdata+ = case fl (PArray n# pdata) of+ PArray _ pdata' -> pdata'+ in closure1 fv fl'+{-# INLINE_CLOSURE closure1' #-}+++-- | Construct an arity-2 closure.+closure2'+ :: forall a b c. PA a+ => (a -> b -> c)+ -> (PArray a -> PArray b -> PArray c)+ -> (a :-> b :-> c)++closure2' fv fl + = let {-# INLINE fl' #-}+ fl' (I# n#) !pdata1 !pdata2+ = case fl (PArray n# pdata1) (PArray n# pdata2) of+ PArray _ pdata' -> pdata'+ in closure2 fv fl'+{-# INLINE_CLOSURE closure2' #-}+++-- | Construct an arity-3 closure.+closure3'+ :: forall a b c d. (PA a, PA b) + => (a -> b -> c -> d)+ -> (PArray a -> PArray b -> PArray c -> PArray d)+ -> (a :-> b :-> c :-> d) ++closure3' fv fl + = let {-# INLINE fl' #-}+ fl' (I# n#) !pdata1 !pdata2 !pdata3+ = case fl (PArray n# pdata1) (PArray n# pdata2) (PArray n# pdata3) of+ PArray _ pdata' -> pdata'+ in closure3 fv fl'+{-# INLINE_CLOSURE closure3' #-}+++-- | Construct an arity-4 closure.+closure4'+ :: forall a b c d e. (PA a, PA b, PA c) + => (a -> b -> c -> d -> e)+ -> (PArray a -> PArray b -> PArray c -> PArray d -> PArray e)+ -> (a :-> b :-> c :-> d :-> e) ++closure4' fv fl + = let {-# INLINE fl' #-}+ fl' (I# n#) !pdata1 !pdata2 !pdata3 !pdata4+ = case fl (PArray n# pdata1) (PArray n# pdata2) + (PArray n# pdata3) (PArray n# pdata4) of+ PArray _ pdata' -> pdata'+ in closure4 fv fl'+{-# INLINE_CLOSURE closure4' #-}+++-- | Construct an arity-5 closure.+closure5'+ :: forall a b c d e f. (PA a, PA b, PA c, PA d) + => (a -> b -> c -> d -> e -> f)+ -> (PArray a -> PArray b -> PArray c -> PArray d -> PArray e -> PArray f)+ -> (a :-> b :-> c :-> d :-> e :-> f) ++closure5' fv fl + = let {-# INLINE fl' #-}+ fl' (I# n#) !pdata1 !pdata2 !pdata3 !pdata4 !pdata5+ = case fl (PArray n# pdata1) (PArray n# pdata2) + (PArray n# pdata3) (PArray n# pdata4) + (PArray n# pdata5) of+ PArray _ pdata' -> pdata'+ in closure5 fv fl'+{-# INLINE_CLOSURE closure5' #-}+++-- PData instance for closures ------------------------------------------------+-- This needs to be here instead of in a module D.A.P.PArray.PData.Closure+-- to break an import loop.+-- We use INLINE_CLOSURE for these bindings instead of INLINE_PDATA because+-- most of the functions return closure constructors, and we want to eliminate+-- these early in the compilation.+--+instance PR (a :-> b) where++ {-# NOINLINE validPR #-}+ validPR (AClo _ _ env)+ = validPA env++ {-# NOINLINE nfPR #-}+ nfPR (AClo fv fl envs)+ = fv `seq` fl `seq` nfPA envs `seq` ()++ -- We can't test functions for equality.+ -- We can't test the environments either, because they're existentially quantified.+ -- Provided the closures have the same type, we just call them similar.+ {-# NOINLINE similarPR #-}+ similarPR _ _+ = True++ {-# NOINLINE coversPR #-}+ coversPR weak (AClo _ _ envs) ix+ = coversPA weak envs ix++ {-# NOINLINE pprpPR #-}+ pprpPR (Clo _ _ env)+ = vcat+ [ text "Clo"+ , pprpPA env ]++ {-# NOINLINE pprpDataPR #-}+ pprpDataPR (AClo _ _ envs)+ = vcat+ [ text "AClo"+ , pprpDataPA envs ]+++ -- Constructors -------------------------------+ {-# INLINE_CLOSURE emptyPR #-}+ emptyPR+ = let die = error "emptydPR[:->]: no function in empty closure array"+ in AClo die die (emptyPA :: PData ())++ {-# INLINE_CLOSURE replicatePR #-}+ replicatePR n (Clo fv fl envs)+ = AClo fv fl (replicatePA n envs)++ {-# INLINE_CLOSURE replicatesPR #-}+ replicatesPR lens (AClo fv fl envs)+ = AClo fv fl (replicatesPA lens envs)+++ -- Projections --------------------------------+ {-# INLINE_CLOSURE lengthPR #-}+ lengthPR (AClo _ _ envs)+ = lengthPA envs++ {-# INLINE_CLOSURE indexPR #-}+ indexPR (AClo fv fl envs) ix+ = Clo fv fl $ indexPA envs ix++ {-# INLINE_CLOSURE indexsPR #-}+ indexsPR (AClos fv fl envs) srcixs+ = AClo fv fl $ indexsPA envs srcixs++ {-# INLINE_CLOSURE extractPR #-}+ extractPR (AClo fv fl envs) start len+ = AClo fv fl $ extractPA envs start len++ {-# INLINE_CLOSURE extractssPR #-}+ extractssPR (AClos fv fl envs) ssegd+ = AClo fv fl $ extractssPA envs ssegd++ {-# INLINE_CLOSURE extractvsPR #-}+ extractvsPR (AClos fv fl envs) vsegd+ = AClo fv fl $ extractvsPA envs vsegd+++ -- Pack and Combine ---------------------------+ {-# INLINE_CLOSURE packByTagPR #-}+ packByTagPR (AClo fv fl envs) tags tag+ = AClo fv fl $ packByTagPA envs tags tag+++ -- Conversions --------------------------------+ {-# NOINLINE toVectorPR #-}+ toVectorPR (AClo fv fl envs)+ = V.map (Clo fv fl) $ toVectorPA envs+++ -- PDatas -------------------------------------+ -- When constructing an empty array of closures, we don't know what + {-# INLINE_CLOSURE emptydPR #-}+ emptydPR + = let die = error "emptydPR[:->]: no function in empty closure array"+ in AClos die die (emptydPA :: PDatas ())++ {-# INLINE_CLOSURE singletondPR #-}+ singletondPR (AClo fv fl env)+ = AClos fv fl $ singletondPA env+ + {-# INLINE_CLOSURE lengthdPR #-}+ lengthdPR (AClos _ _ env)+ = lengthdPA env+ + {-# INLINE_CLOSURE indexdPR #-}+ indexdPR (AClos fv fl envs) ix+ = AClo fv fl $ indexdPA envs ix++ {-# NOINLINE toVectordPR #-}+ toVectordPR (AClos fv fl envs)+ = V.map (AClo fv fl) $ toVectordPA envs+++ -- Unsupported --------------------------------+ -- To support these operators we'd need to manage closure arrays containing+ -- multiple hetrogenous functions. But this is more work than we care for+ -- right now. Note that the problematic functions are all constructors, and+ -- we can't know that all the parameters contain the same function.+ appendPR = dieHetroFunctions "appendPR"+ appendsPR = dieHetroFunctions "appendsPR"+ combine2PR = dieHetroFunctions "combine2PR"+ fromVectorPR = dieHetroFunctions "fromVectorPR"+ appenddPR = dieHetroFunctions "appenddPR"+ fromVectordPR = dieHetroFunctions "fromVectordPR"+++dieHetroFunctions :: String -> a+dieHetroFunctions name+ = error $ unlines+ [ "Data.Array.Parallel.Lifted.Closure." ++ name+ , " Unsupported Array Operation"+ , " It looks like you're trying to define an array containing multiple"+ , " hetrogenous functions, or trying to select between multiple arrays"+ , " of functions in vectorised code. Although we could support this by"+ , " constructing a new function that selects between them depending on"+ , " what the array index is, to make that anywhere near efficient is"+ , " more work than we care to do right now, and we expect this use case"+ , " to be uncommon. If you want this to work then contact the DPH team"+ , " and ask what you can do to help." ]+++-- PRepr Instance -------------------------------------------------------------+-- This needs to be here instead of in D.A.P.PRepr.Instances +-- to break an import loop.+--+type instance PRepr (a :-> b) + = a :-> b++instance (PA a, PA b) => PA (a :-> b) where+ toPRepr = id+ fromPRepr = id+ toArrPRepr = id+ fromArrPRepr = id+ toArrPReprs = id+ fromArrPReprs = id
+ Data/Array/Parallel/Lifted/Combinators.hs view
@@ -0,0 +1,232 @@+{-# LANGUAGE CPP #-}+{-# OPTIONS -fno-spec-constr #-}+#include "fusion-phases.h"++-- NOTE NOTE NOTE+-- This file is IDENTICAL to the one in dph-lifted-boxed.+-- If you update one then update the other as well.++-- | Closure converted lifted array combinators.+-- The vectoriser produces code that uses these combinators directly.+-- +-- All of the combinators in this module are polymorphic, work on `PArray`, and+-- take `PA` dictionaries. Combinators that are specific to a certain element type,+-- like `Int`, are defined in the corresponding prelude module, +-- eg "Data.Array.Parallel.Prelude.Int".+--+module Data.Array.Parallel.Lifted.Combinators + ( -- * Conversions+ fromPArrayPP+ , toPArrayPP+ , fromNestedPArrayPP+ + -- * Constructors+ , emptyPP+ , singletonPP+ , replicatePP+ , appendPP++ -- * Projections+ , lengthPP+ , indexPP+ , slicePP++ -- * Traversals+ , mapPP+ , zipWithPP+ , crossMapPP++ -- * Filtering+ , filterPP++ -- * Concatenation+ , concatPP++ -- * Tuple functions+ , zipPP+ , unzipPP)+where+import Data.Array.Parallel.Lifted.Closure+import Data.Array.Parallel.PArray.PData as PA+import Data.Array.Parallel.PArray.PRepr as PA+import Data.Array.Parallel.PArray as PA+++-- Conversions ================================================================+-- The following identity functions are used as the vectorised versions of the+-- functions that convert between the source level array type [:a:] and the +-- PArray type which is used in the library. ++-- | Identity function, used as the vectorised version of fromPArrayP.+fromPArrayPP :: PA a => PArray a :-> PArray a+fromPArrayPP = closure1 (\x -> x) (\_ xs -> xs)+{-# INLINE fromPArrayPP #-}+++-- | Identity function, used as the vectorised version of toPArrayP.+toPArrayPP :: PA a => PArray a :-> PArray a+toPArrayPP = closure1 (\x -> x) (\_ xs -> xs)+{-# INLINE toPArrayPP #-}+++-- | Identity function, used as the vectorised version of fromNestedPArrayP+fromNestedPArrayPP :: PA a => (PArray (PArray a) :-> PArray (PArray a))+fromNestedPArrayPP = closure1 (\xs -> xs) (\_ xss -> xss)+{-# INLINE fromNestedPArrayPP #-}+++-- Combinators ================================================================+-- For each combinator:+-- The *PP_v version is the "vectorised" version that has had its parameters+-- closure converted. For first-order functions, the *PP_v version is+-- identical to the standard *PA version from D.A.P.PArray, so we can +-- just use that directly.+--+-- The *PP_l version is the "lifted" version that works on arrays of arrays.+-- Each of these functions also takes an integer as its first argument. +-- This is the "lifting context" that says now many element to expect in +-- each of the argument arrays. +--+-- The *PP version contains both the vectorised and lifted versions wrapped+-- up in a closure. The code produced by the vectoriser uses the *PP+-- versions directly.+++-- Constructors ---------------------------------------------------------------+-- | O(1). Construct an empty array.+emptyPP :: PA a => PArray a+emptyPP = PA.empty+{-# INLINE_PA emptyPP #-}+++-- | O(1). Construct an array containing a single element.+singletonPP :: PA a => a :-> PArray a+singletonPP = closure1' PA.singleton PA.singletonl+{-# INLINE_PA singletonPP #-}+++-- | O(n). Construct an array of the given size, that maps all elements to the same value.+replicatePP :: PA a => Int :-> a :-> PArray a+replicatePP = closure2' PA.replicate PA.replicatel+{-# INLINE_PA replicatePP #-}+++-- | O(len result). Append two arrays.+appendPP :: PA a => PArray a :-> PArray a :-> PArray a+appendPP = closure2' PA.append PA.appendl+{-# INLINE_PA appendPP #-}+++-- | O(len result). Concatenate a nested array.+concatPP :: PA a => PArray (PArray a) :-> PArray a+concatPP = closure1' PA.concat PA.concatl+{-# INLINE_PA concatPP #-}+++-- Projections ----------------------------------------------------------------+-- | O(1). Take the number of elements in an array.+lengthPP :: PA a => PArray a :-> Int+lengthPP = closure1' PA.length PA.lengthl+{-# INLINE_PA lengthPP #-}+++-- | O(1). Lookup a single element from the source array.+indexPP :: PA a => PArray a :-> Int :-> a+indexPP = closure2' PA.index PA.indexl+{-# INLINE_PA indexPP #-}+++-- | O(len slice). Extract a range of elements from an array.+slicePP :: PA a => Int :-> Int :-> PArray a :-> PArray a+slicePP = closure3' PA.slice PA.slicel+{-# INLINE_PA slicePP #-}+++-- Traversals -----------------------------------------------------------------+-- | Apply a worker function to every element of an array.+mapPP :: (PA a, PA b) + => (a :-> b) :-> PArray a :-> PArray b++mapPP = closure2' mapPP_v mapPP_l+{-# INLINE_PA mapPP #-}+++mapPP_v :: (PA a, PA b)+ => (a :-> b) -> PArray a -> PArray b+mapPP_v f as+ = PA.replicate (PA.length as) f $:^ as+{-# INLINE mapPP_v #-}+++mapPP_l :: (PA a, PA b)+ => (PArray (a :-> b)) -> PArray (PArray a) -> PArray (PArray b)+mapPP_l fs ass+ = PA.unconcat ass + $ PA.replicates (PA.takeUSegd ass) fs+ $:^ PA.concat ass+{-# INLINE mapPP_l #-}+++-- | Apply a worker function to every pair of two arrays.+zipWithPP + :: (PA a, PA b, PA c)+ => (a :-> b :-> c) :-> PArray a :-> PArray b :-> PArray c++zipWithPP = closure3' zipWithPP_v zipWithPP_l+ where+ {-# INLINE zipWithPP_v #-}+ zipWithPP_v f as bs+ = PA.replicate (PA.length as) f $:^ as $:^ bs++ {-# INLINE zipWithPP_l #-}+ zipWithPP_l fs ass bss+ = PA.unconcat ass+ $ PA.replicates (PA.takeUSegd ass) fs+ $:^ PA.concat ass+ $:^ PA.concat bss+{-# INLINE_PA zipWithPP #-}+++-- | +crossMapPP+ :: (PA a, PA b)+ => PArray a :-> (a :-> PArray b) :-> PArray (a, b)++crossMapPP = closure2' crossMapPP_v crossMapPP_l+ where+ {-# INLINE crossMapPP_v #-}+ crossMapPP_v _ _+ = error "crossMapP: not implemented"++ {-# INLINE crossMapPP_l #-}+ crossMapPP_l _ _+ = error "crossMapP: not implemented"++{-# INLINE_PA crossMapPP #-}+++-- Filtering ------------------------------------------------------------------+-- | Extract the elements from an array that match the given predicate.+filterPP :: PA a => (a :-> Bool) :-> PArray a :-> PArray a+{-# INLINE filterPP #-}+filterPP = closure2' filterPP_v filterPP_l+ where+ {-# INLINE filterPP_v #-}+ filterPP_v p xs = PA.pack xs (mapPP_v p xs)+ + {-# INLINE filterPP_l #-}+ filterPP_l ps xss = PA.packl xss (mapPP_l ps xss)+++-- Tuple Functions ------------------------------------------------------------+-- | Zip a pair of arrays into an array of pairs.+zipPP :: (PA a, PA b) => PArray a :-> PArray b :-> PArray (a, b)+zipPP = closure2' PA.zip PA.zipl+{-# INLINE_PA zipPP #-}+++-- | Unzip an array of pairs into a pair of arrays.+unzipPP :: (PA a, PA b) => PArray (a, b) :-> (PArray a, PArray b)+unzipPP = closure1' PA.unzip PA.unzipl+{-# INLINE_PA unzipPP #-}+
+ Data/Array/Parallel/PArray.hs view
@@ -0,0 +1,547 @@+{-# OPTIONS -fno-spec-constr #-}+{-# LANGUAGE CPP, UndecidableInstances #-}+#include "fusion-phases.h"++-- | Unvectorised parallel arrays.+--+-- * These operators may be used directly by unvectorised client programs.+--+-- * They are also used by the "Data.Array.Parallel.Lifted.Combinators"+-- module to define the closure converted versions that vectorised code+-- uses.+--+-- * In general, the operators here are all unsafe and don't do bounds checks.+-- The lifted versions also don't check that each of the argument arrays+-- have the same length.++-- TODO:+-- Export unsafe versions from Data.Array.Parallel.PArray.Unsafe, and ensure+-- this module exports safe wrappers. We want to use the unsafe versions in+-- D.A.P.Lifted.Combinators for performance reasons, but the user facing PArray+-- functions should all be safe. In particular, the vectoriser guarantees+-- that all arrays passed to lifted functions will have the same length, but+-- the user may not obey this restriction.+-- +module Data.Array.Parallel.PArray + ( PArray, PA+ , valid+ , nf++ -- * Constructors+ , empty+ , singleton, singletonl+ , replicate, replicatel, replicates, replicates'+ , append, appendl+ , concat, concatl+ , unconcat+ , nestUSegd++ -- * Projections+ , length, lengthl -- length from D.A.P.PArray.PData.Base+ , index, indexl+ , extract, extracts, extracts'+ , slice, slicel+ , takeUSegd++ -- * Pack and Combine+ , pack, packl+ , packByTag+ , combine2++ -- * Enumerations+ , enumFromTo, enumFromTol -- from D.A.P.PArray.Scalar++ -- * Tuples+ , zip, zipl+ , zip3+ , zip4+ , zip5+ , unzip, unzipl++ -- * Conversions+ , fromVector, toVector+ , fromList, toList+ , fromUArray, toUArray -- from D.A.P.PArray.Scalar+ , fromUArray2) -- from D.A.P.PArray.Scalar+where+import qualified Data.Array.Parallel.Pretty as T+import Data.Array.Parallel.PArray.PData+import Data.Array.Parallel.PArray.PRepr+import Data.Array.Parallel.PArray.Scalar+import Data.Array.Parallel.PArray.Reference+import GHC.Exts+import Data.Vector (Vector)+import Data.Array.Parallel.Base (Tag)+import qualified Data.Array.Parallel.Array as A+import qualified Data.Array.Parallel.Unlifted as U+import qualified Data.Vector as V+import qualified "dph-lifted-base" Data.Array.Parallel.PArray as R+import qualified "dph-lifted-base" Data.Array.Parallel.PArray.Reference as R++import qualified Prelude as P+import Prelude hiding + ( length, replicate, concat+ , enumFromTo+ , zip, zip3, unzip)+++-- Pretty ---------------------------------------------------------------------+instance PA a => T.PprPhysical (PArray a) where+ pprp (PArray n# pdata)+ = ( T.text "PArray " T.<+> T.int (I# n#))+ T.$+$ ( T.nest 4 + $ pprpDataPA pdata)++instance PA a => Similar a where+ similar = similarPA++instance PA a => R.PprPhysical1 a where+ pprp1 = pprpPA+++trace :: String -> a -> a+trace _str x+ = x -- Debug.Trace.trace ("! " ++ str) x++-- Array -----------------------------------------------------------------------+-- Generic interface to PArrays.+--+-- NOTE: +-- The toVector conversion is defined by looking up every index instead of+-- using the bulk fromVectorPA function.+-- We do this to convert arrays of type (PArray Void) properly, as although a+-- (PArray Void) has an intrinsic length, a (PData Void) does not. If we try+-- to se the fromVectorPA function at this type we'll just get an `error`.+-- Arrays of type PArray Void aren't visible in the user API, but during+-- debugging we need to be able to print them out with the implied length.+--+instance PA e => A.Array PArray e where+ valid = valid+ singleton = singleton+ append = append++ length = length+ index (PArray _ pdata) ix+ = indexPA pdata ix++ toVector arr = V.map (A.index arr) $ V.enumFromTo 0 (A.length arr - 1)+ fromVector = fromVector++-- Operators ==================================================================+-- Each of these operators is wrapped in withRef functions so that we can +-- compare their outputs to the reference implementation. +-- See D.A.P.Reference for details.++ +-- Basics ---------------------------------------------------------------------+instance (Eq a, PA a) => Eq (PArray a) where+ (==) (PArray _ xs) (PArray _ ys) = toVectorPA xs == toVectorPA ys+ (/=) (PArray _ xs) (PArray _ ys) = toVectorPA xs /= toVectorPA ys+++-- | Check that an array has a valid internal representation.+valid :: PA a => PArray a -> Bool+valid (PArray n# darr1)+ = trace "valid"+ $ validPA darr1+ && coversPA True darr1 (I# n#)+{-# INLINE_PA valid #-}+++-- | Force an array to normal form.+nf :: PA a => PArray a -> ()+nf (PArray _ d)+ = trace "nf"+ $ nfPA d+{-# INLINE_PA nf #-}+++-- Constructors ----------------------------------------------------------------+-- | O(1). An empty array.+empty :: PA a => PArray a+empty+ = withRef1 "empty" R.empty+ $ PArray 0# emptyPA++{-# INLINE_PA empty #-}+++-- | O(1). Produce an array containing a single element.+singleton :: PA a => a -> PArray a+singleton x+ = withRef1 "singleton" (R.singleton x)+ $ PArray 1# (replicatePA 1 x)+{-# INLINE_PA singleton #-}+++-- | O(n). Produce an array of singleton arrays.+singletonl :: PA a => PArray a -> PArray (PArray a)+singletonl arr+ = withRef2 "singletonl" (R.singletonl (toRef1 arr))+ $ replicatel_ (replicate_ (length arr) 1) arr+{-# INLINE_PA singletonl #-}+++-- | O(n). Define an array of the given size, that maps all elements to the same value.+-- We require the replication count to be > 0 so that it's easier to maintain+-- the validPR invariants for nested arrays.+replicate :: PA a => Int -> a -> PArray a+replicate n x+ = withRef1 "replicate" (R.replicate n x)+ $ replicate_ n x+{-# INLINE_PA replicate #-}+ +replicate_ :: PA a => Int -> a -> PArray a+replicate_ (I# n#) x+ = PArray n# (replicatePA (I# n#) x)+{-# INLINE_PA replicate_ #-}+++-- | O(sum lengths). Lifted replicate.+replicatel :: PA a => PArray Int -> PArray a -> PArray (PArray a)+replicatel reps arr+ = withRef2 "replicatel" (R.replicatel (toRef1 reps) (toRef1 arr))+ $ replicatel_ reps arr++replicatel_ :: PA a => PArray Int -> PArray a -> PArray (PArray a)+replicatel_ (PArray n# (PInt lens)) (PArray _ pdata)+ = if n# ==# 0# then empty else + let !segd = U.lengthsToSegd lens+ !vsegd = U.promoteSegdToVSegd segd+ !pdata' = replicatesPA segd pdata+ !pdatas' = singletondPA pdata' + in PArray n# $ mkPNestedPA vsegd pdatas' segd pdata'+{-# INLINE_PA replicatel_ #-}+++-- | O(sum lengths). Segmented replicate.+replicates :: PA a => U.Segd -> PArray a -> PArray a+replicates segd arr@(PArray _ pdata)+ = trace (T.render $ T.text "!!! replicates " T.$+$ T.pprp segd T.$+$ T.pprp arr)+ $ withRef1 "replicates" (R.replicates segd (toRef1 arr))+ $ let !(I# n#) = U.elementsSegd segd+ in PArray n# $ replicatesPA segd pdata+{-# INLINE_PA replicates #-}+++-- | O(sum lengths). Wrapper for segmented replicate that takes replication counts+-- and uses them to build the `U.Segd`.+replicates' :: PA a => PArray Int -> PArray a -> PArray a+replicates' (PArray _ (PInt reps)) arr+ = trace "replicates'"+ $ replicates (U.lengthsToSegd reps) arr+{-# INLINE_PA replicates' #-}+ + +-- | Append two arrays.+append :: PA a => PArray a -> PArray a -> PArray a+append arr1@(PArray n1# darr1) arr2@(PArray n2# darr2)+ = withRef1 "append" (R.append (toRef1 arr1) (toRef1 arr2))+ $ PArray (n1# +# n2#) (appendPA darr1 darr2)+{-# INLINE_PA append #-}+++-- | Lifted append.+-- Both arrays must have the same length+appendl :: PA a => PArray (PArray a) -> PArray (PArray a) -> PArray (PArray a)+appendl arr1@(PArray n# pdata1) arr2@(PArray _ pdata2)+ = withRef2 "appendl" (R.appendl (toRef2 arr1) (toRef2 arr2))+ $ PArray n# $ appendlPA pdata1 pdata2+{-# INLINE_PA appendl #-}+++-- | Concatenate a nested array.+concat :: PA a => PArray (PArray a) -> PArray a+concat arr@(PArray _ darr)+ = withRef1 "concat" (R.concat (toRef2 arr))+ $ let darr' = concatPA darr+ !(I# n#) = lengthPA darr'+ in PArray n# darr'+{-# INLINE_PA concat #-}+++-- | Lifted concat.+concatl :: PA a => PArray (PArray (PArray a)) -> PArray (PArray a)+concatl arr@(PArray n# pdata1)+ = withRef2 "concatl" (R.concatl (toRef3 arr))+ $ PArray n# $ concatlPA pdata1+{-# INLINE_PA concatl #-}+++-- | Impose a nesting structure on a flat array+unconcat :: (PA a, PA b) => PArray (PArray a) -> PArray b -> PArray (PArray b)+unconcat (PArray n# pdata1) (PArray _ pdata2)+ = trace "! unconcat"+ $ PArray n# $ unconcatPA pdata1 pdata2+{-# INLINE_PA unconcat #-}+++-- | Create a nested array from a segment descriptor and some flat data.+-- The segment descriptor must represent as many elements as present+-- in the flat data array, else `error`+nestUSegd :: PA a => U.Segd -> PArray a -> PArray (PArray a)+nestUSegd segd (PArray n# pdata)+ | U.elementsSegd segd == I# n#+ , I# n2# <- U.lengthSegd segd+ = PArray n2#+ $ PNested (U.promoteSegdToVSegd segd) (singletondPA pdata) segd pdata ++ | otherwise+ = error $ unlines+ [ "Data.Array.Parallel.PArray.nestUSegd: number of elements defined by "+ ++ "segment descriptor and data array do not match"+ , " length of segment desciptor = " ++ show (U.elementsSegd segd)+ , " length of data array = " ++ show (I# n#) ]+{-# INLINE_PA nestUSegd #-}+++-- Projections ---------------------------------------------------------------+-- | Take the length of some arrays.+lengthl :: PA a => PArray (PArray a) -> PArray Int+lengthl arr@(PArray n# (PNested vsegd _ _ _))+ = withRef1 "lengthl" (R.lengthl (toRef2 arr))+ $ PArray n# $ PInt $ U.takeLengthsOfVSegd vsegd+{-# INLINE_PA lengthl #-}+++-- | O(1). Lookup a single element from the source array.+index :: PA a => PArray a -> Int -> a+index (PArray _ arr) ix+ = trace "index"+ $ indexPA arr ix+{-# INLINE_PA index #-}+++-- | O(len indices). Lookup a several elements from several source arrays+indexl :: PA a => PArray (PArray a) -> PArray Int -> PArray a+indexl (PArray n# darr) (PArray _ ixs)+ = trace "indexl"+ $ PArray n# (indexlPA darr ixs)+{-# INLINE_PA indexl #-}+++-- | Extract a range of elements from an array.+extract :: PA a => PArray a -> Int -> Int -> PArray a+extract (PArray _ arr) start len@(I# len#)+ = trace "extract"+ $ PArray len# (extractPA arr start len)+{-# INLINE_PA extract #-}+++-- | Segmented extract.+extracts :: PA a => Vector (PArray a) -> U.SSegd -> PArray a+extracts arrs ssegd+ = trace "extracts"+ $ let pdatas = fromVectordPA $ V.map (\(PArray _ vec) -> vec) arrs+ !(I# n#) = (U.sum $ U.lengthsOfSSegd ssegd)+ in PArray n#+ (extractssPA pdatas ssegd)+{-# INLINE_PA extracts #-}+++-- | Wrapper for `extracts` that takes arrays of sources, starts and lengths of+-- the segments, and uses these to build the `U.SSegd`.+-- TODO: The lengths of the sources, starts and lengths arrays must be the same, +-- but this is not checked.+-- All sourceids must point to valid data arrays.+-- Segments must be within their corresponding source array.+extracts' + :: PA a + => Vector (PArray a) + -> PArray Int -- ^ id of source array for each segment.+ -> PArray Int -- ^ starting index of each segment in its source array.+ -> PArray Int -- ^ length of each segment.+ -> PArray a+extracts' arrs (PArray _ (PInt sources)) (PArray _ (PInt starts)) (PArray _ (PInt lengths))+ = trace "extracts'"+ $ let segd = U.lengthsToSegd lengths+ ssegd = U.mkSSegd starts sources segd+ in extracts arrs ssegd+{-# INLINE_PA extracts' #-}+ ++-- | Extract a range of elements from an arrary.+-- Like `extract` but with the parameters in a different order.+slice :: PA a => Int -> Int -> PArray a -> PArray a+slice start len@(I# len#) (PArray _ darr)+ = trace "slice"+ $ PArray len# (extractPA darr start len)+{-# INLINE_PA slice #-}+++-- | Extract some slices from some arrays.+-- The arrays of starting indices and lengths must themselves+-- have the same length.+slicel :: PA a => PArray Int -> PArray Int -> PArray (PArray a) -> PArray (PArray a)+slicel (PArray n# sliceStarts) (PArray _ sliceLens) (PArray _ darr)+ = trace "slicel"+ $ PArray n# (slicelPA sliceStarts sliceLens darr)+{-# INLINE_PA slicel #-}+++-- | Take the segment descriptor from a nested array and demote it to a+-- plain Segd. This is unsafe because it can cause index space overflow.+takeUSegd :: PArray (PArray a) -> U.Segd+takeUSegd (PArray _ pdata)+ = trace "takeUSegd"+ $ takeSegdPD pdata+{-# INLINE_PA takeUSegd #-}+++-- Pack and Combine -----------------------------------------------------------+-- | Select the elements of an array that have their tag set to True.+pack :: PA a => PArray a -> PArray Bool -> PArray a+pack arr@(PArray _ xs) flags@(PArray _ (PBool sel2))+ = withRef1 "pack" (R.pack (toRef1 arr) (toRef1 flags))+ $ let darr' = packByTagPA xs (U.tagsSel2 sel2) 1++ -- The selector knows how many elements are set to '1',+ -- so we can use this for the length of the resulting array.+ !(I# m#) = U.elementsSel2_1 sel2++ in PArray m# darr'+{-# INLINE_PA pack #-}+++-- | Lifted pack.+packl :: PA a => PArray (PArray a) -> PArray (PArray Bool) -> PArray (PArray a)+packl xss@(PArray n# xdata@(PNested _ _ segd _))+ fss@(PArray _ fdata)+ = withRef2 "packl" (R.packl (toRef2 xss) (toRef2 fss))+ $ let + -- Concatenate both arrays to get the flat data.+ -- Although the virtual segmentation should be the same,+ -- the physical segmentation of both arrays may be different.+ xdata_flat = concatPA xdata+ PBool sel = concatPA fdata+ tags = U.tagsSel2 sel+ + -- Count how many elements go into each segment. + segd' = U.lengthsToSegd $ U.count_s segd tags 1++ -- Build the result array+ vsegd' = U.promoteSegdToVSegd segd'+ flat' = packByTagPA xdata_flat tags 1+ pdatas' = singletondPA flat'+ + in PArray n# (PNested vsegd' pdatas' segd' flat')+{-# INLINE_PA packl #-}+++-- | Filter an array based on some tags.+packByTag :: PA a => PArray a -> U.Array Tag -> Tag -> PArray a+packByTag arr@(PArray _ darr) tags tag+ = withRef1 "packByTag" (R.packByTag (toRef1 arr) tags tag)+ $ let darr' = packByTagPA darr tags tag+ !(I# n#) = lengthPA darr'+ in PArray n# darr'++{-# INLINE_PA packByTag #-}+++-- | Combine two arrays based on a selector.+combine2 :: forall a. PA a => U.Sel2 -> PArray a -> PArray a -> PArray a+combine2 sel arr1@(PArray _ darr1) arr2@(PArray _ darr2)+ = withRef1 "combine2" (R.combine2 sel (toRef1 arr1) (toRef1 arr2))+ $ let darr' = combine2PA sel darr1 darr2+ !(I# n#) = lengthPA darr'+ in PArray n# darr'+{-# INLINE_PA combine2 #-}+++-- Tuples ---------------------------------------------------------------------+-- | O(1). Zip a pair of arrays into an array of pairs.+-- The two arrays must have the same length, else `error`. +zip :: PArray a -> PArray b -> PArray (a, b)+zip (PArray n# pdata1) (PArray _ pdata2)+ = trace "zip"+ $ PArray n# $ zipPD pdata1 pdata2+{-# INLINE_PA zip #-}+++-- | Lifted zip.+zipl :: (PA a, PA b)+ => PArray (PArray a) -> PArray (PArray b) -> PArray (PArray (a, b))+zipl (PArray n# xs) (PArray _ ys)+ = trace "zipl"+ $ PArray n# $ ziplPA xs ys+{-# INLINE_PA zipl #-}+++-- | O(1). Zip three arrays.+-- All arrays must have the same length, else `error`. +zip3 :: PArray a -> PArray b -> PArray c -> PArray (a, b, c)+zip3 (PArray n# pdata1) (PArray _ pdata2) (PArray _ pdata3)+ = trace "zip3"+ $ PArray n# $ zip3PD pdata1 pdata2 pdata3+{-# INLINE_PA zip3 #-}+++-- | O(1). Zip four arrays.+-- All arrays must have the same length, else `error`. +zip4 :: PArray a -> PArray b -> PArray c -> PArray d -> PArray (a, b, c, d)+zip4 (PArray n# pdata1) (PArray _ pdata2) (PArray _ pdata3) (PArray _ pdata4)+ = trace "zip4"+ $ PArray n# $ zip4PD pdata1 pdata2 pdata3 pdata4+{-# INLINE_PA zip4 #-}+++-- | O(1). Zip five arrays.+-- All arrays must have the same length, else `error`. +zip5 :: PArray a -> PArray b -> PArray c -> PArray d -> PArray e -> PArray (a, b, c, d, e)+zip5 (PArray n# pdata1) (PArray _ pdata2) (PArray _ pdata3) (PArray _ pdata4) (PArray _ pdata5)+ = trace "zip5"+ $ PArray n# $ zip5PD pdata1 pdata2 pdata3 pdata4 pdata5+{-# INLINE_PA zip5 #-}+++-- | O(1). Unzip an array of pairs into a pair of arrays.+unzip :: PArray (a, b) -> (PArray a, PArray b)+unzip (PArray n# (PTuple2 xs ys))+ = trace "unzip"+ $ (PArray n# xs, PArray n# ys)+{-# INLINE_PA unzip #-}+++-- | Lifted unzip+unzipl :: PArray (PArray (a, b)) -> PArray (PArray a, PArray b)+unzipl (PArray n# pdata)+ = trace "unzipl"+ $ PArray n# $ unziplPD pdata+{-# INLINE_PA unzipl #-}+++-- Conversions ----------------------------------------------------------------+-- | Convert a `Vector` to a `PArray`+fromVector :: PA a => Vector a -> PArray a+fromVector vec+ = trace "fromVector"+ $ let !(I# n#) = V.length vec+ in PArray n# (fromVectorPA vec)+{-# INLINE_PA fromVector #-}+++-- | Convert a `PArray` to a `Vector` +toVector :: PA a => PArray a -> Vector a+toVector (PArray _ arr)+ = trace "toVector"+ $ toVectorPA arr+{-# INLINE_PA toVector #-}+++-- | Convert a list to a `PArray`.+fromList :: PA a => [a] -> PArray a+fromList xx+ = trace "fromList"+ $ let !(I# n#) = P.length xx+ in PArray n# (fromVectorPA $ V.fromList xx)+{-# INLINE_PA fromList #-}+++-- | Convert a `PArray` to a list.+toList :: PA a => PArray a -> [a]+toList (PArray _ arr)+ = trace "toList"+ $ V.toList $ toVectorPA arr+{-# INLINE_PA toList #-}+
+ Data/Array/Parallel/PArray/PData.hs view
@@ -0,0 +1,53 @@++-- | Parallel array data.+--+-- This is an interface onto the internal array types and operators defined+-- by the library, and should not normally be used by client programs.+module Data.Array.Parallel.PArray.PData + ( -- * Parallel array types+ PArray (..), PData(..), PDatas(..)+ , length, takeData+ + -- * PR (Parallel Representation)+ , PR (..) ++ -- * Extra conversions+ , fromListPR+ , toListPR++ -- * Nested arrays+ , module Data.Array.Parallel.PArray.PData.Nested++ -- * Tuple arrays+ , module Data.Array.Parallel.PArray.PData.Tuple2+ , module Data.Array.Parallel.PArray.PData.Tuple3+ , module Data.Array.Parallel.PArray.PData.Tuple4+ , module Data.Array.Parallel.PArray.PData.Tuple5)+where+import Data.Array.Parallel.PArray.PData.Base+import Data.Array.Parallel.PArray.PData.Wrap+import Data.Array.Parallel.PArray.PData.Nested+import Data.Array.Parallel.PArray.PData.Tuple2+import Data.Array.Parallel.PArray.PData.Tuple3+import Data.Array.Parallel.PArray.PData.Tuple4+import Data.Array.Parallel.PArray.PData.Tuple5+import Data.Array.Parallel.PArray.PData.Void ()+import Data.Array.Parallel.PArray.PData.Unit ()+import Data.Array.Parallel.PArray.PData.Int ()+import Data.Array.Parallel.PArray.PData.Word8 ()+import Data.Array.Parallel.PArray.PData.Double ()+import Data.Array.Parallel.PArray.PData.Sum2 ()+import Data.Array.Parallel.PArray.PRepr.Instances ()+import qualified Data.Vector as V+import Prelude hiding (length)+++-- | Convert a list to a PData.+fromListPR :: PR a => [a] -> PData a+fromListPR = fromVectorPR . V.fromList +++-- | Convert a PData to a list.+toListPR :: PR a => PData a -> [a]+toListPR = V.toList . toVectorPR+
+ Data/Array/Parallel/PArray/PData/Base.hs view
@@ -0,0 +1,273 @@+{-# OPTIONS_HADDOCK hide #-}+{-# LANGUAGE CPP, UndecidableInstances, ParallelListComp #-}+-- Undeciable instances only need for derived Show instance+#include "fusion-phases.h"++-- | Parallel array types and the PR class that works on the generic+-- representation of array data.+module Data.Array.Parallel.PArray.PData.Base + ( -- * Parallel Array types.+ PArray(..)+ , length, takeData++ , PR (..)+ , PData(..), PDatas(..)+ , bpermutePR)+where+import Data.Array.Parallel.Pretty+import GHC.Exts+import SpecConstr ()+import Data.Vector (Vector)+import Data.Array.Parallel.Base (Tag)+import qualified Data.Array.Parallel.Unlifted as U+import qualified Data.Vector as V+import Prelude hiding (length)++-- PArray ---------------------------------------------------------------------+-- | A parallel array consisting of a length field and some array data.++-- IMPORTANT: +-- The vectoriser requires the PArray data constructor to have this specific+-- form, because it builds them explicitly. Specifically, the array length+-- must be unboxed.+--+-- TODO: Why do we need the NoSpecConstr annotation?+-- +{-# ANN type PArray NoSpecConstr #-}+data PArray a+ = PArray Int# (PData a)++-- | Take the length field of a `PArray`.+{-# INLINE_PA length #-}+length :: PArray a -> Int+length (PArray n# _) = (I# n#)+++-- | Take the `PData` of a `PArray`.+{-# INLINE_PA takeData #-}+takeData :: PArray a -> PData a+takeData (PArray _ d) = d+++-- Parallel array data --------------------------------------------------------+-- | A chunk of parallel array data with a linear index space.+-- +-- In contrast to a `PArray`, a `PData` may not have a fixed length, and its+-- elements may have been converted to a generic representation. Whereas a+-- `PArray` is the \"user view\" of an array, a `PData` is a type only+-- used internally to the library.++-- An example of an array with no length is PData Void. We can index this+-- at an arbitrary position, and always get a 'void' element back.+--+{-# ANN type PData NoSpecConstr #-}+data family PData a++-- | Several chunks of parallel array data.+--+-- Although a `PArray` of atomic type such as `Int` only contains a+-- single `PData` chunk, nested arrays may contain several, which we +-- wrap up into a `PDatas`.+{-# ANN type PDatas NoSpecConstr #-}+data family PDatas a+++-- Put these here to break an import loop.+data instance PData Int+ = PInt (U.Array Int)++data instance PDatas Int+ = PInts (U.Arrays Int)+++-- PR -------------------------------------------------------------------------+-- | The PR (Parallel Representation) class holds primitive array operators that+-- work on our generic representation of data.+--+-- There are instances for all atomic types such as `Int` and `Double`, tuples,+-- nested arrays `PData (PArray a)` and for the generic types we used to represent+-- user level algebraic data, `Sum2` and `Wrap` and `Void`. All array data +-- is converted to this fixed set of types.+--+-- TODO: refactor to change PData Int to U.Array Int, +-- there's not need to wrap an extra PData constructor around these arrays,+-- and the type of bpermute is different than the others.+class PR a where++ -- House Keeping ------------------------------+ -- These methods are helpful for debugging, but we don't want their+ -- associated type classes as superclasses of PR.++ -- | (debugging) Check that an array has a well formed representation.+ -- This should only return `False` where there is a bug in the library.+ validPR :: PData a -> Bool++ -- | (debugging) Ensure an array is fully evaluted.+ nfPR :: PData a -> ()++ -- | (debugging) Weak equality of contained elements.+ --+ -- Returns `True` for functions of the same type. In the case of nested arrays,+ -- returns `True` if the array defines the same set of elements, but does not+ -- care about the exact form of the segement descriptors.+ similarPR :: a -> a -> Bool++ -- | (debugging) Check that an index is within an array.+ -- + -- Arrays containing `Void` elements don't have a fixed length, and return + -- `Void` for all indices. If the array does have a fixed length, and the + -- flag is true, then we allow the index to be equal to this length, as+ -- well as less than it.+ coversPR :: Bool -> PData a -> Int -> Bool++ -- | (debugging) Pretty print the physical representation of an element.+ pprpPR :: a -> Doc++ -- | (debugging) Pretty print the physical representation of some array data.+ pprpDataPR :: PData a -> Doc+++ -- Constructors -------------------------------+ -- | Produce an empty array with size zero.+ emptyPR :: PData a++ -- | O(n). Define an array of the given size, that maps all elements to the+ -- same value.+ -- + -- We require the replication count to be > 0 so that it's easier to+ -- maintain the `validPR` invariants for nested arrays.+ replicatePR :: Int -> a -> PData a++ -- | O(sum lengths). Segmented replicate.+ -- + -- Given a Segment Descriptor (Segd), replicate each each element in the+ -- array according to the length of the corrsponding segment.+ -- The array data must define at least as many elements as there are segments+ -- in the descriptor.++ -- TODO: This takes a whole Segd instead of just the lengths. If the Segd knew+ -- that there were no zero length segments then we could implement this+ -- more efficiently in the nested case case. If there are no zeros, then+ -- all psegs in the result are reachable from the vsegs, and we wouldn't+ -- need to pack them after the replicate.+ -- + replicatesPR :: U.Segd -> PData a -> PData a++ -- | Append two arrays.+ appendPR :: PData a -> PData a -> PData a++ -- | Segmented append.+ --+ -- The first descriptor defines the segmentation of the result, + -- and the others define the segmentation of each source array.+ appendsPR :: U.Segd+ -> U.Segd -> PData a+ -> U.Segd -> PData a+ -> PData a+++ -- Projections --------------------------------+ -- | O(1). Get the length of an array, if it has one.+ -- + -- Applying this function to an array of `Void` will yield `error`, as+ -- these arrays have no fixed length. To check array bounds, use the+ -- `coversPR` method instead, as that is a total function.+ lengthPR :: PData a -> Int+ + -- | O(1). Retrieve a single element from a single array.+ indexPR :: PData a -> Int -> a++ -- | O(1). Shared indexing.+ -- Retrieve several elements from several chunks of array data, + -- given the chunkid and index in that chunk for each element.+ indexsPR :: PDatas a -> U.Array (Int, Int) -> PData a++ -- | O(1). Shared indexing+ indexvsPR :: PDatas a -> U.VSegd -> U.Array (Int, Int) -> PData a++ -- | O(slice len). Extract a slice of elements from an array,+ -- given the starting index and length of the slice.+ extractPR :: PData a -> Int -> Int -> PData a++ -- | O(sum seglens). Shared extract.+ -- Extract several slices from several source arrays.+ -- + -- The Scattered Segment Descriptor (`SSegd`) describes where to get each + -- slice, and all slices are concatenated together into the result.+ extractssPR :: PDatas a -> U.SSegd -> PData a++ -- | O(sum seglens). Shared extract.+ -- Extract several slices from several source arrays.+ -- TODO: we're refactoring the library so functions use the VSeg form directly,+ -- instead of going via a SSegd.+ extractvsPR :: PDatas a -> U.VSegd -> PData a+ extractvsPR pdatas vsegd+ = extractssPR pdatas (U.unsafeDemoteToSSegdOfVSegd vsegd)+ + -- Pack and Combine ---------------------------+ -- | Select elements of an array that have their corresponding tag set to+ -- the given value. + --+ -- The data array must define at least as many elements as the length+ -- of the tags array. + packByTagPR :: PData a -> U.Array Tag -> Tag -> PData a++ -- | Combine two arrays based on a selector.+ -- + -- See the documentation for selectors in the dph-prim-seq library+ -- for how this works.+ combine2PR :: U.Sel2 -> PData a -> PData a -> PData a+++ -- Conversions --------------------------------+ -- | Convert a boxed vector to an array.+ fromVectorPR :: Vector a -> PData a++ -- | Convert an array to a boxed vector.+ toVectorPR :: PData a -> Vector a+++ -- PDatas -------------------------------------+ -- | O(1). Yield an empty collection of `PData`.+ emptydPR :: PDatas a++ -- | O(1). Yield a singleton collection of `PData`.+ singletondPR :: PData a -> PDatas a++ -- | O(1). Yield how many `PData` are in the collection.+ lengthdPR :: PDatas a -> Int++ -- | O(1). Lookup a `PData` from a collection.+ indexdPR :: PDatas a -> Int -> PData a++ -- | O(n). Append two collections of `PData`.+ appenddPR :: PDatas a -> PDatas a -> PDatas a++ -- | O(n). Convert a vector of `PData` to a `PDatas`.+ fromVectordPR :: V.Vector (PData a) -> PDatas a++ -- | O(n). Convert a `PDatas` to a vector of `PData`.+ toVectordPR :: PDatas a -> V.Vector (PData a)++++-- | O(len indices) Backwards permutation.+-- Retrieve several elements from a single array.+bpermutePR :: PR a => PData a -> U.Array Int -> PData a+bpermutePR pdata ixs+ = indexsPR (singletondPR pdata) + (U.zip (U.replicate (U.length ixs) 0)+ ixs)+++-- Pretty ---------------------------------------------------------------------+instance PR a => PprPhysical (PData a) where+ pprp = pprpDataPR++instance PR a => PprPhysical (PDatas a) where+ pprp pdatas+ = vcat+ $ [ int n <> colon <> text " " <> pprpDataPR pd+ | n <- [0..]+ | pd <- V.toList $ toVectordPR pdatas]+
+ Data/Array/Parallel/PArray/PData/Double.hs view
@@ -0,0 +1,167 @@+{-# OPTIONS_HADDOCK hide #-}+{-# LANGUAGE CPP #-}+#include "fusion-phases.h"++-- | PR instance for Doubles.+module Data.Array.Parallel.PArray.PData.Double + ( PData (..)+ , PDatas(..))+where+import Data.Array.Parallel.Pretty+import Data.Array.Parallel.PArray.PData.Base+import Data.Array.Parallel.PArray.PData.Nested+import qualified Data.Array.Parallel.Unlifted as U+import qualified Data.Vector as V+++-------------------------------------------------------------------------------+data instance PData Double+ = PDouble (U.Array Double)++data instance PDatas Double+ = PDoubles (U.Arrays Double)+++-- PR -------------------------------------------------------------------------+instance PR Double where++ {-# NOINLINE validPR #-}+ validPR _+ = True++ {-# NOINLINE nfPR #-}+ nfPR (PDouble xx)+ = xx `seq` ()++ {-# NOINLINE similarPR #-}+ similarPR = (==)++ {-# NOINLINE coversPR #-}+ coversPR weak (PDouble uarr) ix+ | weak = ix <= U.length uarr+ | otherwise = ix < U.length uarr++ {-# NOINLINE pprpPR #-}+ pprpPR d+ = double d++ {-# NOINLINE pprpDataPR #-}+ pprpDataPR (PDouble vec)+ = text "PDouble"+ <+> text (show $ U.toList vec)+++ -- Constructors -------------------------------+ {-# INLINE_PDATA emptyPR #-}+ emptyPR+ = PDouble U.empty++ {-# INLINE_PDATA replicatePR #-}+ replicatePR len x+ = PDouble $ U.replicate len x++ {-# INLINE_PDATA replicatesPR #-}+ replicatesPR segd (PDouble arr)+ = PDouble $ U.replicate_s segd arr++ {-# INLINE_PDATA appendPR #-}+ appendPR (PDouble arr1) (PDouble arr2)+ = PDouble $ arr1 U.+:+ arr2++ {-# INLINE_PDATA appendsPR #-}+ appendsPR segdResult segd1 (PDouble arr1) segd2 (PDouble arr2)+ = PDouble $ U.append_s segdResult segd1 arr1 segd2 arr2+++ -- Projections -------------------------------- + {-# INLINE_PDATA lengthPR #-}+ lengthPR (PDouble uarr)+ = U.length uarr++ {-# INLINE_PDATA indexPR #-}+ indexPR (PDouble arr) ix+ = U.index "indexPR[Double]" arr ix++ {-# INLINE_PDATA indexsPR #-}+ indexsPR (PDoubles pvecs) srcixs+ = PDouble $ U.map (\(src, ix) -> U.unsafeIndex2s pvecs src ix) srcixs++ {-# INLINE_PDATA indexvsPR #-}+ indexvsPR (PDoubles arrs) vsegd srcixs + = PDouble $ U.indexs_avs arrs vsegd srcixs++ {-# INLINE_PDATA extractPR #-}+ extractPR (PDouble arr) start len + = PDouble $ U.extract arr start len++ {-# INLINE_PDATA extractssPR #-}+ extractssPR (PDoubles arrs) ssegd+ = PDouble $ U.extracts_ass ssegd arrs++ {-# INLINE_PDATA extractvsPR #-}+ extractvsPR (PDoubles arrs) vsegd+ = PDouble $ U.extracts_avs vsegd arrs+ ++ -- Pack and Combine ---------------------------+ {-# NOINLINE packByTagPR #-}+ packByTagPR (PDouble arr1) arrTags tag+ = PDouble $ U.packByTag arr1 arrTags tag++ {-# NOINLINE combine2PR #-}+ combine2PR sel (PDouble arr1) (PDouble arr2)+ = PDouble $ U.combine2 (U.tagsSel2 sel)+ (U.repSel2 sel)+ arr1 arr2+++ -- Conversions --------------------------------+ {-# NOINLINE fromVectorPR #-}+ fromVectorPR xx+ = PDouble (U.fromList $ V.toList xx)++ {-# NOINLINE toVectorPR #-}+ toVectorPR (PDouble arr)+ = V.fromList $ U.toList arr+++ -- PDatas -------------------------------------+ {-# INLINE_PDATA emptydPR #-}+ emptydPR + = PDoubles $ U.emptys+ + {-# INLINE_PDATA singletondPR #-}+ singletondPR (PDouble pdata)+ = PDoubles $ U.singletons pdata+ + {-# INLINE_PDATA lengthdPR #-}+ lengthdPR (PDoubles vec)+ = U.lengths vec+ + {-# INLINE_PDATA indexdPR #-}+ indexdPR (PDoubles vec) ix+ = PDouble $ vec `U.unsafeIndexs` ix++ {-# INLINE_PDATA appenddPR #-}+ appenddPR (PDoubles xs) (PDoubles ys)+ = PDoubles $ xs `U.appends` ys+ + {-# NOINLINE fromVectordPR #-}+ fromVectordPR pdatas+ = PDoubles + $ U.fromVectors + $ V.map (\(PDouble vec) -> vec) pdatas+ + {-# NOINLINE toVectordPR #-}+ toVectordPR (PDoubles vec)+ = V.map PDouble $ U.toVectors vec+++-- Show -----------------------------------------------------------------------+deriving instance Show (PData Double)+deriving instance Show (PDatas Double)++instance PprVirtual (PData Double) where+ pprv (PDouble vec)+ = text (show $ U.toList vec)+
+ Data/Array/Parallel/PArray/PData/Int.hs view
@@ -0,0 +1,159 @@+{-# OPTIONS_HADDOCK hide #-}+{-# LANGUAGE CPP #-}+#include "fusion-phases.h"++-- | PR instance for Ints+module Data.Array.Parallel.PArray.PData.Int () where+import Data.Array.Parallel.PArray.PData.Base+import qualified Data.Array.Parallel.Unlifted as U+import qualified Data.Vector as V+import Text.PrettyPrint+import Prelude as P+import Data.Array.Parallel.Pretty+++-- PR -------------------------------------------------------------------------+instance PR Int where++ {-# NOINLINE validPR #-}+ validPR _+ = True++ {-# NOINLINE nfPR #-}+ nfPR (PInt xx)+ = xx `seq` ()++ {-# NOINLINE similarPR #-}+ similarPR = (==)++ {-# NOINLINE coversPR #-}+ coversPR weak (PInt uarr) ix+ | weak = ix <= U.length uarr+ | otherwise = ix < U.length uarr++ {-# NOINLINE pprpPR #-}+ pprpPR i+ = int i++ {-# NOINLINE pprpDataPR #-}+ pprpDataPR (PInt uarr)+ = text "PInt" <+> pprp uarr+++ -- Constructors -------------------------------+ {-# INLINE_PDATA emptyPR #-}+ emptyPR+ = PInt U.empty++ {-# INLINE_PDATA replicatePR #-}+ replicatePR len x+ = PInt (U.replicate len x)++ {-# INLINE_PDATA replicatesPR #-}+ replicatesPR segd (PInt arr)+ = PInt (U.replicate_s segd arr)+ + {-# INLINE_PDATA appendPR #-}+ appendPR (PInt arr1) (PInt arr2)+ = PInt $ arr1 U.+:+ arr2++ {-# INLINE_PDATA appendsPR #-}+ appendsPR segdResult segd1 (PInt arr1) segd2 (PInt arr2)+ = PInt $ U.append_s segdResult segd1 arr1 segd2 arr2+++ -- Projections -------------------------------- + {-# INLINE_PDATA lengthPR #-}+ lengthPR (PInt uarr) + = U.length uarr++ {-# INLINE_PDATA indexPR #-}+ indexPR (PInt uarr) ix+ = U.index "indexPR[Int]" uarr ix++ {-# INLINE_PDATA indexsPR #-}+ indexsPR (PInts pvecs) srcixs+ = PInt $ U.map (\(src, ix) -> U.unsafeIndex2s pvecs src ix) srcixs++ {-# INLINE_PDATA indexvsPR #-}+ indexvsPR (PInts arrs) vsegd srcixs + = PInt $ U.indexs_avs arrs vsegd srcixs++ {-# INLINE_PDATA extractPR #-}+ extractPR (PInt arr) start len + = PInt $ U.extract arr start len++ {-# INLINE_PDATA extractssPR #-}+ extractssPR (PInts arrs) ssegd+ = PInt $ U.extracts_ass ssegd arrs++ {-# INLINE_PDATA extractvsPR #-}+ extractvsPR (PInts arrs) vsegd+ = PInt $ U.extracts_avs vsegd arrs+++ -- Pack and Combine ---------------------------+ {-# NOINLINE packByTagPR #-}+ packByTagPR (PInt arr1) arrTags tag+ = PInt $ U.packByTag arr1 arrTags tag++ {-# NOINLINE combine2PR #-}+ combine2PR sel (PInt arr1) (PInt arr2)+ = PInt $ U.combine2 (U.tagsSel2 sel)+ (U.repSel2 sel)+ arr1 arr2+++ -- Conversions --------------------------------+ {-# NOINLINE fromVectorPR #-}+ fromVectorPR xx+ = PInt $U.fromList $ V.toList xx++ {-# NOINLINE toVectorPR #-}+ toVectorPR (PInt arr)+ = V.fromList $ U.toList arr+++ -- PDatas -------------------------------------+ {-# INLINE_PDATA emptydPR #-}+ emptydPR + = PInts $ U.emptys+ + {-# INLINE_PDATA singletondPR #-}+ singletondPR (PInt arr)+ = PInts $ U.singletons arr+ + {-# INLINE_PDATA lengthdPR #-}+ lengthdPR (PInts arrs)+ = U.lengths arrs+ + {-# INLINE_PDATA indexdPR #-}+ indexdPR (PInts arrs) ix+ = PInt $ arrs `U.unsafeIndexs` ix++ {-# INLINE_PDATA appenddPR #-}+ appenddPR (PInts xs) (PInts ys)+ = PInts $ xs `U.appends` ys+ + {-# NOINLINE fromVectordPR #-}+ fromVectordPR pdatas+ = PInts + $ U.fromVectors + $ V.map (\(PInt vec) -> vec) pdatas+ + {-# NOINLINE toVectordPR #-}+ toVectordPR (PInts vec)+ = V.map PInt $ U.toVectors vec+++-- Show -----------------------------------------------------------------------+deriving instance Show (PData Int)+deriving instance Show (PDatas Int)++instance PprPhysical (U.Array Int) where+ pprp uarr + = text (show $ U.toList uarr)++instance PprVirtual (PData Int) where+ pprv (PInt vec)+ = text (show $ U.toList vec)
+ Data/Array/Parallel/PArray/PData/Nested.hs view
@@ -0,0 +1,718 @@+{-# OPTIONS_HADDOCK hide #-}+{-# LANGUAGE CPP, UndecidableInstances, ParallelListComp #-}+{-# OPTIONS -fno-spec-constr #-}+#include "fusion-phases.h"++-- | PR instance for nested arrays.+module Data.Array.Parallel.PArray.PData.Nested + ( PData(..)+ , PDatas(..)+ , mkPNested+ , concatPR, concatlPR+ , flattenPR, takeSegdPD+ , unconcatPR+ , appendlPR+ , indexlPR+ , slicelPR+ , extractvs_delay)+where+import Data.Array.Parallel.Base+import Data.Array.Parallel.Pretty+import Data.Array.Parallel.PArray.PData.Base as PA+import qualified Data.IntSet as IS+import qualified Data.Array.Parallel.Unlifted as U+import qualified Data.Vector as V+import GHC.Exts+import System.IO.Unsafe+++-- Nested arrays --------------------------------------------------------------+data instance PData (PArray a)+ = PNested+ { pnested_uvsegd :: U.VSegd+ -- ^ Virtual segmentation descriptor. + -- Defines a virtual nested array based on physical data.++ , pnested_psegdata :: PDatas a+ -- ^ Chunks of array data, where each chunk has a linear index space. ++ , pnested_segd :: U.Segd -- LAZY FIELD+ -- ^ A demoted version of the VSegd.+ -- If the function that creates the array already has the plain Segd,+ -- then it should stash it here, otherwise build a thunk that makes it.++ , pnested_flat :: PData a -- LAZY FIELD+ -- ^ A pre-concatenated version of the array.+ -- If the function that creates the array already has a flat form,+ -- then it should stash it here, otherwise build a thunk that makes it.+ }+++-- TODO: should we unpack the vsegd fields here?+data instance PDatas (PArray a)+ = PNesteds (V.Vector (PData (PArray a)))+++-- | Construct a nested array.+mkPNested :: PR a+ => U.VSegd -> PDatas a+ -> U.Segd -> PData a+ -> PData (PArray a)+mkPNested = PNested+{-# INLINE_PDATA mkPNested #-}+++-- Projections ----------------------------------------------------------------+-- These functions take concatenated forms of the vsegd and array data from+-- the representation of the nested array. Although the projections themselves+-- are O(1), they could return thunks.++-- | Concatenate a nested array.+concatPR :: PR a => PData (PArray a) -> PData a+concatPR (PNested _ _ _ flat)+ = flat+{-# INLINE concatPR #-}++-- | Take the segment descriptor from a nested array and demote it to a+-- plain Segd.+takeSegdPD :: PData (PArray a) -> U.Segd+takeSegdPD (PNested _ _ segd _) + = segd+{-# INLINE_PDATA takeSegdPD #-}++-- | Flatten a nested array, yielding a plain segment descriptor and +-- concatenated data.+--+flattenPR :: PR a => PData (PArray a) -> (U.Segd, PData a)+flattenPR (PNested _ _ segd flat)+ = (segd, flat)+{-# INLINE_PDATA flattenPR #-}+++-- PR Instances ---------------------------------------------------------------+instance U.Elt (Int, Int, Int)++instance PR a => PR (PArray a) where+ -- TODO: make this check all sub arrays as well+ -- TODO: ensure that all psegdata arrays are referenced from some psegsrc.+ -- TODO: shift segd checks into associated modules.+ {-# NOINLINE validPR #-}+ validPR (PNested vsegd pdatas _ _)+ = let vsegids = U.takeVSegidsOfVSegd vsegd+ ssegd = U.takeSSegdOfVSegd vsegd+ pseglens = U.lengthsOfSSegd ssegd+ psegstarts = U.startsOfSSegd ssegd+ psegsrcs = U.sourcesOfSSegd ssegd++ -- The lengths of the pseglens, psegstarts and psegsrcs fields must all be the same+ fieldLensOK+ = validBool "nested array field lengths not identical"+ $ and + [ U.length psegstarts == U.length pseglens+ , U.length psegsrcs == U.length pseglens ]++ -- Every vseg must reference a valid pseg.+ vsegsRefOK+ = validBool "nested array vseg doesn't ref pseg"+ $ U.and+ $ U.map (\vseg -> vseg < U.length pseglens) vsegids+ + -- Every pseg source id must point to a flat data array+ psegsrcsRefOK+ = validBool "nested array psegsrc doesn't ref flat array"+ $ U.and + $ U.map (\srcid -> srcid < lengthdPR pdatas) psegsrcs++ -- Every physical segment must be a valid slice of the corresponding flat array.+ -- + -- We allow psegs with len 0, start 0 even if the flat array is empty.+ -- This occurs with [ [] ]. + -- + -- As a generalistion of above, we allow segments with len 0, start <= srclen.+ -- This occurs when there is an empty array as the last segment+ -- For example:+ -- [ [5, 4, 3, 2] [ ] ].+ -- PNested vsegids: [0,1]+ -- pseglens: [4,0]+ -- psegstarts: [0,4] -- last '4' here is <= length of flat array+ -- psegsrcs: [0,0]+ -- PInt [5, 4, 3, 2]+ --+ psegSlicesOK + = validBool "nested array pseg slices are invalid"+ $ U.and + $ U.zipWith3 + (\len start srcid+ -> let pdata = pdatas `indexdPR` srcid+ in and [ coversPR (len == 0) pdata start+ , coversPR True pdata (start + len) ])+ pseglens psegstarts psegsrcs++ -- Every pseg must be referenced by some vseg.+ vsegs = IS.fromList $ U.toList vsegids+ psegsReffedOK+ = validBool "nested array pseg not reffed by vseg"+ $ (U.length pseglens == 0) + || (U.and $ U.map (flip IS.member vsegs) + $ U.enumFromTo 0 (U.length pseglens - 1))++ in unsafePerformIO+ $ do {-print fieldLensOK+ print vsegsRefOK+ print psegsrcsRefOK+ print psegSlicesOK+ print psegsReffedOK-}+ return $ + and [ fieldLensOK+ , vsegsRefOK+ , psegsrcsRefOK+ , psegSlicesOK+ , psegsReffedOK ]++ {-# NOINLINE nfPR #-}+ nfPR = error "nfPR[PArray]: not defined yet"+++ {-# NOINLINE similarPR #-}+ similarPR (PArray _ pdata1) (PArray _ pdata2)+ = V.and $ V.zipWith similarPR + (toVectorPR pdata1)+ (toVectorPR pdata2)+++ {-# NOINLINE coversPR #-}+ coversPR weak (PNested vsegd _ _ _) ix+ | weak = ix <= (U.length $ U.takeVSegidsOfVSegd vsegd)+ | otherwise = ix < (U.length $ U.takeVSegidsOfVSegd vsegd)++ {-# NOINLINE pprpPR #-}+ pprpPR (PArray n# pdata)+ = (text "PArray " <+> int (I# n#))+ $+$ ( nest 4 + $ pprpDataPR pdata)++ {-# NOINLINE pprpDataPR #-}+ pprpDataPR (PNested vsegd pdatas _ _)+ = text "PNested"+ $+$ ( nest 4+ $ pprp vsegd $$ pprp pdatas)+++ -- Constructors -----------------------------------------+ {-# INLINE_PDATA emptyPR #-}+ emptyPR = PNested U.emptyVSegd emptydPR U.emptySegd emptyPR+++ -- When replicating an array we use the source as the single physical+ -- segment, then point all the virtual segments to it.+ {-# INLINE_PDATA replicatePR #-}+ replicatePR c (PArray n# pdata)+ = checkNotEmpty "replicatePR[PArray]" c+ $ let -- All virtual segments point to the same physical segment.+ vsegd = U.replicatedVSegd (I# n#) c++ -- There is only one physical array.+ pdatas = singletondPR pdata++ -- Pre-concatenated version.+ -- If the consumer pulls on this then the single segment gets physically copied.+ segd = U.unsafeDemoteToSegdOfVSegd vsegd+ flat = extractvs_delay pdatas vsegd++ in PNested vsegd pdatas segd flat+ ++ -- For segmented replicates, we just replicate the vsegids field.+ --+ -- TODO: Does replicate_s really need the whole segd,+ -- or could we get away without creating the indices field?+ --+ -- TODO: If we know the lens does not contain zeros, then we don't need+ -- to cull down the psegs.+ --+ {-# INLINE_PDATA replicatesPR #-}+ replicatesPR segd (PNested uvsegd pdatas _ _)+ = let vsegd' = U.updateVSegsOfVSegd (U.replicate_s segd) uvsegd+ segd' = U.unsafeDemoteToSegdOfVSegd vsegd'+ flat' = extractvs_delay pdatas vsegd'+ in PNested vsegd' pdatas segd' flat'+++ -- Append nested arrays by appending the segment descriptors,+ -- and putting all physical arrays in the result.+ {-# NOINLINE appendPR #-}+ appendPR (PNested uvsegd1 pdatas1 _ _) (PNested uvsegd2 pdatas2 _ _)+ = let vsegd' = U.appendVSegd+ uvsegd1 (lengthdPR pdatas1) + uvsegd2 (lengthdPR pdatas2)++ pdatas' = appenddPR pdatas1 pdatas2+ segd' = U.unsafeDemoteToSegdOfVSegd vsegd'+ flat' = extractvs_delay pdatas' vsegd'++ in PNested vsegd' pdatas' segd' flat'+ ++ -- Performing segmented append requires segments from the physical arrays to+ -- be interspersed, so we need to copy data from the second level of nesting. + --+ -- In the implementation we can safely flatten out replication in the vsegs+ -- because the source program result would have this same physical size+ -- anyway. Once this is done we use copying segmented append on the flat + -- arrays, and then reconstruct the segment descriptor.+ --+ {-# NOINLINE appendsPR #-}+ appendsPR rsegd segd1 xarr segd2 yarr+ = let (xsegd, xs) = flattenPR xarr+ (ysegd, ys) = flattenPR yarr+ + xsegd' = U.lengthsToSegd + $ U.sum_s segd1 (U.lengthsSegd xsegd)+ + ysegd' = U.lengthsToSegd+ $ U.sum_s segd2 (U.lengthsSegd ysegd)+ + segd' = U.lengthsToSegd+ $ U.append_s rsegd segd1 (U.lengthsSegd xsegd)+ segd2 (U.lengthsSegd ysegd)+++ -- The pdatas only contains a single flat chunk.+ vsegd' = U.promoteSegdToVSegd segd'+ flat' = appendsPR (U.plusSegd xsegd' ysegd')+ xsegd' xs+ ysegd' ys++ pdatas' = singletondPR flat'++ in PNested vsegd' pdatas' segd' flat'+++ -- Projections ------------------------------------------+ {-# INLINE_PDATA lengthPR #-}+ lengthPR (PNested vsegd _ _ _)+ = U.lengthOfVSegd vsegd+++ -- To index into a nested array, first determine what segment the index+ -- corresponds to, and extract that as a slice from that physical array.+ --+ -- IMPORTANT: + -- We need to go through the vsegd here, instead of demanding the+ -- flat version, because we don't want to force creation of the+ -- entire manifest array.+ {-# INLINE_PDATA indexPR #-}+ indexPR (PNested uvsegd pdatas _ _) ix+ | (pseglen@(I# pseglen#), psegstart, psegsrcid) <- U.getSegOfVSegd uvsegd ix+ = let !psrc = pdatas `indexdPR` psegsrcid+ !pdata' = extractPR psrc psegstart pseglen+ in PArray pseglen# pdata'+++ {-# INLINE_PDATA indexsPR #-}+ indexsPR pdatas@(PNesteds arrs) srcixs+ = let (srcids, ixs) = U.unzip srcixs+ + -- See Note: psrcoffset+ !psrcoffset = V.prescanl (+) 0+ $ V.map (lengthdPR . pnested_psegdata) arrs++ -- length, start and srcid of the segments we're returning.+ -- Note that we need to offset the srcid + -- TODO: don't unbox the VSegd for every iteration.+ seginfo :: U.Array (Int, Int, Int)+ seginfo + = U.zipWith (\srcid ix -> + let (PNested vsegd _ _ _) = pdatas `indexdPR` srcid+ (len, start, srcid') = U.getSegOfVSegd vsegd ix+ in (len, start, srcid' + (psrcoffset `V.unsafeIndex` srcid)))+ srcids+ ixs++ (pseglens', psegstarts', psegsrcs') + = U.unzip3 seginfo+ + -- TODO: check that doing lengthsToSegd won't cause overflow+ segd' = U.lengthsToSegd pseglens'+ vsegd' = U.promoteSSegdToVSegd+ $ U.mkSSegd psegstarts' psegsrcs' segd'+ + -- All flat data arrays in the sources go into the result.+ pdatas' = fromVectordPR+ $ V.concat $ V.toList + $ V.map (toVectordPR . pnested_psegdata) arrs+ + flat' = extractvs_delay pdatas' vsegd'+ + in PNested vsegd' pdatas' segd' flat'+++ {-# INLINE_PDATA indexvsPR #-}+ indexvsPR pdatas vsegd srcixs+ = let !vsegids = U.takeVSegidsRedundantOfVSegd vsegd+ !ssegd = U.takeSSegdRedundantOfVSegd vsegd+ !sources = U.sourcesOfSSegd ssegd+ !starts = U.startsOfSSegd ssegd++ !srcixs' + = U.map (\(ix1, ix2)+ -> let !psegid = U.index "indexvsPR/vsegids" vsegids ix1+ !source = U.index "indexvsPR/sources" sources psegid+ !start = U.index "indexvsPR/starts" starts psegid+ in (source, start + ix2))+ srcixs++ in indexsPR pdatas srcixs'+++ -- To extract a range of elements from a nested array, perform the extract+ -- on the vsegids field. The `updateVSegsOfUVSegd` function will then filter+ -- out all of the psegs that are no longer reachable from the new vsegids.+ --+ -- IMPORTANT: + -- We need to go through the vsegd here, instead of demanding the+ -- flat version, because we don't want to force creation of the+ -- entire manifest array.+ {-# INLINE_PDATA extractPR #-}+ extractPR (PNested uvsegd pdatas _ _) start len+ = let vsegd' = U.updateVSegsOfVSegd (\vsegids -> U.extract vsegids start len) uvsegd+ segd' = U.unsafeDemoteToSegdOfVSegd vsegd'+ flat' = extractvs_delay pdatas vsegd'+ in PNested vsegd' pdatas segd' flat'+++ -- [Note: psrcoffset]+ -- ~~~~~~~~~~~~~~~~~~+ -- As all the flat data arrays in the sources are present in the result array,+ -- we need to offset the psegsrcs field when combining multiple sources.+ -- + -- Exaple+ -- Source Arrays:+ -- arr0 ...+ -- psrcids : [0, 0, 0, 1, 1]+ -- psegdata : [PInt xs1, PInt xs2]+ --+ -- arr1 ... + -- psrcids : [0, 0, 1, 1, 2, 2, 2]+ -- psegdata : [PInt ys1, PInt ys2, PInt ys3]+ -- + -- Result Array:+ -- psrcids : [...]+ -- psegdata : [PInt xs1, PInt xs2, PInt ys1, PInt ys2, PInt ys3] + --+ -- Note that references to flatdata arrays [0, 1, 2] in arr1 need to be offset+ -- by 2 (which is length arr0.psegdata) to refer to the same flat data arrays+ -- in the result.+ -- + -- We encode these offsets in the psrcoffset vector:+ -- psrcoffset : [0, 2]+ --+ -- TODO: cleanup pnested projections+ -- use getSegOfUVSegd like in indexlPR+ --+ {-# NOINLINE extractssPR #-}+ extractssPR (PNesteds arrs) ussegd+ = let + + segsrcs = U.sourcesOfSSegd ussegd+ seglens = U.lengthsOfSSegd ussegd++ vsegidss = V.map (U.takeVSegidsOfVSegd . pnested_uvsegd) arrs+ vsegids_src = U.extracts_nss ussegd vsegidss+ srcids' = U.replicate_s (U.lengthsToSegd seglens) segsrcs++ -- See Note: psrcoffset+ psrcoffset = V.prescanl (+) 0 + $ V.map (lengthdPR . pnested_psegdata) arrs++ -- Unpack the lens and srcids arrays so we don't need to + -- go though all the segment descriptors each time.+ !arrs_pseglens = V.map (U.lengthsOfSSegd . U.takeSSegdOfVSegd . pnested_uvsegd) arrs+ !arrs_psegstarts = V.map (U.startsOfSSegd . U.takeSSegdOfVSegd . pnested_uvsegd) arrs+ !arrs_psegsrcids = V.map (U.sourcesOfSSegd . U.takeSSegdOfVSegd . pnested_uvsegd) arrs++ !here' = "extractssPR[Nested]"+ -- Function to get one element of the result.+ {-# INLINE get #-}+ get srcid vsegid+ = let !pseglen = U.index here' (arrs_pseglens `V.unsafeIndex` srcid) vsegid+ !psegstart = U.index here' (arrs_psegstarts `V.unsafeIndex` srcid) vsegid+ !psegsrcid = (U.index here' (arrs_psegsrcids `V.unsafeIndex` srcid) vsegid)+ + (psrcoffset `V.unsafeIndex` srcid)+ in (pseglen, psegstart, psegsrcid)+ + (pseglens', psegstarts', psegsrcs')+ = U.unzip3 $ U.zipWith get srcids' vsegids_src++ -- All flat data arrays in the sources go into the result.+ pdatas' = fromVectordPR+ $ V.concat $ V.toList + $ V.map (toVectordPR . pnested_psegdata) arrs+ + -- Build the result segment descriptor.+ segd' = U.lengthsToSegd pseglens'+ vsegd' = U.promoteSSegdToVSegd+ $ U.mkSSegd psegstarts' psegsrcs' segd'+ + flat' = extractvs_delay pdatas' vsegd'+ + in PNested vsegd' pdatas' segd' flat'+++ {-# INLINE_PDATA extractvsPR #-}+ extractvsPR pdatas vsegd+ = extractssPR pdatas (U.unsafeDemoteToSSegdOfVSegd vsegd)++ + -- Pack and Combine -------------------------------------+ -- Pack the vsegids to determine which of the vsegs are present in the result.+ -- eg tags: [0 1 1 1 0 0 0 0 1 0 0 0 0 1 0 1 0 1 1] tag = 1+ -- vsegids: [0 0 1 1 2 2 2 2 3 3 4 4 4 5 5 5 5 6 6]+ -- => vsegids_packed: [ 0 1 1 3 5 5 6 6]+ -- + {-# INLINE_PDATA packByTagPR #-}+ packByTagPR (PNested vsegd pdatas _ _) tags tag+ = let vsegd' = U.updateVSegsOfVSegd (\vsegids -> U.packByTag vsegids tags tag) vsegd+ segd' = U.unsafeDemoteToSegdOfVSegd vsegd'+ flat' = extractvs_delay pdatas vsegd'+ in PNested vsegd' pdatas segd' flat'+++ -- Combine nested arrays by combining the segment descriptors, + -- and putting all physical arrays in the result.+ {-# INLINE_PDATA combine2PR #-}+ combine2PR sel2 (PNested vsegd1 pdatas1 _ _) (PNested vsegd2 pdatas2 _ _)+ = let vsegd' = U.combine2VSegd sel2 + vsegd1 (lengthdPR pdatas1)+ vsegd2 (lengthdPR pdatas2)++ pdatas' = appenddPR pdatas1 pdatas2+ segd' = U.unsafeDemoteToSegdOfVSegd vsegd'+ flat' = extractvs_delay pdatas' vsegd'+ in PNested vsegd' pdatas' segd' flat'+++ -- Conversions ----------------------+ {-# NOINLINE fromVectorPR #-}+ fromVectorPR xx+ | V.length xx == 0 = emptyPR+ | otherwise+ = let segd = U.lengthsToSegd $ U.fromList $ V.toList $ V.map PA.length xx+ vsegd = U.promoteSegdToVSegd segd+ pdata = V.foldl1 appendPR $ V.map takeData xx+ pdatas = singletondPR pdata+ flat = extractvs_delay pdatas vsegd+ in PNested vsegd pdatas segd flat+++ {-# NOINLINE toVectorPR #-}+ toVectorPR arr@(PNested vsegd _ _ _)+ = let len = U.length $ U.takeVSegidsOfVSegd vsegd+ in V.generate len (indexPR arr)+++ -- PData --------------------------------------+ {-# INLINE_PDATA emptydPR #-}+ emptydPR + = PNesteds $ V.empty+ + {-# INLINE_PDATA singletondPR #-}+ singletondPR pdata+ = PNesteds $ V.singleton pdata++ {-# INLINE_PDATA lengthdPR #-}+ lengthdPR (PNesteds vec)+ = V.length vec+ + {-# INLINE_PDATA indexdPR #-}+ indexdPR (PNesteds vec) ix+ = vec `V.unsafeIndex` ix++ {-# INLINE_PDATA appenddPR #-}+ appenddPR (PNesteds xs) (PNesteds ys)+ = PNesteds $ xs V.++ ys++ {-# INLINE_PDATA fromVectordPR #-}+ fromVectordPR vec+ = PNesteds vec+ + {-# INLINE_PDATA toVectordPR #-}+ toVectordPR (PNesteds vec)+ = vec+++-------------------------------------------------------------------------------+-- | Wrapper for extracts that is NOT INLINED.+--+-- This is experimental, used to initialise the pnested_flat field+-- of a nested array. It's' marked at NOINLINE to avoid code explosion.+---+-- TODO: at a later fusion stage we could rewrite this to an INLINED+-- version to generate core for the occurrences we actually use.+extractvs_delay :: PR a => PDatas a -> U.VSegd -> PData a+extractvs_delay pdatas vsegd+ = extractvsPR pdatas vsegd+{-# NOINLINE extractvs_delay #-}+-- NOINLINE because we don't want a copy of the extracts loop to +-- be generated at the use site.+++------------------------------------------------------------------------------+-- | O(len result). Lifted indexing+indexlPR :: PR a => PData (PArray a) -> PData Int -> PData a+indexlPR (PNested vsegd pdatas _ _) (PInt ixs)+ = indexvsPR pdatas vsegd + (U.zip (U.enumFromTo 0 (U.length ixs - 1))+ ixs)+{-# INLINE_PDATA indexlPR #-}+++-- concatlPR ------------------------------------------------------------------+-- | Lifted concatenation.+-- +-- Concatenate all the arrays in a triply nested array.+--+concatlPR :: PR a => PData (PArray (PArray a)) -> PData (PArray a)+concatlPR arr+ = let (segd1, darr1) = flattenPR arr+ (segd2, darr2) = flattenPR darr1++ -- Generate indices for the result array+ -- See Note: Empty Arrays on End.+ ixs1 = U.indicesSegd segd1+ ixs2 = U.indicesSegd segd2+ len2 = U.length ixs2++ ixs' = U.map (\ix -> if ix >= len2+ then 0+ else U.index "concatlPR" ixs2 ix)+ $ ixs1++ segd' = U.mkSegd (U.sum_s segd1 (U.lengthsSegd segd2))+ ixs'+ (U.elementsSegd segd2)++ vsegd' = U.promoteSegdToVSegd segd'+ pdatas' = singletondPR flat'+ flat' = darr2++ in PNested vsegd' pdatas' segd' flat'+{-# INLINE_PDATA concatlPR #-}++-- [Note: Empty Arrays on End]+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~+--+-- There is a tedious edge case when the last segment in the nested+-- array has length 0. For example:+--+-- concatl [ [[1, 2, 3] [4, 5, 6]] [] ]+-- +-- After the calls to flattenPR we get:+-- segd1: lengths1 = [ 2 0 ]+-- indices1 = [ 0 2 ]++-- segd2: lengths2 = [ 3 3 ]+-- indices2 = [ 0 3 ]+-- +-- The problem is that the last element of 'indices1' points off the end+-- of 'indices2' so we can't use use 'backpermute' as we'd like to:+-- ixs' = (U.bpermute (U.indicesSegd segd2) (U.indicesSegd segd1)) +-- Instead, we have to explicitly check for the out-of-bounds condition.+--+-- TODO: We want a faster way of doing this, that doesn't require the +-- test for every element.++++-- unconcatPR -----------------------------------------------------------------+-- | Build a nested array given a single flat data vector, +-- and a template nested array that defines the segmentation.++-- Although the template nested array may be using vsegids to describe+-- internal sharing, the provided data array has manifest elements+-- for every segment. Because of this we need flatten out the virtual+-- segmentation of the template array.+--+unconcatPR :: PR b => PData (PArray a) -> PData b -> PData (PArray b)+unconcatPR (PNested _ _ segd _) pdata+ = {-# SCC "unconcatPD" #-}+ let -- Demote the vsegd to a manifest vsegd so it contains all the segment+ -- lengths individually without going through the vsegids.+ -- Then Rebuild the vsegd based on the manifest vsegd. + -- The vsegids will be just [0..len-1], but this field is constructed+ -- lazilly and consumers aren't required to demand it.+ vsegd' = U.promoteSegdToVSegd segd+ pdatas' = singletondPR pdata+ in PNested vsegd' pdatas' segd pdata+{-# INLINE_PDATA unconcatPR #-}+++-- appendlPR ------------------------------------------------------------------+-- | Lifted append.+-- Both arrays must contain the same number of elements.+appendlPR :: PR a => PData (PArray a) -> PData (PArray a) -> PData (PArray a)+appendlPR arr1 arr2+ = let (segd1, darr1) = flattenPR arr1+ (segd2, darr2) = flattenPR arr2+ segd' = U.plusSegd segd1 segd2+ vsegd' = U.promoteSegdToVSegd segd'++ flat' = appendsPR segd' segd1 darr1 segd2 darr2+ pdatas' = singletondPR flat'+ in PNested vsegd' pdatas' segd' flat'+{-# INLINE_PDATA appendlPR #-}+++-- slicelPR -------------------------------------------------------------------+-- | Extract some slices from some arrays.+--+-- All three parameters must have the same length, and we take+-- one slice from each of the source arrays. ++-- TODO: cleanup pnested projections+slicelPR+ :: PR a+ => PData Int -- ^ Starting indices of slices.+ -> PData Int -- ^ Lengths of slices.+ -> PData (PArray a) -- ^ Arrays to slice.+ -> PData (PArray a)++slicelPR (PInt sliceStarts) (PInt sliceLens)+ (PNested vsegd pdatas _segd _flat)+ = let -- Build the new Segd+ segd' = U.lengthsToSegd sliceLens++ -- Build the new SSegd+ vsegids = U.takeVSegidsOfVSegd vsegd+ ssegd = U.takeSSegdOfVSegd vsegd+ psegstarts = U.startsOfSSegd ssegd+ psegsrcs = U.sourcesOfSSegd ssegd++ psegstarts' = U.zipWith (+) (U.bpermute psegstarts vsegids) sliceStarts+ psegsources' = U.bpermute psegsrcs vsegids+ ssegd' = U.mkSSegd psegstarts' psegsources' segd'++ -- Promote SSegd to a VSegd+ vsegd' = U.promoteSSegdToVSegd ssegd'+ flat' = extractvs_delay pdatas vsegd'++ in PNested vsegd' pdatas segd' flat'+{-# NOINLINE slicelPR #-}+-- NOINLINE because it won't fuse with anything.+-- The operation is also entierly on the segment descriptor, so we don't +-- need to inline it to specialise it for the element type.+++-- Testing --------------------------------------------------------------------+-- TODO: slurp debug flag from base +validBool :: String -> Bool -> Bool+validBool str b+ = if b then True + else error $ "validBool check failed -- " ++ str+++-- Pretty ---------------------------------------------------------------------+deriving instance (Show (PDatas a), Show (PData a)) => Show (PDatas (PArray a))+deriving instance (Show (PDatas a), Show (PData a)) => Show (PData (PArray a))++
+ Data/Array/Parallel/PArray/PData/Sum2.hs view
@@ -0,0 +1,516 @@+{-# OPTIONS_HADDOCK hide #-}+{-# LANGUAGE CPP #-}+#include "fusion-phases.h"++-- | PR instance for Sum2.+module Data.Array.Parallel.PArray.PData.Sum2 + ( PData(..)+ , PDatas(..)+ , Sels2, lengthSels2)+where+import Data.Array.Parallel.PArray.PData.Int ()+import Data.Array.Parallel.PArray.PData.Base+import Data.Array.Parallel.PArray.PData.Nested+import Data.Array.Parallel.PArray.Types+import Data.Array.Parallel.Base (intToTag)+import Data.Array.Parallel.Unlifted as U+import qualified Data.Vector as V+import Text.PrettyPrint+import Prelude as P+import Data.Array.Parallel.Pretty++-------------------------------------------------------------------------------+data instance PData (Sum2 a b)+ = PSum2 U.Sel2+ (PData a)+ (PData b)+++data instance PDatas (Sum2 a b)+ = PSum2s Sels2+ (PDatas a)+ (PDatas b)++type Sels2+ = V.Vector U.Sel2++lengthSels2 :: Sels2 -> Int+lengthSels2 sels2+ = V.length sels2++-- PR -------------------------------------------------------------------------+instance (PR a, PR b) => PR (Sum2 a b) where++ {-# NOINLINE validPR #-}+ validPR _+ = True++ {-# NOINLINE similarPR #-}+ similarPR x y+ = case (x, y) of+ (Alt2_1 x', Alt2_1 y') -> similarPR x' y'+ (Alt2_2 x', Alt2_2 y') -> similarPR x' y'+ _ -> False++ {-# NOINLINE nfPR #-}+ nfPR (PSum2 sel xs ys)+ = sel `seq` nfPR xs `seq` nfPR ys `seq` ()++ {-# NOINLINE coversPR #-}+ coversPR weak (PSum2 sel _ _) ix+ | weak = ix <= U.length (U.tagsSel2 sel)+ | otherwise = ix < U.length (U.tagsSel2 sel)++ + {-# NOINLINE pprpPR #-}+ pprpPR xx+ = case xx of+ Alt2_1 x -> text "Alt2_1" <+> parens (pprpPR x)+ Alt2_2 y -> text "Alt2_2" <+> parens (pprpPR y)+++ {-# NOINLINE pprpDataPR #-}+ pprpDataPR (PSum2 sel pdatas1 pdatas2)+ = text "PSum2"+ $+$ (nest 4 $ vcat+ [ pprp sel+ , text "ALTS0: " <+> pprp pdatas1+ , text "ALTS1: " <+> pprp pdatas2])+++ -- Constructors -------------------------------+ {-# INLINE_PDATA emptyPR #-}+ emptyPR+ = PSum2 (U.mkSel2 U.empty U.empty 0 0 (U.mkSelRep2 U.empty)) emptyPR emptyPR+++ {-# INLINE_PDATA replicatePR #-}+ replicatePR n aa+ = case aa of+ Alt2_1 x + -> PSum2 (U.mkSel2 (U.replicate n 0)+ (U.enumFromStepLen 0 1 n)+ n 0+ (U.mkSelRep2 (U.replicate n 0)))+ (replicatePR n x)+ emptyPR+ + Alt2_2 x+ -> PSum2 (U.mkSel2 (U.replicate n 1)+ (U.enumFromStepLen 0 1 n)+ 0 n+ (U.mkSelRep2 (U.replicate n 1)))+ emptyPR+ (replicatePR n x) ++ + {-# INLINE_PDATA replicatesPR #-}+ replicatesPR segd (PSum2 sel as bs)+ = let tags = U.tagsSel2 sel+ tags' = U.replicate_s segd tags+ sel' = U.tagsToSel2 tags'++ lens = U.lengthsSegd segd+ asegd = U.lengthsToSegd (U.packByTag lens tags 0)+ bsegd = U.lengthsToSegd (U.packByTag lens tags 1)++ as' = replicatesPR asegd as+ bs' = replicatesPR bsegd bs+ in PSum2 sel' as' bs'+ ++ {-# INLINE_PDATA appendPR #-}+ appendPR (PSum2 sel1 as1 bs1)+ (PSum2 sel2 as2 bs2)+ = let !sel = U.tagsToSel2 $ U.tagsSel2 sel1 U.+:+ U.tagsSel2 sel2+ as = appendPR as1 as2+ bs = appendPR bs1 bs2+ in PSum2 sel as bs+ ++ -- Projections --------------------------------+ {-# INLINE_PDATA lengthPR #-}+ lengthPR (PSum2 sel _ _)+ = U.length $ tagsSel2 sel+ + + {-# INLINE_PDATA indexPR #-}+ indexPR (PSum2 sel as bs) i+ = let !k = U.index "indexPR[Sum2]" (U.indicesSel2 sel) i+ in case U.index "indexPR[Sum2]" (U.tagsSel2 sel) i of+ 0 -> Alt2_1 (indexPR as k)+ _ -> Alt2_2 (indexPR bs k)++ {-# INLINE_PDATA indexsPR #-}+ indexsPR (PSum2s sels ass bss) srcixs+ = let (srcids, ixs) = U.unzip srcixs+ + getFlagIndex !src !ix+ = let !sel = V.unsafeIndex sels src+ !elemFlag = U.index "indexPR[Sum2]" (U.tagsSel2 sel) ix+ !elemIndex = U.index "indexPR[Sum2]" (U.indicesSel2 sel) ix+ in (elemFlag, elemIndex)+ + (flags', indices')+ = U.unzip $ U.zipWith getFlagIndex srcids ixs ++ sel' = U.tagsToSel2 flags' + asIndices = U.packByTag indices' flags' 0+ bsIndices = U.packByTag indices' flags' 1+ + as' = indexsPR ass (U.zip srcids asIndices) + bs' = indexsPR bss (U.zip srcids bsIndices)++ in PSum2 sel' as' bs'+++ -- extract / extracts + -- Extract a range of elements from an array of Sum2s.+ -- Example:+ -- arr: [L 20, R 30, L 40, R 50, R 60, R 70, L 80, R 90, L 100]+ -- -----------------------------+ -- Sel2:+ -- TAGS: [0 1 0 1 1 1 0 1 0]+ -- INDICES: [0 0 1 1 2 3 2 4 3]+ -- ALTS0: PInt [20 40 80 100]+ -- ALTS1: PInt [30 50 60 70 90]+ --+ -- Goal: extract arr 2 5+ -- = [L 40, R 50, R 60, R 70, L 80]+ -- Sel2: + -- TAGS: [0 1 1 1 0]+ -- INDICES: [0 0 1 2 1]+ -- ALTS0: PInt [40 80]+ -- ALTS1: PInt [50 60 70]+ -- + {-# NOINLINE extractPR #-}+ extractPR (PSum2 sel as bs) start len+ = let + -- Extract the tags of the result elements,+ -- and rebuild the result selector indices based on these tags.+ -- This is the selelector for the result array.+ -- TAGS: [0 1 1 1 0]+ -- INDICES: [0 0 1 2 1]+ tags' = U.extract (U.tagsSel2 sel) start len+ sel' = U.tagsToSel2 tags'+ + -- Extract the indices of the data elements that we want.+ -- These are the indices of the elements in their source arrays.+ -- INDICES: [1 1 2 3 2]+ indices' = U.extract (U.indicesSel2 sel) start len++ -- Build maps of which source index to get the data for each ALT array.+ -- indices0: [1 2]+ -- indices1: [1 2 3]+ indices0 = U.packByTag indices' tags' 0+ indices1 = U.packByTag indices' tags' 1+ + -- Copy source data into new ALT arrays.+ -- as: [40 80]+ -- bs: [50 60 70]+ as' = bpermutePR as indices0+ bs' = bpermutePR bs indices1++ in PSum2 sel' as' bs'++ + -- Extract several ranges of elements form some arrays of Sum2s.+ -- Example:+ -- arrs: 0: [L 20, R 30, L 40]+ -- ----------1 ----3+ -- 1: [R 50, R 60, R 70, L 80, R 90, L 100]+ -- ----4 ----------------0 -----------2+ -- + -- Sel2+ -- 0 TAGS: [0 1 0]+ -- INDICES: [0 0 1]+ -- -------1 ----3+ -- ALTS0: [20 40]+ -- ALTS1: [30]+ --+ -- 1 TAGS: [1 1 1 0 1 0]+ -- INDICES: [0 1 2 0 3 1]+ -- ----4 --------------0 --------2+ -- ALTS0 [80 100]+ -- ALTS1 [50 60 70 90]+ --+ -- Goal: extract arrs ssegd+ -- => [R 60, R 70, L 80, L 20, R 30, R 90, L 100, L 40, R 50]+ -- ----------------0 ----------1 -----------2 ----3 ----4+ --+ -- Sel2:+ -- TAGS: [1 1 0 0 1 1 0 0 1]+ -- INDICES: [0 1 0 1 2 3 2 3 4] + -- ALTS0: [80 20 100 40]+ -- ALTS1: [60 70 30 90 50]+ --+ -- ssegd:+ -- SRCIDS: [1 0 1 0 1]+ -- STARTS: [1 0 4 2 0]+ -- LENGTHS: [3 2 2 1 1]+ -- + {-# NOINLINE extractssPR #-}+ extractssPR (PSum2s sels pdatas0 pdatas1) ssegd+ = let + tagss = V.map U.tagsSel2 sels++ -- Extract the tags of the result elements,+ -- and rebuild the result selector indices based on these tags.+ -- tags' = [1 1 0 0 1 1 0 0 1]+ -- sel' = [0 1 0 1 2 3 2 3 4] + tags' = U.extracts_nss ssegd tagss+ sel' = U.tagsToSel2 tags'++ -- Extract the indices of the data elements we want.+ -- These are the indices of the elements in their source arrays.+ -- (result) [R 60, R 70, L 80, L 20, R 30, R 90, L 100, L 40, R 50]+ -- ----------------0 ----------1 -----------2 ----3 ----4+ -- indices' = [ 1 2 0 0 0 3 1 1 0 ]+ indices' = U.extracts_nss ssegd (V.map U.indicesSel2 sels)++ -- Count the number of L and R elements for each segment,+ -- then scan them to produce the starting index of each segment in the+ -- result alt data.++ -- ALTS0: [80 20 100 40 ] (result)+ -- --0 --1 --2 --3 .4 (segs)+ -- lens0 = [1 1 1 1 0 ]+ -- indices0 = [0 1 2 3 4 ]+ + -- ALTS1: [60 70 30 90 50] (result)+ -- ------0 --1 --2 .3 --4 (segs)+ -- lens1 = [2 1 1 0 1 ]+ -- indices1 = [0 2 3 3 4 ]+ + lens0 = U.count_ss ssegd tagss 0+ indices0 = U.scan (+) 0 lens0++ lens1 = U.count_ss ssegd tagss 1+ indices1 = U.scan (+) 0 lens1++ -- For each segment in the result alt data, get its starting index in+ -- the original alt array.+ -- + -- TODO: We're doing this by getting the index of EVERY result eleement+ -- as it is in the original array original array, then just selecting+ -- the indices corresponding to the start of each segment. If the last+ -- segment has length 0, then we get an index overflow problem because+ -- the last element in the indices array doesn't point to real data.+ -- There might be a better way to do this that doesn't require copying+ -- all indices, and doesn't need a bounds check.+ -- + + -- indices0 = [ 0 1 2 3 4 ] (from above)+ -- sel0 = [ 0 0 1 1 ] -- here, we've only got starting indices+ -- sel0_len = 4 -- for 4 segs, but there are 5 segs in total.+ -- starts0 = [ 0 0 1 1 0 ]+ sel0 = U.packByTag indices' tags' 0+ sel0_len = U.length sel0+ starts0 = U.map (\i -> if i >= sel0_len+ then 0 + else U.index "extractssPR[Sum2]" sel0 i)+ indices0++ -- indices1 = [ 0 2 3 3 4 ] (from above)+ -- sel1 = [ 1 2 0 3 0 ]+ -- sel1_len = 5+ -- starts1 = [ 1 0 3 3 0 ]+ sel1 = U.packByTag indices' tags' 1+ sel1_len = U.length sel1+ starts1 = U.map (\i -> if i >= sel1_len+ then 0+ else U.index "extractssPR[Sum2]" sel1 i)+ indices1++ -- Extract the final alts data:+ -- sources = [ 1 0 1 0 1 ] (from above)+ -- starts0 = [ 0 0 1 1 0 ] (from above)+ -- starts1 = [ 1 0 3 3 0 ] (from above)+ -- lens0 = [ 1 1 1 1 0 ] (from above)+ -- lens1 = [ 2 1 1 0 1 ] (from above)++ -- (source data)+ -- 0: ALTS0: [20 40]+ -- --1 --3+ -- ALTS1: [30]+ -- --1 .3 (no alt1 data for seg 3)+ -- + -- 1: ALTS0: [80 100]+ -- --0 ---2 .4 (no alt0 data for seg 4)+ -- ALTS1: [50 60 70 90]+ -- --4 -----0 --2++ -- (result data)+ -- ALTS0: [80 20 100 40 ]+ -- ALTS1: [60 70 30 90 50]++ pdata0 = extractssPR pdatas0 + $ U.mkSSegd starts0+ (U.sourcesOfSSegd ssegd)+ (U.lengthsToSegd lens0)++ pdata1 = extractssPR pdatas1 + $ U.mkSSegd starts1 + (U.sourcesOfSSegd ssegd)+ (U.lengthsToSegd lens1)++ in {- trace (render $ vcat + [ text "tags' = " <> pprp tags'+ , text ""+ , text "lens0 = " <> pprp lens0+ , text "selStarts0 = " <> pprp selStarts0+ , text "sel0 = " <> pprp sel0+ , text "starts0 = " <> pprp starts0+ , text ""+ , text "lens1 = " <> pprp lens1+ , text "selStarts1 = " <> pprp selStarts1+ , text "sel1 = " <> pprp sel1+ , text ""+ , text "sources = " <> pprp sources+ , text "selindices' = " <> pprp selIndices'+ , text ""]) $ -}+ PSum2 sel' pdata0 pdata1++ {-# INLINE_PDATA extractvsPR #-}+ extractvsPR pdatas vsegd+ = extractssPR pdatas (unsafeDemoteToSSegdOfVSegd vsegd)+++ -- Pack and Combine ---------------------------++ -- Select the elements of an array that match the given tag.+ -- Example:+ -- arr = [L 20, R 30, L 40, L 50, R 60, L 70, R 80, L 90]+ -- flags = [0 1 0 0 1 0 1 0]+ -- indices = [0 0 1 2 1 3 2 4]+ -- as = [20 40 50 70 90]+ -- bs = [30 60 80]+ --+ -- tags = [1 1 0 1 0 0 1 0]+ -- result = [L 20, R 30, L 50, R 80]+ -- flags' = [0 1 0 1]+ -- as' = [20 50]+ -- as' = [30 80]+ --+ {-# NOINLINE packByTagPR #-}+ packByTagPR (PSum2 sel as bs) tags tag+ = let flags = U.tagsSel2 sel++ -- Make the flags of the result+ -- flags' = [0 1 0 1]+ flags' = U.packByTag flags tags (intToTag tag)+ sel' = U.tagsToSel2 flags'++ -- Map the tags array onto the data for each alternative.+ -- This tells us what of the alt data we want to keep.+ -- atags = [ 1 0 1 0 0 ]+ -- btags = [ 1 0 1 ]+ atags = U.packByTag tags flags 0+ btags = U.packByTag tags flags 1++ -- Now pack the alt data using the above tag arrays+ -- as' = [ 20 50 ]+ -- bs' = [ 30 80 ]+ as' = packByTagPR as atags tag+ bs' = packByTagPR bs btags tag+ in PSum2 sel' as' bs'+ + + {-# NOINLINE combine2PR #-}+ combine2PR sel (PSum2 sel1 as1 bs1) (PSum2 sel2 as2 bs2)+ = let tags = U.tagsSel2 sel+ tags' = U.combine2 (U.tagsSel2 sel) (U.repSel2 sel)+ (U.tagsSel2 sel1) (U.tagsSel2 sel2)+ sel' = U.tagsToSel2 tags'++ asel = U.tagsToSel2 (U.packByTag tags tags' 0)+ bsel = U.tagsToSel2 (U.packByTag tags tags' 1)++ as = combine2PR asel as1 as2+ bs = combine2PR bsel bs1 bs2+ in PSum2 sel' as bs+++ -- Conversions --------------------------------+ -- TODO: fix rubbish via-lists filtering. + {-# NOINLINE fromVectorPR #-}+ fromVectorPR vec+ = let tags = V.convert $ V.map tagOfSum2 vec+ sel2 = U.tagsToSel2 tags+ as' = fromVectorPR $ V.fromList $ [x | Alt2_1 x <- V.toList vec]+ bs' = fromVectorPR $ V.fromList $ [x | Alt2_2 x <- V.toList vec]+ + in PSum2 sel2 as' bs'+ ++ {-# NOINLINE toVectorPR #-}+ toVectorPR pdata@(PSum2 sel _ _)+ = let len = U.length $ U.tagsSel2 sel+ in if len == 0+ then V.empty+ else V.map (indexPR pdata) + $ V.enumFromTo 0 (len - 1)+++ -- PDatas -------------------------------------+ {-# INLINE_PDATA emptydPR #-}+ emptydPR + = PSum2s V.empty emptydPR emptydPR+++ {-# INLINE_PDATA singletondPR #-}+ singletondPR (PSum2 sel2 xs ys)+ = PSum2s (V.singleton sel2)+ (singletondPR xs)+ (singletondPR ys)+++ {-# INLINE_PDATA lengthdPR #-}+ lengthdPR (PSum2s sel2s _ _)+ = V.length sel2s+++ {-# INLINE_PDATA indexdPR #-}+ indexdPR (PSum2s sel2s xss yss) ix+ = PSum2 (sel2s `V.unsafeIndex` ix)+ (indexdPR xss ix)+ (indexdPR yss ix)+++ {-# INLINE_PDATA appenddPR #-}+ appenddPR (PSum2s sels1 xss1 yss1)+ (PSum2s sels2 xss2 yss2)+ = PSum2s (sels1 V.++ sels2)+ (xss1 `appenddPR` xss2)+ (yss1 `appenddPR` yss2)+++ -- TODO: fix rubbish via-lists conversion.+ {-# NOINLINE fromVectordPR #-}+ fromVectordPR vec+ = let (sels, pdatas1, pdatas2) + = P.unzip3 + $ [ (sel, pdata1, pdata2) + | PSum2 sel pdata1 pdata2 <- V.toList vec]+ in PSum2s (V.fromList sels)+ (fromVectordPR $ V.fromList pdatas1)+ (fromVectordPR $ V.fromList pdatas2)+ ++ {-# NOINLINE toVectordPR #-}+ toVectordPR (PSum2s sels pdatas1 pdatas2)+ = let vecs1 = toVectordPR pdatas1+ vecs2 = toVectordPR pdatas2+ + in V.zipWith3 PSum2 sels vecs1 vecs2+++-- Pretty ---------------------------------------------------------------------+instance PprPhysical U.Sel2 where+ pprp sel2+ = text "Sel2"+ $+$ (nest 4 $ vcat+ [ text "TAGS: " <+> text (show $ U.toList $ U.tagsSel2 sel2)+ , text "INDICES:" <+> text (show $ U.toList $ U.indicesSel2 sel2)])++
+ Data/Array/Parallel/PArray/PData/Tuple2.hs view
@@ -0,0 +1,251 @@+{-# OPTIONS_HADDOCK hide #-}+{-# LANGUAGE CPP #-}+#include "fusion-phases.h"++-- | PR instance for tuples.+module Data.Array.Parallel.PArray.PData.Tuple2+ ( PData(..), PDatas(..)+ , zipPD+ , ziplPR+ , unzipPD+ , unziplPD)+where+import Data.Array.Parallel.Pretty+import Data.Array.Parallel.PArray.PData.Base+import Data.Array.Parallel.PArray.PData.Nested+import GHC.Exts+import Prelude hiding (zip, unzip)+import qualified Data.Vector as V+import qualified Prelude as P+import qualified Data.Array.Parallel.Unlifted as U++-------------------------------------------------------------------------------+data instance PData (a, b)+ = PTuple2 (PData a) (PData b)++data instance PDatas (a, b)+ = PTuple2s (PDatas a) (PDatas b)+++-- PR -------------------------------------------------------------------------+instance (PR a, PR b) => PR (a, b) where++ {-# NOINLINE validPR #-}+ validPR (PTuple2 xs ys)+ = validPR xs && validPR ys+++ {-# NOINLINE nfPR #-}+ nfPR (PTuple2 arr1 arr2)+ = nfPR arr1 `seq` nfPR arr2 `seq` ()+++ {-# NOINLINE similarPR #-}+ similarPR (x1, y1) (x2, y2)+ = similarPR x1 x2+ && similarPR y1 y2+++ {-# NOINLINE coversPR #-}+ coversPR weak (PTuple2 arr1 arr2) ix+ = coversPR weak arr1 ix+ && coversPR weak arr2 ix++ {-# NOINLINE pprpPR #-}+ pprpPR (x, y)+ = text "Tuple2 " <> vcat [pprpPR x, pprpPR y]+ ++ {-# NOINLINE pprpDataPR #-}+ pprpDataPR (PTuple2 xs ys)+ = text "PTuple2 " <> vcat [pprpDataPR xs, pprpDataPR ys]++ -- Constructors -------------------------------+ {-# INLINE_PDATA emptyPR #-}+ emptyPR+ = PTuple2 emptyPR emptyPR+++ {-# INLINE_PDATA replicatePR #-}+ replicatePR len (x, y)+ = PTuple2 (replicatePR len x)+ (replicatePR len y)+++ {-# INLINE_PDATA replicatesPR #-}+ replicatesPR lens (PTuple2 arr1 arr2)+ = PTuple2 (replicatesPR lens arr1)+ (replicatesPR lens arr2)+++ {-# INLINE_PDATA appendPR #-}+ appendPR (PTuple2 arr11 arr12) (PTuple2 arr21 arr22)+ = PTuple2 (arr11 `appendPR` arr21)+ (arr12 `appendPR` arr22)+++ {-# INLINE_PDATA appendsPR #-}+ appendsPR segdResult segd1 (PTuple2 arrs11 arrs12) segd2 (PTuple2 arrs21 arrs22)+ = PTuple2 (appendsPR segdResult segd1 arrs11 segd2 arrs21)+ (appendsPR segdResult segd1 arrs12 segd2 arrs22)+++ -- Projections ---------------------------------+ {-# INLINE_PDATA lengthPR #-}+ lengthPR (PTuple2 arr1 _) + = lengthPR arr1+ + {-# INLINE_PDATA indexPR #-}+ indexPR (PTuple2 arr1 arr2) ix+ = (indexPR arr1 ix, indexPR arr2 ix)++ {-# INLINE_PDATA indexsPR #-}+ indexsPR (PTuple2s xs ys) srcixs+ = PTuple2 (indexsPR xs srcixs)+ (indexsPR ys srcixs)++ {-# INLINE_PDATA indexvsPR #-}+ indexvsPR (PTuple2s xs ys) vsegd srcixs+ = PTuple2 (indexvsPR xs vsegd srcixs)+ (indexvsPR ys vsegd srcixs)++ {-# INLINE_PDATA extractPR #-}+ extractPR (PTuple2 arr1 arr2) start len+ = PTuple2 (extractPR arr1 start len) + (extractPR arr2 start len)++ {-# INLINE_PDATA extractssPR #-}+ extractssPR (PTuple2s xs ys) ussegd+ = PTuple2 (extractssPR xs ussegd)+ (extractssPR ys ussegd)++ {-# INLINE_PDATA extractvsPR #-}+ extractvsPR (PTuple2s xs ys) uvsegd+ = PTuple2 (extractvsPR xs uvsegd)+ (extractvsPR ys uvsegd)+++ -- Pack and Combine ---------------------------+ {-# INLINE_PDATA packByTagPR #-}+ packByTagPR (PTuple2 arr1 arr2) tags tag+ = PTuple2 (packByTagPR arr1 tags tag)+ (packByTagPR arr2 tags tag)++ {-# INLINE_PDATA combine2PR #-}+ combine2PR sel (PTuple2 xs1 ys1) (PTuple2 xs2 ys2)+ = PTuple2 (combine2PR sel xs1 xs2)+ (combine2PR sel ys1 ys2)+++ -- Conversions --------------------------------+ {-# NOINLINE fromVectorPR #-}+ fromVectorPR vec+ = let (xs, ys) = V.unzip vec+ in PTuple2 (fromVectorPR xs)+ (fromVectorPR ys)++ {-# NOINLINE toVectorPR #-}+ toVectorPR (PTuple2 xs ys)+ = V.zip (toVectorPR xs)+ (toVectorPR ys)+++ -- PData --------------------------------------+ {-# INLINE_PDATA emptydPR #-}+ emptydPR + = PTuple2s emptydPR+ emptydPR++ + {-# INLINE_PDATA singletondPR #-}+ singletondPR (PTuple2 x y)+ = PTuple2s (singletondPR x)+ (singletondPR y)+++ {-# INLINE_PDATA lengthdPR #-}+ lengthdPR (PTuple2s xs _)+ = lengthdPR xs+ + + {-# INLINE_PDATA indexdPR #-}+ indexdPR (PTuple2s xs ys) i+ = PTuple2 (indexdPR xs i)+ (indexdPR ys i)++ + {-# INLINE_PDATA appenddPR #-}+ appenddPR (PTuple2s xs1 ys1) (PTuple2s xs2 ys2)+ = PTuple2s (appenddPR xs1 xs2)+ (appenddPR ys1 ys2)+ ++ {-# NOINLINE fromVectordPR #-}+ fromVectordPR vec+ = let (xss, yss) = V.unzip $ V.map (\(PTuple2 xs ys) -> (xs, ys)) vec+ in PTuple2s (fromVectordPR xss)+ (fromVectordPR yss)+++ {-# NOINLINE toVectordPR #-}+ toVectordPR (PTuple2s pdatas1 pdatas2)+ = V.zipWith PTuple2+ (toVectordPR pdatas1)+ (toVectordPR pdatas2)+++-- PD Functions ---------------------------------------------------------------+-- These work on PData arrays of tuples, but don't need a PA or PR dictionary++-- | O(1). Zip a pair of arrays into an array of pairs.+zipPD :: PData a -> PData b -> PData (a, b)+zipPD = PTuple2+{-# INLINE_PA zipPD #-}+++-- | Lifted zip.+ziplPR :: (PR a, PR b) => PData (PArray a) -> PData (PArray b) -> PData (PArray (a, b))+ziplPR arr1 arr2+ = let -- We need to flatten the data here because we can't guarantee+ -- that the vsegds of both arrays have the same form.+ -- One of the arrays may have been created with replicate, and + -- thus has internal sharing, while the other does not.+ (segd1, pdata1) = flattenPR arr1+ (_, pdata2) = flattenPR arr2+ vsegd' = U.promoteSegdToVSegd segd1++ in PNested vsegd'+ (PTuple2s (singletondPR pdata1) (singletondPR pdata2))+ segd1+ (PTuple2 pdata1 pdata2)++{-# INLINE_PA ziplPR #-}+++-- | O(1). Unzip an array of pairs into a pair of arrays.+unzipPD :: PData (a, b) -> (PData a, PData b)+unzipPD (PTuple2 xs ys) = (xs, ys)+{-# INLINE_PA unzipPD #-}+++-- | Lifted unzip.+unziplPD :: PData (PArray (a, b)) -> PData (PArray a, PArray b)+unziplPD (PNested vsegd (PTuple2s xsdata ysdata) segd (PTuple2 xflat yflat))+ = PTuple2 (PNested vsegd xsdata segd xflat)+ (PNested vsegd ysdata segd yflat)+{-# INLINE_PA unziplPD #-}+++-- Show -----------------------------------------------------------------------+deriving instance (Show (PData a), Show (PData b)) => Show (PData (a, b))+deriving instance (Show (PDatas a), Show (PDatas b)) => Show (PDatas (a, b))+++instance ( PR a, PR b, Show a, Show b+ , PprVirtual (PData a), PprVirtual (PData b))+ => PprVirtual (PData (a, b)) where+ pprv (PTuple2 xs ys)+ = text $ show + $ P.zip (V.toList $ toVectorPR xs) + (V.toList $ toVectorPR ys)+
+ Data/Array/Parallel/PArray/PData/Tuple3.hs view
@@ -0,0 +1,242 @@+{-# OPTIONS_HADDOCK hide #-}+{-# LANGUAGE CPP #-}+#include "fusion-phases.h"++-- | PR instance for tuples.+module Data.Array.Parallel.PArray.PData.Tuple3+ ( PData(..), PDatas(..)+ , zip3PD)+where+import Data.Array.Parallel.Pretty+import Data.Array.Parallel.PArray.PData.Base+import Data.Array.Parallel.PArray.PData.Nested+import GHC.Exts+import Prelude hiding (zip, unzip)+import qualified Data.Vector as V+import qualified Prelude as P++-------------------------------------------------------------------------------+data instance PData (a, b, c)+ = PTuple3 (PData a) (PData b) (PData c)++data instance PDatas (a, b, c)+ = PTuple3s (PDatas a) (PDatas b) (PDatas c)+++-- PR -------------------------------------------------------------------------+instance (PR a, PR b, PR c) => PR (a, b, c) where++ {-# NOINLINE validPR #-}+ validPR (PTuple3 xs ys zs)+ = validPR xs && validPR ys && validPR zs+++ {-# NOINLINE nfPR #-}+ nfPR (PTuple3 arr1 arr2 arr3)+ = nfPR arr1 `seq` nfPR arr2 `seq` nfPR arr3 `seq` ()+++ {-# NOINLINE similarPR #-}+ similarPR (x1, y1, z1) (x2, y2, z2)+ = similarPR x1 x2+ && similarPR y1 y2+ && similarPR z1 z2+++ {-# NOINLINE coversPR #-}+ coversPR weak (PTuple3 arr1 arr2 arr3) ix+ = coversPR weak arr1 ix+ && coversPR weak arr2 ix+ && coversPR weak arr3 ix++ {-# NOINLINE pprpPR #-}+ pprpPR (x, y, z)+ = text "Tuple3 "+ <> vcat [ pprpPR x+ , pprpPR y+ , pprpPR z]+ ++ {-# NOINLINE pprpDataPR #-}+ pprpDataPR (PTuple3 xs ys zs)+ = text "PTuple3 " + <> vcat [ pprpDataPR xs+ , pprpDataPR ys+ , pprpDataPR zs]+++ -- Constructors -------------------------------+ {-# INLINE_PDATA emptyPR #-}+ emptyPR+ = PTuple3 emptyPR emptyPR emptyPR+++ {-# INLINE_PDATA replicatePR #-}+ replicatePR len (x, y, z)+ = PTuple3 (replicatePR len x)+ (replicatePR len y)+ (replicatePR len z)+++ {-# INLINE_PDATA replicatesPR #-}+ replicatesPR lens (PTuple3 arr1 arr2 arr3)+ = PTuple3 (replicatesPR lens arr1)+ (replicatesPR lens arr2)+ (replicatesPR lens arr3)+++ {-# INLINE_PDATA appendPR #-}+ appendPR (PTuple3 arr11 arr12 arr13) (PTuple3 arr21 arr22 arr23)+ = PTuple3 (arr11 `appendPR` arr21)+ (arr12 `appendPR` arr22)+ (arr13 `appendPR` arr23) +++ {-# INLINE_PDATA appendsPR #-}+ appendsPR segdResult segd1 (PTuple3 arrs11 arrs12 arrs13) segd2 (PTuple3 arrs21 arrs22 arrs23)+ = PTuple3 (appendsPR segdResult segd1 arrs11 segd2 arrs21)+ (appendsPR segdResult segd1 arrs12 segd2 arrs22)+ (appendsPR segdResult segd1 arrs13 segd2 arrs23)+++ -- Projections ---------------------------------+ {-# INLINE_PDATA lengthPR #-}+ lengthPR (PTuple3 arr1 _ _) + = lengthPR arr1+ + {-# INLINE_PDATA indexPR #-}+ indexPR (PTuple3 arr1 arr2 arr3) ix+ = (indexPR arr1 ix, indexPR arr2 ix, indexPR arr3 ix)++ {-# INLINE_PDATA indexsPR #-}+ indexsPR (PTuple3s xs ys zs) srcixs+ = PTuple3 (indexsPR xs srcixs)+ (indexsPR ys srcixs)+ (indexsPR zs srcixs)++ {-# INLINE_PDATA indexvsPR #-}+ indexvsPR (PTuple3s xs ys zs) vsegd srcixs+ = PTuple3 (indexvsPR xs vsegd srcixs)+ (indexvsPR ys vsegd srcixs)+ (indexvsPR zs vsegd srcixs)++ {-# INLINE_PDATA extractPR #-}+ extractPR (PTuple3 arr1 arr2 arr3) start len+ = PTuple3 (extractPR arr1 start len) + (extractPR arr2 start len)+ (extractPR arr3 start len)++ {-# INLINE_PDATA extractssPR #-}+ extractssPR (PTuple3s xs ys zs) ussegd+ = PTuple3 (extractssPR xs ussegd)+ (extractssPR ys ussegd)+ (extractssPR zs ussegd)++ {-# INLINE_PDATA extractvsPR #-}+ extractvsPR (PTuple3s xs ys zs) uvsegd+ = PTuple3 (extractvsPR xs uvsegd)+ (extractvsPR ys uvsegd)+ (extractvsPR zs uvsegd)+++ -- Pack and Combine ---------------------------+ {-# INLINE_PDATA packByTagPR #-}+ packByTagPR (PTuple3 arr1 arr2 arr3) tags tag+ = PTuple3 (packByTagPR arr1 tags tag)+ (packByTagPR arr2 tags tag)+ (packByTagPR arr3 tags tag)++ {-# INLINE_PDATA combine2PR #-}+ combine2PR sel (PTuple3 xs1 ys1 zs1) (PTuple3 xs2 ys2 zs2)+ = PTuple3 (combine2PR sel xs1 xs2)+ (combine2PR sel ys1 ys2)+ (combine2PR sel zs1 zs2)+++ -- Conversions --------------------------------+ {-# NOINLINE fromVectorPR #-}+ fromVectorPR vec+ = let (xs, ys, zs) = V.unzip3 vec+ in PTuple3 (fromVectorPR xs)+ (fromVectorPR ys)+ (fromVectorPR zs)++ {-# NOINLINE toVectorPR #-}+ toVectorPR (PTuple3 xs ys zs)+ = V.zip3 (toVectorPR xs)+ (toVectorPR ys)+ (toVectorPR zs)+++ -- PData --------------------------------------+ {-# INLINE_PDATA emptydPR #-}+ emptydPR + = PTuple3s emptydPR+ emptydPR+ emptydPR ++ + {-# INLINE_PDATA singletondPR #-}+ singletondPR (PTuple3 x y z)+ = PTuple3s (singletondPR x)+ (singletondPR y)+ (singletondPR z)+++ {-# INLINE_PDATA lengthdPR #-}+ lengthdPR (PTuple3s xs _ _)+ = lengthdPR xs+ + + {-# INLINE_PDATA indexdPR #-}+ indexdPR (PTuple3s xs ys zs) i+ = PTuple3 (indexdPR xs i)+ (indexdPR ys i)+ (indexdPR zs i)++ + {-# INLINE_PDATA appenddPR #-}+ appenddPR (PTuple3s xs1 ys1 zs1) (PTuple3s xs2 ys2 zs2)+ = PTuple3s (appenddPR xs1 xs2)+ (appenddPR ys1 ys2)+ (appenddPR zs1 zs2)+ ++ {-# NOINLINE fromVectordPR #-}+ fromVectordPR vec+ = let (xss, yss, zss) = V.unzip3 $ V.map (\(PTuple3 xs ys zs) -> (xs, ys, zs)) vec+ in PTuple3s (fromVectordPR xss)+ (fromVectordPR yss)+ (fromVectordPR zss)+++ {-# NOINLINE toVectordPR #-}+ toVectordPR (PTuple3s pdatas1 pdatas2 pdatas3)+ = V.zipWith3 PTuple3+ (toVectordPR pdatas1)+ (toVectordPR pdatas2)+ (toVectordPR pdatas3)++-- PD Functions ---------------------------------------------------------------+-- | O(1). Zip a pair of arrays into an array of pairs.+zip3PD :: PData a -> PData b -> PData c -> PData (a, b, c)+zip3PD = PTuple3+{-# INLINE_PA zip3PD #-}+++-- Show -----------------------------------------------------------------------+deriving instance (Show (PData a), Show (PData b), Show (PData c))+ => Show (PData (a, b, c))++deriving instance (Show (PDatas a), Show (PDatas b), Show (PDatas c))+ => Show (PDatas (a, b, c))+++instance ( PR a, PR b, PR c, Show a, Show b, Show c+ , PprVirtual (PData a), PprVirtual (PData b), PprVirtual (PData c))+ => PprVirtual (PData (a, b, c)) where+ pprv (PTuple3 xs ys zs)+ = text $ show + $ P.zip3 (V.toList $ toVectorPR xs) + (V.toList $ toVectorPR ys)+ (V.toList $ toVectorPR zs)
+ Data/Array/Parallel/PArray/PData/Tuple4.hs view
@@ -0,0 +1,279 @@+{-# OPTIONS_HADDOCK hide #-}+{-# LANGUAGE CPP #-}+#include "fusion-phases.h"++-- | PR instance for tuples.+module Data.Array.Parallel.PArray.PData.Tuple4+ ( PData(..), PDatas(..)+ , zip4PD)+where+import Data.Array.Parallel.Pretty+import Data.Array.Parallel.PArray.PData.Base+import Data.Array.Parallel.PArray.PData.Nested+import GHC.Exts+import Prelude hiding (zip, unzip)+import qualified Data.Vector as V+import qualified Prelude as P+import qualified Data.List as P++-------------------------------------------------------------------------------+data instance PData (a, b, c, d)+ = PTuple4 (PData a) (PData b) (PData c) (PData d)++data instance PDatas (a, b, c, d)+ = PTuple4s (PDatas a) (PDatas b) (PDatas c) (PDatas d)+++-- PR -------------------------------------------------------------------------+instance (PR a, PR b, PR c, PR d) => PR (a, b, c, d) where++ {-# NOINLINE validPR #-}+ validPR (PTuple4 xs ys zs ds)+ = validPR xs && validPR ys && validPR zs && validPR ds+++ {-# NOINLINE nfPR #-}+ nfPR (PTuple4 arr1 arr2 arr3 arr4)+ = nfPR arr1 `seq` nfPR arr2 `seq` nfPR arr3 `seq` nfPR arr4 `seq` ()+++ {-# NOINLINE similarPR #-}+ similarPR (x1, y1, z1, d1) (x2, y2, z2, d2)+ = similarPR x1 x2+ && similarPR y1 y2+ && similarPR z1 z2+ && similarPR d1 d2+++ {-# NOINLINE coversPR #-}+ coversPR weak (PTuple4 arr1 arr2 arr3 arr4) ix+ = coversPR weak arr1 ix+ && coversPR weak arr2 ix+ && coversPR weak arr3 ix+ && coversPR weak arr4 ix+++ {-# NOINLINE pprpPR #-}+ pprpPR (x, y, z, d)+ = text "Tuple4 "+ <> vcat [ pprpPR x+ , pprpPR y+ , pprpPR z+ , pprpPR d ]+ ++ {-# NOINLINE pprpDataPR #-}+ pprpDataPR (PTuple4 xs ys zs ds)+ = text "PTuple4 " + <> vcat [ pprpDataPR xs+ , pprpDataPR ys+ , pprpDataPR zs+ , pprpDataPR ds]+++ -- Constructors -------------------------------+ {-# INLINE_PDATA emptyPR #-}+ emptyPR+ = PTuple4 emptyPR emptyPR emptyPR emptyPR+++ {-# INLINE_PDATA replicatePR #-}+ replicatePR len (x, y, z, d)+ = PTuple4 (replicatePR len x)+ (replicatePR len y)+ (replicatePR len z)+ (replicatePR len d)+++ {-# INLINE_PDATA replicatesPR #-}+ replicatesPR lens (PTuple4 arr1 arr2 arr3 arr4)+ = PTuple4 (replicatesPR lens arr1)+ (replicatesPR lens arr2)+ (replicatesPR lens arr3)+ (replicatesPR lens arr4)+++ {-# INLINE_PDATA appendPR #-}+ appendPR (PTuple4 arr11 arr12 arr13 arr14)+ (PTuple4 arr21 arr22 arr23 arr24)+ = PTuple4 (arr11 `appendPR` arr21)+ (arr12 `appendPR` arr22)+ (arr13 `appendPR` arr23) + (arr14 `appendPR` arr24) +++ {-# INLINE_PDATA appendsPR #-}+ appendsPR segdResult segd1 (PTuple4 arrs11 arrs12 arrs13 arrs14)+ segd2 (PTuple4 arrs21 arrs22 arrs23 arrs24)+ = PTuple4 (appendsPR segdResult segd1 arrs11 segd2 arrs21)+ (appendsPR segdResult segd1 arrs12 segd2 arrs22)+ (appendsPR segdResult segd1 arrs13 segd2 arrs23)+ (appendsPR segdResult segd1 arrs14 segd2 arrs24)+++ -- Projections ---------------------------------+ {-# INLINE_PDATA lengthPR #-}+ lengthPR (PTuple4 arr1 _ _ _) + = lengthPR arr1+ + {-# INLINE_PDATA indexPR #-}+ indexPR (PTuple4 arr1 arr2 arr3 arr4) ix+ = ( indexPR arr1 ix+ , indexPR arr2 ix+ , indexPR arr3 ix+ , indexPR arr4 ix)+++ {-# INLINE_PDATA indexsPR #-}+ indexsPR (PTuple4s xs ys zs ds) srcixs+ = PTuple4 (indexsPR xs srcixs)+ (indexsPR ys srcixs)+ (indexsPR zs srcixs)+ (indexsPR ds srcixs)++ {-# INLINE_PDATA indexvsPR #-}+ indexvsPR (PTuple4s xs ys zs ds) vsegd srcixs+ = PTuple4 (indexvsPR xs vsegd srcixs)+ (indexvsPR ys vsegd srcixs)+ (indexvsPR zs vsegd srcixs)+ (indexvsPR ds vsegd srcixs)++ {-# INLINE_PDATA extractPR #-}+ extractPR (PTuple4 arr1 arr2 arr3 arr4) start len+ = PTuple4 (extractPR arr1 start len) + (extractPR arr2 start len)+ (extractPR arr3 start len)+ (extractPR arr4 start len)++ {-# INLINE_PDATA extractssPR #-}+ extractssPR (PTuple4s xs ys zs ds) ussegd+ = PTuple4 (extractssPR xs ussegd)+ (extractssPR ys ussegd)+ (extractssPR zs ussegd)+ (extractssPR ds ussegd)++ {-# INLINE_PDATA extractvsPR #-}+ extractvsPR (PTuple4s xs ys zs ds) uvsegd+ = PTuple4 (extractvsPR xs uvsegd)+ (extractvsPR ys uvsegd)+ (extractvsPR zs uvsegd)+ (extractvsPR ds uvsegd)+++ -- Pack and Combine ---------------------------+ {-# INLINE_PDATA packByTagPR #-}+ packByTagPR (PTuple4 arr1 arr2 arr3 arr4) tags tag+ = PTuple4 (packByTagPR arr1 tags tag)+ (packByTagPR arr2 tags tag)+ (packByTagPR arr3 tags tag)+ (packByTagPR arr4 tags tag)+++ {-# INLINE_PDATA combine2PR #-}+ combine2PR sel (PTuple4 xs1 ys1 zs1 ds1) (PTuple4 xs2 ys2 zs2 ds2)+ = PTuple4 (combine2PR sel xs1 xs2)+ (combine2PR sel ys1 ys2)+ (combine2PR sel zs1 zs2)+ (combine2PR sel ds1 ds2)+++ -- Conversions --------------------------------+ {-# NOINLINE fromVectorPR #-}+ fromVectorPR vec+ = let (xs, ys, zs, ds) = V.unzip4 vec+ in PTuple4 (fromVectorPR xs)+ (fromVectorPR ys)+ (fromVectorPR zs)+ (fromVectorPR ds)++ {-# NOINLINE toVectorPR #-}+ toVectorPR (PTuple4 xs ys zs ds)+ = V.zip4 (toVectorPR xs)+ (toVectorPR ys)+ (toVectorPR zs)+ (toVectorPR ds)+++ -- PData --------------------------------------+ {-# INLINE_PDATA emptydPR #-}+ emptydPR + = PTuple4s emptydPR+ emptydPR+ emptydPR + emptydPR ++ + {-# INLINE_PDATA singletondPR #-}+ singletondPR (PTuple4 x y z d)+ = PTuple4s (singletondPR x)+ (singletondPR y)+ (singletondPR z)+ (singletondPR d)+++ {-# INLINE_PDATA lengthdPR #-}+ lengthdPR (PTuple4s xs _ _ _)+ = lengthdPR xs+ + + {-# INLINE_PDATA indexdPR #-}+ indexdPR (PTuple4s xs ys zs ds) i+ = PTuple4 (indexdPR xs i)+ (indexdPR ys i)+ (indexdPR zs i)+ (indexdPR ds i)++ + {-# INLINE_PDATA appenddPR #-}+ appenddPR (PTuple4s xs1 ys1 zs1 ds1) (PTuple4s xs2 ys2 zs2 ds2)+ = PTuple4s (appenddPR xs1 xs2)+ (appenddPR ys1 ys2)+ (appenddPR zs1 zs2)+ (appenddPR ds1 ds2)+ ++ {-# NOINLINE fromVectordPR #-}+ fromVectordPR vec+ = let (xss, yss, zss, dss) = V.unzip4 $ V.map (\(PTuple4 xs ys zs ds) -> (xs, ys, zs, ds)) vec+ in PTuple4s (fromVectordPR xss)+ (fromVectordPR yss)+ (fromVectordPR zss)+ (fromVectordPR dss)+++ {-# NOINLINE toVectordPR #-}+ toVectordPR (PTuple4s pdatas1 pdatas2 pdatas3 pdatas4)+ = V.zipWith4 PTuple4+ (toVectordPR pdatas1)+ (toVectordPR pdatas2)+ (toVectordPR pdatas3)+ (toVectordPR pdatas4)+++-- PD Functions ---------------------------------------------------------------+-- | O(1). Zip a pair of arrays into an array of pairs.+zip4PD :: PData a -> PData b -> PData c -> PData d -> PData (a, b, c, d)+zip4PD = PTuple4+{-# INLINE_PA zip4PD #-}+++-- Show -----------------------------------------------------------------------+deriving instance (Show (PData a), Show (PData b), Show (PData c), Show (PData d))+ => Show (PData (a, b, c, d))++deriving instance (Show (PDatas a), Show (PDatas b), Show (PDatas c), Show (PDatas d))+ => Show (PDatas (a, b, c, d))+++instance ( PR a, PR b, PR c, PR d, Show a, Show b, Show c, Show d+ , PprVirtual (PData a), PprVirtual (PData b), PprVirtual (PData c), PprVirtual (PData d))+ => PprVirtual (PData (a, b, c, d)) where+ pprv (PTuple4 xs ys zs ds)+ = text $ show + $ P.zip4 (V.toList $ toVectorPR xs) + (V.toList $ toVectorPR ys)+ (V.toList $ toVectorPR zs)+ (V.toList $ toVectorPR ds)++ +
+ Data/Array/Parallel/PArray/PData/Tuple5.hs view
@@ -0,0 +1,304 @@+{-# OPTIONS_HADDOCK hide #-}+{-# LANGUAGE CPP #-}+#include "fusion-phases.h"++-- | PR instance for tuples.+module Data.Array.Parallel.PArray.PData.Tuple5+ ( PData(..), PDatas(..)+ , zip5PD)+where+import Data.Array.Parallel.Pretty+import Data.Array.Parallel.PArray.PData.Base+import Data.Array.Parallel.PArray.PData.Nested+import GHC.Exts+import Prelude hiding (zip, unzip)+import qualified Data.Vector as V+import qualified Prelude as P+import qualified Data.List as P++-------------------------------------------------------------------------------+data instance PData (a, b, c, d, e)+ = PTuple5 (PData a) (PData b) (PData c) (PData d) (PData e)++data instance PDatas (a, b, c, d, e)+ = PTuple5s (PDatas a) (PDatas b) (PDatas c) (PDatas d) (PDatas e)+++-- PR -------------------------------------------------------------------------+instance (PR a, PR b, PR c, PR d, PR e) => PR (a, b, c, d, e) where++ {-# NOINLINE validPR #-}+ validPR (PTuple5 xs ys zs ds es)+ = validPR xs && validPR ys && validPR zs && validPR ds && validPR es+++ {-# NOINLINE nfPR #-}+ nfPR (PTuple5 arr1 arr2 arr3 arr4 arr5)+ = nfPR arr1 `seq` nfPR arr2 `seq` nfPR arr3 `seq` nfPR arr4 `seq` nfPR arr5 `seq` ()+++ {-# NOINLINE similarPR #-}+ similarPR (x1, y1, z1, d1, e1) (x2, y2, z2, d2, e2)+ = similarPR x1 x2+ && similarPR y1 y2+ && similarPR z1 z2+ && similarPR d1 d2+ && similarPR e1 e2+++ {-# NOINLINE coversPR #-}+ coversPR weak (PTuple5 arr1 arr2 arr3 arr4 arr5) ix+ = coversPR weak arr1 ix+ && coversPR weak arr2 ix+ && coversPR weak arr3 ix+ && coversPR weak arr4 ix+ && coversPR weak arr5 ix+++ {-# NOINLINE pprpPR #-}+ pprpPR (x, y, z, d, e)+ = text "Tuple5 "+ <> vcat [ pprpPR x+ , pprpPR y+ , pprpPR z+ , pprpPR d+ , pprpPR e ]+ ++ {-# NOINLINE pprpDataPR #-}+ pprpDataPR (PTuple5 xs ys zs ds es)+ = text "PTuple5 " + <> vcat [ pprpDataPR xs+ , pprpDataPR ys+ , pprpDataPR zs+ , pprpDataPR ds+ , pprpDataPR es]+++ -- Constructors -------------------------------+ {-# INLINE_PDATA emptyPR #-}+ emptyPR+ = PTuple5 emptyPR emptyPR emptyPR emptyPR emptyPR+++ {-# INLINE_PDATA replicatePR #-}+ replicatePR len (x, y, z, d, e)+ = PTuple5 (replicatePR len x)+ (replicatePR len y)+ (replicatePR len z)+ (replicatePR len d)+ (replicatePR len e)+++ {-# INLINE_PDATA replicatesPR #-}+ replicatesPR lens (PTuple5 arr1 arr2 arr3 arr4 arr5)+ = PTuple5 (replicatesPR lens arr1)+ (replicatesPR lens arr2)+ (replicatesPR lens arr3)+ (replicatesPR lens arr4)+ (replicatesPR lens arr5)+++ {-# INLINE_PDATA appendPR #-}+ appendPR (PTuple5 arr11 arr12 arr13 arr14 arr15)+ (PTuple5 arr21 arr22 arr23 arr24 arr25)+ = PTuple5 (arr11 `appendPR` arr21)+ (arr12 `appendPR` arr22)+ (arr13 `appendPR` arr23) + (arr14 `appendPR` arr24) + (arr15 `appendPR` arr25) +++ {-# INLINE_PDATA appendsPR #-}+ appendsPR segdResult segd1 (PTuple5 arrs11 arrs12 arrs13 arrs14 arrs15)+ segd2 (PTuple5 arrs21 arrs22 arrs23 arrs24 arrs25)+ = PTuple5 (appendsPR segdResult segd1 arrs11 segd2 arrs21)+ (appendsPR segdResult segd1 arrs12 segd2 arrs22)+ (appendsPR segdResult segd1 arrs13 segd2 arrs23)+ (appendsPR segdResult segd1 arrs14 segd2 arrs24)+ (appendsPR segdResult segd1 arrs15 segd2 arrs25)+++ -- Projections ---------------------------------+ {-# INLINE_PDATA lengthPR #-}+ lengthPR (PTuple5 arr1 _ _ _ _) + = lengthPR arr1+ + {-# INLINE_PDATA indexPR #-}+ indexPR (PTuple5 arr1 arr2 arr3 arr4 arr5) ix+ = ( indexPR arr1 ix+ , indexPR arr2 ix+ , indexPR arr3 ix+ , indexPR arr4 ix+ , indexPR arr5 ix)+++ {-# INLINE_PDATA indexsPR #-}+ indexsPR (PTuple5s xs ys zs ds es) srcixs+ = PTuple5 (indexsPR xs srcixs)+ (indexsPR ys srcixs)+ (indexsPR zs srcixs)+ (indexsPR ds srcixs)+ (indexsPR es srcixs)++ {-# INLINE_PDATA indexvsPR #-}+ indexvsPR (PTuple5s xs ys zs ds es) vsegd srcixs+ = PTuple5 (indexvsPR xs vsegd srcixs)+ (indexvsPR ys vsegd srcixs)+ (indexvsPR zs vsegd srcixs)+ (indexvsPR ds vsegd srcixs)+ (indexvsPR es vsegd srcixs)++ {-# INLINE_PDATA extractPR #-}+ extractPR (PTuple5 arr1 arr2 arr3 arr4 arr5) start len+ = PTuple5 (extractPR arr1 start len) + (extractPR arr2 start len)+ (extractPR arr3 start len)+ (extractPR arr4 start len)+ (extractPR arr5 start len)++ {-# INLINE_PDATA extractssPR #-}+ extractssPR (PTuple5s xs ys zs ds es) ussegd+ = PTuple5 (extractssPR xs ussegd)+ (extractssPR ys ussegd)+ (extractssPR zs ussegd)+ (extractssPR ds ussegd)+ (extractssPR es ussegd)++ {-# INLINE_PDATA extractvsPR #-}+ extractvsPR (PTuple5s xs ys zs ds es) uvsegd+ = PTuple5 (extractvsPR xs uvsegd)+ (extractvsPR ys uvsegd)+ (extractvsPR zs uvsegd)+ (extractvsPR ds uvsegd)+ (extractvsPR es uvsegd)+++ -- Pack and Combine ---------------------------+ {-# INLINE_PDATA packByTagPR #-}+ packByTagPR (PTuple5 arr1 arr2 arr3 arr4 arr5) tags tag+ = PTuple5 (packByTagPR arr1 tags tag)+ (packByTagPR arr2 tags tag)+ (packByTagPR arr3 tags tag)+ (packByTagPR arr4 tags tag)+ (packByTagPR arr5 tags tag)+++ {-# INLINE_PDATA combine2PR #-}+ combine2PR sel (PTuple5 xs1 ys1 zs1 ds1 es1) (PTuple5 xs2 ys2 zs2 ds2 es2)+ = PTuple5 (combine2PR sel xs1 xs2)+ (combine2PR sel ys1 ys2)+ (combine2PR sel zs1 zs2)+ (combine2PR sel ds1 ds2)+ (combine2PR sel es1 es2)+++ -- Conversions --------------------------------+ {-# NOINLINE fromVectorPR #-}+ fromVectorPR vec+ = let (xs, ys, zs, ds, es) = V.unzip5 vec+ in PTuple5 (fromVectorPR xs)+ (fromVectorPR ys)+ (fromVectorPR zs)+ (fromVectorPR ds)+ (fromVectorPR es)++ {-# NOINLINE toVectorPR #-}+ toVectorPR (PTuple5 xs ys zs ds es)+ = V.zip5 (toVectorPR xs)+ (toVectorPR ys)+ (toVectorPR zs)+ (toVectorPR ds)+ (toVectorPR es)+++ -- PData --------------------------------------+ {-# INLINE_PDATA emptydPR #-}+ emptydPR + = PTuple5s emptydPR+ emptydPR+ emptydPR + emptydPR + emptydPR ++ + {-# INLINE_PDATA singletondPR #-}+ singletondPR (PTuple5 x y z d e)+ = PTuple5s (singletondPR x)+ (singletondPR y)+ (singletondPR z)+ (singletondPR d)+ (singletondPR e)+++ {-# INLINE_PDATA lengthdPR #-}+ lengthdPR (PTuple5s xs _ _ _ _)+ = lengthdPR xs+ + + {-# INLINE_PDATA indexdPR #-}+ indexdPR (PTuple5s xs ys zs ds es) i+ = PTuple5 (indexdPR xs i)+ (indexdPR ys i)+ (indexdPR zs i)+ (indexdPR ds i)+ (indexdPR es i)++ + {-# INLINE_PDATA appenddPR #-}+ appenddPR (PTuple5s xs1 ys1 zs1 ds1 es1) (PTuple5s xs2 ys2 zs2 ds2 es2)+ = PTuple5s (appenddPR xs1 xs2)+ (appenddPR ys1 ys2)+ (appenddPR zs1 zs2)+ (appenddPR ds1 ds2)+ (appenddPR es1 es2)+ ++ {-# NOINLINE fromVectordPR #-}+ fromVectordPR vec+ = let (xss, yss, zss, dss, ess) = V.unzip5 $ V.map (\(PTuple5 xs ys zs ds es) -> (xs, ys, zs, ds, es)) vec+ in PTuple5s (fromVectordPR xss)+ (fromVectordPR yss)+ (fromVectordPR zss)+ (fromVectordPR dss)+ (fromVectordPR ess)+++ {-# NOINLINE toVectordPR #-}+ toVectordPR (PTuple5s pdatas1 pdatas2 pdatas3 pdatas4 pdatas5)+ = V.zipWith5 PTuple5+ (toVectordPR pdatas1)+ (toVectordPR pdatas2)+ (toVectordPR pdatas3)+ (toVectordPR pdatas4)+ (toVectordPR pdatas5)+++-- PD Functions ---------------------------------------------------------------+-- | O(1). Zip a pair of arrays into an array of pairs.+zip5PD :: PData a -> PData b -> PData c -> PData d -> PData e -> PData (a, b, c, d, e)+zip5PD = PTuple5+{-# INLINE_PA zip5PD #-}+++-- Show -----------------------------------------------------------------------+deriving instance (Show (PData a), Show (PData b), Show (PData c), Show (PData d), Show (PData e))+ => Show (PData (a, b, c, d, e))++deriving instance (Show (PDatas a), Show (PDatas b), Show (PDatas c), Show (PDatas d), Show (PDatas e))+ => Show (PDatas (a, b, c, d, e))+++instance ( PR a, PR b, PR c, PR d, PR e, Show a, Show b, Show c, Show d, Show e+ , PprVirtual (PData a), PprVirtual (PData b), PprVirtual (PData c), PprVirtual (PData d), PprVirtual (PData e))+ => PprVirtual (PData (a, b, c, d, e)) where+ pprv (PTuple5 xs ys zs ds es)+ = text $ show + $ P.zip5 (V.toList $ toVectorPR xs) + (V.toList $ toVectorPR ys)+ (V.toList $ toVectorPR zs)+ (V.toList $ toVectorPR ds)+ (V.toList $ toVectorPR es)++ +
+ Data/Array/Parallel/PArray/PData/Unit.hs view
@@ -0,0 +1,164 @@+{-# OPTIONS_HADDOCK hide #-}+{-# LANGUAGE CPP #-}+#include "fusion-phases.h"++-- | PR instance for unit.+module Data.Array.Parallel.PArray.PData.Unit where+import Data.Array.Parallel.PArray.PData.Base+import Data.Array.Parallel.Pretty+import qualified Data.Array.Parallel.Unlifted as U+import qualified Data.Vector as V++-------------------------------------------------------------------------------+-- | TODO: For arrays of units, we're currently maintaining their length so+-- that validPR works properly. In future we should ditch the length field+-- and rely on coversPR to check that indices are in bounds, like we do+-- with arrays of type PData Void.+data instance PData ()+ = PUnit Int++data instance PDatas ()+ = PUnits (U.Array Int)++punit :: Int -> PData ()+punit = PUnit+++-- PR -------------------------------------------------------------------------+instance PR () where++ {-# NOINLINE validPR #-}+ validPR _+ = True++ {-# NOINLINE nfPR #-}+ nfPR xx+ = xx `seq` ()+ + {-# NOINLINE similarPR #-}+ similarPR _ _+ = True++ {-# NOINLINE coversPR #-}+ coversPR weak (PUnit n) i+ | weak = i <= n+ | otherwise = i < n++ {-# NOINLINE pprpPR #-}+ pprpPR _+ = text "()"++ {-# NOINLINE pprpDataPR #-}+ pprpDataPR uu+ = text $ show uu+++ -- Constructors -------------------------------+ {-# INLINE_PDATA emptyPR #-}+ emptyPR+ = PUnit 0++ {-# INLINE_PDATA replicatePR #-}+ replicatePR n _+ = PUnit n++ {-# INLINE_PDATA replicatesPR #-}+ replicatesPR segd _+ = PUnit (U.elementsSegd segd)+ + {-# INLINE_PDATA appendPR #-}+ appendPR (PUnit len1) (PUnit len2)+ = PUnit (len1 + len2)++ {-# INLINE_PDATA appendsPR #-}+ appendsPR segdResult _ _ _ _+ = PUnit (U.lengthSegd segdResult)+++ -- Projections ------------------------------- + {-# INLINE_PDATA lengthPR #-}+ lengthPR (PUnit n)+ = n++ {-# INLINE_PDATA indexPR #-}+ indexPR _ _+ = ()++ {-# INLINE_PDATA indexsPR #-}+ indexsPR _ srcixs+ = PUnit $ U.length srcixs++ {-# INLINE_PDATA indexvsPR #-}+ indexvsPR _ _ srcixs+ = PUnit $ U.length srcixs++ {-# INLINE_PDATA extractPR #-}+ extractPR _ _ len+ = PUnit len+ + {-# INLINE_PDATA extractssPR #-}+ extractssPR _ ussegd+ = PUnit $ U.sum $ U.lengthsOfSSegd ussegd++ {-# INLINE_PDATA extractvsPR #-}+ extractvsPR _ uvsegd+ = PUnit $ U.sum $ U.takeLengthsOfVSegd uvsegd+ ++ -- Pack and Combine --------------------------- + {-# INLINE_PDATA packByTagPR #-}+ packByTagPR _ tags tag+ = PUnit (U.length $ U.filter (== tag) tags)++ {-# INLINE_PDATA combine2PR #-}+ combine2PR sel2 _ _+ = PUnit ( U.elementsSel2_0 sel2+ + U.elementsSel2_1 sel2)+++ -- Conversions --------------------------------+ {-# NOINLINE fromVectorPR #-}+ fromVectorPR vec+ = PUnit (V.length vec)++ {-# NOINLINE toVectorPR #-}+ toVectorPR (PUnit len)+ = V.replicate len ()++ -- PDatas -------------------------------------+ {-# INLINE_PDATA emptydPR #-}+ emptydPR+ = PUnits $ U.empty++ {-# INLINE_PDATA singletondPR #-}+ singletondPR (PUnit n)+ = PUnits $ U.replicate 1 n++ {-# INLINE_PDATA lengthdPR #-}+ lengthdPR (PUnits pdatas)+ = U.length pdatas+ + {-# INLINE_PDATA indexdPR #-}+ indexdPR (PUnits pdatas) ix+ = PUnit $ U.index "indexdPR[Unit]" pdatas ix+ + {-# INLINE_PDATA appenddPR #-}+ appenddPR (PUnits lens1) (PUnits lens2)+ = PUnits $ lens1 U.+:+ lens2++ {-# NOINLINE fromVectordPR #-}+ fromVectordPR vec+ = PUnits $ V.convert $ V.map lengthPR vec+ + {-# NOINLINE toVectordPR #-}+ toVectordPR (PUnits uvecs)+ = V.map PUnit $ V.convert uvecs++-- Show -----------------------------------------------------------------------+deriving instance Show (PData ())+deriving instance Show (PDatas ())++instance PprVirtual (PData ()) where+ pprv (PUnit n)+ = text $ "[ () x " ++ show n ++ " ]"+
+ Data/Array/Parallel/PArray/PData/Void.hs view
@@ -0,0 +1,166 @@+{-# OPTIONS_HADDOCK hide #-}+{-# LANGUAGE CPP #-}+#include "fusion-phases.h"++-- | PR instance for the void type.+module Data.Array.Parallel.PArray.PData.Void + (Void, void, pvoid, fromVoid, pvoids)+where+import Data.Array.Parallel.PArray.PData.Base+import Data.Array.Parallel.PArray.PRepr.Base ()+import Data.Array.Parallel.PArray.Types+import Data.Array.Parallel.Pretty+import qualified Data.Vector as V++-------------------------------------------------------------------------------+-- | The Void type is used as a place holder in situations where we don't +-- want to track a real array.+-- +-- For example:+-- A type like Bool is represented as @Sum2 Void Void@, meaning that we only+-- only care about the tag of the data constructor and not its argumnent.+--+-- We also use it as the to fill empty closures.+--+-- Note that arrays of (PData Void) do not have an intrinsic length, which +-- is the reason that the PR dictionary only contains a coversPR function+-- was well as a partial lengthPR function.+--+data instance PData Void++-- | PVoids instance counts how many "vectors" of void we have+data instance PDatas Void+ = PVoids Int++pvoid :: PData Void+pvoid = error "Data.Array.Parallel.PData.Void"++pvoids :: Int -> PDatas Void+pvoids = PVoids +++-- PR --------------------------------------------------------------------------+nope :: String -> a+nope str = error $ "Data.Array.Parallel.PData.Void: no PR method for " ++ str++instance PR Void where++ {-# NOINLINE validPR #-}+ validPR _ = True++ {-# NOINLINE nfPR #-}+ nfPR _ = ()++ {-# NOINLINE similarPR #-}+ similarPR _ _ = True+ + {-# NOINLINE coversPR #-}+ coversPR _ _ _ = True+ + {-# NOINLINE pprpPR #-}+ pprpPR _ = text "void"+ + {-# NOINLINE pprpDataPR #-}+ pprpDataPR _ = text "pvoid"+++ -- Constructors ------------------------------- + {-# INLINE_PDATA emptyPR #-}+ emptyPR = nope "emptyPR"++ {-# INLINE_PDATA replicatePR #-}+ replicatePR = nope "replicate"++ {-# INLINE_PDATA replicatesPR #-}+ replicatesPR = nope "replicates"++ {-# INLINE_PDATA appendPR #-}+ appendPR = nope "append"+ + {-# INLINE_PDATA appendsPR #-}+ appendsPR = nope "appends"+++ -- Projections --------------------------------+ {-# INLINE_PDATA lengthPR #-}+ lengthPR _ = nope "length"++ -- We return the black hole here so that we can construct vectors of type+ -- Vector Void during debugging.+ -- See the (A.Array PArray e) instance in D.A.P.PArray for details.+ {-# INLINE_PDATA indexPR #-}+ indexPR _ _ = void++ {-# INLINE_PDATA indexsPR #-}+ indexsPR = nope "indexs"++ {-# INLINE_PDATA indexvsPR #-}+ indexvsPR = nope "indexvs"++ {-# INLINE_PDATA extractPR #-}+ extractPR = nope "extractl"++ {-# INLINE_PDATA extractssPR #-}+ extractssPR = nope "extractss"++ {-# INLINE_PDATA extractvsPR #-}+ extractvsPR = nope "extractvs"+++ -- Pack and Combine ---------------------------+ {-# INLINE_PDATA packByTagPR #-}+ packByTagPR = nope "packByTag"++ {-# INLINE_PDATA combine2PR #-}+ combine2PR = nope "combine2"+++ -- Conversions --------------------------------+ {-# NOINLINE fromVectorPR #-}+ fromVectorPR = nope "fromVector"++ {-# NOINLINE toVectorPR #-}+ toVectorPR _ = nope "toVector"+++ -- PDatas ------------------------------------- + {-# INLINE_PDATA emptydPR #-} + emptydPR = PVoids 0++ {-# INLINE_PDATA singletondPR #-} + singletondPR _+ = PVoids 1++ {-# INLINE_PDATA lengthdPR #-}+ lengthdPR (PVoids n)+ = n++ {-# INLINE_PDATA indexdPR #-}+ indexdPR _ _+ = pvoid+ + {-# INLINE_PDATA appenddPR #-}+ appenddPR (PVoids n1) (PVoids n2)+ = PVoids (n1 + n2)++ {-# NOINLINE fromVectordPR #-}+ fromVectordPR vec+ = PVoids $ V.length vec++ {-# NOINLINE toVectordPR #-}+ toVectordPR (PVoids n)+ = V.replicate n pvoid+++-- Show -----------------------------------------------------------------------+instance Show (PData Void) where+ show _ = "pvoid"+++instance Show (PDatas Void) where+ show _ = "pvoids"+ ++instance PprVirtual (PData Void) where+ pprv _ = text "pvoid"+
+ Data/Array/Parallel/PArray/PData/Word8.hs view
@@ -0,0 +1,168 @@+{-# OPTIONS_HADDOCK hide #-}+{-# LANGUAGE CPP #-}+#include "fusion-phases.h"++-- | PR instance for Word8.+module Data.Array.Parallel.PArray.PData.Word8 where+import Data.Array.Parallel.PArray.PData.Base+import qualified Data.Array.Parallel.Unlifted as U+import qualified Data.Vector as V+import Text.PrettyPrint+import Prelude as P+import Data.Word+import Data.Array.Parallel.Pretty++-------------------------------------------------------------------------------+data instance PData Word8+ = PWord8 (U.Array Word8)++data instance PDatas Word8+ = PWord8s (U.Arrays Word8)+++-- PR -------------------------------------------------------------------------+instance PR Word8 where++ {-# NOINLINE validPR #-}+ validPR _+ = True++ {-# NOINLINE nfPR #-}+ nfPR (PWord8 xx)+ = xx `seq` ()++ {-# NOINLINE similarPR #-}+ similarPR = (==)++ {-# NOINLINE coversPR #-}+ coversPR weak (PWord8 uarr) ix+ | weak = ix <= U.length uarr+ | otherwise = ix < U.length uarr++ {-# NOINLINE pprpPR #-}+ pprpPR i+ = int (fromIntegral i)++ {-# NOINLINE pprpDataPR #-}+ pprpDataPR (PWord8 uarr)+ = text "PWord8" <+> pprp uarr+++ -- Constructors -------------------------------+ {-# INLINE_PDATA emptyPR #-}+ emptyPR+ = PWord8 U.empty++ {-# INLINE_PDATA replicatePR #-}+ replicatePR len x+ = PWord8 (U.replicate len x)++ {-# INLINE_PDATA replicatesPR #-}+ replicatesPR segd (PWord8 arr)+ = PWord8 (U.replicate_s segd arr)+ + {-# INLINE_PDATA appendPR #-}+ appendPR (PWord8 arr1) (PWord8 arr2)+ = PWord8 $ arr1 U.+:+ arr2++ {-# INLINE_PDATA appendsPR #-}+ appendsPR segdResult segd1 (PWord8 arr1) segd2 (PWord8 arr2)+ = PWord8 $ U.append_s segdResult segd1 arr1 segd2 arr2+++ -- Projections -------------------------------- + {-# INLINE_PDATA lengthPR #-}+ lengthPR (PWord8 uarr) + = U.length uarr++ {-# INLINE_PDATA indexPR #-}+ indexPR (PWord8 uarr) ix+ = U.index "indexPR[Word8]" uarr ix++ {-# INLINE_PDATA indexsPR #-}+ indexsPR (PWord8s pvecs) srcixs+ = PWord8 $ U.map (\(src, ix) -> U.unsafeIndex2s pvecs src ix) srcixs++ {-# INLINE_PDATA indexvsPR #-}+ indexvsPR (PWord8s arrs) vsegd srcixs + = PWord8 $ U.indexs_avs arrs vsegd srcixs++ {-# INLINE_PDATA extractPR #-}+ extractPR (PWord8 arr) start len + = PWord8 (U.extract arr start len)++ {-# INLINE_PDATA extractssPR #-}+ extractssPR (PWord8s arrs) ssegd+ = PWord8 $ U.extracts_ass ssegd arrs++ {-# INLINE_PDATA extractvsPR #-}+ extractvsPR (PWord8s arrs) vsegd+ = PWord8 $ U.extracts_avs vsegd arrs+++ -- Pack and Combine ---------------------------+ {-# INLINE_PDATA packByTagPR #-}+ packByTagPR (PWord8 arr1) arrTags tag+ = PWord8 $ U.packByTag arr1 arrTags tag++ {-# INLINE_PDATA combine2PR #-}+ combine2PR sel (PWord8 arr1) (PWord8 arr2)+ = PWord8 $ U.combine2 (U.tagsSel2 sel)+ (U.repSel2 sel)+ arr1 arr2+++ -- Conversions --------------------------------+ {-# NOINLINE fromVectorPR #-}+ fromVectorPR xx+ = PWord8 $U.fromList $ V.toList xx++ {-# NOINLINE toVectorPR #-}+ toVectorPR (PWord8 arr)+ = V.fromList $ U.toList arr+++ -- PDatas -------------------------------------+ {-# INLINE_PDATA emptydPR #-}+ emptydPR + = PWord8s $ U.emptys+ + {-# INLINE_PDATA singletondPR #-}+ singletondPR (PWord8 pdata)+ = PWord8s $ U.singletons pdata+ + {-# INLINE_PDATA lengthdPR #-}+ lengthdPR (PWord8s arrs)+ = U.lengths arrs+ + {-# INLINE_PDATA indexdPR #-}+ indexdPR (PWord8s arrs) ix+ = PWord8 $ arrs `U.unsafeIndexs` ix++ {-# INLINE_PDATA appenddPR #-}+ appenddPR (PWord8s xs) (PWord8s ys)+ = PWord8s $ xs `U.appends` ys+ + {-# NOINLINE fromVectordPR #-}+ fromVectordPR pdatas+ = PWord8s + $ U.fromVectors+ $ V.map (\(PWord8 xs) -> xs) pdatas+ + {-# NOINLINE toVectordPR #-}+ toVectordPR (PWord8s vec)+ = V.map PWord8 $ U.toVectors vec+++-- Show -----------------------------------------------------------------------+deriving instance Show (PData Word8)+deriving instance Show (PDatas Word8)++instance PprPhysical (U.Array Word8) where+ pprp uarr + = text (show $ U.toList uarr)++instance PprVirtual (PData Word8) where+ pprv (PWord8 vec)+ = text (show $ U.toList vec)+
+ Data/Array/Parallel/PArray/PData/Wrap.hs view
@@ -0,0 +1,150 @@+{-# OPTIONS_HADDOCK hide #-}+{-# LANGUAGE CPP #-}+#include "fusion-phases.h"++-- | PR instance for the Wrap type.+module Data.Array.Parallel.PArray.PData.Wrap where+import Data.Array.Parallel.PArray.PData.Base+import Data.Array.Parallel.PArray.Types+import Data.Array.Parallel.PArray.PRepr.Base+import qualified Data.Vector as V++-------------------------------------------------------------------------------+newtype instance PData (Wrap a)+ = PWrap (PData a)++newtype instance PDatas (Wrap a)+ = PWraps (PDatas a)+++-- PR -------------------------------------------------------------------------+instance PA a => PR (Wrap a) where ++ {-# NOINLINE validPR #-}+ validPR (PWrap pdata) + = validPA pdata++ {-# NOINLINE nfPR #-}+ nfPR (PWrap pdata) + = nfPA pdata++ {-# NOINLINE similarPR #-}+ similarPR (Wrap x) (Wrap y)+ = similarPA x y++ {-# NOINLINE coversPR #-}+ coversPR weak (PWrap pdata) ix+ = coversPA weak pdata ix++ {-# NOINLINE pprpPR #-}+ pprpPR (Wrap x)+ = pprpPA x++ {-# NOINLINE pprpDataPR #-}+ pprpDataPR (PWrap pdata)+ = pprpDataPA pdata+++ -- Constructors -------------------------------+ {-# INLINE_PDATA emptyPR #-}+ emptyPR + = PWrap emptyPA+ + {-# INLINE_PDATA replicatePR #-}+ replicatePR n (Wrap x)+ = PWrap $ replicatePA n x++ {-# INLINE_PDATA replicatesPR #-}+ replicatesPR segd (PWrap xs)+ = PWrap $ replicatesPA segd xs++ {-# INLINE_PDATA appendPR #-}+ appendPR (PWrap xs) (PWrap ys)+ = PWrap $ appendPA xs ys+ + {-# INLINE_PDATA appendsPR #-}+ appendsPR segdResult segd1 (PWrap xs) segd2 (PWrap ys)+ = PWrap $ appendsPA segdResult segd1 xs segd2 ys+ ++ -- Projections --------------------------------+ {-# INLINE_PDATA lengthPR #-}+ lengthPR (PWrap xs)+ = lengthPA xs+ + {-# INLINE_PDATA indexPR #-}+ indexPR (PWrap xs) ix+ = Wrap $ indexPA xs ix++ {-# INLINE_PDATA indexsPR #-}+ indexsPR (PWraps pdatas) srcixs+ = PWrap $ indexsPA pdatas srcixs++ {-# INLINE_PDATA indexvsPR #-}+ indexvsPR (PWraps arrs) vsegd srcixs+ = PWrap $ indexvsPA arrs vsegd srcixs++ {-# INLINE_PDATA extractPR #-}+ extractPR (PWrap xs) ix n+ = PWrap $ extractPA xs ix n+ + {-# INLINE_PDATA extractssPR #-}+ extractssPR (PWraps pdatas) ssegd+ = PWrap $ extractssPA pdatas ssegd++ {-# INLINE_PDATA extractvsPR #-}+ extractvsPR (PWraps pdatas) vsegd+ = PWrap $ extractvsPA pdatas vsegd+++ -- Pack and Combine ---------------------------+ {-# INLINE_PDATA packByTagPR #-}+ packByTagPR (PWrap xs) tags tag+ = PWrap $ packByTagPA xs tags tag++ {-# INLINE_PDATA combine2PR #-}+ combine2PR sel (PWrap xs) (PWrap ys)+ = PWrap $ combine2PA sel xs ys+++ -- Conversions --------------------------------+ {-# NOINLINE fromVectorPR #-}+ fromVectorPR vec + = PWrap $ fromVectorPA $ V.map unWrap vec+ + {-# NOINLINE toVectorPR #-}+ toVectorPR (PWrap pdata)+ = V.map Wrap $ toVectorPA pdata+++ -- PDatas -------------------------------------+ {-# INLINE_PDATA emptydPR #-}+ emptydPR + = PWraps emptydPA++ {-# INLINE_PDATA singletondPR #-}+ singletondPR (PWrap pdata)+ = PWraps $ singletondPA pdata+ + {-# INLINE_PDATA lengthdPR #-}+ lengthdPR (PWraps pdatas)+ = lengthdPA pdatas+ + {-# INLINE_PDATA indexdPR #-}+ indexdPR (PWraps pdatas) ix+ = PWrap $ indexdPA pdatas ix++ {-# INLINE_PDATA appenddPR #-}+ appenddPR (PWraps xs) (PWraps ys)+ = PWraps $ appenddPA xs ys++ {-# NOINLINE fromVectordPR #-}+ fromVectordPR vec+ = PWraps $ fromVectordPA $ V.map (\(PWrap x) -> x) vec++ {-# NOINLINE toVectordPR #-}+ toVectordPR (PWraps pdatas)+ = V.map PWrap $ toVectordPA pdatas+ ++
+ Data/Array/Parallel/PArray/PRepr.hs view
@@ -0,0 +1,57 @@+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE CPP #-}+#include "fusion-phases.h"++-- | Defines the `PRepr` family and `PA` class that converts between the user+-- level element types and our generic representation.+-- Apart from `unpackPA`, the `PA` wrapper functions defined here all have+-- equivalent `PR` versions in "Data.Array.Parallel.PArray.PData",+-- so see there for documentation.+module Data.Array.Parallel.PArray.PRepr+ ( module Data.Array.Parallel.PArray.PRepr.Base+ , module Data.Array.Parallel.PArray.PRepr.Instances++ -- * Nested Arrays+ , module Data.Array.Parallel.PArray.PRepr.Nested+ , unpackPA++ -- * Tuple Arrays+ , module Data.Array.Parallel.PArray.PRepr.Tuple)+where+import Data.Array.Parallel.PArray.PRepr.Base+import Data.Array.Parallel.PArray.PRepr.Instances+import Data.Array.Parallel.PArray.PRepr.Nested+import Data.Array.Parallel.PArray.PRepr.Tuple+import Data.Array.Parallel.PArray.PData+import Data.Array.Parallel.Pretty+import qualified Data.Vector as V+++-- Pretty -------------------------------------------------------------------+instance (Show a, PA a)+ => Show (PArray a) where+ show (PArray _ pdata)+ = render + $ brackets + $ text "|"+ <> (hcat $ punctuate comma + $ map (text . show) $ V.toList $ toVectorPA pdata)+ <> text "|"+++instance (PprVirtual a, PA a)+ => PprVirtual (PArray a) where+ pprv (PArray _ pdata)+ = brackets + $ text "|"+ <> (hcat $ punctuate comma + $ map pprv $ V.toList $ toVectorPA pdata)+ <> text "|"+++-- Unpack ----------------------------------------------------------------------+-- | Unpack an array to reveal its representation.+{-# INLINE_PA unpackPA #-}+unpackPA :: PA a => PArray a -> PData (PRepr a)+unpackPA (PArray _ pdata)+ = toArrPRepr pdata
+ Data/Array/Parallel/PArray/PRepr/Base.hs view
@@ -0,0 +1,312 @@+{-# OPTIONS_HADDOCK hide #-}+{-# LANGUAGE CPP #-}+#include "fusion-phases.h"++-- | Definition of the PRepr/PA family and class.+-- This module manages the conversion between the user level view of the +-- element data, and our internal generic view.+module Data.Array.Parallel.PArray.PRepr.Base + ( PRepr+ , PA (..)+ , toNestedArrPRepr++ -- * House Keeping+ , validPA+ , nfPA+ , similarPA+ , coversPA+ , pprpPA+ , pprpDataPA++ -- * Constructors+ , emptyPA+ , replicatePA, replicatesPA+ , appendPA, appendsPA++ -- * Projections+ , lengthPA+ , indexPA, indexsPA, indexvsPA+ , bpermutePA+ , extractPA, extractssPA, extractvsPA++ -- * Pack and Combine+ , packByTagPA+ , combine2PA++ -- * Conversions + , fromVectorPA, toVectorPA++ -- * PDatas+ , emptydPA+ , singletondPA+ , lengthdPA+ , indexdPA+ , appenddPA+ , fromVectordPA, toVectordPA)+where+import Data.Array.Parallel.Pretty+import Data.Array.Parallel.PArray.PData.Base+import Data.Array.Parallel.PArray.PData.Nested+import Data.Array.Parallel.Base (Tag)+import Data.Vector (Vector)+import qualified Data.Array.Parallel.Unlifted as U+import qualified Data.Vector as V++-- PRepr / PA -----------------------------------------------------------------+-- | Family of Representable types. These are the types that we know how to+-- represent generically. `PRepr` takes an arbitrary type and produces the+-- generic type we use to represent it.+--+-- Instances for simple types are defined by the library. +-- For algebraic types, it's up to the vectoriser/client module to create+-- a suitable instance.+--+type family PRepr a+++-- | A PA dictionary contains the functions that we use to convert a+-- representable type to and from its generic representation.+--+-- The conversions methods should all be O(1). +class PR (PRepr a) => PA a where+ toPRepr :: a -> PRepr a+ fromPRepr :: PRepr a -> a++ toArrPRepr :: PData a -> PData (PRepr a)+ fromArrPRepr :: PData (PRepr a) -> PData a++ toArrPReprs :: PDatas a -> PDatas (PRepr a)+ fromArrPReprs :: PDatas (PRepr a) -> PDatas a+++-- | Convert a nested array to its generic representation.+toNestedArrPRepr+ :: PA a + => PData (PArray a)+ -> PData (PArray (PRepr a))++toNestedArrPRepr (PNested vsegd pdatas segd flat)+ = PNested vsegd (toArrPReprs pdatas) segd (toArrPRepr flat)+++-- PA Wrappers ----------------------------------------------------------------+-- These wrappers work on (PData a) arrays when we know the element type 'a'+-- is generically representable. We implement the array operators by converting+-- the PData to our generic representation type, and use the corresponding+-- method from the PR dictionary.+--+-- The wrappers are used in situations when we only have PA dictionary, +-- instead of a PR dictionary. This happens in the PR (a :-> b) instance, +-- as we need to work on a generically represented environment, and only+-- have an existential PA dictionary. We also use them in the PA functions+-- defined by D.A.P.PArray.+--+-- See the D.A.P.PArray.PData.Base for docs on what these functions do.+-- Each of the following functions has a corresponding method in the PR class.+--+{-# INLINE_PA validPA #-}+validPA :: PA a => PData a -> Bool+validPA arr+ = validPR (toArrPRepr arr)+++{-# INLINE_PA nfPA #-}+nfPA :: PA a => PData a -> ()+nfPA arr+ = nfPR + $ toArrPRepr arr+++{-# INLINE_PA similarPA #-}+similarPA :: PA a => a -> a -> Bool+similarPA x y+ = similarPR (toPRepr x) (toPRepr y)+++{-# INLINE_PA coversPA #-}+coversPA :: PA a => Bool -> PData a -> Int -> Bool+coversPA weak pdata ix+ = coversPR weak (toArrPRepr pdata) ix+++{-# INLINE_PA pprpPA #-}+pprpPA :: PA a => a -> Doc+pprpPA x+ = pprpPR (toPRepr x)+++{-# INLINE_PA pprpDataPA #-}+pprpDataPA :: PA a => PData a -> Doc+pprpDataPA x+ = pprpDataPR (toArrPRepr x)+++-- Constructors ---------------------------------+{-# INLINE_PA emptyPA #-}+emptyPA :: PA a => PData a+emptyPA + = fromArrPRepr emptyPR+++{-# INLINE_PA replicatePA #-}+replicatePA :: PA a => Int -> a -> PData a+replicatePA n x+ = fromArrPRepr+ $ replicatePR n $ toPRepr x+++{-# INLINE_PA replicatesPA #-}+replicatesPA :: PA a => U.Segd -> PData a -> PData a+replicatesPA segd xs+ = fromArrPRepr+ $ replicatesPR segd (toArrPRepr xs)+++{-# INLINE_PA appendPA #-}+appendPA :: PA a => PData a -> PData a -> PData a+appendPA xs ys+ = fromArrPRepr+ $ appendPR (toArrPRepr xs) (toArrPRepr ys)+++{-# INLINE_PA appendsPA #-}+appendsPA :: PA a => U.Segd -> U.Segd -> PData a -> U.Segd + -> PData a -> PData a+appendsPA segdResult segd1 xs segd2 ys+ = fromArrPRepr+ $ appendsPR segdResult segd1 (toArrPRepr xs) segd2 (toArrPRepr ys)+++-- Projections ----------------------------------+{-# INLINE_PA lengthPA #-}+lengthPA :: PA a => PData a -> Int+lengthPA xs+ = lengthPR (toArrPRepr xs)+++{-# INLINE_PA indexPA #-}+indexPA :: PA a => PData a -> Int -> a+indexPA xs i+ = fromPRepr + $ indexPR (toArrPRepr xs) i+++{-# INLINE_PA indexsPA #-}+indexsPA :: PA a => PDatas a -> U.Array (Int, Int) -> PData a+indexsPA pdatas srcixs+ = fromArrPRepr+ $ indexsPR (toArrPReprs pdatas) srcixs+++{-# INLINE_PA indexvsPA #-}+indexvsPA :: PA a => PDatas a -> U.VSegd -> U.Array (Int, Int) -> PData a+indexvsPA pdatas vsegd srcixs+ = fromArrPRepr+ $ indexvsPR (toArrPReprs pdatas) vsegd srcixs+++{-# INLINE_PDATA bpermutePA #-}+bpermutePA :: PA a => PData a -> U.Array Int -> PData a+bpermutePA xs ixs+ = fromArrPRepr+ $ bpermutePR (toArrPRepr xs) ixs+++{-# INLINE_PA extractPA #-}+extractPA :: PA a => PData a -> Int -> Int -> PData a+extractPA xs start len+ = fromArrPRepr+ $ extractPR (toArrPRepr xs) start len+++{-# INLINE_PA extractssPA #-}+extractssPA :: PA a => PDatas a -> U.SSegd -> PData a+extractssPA xss segd+ = fromArrPRepr+ $ extractssPR (toArrPReprs xss) segd+++{-# INLINE_PA extractvsPA #-}+extractvsPA :: PA a => PDatas a -> U.VSegd -> PData a+extractvsPA xss segd+ = fromArrPRepr+ $ extractvsPR (toArrPReprs xss) segd+++-- Pack and Combine -----------------------------+{-# INLINE_PA packByTagPA #-}+packByTagPA :: PA a => PData a -> U.Array Tag -> Tag -> PData a+packByTagPA xs tags tag+ = fromArrPRepr+ $ packByTagPR (toArrPRepr xs) tags tag+++{-# INLINE_PA combine2PA #-}+combine2PA :: PA a => U.Sel2 -> PData a -> PData a -> PData a+combine2PA sel xs ys+ = fromArrPRepr+ $ combine2PR sel (toArrPRepr xs) (toArrPRepr ys)+ + +-- Conversions ----------------------------------+{-# INLINE_PA fromVectorPA #-}+fromVectorPA :: PA a => Vector a -> PData a+fromVectorPA vec+ = fromArrPRepr+ $ fromVectorPR (V.map toPRepr vec)+++{-# INLINE_PA toVectorPA #-}+toVectorPA :: PA a => PData a -> Vector a+toVectorPA pdata+ = V.map fromPRepr+ $ toVectorPR (toArrPRepr pdata)+ ++{-# INLINE_PA emptydPA #-}+emptydPA :: PA a => PDatas a+emptydPA + = fromArrPReprs+ $ emptydPR++ +{-# INLINE_PA singletondPA #-}+singletondPA :: PA a => PData a -> PDatas a+singletondPA pdata+ = fromArrPReprs+ $ singletondPR (toArrPRepr pdata)+++{-# INLINE_PA lengthdPA #-}+lengthdPA :: PA a => PDatas a -> Int+lengthdPA pdatas+ = lengthdPR (toArrPReprs pdatas)+++{-# INLINE_PA indexdPA #-}+indexdPA :: PA a => PDatas a -> Int -> PData a+indexdPA pdatas ix+ = fromArrPRepr+ $ indexdPR (toArrPReprs pdatas) ix+ + +{-# INLINE_PA appenddPA #-}+appenddPA :: PA a => PDatas a -> PDatas a -> PDatas a+appenddPA xs ys+ = fromArrPReprs+ $ appenddPR (toArrPReprs xs) (toArrPReprs ys)+++{-# INLINE_PA fromVectordPA #-}+fromVectordPA :: PA a => V.Vector (PData a) -> PDatas a+fromVectordPA vec+ = fromArrPReprs+ $ fromVectordPR (V.map toArrPRepr vec)+++{-# INLINE_PA toVectordPA #-}+toVectordPA :: PA a => PDatas a -> V.Vector (PData a)+toVectordPA pdatas+ = V.map fromArrPRepr + $ toVectordPR (toArrPReprs pdatas)+
+ Data/Array/Parallel/PArray/PRepr/Instances.hs view
@@ -0,0 +1,203 @@+{-# OPTIONS_HADDOCK hide #-}+{-# LANGUAGE CPP, UndecidableInstances #-}+#include "fusion-phases.h"++-- | Simple instances for the PRRepr/PA family and class.+-- This module is kept separate from PRepr.Base to break an import cycle+-- between PRepr.Base PRepr.Instances and PArray.PData.Wrap+--+module Data.Array.Parallel.PArray.PRepr.Instances where+import Data.Array.Parallel.PArray.Types+import Data.Array.Parallel.PArray.PRepr.Base+import Data.Array.Parallel.PArray.PData.Base++import Data.Array.Parallel.PArray.PData.Void+import Data.Array.Parallel.PArray.PData.Sum2 +import Data.Array.Parallel.PArray.PData.Word8+import Data.Array.Parallel.PArray.PData.Wrap ()+import Data.Array.Parallel.PArray.PData.Unit ()+import Data.Array.Parallel.PArray.PData.Nested ()+import Data.Array.Parallel.PArray.PData.Tuple2 ()+import Data.Array.Parallel.PArray.PData.Int ()+import Data.Array.Parallel.PArray.PData.Double ()+import qualified Data.Array.Parallel.Unlifted as U+import qualified Data.Vector as V+import Data.Word+++-- Void -----------------------------------------------------------------------+type instance PRepr Void = Void++instance PA Void where+ toPRepr = id+ fromPRepr = id+ toArrPRepr = id+ fromArrPRepr = id+ toArrPReprs = id+ fromArrPReprs = id+++-- Unit -----------------------------------------------------------------------+type instance PRepr () = ()++instance PA () where+ toPRepr = id+ fromPRepr = id+ toArrPRepr = id+ fromArrPRepr = id+ toArrPReprs = id+ fromArrPReprs = id+++-- Int ------------------------------------------------------------------------+type instance PRepr Int = Int++instance PA Int where+ toPRepr = id+ fromPRepr = id+ toArrPRepr = id+ fromArrPRepr = id+ toArrPReprs = id+ fromArrPReprs = id+++-- Int ------------------------------------------------------------------------+type instance PRepr Word8 = Word8++instance PA Word8 where+ toPRepr = id+ fromPRepr = id+ toArrPRepr = id+ fromArrPRepr = id+ toArrPReprs = id+ fromArrPReprs = id+++-- Double ---------------------------------------------------------------------+type instance PRepr Double = Double++instance PA Double where+ toPRepr = id+ fromPRepr = id+ toArrPRepr = id+ fromArrPRepr = id+ toArrPReprs = id+ fromArrPReprs = id+ + +-- Bool -----------------------------------------------------------------------+-- | We use the `Void` type for both sides because we only care about the tag.+-- The `Void` fields don't use any space at runtime.+type instance PRepr Bool+ = Sum2 Void Void++data instance PData Bool+ = PBool U.Sel2++data instance PDatas Bool+ = PBools (V.Vector U.Sel2)++instance PA Bool where+ {-# INLINE toPRepr #-}+ toPRepr False = Alt2_1 void+ toPRepr True = Alt2_2 void++ {-# INLINE fromPRepr #-}+ fromPRepr (Alt2_1 _) = False+ fromPRepr (Alt2_2 _) = True++ {-# INLINE toArrPRepr #-}+ toArrPRepr (PBool sel) + = PSum2 sel pvoid pvoid++ {-# INLINE fromArrPRepr #-}+ fromArrPRepr (PSum2 sel _ _)+ = PBool sel++ {-# INLINE toArrPReprs #-}+ toArrPReprs (PBools sels)+ = PSum2s sels+ (pvoids $ V.length sels)+ (pvoids $ V.length sels)++ {-# INLINE fromArrPReprs #-}+ fromArrPReprs (PSum2s sels _ _)+ = PBools sels+++-- Ordering -------------------------------------------------------------------+type instance PRepr Ordering+ = Word8++data instance PData Ordering+ = POrdering (U.Array Word8)+ +data instance PDatas Ordering+ = POrderings (U.Arrays Word8)++instance PA Ordering where+ {-# INLINE toPRepr #-}+ toPRepr LT = 0+ toPRepr EQ = 1+ toPRepr GT = 2+ + {-# INLINE fromPRepr #-}+ fromPRepr 0 = LT+ fromPRepr 1 = EQ+ fromPRepr 2 = GT+ fromPRepr _ = error "dph-prim-vseg: bad value converting Word8 to Ordering"+ + {-# INLINE toArrPRepr #-}+ toArrPRepr (POrdering arr)+ = PWord8 arr+ + {-# INLINE fromArrPRepr #-}+ fromArrPRepr (PWord8 arr)+ = POrdering arr++ {-# INLINE toArrPReprs #-}+ toArrPReprs (POrderings arrs)+ = PWord8s arrs+ + {-# INLINE fromArrPReprs #-}+ fromArrPReprs (PWord8s arrs)+ = POrderings arrs+++-- Either ---------------------------------------------------------------------+type instance PRepr (Either a b)+ = Sum2 a b+ +data instance PData (Either a b)+ = PEither U.Sel2 (PData a) (PData b)++data instance PDatas (Either a b)+ = PEithers (V.Vector U.Sel2) (PDatas a) (PDatas b)++instance (PR a, PR b) => PA (Either a b) where+ {-# INLINE toPRepr #-}+ toPRepr xx+ = case xx of+ Left x -> Alt2_1 x+ Right y -> Alt2_2 y++ {-# INLINE fromPRepr #-}+ fromPRepr (Alt2_1 x) = Left x+ fromPRepr (Alt2_2 x) = Right x++ {-# INLINE toArrPRepr #-}+ toArrPRepr (PEither sel pdata1 pdata2)+ = PSum2 sel pdata1 pdata2+ + {-# INLINE fromArrPRepr #-}+ fromArrPRepr (PSum2 sel pdata1 pdata2)+ = PEither sel pdata1 pdata2++ {-# INLINE toArrPReprs #-}+ toArrPReprs (PEithers sels pdatas1 pdatas2)+ = PSum2s sels pdatas1 pdatas2++ {-# INLINE fromArrPReprs #-}+ fromArrPReprs (PSum2s sels pdatas1 pdatas2)+ = PEithers sels pdatas1 pdatas2+
+ Data/Array/Parallel/PArray/PRepr/Nested.hs view
@@ -0,0 +1,106 @@+{-# OPTIONS_HADDOCK hide #-}+{-# LANGUAGE CPP #-}+#include "fusion-phases.h"++-- | PRepr/PA instance for nested arrays, +-- and PA wrappers for other functions defined in D.A.P.PArray.PData.Nested.+module Data.Array.Parallel.PArray.PRepr.Nested+ ( mkPNestedPA+ , concatPA, concatlPA+ , unconcatPA+ , appendlPA+ , indexlPA+ , slicelPA)+where+import Data.Array.Parallel.PArray.PRepr.Base+import Data.Array.Parallel.PArray.PData.Base+import Data.Array.Parallel.PArray.PData.Nested+import qualified Data.Array.Parallel.Unlifted as U+import qualified Data.Vector as V+++-- PArray ---------------------------------------------------------------------+type instance PRepr (PArray a)+ = PArray (PRepr a)++instance PA a => PA (PArray a) where+ {-# INLINE_PA toPRepr #-}+ toPRepr (PArray n xs) + = PArray n $ toArrPRepr xs++ {-# INLINE_PA fromPRepr #-}+ fromPRepr (PArray n xs)+ = PArray n $ fromArrPRepr xs++ {-# INLINE_PA toArrPRepr #-}+ toArrPRepr (PNested vsegd xs segd flat)+ = PNested vsegd (toArrPReprs xs) segd (toArrPRepr flat)++ {-# INLINE_PA fromArrPRepr #-}+ fromArrPRepr (PNested vsegd xs segd flat)+ = PNested vsegd (fromArrPReprs xs) segd (fromArrPRepr flat)++ {-# INLINE_PA toArrPReprs #-}+ toArrPReprs (PNesteds vec)+ = PNesteds $ V.map toArrPRepr vec++ {-# INLINE_PA fromArrPReprs #-}+ fromArrPReprs (PNesteds vec)+ = PNesteds $ V.map fromArrPRepr vec+++-- PA Wrappers ----------------------------------------------------------------+-- These wrappers have the same types in the ones in D.A.P.PArray.PData.Nested,+-- except that they take a PA dictionary instead of a PR dictionary.+--+-- See D.A.P.PArray.PRepr.Base for docs on why we need the wrappers.+-- See D.A.P.PArray.PData.Nested for docs on what the PR versions do.+--+-- | Conatruct a nested array.+mkPNestedPA + :: PA a+ => U.VSegd -> PDatas a+ -> U.Segd -> PData a+ -> PData (PArray a)++mkPNestedPA vsegd pdatas segd pdata+ = let pdatas' = toArrPReprs pdatas+ pdata' = toArrPRepr pdata+ in fromArrPRepr $ mkPNested vsegd pdatas' segd pdata'+++concatPA :: PA a => PData (PArray a) -> PData a+concatPA arr+ = fromArrPRepr $ concatPR $ toArrPRepr arr+{-# INLINE_PA concatPA #-}+ + +unconcatPA :: (PA a, PA b) => PData (PArray a) -> PData b -> PData (PArray b)+unconcatPA arr1 arr2+ = fromArrPRepr $ unconcatPR (toArrPRepr arr1) (toArrPRepr arr2)+{-# INLINE_PA unconcatPA #-}+++concatlPA :: PA a => PData (PArray (PArray a)) -> PData (PArray a)+concatlPA arr+ = fromArrPRepr $ concatlPR (toArrPRepr arr)+{-# INLINE_PA concatlPA #-}+++appendlPA :: PA a => PData (PArray a) -> PData (PArray a) -> PData (PArray a)+appendlPA arr1 arr2+ = fromArrPRepr $ appendlPR (toArrPRepr arr1) (toArrPRepr arr2)+{-# INLINE_PA appendlPA #-}+++indexlPA :: PA a => PData (PArray a) -> PData Int -> PData a+indexlPA arr ixs+ = fromArrPRepr $ indexlPR (toArrPRepr arr) ixs+{-# INLINE_PA indexlPA #-}+++slicelPA :: PA a => PData Int -> PData Int -> PData (PArray a) -> PData (PArray a)+slicelPA starts lens arr+ = fromArrPRepr $ slicelPR starts lens (toArrPRepr arr)+{-# INLINE_PA slicelPA #-}+
+ Data/Array/Parallel/PArray/PRepr/Tuple.hs view
@@ -0,0 +1,156 @@+{-# OPTIONS_HADDOCK hide #-}+{-# LANGUAGE CPP #-}+#include "fusion-phases.h"++-- | PRepr instance for tuples+-- and PD wrappers for other functions defined in D.A.P.PArray.PData.Tuple.+module Data.Array.Parallel.PArray.PRepr.Tuple+ ( PRepr+ , ziplPA)+where+import Data.Array.Parallel.PArray.Types+import Data.Array.Parallel.PArray.PRepr.Base+import Data.Array.Parallel.PArray.PData.Base+import Data.Array.Parallel.PArray.PData.Tuple2+import Data.Array.Parallel.PArray.PData.Tuple3+import Data.Array.Parallel.PArray.PData.Tuple4+import Data.Array.Parallel.PArray.PData.Tuple5+import Data.Array.Parallel.PArray.PData.Nested+import Data.Array.Parallel.PArray.PData.Wrap+++-- Tuple2 --------------------------------------------------------------------+type instance PRepr (a, b)+ = (Wrap a, Wrap b)++instance (PA a, PA b) => PA (a, b) where+ {-# INLINE_PA toPRepr #-}+ toPRepr (a, b)+ = (Wrap a, Wrap b)++ {-# INLINE_PA fromPRepr #-}+ fromPRepr (Wrap a, Wrap b)+ = (a, b)++ {-# INLINE_PA toArrPRepr #-}+ toArrPRepr (PTuple2 as bs)+ = PTuple2 (PWrap as) (PWrap bs)++ {-# INLINE_PA fromArrPRepr #-}+ fromArrPRepr (PTuple2 (PWrap as) (PWrap bs))+ = PTuple2 as bs++ {-# INLINE_PA toArrPReprs #-}+ toArrPReprs (PTuple2s as bs)+ = PTuple2s (PWraps as) (PWraps bs)++ {-# INLINE_PA fromArrPReprs #-}+ fromArrPReprs (PTuple2s (PWraps as) (PWraps bs))+ = PTuple2s as bs+++-- | Lifted zip on PData arrays.+ziplPA :: (PA a, PA b) + => PData (PArray a) -> PData (PArray b) -> PData (PArray (a, b))+ziplPA xs ys+ = let + -- TODO: can we use the flat version here?+ PNested vsegd (PTuple2s xs' ys') segd _+ = ziplPR (toNestedArrPRepr xs) (toNestedArrPRepr ys)++ pdatas = PTuple2s (fromArrPReprs xs') (fromArrPReprs ys')+ flat = fromArrPRepr $ extractvs_delay (toArrPReprs pdatas) vsegd++ in PNested vsegd pdatas segd flat+ ++-- Tuple3 --------------------------------------------------------------------+type instance PRepr (a, b, c)+ = (Wrap a, Wrap b, Wrap c)++instance (PA a, PA b, PA c) => PA (a, b, c) where+ {-# INLINE_PA toPRepr #-}+ toPRepr (a, b, c)+ = (Wrap a, Wrap b, Wrap c)++ {-# INLINE_PA fromPRepr #-}+ fromPRepr (Wrap a, Wrap b, Wrap c)+ = (a, b, c)++ {-# INLINE_PA toArrPRepr #-}+ toArrPRepr (PTuple3 as bs cs)+ = PTuple3 (PWrap as) (PWrap bs) (PWrap cs)++ {-# INLINE_PA fromArrPRepr #-}+ fromArrPRepr (PTuple3 (PWrap as) (PWrap bs) (PWrap cs))+ = PTuple3 as bs cs++ {-# INLINE_PA toArrPReprs #-}+ toArrPReprs (PTuple3s as bs cs)+ = PTuple3s (PWraps as) (PWraps bs) (PWraps cs)++ {-# INLINE_PA fromArrPReprs #-}+ fromArrPReprs (PTuple3s (PWraps as) (PWraps bs) (PWraps cs))+ = PTuple3s as bs cs+++-- Tuple4 --------------------------------------------------------------------+type instance PRepr (a, b, c, d)+ = (Wrap a, Wrap b, Wrap c, Wrap d)++instance (PA a, PA b, PA c, PA d) => PA (a, b, c, d) where+ {-# INLINE_PA toPRepr #-}+ toPRepr (a, b, c, d)+ = (Wrap a, Wrap b, Wrap c, Wrap d)++ {-# INLINE_PA fromPRepr #-}+ fromPRepr (Wrap a, Wrap b, Wrap c, Wrap d)+ = (a, b, c, d)++ {-# INLINE_PA toArrPRepr #-}+ toArrPRepr (PTuple4 as bs cs ds)+ = PTuple4 (PWrap as) (PWrap bs) (PWrap cs) (PWrap ds)++ {-# INLINE_PA fromArrPRepr #-}+ fromArrPRepr (PTuple4 (PWrap as) (PWrap bs) (PWrap cs) (PWrap ds))+ = PTuple4 as bs cs ds++ {-# INLINE_PA toArrPReprs #-}+ toArrPReprs (PTuple4s as bs cs ds)+ = PTuple4s (PWraps as) (PWraps bs) (PWraps cs) (PWraps ds)++ {-# INLINE_PA fromArrPReprs #-}+ fromArrPReprs (PTuple4s (PWraps as) (PWraps bs) (PWraps cs) (PWraps ds))+ = PTuple4s as bs cs ds+++-- Tuple4 --------------------------------------------------------------------+type instance PRepr (a, b, c, d, e)+ = (Wrap a, Wrap b, Wrap c, Wrap d, Wrap e)++instance (PA a, PA b, PA c, PA d, PA e) => PA (a, b, c, d, e) where+ {-# INLINE_PA toPRepr #-}+ toPRepr (a, b, c, d, e)+ = (Wrap a, Wrap b, Wrap c, Wrap d, Wrap e)++ {-# INLINE_PA fromPRepr #-}+ fromPRepr (Wrap a, Wrap b, Wrap c, Wrap d, Wrap e)+ = (a, b, c, d, e)++ {-# INLINE_PA toArrPRepr #-}+ toArrPRepr (PTuple5 as bs cs ds es)+ = PTuple5 (PWrap as) (PWrap bs) (PWrap cs) (PWrap ds) (PWrap es)++ {-# INLINE_PA fromArrPRepr #-}+ fromArrPRepr (PTuple5 (PWrap as) (PWrap bs) (PWrap cs) (PWrap ds) (PWrap es))+ = PTuple5 as bs cs ds es++ {-# INLINE_PA toArrPReprs #-}+ toArrPReprs (PTuple5s as bs cs ds es)+ = PTuple5s (PWraps as) (PWraps bs) (PWraps cs) (PWraps ds) (PWraps es)++ {-# INLINE_PA fromArrPReprs #-}+ fromArrPReprs (PTuple5s (PWraps as) (PWraps bs) (PWraps cs) (PWraps ds) (PWraps es))+ = PTuple5s as bs cs ds es++
+ Data/Array/Parallel/PArray/Scalar.hs view
@@ -0,0 +1,313 @@+{-# LANGUAGE CPP #-}+#include "fusion-phases.h"++{-# OPTIONS_GHC -fno-warn-unused-binds #-}++-- | Functions that work on parallel arrays of scalar elements.+-- Unlike the functions defined in D.A.P.PArray, these only need+-- Scalar dictionaries, instead of PR or PA dictionaries. +--+-- They are used when defining vectorised Prelude functions, +-- eg in D.A.P.Prelude.Int and D.A.P.Prelude.Double.+--+-- The map and zipWith functions are also used by the vectoriser when+-- vectorising uses of scalar operators like (+).+--+module Data.Array.Parallel.PArray.Scalar + ( Scalar(..)++ -- * Conversions+ , toUArray, fromUArray+ , fromUArray2++ -- * Maps and Zips+ , map+ , zipWith+ , zipWith3+ + -- * Folds+ , fold, folds+ , fold1, fold1s+ , fold1Index, fold1sIndex+ + -- * Enumerations+ , enumFromTo, enumFromTol)+where+import Data.Array.Parallel.PArray.PData.Void+import Data.Array.Parallel.PArray.PData.Word8+import Data.Array.Parallel.PArray.PData.Double+import Data.Array.Parallel.PArray.PData+import Data.Array.Parallel.PArray.PRepr+import Data.Array.Parallel.Base+import Data.Word+import GHC.Exts+import qualified Data.Array.Parallel.Unlifted as U+import Prelude hiding ( map, zipWith, zipWith3, enumFromTo)+++-- | Class of Scalar data that can be converted to and from single unboxed+-- vectors.+class (PA a, U.Elt a) => Scalar a where+ fromScalarPData :: PData a -> U.Array a+ toScalarPData :: U.Array a -> PData a+ + fromScalarPDatas :: PDatas a -> U.Arrays a+ toScalarPDatas :: U.Arrays a -> PDatas a+++-- Shorthands for the above methods used in this module only.+from :: Scalar a => PData a -> U.Array a+from = fromScalarPData++to :: Scalar a => U.Array a -> PData a+to = toScalarPData+++-- Instances --------------------------------------------------------------+instance Scalar Bool where+ {-# INLINE toScalarPData #-}+ toScalarPData bs+ = PBool (U.tagsToSel2 (U.map fromBool bs))++ {-# INLINE fromScalarPData #-}+ fromScalarPData (PBool sel)+ = U.map toBool (U.tagsSel2 sel)++ -- NOTE: There is no Arrays instance for Bool, + -- but we don't need it yet because the PDatas Sel2s instance+ -- just uses a boxed vector of Sel2s.+ {-# NOINLINE fromScalarPDatas #-}+ fromScalarPDatas _+ = error "Data.Array.Parallel.PArray.Lifted.Scalar: no Arrays instance for Bool."++ {-# NOINLINE toScalarPDatas #-}+ toScalarPDatas _+ = error "Data.Array.Parallel.PArray.Lifted.Scalar: no Arrays instance for Bool."++instance U.Elt Ordering++instance Scalar Ordering where+ {-# INLINE toScalarPData #-}+ toScalarPData+ = POrdering . U.map toPRepr++ {-# INLINE fromScalarPData #-}+ fromScalarPData (POrdering w8s)+ = U.map fromPRepr w8s++ -- FIXME: no idea whether these are used; should be possible to convert, though+ {-# INLINE toScalarPDatas #-}+ toScalarPDatas _+ = error "Data.Array.Parallel.PArray.Lifted.Scalar: no 'Arrays' instance for 'Ordering'."++ {-# INLINE fromScalarPDatas #-}+ fromScalarPDatas _+ = error "Data.Array.Parallel.PArray.Lifted.Scalar: no 'Arrays' instance for 'Ordering'."++-- FIXME: this is a fake instance to enable us to vectorise 'Num'+type instance PRepr Integer = Void+data instance PData Integer = PInteger+data instance PDatas Integer = PIntegers+instance PA Integer+instance U.Elt Integer+instance Scalar Integer where+ toScalarPData = fakeScalarInteger+ fromScalarPData = fakeScalarInteger+ toScalarPDatas = fakeScalarInteger+ fromScalarPDatas = fakeScalarInteger+fakeScalarInteger :: a+fakeScalarInteger = error "D.A.P.PArray.Scalar: fake instance 'Scalar Integer'"++-- See Note: Seqs in fromScalar+instance Scalar Int where+ fromScalarPData (PInt xs) = xs `seq` xs+ fromScalarPDatas (PInts xss) = xss `seq` xss+ toScalarPData = PInt+ toScalarPDatas = PInts++instance Scalar Word8 where+ fromScalarPData (PWord8 xs) = xs `seq` xs+ fromScalarPDatas (PWord8s xss) = xss `seq` xss+ toScalarPData = PWord8+ toScalarPDatas = PWord8s++instance Scalar Double where+ fromScalarPData (PDouble xs) = xs `seq` xs+ fromScalarPDatas (PDoubles xss) = xss `seq` xss+ toScalarPData = PDouble+ toScalarPDatas = PDoubles+++-- [Note: Seqs in fromScalar]+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~+-- As we expect the result of fromScalarPData to always be demanded by the +-- consuming function, we seq on it to force the demand. This helps to avoid+-- fusion problems when GHC can't see that the consumer actually demands the+-- data. This shows up in SMVM where removing the `seq in the Doubles instance+-- prevents the fold_vs/promoteSegdToVSegd rule from firing.+ +-- Conversions ----------------------------------------------------------------+{-# INLINE_PA fromUArray #-}+fromUArray :: Scalar a => U.Array a -> PArray a+fromUArray uarr+ = let !(I# n#) = U.length uarr+ in PArray n# (toScalarPData uarr) + + +{-# INLINE_PA toUArray #-}+toUArray :: Scalar a => PArray a -> U.Array a+toUArray (PArray _ pdata)+ = fromScalarPData pdata+ ++-- Tuple Conversions ----------------------------------------------------------+-- | Convert an U.Array of pairs to a PArray.+{-# INLINE fromUArray2 #-}+fromUArray2+ :: (Scalar a, Scalar b)+ => U.Array (a, b) -> PArray (a, b)+fromUArray2 ps+ = let !(I# n#) = U.length ps+ (xs,ys) = U.unzip ps+ in PArray n# (PTuple2 (toScalarPData xs) (toScalarPData ys))+ ++-- Maps and Zips --------------------------------------------------------------+-- | Apply a worker function to every element of an array, yielding a new array.+{-# INLINE_PA map #-}+map :: (Scalar a, Scalar b) + => (a -> b) -> PArray a -> PArray b++map f (PArray len xs)+ = PArray len $ to $ U.map f (from xs)+++-- | Zip two arrays, yielding a new array.+{-# INLINE_PA zipWith #-}+zipWith :: (Scalar a, Scalar b, Scalar c)+ => (a -> b -> c) -> PArray a -> PArray b -> PArray c++zipWith f (PArray len xs) (PArray _ ys)+ = PArray len $ to $ U.zipWith f (from xs) (from ys)+++-- | Zip three arrays, yielding a new array.+{-# INLINE_PA zipWith3 #-}+zipWith3+ :: (Scalar a, Scalar b, Scalar c, Scalar d)+ => (a -> b -> c -> d) -> PArray a -> PArray b -> PArray c -> PArray d++zipWith3 f (PArray len xs) (PArray _ ys) (PArray _ zs)+ = PArray len $ to $ U.zipWith3 f (from xs) (from ys) (from zs)+++-- Folds ----------------------------------------------------------------------+-- | Left fold over an array.+{-# INLINE_PA fold #-}+fold :: Scalar a + => (a -> a -> a) -> a -> PArray a -> a++fold f !z (PArray _ pdata)+ = U.fold f z $ from pdata+++-- | Left fold over an array, using the first element to initialise the state.+{-# INLINE_PA fold1 #-}+fold1 :: Scalar a+ => (a -> a -> a) -> PArray a -> a++fold1 f (PArray _ pdata)+ = U.fold1 f $ from pdata+++-- | Segmented fold of an array of arrays.+folds :: (Scalar a, U.Elts a)+ => (a -> a -> a) -> a -> PArray (PArray a) -> PArray a++folds f !z (PArray _ (PNested vsegd pdatas _ _))+ = pdatas `seq` -- Don't seq on vsegd. See Note: fold/promoteSegd+ fromUArray $ U.fold_vs f z vsegd $ fromScalarPDatas pdatas+{-# INLINE_PA folds #-}+ ++-- | Segmented fold of an array of arrays, using the first element of each+-- segment to initialse the state for that segment.+fold1s :: (Scalar a, U.Elts a)+ => (a -> a -> a) -> PArray (PArray a) -> PArray a++fold1s f (PArray _ (PNested vsegd pdatas _ _))+ = pdatas `seq` -- Don't seq on vsegd. See Note: fold/promoteSegd+ fromUArray $ U.fold1_vs f vsegd $ fromScalarPDatas pdatas+{-# INLINE_PA fold1s #-}+++-- | Left fold over an array, also passing the index of each element+-- to the parameter function.+fold1Index+ :: Scalar a+ => ((Int, a) -> (Int, a) -> (Int, a)) -> PArray a -> Int++fold1Index f+ = fst . U.fold1 f . U.indexed . toUArray+{-# INLINE_PA fold1Index #-}+++-- | Segmented fold over an array, also passing the index of each +-- element to the parameter function.+-- TODO: fold the psegs then replicate, like in the other folds.+-- this currently has the wrong complexity.+fold1sIndex+ :: Scalar a+ => ((Int, a) -> (Int, a) -> (Int, a))+ -> PArray (PArray a) -> PArray Int++{-# INLINE_PA fold1sIndex #-}+fold1sIndex f (PArray n# pdata)+ = let segd = takeSegdPD pdata+ xs = concatPA pdata+ in PArray n#+ $ toScalarPData+ $ U.fsts+ $ U.fold1_s f segd+ $ U.zip (U.indices_s segd)+ $ fromScalarPData xs++{- [Note: fold/promoteSegd]+ ~~~~~~~~~~~~~~~~~~~~~~~~+ In the segmented fold functions above, don't seq on the vsegd because we+ we need the vsegd to remain as an argument to the fold function. + This ensures that the fold/promoteSegdToVSegd rules from DPH_Interface.h+ will fire, which shows up in SMVM.+-}++-- Enumerations --------------------------------------------------------------+-- | Construct a range of integers.+{-# INLINE_PA enumFromTo #-}+enumFromTo :: Int -> Int -> PArray Int+enumFromTo m n + = fromUArray (U.enumFromTo m n)+++{-# INLINE_PA enumFromTol #-}+enumFromTol :: PArray Int -> PArray Int -> PArray (PArray Int)+enumFromTol (PArray m# ms) (PArray _ ns)+ = let + lens = U.zipWith distance (fromScalarPData ms) (fromScalarPData ns)+ segd = U.lengthsToSegd lens++ flat = toScalarPData+ $ U.enumFromStepLenEach + (U.elementsSegd segd)+ (fromScalarPData ms)+ (U.replicate (U.elementsSegd segd) 1) + lens+ + vsegd = U.promoteSegdToVSegd segd+ pdatas = singletondPA flat+ + in PArray m# $ PNested vsegd pdatas segd flat+ +distance :: Int -> Int -> Int+{-# INLINE_STREAM distance #-}+distance m n = max 0 (n - m + 1)+
+ Data/Array/Parallel/Prelude.hs view
@@ -0,0 +1,17 @@+-- |This modules bundles all vectorised versions of Prelude definitions.+--+-- /This module should not be explicitly imported in user code anymore./+-- User code should only import 'Data.Array.Parallel' and, until the+-- vectoriser supports type classes, the type-specific+-- modules 'Data.Array.Parallel.Prelude.*'.++module Data.Array.Parallel.Prelude + ( module Data.Array.Parallel.Prelude.Base+ , module Data.Array.Parallel.Prelude.Bool)+where+import Data.Array.Parallel.Prelude.Base+import Data.Array.Parallel.Prelude.Bool+import Data.Array.Parallel.Prelude.Ordering ()+import Data.Array.Parallel.Prelude.Int ()+import Data.Array.Parallel.Prelude.Word8 ()+import Data.Array.Parallel.Prelude.Double ()
+ Data/Array/Parallel/Prelude/Base.hs view
@@ -0,0 +1,46 @@+{-# OPTIONS_GHC -fvectorise #-}++-- |This module sets up the basic vectorisation map for vectorising the DPH Prelude.+module Data.Array.Parallel.Prelude.Base+ ( PArr+ -- , ()+ , Bool(..)+ , Ordering(..)+ , Word8, Int+ , Float, Double+ , Eq(..), Ord(..)+ , Show+ , Num(..)+ )+where+import Data.Array.Parallel.Prim () -- dependency required by the vectoriser++import Data.Array.Parallel.PArr+import Data.Array.Parallel.PArray.PData.Base+import Data.Array.Parallel.Lifted.Closure++import Data.Word (Word8)+++-- internal types+{-# VECTORISE SCALAR type PArr = PArray #-}+{-# VECTORISE SCALAR type PArray = PArray #-}+{-# VECTORISE SCALAR type (->) = (:->) #-}++-- vectorised versions of types from the standard Prelude+{-# VECTORISE type () = () #-}+{-# VECTORISE type Bool = Bool #-}+{-# VECTORISE type Ordering = Ordering #-}+{-# VECTORISE SCALAR type Word8 #-}+{-# VECTORISE SCALAR type Int #-}+{-# VECTORISE SCALAR type Float #-}+{-# VECTORISE SCALAR type Double #-}++-- FIXME: currently a fake definition to allow 'Integer' in SCALAR class instances+{-# VECTORISE SCALAR type Integer #-}++-- vectorised versions of type classes from the standard Prelude+{-# VECTORISE class Eq #-}+{-# VECTORISE class Ord #-}+{-# VECTORISE class Show #-} -- only to facilitate 'Num', no vectorised instances provided+{-# VECTORISE class Num #-}
+ Data/Array/Parallel/Prelude/Bool.hs view
@@ -0,0 +1,135 @@+{-# OPTIONS_GHC -fvectorise #-}++module Data.Array.Parallel.Prelude.Bool + ( Bool(..)+ , P.otherwise+ , (P.&&), (P.||), P.not, andP, orP+ , fromBool, toBool)+where+-- Primitives needed by the vectoriser.+import Data.Array.Parallel.Prim+import Data.Array.Parallel.PArr+import Data.Array.Parallel.Prelude.Base (Bool(..), Int, Eq, Ord)+import Data.Array.Parallel.Prelude.Int as I (sumP, (==), (/=)) -- just temporary+import Data.Array.Parallel.Lifted (mapPP, lengthPP) -- just temporary+import Data.Array.Parallel.PArray.PRepr+import Data.Array.Parallel.PArray.PData.Base+import qualified Data.Array.Parallel.Unlifted as U+import Data.Bits+import qualified Prelude as P+ + +-- instances of standard type classes from the Prelude +{-# VECTORISE SCALAR instance Eq Bool #-}+{-# VECTORISE SCALAR instance Ord Bool #-}++-- and ------------------------------------------------------------------------+{-# VECTORISE (P.&&) = (&&*) #-}++(&&*) :: Bool :-> Bool :-> Bool+(&&*) = closure2 (P.&&) and_l+{-# INLINE (&&*) #-}+{-# NOVECTORISE (&&*) #-}++and_l :: PArray Bool -> PArray Bool -> PArray Bool+and_l (PArray n# bs) (PArray _ cs)+ = PArray n# P.$+ case bs of { PBool sel1 ->+ case cs of { PBool sel2 ->+ PBool P.$ U.tagsToSel2 (U.zipWith (.&.) (U.tagsSel2 sel1) (U.tagsSel2 sel2)) }}+{-# INLINE and_l #-}+{-# NOVECTORISE and_l #-}+++-- or -------------------------------------------------------------------------+{-# VECTORISE (P.||) = (||*) #-}++(||*) :: Bool :-> Bool :-> Bool+(||*) = closure2 (P.||) or_l+{-# INLINE (||*) #-}+{-# NOVECTORISE (||*) #-}++or_l :: PArray Bool -> PArray Bool -> PArray Bool+or_l (PArray n# bs) (PArray _ cs)+ = PArray n# P.$+ case bs of { PBool sel1 ->+ case cs of { PBool sel2 ->+ PBool P.$ U.tagsToSel2 (U.zipWith (.|.) (U.tagsSel2 sel1) (U.tagsSel2 sel2)) }}+{-# INLINE or_l #-}+{-# NOVECTORISE or_l #-}+++-- not ------------------------------------------------------------------------+{-# VECTORISE P.not = notPP #-}++notPP :: Bool :-> Bool+notPP = closure1 P.not notPP_l+{-# INLINE notPP #-}+{-# NOVECTORISE notPP #-}++notPP_l :: PArray Bool -> PArray Bool+notPP_l (PArray n# bs)+ = PArray n# P.$+ case bs of { PBool sel ->+ PBool P.$ U.tagsToSel2 (U.map complement (U.tagsSel2 sel)) }+{-# NOVECTORISE notPP_l #-}+{-# INLINE notPP_l #-}+++{- TODO: We can't do these because there is no Unboxes instance for Bool.+-- andP -----------------------------------------------------------------------+andP :: PArr Bool -> Bool+andP _ = True+{-# NOINLINE andP #-}+{-# VECTORISE andP = andPP #-}++andPP :: PArray Bool :-> Bool+andPP = L.closure1' (SC.fold (&&) True) (SC.folds (&&) True)+{-# INLINE andPP #-}+{-# NOVECTORISE andPP #-}+++-- orP ------------------------------------------------------------------------+orP :: PArr Bool -> Bool+orP _ = True+{-# NOINLINE orP #-}+{-# VECTORISE orP = orPP #-}++orPP :: PArray Bool :-> Bool+orPP = L.closure1' (SC.fold (||) False) (SC.folds (||) False)+{-# INLINE orPP #-}+{-# NOVECTORISE orPP #-}+-}++-- Until we have Unboxes for Bool, we use the following definitions instead.++andP :: PArr Bool -> Bool+andP bs = I.sumP (mapP fromBool bs) I.== lengthP bs++orP :: PArr Bool -> Bool+orP bs = sumP (mapP fromBool bs) I./= 0++-- Defining 'mapP' and 'lengthP' here is just a kludge until the original definitions of+-- 'andP' and 'orP' work again.+mapP :: (a -> b) -> PArr a -> PArr b+mapP !_ !_ = emptyPArr+{-# NOINLINE mapP #-}+{-# VECTORISE mapP = mapPP #-}++lengthP :: PArr a -> Int+lengthP = lengthPArr+{-# NOINLINE lengthP #-}+{-# VECTORISE lengthP = lengthPP #-}+++-- conversion functions --------------------------------------------------------++fromBool :: Bool -> Int+fromBool False = 0+fromBool True = 1+{-# VECTORISE SCALAR fromBool #-}++toBool :: Int -> Bool+toBool 0 = False+toBool _ = True+{-# VECTORISE SCALAR toBool #-}
+ Data/Array/Parallel/Prelude/Double.hs view
@@ -0,0 +1,256 @@+{-# OPTIONS_GHC -fvectorise #-}++module Data.Array.Parallel.Prelude.Double + ( Double+ + -- * Ord+ , (==), (/=), (<), (<=), (>), (>=), min, max+ , maximumP, minimumP+ , maxIndexP, minIndexP++ -- * Num+ , (+), (-), (*), (/)+ , negate, abs+ , sumP, productP+ + -- * Floating+ , pi+ , sqrt+ , exp, (**)+ , log, logBase+ , sin, tan, cos+ , asin, atan, acos+ , sinh, tanh, cosh+ , asinh, atanh, acosh+ + -- * RealFrac+ , fromInt)+where+-- Primitives needed by the vectoriser.+import Data.Array.Parallel.Prim () +import Data.Array.Parallel.Prelude.Base (Bool, Int, Double, Eq, Ord, Num)+import Data.Array.Parallel.PArr+import Data.Array.Parallel.PArray+import Data.Array.Parallel.Lifted ((:->)(..))+import qualified Data.Array.Parallel.Lifted as L+import qualified Data.Array.Parallel.PArray.Scalar as SC+import qualified Prelude as P+++{-# VECTORISE SCALAR instance Eq Double #-}+{-# VECTORISE SCALAR instance Ord Double #-}+{-# VECTORISE SCALAR instance Num Double #-}+++infixl 7 *, /+infixl 6 +, -+infix 4 ==, /=, <, <=, >, >=++-- Ord ------------------------------------------------------------------------+(==), (/=), (<), (<=), (>), (>=) :: Double -> Double -> Bool++(==) = (P.==)+{-# VECTORISE SCALAR (==) #-}++(/=) = (P./=)+{-# VECTORISE SCALAR (/=) #-}++(<=) = (P.<=)+{-# VECTORISE SCALAR (<=) #-}++(<) = (P.<)+{-# VECTORISE SCALAR (<) #-}++(>=) = (P.>=)+{-# VECTORISE SCALAR (>=) #-}++(>) = (P.>)+{-# VECTORISE SCALAR (>) #-}+++-- min/max ----------------------------+min, max :: Double -> Double -> Double++min = P.min+{-# VECTORISE SCALAR min #-}++max = P.max+{-# VECTORISE SCALAR max #-}+++-- minimum/maximum --------------------+minimumP, maximumP :: PArr Double -> Double++minimumP arr = headPArr arr+{-# NOINLINE minimumP #-}+{-# VECTORISE minimumP = minimumPP #-}++maximumP arr = headPArr arr+{-# NOINLINE maximumP #-}+{-# VECTORISE maximumP = maximumPP #-}++minimumPP, maximumPP :: PArray Double :-> Double+minimumPP = L.closure1' (SC.fold1 P.min) (SC.fold1s P.min)+{-# INLINE minimumPP #-}+{-# NOVECTORISE minimumPP #-}++maximumPP = L.closure1' (SC.fold1 P.max) (SC.fold1s P.max)+{-# INLINE maximumPP #-}+{-# NOVECTORISE maximumPP #-}+++-- minIndex/maxIndex ------------------+minIndexP :: PArr Double -> Int+minIndexP !_ = 0 +{-# NOINLINE minIndexP #-}+{-# VECTORISE minIndexP = minIndexPP #-}++minIndexPP :: PArray Double :-> Int+minIndexPP = L.closure1' (SC.fold1Index min') (SC.fold1sIndex min')+{-# INLINE minIndexPP #-}+{-# NOVECTORISE minIndexPP #-}++min' :: P.Ord b => (a, b) -> (a, b) -> (a, b)+min' (i,x) (j,y) | x P.<= y = (i,x)+ | P.otherwise = (j,y)+{-# NOVECTORISE min' #-}+++maxIndexP :: PArr Double -> Int+maxIndexP _ = 0+{-# NOINLINE maxIndexP #-}+{-# VECTORISE maxIndexP = maxIndexPP #-}++maxIndexPP :: PArray Double :-> Int+maxIndexPP = L.closure1' (SC.fold1Index max') (SC.fold1sIndex max')+{-# INLINE maxIndexPP #-}+{-# NOVECTORISE maxIndexPP #-}++max' :: P.Ord b => (a, b) -> (a, b) -> (a, b)+max' (i,x) (j,y) | x P.>= y = (i,x)+ | P.otherwise = (j,y)+{-# NOVECTORISE max' #-}+++-- Num ---------------------------------------------------------------------+(+), (-), (*), (/) :: Double -> Double -> Double++(+) = (P.+)+{-# VECTORISE SCALAR (+) #-}++(-) = (P.-)+{-# VECTORISE SCALAR (-) #-}++(*) = (P.*)+{-# VECTORISE (*) = mulPP #-}++mulPP :: Double :-> Double :-> Double+mulPP = L.closure2' (P.*) (SC.zipWith (P.*))+{-# INLINE mulPP #-}+{-# NOVECTORISE mulPP #-}+++(/) = (P./)+{-# VECTORISE SCALAR (/) #-}++-- negate/abs -------------------------+negate, abs :: Double -> Double++negate = P.negate+{-# VECTORISE SCALAR negate #-}++abs = P.abs+{-# VECTORISE SCALAR abs #-}+++-- sum/product ------------------------+sumP, productP :: PArr Double -> Double++sumP arr = headPArr arr+{-# NOINLINE sumP #-}+{-# VECTORISE sumP = sumPP #-}++productP arr = headPArr arr+{-# NOINLINE productP #-}+{-# VECTORISE productP = productPP #-}++sumPP, productPP :: PArray Double :-> Double+sumPP = L.closure1' (SC.fold (+) 0) (SC.folds (+) 0)+{-# INLINE sumPP #-}+{-# NOVECTORISE sumPP #-}++productPP = L.closure1' (SC.fold (*) 1) (SC.folds (*) 1)+{-# INLINE productPP #-}+{-# NOVECTORISE productPP #-}+++-- Floating -------------------------------------------------------------------+pi :: Double+pi = P.pi+{-# NOVECTORISE pi #-}++sqrt, exp, log, + sin, tan, cos, + asin, atan, acos, + sinh, tanh, cosh,+ asinh, atanh, acosh :: Double -> Double++exp = P.exp+{-# VECTORISE SCALAR exp #-}++sqrt = P.sqrt+{-# VECTORISE SCALAR sqrt #-}++log = P.log+{-# VECTORISE SCALAR log #-}++sin = P.sin+{-# VECTORISE SCALAR sin #-}++tan = P.tan+{-# VECTORISE SCALAR tan #-}++cos = P.cos+{-# VECTORISE SCALAR cos #-}++asin = P.asin+{-# VECTORISE SCALAR asin #-}++atan = P.atan+{-# VECTORISE SCALAR atan #-}++acos = P.acos+{-# VECTORISE SCALAR acos #-}++sinh = P.sinh+{-# VECTORISE SCALAR sinh #-}++tanh = P.tanh+{-# VECTORISE SCALAR tanh #-}++cosh = P.cosh+{-# VECTORISE SCALAR cosh #-}++asinh = P.asinh+{-# VECTORISE SCALAR asinh #-}++atanh = P.atanh+{-# VECTORISE SCALAR atanh #-}++acosh = P.acosh+{-# VECTORISE SCALAR acosh #-}+++(**), logBase :: Double -> Double -> Double++(**) = (P.**)+{-# VECTORISE SCALAR (**) #-}++logBase = P.logBase+{-# VECTORISE SCALAR logBase #-}+++-- RealFrac -------------------------------------------------------------------+fromInt :: Int -> Double+fromInt = P.fromIntegral+{-# VECTORISE SCALAR fromInt #-}
+ Data/Array/Parallel/Prelude/Int.hs view
@@ -0,0 +1,197 @@+{-# OPTIONS_GHC -fvectorise #-}++module Data.Array.Parallel.Prelude.Int + ( Int+ + -- * Ord+ , (==), (/=), (<), (<=), (>), (>=), min, max+ , maximumP, minimumP+ , maxIndexP, minIndexP+ + -- * Num+ , (+), (-), (*)+ , negate, abs+ , sumP, productP+ + -- * Integral+ , div, mod, sqrt+ + -- * Enum+ , enumFromToP)+where+-- Primitives needed by the vectoriser.+import Data.Array.Parallel.Prim () +import Data.Array.Parallel.Prelude.Base (Bool, Int, Eq, Ord, Num)+import Data.Array.Parallel.PArr+import Data.Array.Parallel.PArray+import Data.Array.Parallel.Lifted ((:->)(..))+import qualified Data.Array.Parallel.Lifted as L+import qualified Data.Array.Parallel.PArray.Scalar as SC+import qualified Prelude as P+ ++{-# VECTORISE SCALAR instance Eq Int #-}+{-# VECTORISE SCALAR instance Ord Int #-}+{-# VECTORISE SCALAR instance Num Int #-}+++infixl 7 *+infixl 6 +, -+infix 4 ==, /=, <, <=, >, >=+infixl 7 `div`, `mod`++-- Ord ------------------------------------------------------------------------+(==), (/=), (<), (<=), (>), (>=) :: Int -> Int -> Bool++(==) = (P.==)+{-# VECTORISE SCALAR (==) #-}++(/=) = (P./=)+{-# VECTORISE SCALAR (/=) #-}++(<=) = (P.<=)+{-# VECTORISE SCALAR (<=) #-}++(<) = (P.<)+{-# VECTORISE SCALAR (<) #-}++(>=) = (P.>=)+{-# VECTORISE SCALAR (>=) #-}++(>) = (P.>)+{-# VECTORISE SCALAR (>) #-}+++-- min/max ----------------------------+min, max :: Int -> Int -> Int++min = P.min+{-# VECTORISE SCALAR min #-}++max = P.max+{-# VECTORISE SCALAR max #-}+++-- minimum/maximum --------------------+minimumP, maximumP :: PArr Int -> Int++minimumP arr = headPArr arr+{-# NOINLINE minimumP #-}+{-# VECTORISE minimumP = minimumPP #-}++maximumP arr = headPArr arr+{-# NOINLINE maximumP #-}+{-# VECTORISE maximumP = maximumPP #-}++minimumPP, maximumPP :: PArray Int :-> Int+minimumPP = L.closure1' (SC.fold1 P.min) (SC.fold1s P.min)+{-# INLINE minimumPP #-}+{-# NOVECTORISE minimumPP #-}++maximumPP = L.closure1' (SC.fold1 P.max) (SC.fold1s P.max)+{-# INLINE maximumPP #-}+{-# NOVECTORISE maximumPP #-}+++-- minIndex/maxIndex ------------------+minIndexP :: PArr Int -> Int+minIndexP !_ = 0 +{-# NOINLINE minIndexP #-}+{-# VECTORISE minIndexP = minIndexPP #-}++minIndexPP :: PArray Int :-> Int+minIndexPP = L.closure1' (SC.fold1Index min') (SC.fold1sIndex min')+{-# INLINE minIndexPP #-}+{-# NOVECTORISE minIndexPP #-}++min' :: P.Ord b => (a, b) -> (a, b) -> (a, b)+min' (i,x) (j,y) | x P.<= y = (i,x)+ | P.otherwise = (j,y)+{-# NOVECTORISE min' #-}+++maxIndexP :: PArr Int -> Int+maxIndexP _ = 0+{-# NOINLINE maxIndexP #-}+{-# VECTORISE maxIndexP = maxIndexPP #-}++maxIndexPP :: PArray Int :-> Int+maxIndexPP = L.closure1' (SC.fold1Index max') (SC.fold1sIndex max')+{-# INLINE maxIndexPP #-}+{-# NOVECTORISE maxIndexPP #-}++max' :: P.Ord b => (a, b) -> (a, b) -> (a, b)+max' (i,x) (j,y) | x P.>= y = (i,x)+ | P.otherwise = (j,y)+{-# NOVECTORISE max' #-}+++-- Num ------------------------------------------------------------------------+(+), (-), (*) :: Int -> Int -> Int++(+) = (P.+)+{-# VECTORISE SCALAR (+) #-}++(-) = (P.-)+{-# VECTORISE SCALAR (-) #-}++(*) = (P.*)+{-# VECTORISE SCALAR (*) #-}+++-- negate/abs -------------------------+negate, abs :: Int -> Int++negate = P.negate+{-# VECTORISE SCALAR negate #-}++abs = P.abs+{-# VECTORISE SCALAR abs #-}+++-- sum/product ------------------------+sumP, productP :: PArr Int -> Int++sumP arr = headPArr arr+{-# NOINLINE sumP #-}+{-# VECTORISE sumP = sumPP #-}++productP arr = headPArr arr+{-# NOINLINE productP #-}+{-# VECTORISE productP = productPP #-}++sumPP, productPP :: PArray Int :-> Int+sumPP = L.closure1' (SC.fold (+) 0) (SC.folds (+) 0)+{-# INLINE sumPP #-}+{-# NOVECTORISE sumPP #-}++productPP = L.closure1' (SC.fold (*) 1) (SC.folds (*) 1)+{-# INLINE productPP #-}+{-# NOVECTORISE productPP #-}+++-- Integral -------------------------------------------------------------------+div, mod :: Int -> Int -> Int++div = P.div+{-# VECTORISE SCALAR div #-}++mod = P.mod+{-# VECTORISE SCALAR mod #-}+++sqrt :: Int -> Int +sqrt n = P.floor (P.sqrt (P.fromIntegral n) :: P.Double)+{-# VECTORISE SCALAR sqrt #-}+++-- Enum -----------------------------------------------------------------------+enumFromToP :: Int -> Int -> PArr Int+enumFromToP !_ !_ = emptyPArr+{-# NOINLINE enumFromToP #-}+{-# VECTORISE enumFromToP = enumFromToPP #-}++enumFromToPP :: Int :-> Int :-> PArray Int+enumFromToPP = L.closure2' SC.enumFromTo SC.enumFromTol+{-# INLINE enumFromToPP #-}+{-# NOVECTORISE enumFromToPP #-}
+ Data/Array/Parallel/Prelude/Ordering.hs view
@@ -0,0 +1,55 @@+{-# OPTIONS_GHC -fvectorise #-}++module Data.Array.Parallel.Prelude.Ordering+ ( Ordering+ , isLT, isEQ, isGT)+where+import Data.Array.Parallel.Prim () +import Data.Array.Parallel.Prelude.Base ()+import Data.Array.Parallel.PArray.PData+import Data.Array.Parallel.PArray.PData.Word8+import Data.Array.Parallel.PArray.PRepr+import Data.Array.Parallel.Lifted ((:->)(..))+import qualified Data.Array.Parallel.Lifted as L+import qualified Data.Array.Parallel.PArray.Scalar as SC+++{-# VECTORISE SCALAR instance Eq Ordering #-}+{-# VECTORISE SCALAR instance Ord Ordering #-}+++isLT, isEQ, isGT :: Ordering -> Bool++isLT _ = False+{-# NOINLINE isLT #-}+{-# VECTORISE isLT = isLtPP #-}++isEQ _ = False+{-# NOINLINE isEQ #-}+{-# VECTORISE isEQ = isEqPP #-}++isGT _ = False+{-# NOINLINE isGT #-}+{-# VECTORISE isGT = isGtPP #-}+++isLtPP, isEqPP, isGtPP :: Ordering :-> Bool+isLtPP = L.closure1' (== LT) (isOrdering LT)+{-# INLINE isLtPP #-}+{-# NOVECTORISE isLtPP #-}++isEqPP = L.closure1' (== EQ) (isOrdering EQ)+{-# INLINE isEqPP #-}+{-# NOVECTORISE isEqPP #-}++isGtPP = L.closure1' (== GT) (isOrdering GT)+{-# INLINE isGtPP #-}+{-# NOVECTORISE isGtPP #-}++isOrdering :: Ordering -> PArray Ordering -> PArray Bool+isOrdering o (PArray n pdata)+ = case pdata of+ POrdering w8s+ -> SC.map (== (toPRepr o)) (PArray n $ PWord8 w8s)+{-# INLINE isOrdering #-}+{-# NOVECTORISE isOrdering #-}
+ Data/Array/Parallel/Prelude/Tuple.hs view
@@ -0,0 +1,32 @@++-- | Closure converted tuple data constructors used by the vectoriser.+module Data.Array.Parallel.Prelude.Tuple + (tup2, tup3, tup4, tup5)+where +import Data.Array.Parallel.Lifted.Closure+import Data.Array.Parallel.PArray.PRepr+import qualified Data.Array.Parallel.PArray as PA+++tup2 :: (PA a, PA b)+ => a :-> b :-> (a, b)+tup2 = closure2' (,) PA.zip+{-# INLINE tup2 #-}+++tup3 :: (PA a, PA b, PA c)+ => a :-> b :-> c :-> (a, b, c)+tup3 = closure3' (,,) PA.zip3+{-# INLINE tup3 #-}+++tup4 :: (PA a, PA b, PA c, PA d)+ => a :-> b :-> c :-> d :-> (a, b, c, d)+tup4 = closure4' (,,,) PA.zip4+{-# INLINE tup4 #-}+++tup5 :: (PA a, PA b, PA c, PA d)+ => a :-> b :-> c :-> d :-> e :-> (a, b, c, d, e)+tup5 = closure5' (,,,,) PA.zip5+{-# INLINE tup5 #-}
+ Data/Array/Parallel/Prelude/Word8.hs view
@@ -0,0 +1,195 @@+{-# OPTIONS_GHC -fvectorise #-}++module Data.Array.Parallel.Prelude.Word8+ ( Word8+ + -- * Ord+ , (==), (/=), (<), (<=), (>), (>=), min, max+ , maximumP, minimumP+ , maxIndexP, minIndexP+ + -- * Num+ , (+), (-), (*)+ , negate, abs+ , sumP, productP+ + -- * Integral+ , div, mod, sqrt+ + -- * Conversion+ , fromInt+ , toInt)+where+import Data.Array.Parallel.Prim () +import Data.Array.Parallel.Prelude.Base (Bool, Int, Word8, Eq, Ord, Num)+import Data.Array.Parallel.PArr+import Data.Array.Parallel.PArray+import Data.Array.Parallel.Lifted ((:->)(..))+import qualified Data.Array.Parallel.Lifted as L+import qualified Data.Array.Parallel.PArray.Scalar as SC+import qualified Prelude as P+++{-# VECTORISE SCALAR instance Eq Word8 #-}+{-# VECTORISE SCALAR instance Ord Word8 #-}+{-# VECTORISE SCALAR instance Num Word8 #-}+++infixl 7 *+infixl 6 +, -+infix 4 ==, /=, <, <=, >, >=+infixl 7 `div`, `mod`++-- Ord ------------------------------------------------------------------------+(==), (/=), (<), (<=), (>), (>=) :: Word8 -> Word8 -> Bool++(==) = (P.==)+{-# VECTORISE SCALAR (==) #-}++(/=) = (P./=)+{-# VECTORISE SCALAR (/=) #-}++(<=) = (P.<=)+{-# VECTORISE SCALAR (<=) #-}++(<) = (P.<)+{-# VECTORISE SCALAR (<) #-}++(>=) = (P.>=)+{-# VECTORISE SCALAR (>=) #-}++(>) = (P.>)+{-# VECTORISE SCALAR (>) #-}+++-- min/max ----------------------------+min, max :: Word8 -> Word8 -> Word8++min = P.min+{-# VECTORISE SCALAR min #-}++max = P.max+{-# VECTORISE SCALAR max #-}+++-- minimum/maximum --------------------+minimumP, maximumP :: PArr Word8 -> Word8++minimumP arr = headPArr arr+{-# NOINLINE minimumP #-}+{-# VECTORISE minimumP = minimumPP #-}++maximumP arr = headPArr arr+{-# NOINLINE maximumP #-}+{-# VECTORISE maximumP = maximumPP #-}++minimumPP, maximumPP :: PArray Word8 :-> Word8+minimumPP = L.closure1' (SC.fold1 P.min) (SC.fold1s P.min)+{-# INLINE minimumPP #-}+{-# NOVECTORISE minimumPP #-}++maximumPP = L.closure1' (SC.fold1 P.max) (SC.fold1s P.max)+{-# INLINE maximumPP #-}+{-# NOVECTORISE maximumPP #-}+++-- minIndex/maxIndex ------------------+minIndexP :: PArr Word8 -> Int+minIndexP !_ = 0 +{-# NOINLINE minIndexP #-}+{-# VECTORISE minIndexP = minIndexPP #-}++minIndexPP :: PArray Word8 :-> Int+minIndexPP = L.closure1' (SC.fold1Index min') (SC.fold1sIndex min')+{-# INLINE minIndexPP #-}+{-# NOVECTORISE minIndexPP #-}++min' :: P.Ord b => (a, b) -> (a, b) -> (a, b)+min' (i,x) (j,y) | x P.<= y = (i,x)+ | P.otherwise = (j,y)+{-# NOVECTORISE min' #-}+++maxIndexP :: PArr Word8 -> Int+maxIndexP _ = 0+{-# NOINLINE maxIndexP #-}+{-# VECTORISE maxIndexP = maxIndexPP #-}++maxIndexPP :: PArray Word8 :-> Int+maxIndexPP = L.closure1' (SC.fold1Index max') (SC.fold1sIndex max')+{-# INLINE maxIndexPP #-}+{-# NOVECTORISE maxIndexPP #-}++max' :: P.Ord b => (a, b) -> (a, b) -> (a, b)+max' (i,x) (j,y) | x P.>= y = (i,x)+ | P.otherwise = (j,y)+{-# NOVECTORISE max' #-}+++-- Num ------------------------------------------------------------------------+(+), (-), (*) :: Word8 -> Word8 -> Word8++(+) = (P.+)+{-# VECTORISE SCALAR (+) #-}++(-) = (P.-)+{-# VECTORISE SCALAR (-) #-}++(*) = (P.*)+{-# VECTORISE SCALAR (*) #-}+++-- negate/abs -------------------------+negate, abs :: Word8 -> Word8++negate = P.negate+{-# VECTORISE SCALAR negate #-}++abs = P.abs+{-# VECTORISE SCALAR abs #-}+++-- sum/product ------------------------+sumP, productP :: PArr Word8 -> Word8++sumP arr = headPArr arr+{-# NOINLINE sumP #-}+{-# VECTORISE sumP = sumPP #-}++productP arr = headPArr arr+{-# NOINLINE productP #-}+{-# VECTORISE productP = productPP #-}++sumPP, productPP :: PArray Word8 :-> Word8+sumPP = L.closure1' (SC.fold (+) 0) (SC.folds (+) 0)+{-# INLINE sumPP #-}+{-# NOVECTORISE sumPP #-}++productPP = L.closure1' (SC.fold (*) 1) (SC.folds (*) 1)+{-# INLINE productPP #-}+{-# NOVECTORISE productPP #-}+++-- Integral -------------------------------------------------------------------+div, mod :: Word8 -> Word8 -> Word8++div = P.div+{-# VECTORISE SCALAR div #-}++mod = P.mod+{-# VECTORISE SCALAR mod #-}+++sqrt :: Word8 -> Word8 +sqrt n = P.floor (P.sqrt (P.fromIntegral n) :: P.Double)+{-# VECTORISE SCALAR sqrt #-}+++-- Conversion -----------------------------------------------------------------+toInt :: Word8 -> Int+toInt = P.fromIntegral+{-# VECTORISE SCALAR toInt #-}++fromInt :: Int -> Word8+fromInt = P.fromIntegral+{-# VECTORISE SCALAR fromInt #-}
+ Data/Array/Parallel/Prim.hs view
@@ -0,0 +1,358 @@+{-# LANGUAGE CPP #-}+#include "fusion-phases.h"++-- | This is the API used by the vectoriser.+-- The vectoriser wants a slightly different interface to the one used +-- natively by the library. This module performs the impedance matching.+module Data.Array.Parallel.Prim + -- Core types+ ( PData, PDatas, PRepr, PA(..), PR(..)++ -- Array Functions+ , emptyPD+ , replicatePD+ , packByTagPD+ , combine2PD++ -- Scalar primitives+ , Scalar(..)+ , scalar_map+ , scalar_zipWith+ , scalar_zipWith3++ -- Types used in the generic representation+ , Void, void, fromVoid, pvoid, pvoids#+ , punit+ , Wrap(..)+ , Sum2(..), Sum3(..)+ + -- Closures, and closure functions+ , (:->)(..)+ , closure, ($:)+ , liftedClosure, liftedApply+ , closure1, closure2, closure3+ + -- Selectors+ , Sel2+ , tagsSel2+ , pickSel2#+ , replicateSel2#+ , elementsSel2_0#+ , elementsSel2_1#++ , Sels2+ , lengthSels2#++ -- Scalar constructors+ , emptyPA_Int#, emptyPA_Double#+ , replicatePA_Int#, replicatePA_Double#+ , packByTagPA_Int#, packByTagPA_Double#+ , combine2PA_Int#, combine2PA_Double#++ -- Tuple constructors+ , tup2, tup3, tup4, tup5)+where+import Data.Array.Parallel.PArray.PData.Base + (PArray(..), PData, PDatas, PR(..))++import Data.Array.Parallel.PArray.PData.Void+ ( Void, void, pvoid, pvoids, fromVoid )++import Data.Array.Parallel.PArray.PData.Unit+ ( punit )++import Data.Array.Parallel.PArray.PData.Sum2+ ( Sels2, lengthSels2 )++import Data.Array.Parallel.PArray.PRepr + ( PRepr, PA(..)+ , emptyPA, replicatePA, packByTagPA, combine2PA)+ +import Data.Array.Parallel.PArray.Scalar+ ( Scalar(..))++import Data.Array.Parallel.PArray.Types+ ( Wrap(..)+ , Sum2(..), Sum3(..))+ +import Data.Array.Parallel.Lifted.Closure+ ( (:->)(..))++import Data.Array.Parallel.Prelude.Tuple+ ( tup2, tup3, tup4, tup5)++import Data.Array.Parallel.Base (Tag, intToTag)+import qualified Data.Array.Parallel.Unlifted as U+import qualified Data.Array.Parallel.PArray.Scalar as Scalar+import qualified Data.Array.Parallel.Lifted.Closure as C+import GHC.Exts+++-- Array functions ------------------------------------------------------------+emptyPD :: PA a => PData a+emptyPD = emptyPA+{-# INLINE_PA emptyPD #-}+++replicatePD :: PA a => Int# -> a -> PData a+replicatePD i# x + = replicatePA (I# i#) x+{-# INLINE_PA replicatePD #-}++ +packByTagPD :: PA a => PData a -> Int# -> U.Array Tag -> Int# -> PData a+packByTagPD xs _ tags tag#+ = packByTagPA xs tags (I# tag#)+{-# INLINE_PA packByTagPD #-}+++combine2PD :: PA a => Int# -> U.Sel2 -> PData a -> PData a -> PData a+combine2PD _ sel xs ys+ = combine2PA sel xs ys+{-# INLINE_PA combine2PD #-}+++-- Generic Representation ----------------------------------------------------+pvoids# :: Int# -> PDatas Void+pvoids# n# = pvoids (I# n#)+{-# INLINE_PA pvoids# #-}+++-- Closures -------------------------------------------------------------------+-- The vectoriser wants versions of these functions that take unboxed+-- integers for the first argument of the lifted function.++-- | Construct a closure.+closure :: forall a b e+ . PA e+ => (e -> a -> b)+ -> (Int# -> PData e -> PData a -> PData b)+ -> e+ -> (a :-> b)++closure fv fl e + = Clo fv + (\(I# c) v x -> fl c v x)+ e+{-# INLINE_CLOSURE closure #-}+++-- | Apply a closure.+($:) :: forall a b. (a :-> b) -> a -> b+($:) = (C.$:)+{-# INLINE_CLOSURE ($:) #-}+++-- | Construct a lifted closure.+liftedClosure+ :: forall a b e+ . PA e+ => (e -> a -> b)+ -> (Int# -> PData e -> PData a -> PData b)+ -> PData e+ -> PData (a :-> b)+{-# INLINE_CLOSURE liftedClosure #-}++liftedClosure fv fl es+ = C.AClo fv + (\(I# c) v x -> fl c v x)+ es+ ++-- | Apply a lifted closure.+liftedApply :: Int# -> PData (a :-> b) -> PData a -> PData b+liftedApply n# arr xs+ = C.liftedApply (I# n#) arr xs+{-# INLINE_CLOSURE liftedApply #-}+++closure1 :: forall a b+ . (a -> b)+ -> (PArray a -> PArray b)+ -> (a :-> b)+closure1 fv fl+ = let fl' :: Int -> PData a -> PData b+ fl' (I# c#) pdata + = case fl (PArray c# pdata) of+ PArray _ pdata' -> pdata'+ + in C.closure1 fv fl'+{-# INLINE_CLOSURE closure1 #-}+++closure2 :: forall a b c. PA a+ => (a -> b -> c)+ -> (PArray a -> PArray b -> PArray c)+ -> (a :-> b :-> c)+closure2 fv fl+ = let fl' :: Int -> PData a -> PData b -> PData c+ fl' (I# c#) pdata1 pdata2+ = case fl (PArray c# pdata1) (PArray c# pdata2) of+ PArray _ pdata' -> pdata'+ + in C.closure2 fv fl'+{-# INLINE_CLOSURE closure2 #-}+++closure3 :: forall a b c d. (PA a, PA b)+ => (a -> b -> c -> d)+ -> (PArray a -> PArray b -> PArray c -> PArray d)+ -> (a :-> b :-> c :-> d)+closure3 fv fl+ = let fl' :: Int -> PData a -> PData b -> PData c -> PData d+ fl' (I# c#) pdata1 pdata2 pdata3+ = case fl (PArray c# pdata1) (PArray c# pdata2) (PArray c# pdata3) of+ PArray _ pdata' -> pdata'+ + in C.closure3 fv fl'+{-# INLINE_CLOSURE closure3 #-}+++-- Selector functions ---------------------------------------------------------+-- The vectoriser wants versions of these that take unboxed integers+-- for some arguments.+type Sel2 = U.Sel2+++replicateSel2# :: Int# -> Int# -> Sel2+replicateSel2# n# tag#+ = U.mkSel2+ (U.replicate n (intToTag tag))+ (U.enumFromStepLen 0 1 n)+ (if tag == 0 then n else 0)+ (if tag == 0 then 0 else n)+ (U.mkSelRep2 (U.replicate n (intToTag tag)))+ where+ n = I# n#+ tag = I# tag#+{-# INLINE_PA replicateSel2# #-}+++pickSel2# :: Sel2 -> Int# -> U.Array Bool+pickSel2# sel tag#+ = U.pick (U.tagsSel2 sel) (intToTag (I# tag#))+{-# INLINE_PA pickSel2# #-}+++tagsSel2 :: Sel2 -> U.Array Tag+tagsSel2 = U.tagsSel2+{-# INLINE_PA tagsSel2 #-}+++elementsSel2_0# :: Sel2 -> Int#+elementsSel2_0# sel+ = case U.elementsSel2_0 sel of { I# n# -> n# }+{-# INLINE_PA elementsSel2_0# #-}+++elementsSel2_1# :: Sel2 -> Int#+elementsSel2_1# sel+ = case U.elementsSel2_1 sel of { I# n# -> n# }+{-# INLINE_PA elementsSel2_1# #-}+++lengthSels2# :: Sels2 -> Int#+lengthSels2# sels2+ = case lengthSels2 sels2 of { I# n# -> n# }+{-# INLINE_PA lengthSels2# #-}+++-- Scalar functions -----------------------------------------------------------+scalar_map + :: (Scalar a, Scalar b) + => (a -> b) -> PArray a -> PArray b++scalar_map = Scalar.map+{-# INLINE scalar_map #-}+++scalar_zipWith+ :: (Scalar a, Scalar b, Scalar c)+ => (a -> b -> c) -> PArray a -> PArray b -> PArray c++scalar_zipWith = Scalar.zipWith+{-# INLINE scalar_zipWith #-}+++scalar_zipWith3+ :: (Scalar a, Scalar b, Scalar c, Scalar d)+ => (a -> b -> c -> d) -> PArray a -> PArray b -> PArray c -> PArray d++scalar_zipWith3 = Scalar.zipWith3+{-# INLINE scalar_zipWith3 #-}+++-- Int functions --------------------------------------------------------------+type PArray_Int# = U.Array Int+++replicatePA_Int# :: Int# -> Int# -> PArray_Int#+replicatePA_Int# n# i# = U.replicate (I# n#) (I# i#)+{-# INLINE_PA replicatePA_Int# #-}+++emptyPA_Int# :: PArray_Int#+emptyPA_Int# = U.empty+{-# INLINE_PA emptyPA_Int# #-}+++{-# RULES++"replicatePA_Int#" forall n# i#.+ replicatePA_Int# n# i# = U.replicate (I# n#) (I# i#)++ #-}+++packByTagPA_Int# :: a+packByTagPA_Int# + = error "Data.Array.Parallel.Prim: 'packByTagPA_Int#' not implemented"+{-# NOINLINE packByTagPA_Int# #-}+++combine2'PA_Int# :: PArray_Int# -> PArray_Int# -> PArray_Int# -> PArray_Int#+combine2'PA_Int# sel xs ys = U.combine (U.map (== 0) sel) xs ys+{-# INLINE_PA combine2'PA_Int# #-}+++combine2PA_Int#+ :: Int#+ -> PArray_Int# -> PArray_Int#+ -> PArray_Int# -> PArray_Int# -> PArray_Int#+combine2PA_Int# _ sel _ xs ys = combine2'PA_Int# sel xs ys+{-# INLINE_PA combine2PA_Int# #-}+++-- Double functions -----------------------------------------------------------+type PArray_Double# = U.Array Double+++replicatePA_Double# :: Int# -> Double# -> PArray_Double#+replicatePA_Double# n# d# = U.replicate (I# n#) (D# d#)+{-# INLINE_PA replicatePA_Double# #-}+++emptyPA_Double# :: PArray_Double#+emptyPA_Double# = U.empty+{-# INLINE_PA emptyPA_Double# #-}+++packByTagPA_Double# :: a+packByTagPA_Double# + = error "Data.Array.Parallel.Prim: 'packByTagPA_Double#' not implemented"+{-# NOINLINE packByTagPA_Double# #-}+++combine2'PA_Double#+ :: PArray_Int#+ -> PArray_Double# -> PArray_Double# -> PArray_Double#+combine2'PA_Double# sel xs ys = U.combine (U.map (== 0) sel) xs ys+{-# INLINE_PA combine2'PA_Double# #-}+++combine2PA_Double#+ :: Int#+ -> PArray_Int# -> PArray_Int#+ -> PArray_Double# -> PArray_Double# -> PArray_Double#+combine2PA_Double# _ sel _ xs ys = combine2'PA_Double# sel xs ys+{-# INLINE_PA combine2PA_Double# #-}
+ LICENSE view
@@ -0,0 +1,36 @@+Copyright (c) 2001-2012, The DPH Team++The DPH Team is:+ Manuel M T Chakravarty+ Gabriele Keller+ Roman Leshchinskiy+ Ben Lippmeier+ George Roldugin++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++- Redistributions of source code must retain the above copyright notice,+this list of conditions and the following disclaimer.+ +- Redistributions in binary form must reproduce the above copyright notice,+this list of conditions and the following disclaimer in the documentation+and/or other materials provided with the distribution.+ +- Neither name of the University nor the names of its contributors may be+used to endorse or promote products derived from this software without+specific prior written permission. ++THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY COURT OF THE UNIVERSITY OF+GLASGOW AND THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE+UNIVERSITY COURT OF THE UNIVERSITY OF GLASGOW OR THE CONTRIBUTORS BE LIABLE+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH+DAMAGE.+
+ Setup.hs view
@@ -0,0 +1,3 @@+import Distribution.Simple+main = defaultMain+
+ dph-lifted-vseg.cabal view
@@ -0,0 +1,103 @@+Name: dph-lifted-vseg+Version: 0.6.0.1+License: BSD3+License-File: LICENSE+Author: The DPH Team+Maintainer: Ben Lippmeier <benl@cse.unsw.edu.au>+Homepage: http://www.haskell.org/haskellwiki/GHC/Data_Parallel_Haskell+Category: Data Structures+Synopsis: Data Parallel Haskell lifted array combinators.+Description: This package provides the following:+ nested arrays and the primitive operators that work on them (PA functions);+ the lifted array combinators that the vectoriser introduces (PP functions);+ the user facing library functions that work on [::] style arrays (P functions).+ This implementation directly encodes sharing between array segments,+ and avoids the copying that dph-lifted-copy would otherwise do.+ Use this version for production code.++Cabal-Version: >= 1.6+Build-Type: Simple++Library+ Exposed-Modules:+ Data.Array.Parallel.Lifted.Closure+ Data.Array.Parallel.Lifted.Combinators+ Data.Array.Parallel.Lifted+ Data.Array.Parallel.PArray.PData.Base+ Data.Array.Parallel.PArray.PData.Double+ Data.Array.Parallel.PArray.PData.Int+ Data.Array.Parallel.PArray.PData.Word8+ Data.Array.Parallel.PArray.PData.Nested+ Data.Array.Parallel.PArray.PData.Sum2+ Data.Array.Parallel.PArray.PData.Tuple2+ Data.Array.Parallel.PArray.PData.Tuple3+ Data.Array.Parallel.PArray.PData.Tuple4+ Data.Array.Parallel.PArray.PData.Tuple5+ Data.Array.Parallel.PArray.PData.Unit+ Data.Array.Parallel.PArray.PData.Void+ Data.Array.Parallel.PArray.PData.Wrap+ Data.Array.Parallel.PArray.PData+ Data.Array.Parallel.PArray.PRepr.Base+ Data.Array.Parallel.PArray.PRepr.Instances+ Data.Array.Parallel.PArray.PRepr.Nested+ Data.Array.Parallel.PArray.PRepr.Tuple+ Data.Array.Parallel.PArray.PRepr+ Data.Array.Parallel.PArray.Scalar+ Data.Array.Parallel.PArray+ Data.Array.Parallel.Prelude.Base+ Data.Array.Parallel.Prelude.Bool+ Data.Array.Parallel.Prelude.Double+ Data.Array.Parallel.Prelude.Int+ Data.Array.Parallel.Prelude.Word8+ Data.Array.Parallel.Prelude.Tuple+ Data.Array.Parallel.Prelude.Ordering+ Data.Array.Parallel.Prelude+ Data.Array.Parallel+ Data.Array.Parallel.Prim+ + Exposed:+ False++ Extensions:+ BangPatterns,+ PatternGuards+ TypeFamilies,+ TypeOperators,+ RankNTypes,+ BangPatterns,+ MagicHash,+ UnboxedTuples,+ TypeOperators,+ FlexibleContexts,+ FlexibleInstances,+ EmptyDataDecls,+ NoMonomorphismRestriction,+ MultiParamTypeClasses,+ EmptyDataDecls,+ StandaloneDeriving,+ ExplicitForAll,+ ParallelListComp,+ ExistentialQuantification,+ ScopedTypeVariables,+ PatternGuards,+ PackageImports++ GHC-Options:+ -Odph+ -fcpr-off -fno-liberate-case -fno-spec-constr+ -Wall+ -fno-warn-missing-methods+ -fno-warn-orphans++ Build-Depends: + base == 4.5.*,+ ghc == 7.*,+ array == 0.4.*,+ random == 1.0.*,+ template-haskell == 2.7.*,+ dph-base == 0.6.*,+ dph-prim-par == 0.6.*,+ dph-lifted-base == 0.6.*,+ vector == 0.9.*,+ pretty == 1.1.*,+ containers == 0.4.*