packages feed

dph-lifted-base 0.6.1.1 → 0.7.0.1

raw patch · 5 files changed

+558/−548 lines, 5 filesdep ~basedep ~containersdep ~dph-basePVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base, containers, dph-base, dph-prim-par, template-haskell, vector

API changes (from Hackage documentation)

- Data.Array.Parallel.PArray: append :: PArray a -> PArray a -> PArray a
- Data.Array.Parallel.PArray: appendl :: PArray (PArray a) -> PArray (PArray a) -> PArray (PArray a)
- Data.Array.Parallel.PArray: combine2 :: Sel2 -> PArray a -> PArray a -> PArray a
- Data.Array.Parallel.PArray: concat :: PArray (PArray a) -> PArray a
- Data.Array.Parallel.PArray: concatl :: PArray (PArray (PArray a)) -> PArray (PArray a)
- Data.Array.Parallel.PArray: empty :: PArray a
- Data.Array.Parallel.PArray: enumFromTo :: Int -> Int -> PArray Int
- Data.Array.Parallel.PArray: enumFromTol :: PArray Int -> PArray Int -> PArray (PArray Int)
- Data.Array.Parallel.PArray: extract :: PArray a -> Int -> Int -> PArray a
- Data.Array.Parallel.PArray: extracts :: Vector (PArray a) -> SSegd -> PArray a
- Data.Array.Parallel.PArray: extracts' :: Vector (PArray a) -> PArray Int -> PArray Int -> PArray Int -> PArray a
- Data.Array.Parallel.PArray: fromList :: [a] -> PArray a
- Data.Array.Parallel.PArray: fromUArray :: Elt a => Array a -> PArray a
- Data.Array.Parallel.PArray: fromUArray2 :: (Elt a, Elt b) => Array (a, b) -> PArray (a, b)
- Data.Array.Parallel.PArray: fromVector :: Vector a -> PArray a
- Data.Array.Parallel.PArray: index :: PArray a -> Int -> a
- Data.Array.Parallel.PArray: indexl :: PArray (PArray a) -> PArray Int -> PArray a
- Data.Array.Parallel.PArray: length :: PArray a -> Int
- Data.Array.Parallel.PArray: lengthl :: PArray (PArray a) -> PArray Int
- Data.Array.Parallel.PArray: nestUSegd :: Segd -> PArray a -> PArray (PArray a)
- Data.Array.Parallel.PArray: nf :: PArray a -> ()
- Data.Array.Parallel.PArray: pack :: PArray a -> PArray Bool -> PArray a
- Data.Array.Parallel.PArray: packByTag :: PArray a -> Array Tag -> Tag -> PArray a
- Data.Array.Parallel.PArray: packl :: PArray (PArray a) -> PArray (PArray Bool) -> PArray (PArray a)
- Data.Array.Parallel.PArray: replicate :: Int -> a -> PArray a
- Data.Array.Parallel.PArray: replicatel :: PArray Int -> PArray a -> PArray (PArray a)
- Data.Array.Parallel.PArray: replicates :: Segd -> PArray a -> PArray a
- Data.Array.Parallel.PArray: replicates' :: PArray Int -> PArray a -> PArray a
- Data.Array.Parallel.PArray: singleton :: a -> PArray a
- Data.Array.Parallel.PArray: singletonl :: PArray a -> PArray (PArray a)
- Data.Array.Parallel.PArray: slice :: Int -> Int -> PArray a -> PArray a
- Data.Array.Parallel.PArray: slicel :: PArray Int -> PArray Int -> PArray (PArray a) -> PArray (PArray a)
- Data.Array.Parallel.PArray: takeUSegd :: PArray (PArray a) -> Segd
- Data.Array.Parallel.PArray: toList :: PArray a -> [a]
- Data.Array.Parallel.PArray: toUArray :: Elt a => PArray a -> Array a
- Data.Array.Parallel.PArray: toVector :: PArray a -> Vector a
- Data.Array.Parallel.PArray: type PArray a = Vector a
- Data.Array.Parallel.PArray: unconcat :: PArray (PArray a) -> PArray b -> PArray (PArray b)
- Data.Array.Parallel.PArray: unzip :: PArray (a, b) -> (PArray a, PArray b)
- Data.Array.Parallel.PArray: unzipl :: PArray (PArray (a, b)) -> PArray (PArray a, PArray b)
- Data.Array.Parallel.PArray: valid :: PArray a -> Bool
- Data.Array.Parallel.PArray: zip :: PArray a -> PArray b -> PArray (a, b)
- Data.Array.Parallel.PArray: zipl :: PArray (PArray a) -> PArray (PArray b) -> PArray (PArray (a, b))
- Data.Array.Parallel.PArray.Reference: class PprPhysical1 a where pprp1v vec = brackets $ hcat $ punctuate (text ", ") $ toList $ map pprp1 vec
- Data.Array.Parallel.PArray.Reference: class Similar a
- Data.Array.Parallel.PArray.Reference: pprp1 :: PprPhysical1 a => a -> Doc
- Data.Array.Parallel.PArray.Reference: pprp1v :: PprPhysical1 a => Vector a -> Doc
- Data.Array.Parallel.PArray.Reference: similar :: Similar a => a -> a -> Bool
- Data.Array.Parallel.PArray.Reference: toRef1 :: (Array c a, Array r a) => c a -> r a
- Data.Array.Parallel.PArray.Reference: toRef2 :: (Array c (c a), Array c a, Array r (r a), Array r a) => c (c a) -> r (r a)
- Data.Array.Parallel.PArray.Reference: toRef3 :: (Array c (c (c a)), Array c (c a), Array c a, Array r (r (r a)), Array r (r a), Array r a) => c (c (c a)) -> r (r (r a))
- Data.Array.Parallel.PArray.Reference: withRef1 :: (Array r a, Array c a, PprPhysical1 (c a), Similar a, PprPhysical1 a) => String -> r a -> c a -> c a
- Data.Array.Parallel.PArray.Reference: withRef2 :: (Array r (r a), Array r a, Array c (c a), PprPhysical1 (c (c a)), Array c a, PprPhysical1 (c a), Similar a, PprPhysical1 a) => String -> r (r a) -> c (c a) -> c (c a)
+ Data.Array.Parallel.PArray.Reference: append :: PArray a -> PArray a -> PArray a
+ Data.Array.Parallel.PArray.Reference: appendl :: PArray (PArray a) -> PArray (PArray a) -> PArray (PArray a)
+ Data.Array.Parallel.PArray.Reference: combine2 :: Sel2 -> PArray a -> PArray a -> PArray a
+ Data.Array.Parallel.PArray.Reference: concat :: PArray (PArray a) -> PArray a
+ Data.Array.Parallel.PArray.Reference: concatl :: PArray (PArray (PArray a)) -> PArray (PArray a)
+ Data.Array.Parallel.PArray.Reference: empty :: PArray a
+ Data.Array.Parallel.PArray.Reference: enumFromTo :: Int -> Int -> PArray Int
+ Data.Array.Parallel.PArray.Reference: enumFromTol :: PArray Int -> PArray Int -> PArray (PArray Int)
+ Data.Array.Parallel.PArray.Reference: extract :: PArray a -> Int -> Int -> PArray a
+ Data.Array.Parallel.PArray.Reference: extracts :: Vector (PArray a) -> SSegd -> PArray a
+ Data.Array.Parallel.PArray.Reference: extracts' :: Vector (PArray a) -> PArray Int -> PArray Int -> PArray Int -> PArray a
+ Data.Array.Parallel.PArray.Reference: fromList :: [a] -> PArray a
+ Data.Array.Parallel.PArray.Reference: fromUArray :: Elt a => Array a -> PArray a
+ Data.Array.Parallel.PArray.Reference: fromUArray2 :: (Elt a, Elt b) => Array (a, b) -> PArray (a, b)
+ Data.Array.Parallel.PArray.Reference: fromVector :: Vector a -> PArray a
+ Data.Array.Parallel.PArray.Reference: index :: PArray a -> Int -> a
+ Data.Array.Parallel.PArray.Reference: indexl :: PArray (PArray a) -> PArray Int -> PArray a
+ Data.Array.Parallel.PArray.Reference: length :: PArray a -> Int
+ Data.Array.Parallel.PArray.Reference: lengthl :: PArray (PArray a) -> PArray Int
+ Data.Array.Parallel.PArray.Reference: nestUSegd :: Segd -> PArray a -> PArray (PArray a)
+ Data.Array.Parallel.PArray.Reference: nf :: PArray a -> ()
+ Data.Array.Parallel.PArray.Reference: pack :: PArray a -> PArray Bool -> PArray a
+ Data.Array.Parallel.PArray.Reference: packByTag :: PArray a -> Array Tag -> Tag -> PArray a
+ Data.Array.Parallel.PArray.Reference: packl :: PArray (PArray a) -> PArray (PArray Bool) -> PArray (PArray a)
+ Data.Array.Parallel.PArray.Reference: replicate :: Int -> a -> PArray a
+ Data.Array.Parallel.PArray.Reference: replicatel :: PArray Int -> PArray a -> PArray (PArray a)
+ Data.Array.Parallel.PArray.Reference: replicates :: Segd -> PArray a -> PArray a
+ Data.Array.Parallel.PArray.Reference: replicates' :: PArray Int -> PArray a -> PArray a
+ Data.Array.Parallel.PArray.Reference: singleton :: a -> PArray a
+ Data.Array.Parallel.PArray.Reference: singletonl :: PArray a -> PArray (PArray a)
+ Data.Array.Parallel.PArray.Reference: slice :: Int -> Int -> PArray a -> PArray a
+ Data.Array.Parallel.PArray.Reference: slicel :: PArray Int -> PArray Int -> PArray (PArray a) -> PArray (PArray a)
+ Data.Array.Parallel.PArray.Reference: takeUSegd :: PArray (PArray a) -> Segd
+ Data.Array.Parallel.PArray.Reference: toList :: PArray a -> [a]
+ Data.Array.Parallel.PArray.Reference: toUArray :: Elt a => PArray a -> Array a
+ Data.Array.Parallel.PArray.Reference: toVector :: PArray a -> Vector a
+ Data.Array.Parallel.PArray.Reference: type PArray a = Vector a
+ Data.Array.Parallel.PArray.Reference: unconcat :: PArray (PArray a) -> PArray b -> PArray (PArray b)
+ Data.Array.Parallel.PArray.Reference: unzip :: PArray (a, b) -> (PArray a, PArray b)
+ Data.Array.Parallel.PArray.Reference: unzipl :: PArray (PArray (a, b)) -> PArray (PArray a, PArray b)
+ Data.Array.Parallel.PArray.Reference: valid :: PArray a -> Bool
+ Data.Array.Parallel.PArray.Reference: zip :: PArray a -> PArray b -> PArray (a, b)
+ Data.Array.Parallel.PArray.Reference: zipl :: PArray (PArray a) -> PArray (PArray b) -> PArray (PArray (a, b))
+ Data.Array.Parallel.PArray.Reference.Convert: class PprPhysical1 a where pprp1v vec = brackets $ hcat $ punctuate (text ", ") $ toList $ map pprp1 vec
+ Data.Array.Parallel.PArray.Reference.Convert: class Similar a
+ Data.Array.Parallel.PArray.Reference.Convert: pprp1 :: PprPhysical1 a => a -> Doc
+ Data.Array.Parallel.PArray.Reference.Convert: pprp1v :: PprPhysical1 a => Vector a -> Doc
+ Data.Array.Parallel.PArray.Reference.Convert: similar :: Similar a => a -> a -> Bool
+ Data.Array.Parallel.PArray.Reference.Convert: toRef1 :: (Array c a, Array r a) => c a -> r a
+ Data.Array.Parallel.PArray.Reference.Convert: toRef2 :: (Array c (c a), Array c a, Array r (r a), Array r a) => c (c a) -> r (r a)
+ Data.Array.Parallel.PArray.Reference.Convert: toRef3 :: (Array c (c (c a)), Array c (c a), Array c a, Array r (r (r a)), Array r (r a), Array r a) => c (c (c a)) -> r (r (r a))
+ Data.Array.Parallel.PArray.Reference.Convert: withRef1 :: (Array r a, Array c a, PprPhysical1 (c a), Similar a, PprPhysical1 a) => String -> r a -> c a -> c a
+ Data.Array.Parallel.PArray.Reference.Convert: withRef2 :: (Array r (r a), Array r a, Array c (c a), PprPhysical1 (c (c a)), Array c a, PprPhysical1 (c a), Similar a, PprPhysical1 a) => String -> r (r a) -> c (c a) -> c (c a)
+ Data.Array.Parallel.PArray.Types: instance Typeable Void
+ Data.Array.Parallel.PArray.Types: instance Typeable1 Wrap
+ Data.Array.Parallel.PArray.Types: instance Typeable2 Sum2
+ Data.Array.Parallel.PArray.Types: instance Typeable3 Sum3

Files

− Data/Array/Parallel/PArray.hs
@@ -1,400 +0,0 @@---- | Reference implementation of operators on unvectorised parallel arrays.------   * In this module we just used boxed vectors as the array representation. ---     This won't be fast, but it means we can write the operators without---     needing type class dictionaries such as PA. This makes them---     much easier to use as reference code.------   * The operators should also all do bounds checks, sanity checks, and ---     give nice error messages if something is wrong. The ideas is that---     this code can be run side-by-side production code during debugging.-------   TODO: check lengths properly in functions like zip, extracts----module Data.Array.Parallel.PArray-        ( PArray-        , valid-        , nf-        -        -- * Constructors-        , empty-        , singleton,    singletonl-        , replicate,    replicatel,     replicates,     replicates'-        , append,       appendl-        , concat,       concatl-        , unconcat-        , nestUSegd-        -        -- * Projections-        , length,       lengthl-        , index,        indexl-        , extract,      extracts,       extracts'-        , slice,        slicel-        , takeUSegd-        -        -- * Pack and Combine-        , pack,         packl-        , packByTag-        , combine2-        -        -- * Enumerations-        , enumFromTo,   enumFromTol-        -        -- * Tuples-        , zip,          zipl-        , unzip,        unzipl-        -        -- * Conversions-        , fromVector,   toVector-        , fromList,     toList-        , fromUArray,   toUArray-        , fromUArray2)-where-import Data.Array.Parallel.Base                 (Tag)-import Data.Vector                              (Vector)-import qualified Data.Array.Parallel.Unlifted   as U-import qualified Data.Vector                    as V-import qualified Prelude                        as P-import Control.Monad-import GHC.Exts-import Prelude hiding-        ( replicate, length, concat-        , enumFromTo-        , zip, unzip)----------------------------------------------------------------------------------here :: String -> String-here str   = "Data.Array.Parallel.PArray." ++ str--die :: String -> String -> a-die fn str = error (here $ fn ++ " " ++ str)---- Array Type ------------------------------------------------------------------type PArray a-        = Vector a-        --- | Lift a unary array operator.-lift1   :: (a -> b) -> PArray a -> PArray b-lift1 f vec-        = V.map f vec----- | Lift a binary array operator.-lift2   :: (a -> b -> c) -> PArray a -> PArray b -> PArray c-lift2 f vec1 vec2-        | V.length vec1 /= V.length vec2-        = die "lift2" "length mismatch"- -        | otherwise-        = V.zipWith f vec1 vec2----- | Lift a trinary array operator-lift3   :: (a -> b -> c -> d) -> PArray a -> PArray b -> PArray c -> PArray d-lift3 f vec1 vec2 vec3-        |   V.length vec1 /= V.length vec2-         || V.length vec1 /= V.length vec3-        = die "lift3" "length mismatch"- -        | otherwise-        = V.zipWith3 f vec1 vec2 vec3----- Basics ------------------------------------------------------------------------ | Check that an array has a valid internal representation.-valid :: PArray a -> Bool-valid _ = True---- | Force an array to normal form.-nf :: PArray a -> ()-nf _    = ()----- Constructors ------------------------------------------------------------------- | O(1). An empty array.-empty :: PArray a-empty           = V.empty----- | O(1). Produce an array containing a single element.-singleton :: a -> PArray a-singleton       = V.singleton----- | O(n). Produce an array of singleton arrays.-singletonl :: PArray a -> PArray (PArray a)-singletonl      = lift1 singleton----- | O(n). Define an array of the given size, that maps all elements to the same value.-replicate :: Int -> a -> PArray a-replicate       = V.replicate----- | O(sum lengths). Lifted replicate.-replicatel :: PArray Int -> PArray a -> PArray (PArray a)-replicatel      = lift2 replicate----- | O(sum lengths). Segmented replicate.-replicates :: U.Segd -> PArray a -> PArray a-replicates segd vec-        | V.length vec /= U.lengthSegd segd-        = die "replicates" $ unlines-                [ "segd length mismatch"-                , "  segd length  = " ++ (show $ U.lengthSegd segd)-                , "  array length = " ++ (show $ V.length vec)]--        | otherwise-        = join -        $ V.zipWith V.replicate-                (V.convert $ U.lengthsSegd segd)-                vec----- | O(sum lengths). Wrapper for segmented replicate that takes replication counts---  and uses them to build the `U.Segd`.-replicates' :: PArray Int -> PArray a -> PArray a-replicates' reps arr-        = replicates (U.lengthsToSegd $ V.convert $ reps) arr----- | Append two arrays.-append :: PArray a -> PArray a -> PArray a-append          = (V.++)----- | Lifted append.-appendl :: PArray (PArray a) -> PArray (PArray a) -> PArray (PArray a)-appendl         = lift2 append----- | Concatenation-concat :: PArray (PArray a) -> PArray a-concat          = join----- | Lifted concatenation.-concatl :: PArray (PArray (PArray a)) -> PArray (PArray a)-concatl         = lift1 concat----- | Impose a nesting structure on a flat array-unconcat :: PArray (PArray a) -> PArray b -> PArray (PArray b)-unconcat arr1 arr2-        = nestUSegd (takeUSegd arr1) arr2----- | 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 :: U.Segd -> PArray a -> PArray (PArray a)-nestUSegd segd vec-        | U.elementsSegd segd     == V.length vec -        = V.zipWith-                (\start len -> V.slice start len vec)-                (V.convert $ U.indicesSegd segd)-                (V.convert $ U.lengthsSegd segd)--        | otherwise-        = error $ unlines-                [ "Data.Array.Parallel.PArray.nestSegd: 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 $ V.length vec)]-{-# NOINLINE nestUSegd #-}----- Projections ------------------------------------------------------------------- | Take the length of an array-length :: PArray a -> Int-length          = V.length----- | Take the length of some arrays.-lengthl :: PArray (PArray a) -> PArray Int-lengthl         = lift1 length----- | Lookup a single element from the source array.-index :: PArray a -> Int -> a-index           = (V.!)----- | Lookup a several elements from several source arrays.-indexl :: PArray (PArray a) -> PArray Int -> PArray a-indexl          = lift2 index----- | Extract a range of elements from an array.-extract :: PArray a -> Int -> Int -> PArray a-extract vec start len-        = V.slice start len vec----- | Segmented extract.-extracts :: Vector (PArray a) -> U.SSegd -> PArray a-extracts arrs ssegd-        = join-        $ V.zipWith3-                (\src start len -> extract (arrs V.! src) start len)-                (V.convert $ U.sourcesOfSSegd ssegd)-                (V.convert $ U.startsOfSSegd  ssegd)-                (V.convert $ U.lengthsOfSSegd ssegd)----- | Wrapper for `extracts` that takes arrays of sources, starts and lengths of---   the segments, and uses these to build the `U.SSegd`.-extracts' -        :: 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 sources starts lengths- = let  segd    = U.lengthsToSegd $ V.convert lengths-        ssegd   = U.mkSSegd -                        (V.convert $ starts)-                        (V.convert $ sources)-                        segd-   in   extracts arrs ssegd----- | Extract a range of elements from an arrary.---   Like `extract` but with the parameters in a different order.-slice :: Int -> Int -> PArray a -> PArray a-slice start len arr-        = extract arr start len----- | Extract some slices from some arrays.---   The arrays of starting indices and lengths must themselves---   have the same length.-slicel :: PArray Int -> PArray Int -> PArray (PArray a) -> PArray (PArray a)-slicel  = lift3 slice----- | Take the segment descriptor from a nested array. This can cause index space---   overflow if the number of elements in the result does not can not be---   represented by a single machine word.-takeUSegd :: PArray (PArray a) -> U.Segd-takeUSegd vec-        = U.lengthsToSegd -        $ V.convert-        $ V.map length vec-        ---- Pack and Combine -------------------------------------------------------------- | Select the elements of an array that have their tag set to True.-pack    :: PArray a -> PArray Bool -> PArray a-pack xs bs-        | V.length xs /= V.length bs-        = die "pack" $ unlines-                [ "array length mismatch"-                , "  data  length = " ++ (show $ V.length xs)-                , "  flags length = " ++ (show $ V.length bs) ]--        | otherwise-        = V.ifilter (\i _ -> bs V.! i) xs----- | Lifted pack.-packl :: PArray (PArray a) -> PArray (PArray Bool) -> PArray (PArray a)-packl   = lift2 pack----- | Filter an array based on some tags.-packByTag :: PArray a -> U.Array Tag -> Tag -> PArray a-packByTag xs tags tag-        | V.length xs /= U.length tags-        = die "packByTag" $ unlines-                [ "array length mismatch"-                , "  data  length = " ++ (show $ V.length xs)-                , "  flags length = " ++ (show $ U.length tags) ]--        | otherwise-        = V.ifilter (\i _ -> U.index (here "packByTag") tags i == tag) xs----- | Combine two arrays based on a selector.-combine2 :: U.Sel2 -> PArray a -> PArray a -> PArray a-combine2 tags vec1 vec2- = let  go [] [] []                     = []-        go (0 : bs) (x : xs) ys         = x : go bs xs ys-        go (1 : bs) xs       (y : ys)   = y : go bs xs ys-        go _ _ _ = error "Data.Array.Parallel.PArray.combine: length mismatch"- -   in   V.fromList-                $ go    (V.toList $ V.convert $ U.tagsSel2 tags)-                        (V.toList vec1)-                        (V.toList vec2)----- Enumerations ------------------------------------------------------------------ | Construct a range of integers-enumFromTo :: Int -> Int -> PArray Int-enumFromTo      = V.enumFromTo----- | Lifted enumeration-enumFromTol :: PArray Int -> PArray Int -> PArray (PArray Int)-enumFromTol     = lift2 enumFromTo----- Tuples ------------------------------------------------------------------------ | O(n). Zip a pair of arrays into an array of pairs.-zip     :: PArray a -> PArray b -> PArray (a, b)-zip     = V.zip----- | Lifted zip-zipl    :: PArray (PArray a) -> PArray (PArray b) -> PArray (PArray (a, b))-zipl    = lift2 zip----- | O(n). Unzip an array of pairs into a pair of arrays.-unzip   :: PArray (a, b) -> (PArray a, PArray b)-unzip   = V.unzip----- | Lifted unzip-unzipl  :: PArray (PArray (a, b)) -> PArray (PArray a, PArray b)-unzipl  = lift1 unzip----- Conversions ------------------------------------------------------------------- | Convert a `Vector` to a `PArray`-fromVector :: Vector a -> PArray a-fromVector = id----- | Convert a `PArray` to a `Vector`        -toVector   :: PArray a -> Vector a-toVector   = id---- | Convert a list to a `PArray`.-fromList   :: [a] -> PArray a-fromList   = V.fromList---- | Convert a `PArray` to a list.-toList     :: PArray a -> [a]-toList     = V.toList----- | Convert a `U.Array` to a `PArray`-fromUArray :: U.Elt a => U.Array a -> PArray a-fromUArray  = V.convert----- | Convert a `PArray` to a `U.Array`-toUArray   :: U.Elt a => PArray a -> U.Array a-toUArray    = V.convert----- | Convert a `U.Array` of tuples to a `PArray`-fromUArray2-        :: (U.Elt a, U.Elt b)-        => U.Array (a, b) -> PArray (a, b)-        -fromUArray2  = V.convert
Data/Array/Parallel/PArray/Reference.hs view
@@ -1,170 +1,400 @@-{-# LANGUAGE UndecidableInstances #-}-{-# OPTIONS -fno-warn-missing-signatures #-}--- | During testing, we compare the output of each invocation of the lifted---   combinators in "Data.Array.Parallel.PArray" with the reference implementations. ------   This module helps convert the to and from the array representation---   used by the reference implementation. ---   TODO: we could use this to trace the lengths of the vectors being used, ---         as well as the types that each opeartor is being called at.+-- | Reference implementation of operators on unvectorised parallel arrays. --+--   * In this module we just used boxed vectors as the array representation. +--     This won't be fast, but it means we can write the operators without+--     needing type class dictionaries such as PA. This makes them+--     much easier to use as reference code.+--+--   * The operators should also all do bounds checks, sanity checks, and +--     give nice error messages if something is wrong. The ideas is that+--     this code can be run side-by-side production code during debugging.+---+--   TODO: check lengths properly in functions like zip, extracts+-- module Data.Array.Parallel.PArray.Reference-        ( Similar(..), PprPhysical1 (..)-        , withRef1, withRef2-        , toRef1,   toRef2,   toRef3)+        ( PArray+        , valid+        , nf+        +        -- * Constructors+        , empty+        , singleton,    singletonl+        , replicate,    replicatel,     replicates,     replicates'+        , append,       appendl+        , concat,       concatl+        , unconcat+        , nestUSegd+        +        -- * Projections+        , length,       lengthl+        , index,        indexl+        , extract,      extracts,       extracts'+        , slice,        slicel+        , takeUSegd+        +        -- * Pack and Combine+        , pack,         packl+        , packByTag+        , combine2+        +        -- * Enumerations+        , enumFromTo,   enumFromTol+        +        -- * Tuples+        , zip,          zipl+        , unzip,        unzipl+        +        -- * Conversions+        , fromVector,   toVector+        , fromList,     toList+        , fromUArray,   toUArray+        , fromUArray2) where-import Data.Array.Parallel.Pretty-import qualified Data.Array.Parallel.Array      as A-import qualified Data.Vector                    as V+import Data.Array.Parallel.Base                 (Tag) import Data.Vector                              (Vector)-import Prelude hiding (length)-import System.IO-import System.IO.Unsafe+import qualified Data.Array.Parallel.Unlifted   as U+import qualified Data.Vector                    as V+import qualified Prelude                        as P import Control.Monad+import GHC.Exts+import Prelude hiding+        ( replicate, length, concat+        , enumFromTo+        , zip, unzip) --- Config ----------------------------------------------------------------------debugLiftedTrace        :: Bool-debugLiftedTrace        = False+-------------------------------------------------------------------------------+here :: String -> String+here str   = "Data.Array.Parallel.PArray." ++ str -debugLiftedCompare      :: Bool-debugLiftedCompare      = False+die :: String -> String -> a+die fn str = error (here $ fn ++ " " ++ str) -class Similar a where- similar :: a -> a -> Bool+-- Array Type -----------------------------------------------------------------+type PArray a+        = Vector a+        +-- | Lift a unary array operator.+lift1   :: (a -> b) -> PArray a -> PArray b+lift1 f vec+        = V.map f vec -class PprPhysical1 a where- pprp1  :: a -> Doc - pprp1v :: Vector a -> Doc- pprp1v vec-        = brackets -        $ hcat-        $ punctuate (text ", ") -        $ V.toList $ V.map pprp1 vec-        +-- | Lift a binary array operator.+lift2   :: (a -> b -> c) -> PArray a -> PArray b -> PArray c+lift2 f vec1 vec2+        | V.length vec1 /= V.length vec2+        = die "lift2" "length mismatch"+ +        | otherwise+        = V.zipWith f vec1 vec2 --- withRef ----------------------------------------------------------------------- | Compare the result of some array operator against a reference. ---  Careful:---   * We don't want to inline the whole body of this function into---     every use site, or we'll get code explosion. When debugging is off we---     want this wrapper to be inlined and eliminated as cheaply as possible.---   * We also do this with 'unsafePerformIO' instead of trace, because---     with trace, if the computation contructing the string throws an exception---     then we get no output. For debugging we want to see what function was---     entered before we try to print the result (which might be badly formed),----withRef1 :: ( A.Array r a-            , A.Array c a, PprPhysical1 (c a)-            , Similar a,   PprPhysical1 a)-         => String              -- name of operator-         -> r a                 -- result using reference implementation-         -> c a                 -- result using vseg implementation-         -> c a+-- | Lift a trinary array operator+lift3   :: (a -> b -> c -> d) -> PArray a -> PArray b -> PArray c -> PArray d+lift3 f vec1 vec2 vec3+        |   V.length vec1 /= V.length vec2+         || V.length vec1 /= V.length vec3+        = die "lift3" "length mismatch"+ +        | otherwise+        = V.zipWith3 f vec1 vec2 vec3 -{-# INLINE withRef1 #-}-withRef1 name arrRef arrImpl- = if debugLiftedCompare || debugLiftedTrace-        then withRef1' name arrRef arrImpl-        else arrImpl-        -{-# NOINLINE withRef1' #-}-withRef1' name arrRef arrImpl- = unsafePerformIO- $ do   when debugLiftedTrace-         $ do putStrLn  $ "* " ++ name-              putStrLn  $ render (nest 4 $ pprp1 arrImpl)-              hFlush stdout++-- Basics ---------------------------------------------------------------------+-- | Check that an array has a valid internal representation.+valid :: PArray a -> Bool+valid _ = True++-- | Force an array to normal form.+nf :: PArray a -> ()+nf _    = ()+++-- Constructors ----------------------------------------------------------------+-- | O(1). An empty array.+empty :: PArray a+empty           = V.empty+++-- | O(1). Produce an array containing a single element.+singleton :: a -> PArray a+singleton       = V.singleton+++-- | O(n). Produce an array of singleton arrays.+singletonl :: PArray a -> PArray (PArray a)+singletonl      = lift1 singleton+++-- | O(n). Define an array of the given size, that maps all elements to the same value.+replicate :: Int -> a -> PArray a+replicate       = V.replicate+++-- | O(sum lengths). Lifted replicate.+replicatel :: PArray Int -> PArray a -> PArray (PArray a)+replicatel      = lift2 replicate+++-- | O(sum lengths). Segmented replicate.+replicates :: U.Segd -> PArray a -> PArray a+replicates segd vec+        | V.length vec /= U.lengthSegd segd+        = die "replicates" $ unlines+                [ "segd length mismatch"+                , "  segd length  = " ++ (show $ U.lengthSegd segd)+                , "  array length = " ++ (show $ V.length vec)]++        | otherwise+        = join +        $ V.zipWith V.replicate+                (V.convert $ U.lengthsSegd segd)+                vec+++-- | O(sum lengths). Wrapper for segmented replicate that takes replication counts+--  and uses them to build the `U.Segd`.+replicates' :: PArray Int -> PArray a -> PArray a+replicates' reps arr+        = replicates (U.lengthsToSegd $ V.convert $ reps) arr+++-- | Append two arrays.+append :: PArray a -> PArray a -> PArray a+append          = (V.++)+++-- | Lifted append.+appendl :: PArray (PArray a) -> PArray (PArray a) -> PArray (PArray a)+appendl         = lift2 append+++-- | Concatenation+concat :: PArray (PArray a) -> PArray a+concat          = join+++-- | Lifted concatenation.+concatl :: PArray (PArray (PArray a)) -> PArray (PArray a)+concatl         = lift1 concat+++-- | Impose a nesting structure on a flat array+unconcat :: PArray (PArray a) -> PArray b -> PArray (PArray b)+unconcat arr1 arr2+        = nestUSegd (takeUSegd arr1) arr2+++-- | 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 :: U.Segd -> PArray a -> PArray (PArray a)+nestUSegd segd vec+        | U.elementsSegd segd     == V.length vec +        = V.zipWith+                (\start len -> V.slice start len vec)+                (V.convert $ U.indicesSegd segd)+                (V.convert $ U.lengthsSegd segd)++        | otherwise+        = error $ unlines+                [ "Data.Array.Parallel.PArray.nestSegd: 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 $ V.length vec)]+{-# NOINLINE nestUSegd #-}+++-- Projections ----------------------------------------------------------------+-- | Take the length of an array+length :: PArray a -> Int+length          = V.length+++-- | Take the length of some arrays.+lengthl :: PArray (PArray a) -> PArray Int+lengthl         = lift1 length+++-- | Lookup a single element from the source array.+index :: PArray a -> Int -> a+index           = (V.!)+++-- | Lookup a several elements from several source arrays.+indexl :: PArray (PArray a) -> PArray Int -> PArray a+indexl          = lift2 index+++-- | Extract a range of elements from an array.+extract :: PArray a -> Int -> Int -> PArray a+extract vec start len+        = V.slice start len vec+++-- | Segmented extract.+extracts :: Vector (PArray a) -> U.SSegd -> PArray a+extracts arrs ssegd+        = join+        $ V.zipWith3+                (\src start len -> extract (arrs V.! src) start len)+                (V.convert $ U.sourcesOfSSegd ssegd)+                (V.convert $ U.startsOfSSegd  ssegd)+                (V.convert $ U.lengthsOfSSegd ssegd)+++-- | Wrapper for `extracts` that takes arrays of sources, starts and lengths of+--   the segments, and uses these to build the `U.SSegd`.+extracts' +        :: 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 sources starts lengths+ = let  segd    = U.lengthsToSegd $ V.convert lengths+        ssegd   = U.mkSSegd +                        (V.convert $ starts)+                        (V.convert $ sources)+                        segd+   in   extracts arrs ssegd+++-- | Extract a range of elements from an arrary.+--   Like `extract` but with the parameters in a different order.+slice :: Int -> Int -> PArray a -> PArray a+slice start len arr+        = extract arr start len+++-- | Extract some slices from some arrays.+--   The arrays of starting indices and lengths must themselves+--   have the same length.+slicel :: PArray Int -> PArray Int -> PArray (PArray a) -> PArray (PArray a)+slicel  = lift3 slice+++-- | Take the segment descriptor from a nested array. This can cause index space+--   overflow if the number of elements in the result does not can not be+--   represented by a single machine word.+takeUSegd :: PArray (PArray a) -> U.Segd+takeUSegd vec+        = U.lengthsToSegd +        $ V.convert+        $ V.map length vec         -        when ( debugLiftedCompare -             && or [ not $ A.valid arrImpl-                   , not $ A.length arrRef == A.length arrImpl-                   , not $ V.and $ V.zipWith similar-                                (A.toVectors1 arrRef)-                                (A.toVectors1 arrImpl)])-         $ error $ render $ vcat-                [ text "withRef1: failure " <> text name-                , nest 4 $ pprp1v $ A.toVectors1 arrRef-                , nest 4 $ pprp1  $ arrImpl ] -        return arrImpl+-- Pack and Combine -----------------------------------------------------------+-- | Select the elements of an array that have their tag set to True.+pack    :: PArray a -> PArray Bool -> PArray a+pack xs bs+        | V.length xs /= V.length bs+        = die "pack" $ unlines+                [ "array length mismatch"+                , "  data  length = " ++ (show $ V.length xs)+                , "  flags length = " ++ (show $ V.length bs) ] +        | otherwise+        = V.ifilter (\i _ -> bs V.! i) xs --- | Compare the nested result of some array operator against a reference.-withRef2 :: ( A.Array r (r a)-            , A.Array r a-            , A.Array c (c a), PprPhysical1 (c (c a))-            , A.Array c a,     PprPhysical1 (c a)-            , Similar a,       PprPhysical1 a)-         => String      -- name of operator.-         -> r (r a)     -- result using reference implementaiton.-         -> c (c a)     -- result using vseg implementation.-         -> c (c a) -{-# INLINE withRef2 #-}-withRef2 name arrRef arrImpl- = if debugLiftedCompare || debugLiftedTrace-         then withRef2' name arrRef arrImpl-         else arrImpl+-- | Lifted pack.+packl :: PArray (PArray a) -> PArray (PArray Bool) -> PArray (PArray a)+packl   = lift2 pack -{-# NOINLINE withRef2' #-}-withRef2' name arrRef arrImpl- = unsafePerformIO- $ do   when debugLiftedTrace-         $ do putStrLn  $ "* " ++ name-              putStrLn  $ render (nest 4 $ pprp1 arrImpl)-              hFlush stdout -        when ( debugLiftedCompare-             && or [ not $ A.valid arrImpl-                   , not $ A.length arrRef == A.length arrImpl-                   , not $ V.and $ V.zipWith -                                (\xs ys -> V.and $ V.zipWith similar xs ys)-                                (A.toVectors2 arrRef)-                                (A.toVectors2 arrImpl) ])-         $ error $ render $ vcat-                [ text "withRef2: failure " <> text name-                , nest 4 $ pprp1 arrImpl ]+-- | Filter an array based on some tags.+packByTag :: PArray a -> U.Array Tag -> Tag -> PArray a+packByTag xs tags tag+        | V.length xs /= U.length tags+        = die "packByTag" $ unlines+                [ "array length mismatch"+                , "  data  length = " ++ (show $ V.length xs)+                , "  flags length = " ++ (show $ U.length tags) ] -        return arrImpl+        | otherwise+        = V.ifilter (\i _ -> U.index (here "packByTag") tags i == tag) xs  --- toRef ------------------------------------------------------------------------- | Convert an array to the reference version.-toRef1  :: ( A.Array c a-           , A.Array r a)-        => c a -> r a+-- | Combine two arrays based on a selector.+combine2 :: U.Sel2 -> PArray a -> PArray a -> PArray a+combine2 tags vec1 vec2+ = let  go [] [] []                     = []+        go (0 : bs) (x : xs) ys         = x : go bs xs ys+        go (1 : bs) xs       (y : ys)   = y : go bs xs ys+        go _ _ _ = error "Data.Array.Parallel.PArray.combine: length mismatch"+ +   in   V.fromList+                $ go    (V.toList $ V.convert $ U.tagsSel2 tags)+                        (V.toList vec1)+                        (V.toList vec2) -toRef1  = A.fromVectors1 . A.toVectors1-{-# NOINLINE toRef1 #-}---  NOINLINE because it's only for debugging. +-- Enumerations ---------------------------------------------------------------+-- | Construct a range of integers+enumFromTo :: Int -> Int -> PArray Int+enumFromTo      = V.enumFromTo --- | Convert a nested array to the reference version.-toRef2 :: ( A.Array c (c a)-          , A.Array c a-          , A.Array r (r a)-          , A.Array r a)-       => c (c a)-       -> r (r a) -toRef2  = A.fromVectors2 . A.toVectors2-{-# NOINLINE toRef2 #-}---  NOINLINE because it's only for debugging.+-- | Lifted enumeration+enumFromTol :: PArray Int -> PArray Int -> PArray (PArray Int)+enumFromTol     = lift2 enumFromTo  --- | Convert a doubly nested array to the reference version.-toRef3 :: ( A.Array c (c (c a))-          , A.Array c (c a)-          , A.Array c a-          , A.Array r (r (r a))-          , A.Array r (r a)-          , A.Array r a)-       => c (c (c a))-       -> r (r (r a))+-- Tuples ---------------------------------------------------------------------+-- | O(n). Zip a pair of arrays into an array of pairs.+zip     :: PArray a -> PArray b -> PArray (a, b)+zip     = V.zip -toRef3  = A.fromVectors3 . A.toVectors3-{-# NOINLINE toRef3 #-}---  NOINLINE because it's only for debugging.++-- | Lifted zip+zipl    :: PArray (PArray a) -> PArray (PArray b) -> PArray (PArray (a, b))+zipl    = lift2 zip+++-- | O(n). Unzip an array of pairs into a pair of arrays.+unzip   :: PArray (a, b) -> (PArray a, PArray b)+unzip   = V.unzip+++-- | Lifted unzip+unzipl  :: PArray (PArray (a, b)) -> PArray (PArray a, PArray b)+unzipl  = lift1 unzip+++-- Conversions ----------------------------------------------------------------+-- | Convert a `Vector` to a `PArray`+fromVector :: Vector a -> PArray a+fromVector = id+++-- | Convert a `PArray` to a `Vector`        +toVector   :: PArray a -> Vector a+toVector   = id++-- | Convert a list to a `PArray`.+fromList   :: [a] -> PArray a+fromList   = V.fromList++-- | Convert a `PArray` to a list.+toList     :: PArray a -> [a]+toList     = V.toList+++-- | Convert a `U.Array` to a `PArray`+fromUArray :: U.Elt a => U.Array a -> PArray a+fromUArray  = V.convert+++-- | Convert a `PArray` to a `U.Array`+toUArray   :: U.Elt a => PArray a -> U.Array a+toUArray    = V.convert+++-- | Convert a `U.Array` of tuples to a `PArray`+fromUArray2+        :: (U.Elt a, U.Elt b)+        => U.Array (a, b) -> PArray (a, b)+        +fromUArray2  = V.convert
+ Data/Array/Parallel/PArray/Reference/Convert.hs view
@@ -0,0 +1,170 @@+{-# LANGUAGE UndecidableInstances #-}+{-# OPTIONS -fno-warn-missing-signatures #-}+-- | During testing, we compare the output of each invocation of the lifted+--   combinators in "Data.Array.Parallel.PArray" with the reference implementations. +--+--   This module helps convert the to and from the array representation+--   used by the reference implementation.++--   TODO: we could use this to trace the lengths of the vectors being used, +--         as well as the types that each opeartor is being called at.+--+module Data.Array.Parallel.PArray.Reference.Convert+        ( Similar(..), PprPhysical1 (..)+        , withRef1, withRef2+        , toRef1,   toRef2,   toRef3)+where+import Data.Array.Parallel.Pretty+import qualified Data.Array.Parallel.Array      as A+import qualified Data.Vector                    as V+import Data.Vector                              (Vector)+import Prelude hiding (length)+import System.IO+import System.IO.Unsafe+import Control.Monad++-- Config ---------------------------------------------------------------------+debugLiftedTrace        :: Bool+debugLiftedTrace        = False++debugLiftedCompare      :: Bool+debugLiftedCompare      = False++class Similar a where+ similar :: a -> a -> Bool++class PprPhysical1 a where+ pprp1  :: a -> Doc++ pprp1v :: Vector a -> Doc+ pprp1v vec+        = brackets +        $ hcat+        $ punctuate (text ", ") +        $ V.toList $ V.map pprp1 vec+        ++-- withRef --------------------------------------------------------------------+-- | Compare the result of some array operator against a reference.++--  Careful:+--   * We don't want to inline the whole body of this function into+--     every use site, or we'll get code explosion. When debugging is off we+--     want this wrapper to be inlined and eliminated as cheaply as possible.+--   * We also do this with 'unsafePerformIO' instead of trace, because+--     with trace, if the computation contructing the string throws an exception+--     then we get no output. For debugging we want to see what function was+--     entered before we try to print the result (which might be badly formed),+--+withRef1 :: ( A.Array r a+            , A.Array c a, PprPhysical1 (c a)+            , Similar a,   PprPhysical1 a)+         => String              -- name of operator+         -> r a                 -- result using reference implementation+         -> c a                 -- result using vseg implementation+         -> c a++{-# INLINE withRef1 #-}+withRef1 name arrRef arrImpl+ = if debugLiftedCompare || debugLiftedTrace+        then withRef1' name arrRef arrImpl+        else arrImpl+        +{-# NOINLINE withRef1' #-}+withRef1' name arrRef arrImpl+ = unsafePerformIO+ $ do   when debugLiftedTrace+         $ do putStrLn  $ "* " ++ name+              putStrLn  $ render (nest 4 $ pprp1 arrImpl)+              hFlush stdout+        +        when ( debugLiftedCompare +             && or [ not $ A.valid arrImpl+                   , not $ A.length arrRef == A.length arrImpl+                   , not $ V.and $ V.zipWith similar+                                (A.toVectors1 arrRef)+                                (A.toVectors1 arrImpl)])+         $ error $ render $ vcat+                [ text "withRef1: failure " <> text name+                , nest 4 $ pprp1v $ A.toVectors1 arrRef+                , nest 4 $ pprp1  $ arrImpl ]++        return arrImpl+++-- | Compare the nested result of some array operator against a reference.+withRef2 :: ( A.Array r (r a)+            , A.Array r a+            , A.Array c (c a), PprPhysical1 (c (c a))+            , A.Array c a,     PprPhysical1 (c a)+            , Similar a,       PprPhysical1 a)+         => String      -- name of operator.+         -> r (r a)     -- result using reference implementaiton.+         -> c (c a)     -- result using vseg implementation.+         -> c (c a)++{-# INLINE withRef2 #-}+withRef2 name arrRef arrImpl+ = if debugLiftedCompare || debugLiftedTrace+         then withRef2' name arrRef arrImpl+         else arrImpl++{-# NOINLINE withRef2' #-}+withRef2' name arrRef arrImpl+ = unsafePerformIO+ $ do   when debugLiftedTrace+         $ do putStrLn  $ "* " ++ name+              putStrLn  $ render (nest 4 $ pprp1 arrImpl)+              hFlush stdout++        when ( debugLiftedCompare+             && or [ not $ A.valid arrImpl+                   , not $ A.length arrRef == A.length arrImpl+                   , not $ V.and $ V.zipWith +                                (\xs ys -> V.and $ V.zipWith similar xs ys)+                                (A.toVectors2 arrRef)+                                (A.toVectors2 arrImpl) ])+         $ error $ render $ vcat+                [ text "withRef2: failure " <> text name+                , nest 4 $ pprp1 arrImpl ]++        return arrImpl+++-- toRef ----------------------------------------------------------------------+-- | Convert an array to the reference version.+toRef1  :: ( A.Array c a+           , A.Array r a)+        => c a -> r a++toRef1  = A.fromVectors1 . A.toVectors1+{-# NOINLINE toRef1 #-}+--  NOINLINE because it's only for debugging.+++-- | Convert a nested array to the reference version.+toRef2 :: ( A.Array c (c a)+          , A.Array c a+          , A.Array r (r a)+          , A.Array r a)+       => c (c a)+       -> r (r a)++toRef2  = A.fromVectors2 . A.toVectors2+{-# NOINLINE toRef2 #-}+--  NOINLINE because it's only for debugging.+++-- | Convert a doubly nested array to the reference version.+toRef3 :: ( A.Array c (c (c a))+          , A.Array c (c a)+          , A.Array c a+          , A.Array r (r (r a))+          , A.Array r (r a)+          , A.Array r a)+       => c (c (c a))+       -> r (r (r a))++toRef3  = A.fromVectors3 . A.toVectors3+{-# NOINLINE toRef3 #-}+--  NOINLINE because it's only for debugging.
Data/Array/Parallel/PArray/Types.hs view
@@ -27,6 +27,7 @@ where import Data.Array.Parallel.Base (Tag) import Data.Array.Parallel.Pretty+import Data.Typeable   -- Void -----------------------------------------------------------------------@@ -37,6 +38,8 @@ --  data Void +deriving instance Typeable Void+ -- | A 'value' with the void type. Used as a placholder like `undefined`. --   Forcing this yields `error`.  void    :: Void@@ -60,6 +63,9 @@ data Sum2 a b         = Alt2_1 a | Alt2_2 b +deriving instance Typeable2 Sum2++ tagOfSum2 :: Sum2 a b -> Tag tagOfSum2 ss  = case ss of@@ -80,6 +86,9 @@ data Sum3 a b c         = Alt3_1 a | Alt3_2 b | Alt3_3 c +deriving instance Typeable3 Sum3++ tagOfSum3 :: Sum3 a b c -> Tag tagOfSum3 ss  = case ss of@@ -114,3 +123,4 @@ -- newtype Wrap a = Wrap { unWrap :: a } +deriving instance Typeable1 Wrap
dph-lifted-base.cabal view
@@ -1,5 +1,5 @@ Name:           dph-lifted-base-Version:        0.6.1.1+Version:        0.7.0.1 License:        BSD3 License-File:   LICENSE Author:         The DPH Team@@ -15,7 +15,7 @@   Exposed-Modules:         Data.Array.Parallel.PArray.Types         Data.Array.Parallel.PArray.Reference-        Data.Array.Parallel.PArray+        Data.Array.Parallel.PArray.Reference.Convert         Data.Array.Parallel.PArr            Exposed:@@ -43,7 +43,7 @@         ExistentialQuantification,         ScopedTypeVariables,         PatternGuards,-        PackageImports+        DeriveDataTypeable    GHC-Options:         -Odph @@ -53,13 +53,13 @@         -fno-warn-orphans    Build-Depends:  -        base                    == 4.5.*,+        base                    == 4.6.*,         ghc                     == 7.*,         array                   == 0.4.*,         random                  == 1.0.*,-        template-haskell        == 2.7.*,-        vector                  == 0.9.*,+        template-haskell        == 2.8.*,+        dph-base                == 0.7.*,+        dph-prim-par            == 0.7.*,+        vector                  == 0.10.*,         pretty                  == 1.1.*,-        containers              == 0.4.*, -        dph-base                == 0.6.1.*,-        dph-prim-par            == 0.6.1.*+        containers              == 0.5.*