packages feed

dph-prim-interface 0.5.1.1 → 0.6.0.1

raw patch · 5 files changed

+1784/−951 lines, 5 filesdep +vectordep ~basedep ~dph-basePVP ok

version bump matches the API change (PVP)

Dependencies added: vector

Dependency ranges changed: base, dph-base

API changes (from Hackage documentation)

- Data.Array.Parallel.Unlifted: (!:) :: Elt a => Array a -> Int -> a
+ Data.Array.Parallel.Unlifted: appendSSegd :: SSegd -> Int -> SSegd -> Int -> SSegd
+ Data.Array.Parallel.Unlifted: appendVSegd :: VSegd -> Int -> VSegd -> Int -> VSegd
+ Data.Array.Parallel.Unlifted: appends :: (Elt a, Elts a) => Arrays a -> Arrays a -> Arrays a
+ Data.Array.Parallel.Unlifted: class Elts a
+ Data.Array.Parallel.Unlifted: combine2VSegd :: Sel2 -> VSegd -> Int -> VSegd -> Int -> VSegd
+ Data.Array.Parallel.Unlifted: count_ss :: (Elt a, Eq a) => SSegd -> Vector (Array a) -> a -> Array Int
+ Data.Array.Parallel.Unlifted: data SSegd
+ Data.Array.Parallel.Unlifted: data VSegd
+ Data.Array.Parallel.Unlifted: emptySSegd :: SSegd
+ Data.Array.Parallel.Unlifted: emptySegd :: Segd
+ Data.Array.Parallel.Unlifted: emptyVSegd :: VSegd
+ Data.Array.Parallel.Unlifted: emptys :: Arrays a
+ Data.Array.Parallel.Unlifted: extracts_ass :: (Elt a, Elts a) => SSegd -> Arrays a -> Array a
+ Data.Array.Parallel.Unlifted: extracts_avs :: (Elt a, Elts a) => VSegd -> Arrays a -> Array a
+ Data.Array.Parallel.Unlifted: extracts_nss :: Elt a => SSegd -> Vector (Array a) -> Array a
+ Data.Array.Parallel.Unlifted: fold1_ss :: (Elts a, Elt a) => (a -> a -> a) -> SSegd -> Arrays a -> Array a
+ Data.Array.Parallel.Unlifted: fold1_vs :: (Elts a, Elt a) => (a -> a -> a) -> VSegd -> Arrays a -> Array a
+ Data.Array.Parallel.Unlifted: fold_ss :: (Elts a, Elt a) => (a -> a -> a) -> a -> SSegd -> Arrays a -> Array a
+ Data.Array.Parallel.Unlifted: fold_vs :: (Elts a, Elt a) => (a -> a -> a) -> a -> VSegd -> Arrays a -> Array a
+ Data.Array.Parallel.Unlifted: fromVectors :: (Elt a, Elts a) => Vector (Array a) -> Arrays a
+ Data.Array.Parallel.Unlifted: getSegOfSSegd :: SSegd -> Int -> (Int, Int, Int, Int)
+ Data.Array.Parallel.Unlifted: getSegOfVSegd :: VSegd -> Int -> (Int, Int, Int)
+ Data.Array.Parallel.Unlifted: index :: Elt a => String -> Array a -> Int -> a
+ Data.Array.Parallel.Unlifted: indexs :: Elt a => Array a -> Array Int -> Array a
+ Data.Array.Parallel.Unlifted: indexs_avs :: (Elt a, Elts a) => Arrays a -> VSegd -> Array (Int, Int) -> Array a
+ Data.Array.Parallel.Unlifted: indicesOfSSegd :: SSegd -> Array Int
+ Data.Array.Parallel.Unlifted: instance Elts Double
+ Data.Array.Parallel.Unlifted: instance Elts Float
+ Data.Array.Parallel.Unlifted: instance Elts Int
+ Data.Array.Parallel.Unlifted: instance Elts Word8
+ Data.Array.Parallel.Unlifted: isContiguousSSegd :: SSegd -> Bool
+ Data.Array.Parallel.Unlifted: isContiguousVSegd :: VSegd -> Bool
+ Data.Array.Parallel.Unlifted: isManifestVSegd :: VSegd -> Bool
+ Data.Array.Parallel.Unlifted: lengthOfSSegd :: SSegd -> Int
+ Data.Array.Parallel.Unlifted: lengthOfVSegd :: VSegd -> Int
+ Data.Array.Parallel.Unlifted: lengths :: Elts a => Arrays a -> Int
+ Data.Array.Parallel.Unlifted: lengthsOfSSegd :: SSegd -> Array Int
+ Data.Array.Parallel.Unlifted: mkSSegd :: Array Int -> Array Int -> Segd -> SSegd
+ Data.Array.Parallel.Unlifted: mkVSegd :: Array Int -> SSegd -> VSegd
+ Data.Array.Parallel.Unlifted: promoteSSegdToVSegd :: SSegd -> VSegd
+ Data.Array.Parallel.Unlifted: promoteSegdToSSegd :: Segd -> SSegd
+ Data.Array.Parallel.Unlifted: promoteSegdToVSegd :: Segd -> VSegd
+ Data.Array.Parallel.Unlifted: replicatedVSegd :: Int -> Int -> VSegd
+ Data.Array.Parallel.Unlifted: singletonSSegd :: Int -> SSegd
+ Data.Array.Parallel.Unlifted: singletonSegd :: Int -> Segd
+ Data.Array.Parallel.Unlifted: singletonVSegd :: Int -> VSegd
+ Data.Array.Parallel.Unlifted: singletons :: (Elt a, Elts a) => Array a -> Arrays a
+ Data.Array.Parallel.Unlifted: sourcesOfSSegd :: SSegd -> Array Int
+ Data.Array.Parallel.Unlifted: startsOfSSegd :: SSegd -> Array Int
+ Data.Array.Parallel.Unlifted: sum_ss :: (Num a, Elts a, Elt a) => SSegd -> Arrays a -> Array a
+ Data.Array.Parallel.Unlifted: takeLengthsOfVSegd :: VSegd -> Array Int
+ Data.Array.Parallel.Unlifted: takeSSegdOfVSegd :: VSegd -> SSegd
+ Data.Array.Parallel.Unlifted: takeSSegdRedundantOfVSegd :: VSegd -> SSegd
+ Data.Array.Parallel.Unlifted: takeVSegidsOfVSegd :: VSegd -> Array Int
+ Data.Array.Parallel.Unlifted: takeVSegidsRedundantOfVSegd :: VSegd -> Array Int
+ Data.Array.Parallel.Unlifted: toVectors :: (Elt a, Elts a) => Arrays a -> Vector (Array a)
+ Data.Array.Parallel.Unlifted: type Arrays a = [[a]]
+ Data.Array.Parallel.Unlifted: type SelRep2 = ()
+ Data.Array.Parallel.Unlifted: unsafeDemoteToSSegdOfVSegd :: VSegd -> SSegd
+ Data.Array.Parallel.Unlifted: unsafeDemoteToSegdOfVSegd :: VSegd -> Segd
+ Data.Array.Parallel.Unlifted: unsafeIndex2s :: (Elt a, Elts a) => Arrays a -> Int -> Int -> a
+ Data.Array.Parallel.Unlifted: unsafeIndexs :: (Elt a, Elts a) => Arrays a -> Int -> Array a
+ Data.Array.Parallel.Unlifted: unzip3 :: (Elt a, Elt b, Elt c) => Array (a, b, c) -> (Array a, Array b, Array c)
+ Data.Array.Parallel.Unlifted: updateVSegsOfVSegd :: (Array Int -> Array Int) -> VSegd -> VSegd
+ Data.Array.Parallel.Unlifted: updateVSegsReachableOfVSegd :: (Array Int -> Array Int) -> VSegd -> VSegd
+ Data.Array.Parallel.Unlifted: validSSegd :: SSegd -> Bool
+ Data.Array.Parallel.Unlifted: validSegd :: Segd -> Bool
+ Data.Array.Parallel.Unlifted: validVSegd :: VSegd -> Bool
+ Data.Array.Parallel.Unlifted: zip3 :: (Elt a, Elt b, Elt c) => Array a -> Array b -> Array c -> Array (a, b, c)

Files

Data/Array/Parallel/Unlifted.hs view
@@ -1,21 +1,19 @@ {-# LANGUAGE TypeOperators, CPP #-} --- | This module provides the API for the DPH backend. ------   These are the DPH array primitives that the vectoriser introduces when---   transforming code. The actual code in this module is fake, in the sense---   that is provides a partial reference implementation using lists to---   represent arrays, but this code isn't acually used at runtime.+-- | WARNING: +--   This is an abstract interface. All the functions will just `error` if called.  -----   The actual code used by compiled programs depends on whether @-fdph-par@ or---   @-fdph-seq@ is passed  when compiling it. Depending on the flag, the---   implementation in either the @dph-prim-par@ or @dph-prim-seq packages@ is---   swapped in. These packages export the same API, but use a more efficient, ---   and perhaps parallel implementation.+--   This module provides an API for the segmented array primitives used by DPH.+--   None of the functions here have implementations. -----   All three packages are forced to use the same API by the 'DPH_Header.h'---   and 'DPH_Interface.h' include files in @dph-prim-interface/interface@.+--   Client programs should use either the @dph-prim-seq@ or @dph-prim-par@+--   packages, as these provide the same API and contain real code. --++--   NOTE: The API is enforced by the DPH_Header.h and DPH_Interface.h headers.+--   The dph-prim-interface, dph-prim-seq, and dph-prim-par modules all import+--   the same headers so we can be sure we're presenting the same API.+ #include "DPH_Header.h"  import qualified Prelude as P@@ -23,172 +21,220 @@  #include "DPH_Interface.h" --- NOTE -------------------------------------------------------------------------- See DPH_Interface.h for documentation. ---   As these functions are defined multiple times in different packages, ---   we keep all the docs there.------ The definitions should appear in the same order as they are defined in DPH_Interface.h -#define ASSERT assert __FILE__ __LINE__+------------------------------------------------------------------------------+notImplemented :: P.String -> a+notImplemented fnName+ = P.error $ P.unlines+ [ "dph-prim-interface:Data.Array.Parallel.Unlifted." P.++ fnName+ , "This module is an abstract interface and does not contain real code."+ , "Use dph-prim-seq or dph-prim-par instead." ]+{-# NOINLINE notImplemented #-} -assert :: P.String -> Int -> Bool -> a -> a-assert file line False _-  = P.error $ file P.++ " (line " P.++ P.show line P.++ "): assertion failure"-assert _ _ _ x = x +-- Types ---------------------------------------------------------------------- class Elt a instance Elt a => Elt [a]+type Array a    = [a] -type Array a = [a] -data Segd -        = Segd -        { segd_lengths  :: [Int]-        , segd_indices  :: [Int]-        , segd_elements :: Int }+-- Constructors ---------------------------------------------------------------+empty                           = notImplemented "empty"+(+:+)                           = notImplemented "(+:+)"+append_s                        = notImplemented "append_s"+replicate                       = notImplemented "replicate"+replicate_s                     = notImplemented "replicate_s"+replicate_rs                    = notImplemented "replicate_rs"+repeat                          = notImplemented "repeat"+indexed                         = notImplemented "indexed"+indices_s                       = notImplemented "indices_s"+enumFromTo                      = notImplemented "enumFromTo"+enumFromThenTo                  = notImplemented "enumFromThenTo"+enumFromStepLen                 = notImplemented "enumFromStepLen"+enumFromStepLenEach             = notImplemented "enumFromStepLenEach" -data Sel2 -        = Sel2 -        { sel2_tags      :: [Tag]-        , sel2_indices   :: [Int]-        , sel2_elements0 :: Int-        , sel2_elements1 :: Int } -type SelRep2    = ()+-- Conversions ----------------------------------------------------------------+nest                            = notImplemented "nest"+toList                          = notImplemented "toList"+fromList                        = notImplemented "fromList"+toList_s                        = notImplemented "toList_s"+fromList_s                      = notImplemented "fromList_s"  -length          = P.length-empty           = []-replicate       = P.replicate-repeat n _ xs   = P.concat (replicate n xs)-(!:)            = (P.!!)-extract xs i n  = P.take n (P.drop i xs)-drop            = P.drop-permute         = P.error "Not implemented: dph-prim-interface:Data.Array.Parallel.Unlifted.permute"-bpermute xs ns  = map (xs !:) ns-mbpermute       = P.error "Not implemented: dph-prim-interface:Data.Array.Parallel.Unlifted.mbpermute"-bpermuteDft     = P.error "Not implemented: dph-prim-interface:Data.Array.Parallel.Unlifted.bpermuteDft"-update          = P.error "Not implemented: dph-prim-interface:Data.Array.Parallel.Unlifted.update"-(+:+)           = (P.++)-interleave xs ys = P.concat [[x,y] | (x,y) <- P.zip xs ys]+-- Projections ----------------------------------------------------------------+length                          = notImplemented "length"+index                           = notImplemented "index"+indexs                          = notImplemented "indexs"+indexs_avs                      = notImplemented "indexs_avs"+extract                         = notImplemented "extract"+extracts_nss                    = notImplemented "extract_nss"+extracts_ass                    = notImplemented "extract_ass"+extracts_avs                    = notImplemented "extract_avs"+drop                            = notImplemented "drop" -pack xs bs      = [x | (x,b) <- P.zip xs bs, b] -combine [] [] [] = []-combine (True  : bs) (x : xs) ys       = x : combine bs xs ys-combine (False : bs) xs       (y : ys) = y : combine bs xs ys+-- Update ---------------------------------------------------------------------+update                          = notImplemented "update" -combine2 tags _ xs ys = go tags xs ys-  where-    go [] [] [] = []-    go (0 : bs) (x : xs) ys = x : go bs xs ys-    go (1 : bs) xs (y : ys) = y : go bs xs ys -map             = P.map-filter          = P.filter-zip             = P.zip-zip3            = P.zip3-unzip           = P.unzip-unzip3          = P.unzip3-fsts            = map P.fst-snds            = map P.snd-zipWith         = P.zipWith+-- Permutation ----------------------------------------------------------------+permute                         = notImplemented "permute"+bpermute                        = notImplemented "bpermute"+mbpermute                       = notImplemented "mbpermute"+bpermuteDft                     = notImplemented "bpermuteDft" -fold            = P.foldr-fold1           = P.foldr1-and             = P.and-sum             = P.sum -scan f z        = P.init . P.scanl f z+-- Zipping and Unzipping ------------------------------------------------------+zip                             = notImplemented "zip"+zip3                            = notImplemented "zip3"+unzip                           = notImplemented "unzip"+unzip3                          = notImplemented "unzip3"+fsts                            = notImplemented "fsts"+snds                            = notImplemented "snds" -indexed xs              = zip [0 .. length xs - 1] xs-enumFromTo m n          = [m .. n]-enumFromThenTo m n s    = [m, n..s] -enumFromStepLen i k 0   = []-enumFromStepLen i k n   = i : enumFromStepLen (i+k) k (n-1)+-- Map and zipWith ------------------------------------------------------------+map                             = notImplemented "map"+zipWith                         = notImplemented "zipWith" -enumFromStepLenEach size starts steps lens-  = ASSERT (size == sum lens)-    P.concat-  $ P.zipWith3 (\x y z -> P.enumFromThenTo x (x+y) (x+y*z)) starts steps lens -replicate_s segd xs-        = P.concat-        $ zipWith replicate (lengthsSegd segd) xs+-- Scans and Folds -----------------------------------------------------------+scan                            = notImplemented "scan"+fold                            = notImplemented "fold"+fold_s                          = notImplemented "fold_s"+fold_ss                         = notImplemented "fold_ss"+fold_r                          = notImplemented "fold_r"+fold1                           = notImplemented "fold1"+fold1_s                         = notImplemented "fold1_s"+fold1_ss                        = notImplemented "fold1_ss"+sum                             = notImplemented "sum"+sum_r                           = notImplemented "sum_r"+and                             = notImplemented "and" -replicate_rs n xs-        = P.concat-        $ P.map (P.replicate n) xs -append_s _ xd xs yd ys -        = P.concat (P.zipWith (P.++) (nest xd xs) (nest yd ys))+-- Packing and Combining ------------------------------------------------------+pack                            = notImplemented "pack"+filter                          = notImplemented "filter"+combine                         = notImplemented "combine"+combine2                        = notImplemented "combine2"+interleave                      = notImplemented "interleave" -fold_s  f z segd xs-        = P.map (P.foldr f z) (nest segd xs) -fold1_s f   segd xs-        = P.map (P.foldr1 f)  (nest segd xs)+-- Selectors ------------------------------------------------------------------+data Sel2 +        = Sel2 +        { sel2_tags      :: [Tag]+        , sel2_indices   :: [Int]+        , sel2_elements0 :: Int+        , sel2_elements1 :: Int } -fold_r  f z segSize xs -        = P.error "FIXME GABI PLEASE PLEASE PLEASE"+type SelRep2    = () -sum_r segSize xs -        = P.error "FIXME GABI PLEASE PLEASE PLEASE" +mkSel2                          = notImplemented "mkSel2"+tagsSel2                        = notImplemented "tagsSel2"+indicesSel2                     = notImplemented "indicesSel2"+elementsSel2_0                  = notImplemented "elementsSel2_0"+elementsSel2_1                  = notImplemented "elementsSel2_1"+repSel2                         = notImplemented "repSel2" -indices_s segd-        = P.concat [[0 .. n-1] | n <- segd_lengths segd] +mkSelRep2                       = notImplemented "mkSelRep2"+indicesSelRep2                  = notImplemented "indicesSelRep2"+elementsSelRep2_0               = notImplemented "elementsSelRep2_0"+elementsSelRep2_1               = notImplemented "elementsSelRep2_1" -lengthSegd      = length . lengthsSegd-lengthsSegd     = segd_lengths-indicesSegd     = segd_indices-elementsSegd    = segd_elements-mkSegd          = Segd +-- Segment Descriptors --------------------------------------------------------+data Segd +        = Segd +        { segd_lengths  :: [Int]+        , segd_indices  :: [Int]+        , segd_elements :: Int } -mkSel2 tags idxs n0 n1 _ -        = Sel2 tags idxs n0 n1+mkSegd                          = notImplemented "mkSegd"+emptySegd                       = notImplemented "emptySegd"+singletonSegd                   = notImplemented "singletonSegd"+validSegd                       = notImplemented "validSegd"+lengthSegd                      = notImplemented "lengthSegd"+lengthsSegd                     = notImplemented "lengthsSegd"+indicesSegd                     = notImplemented "indicesSegd"+elementsSegd                    = notImplemented "elementsSegd" -tagsSel2        = sel2_tags-indicesSel2     = sel2_indices-elementsSel2_0  = sel2_elements0-elementsSel2_1  = sel2_elements1-repSel2 _       = () -mkSelRep2 _     = ()+-- Scattered Segment Descriptors ----------------------------------------------+data SSegd+        = SSegd+        { ssegd_starts  :: [Int]+        , ssegd_sources :: [Int]+        , ssegd_segd    :: Segd } -indicesSelRep2 tags _ -  = P.zipWith pick tags-  $ P.init-  $ P.scanl add (0,0) tags-  where-    pick 0 (i,j) = i-    pick 1 (i,j) = j+mkSSegd                         = notImplemented "mkSSegd"+validSSegd                      = notImplemented "validSSegd"+emptySSegd                      = notImplemented "emptySSegd"+singletonSSegd                  = notImplemented "singletonSSegd"+promoteSegdToSSegd              = notImplemented "promoteSegdToSSegd"+isContiguousSSegd               = notImplemented "isContiguousSSegd"+lengthOfSSegd                   = notImplemented "lengthOfSSegd"+lengthsOfSSegd                  = notImplemented "lenghtsOfSSegd"+indicesOfSSegd                  = notImplemented "indicesOfSSegd"+startsOfSSegd                   = notImplemented "startsOfSSegd"+sourcesOfSSegd                  = notImplemented "sourcesOfSSegd"+getSegOfSSegd                   = notImplemented "getSegOfSSegd"+appendSSegd                     = notImplemented "appendSSegd" -    add (i,j) 0 = (i+1,j)-    add (i,j) 1 = (i,j+1) -elementsSelRep2_0 tags _ = P.length [() | 0 <- tags]-elementsSelRep2_1 tags _ = P.length [() | 1 <- tags]+-- Virtual Segment Descriptors ------------------------------------------------+data VSegd+        = VSegd+        { vsegd_vsegids :: [Int]+        , vsegd_ssegd   :: SSegd } -randoms n       = P.take n . System.Random.randoms+mkVSegd                         = notImplemented "mkVSegd"+validVSegd                      = notImplemented "validSSegd"       +emptyVSegd                      = notImplemented "emptyVSegd"+singletonVSegd                  = notImplemented "singletonVSegd"+replicatedVSegd                 = notImplemented "replicatedVSegd"+promoteSegdToVSegd              = notImplemented "promoteSegdToVSegd"+promoteSSegdToVSegd             = notImplemented "promoteSSegdToVSegd"+isContiguousVSegd               = notImplemented "isContiguousVSegd"+isManifestVSegd                 = notImplemented "isManifestVSegd"+lengthOfVSegd                   = notImplemented "lengthOfVSegd"+takeVSegidsOfVSegd              = notImplemented "takeVSegidsOfVSegd"+takeVSegidsRedundantOfVSegd     = notImplemented "takeVSegidsRedundantOfVSegd"+takeSSegdOfVSegd                = notImplemented "takeSSegdOfVSegd"+takeSSegdRedundantOfVSegd       = notImplemented "takeSSegdRedundantOfVSegd"+takeLengthsOfVSegd              = notImplemented "takeLengthsOfVSegd"+getSegOfVSegd                   = notImplemented "getSegOfVSegd"+unsafeDemoteToSSegdOfVSegd      = notImplemented "unsafeDemoteToSSegdOfVSegd"+unsafeDemoteToSegdOfVSegd       = notImplemented "unsafeDemoteToSegdOfVSegd"+updateVSegsOfVSegd              = notImplemented "updateVSegsOfVSegd"+updateVSegsReachableOfVSegd     = notImplemented "updateVSegsReachableOfVSegd"+appendVSegd                     = notImplemented "appendVSegd"+combine2VSegd                   = notImplemented "combine2VSegd" -randomRs n r    = P.take n . System.Random.randomRs r -nest :: Segd -> [a] -> [[a]]-nest (Segd ns is _) xs = go ns xs-  where-    go [] [] = []-    go (n : ns) xs = let (ys, zs) = P.splitAt n xs-                     in ys : go ns zs+-- Irregular two dimensional arrays -------------------------------------------+class Elts a+type Arrays a+        = [[a]] -class Elt a => IOElt a-hPut            = P.error "Not implemented: dph-prim-interface:Data.Array.Parallel.Unlifted.hPut"-hGet            = P.error "Not implemented: dph-prim-interface:Data.Array.Parallel.Unlifted.hGet"+emptys                          = notImplemented "emptys"+lengths                         = notImplemented "lengths"+singletons                      = notImplemented "singletons"+unsafeIndexs                    = notImplemented "unsafeIndexs"+unsafeIndex2s                   = notImplemented "unsafeIndex2s"+appends                         = notImplemented "appends"+fromVectors                     = notImplemented "fromVectors"+toVectors                       = notImplemented "toVectors" -toList x        = x-fromList x      = x -toList_s x      = x-fromList_s x    = x+-- Random Arrays --------------------------------------------------------------+randoms n                       = notImplemented "randoms"+randomRs n r                    = notImplemented "randomRs"+++-- Array IO -------------------------------------------------------------------+class Elt a => IOElt a+hPut                            = notImplemented "hPut"+hGet                            = notImplemented "hGet"+
LICENSE view
@@ -1,5 +1,4 @@-Copyright (c) 2001-2011, The DPH Team-All rights reserved.+Copyright (c) 2001-2012, The DPH Team  The DPH Team is:   Manuel M T Chakravarty
dph-prim-interface.cabal view
@@ -1,12 +1,15 @@ Name:           dph-prim-interface-Version:        0.5.1.1+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:       Backend Interface for Data Parallel Haskell+Synopsis:       Data Parallel Haskell segmented arrays. (abstract interface)+Description:    Empty implementation of flat parallel arrays. +                This package exists only so that dph-prim-par and dph-prim-seq+                can provide the same interface.  Cabal-Version:  >= 1.6 Build-Type:     Simple@@ -26,10 +29,13 @@    Extensions: BangPatterns -  GHC-Options: -Odph -funbox-strict-fields -fcpr-off+  GHC-Options:+        -Odph+        -funbox-strict-fields -fcpr-off    Build-Depends: -        base     == 4.4.*,+        base     == 4.5.*,         random   == 1.0.*,-        dph-base == 0.5.*+        dph-base == 0.6.*,+        vector   == 0.9.* 
interface/DPH_Header.h view
@@ -2,74 +2,151 @@ #include "fusion-phases.h"  module Data.Array.Parallel.Unlifted (-  -- * Basics-  Elt, Array,  -  length,+  -- * Types+  Elt,  Array,      -- * Constructors   empty,-  (+:+),   generate,-  replicate, repeat,+  replicate, replicate_s, replicate_rs,+  repeat,   indexed,-  enumFromTo, enumFromThenTo, enumFromStepLen, enumFromStepLenEach,+  (+:+),     append_s,+  indices_s,+  enumFromTo,+  enumFromThenTo,+  enumFromStepLen,+  enumFromStepLenEach,    -- * Projections-  (!:),-  extract, drop,-  filter,+  length,+  index,+  indexs,+  indexs_avs,++  extract,+  extracts_nss,+  extracts_ass,+  extracts_avs,+  drop,   +  -- * Update+  update,+   -- * Permutation   permute,   bpermute,   mbpermute,   bpermuteDft,-  -  -- * Update-  update,-  -  -- * Packing and Combining-  pack,-  combine, combine2,-  interleave,+      +  -- * Zipping and Unzipping+  zip,   zip3,+  unzip, unzip3,+  fsts,  snds,    -- * Map and ZipWith   map, zipWith, zipWith3, zipWith4, -  -- * Zipping and Unzipping-  zip, unzip, fsts, snds,-    -  -- * Folds-  fold, fold1,-  and, sum, scan,---  -- * Segmented Constructors-  append_s, replicate_s, replicate_rs, +  -- * Scans and Folds+  scan,+  fold,  fold_s,  fold_ss,   fold_vs, fold_r,  +  fold1, fold1_s, fold1_ss,  fold1_vs,+  sum,   sum_s,   sum_ss,    sum_r,  +  count, count_s, count_ss,+  and,  -  -- * Segmented Folds-  fold_s, fold1_s, fold_r, sum_s,  sum_r,+  -- * Pack and Filter+  pack,+  packByTag,+  filter,+  pick,   -  -- * Segment Descriptors-  Segd,-  indices_s,-  lengthSegd, lengthsSegd, indicesSegd, elementsSegd, lengthsToSegd,-  mkSegd, plusSegd,+  -- * Combine and Interleave+  combine, combine2,+  interleave,    -- * Selectors   Sel2,   mkSel2, -  tagsSel2, indicesSel2, elementsSel2_0, elementsSel2_1, repSel2,+  tagsSel2,+  indicesSel2,+  elementsSel2_0,+  elementsSel2_1,+  repSel2,   tagsToSel2,   -  mkSelRep2, indicesSelRep2, elementsSelRep2_0, elementsSelRep2_1,+  -- * Selector Representations+  SelRep2,+  mkSelRep2,+  indicesSelRep2,+  elementsSelRep2_0,+  elementsSelRep2_1,+    +  -- * Segment Descriptors+  Segd,+  mkSegd,+  validSegd,+  emptySegd,+  singletonSegd,+  lengthsToSegd,+  lengthSegd,+  lengthsSegd,+  indicesSegd,+  elementsSegd,+  plusSegd, ++  -- * Scattered Segment Descriptors+  SSegd,+  mkSSegd,+  validSSegd,+  emptySSegd,+  singletonSSegd,+  promoteSegdToSSegd,+  isContiguousSSegd,+  lengthOfSSegd,+  lengthsOfSSegd,+  indicesOfSSegd,+  startsOfSSegd,+  sourcesOfSSegd,+  getSegOfSSegd,+  appendSSegd,   -  -- * Packing and picking-  packByTag, pick,+  -- * Virtual Segment Descriptors+  VSegd,+  mkVSegd,+  validVSegd,+  emptyVSegd,+  singletonVSegd,+  replicatedVSegd,+  promoteSegdToVSegd,+  promoteSSegdToVSegd,+  isManifestVSegd,+  isContiguousVSegd,+  lengthOfVSegd,+  takeVSegidsOfVSegd,+  takeVSegidsRedundantOfVSegd,+  takeSSegdOfVSegd,+  takeSSegdRedundantOfVSegd,+  takeLengthsOfVSegd,+  getSegOfVSegd,+  unsafeDemoteToSSegdOfVSegd,+  unsafeDemoteToSegdOfVSegd,+  updateVSegsOfVSegd,+  updateVSegsReachableOfVSegd,+  appendVSegd,+  combine2VSegd,   -  -- * Counting-  count, count_s,-+  -- * Irregular two dimensional arrays+  Elts, Arrays,+  emptys,+  singletons,+  lengths,+  unsafeIndexs,+  unsafeIndex2s,+  appends,+  fromVectors,+  toVectors,+     -- * Random arrays   randoms, randomRs,   @@ -83,4 +160,4 @@ import Data.Word                  (Word8) import qualified System.Random import qualified Prelude-+import qualified Data.Vector       as VV
interface/DPH_Interface.h view
@@ -1,762 +1,1467 @@-import Data.Array.Parallel.Base ( Tag, tagToInt, fromBool )-import qualified GHC.Base-import Prelude ((.), ($), Num(..), Eq(..), seq)-import qualified Prelude--instance Elt Int-instance Elt Word8-instance Elt Bool-instance Elt Float-instance Elt Double-instance (Elt a, Elt b) => Elt (a, b)--infixl 9 !:-infixr 5 +:+---- Basics ------------------------------------------------------------------------ | O(1). Take the number of elements in an array.-length :: Elt a => Array a -> Int-{-# INLINE_BACKEND length #-}----- Constructors ------------------------------------------------------------------ | An array with no elements.-empty :: Elt a => Array a-{-# INLINE_BACKEND empty #-}----- | O(n). Append two arrays.-(+:+) :: Elt a => Array a -> Array a -> Array a-{-# INLINE_BACKEND (+:+) #-}----- | Generate a new array given its length and a function to compute each element.-generate :: Elt a => Int -> (Int -> a) -> Array a-{-# INLINE_BACKEND generate #-}-generate n f = map f (enumFromTo 0 (n-1))--generate_cheap :: Elt a => Int -> (Int -> a) -> Array a-{-# INLINE_BACKEND generate_cheap #-}-generate_cheap n f = map f (enumFromTo 0 (n-1))---- | O(n). Produce a new array by replicating a single element the given number of times.-replicate :: Elt a => Int -> a -> Array a-{-# INLINE CONLIKE PHASE_BACKEND replicate #-}--{-# RULES--"seq/replicate" forall n x y.-  seq (replicate n x) y = n `seq` x `seq` y-- #-}----- | Produce an array by copying a portion of another array.-repeat  :: Elt a -        => Int          -- ^ number of times to repeat the source-        -> Int          -- ^ length of source (can be less than the provided array)-        -> Array a      -- ^ array elements to repeat-        -> Array a-{-# INLINE_BACKEND repeat #-}----- | Tag each element of an array with its index.------   Example: @indexed [:42, 93, 13:] = [:(0, 42), (1, 93), (2, 13):]@ -indexed :: Elt a => Array a -> Array (Int, a)-{-# INLINE_BACKEND indexed #-}----- | Generate a range of @Int@s.-enumFromTo :: Int -> Int -> Array Int-{-# INLINE_BACKEND enumFromTo #-}--enumFromThenTo :: Int -> Int -> Int -> Array Int-{-# INLINE_BACKEND enumFromThenTo #-}--enumFromStepLen :: Int -> Int -> Int -> Array Int-{-# INLINE_BACKEND enumFromStepLen #-}--enumFromStepLenEach :: Int -> Array Int -> Array Int -> Array Int -> Array Int-{-# INLINE_BACKEND enumFromStepLenEach #-}---{-# RULES--"repeat/enumFromStepLen[Int]" forall i j k n len.-  repeat n len (enumFromStepLen i j k)-    = generate_cheap len (\m -> i + ((m `Prelude.rem` k) * j))--  #-}----- Projections ------------------------------------------------------------------- | O(1). Retrieve a numbered element from an array.-(!:) :: Elt a => Array a -> Int -> a-{-# INLINE_BACKEND (!:) #-}----- | O(n). Extract a subrange of elements from an array.---   Example: @extract [:23, 42, 93, 50, 27:] 1 3  = [:42, 93, 50:]@-extract :: Elt a-        => Array a      -- ^ source array-        -> Int          -- ^ starting index in source array-        -> Int          -- ^ length of result array-        -> Array a-{-# INLINE_BACKEND extract #-}----- | O(n). Drop some elements from the front of an array, ---         returning the latter portion.-drop :: Elt a => Int -> Array a -> Array a-{-# INLINE_BACKEND drop #-}----- Permutation ------------------------------------------------------------------- | O(n). Forwards permutation of array elements.-permute :: Elt a -        => Array a      -- ^ source array-        -> Array Int    -- ^ indices in the destination to copy elements to-        -> Array a-{-# INLINE_BACKEND permute #-}----- | O(n). Backwards permutation of array elements.------   Example @bpermute [:50, 60, 20, 30:] 3 [:0, 3, 2:]  = [:50, 30, 20:]@-bpermute -        :: Elt a -        => Array a      -- ^ source array-        -> Array Int    -- ^ indices in the source to copy elements from.-        -> Array a-{-# INLINE_BACKEND bpermute #-}----- | Combination of map and bpermute.------   The advantage of using this combined version is that we dont need---   to apply the parameter function to source elements that dont appear---   in the result.-mbpermute :: (Elt a, Elt b) => (a->b) -> Array a -> Array Int -> Array b-{-# INLINE_BACKEND mbpermute #-}----- | Default backwards permutation.------   * The values of the index-value pairs are written into the position in the---     result array that is indicated by the corresponding index.------   * All positions not covered by the index-value pairs will have the value---     determined by the initialiser function for that index position.----bpermuteDft:: Elt e => Int -> (Int -> e) -> Array (Int, e) -> Array e-{-# INLINE_BACKEND bpermuteDft #-}--{-# RULES-        -"bpermute/repeat" forall n len xs is.-  bpermute (repeat n len xs) is-    = len `Prelude.seq` bpermute xs (map (dph_mod_index len) is)--"bpermute/bpermute" forall xs is js.-  bpermute (bpermute xs is) js = bpermute xs (bpermute is js)--  #-}----- Update ------------------------------------------------------------------------ | O(n). Copy the source array in the destination, using new values for the given indices.-update :: Elt a => Array a -> Array (Int, a) -> Array a-{-# INLINE_BACKEND update #-}----- Packing and Combining -------------------------------------------------------- | Extract the elements from an array that match the given predicate.-filter :: Elt a => (a -> Bool) -> Array a -> Array a-{-# INLINE_BACKEND filter #-}----- | Extract elements of an array where the associated flag is true.-pack :: Elt a => Array a -> Array Bool -> Array a-{-# INLINE_BACKEND pack #-}----- | Combine two arrays, using a tag array to tell us where to get each element from.------   Example: @combine [T,F,F,T,T,F] [1,2,3] [4,5,6] = [1,4,5,2,3,6]@-combine :: Elt a => Array Bool -> Array a -> Array a -> Array a-{-# INLINE_BACKEND combine #-}----- | Like `combine`, but use a precomputed selector to speed up the process.--- ---   See dph-prim-seq:"Data.Array.Parallel.Unlifted.Sequential.Segmented.USel"---   for a description of how this works.---   -combine2 :: Elt a => Array Tag -> SelRep2 -> Array a -> Array a -> Array a-{-# INLINE_BACKEND combine2 #-}----- | Interleave the elements of two arrays.--- ---   Example: @interleave [1,2,3] [4,5,6] = [1,4,2,5,3,6]@-interleave :: Elt a => Array a -> Array a -> Array a-{-# INLINE_BACKEND interleave #-}----- Zipping and Unzipping --------------------------------------------------------- | O(1). Takes two arrays and returns an array of corresponding pairs.---         If one array is short, excess elements of the longer array are discarded.-zip :: (Elt a, Elt b) => Array a -> Array b -> Array (a, b)-{-# INLINE CONLIKE PHASE_BACKEND zip #-}----- | O(1). Transform an array into an array of the first components,---         and an array of the second components.-unzip :: (Elt a, Elt b) => Array (a, b) -> (Array a, Array b)-{-# INLINE_BACKEND unzip #-}----- | O(1). Take the first elements of an array of pairs.-fsts  :: (Elt a, Elt b) => Array (a, b) -> Array a-{-# INLINE_BACKEND fsts #-}----- | O(1). Take the second elements of an array of pairs.-snds :: (Elt a, Elt b) => Array (a, b) -> Array b-{-# INLINE_BACKEND snds #-}----- Maps and zipWith -------------------------------------------------------------- | Apply a worker function to each element of an array, yielding a new array.-map     :: (Elt a, Elt b)-        => (a -> b) -> Array a -> Array b-{-# INLINE_BACKEND map #-}----- | zipWith generalises zip by zipping with the function given as the first---         argument, instead of a tupling function.-zipWith :: (Elt a, Elt b, Elt c)-        => (a -> b -> c) -> Array a -> Array b -> Array c-{-# INLINE_BACKEND zipWith #-}---zipWith3 :: (Elt a, Elt b, Elt c, Elt d)-          => (a -> b -> c -> d) -> Array a -> Array b -> Array c -> Array d-{-# INLINE zipWith3 #-}-zipWith3 f xs ys zs-        = zipWith (\(x, y) z -> f x y z)-                  (zip xs ys)-                  zs--zipWith4 :: (Elt a, Elt b, Elt c, Elt d, Elt e)-         => (a -> b -> c -> d -> e)-         -> Array a -> Array b -> Array c -> Array d -> Array e-{-# INLINE zipWith4 #-}-zipWith4 f as bs cs ds-         = zipWith (\(a, b) (c, d) -> f a b c d)-                   (zip as bs)-                   (zip cs ds)----- Generally useful rules --------------{-# RULES-        -"zipWith/replicate" forall f m n x y.-  zipWith f (replicate m x) (replicate n y) = replicate m (f x y)--"zipWith/plusInt0_1" forall n xs.-  zipWith GHC.Base.plusInt (replicate n (GHC.Base.I# 0#)) xs = xs--"zipWith/plusInt0_2" forall n xs.-  zipWith GHC.Base.plusInt xs (replicate n (GHC.Base.I# 0#)) = xs--"zipWith(plusInt)/enumFromStepLen" forall i1 k1 n1 i2 k2 n2.-  zipWith GHC.Base.plusInt (enumFromStepLen i1 k1 n1)-                           (enumFromStepLen i2 k2 n2)-    = enumFromStepLen (i1+i2) (k1+k2) n1-  #-}----- FIXME: These are the SMVM rules. They are intentionally quite specific and--- we want to get rid of the ASAP.--{-# RULES--"map/zipWith (+)/enumFromStepLen" forall m n is.-  map (dph_mod_index m) (zipWith GHC.Base.plusInt (enumFromStepLen 0 m n) is)-    = map (dph_mod_index m) is--"map dph_mod_index/enumFromStepLenEach" forall k l is n1 n2.-  map (dph_mod_index k)-      (enumFromStepLenEach l is (replicate n1 (GHC.Base.I# 1#)) (replicate n2 k))-    = enumFromStepLenEach l (map (dph_mod_index k) is)-                            (replicate n1 (GHC.Base.I# 1#))-                            (replicate n2 k)--"map dph_mod_index/replicate_s" forall k segd xs.-  map (dph_mod_index k) (replicate_s segd xs)-    = replicate_s segd (map (dph_mod_index k) xs)--"map dph_mod_index/enumFromStepLen" forall k# i n.-  map (dph_mod_index (GHC.Base.I# k#)) (enumFromStepLen i (GHC.Base.I# k#) n)-    = replicate n i--"enumFromStepLenEach/replicate x 3" forall k m n1 n2 n3.-  enumFromStepLenEach m (replicate n1 (GHC.Base.I# 0#))-                        (replicate n2 (GHC.Base.I# 1#))-                        (replicate n3 k)-    = generate_cheap m (dph_mod_index k)--"bpermute/generate_cheap" forall n f xs.-  bpermute (generate_cheap n f) xs-    = map f xs- #-}-              - --- The following rules fuse arithmetic operations that shouldnt have been---  vectorised in the first place. For example, with  z = x * y + a, the vectoriser---  will lift * and + to vector operations. The result of the  the multiply will be---  written to a vector, and then read back to do the addition.------  Adding the zipWith rules ensures that the multiply and addition are performed---  in one go. On the other hand, they can break fusion in the backend library.------ NOTE: These rules are only temporary, they should go away when we have ---       vectorisation avoidance for scalar operations.--{- RULES  **************** DISABLED--"zipWith/zipWith/zipWith" forall f g h as bs cs ds.-  zipWith f (zipWith g as bs) (zipWith h cs ds)-   = zipWith4 (\a b c d -> f (g a b) (h c d)) as bs cs ds--"zipWith/zipWith_left"  forall f g as bs cs.-  zipWith f (zipWith g as bs) cs-   = zipWith3 (\a b c ->   f (g a b) c) as bs cs--"zipWith/zipWith_right" forall f g as bs cs.-  zipWith f as (zipWith g bs cs)-   = zipWith3 (\a b c ->   f a (g b c)) as bs cs--  -}----- More rules to recover from the lack of vectorisation avoidance.--- The regular form of the rules shows why we really dont want to do it this way.--{- RULES  ****************** DISABLED--"map/zipWith" forall f g xs ys.-  map f (zipWith g xs ys)-   = zipWith (\x y -> f (g x y)) xs ys--"zipWith3/map_1" forall f g xs ys zs.-  zipWith3 f (map g xs) ys zs-   = zipWith3 (\x y z -> f (g x) y z) xs ys zs--"zipWith3/map_2" forall f g xs ys zs.-  zipWith3 f xs (map g ys) zs-   = zipWith3 (\x y z -> f x (g y) z) xs ys zs--"zipWith3/map_3" forall f g xs ys zs.-  zipWith3 f xs ys (map g zs)-   = zipWith3 (\x y z -> f x y (g z)) xs ys zs--  -}----- Folds -------------------------------------------------------------------------- | Left fold over an array.-fold :: Elt a => (a -> a -> a) -> a -> Array a -> a-{-# INLINE_BACKEND fold #-}---- | Left fold over an array, using the first element to initialise the state.-fold1 :: Elt a => (a -> a -> a) -> Array a -> a-{-# INLINE_BACKEND fold1 #-}----- | Compute the conjunction of all elements in a boolean array.-and :: Array Bool -> Bool-{-# INLINE_BACKEND and #-}---- | Compute the sum of an array of numbers.-sum :: (Num a, Elt a) => Array a -> a-{-# INLINE_BACKEND sum #-}---- | Similar to `foldl` but return an array of the intermediate states, including---   the final state that is computed by `foldl`.-scan :: Elt a => (a -> a -> a) -> a -> Array a -> Array a-{-# INLINE_BACKEND scan #-}---{-# RULES--"seq/sum" forall xs e.-  seq (sum xs) e = seq xs e--"seq/scan<Int> (+)" forall i xs e.-  seq (scan GHC.Base.plusInt i xs) e = i `seq` xs `seq` e--"scan/replicate" forall z n x.-  scan GHC.Base.plusInt z (replicate n x)-    = enumFromStepLen z x n--  #-}----- Segmented Constructors ------------------------------------------------------append_s -        :: Elt a-        => Segd         -- ^ segment descriptor of result aarray-        -> Segd         -- ^ segment descriptor of first array-        -> Array a      -- ^ data of first array-        -> Segd         -- ^ segment descriptor of second array-        -> Array a      -- ^ data of first array-        -> Array a-{-# INLINE_BACKEND append_s #-}---replicate_s :: Elt a => Segd -> Array a -> Array a-{-# INLINE CONLIKE PHASE_BACKEND replicate_s #-}---replicate_rs :: Elt a => Int -> Array a -> Array a-{-# INLINE CONLIKE PHASE_BACKEND replicate_rs #-}---{-# RULES--"append_s->interleave" forall n k idxs1 idxs2 idxs3 m1 m2 m3 xs ys.-  append_s (mkSegd (replicate n k) idxs1 m1)-           (mkSegd (replicate n (GHC.Base.I# 1#)) idxs2 m2) xs-           (mkSegd (replicate n (GHC.Base.I# 1#)) idxs3 m3) ys-    = interleave xs ys--  #-}--{-# RULES--"replicate_s/replicate" forall segd k x.-  replicate_s segd (replicate k x) = replicate (elementsSegd segd) x--"replicate_s->replicate_rs" forall n m idxs nm xs.-  replicate_s (mkSegd (replicate n m) idxs nm) xs-    = replicate_rs m xs--"replicate_rs/replicate" forall m n x.-  replicate_rs m (replicate n x) = replicate (m*n) x--"sum/replicate_rs" forall n xs.-  sum (replicate_rs n xs) = sum xs * n--"count/replicate_s" forall segd xs tag.-  count (replicate_s segd xs) tag-    = sum (packByTag (lengthsSegd segd) xs tag)-- #-}----- Segmented Folds -------------------------------------------------------------fold_s :: Elt a => (a -> a -> a) -> a -> Segd -> Array a -> Array a-{-# INLINE_BACKEND fold_s #-}--fold1_s :: Elt a => (a -> a -> a) -> Segd -> Array a -> Array a-{-# INLINE_BACKEND fold1_s #-}--fold_r :: Elt a => (a -> a -> a) -> a -> Int -> Array a -> Array a-{-# INLINE_BACKEND fold_r #-}--sum_s :: (Num a, Elt a) => Segd -> Array a -> Array a-{-# INLINE sum_s #-}-sum_s = fold_s (Prelude.+) 0--sum_r :: (Num a, Elt a) => Int ->Array a -> Array a-{-# INLINE_BACKEND sum_r #-}--{-# RULES--"fold_s/replicate1" forall f z n idxs n' xs.-  fold_s f z (mkSegd (replicate n (GHC.Base.I# 1#)) idxs n') xs = xs--"fold_s/replicate" forall f z m n idxs mn xs.-  fold_s f z (mkSegd (replicate m n) idxs mn) xs-    = fold_r f z n xs--  #-}----- Operations on Segment Descriptors -------------------------------------------indices_s :: Segd -> Array Int-{-# INLINE_BACKEND indices_s #-}--lengthSegd :: Segd -> Int-{-# INLINE_BACKEND lengthSegd #-}--lengthsSegd :: Segd -> Array Int-{-# INLINE_BACKEND lengthsSegd #-}--indicesSegd :: Segd -> Array Int-{-# INLINE_BACKEND indicesSegd #-}--elementsSegd :: Segd -> Int-{-# INLINE_BACKEND elementsSegd #-}--lengthsToSegd :: Array Int -> Segd-{-# INLINE lengthsToSegd #-}-lengthsToSegd ns = mkSegd ns (scan (+) 0 ns) (sum ns)--mkSegd :: Array Int -> Array Int -> Int -> Segd-{-# INLINE CONLIKE PHASE_BACKEND mkSegd #-}--plusSegd :: Segd -> Segd -> Segd-{-# INLINE plusSegd #-}-plusSegd segd1 segd2-  = mkSegd (zipWith (+) (lengthsSegd segd1) (lengthsSegd segd2))-           (zipWith (+) (indicesSegd segd1) (indicesSegd segd2))-           (elementsSegd segd1 `dph_plus` elementsSegd segd2)---{-# RULES--"lengthsSegd/mkSegd" forall lens idxs n.-  lengthsSegd (mkSegd lens idxs n) = lens--"indicesSegd/mkSegd" forall lens idxs n.-  indicesSegd (mkSegd lens idxs n) = idxs--"elementsSegd/mkSegd" forall lens idxs n.-  elementsSegd (mkSegd lens idxs n) = n--"seq/elementsSegd" forall segd e.-  seq (elementsSegd segd) e = seq segd e--"seq/mkSegd" forall lens idxs n e.-  seq (mkSegd lens idxs n) e = lens `seq` idxs `seq` n `seq` e-- #-}----- Operations on Selectors -------------------------------------------------------- | O(1). Construct a selector. Selectors are used to speed up the `combine2` operation.------   See dph-prim-seq:"Data.Array.Parallel.Unlifted.Sequential.Segmented.USel"---   for a description of how this works.-mkSel2  :: Array Tag            -- ^ tags array-        -> Array Int            -- ^ indices array-        -> Int                  -- ^ number of elements taken from first source array-        -> Int                  -- ^ number of elements taken from second source array-        -> SelRep2      -        -> Sel2-{-# INLINE CONLIKE PHASE_BACKEND mkSel2 #-}----- | O(1). Get the tags array of a selector.-tagsSel2 :: Sel2 -> Array Tag-{-# INLINE_BACKEND tagsSel2 #-}----- | O(1). Get the indices array of a selector.-indicesSel2 :: Sel2 -> Array Int-{-# INLINE_BACKEND indicesSel2 #-}----- | O(1). Get the number of elements that will be taken from the first array.-elementsSel2_0 :: Sel2 -> Int-{-# INLINE_BACKEND elementsSel2_0 #-}----- | O(1). Get the number of elements that will be taken from the second array.-elementsSel2_1 :: Sel2 -> Int-{-# INLINE_BACKEND elementsSel2_1 #-}--repSel2 :: Sel2 -> SelRep2-{-# INLINE_BACKEND repSel2 #-}--mkSelRep2 :: Array Tag -> SelRep2-{-# INLINE CONLIKE PHASE_BACKEND mkSelRep2 #-}--indicesSelRep2 :: Array Tag -> SelRep2 -> Array Int-{-# INLINE_BACKEND indicesSelRep2 #-}--elementsSelRep2_0 :: Array Tag -> SelRep2 -> Int-{-# INLINE_BACKEND elementsSelRep2_0 #-}--elementsSelRep2_1 :: Array Tag -> SelRep2 -> Int-{-# INLINE_BACKEND elementsSelRep2_1 #-}----- | O(n), Compute a selector from a tags array.-tagsToSel2 :: Array Tag -> Sel2-{-# INLINE tagsToSel2 #-}-tagsToSel2 tags = let rep = mkSelRep2 tags-                  in-                  mkSel2 tags (indicesSelRep2    tags rep)-                              (elementsSelRep2_0 tags rep)-                              (elementsSelRep2_1 tags rep)-                              rep--{-# RULES--"tagsSel2/mkSel2"-  forall ts is n0 n1 r. tagsSel2 (mkSel2 ts is n0 n1 r) = ts-"indicesSel2/mkSel2"-  forall ts is n0 n1 r. indicesSel2 (mkSel2 ts is n0 n1 r) = is-"elementsSel2_0/mkSel2"-  forall ts is n0 n1 r. elementsSel2_0 (mkSel2 ts is n0 n1 r) = n0-"elementsSel2_1/mkSel2"-  forall ts is n0 n1 r. elementsSel2_1 (mkSel2 ts is n0 n1 r) = n1-"repSel2/mkSel2"-  forall ts is n0 n1 r. repSel2 (mkSel2 ts is n0 n1 r) = r--  #-}----- Packing and Picking ------------------------------------------------------------ | Select the elements of an array that have a corresponding tag.---   --- @--- packByTag [12, 24, 42, 93] [1, 0, 0, 1] 0---  = [24, 42]--- @----packByTag -        :: Elt a-        => Array a      -- ^ data values-        -> Array Tag    -- ^ tag values-        -> Tag          -- ^ the tag of values to select-        -> Array a      -- ^ data values that had that tag--{-# INLINE_BACKEND packByTag #-}-packByTag xs tags !tag-        = fsts (filter (\p -> Prelude.snd p == tag) (zip xs tags))---pick :: (Elt a, Eq a) => Array a -> a -> Array Bool-{-# INLINE pick #-}-pick xs !x = map (x==) xs--{-# RULES--"tagZeroes" UNTIL_PHASE_BACKEND forall xs n.-  map fromBool (zipWith GHC.Base.eqInt xs (replicate n (GHC.Base.I# 0#)))-    = tagZeroes xs--"replicate_s/tagZeroes" forall lens idxs n.-  replicate_s (mkSegd lens idxs n) (tagZeroes lens)-    = replicate n 0--"packByTag/replicate" forall xs n t u.-  packByTag xs (replicate n t) u = if t == u then xs else empty-- #-}--{-# RULES--"packByTag/bpermute" forall xs is tags n.-  packByTag (bpermute xs is) tags n-    = bpermute xs (packByTag is tags n)--  #-}------- Counting ---------------------------------------------------------------------- | Count the number of elements in array that are equal to the given value.-count :: (Elt a, Eq a) => Array a -> a -> Int-{-# INLINE_BACKEND count #-}-count xs !x = sum (map (tagToInt . fromBool . (==) x) xs)----- | Count the number of elements in segments that are equal to the given value.-count_s :: (Elt a, Eq a) => Segd -> Array a -> a -> Array Int-{-# INLINE_BACKEND count_s #-}-count_s segd xs !x = sum_s segd (map (tagToInt . fromBool . (==) x) xs)---{-# RULES--"count/seq" forall xs x y. seq (count xs x) y = seq xs (seq x y)--  #-}----- Random Arrays ---------------------------------------------------------------randoms :: (Elt a, System.Random.Random a, System.Random.RandomGen g)-        => Int -> g -> Array a-{-# INLINE_BACKEND randoms #-}--randomRs :: (Elt a, System.Random.Random a, System.Random.RandomGen g)-          => Int -> (a,a) -> g -> Array a-{-# INLINE_BACKEND randomRs #-}----- Array IO --------------------------------------------------------------------instance IOElt Int-instance IOElt Double-instance (IOElt a, IOElt b) => IOElt (a, b)----- | Write an array to a file.-hPut :: IOElt a => Handle -> Array a -> IO ()-{-# INLINE_BACKEND hPut #-}----- | Read an array from a file.-hGet :: IOElt a => Handle -> IO (Array a)-{-# INLINE_BACKEND hGet #-}----- | Convert an array to a list of elements.-toList :: Elt a => Array a -> [a]-{-# INLINE_BACKEND toList #-}----- | Convert a list of elements to an array.-fromList :: Elt a => [a] -> Array a-{-# INLINE_BACKEND fromList #-}----- Aliases for primitive operations --------------------------------------------dph_mod_index :: Int -> Int -> Int-{-# INLINE_BACKEND dph_mod_index #-}-dph_mod_index by idx = idx `GHC.Base.remInt` by--dph_plus :: Int -> Int -> Int-{-# INLINE_BACKEND dph_plus #-}-dph_plus x y = x Prelude.+ y--{-# RULES--"dph_plus" forall m n.-  dph_plus (GHC.Base.I# m) (GHC.Base.I# n) = GHC.Base.I# m Prelude.+ GHC.Base.I# n--  #-}--dph_mult :: Int -> Int -> Int-{-# INLINE_BACKEND dph_mult #-}-dph_mult x y = x Prelude.* y---tagZeroes :: Array Int -> Array Tag-{-# INLINE CONLIKE PHASE_BACKEND tagZeroes #-}-tagZeroes xs = map (\x -> fromBool (x==0)) xs------------------------------------------------------------------------------------- Currently disabled rules----------------------------------------------------------------------------------{- RULES--"packByTag/combine2ByTag" forall tags1 xs ys tags2 n.-  packByTag (combine2ByTag tags1 xs ys) tags2 n-    = combine2ByTag (packByTag tags1 tags2 n)-                    (packByTag xs (packByTag tags2 tags1 0) n)-                    (packByTag ys (packByTag tags2 tags1 1) n)--  -}+import Data.Array.Parallel.Base (Tag, tagToInt, fromBool)+import qualified GHC.Base+import Prelude                  ((.), ($), Num(..), Eq(..), seq, snd)+import qualified Prelude++instance Elt Int+instance Elt Word8+instance Elt Bool+instance Elt Float+instance Elt Double+instance (Elt a, Elt b) => Elt (a, b)++instance Elts Int+instance Elts Word8+instance Elts Float+instance Elts Double++infixl 9 `index`+infixr 5 +:+++-- TRAGIC HACKS ===============================================================+-- These hacky rules solve the replicate problem for the SMVM benchmark, +-- with dph-lifted-copy but are very fragile and ad-hoc.+--+-- Programs written with the new dph-lifted-vseg library don't need rules like+-- this, so we should dump them at some stage.+{-# RULES++"map/zipWith (+)/enumFromStepLen" forall m n is.+  map (dph_mod_index m) (zipWith GHC.Base.plusInt (enumFromStepLen 0 m n) is)+    = map (dph_mod_index m) is++"map dph_mod_index/enumFromStepLenEach" forall k l is n1 n2.+  map (dph_mod_index k)+      (enumFromStepLenEach l is (replicate n1 (GHC.Base.I# 1#)) (replicate n2 k))+    = enumFromStepLenEach l (map (dph_mod_index k) is)+                            (replicate n1 (GHC.Base.I# 1#))+                            (replicate n2 k)++"map dph_mod_index/replicate_s" forall k segd xs.+  map (dph_mod_index k) (replicate_s segd xs)+    = replicate_s segd (map (dph_mod_index k) xs)++"map dph_mod_index/enumFromStepLen" forall k# i n.+  map (dph_mod_index (GHC.Base.I# k#)) (enumFromStepLen i (GHC.Base.I# k#) n)+    = replicate n i++"enumFromStepLenEach/replicate x 3" forall k m n1 n2 n3.+  enumFromStepLenEach m (replicate n1 (GHC.Base.I# 0#))+                        (replicate n2 (GHC.Base.I# 1#))+                        (replicate n3 k)+    = generate_cheap m (dph_mod_index k)++"bpermute/generate_cheap" forall n f xs.+  bpermute (generate_cheap n f) xs+    = map f xs+ #-}+-- ============================================================================+++-- Constructors ===============================================================+-- | O(1). Construct an array with no elements.+empty :: Elt a => Array a+{-# INLINE_BACKEND empty #-}+++-- Generate ---------------------------+-- | Generate a new array given its length and a function to compute each element.+generate :: Elt a => Int -> (Int -> a) -> Array a+generate n f = map f (enumFromTo 0 (n-1))+{-# INLINE_BACKEND generate #-}+++generate_cheap :: Elt a => Int -> (Int -> a) -> Array a+generate_cheap n f = map f (enumFromTo 0 (n-1))+{-# INLINE_BACKEND generate_cheap #-}+++-- Replicate --------------------------+-- | O(length result). +--   Construct a new array by replicating a single element the given+--   number of times.+replicate :: Elt a => Int -> a -> Array a+{-# INLINE CONLIKE PHASE_BACKEND replicate #-}++{-# RULES++"seq/replicate" forall n x y.+  seq (replicate n x) y = n `seq` x `seq` y++ #-}+++-- | O(length result). Segmented replicate.+--+--   Elements of the array are replicated according to the lengths of the +--   segments defined by the `Segd`.+replicate_s :: Elt a => Segd -> Array a -> Array a+{-# INLINE CONLIKE PHASE_BACKEND replicate_s #-}+++-- | O(length result). Regular segmented replicate.+-- +--   Like `replicate_s`, but all segments are assumed to have the given length.+replicate_rs :: Elt a => Int -> Array a -> Array a+{-# INLINE CONLIKE PHASE_BACKEND replicate_rs #-}+++{-# RULES++"replicate_s/replicate" +  forall segd k x+  . replicate_s segd (replicate k x) +  = replicate (elementsSegd segd) x++"replicate_s->replicate_rs" +  forall n m idxs nm xs+  . replicate_s (mkSegd (replicate n m) idxs nm) xs+  = replicate_rs m xs++"replicate_rs/replicate" +  forall m n x+  . replicate_rs m (replicate n x) = replicate (m*n) x++ #-}+++-- Repeat -----------------------------+-- | O(length result). Construct an array by copying a portion of another array.+repeat  :: Elt a +        => Int          -- ^ Number of times to repeat the source.+        -> Int          -- ^ Length of source (can be less than the provided array).+        -> Array a      -- ^ Array elements to repeat.+        -> Array a+{-# INLINE_BACKEND repeat #-}+++{-# RULES++"repeat/enumFromStepLen[Int]" forall i j k n len.+  repeat n len (enumFromStepLen i j k)+    = generate_cheap len (\m -> i + ((m `Prelude.rem` k) * j))++  #-}+++-- Append -----------------------------+-- | O(length result). Append two arrays.+(+:+) :: Elt a => Array a -> Array a -> Array a+{-# INLINE_BACKEND (+:+) #-}+++-- | O(length result). Segmented append.+append_s +        :: Elt a+        => Segd         -- ^ Segment descriptor of result aarray.+        -> Segd         -- ^ Segment descriptor of first array.+        -> Array a      -- ^ Data of first array.+        -> Segd         -- ^ Segment descriptor of second array.+        -> Array a      -- ^ Data of second array.+        -> Array a+{-# INLINE_BACKEND append_s #-}+++{-# RULES++"append_s->interleave" forall n k idxs1 idxs2 idxs3 m1 m2 m3 xs ys.+  append_s (mkSegd (replicate n k) idxs1 m1)+           (mkSegd (replicate n (GHC.Base.I# 1#)) idxs2 m2) xs+           (mkSegd (replicate n (GHC.Base.I# 1#)) idxs3 m3) ys+    = interleave xs ys++  #-}+++-- Indexed ----------------------------+-- | O(length result). Tag each element of an array with its index.+--+--   @indexed [42, 93, 13] = [(0, 42), (1, 93), (2, 13)]@ +indexed :: Elt a => Array a -> Array (Int, a)+{-# INLINE_BACKEND indexed #-}+++-- Indices ----------------------------+-- | O(length result). Segmented indices. +--+--   Construct an array containing containing the segments defined by the+--   given `Segd`. +--+--   Each segment will contain the elements @[0..len-1]@ where @len@ is the+--   length of that segment.+indices_s :: Segd -> Array Int+{-# INLINE_BACKEND indices_s #-}+++-- Enumerations -----------------------+enumFromTo :: Int -> Int -> Array Int+{-# INLINE_BACKEND enumFromTo #-}++enumFromThenTo :: Int -> Int -> Int -> Array Int+{-# INLINE_BACKEND enumFromThenTo #-}++enumFromStepLen :: Int -> Int -> Int -> Array Int+{-# INLINE_BACKEND enumFromStepLen #-}++enumFromStepLenEach :: Int -> Array Int -> Array Int -> Array Int -> Array Int+{-# INLINE_BACKEND enumFromStepLenEach #-}+++-- Projections ================================================================+-- | O(1). Yield the number of elements in an array.+length :: Elt a => Array a -> Int+{-# INLINE_BACKEND length #-}+++-- | O(1). Retrieve a numbered element from an array.+-- +--   The first argument gives a source-code location for out-of-bounds errors.+index :: Elt a => Prelude.String -> Array a -> Int -> a+{-# INLINE_BACKEND index #-}+++-- | O(length result). Scattered indexing from a single `Array`.+-- +--   This is an alias for `bpermute`.+indexs  :: Elt a+        => Array a+        -> Array Int+        -> Array a+{-# INLINE_BACKEND indexs #-}+++-- | O(length result). Scattered indexing through a `VSegd`.+--+--   The index array contains pairs of segment id and the index within that +--   segment. +-- +--   We use the `VSegd` to map the pairs to 2D indices within the `Arrays`, +--   and return an array of the resulting elements.+indexs_avs+        :: (Elt a, Elts a)+        => Arrays a             -- ^ Irregular 2D array of elements.+        -> VSegd                -- ^ Maps (segment id, segment index) pairs +                                --   to 2D indices in the `Arrays`+        -> Array (Int, Int)     -- ^ Pairs of (segment id, segment index).+        -> Array a+{-# INLINE_BACKEND indexs_avs #-}+++-- | O(length result). Extract a subrange of elements from an array.+--  +--   @extract [23, 42, 93, 50, 27] 1 3  = [42, 93, 50]@+extract :: Elt a+        => Array a      -- ^ Source array.+        -> Int          -- ^ Starting index in source array.+        -> Int          -- ^ Length of result array.+        -> Array a+{-# INLINE_BACKEND extract #-}+++-- | O(length result). Extract segments defined by a `SSegd` from a vector of arrays.+--+--   NOTE: This is a transitory interface, and will be removed in future versions.+--         Use `extracts_ass` instead.+extracts_nss+        :: Elt a+        => SSegd+        -> VV.Vector (Array a)+        -> Array a+{-# INLINE_BACKEND extracts_nss #-}+++-- | O(length result). Extract segments defined by a `SSegd`.+--+--   Extract all the segments defined by the `SSegd` from the `Arrays`,+--   returning them concatenated in a fresh `Array`.+extracts_ass+        :: (Elt a, Elts a)+        => SSegd        -- ^ `SSegd` defining the slices to extract.+        -> Arrays a     -- ^ Source arrays.+        -> Array a+{-# INLINE_BACKEND extracts_ass #-}+++-- | O(length result). Extract segments defined by a `VSegd`.+--+--   Extract all the segments defined by the `VSegd` from the `Arrays`,+--   returning them concatenated in a fresh `Array`.+extracts_avs+        :: (Elt a, Elts a)+        => VSegd        -- ^ `VSegd` defining the slices to extract.+        -> Arrays a     -- ^ Source arrays.+        -> Array a+{-# INLINE_BACKEND extracts_avs #-}+++-- | O(length result). Drop elements from the front of an array, +--         returning the latter portion.+drop :: Elt a => Int -> Array a -> Array a+{-# INLINE_BACKEND drop #-}++{-# RULES ++"indexs_avs/singletons/replicatedVSegd"+  forall arr len reps srcixs+  . indexs_avs (singletons arr) (replicatedVSegd len reps) srcixs+  = indexs arr (map snd srcixs)++ #-}+++-- Update =====================================================================+-- | O(length result). +--   Copy the source array while replacing some elements by new ones in the result.+update  :: Elt a +        => Array a              -- ^ Source array.+        -> Array (Int, a)       -- ^ Index and value of new elements.+        -> Array a+{-# INLINE_BACKEND update #-}+++-- Permutation ================================================================+-- | O(length result). Forwards permutation of array elements.+--+permute :: Elt a +        => Array a      -- ^ Source array.+        -> Array Int    -- ^ Indices in the destination to copy elements to.+        -> Array a+{-# INLINE_BACKEND permute #-}+++-- | O(length result). Backwards permutation of array elements.+--+--   @bpermute [50, 60, 20, 30] [0, 3, 2] = [50, 30, 20]@+bpermute +        :: Elt a +        => Array a      -- ^ Source array.+        -> Array Int    -- ^ Indices in the source to copy elements from.+        -> Array a+{-# INLINE_BACKEND bpermute #-}+++-- | Combination of map and bpermute.+--+--   The advantage of using this combined version is that we don't need+--   to apply the parameter function to source elements that don't appear+--   in the result.+mbpermute :: (Elt a, Elt b) => (a->b) -> Array a -> Array Int -> Array b+{-# INLINE_BACKEND mbpermute #-}+++-- | Default backwards permutation.+--+--   The values of the index-value pairs are written into the position in the+--   result array that is indicated by the corresponding index.+--+--   All positions not covered by the index-value pairs will have the value+--   determined by the initialiser function for that index position.+--+bpermuteDft:: Elt e => Int -> (Int -> e) -> Array (Int, e) -> Array e+{-# INLINE_BACKEND bpermuteDft #-}++{-# RULES+        +"bpermute/repeat" forall n len xs is.+  bpermute (repeat n len xs) is+    = len `Prelude.seq` bpermute xs (map (dph_mod_index len) is)++"bpermute/bpermute" forall xs is js.+  bpermute (bpermute xs is) js = bpermute xs (bpermute is js)++  #-}+++-- Zipping and Unzipping ======================================================+-- | O(1). Zip two arrays into an array of pairs.+--   If one array is short, excess elements of the longer array are discarded.+zip :: (Elt a, Elt b) => Array a -> Array b -> Array (a, b)+{-# INLINE CONLIKE PHASE_BACKEND zip #-}+++-- | O(1). Zip three arrays into an array of triples.+--   If one array is short, excess elements of the longer arrays are discarded.+zip3 :: (Elt a, Elt b, Elt c) => Array a -> Array b -> Array c -> Array (a, b, c)+{-# INLINE CONLIKE PHASE_BACKEND zip3 #-}+++-- | O(1). Unzip an array of pairs into a pair of arrays.+unzip :: (Elt a, Elt b) => Array (a, b) -> (Array a, Array b)+{-# INLINE_BACKEND unzip #-}+++-- | O(1). Unzip an array of triples into a triple of arrays.+unzip3 :: (Elt a, Elt b, Elt c) => Array (a, b, c) -> (Array a, Array b, Array c)+{-# INLINE_BACKEND unzip3 #-}+++-- | O(1). Take the first elements of an array of pairs.+fsts  :: (Elt a, Elt b) => Array (a, b) -> Array a+{-# INLINE_BACKEND fsts #-}+++-- | O(1). Take the second elements of an array of pairs.+snds :: (Elt a, Elt b) => Array (a, b) -> Array b+{-# INLINE_BACKEND snds #-}+++-- Maps and zipWith ===========================================================+-- | Apply a worker function to each element of an array, yielding a new array.+map     :: (Elt a, Elt b)+        => (a -> b) -> Array a -> Array b+{-# INLINE_BACKEND map #-}+++-- | Apply a worker function to correponding elements of two arrays.+zipWith :: (Elt a, Elt b, Elt c)+        => (a -> b -> c) -> Array a -> Array b -> Array c+{-# INLINE_BACKEND zipWith #-}+++-- | Apply a worker function to corresponding elements of three arrays.+zipWith3 :: (Elt a, Elt b, Elt c, Elt d)+          => (a -> b -> c -> d) -> Array a -> Array b -> Array c -> Array d+zipWith3 f xs ys zs+        = zipWith (\(x, y) z -> f x y z)+                  (zip xs ys)+                  zs+{-# INLINE zipWith3 #-}+++-- | Apply a worker function to corresponding elements of four arrays.+zipWith4 :: (Elt a, Elt b, Elt c, Elt d, Elt e)+         => (a -> b -> c -> d -> e)+         -> Array a -> Array b -> Array c -> Array d -> Array e+zipWith4 f as bs cs ds+         = zipWith (\(a, b) (c, d) -> f a b c d)+                   (zip as bs)+                   (zip cs ds)+{-# INLINE zipWith4 #-}+++{-# RULES+        +"zipWith/replicate" forall f m n x y.+  zipWith f (replicate m x) (replicate n y) = replicate m (f x y)++"zipWith/plusInt0_1" forall n xs.+  zipWith GHC.Base.plusInt (replicate n (GHC.Base.I# 0#)) xs = xs++"zipWith/plusInt0_2" forall n xs.+  zipWith GHC.Base.plusInt xs (replicate n (GHC.Base.I# 0#)) = xs++"zipWith(plusInt)/enumFromStepLen" forall i1 k1 n1 i2 k2 n2.+  zipWith GHC.Base.plusInt (enumFromStepLen i1 k1 n1)+                           (enumFromStepLen i2 k2 n2)+    = enumFromStepLen (i1+i2) (k1+k2) n1+  #-}+++-- Folds and Scans ============================================================++-- Scans ------------------------------+-- | Similar to `foldl` but return an array of the intermediate states, including+--   the final state that is computed by `foldl`.+scan :: Elt a => (a -> a -> a) -> a -> Array a -> Array a+{-# INLINE_BACKEND scan #-}+++-- Fold -------------------------------+-- | Undirected fold over an array.+--+--   * The worker function must be associative.+--+--   * The provided starting element must be neutral with respect to the worker.+--     For example 0 is neutral wrt (+) and 1 is neutral wrt (*).+--+fold :: Elt a => (a -> a -> a) -> a -> Array a -> a+{-# INLINE_BACKEND fold #-}+++-- | Undirected segmented fold. +-- +--   All segments are folded individually, and the result contains one+--   element for each segment. +--+--   Same preconditions as `fold`.+fold_s :: Elt a => (a -> a -> a) -> a -> Segd -> Array a -> Array a+{-# INLINE_BACKEND fold_s #-}+++-- | Undirected scattered segmented fold.+--+--   Like `fold_s`, but the segments can be scattered through an `Arrays`. +--+--   Same preconditions as `fold`.+fold_ss :: (Elts a, Elt a)+        => (a -> a -> a) -> a -> SSegd -> Arrays a -> Array a+{-# INLINE_BACKEND fold_ss #-}+++-- | Regular segmented fold. +--+--   All segements have the given length.+--+--   Same preconditions as `fold`.+fold_r :: Elt a => (a -> a -> a) -> a -> Int -> Array a -> Array a+{-# INLINE_BACKEND fold_r #-}+++-- | Undirected fold over virtual segments.+--+--   The physical segments defined by the `VSegd` are folded individually, +--   and these results are replicated according to the virtual segment+--   id table of the `VSegd`. The result contains as many elements as there+--   virtual segments.+--+--   Same preconditions as `fold`.+fold_vs :: (Elts a, Elt a)+         => (a -> a -> a) -> a -> VSegd -> Arrays a -> Array a+fold_vs f x vsegd arrs+ = let  -- Fold each physical segment individually+        psegResults     = fold_ss f x (takeSSegdOfVSegd vsegd) arrs++        -- Replicate the physical results accorsing to the vsegids+    in  bpermute psegResults (takeVSegidsOfVSegd vsegd)+{-# INLINE_BACKEND fold_vs #-}+++-- When we know the array data is manifest and/or contiguous then we want +-- to avoid using the extended information in the VSegd and SSegd types.+{-# RULES ++"fold_ss/promoteSegdToSSegd"  forall f x segd arr.+ fold_ss f x (promoteSegdToSSegd  segd) (singletons arr) +    = fold_s f x segd arr++"fold_vs/promoteSegdToVSegd"  forall f x segd arr.+ fold_vs f x (promoteSegdToVSegd  segd) (singletons arr)+    = fold_s f x segd arr++"fold_vs/promoteSSegdToVSegd" forall f x ssegd arrs.+ fold_vs f x (promoteSSegdToVSegd ssegd) arrs +    = fold_ss f x ssegd arrs++ #-}+++-- Fold1 -------------------------------+-- | Undirected fold, using the first element to initialise the state.+--+--   * The worker function must be associative.+--+--   * The provided starting element must be neutral with respect to the worker.+--     For example 0 is neutral wrt (+) and 1 is neutral wrt (*).+--+--   * If the array contains no elements then you'll get a bounds check `error`.+--+fold1 :: Elt a => (a -> a -> a) -> Array a -> a+{-# INLINE_BACKEND fold1 #-}+++-- | Like `fold_s`, but using the first element of each segment to initialise+--   the state of that segment.+--+--   Same preconditions as `fold1`.+fold1_s :: Elt a => (a -> a -> a) -> Segd -> Array a -> Array a+{-# INLINE_BACKEND fold1_s #-}+++-- | Like `fold_ss`, but using the first element of each segment to intialise +--   the state of that segment.+--+--   Same preconditions as `fold1`.+fold1_ss :: (Elts a, Elt a) +         => (a -> a -> a) -> SSegd -> Arrays a -> Array a+{-# INLINE_BACKEND fold1_ss #-}+++-- | Like `fold_vs`, but using the first element of each segment to initialise +--   the state of that segment.+--+--   Same preconditions as `fold1`.+fold1_vs :: (Elts a, Elt a)+         => (a -> a -> a)  -> VSegd -> Arrays a -> Array a+fold1_vs f vsegd arrs+ = let  -- Fold each physical segment individually+        psegResults     = fold1_ss f (takeSSegdOfVSegd vsegd) arrs++        -- Replicate the physical results accorsing to the vsegids+    in  bpermute psegResults (takeVSegidsOfVSegd vsegd)+{-# INLINE_BACKEND fold1_vs #-}+++-- When we know the array data is manifest and/or contiguous then we want +-- to avoid using the extended information in the VSegd and SSegd types.+{-# RULES ++"fold1_ss/promoteSegdToSSegd"  forall f segd arr.+ fold1_ss f (promoteSegdToSSegd  segd)  (singletons arr) +    = fold1_s f segd arr++"fold1_vs/promoteSegdToVSegd"  forall f segd arr.+ fold1_vs f (promoteSegdToVSegd  segd)  (singletons arr)+    = fold1_s f segd arr++"fold1_vs/promoteSSegdToVSegd" forall f ssegd arrs.+ fold1_vs f (promoteSSegdToVSegd ssegd) arrs +    = fold1_ss f ssegd arrs++ #-}+++-- Sums -------------------------------+-- | Same as @fold (+) 0@+sum :: (Num a, Elt a) => Array a -> a+{-# INLINE_BACKEND sum #-}++-- | Same as @fold_s (+) 0@+sum_s :: (Num a, Elt a) => Segd -> Array a -> Array a+sum_s = fold_s (Prelude.+) 0+{-# INLINE sum_s #-}++-- | Same as @fold_ss (+) 0@+sum_ss :: (Num a, Elts a, Elt a) +       => SSegd -> Arrays a -> Array a+sum_ss = fold_ss (Prelude.+) 0+{-# INLINE sum_ss #-}++-- | Same as @fold_r (+) 0@+sum_r :: (Num a, Elt a) => Int -> Array a -> Array a+{-# INLINE_BACKEND sum_r #-}+++-- Count ------------------------------+-- | Count the number of elements in array that are equal to the given value.+count :: (Elt a, Eq a) => Array a -> a -> Int+count xs !x = sum (map (tagToInt . fromBool . (==) x) xs)+{-# INLINE_BACKEND count #-}+++-- | Segmented count.+count_s :: (Elt a, Eq a) => Segd -> Array a -> a -> Array Int+count_s segd xs !x+        = sum_s segd (map (tagToInt . fromBool . (==) x) xs)+{-# INLINE_BACKEND count_s #-}+++-- | Scattered segmented count.+--+--   NOTE: This is a transitory interface, and will be removed in future versions.+---  TODO: Make this take an `Arrays` instead of a Vector.+count_ss :: (Elt a, Eq a) => SSegd -> VV.Vector (Array a) -> a -> Array Int+{-# INLINE_BACKEND count_ss #-}+count_ss ssegd xs !x+        = sum_ss ssegd (fromVectors $ VV.map (map (tagToInt . fromBool . (==) x)) xs)+++-- And --------------------------------+-- | O(length source). Compute the conjunction of all elements in a boolean array.+and :: Array Bool -> Bool+{-# INLINE_BACKEND and #-}++{-# RULES++"seq/sum" forall xs e.+  seq (sum xs) e = seq xs e++"seq/scan<Int> (+)" forall i xs e.+  seq (scan GHC.Base.plusInt i xs) e = i `seq` xs `seq` e++"scan/replicate" forall z n x.+  scan GHC.Base.plusInt z (replicate n x)+    = enumFromStepLen z x n++"sum/replicate_rs" forall n xs.+  sum (replicate_rs n xs) = sum xs * n++"count/replicate_s" forall segd xs tag.+  count (replicate_s segd xs) tag+    = sum (packByTag (lengthsSegd segd) xs tag)++"fold_s/replicate1" forall f z n idxs n' xs.+  fold_s f z (mkSegd (replicate n (GHC.Base.I# 1#)) idxs n') xs = xs++"fold_s/replicate" forall f z m n idxs mn xs.+  fold_s f z (mkSegd (replicate m n) idxs mn) xs+    = fold_r f z n xs++"count/seq" forall xs x y. seq (count xs x) y = seq xs (seq x y)++  #-}+++-- Pack and Filter ============================================================+-- | O(length result).+--   Extract elements of an array where the associated flag is true.+pack :: Elt a => Array a -> Array Bool -> Array a+{-# INLINE_BACKEND pack #-}+++-- | O(length result).+--   Select the elements of an array that have a corresponding tag.+--   +--   @packByTag [12, 24, 42, 93] [1, 0, 0, 1] 0 = [24, 42]@+--+packByTag +        :: Elt a+        => Array a      -- ^ data values+        -> Array Tag    -- ^ tag values+        -> Tag          -- ^ the tag of values to select+        -> Array a      -- ^ data values that had that tag++packByTag xs tags !tag+        = fsts (filter (\p -> Prelude.snd p == tag) (zip xs tags))+{-# INLINE_BACKEND packByTag #-}+++-- | Extract the elements from an array that match the given predicate.+filter :: Elt a => (a -> Bool) -> Array a -> Array a+{-# INLINE_BACKEND filter #-}++-- | Compute an array of flags indicating which elements match a given value.+--+--   @pick [4, 5, 3, 6, 5, 2, 5] 5 = [F, T, F, F, T, F, T]@+pick :: (Elt a, Eq a) => Array a -> a -> Array Bool+pick xs !x = map (x ==) xs+{-# INLINE pick #-}+++{-# RULES++"tagZeroes" UNTIL_PHASE_BACKEND forall xs n.+  map fromBool (zipWith GHC.Base.eqInt xs (replicate n (GHC.Base.I# 0#)))+    = tagZeroes xs++"replicate_s/tagZeroes" forall lens idxs n.+  replicate_s (mkSegd lens idxs n) (tagZeroes lens)+    = replicate n 0++"packByTag/replicate" forall xs n t u.+  packByTag xs (replicate n t) u = if t == u then xs else empty++"packByTag/bpermute" forall xs is tags n.+  packByTag (bpermute xs is) tags n+    = bpermute xs (packByTag is tags n)++  #-}+++-- Combine and Interleave =====================================================+-- | Combine two arrays, +--    using a flags array to tell us where to get each element from.+--+--   @combine [T, F, F, T, T, F] [1, 2, 3] [4, 5, 6] = [1, 4, 5, 2, 3, 6]@+combine :: Elt a => Array Bool -> Array a -> Array a -> Array a+{-# INLINE_BACKEND combine #-}+++-- | Like `combine`, but use a precomputed selector to speed up the process.+-- +--   See the description of `mkSel2` for how this works.+--+combine2 :: Elt a => Array Tag -> SelRep2 -> Array a -> Array a -> Array a+{-# INLINE_BACKEND combine2 #-}+++-- | Interleave the elements of two arrays.+-- +--    @interleave [1, 2, 3] [4, 5, 6] = [1, 4, 2, 5, 3, 6]@+interleave :: Elt a => Array a -> Array a -> Array a+{-# INLINE_BACKEND interleave #-}+++-- Selectors ==================================================================+-- | O(1). Construct a selector.+--+--   A selector is a description of how to perform a `combine` operation.+--+--   Suppose we are evaluating the following expression:+--+--    @combine [F,F,T,F,T,T] [1,2,3] [4,5,6] = [4,5,1,6,2,3]@+--+--   This is difficult to parallelise. For each element in the result, the+--   source array we get this element from depends on the tag values associated+--   with all previous elements.+--+--   However, if we going to apply `combine` several times with the same flags array, +--   we can precompute a selector that tells us where to get each element. +--   The selector contains the original flags, as well as the source index telling+--   us where to get each element for the result array.+--+--   For example:+--+--   @tagsToIndices2 [F,F,T,F,T,T]   -- tags+--             = [0,1,0,2,1,2]   -- indices+--   @+--+--    This says get the first element from index 0 in the second array, +--     then from index 1 in the second array,+--     then index 0 in the first array ...+--  +--    The selector then consists of both the @tag@ and @indices@ arrays.+--+mkSel2  :: Array Tag            -- ^ Tags array.+        -> Array Int            -- ^ Indices array.+        -> Int                  -- ^ Number of elements taken from first source array.+        -> Int                  -- ^ Number of elements taken from second source array.+        -> SelRep2              -- ^ Parallel selector representation.+        -> Sel2+{-# INLINE CONLIKE PHASE_BACKEND mkSel2 #-}+++-- | O(1). Yield the tags array of a selector.+tagsSel2 :: Sel2 -> Array Tag+{-# INLINE_BACKEND tagsSel2 #-}+++-- | O(1). Yield the indices array of a selector.+indicesSel2 :: Sel2 -> Array Int+{-# INLINE_BACKEND indicesSel2 #-}+++-- | O(1). Yield the number of elements that will be taken from the first array.+elementsSel2_0 :: Sel2 -> Int+{-# INLINE_BACKEND elementsSel2_0 #-}+++-- | O(1). Yield the number of elements that will be taken from the second array.+elementsSel2_1 :: Sel2 -> Int+{-# INLINE_BACKEND elementsSel2_1 #-}+++-- | O(1). Yield the parallel representation of a selector.+repSel2 :: Sel2 -> SelRep2+{-# INLINE_BACKEND repSel2 #-}+++-- Selector Representations ===================================================+-- | O(n). Construct a parallel selector representation.+--+--   A `SelRep2` describes how to distribute the two data vectors+--   corresponding to a `Sel2` across several PEs.+--+--   Suppose we want to perform the following `combine` operation:+--+-- @+-- combine [F,F,T,T,F,T,F,F,T] [A0,A1,A2,A3,A4] [B0,B1,B2,B3] +--   = [A0,A1,B0,B1,A2,B2,A3,A4,B3]+-- @+--+--   The first array is the flags array, that says which of the data arrays to+--   get each successive element from. As `combine` is difficult to compute+--   in parallel, if we are going to perform several combines with the same+--   flags array, we can precompute a selector that tells us where to get each+--   element. The selector contains the original flags, as well as the source+--   index telling us where to get each element for the result array.+-- +-- @+-- flags:   [F,F,T,T,F,T,F,F,T]+-- indices: [0,1,0,1,2,2,3,4,3]+-- @+--+--  Suppose we want to distribute the combine operation across 3 PEs. It's+--  easy to split the selector like so:+--+-- @+--            PE0                PE1               PE2+-- flags:   [F,F,T]            [T,F,T]           [F,F,T] +-- indices: [0,1,0]            [1,2,2]           [3,4,3]+-- @+--+--  We now need to split the two data arrays. Each PE needs slices of the data+--  arrays that correspond to the parts of the selector that were given to it.+--  For the current example we get:+--+-- @+--            PE0                PE1               PE2+-- data_A:   [A0,A1]            [A2]              [A3,A4]+-- data_B:   [B0]               [B1,B2]           [B3]+-- @+--+--  The `SelRep2` contains the starting index and length of each of of these+--  slices:+--+-- @+--            PE0                PE1               PE2+--      ((0, 0), (2, 1))   ((2, 1), (1, 2))  ((3, 3), (2, 1))+--       indices   lens      indices  lens    indices  lens+-- @++mkSelRep2 :: Array Tag -> SelRep2+{-# INLINE CONLIKE PHASE_BACKEND mkSelRep2 #-}+++-- | O(1). Take the `indices` field from a `SelRep2`.+indicesSelRep2 :: Array Tag -> SelRep2 -> Array Int+{-# INLINE_BACKEND indicesSelRep2 #-}+++-- | O(1). Yield the number of elements to take from the first array.+elementsSelRep2_0 :: Array Tag -> SelRep2 -> Int+{-# INLINE_BACKEND elementsSelRep2_0 #-}+++-- | O(1). Yield the number of elements to take from the second array.+elementsSelRep2_1 :: Array Tag -> SelRep2 -> Int+{-# INLINE_BACKEND elementsSelRep2_1 #-}+++-- | O(n). Compute a selector from a tags array.+tagsToSel2 :: Array Tag -> Sel2+tagsToSel2 tags + = let rep = mkSelRep2 tags+   in  mkSel2 tags (indicesSelRep2    tags rep)+                   (elementsSelRep2_0 tags rep)+                   (elementsSelRep2_1 tags rep)+                   rep+{-# INLINE tagsToSel2 #-}+++{-# RULES++"tagsSel2/mkSel2"+  forall ts is n0 n1 r. tagsSel2 (mkSel2 ts is n0 n1 r) = ts++"indicesSel2/mkSel2"+  forall ts is n0 n1 r. indicesSel2 (mkSel2 ts is n0 n1 r) = is++"elementsSel2_0/mkSel2"+  forall ts is n0 n1 r. elementsSel2_0 (mkSel2 ts is n0 n1 r) = n0++"elementsSel2_1/mkSel2"+  forall ts is n0 n1 r. elementsSel2_1 (mkSel2 ts is n0 n1 r) = n1++"repSel2/mkSel2"+  forall ts is n0 n1 r. repSel2 (mkSel2 ts is n0 n1 r) = r++  #-}+++-- Segment Descriptors ========================================================+-- | O(max(segs, threads) . log segs). Construct a segment descriptor.+--+--   A segment desciptor defines an irregular 2D array based on a flat, 1D array+--   of elements. The defined array is a nested array of segments, where every+--   segment covers some of the elements from the flat array. +--+--   * The starting indices must be equal to @init (scanl (+) 0 lengths)@+--+--   * If you don't want to cover all the elements from the flat arrary then+--     use a `SSegd` instead.+--+--  Example:+--+--   @+--   flat array data: [1 2 3 4 5 6 7 8]+--     (segmentation)  --- ----- - ---+--     segd  lengths: [2, 3, 1, 2]+--           indices: [0, 2, 5, 6]+--          elements: 8 +--   @+---+--   * This ensures that the indices are monotonically increasing,+--     and all elements from the flat array are covered by some segment.+-- +--   * We need this because in the implementation of `lengthsToSegd`, we binary+--     search the indices to determine which segment an element of the +--     flat array belongs to. It also means that the segment indices can always+--     be reconstructed from the segment lengths by `lengthsToSegd`.+--+--+mkSegd  :: Array Int    -- ^ (lengths) Segment lengths.+        -> Array Int    -- ^ (indices) Segment indices.+        -> Int          -- ^ Total number of elements.+        -> Segd+{-# INLINE CONLIKE PHASE_BACKEND mkSegd #-}+++-- | Check whether a `Segd` is well formed.+validSegd :: Segd -> Bool+{-# NOINLINE validSegd #-}+--  NOINLINE because it's only used during debugging.+++-- | O(1). Construct an empty `Segd`.+emptySegd :: Segd+{-# INLINE_BACKEND emptySegd #-}+++-- | O(1). Construct a `Segd` containing a single segment of the given length.+singletonSegd :: Int -> Segd+{-# INLINE_BACKEND singletonSegd #-}+++-- | O(max(segs, threads) . log segs). +--   Construct a `Segd` from an array of segment lengths.+lengthsToSegd :: Array Int -> Segd+lengthsToSegd ns = mkSegd ns (scan (+) 0 ns) (sum ns)+{-# INLINE_BACKEND lengthsToSegd #-}+++-- | O(1). Yield the length of a `Segd`.+lengthSegd :: Segd -> Int+{-# INLINE_BACKEND lengthSegd #-}+++-- | O(1). Yield the segment lengths of a `Segd`.+lengthsSegd :: Segd -> Array Int+{-# INLINE_BACKEND lengthsSegd #-}+++-- | O(1). Yield the segment starting indices of a `Segd`.+indicesSegd :: Segd -> Array Int+{-# INLINE_BACKEND indicesSegd #-}+++-- | O(1). Yield the total number of elements defined by a `Segd`.+elementsSegd :: Segd -> Int+{-# INLINE_BACKEND elementsSegd #-}++-- | O(max(segs, threads) . log segs). +--   Add the lengths of corresponding segments in two descriptors.+--+--   @plusSegd [lens: 2 3 1] [lens: 3 1 1] = [lens: 5 4 2]@+--    +plusSegd :: Segd -> Segd -> Segd+plusSegd segd1 segd2+  = mkSegd (zipWith (+) (lengthsSegd segd1) (lengthsSegd segd2))+           (zipWith (+) (indicesSegd segd1) (indicesSegd segd2))+           (elementsSegd segd1 `dph_plus` elementsSegd segd2)+{-# INLINE_BACKEND plusSegd #-}+++{-# RULES++"lengthsSegd/mkSegd" forall lens idxs n.+  lengthsSegd (mkSegd lens idxs n) = lens++"indicesSegd/mkSegd" forall lens idxs n.+  indicesSegd (mkSegd lens idxs n) = idxs++"elementsSegd/mkSegd" forall lens idxs n.+  elementsSegd (mkSegd lens idxs n) = n++"seq/elementsSegd" forall segd e.+  seq (elementsSegd segd) e = seq segd e++"seq/mkSegd" forall lens idxs n e.+  seq (mkSegd lens idxs n) e = lens `seq` idxs `seq` n `seq` e++ #-}++-- Scattered Segment Descriptors ==============================================+-- | Construct a Scattered Segment Descriptor.+--+--   A `SSegd` is an extension of a `Segd` that that allows the segments to be+--   scattered through multiple flat arrays.+--+--   Each segment is associated with a source id that indicates what +--   flat array it is in, along with the starting index in that flat array.+--+--   * The segments need not cover the entire flat array.+--+--   * Different segments may point to the same elements.+--+mkSSegd :: Array Int    -- ^ (starts)  Starting index of each segment within its flat array.+        -> Array Int    -- ^ (sources) Source id of flat array to get each segment from. +        -> Segd         -- ^ Plain segment descriptor giving the lengths+                        --   of the segments.+        -> SSegd+{-# INLINE CONLIKE PHASE_BACKEND mkSSegd #-}+++-- | Check whether a `Segd` is well formed.+validSSegd :: SSegd -> Bool+{-# NOINLINE validSSegd #-}+--  NOINLINE because it's only used during debugging.+++-- | O(1). Construct an empty `SSegd`.+emptySSegd :: SSegd+{-# INLINE_BACKEND emptySSegd #-}+++-- | O(1). Construct a `Segd` containing a single segment of the given length.+singletonSSegd :: Int -> SSegd+{-# INLINE_BACKEND singletonSSegd #-}+++-- | O(segs). Promote a `Segd` to a `SSegd`, +--   assuming all segments are contiguous and come from a single array.+promoteSegdToSSegd :: Segd -> SSegd+{-# INLINE_BACKEND promoteSegdToSSegd #-}+++-- | O(1). True when a `SSegd` has been constructed by promoting a `SSegd`.+--+--   In this case all the data elements are in one contiguous flat+--   array, and consumers can avoid looking at the real starts and+--   sources fields.+isContiguousSSegd :: SSegd -> Bool+{-# INLINE_BACKEND isContiguousSSegd #-}+++-- | O(1). Yield the length of a `SSegd`.+lengthOfSSegd :: SSegd -> Int+{-# INLINE_BACKEND lengthOfSSegd #-}+++-- | O(1). Yield the segment lengths of a `SSegd`.+lengthsOfSSegd :: SSegd -> Array Int+{-# INLINE_BACKEND lengthsOfSSegd #-}+++-- | O(1). Yield the indices field of a `SSegd`.+indicesOfSSegd :: SSegd -> Array Int+{-# INLINE_BACKEND indicesOfSSegd #-}+++-- | O(1). Yield the starts field of a `SSegd`.+startsOfSSegd :: SSegd -> Array Int+{-# INLINE_BACKEND startsOfSSegd #-}+++-- | O(1). Yield the sources field of a `SSegd`.+sourcesOfSSegd :: SSegd -> Array Int+{-# INLINE_BACKEND sourcesOfSSegd #-}+++-- | O(1). Get the length, segment index, starting index, and source id of a segment.+getSegOfSSegd :: SSegd -> Int -> (Int, Int, Int, Int)+{-# INLINE_BACKEND getSegOfSSegd #-}+++-- | Produce a segment descriptor that describes the result of appending two+--   segmented arrays.+appendSSegd :: SSegd -> Int -> SSegd -> Int -> SSegd+{-# INLINE_BACKEND appendSSegd #-}+        ++-- Virtual Segment descriptors ================================================+-- | Construct a Virtual Segment Descriptor.+--+--   A `VSegd` is an extension of a `SSegd` that allows data from the underlying+--   flat array to be shared between segments. For example, you can define an array+--   of 10 virtual segments that all have the same length and elements as a+--   single physical segment.+--+--   * Internally we maintain the invariant that all physical segments must be+--     reachable by some virtual segment. This is needed to ensure that operations+--     such as `fold_ss` segmented fold have the right complexity. +--   +--   * If you don't need the invariant then you can sidestep the code that+--     maintains it by using the redundant versions of the following operators, +--     and sometimes get faster code.+-- +mkVSegd :: Array Int    -- ^ (vsegids) Mapping from virtual to physical segments.+        -> SSegd        -- ^ Scattered Segment descriptor defining the +                        --   physical segments.+        -> VSegd+{-# INLINE_BACKEND mkVSegd #-}+++-- | Check whether a `Segd` is well formed.+validVSegd :: VSegd -> Bool+{-# NOINLINE validVSegd #-}+--  NOINLINE because it's only used during debugging.+++-- | O(1). Construct an empty `SSegd`.+emptyVSegd :: VSegd+{-# INLINE_BACKEND emptyVSegd #-}+++-- | O(1). Construct a `VSegd` containing a single segment of the given length.+singletonVSegd :: Int -> VSegd+{-# INLINE_BACKEND singletonVSegd #-}+++-- | O(len). Construct a `VSegd` that describes an array where all virtual +--   segments point to the same physical segment.+replicatedVSegd +        :: Int          -- ^ Length of segment.+        -> Int          -- ^ Number of times replicated.+        -> VSegd+{-# INLINE_BACKEND replicatedVSegd #-}+++-- | O(segs). Promote a plain `Segd` to a `VSegd`.+--+--   The result contains one virtual segment for every physical segment+--   the provided `Segd`.+promoteSegdToVSegd :: Segd -> VSegd+{-# INLINE CONLIKE PHASE_BACKEND promoteSegdToVSegd #-}+++-- | O(segs). Promote a plain `SSegd` to a `VSegd`.+--+--   The result contains one virtual segment for every physical segment+--   the provided `SSegd`.+promoteSSegdToVSegd :: SSegd -> VSegd+{-# INLINE CONLIKE PHASE_BACKEND promoteSSegdToVSegd #-}+++-- | O(1). If true then the segments are all unshared, and the @vsegids@ field +--         be just @[0..len-1]@. +--+--   Consumers can check this field to avoid demanding the @vsegids@ field.+--   This can avoid the need for it to be constructed in the first place, +--   due to lazy evaluation.+isManifestVSegd :: VSegd -> Bool+{-# INLINE_BACKEND isManifestVSegd #-}+++-- | O(1). If true then the @starts@ field is identical to the @indices@ field+--         and the sourceids are all 0s.+--+--   In this case all the data elements are in one contiguous flat array, and+--   consumers can avoid looking at the real starts and sources fields.+isContiguousVSegd :: VSegd -> Bool+{-# INLINE_BACKEND isContiguousVSegd #-}+++-- | O(1). Yield the length of a `VSegd`.+lengthOfVSegd :: VSegd -> Int+{-# INLINE_BACKEND lengthOfVSegd #-}+++-- | O(1). Yield the vsegids of a `VSegd`.+takeVSegidsOfVSegd :: VSegd -> Array Int+{-# INLINE_BACKEND takeVSegidsOfVSegd #-}+++-- | O(1). Yield the vsegids of a `VSegd`, but don't require that every physical+--   segment is referenced by some virtual segment.+--+--   If you're just performing indexing and don't need the invariant that all+--   physical segments are reachable from some virtual segment, then use this+--   version as it's faster. This sidesteps the code that maintains the invariant.+--+--   The stated O(1) complexity assumes that the array has already been fully+--   evalauted. If this is not the case then we can avoid demanding the result+--   of a prior computation on the @vsegids@, thus reducing the cost attributed+--   to that prior computation.+--+takeVSegidsRedundantOfVSegd :: VSegd -> Array Int+{-# INLINE_BACKEND takeVSegidsRedundantOfVSegd #-}+++-- | O(1). Yield the `SSegd` of a `VSegd`.+takeSSegdOfVSegd :: VSegd -> SSegd+{-# INLINE_BACKEND takeSSegdOfVSegd #-}+++-- | O(1). Yield the `SSegd` of a `VSegd`, but don't require that every physical+--   segment is referenced by some virtual segment.+--+--   See the note in `takeVSegidsRedundantOfVSegd`.+takeSSegdRedundantOfVSegd :: VSegd -> SSegd+{-# INLINE_BACKEND takeSSegdRedundantOfVSegd #-}+++-- | O(1). Yield the segment lengths of a `VSegd`.+takeLengthsOfVSegd :: VSegd -> Array Int+{-# INLINE_BACKEND takeLengthsOfVSegd #-}+++-- | O(1). Get the length, starting index, and source id of a segment.+getSegOfVSegd :: VSegd -> Int -> (Int, Int, Int)+{-# INLINE_BACKEND getSegOfVSegd #-}+++-- | O(segs). +--   Yield a `SSegd` that describes each segment of a `VSegd` individually.+--+--   By doing this we lose information about which virtual segments+--   correspond to the same physical segments.+--+--   /WARNING/: Trying to take the `SSegd` of a nested array that has been+--   constructed with replication can cause index space overflow. This is+--   because the virtual size of the corresponding flat data can be larger+--   than physical memory. If this happens then indices fields and +--   element count in the result will be invalid.+--+unsafeDemoteToSSegdOfVSegd :: VSegd -> SSegd+{-# INLINE_BACKEND unsafeDemoteToSSegdOfVSegd #-}+++-- | O(segs). Yield a `Segd` that describes each segment of a `VSegd` individually.+--+--   By doing this we lose information about which virtual segments+--   correspond to the same physical segments.+--+--   See the warning in `unsafeDemoteToSSegdOfVSegd`.+unsafeDemoteToSegdOfVSegd :: VSegd -> Segd+{-# INLINE_BACKEND unsafeDemoteToSegdOfVSegd #-}+++-- | Update the @vsegids@ of a `VSegd`, and then cull the physical+--   segment descriptor so that all physical segments are reachable from+--   some virtual segment.+--+updateVSegsOfVSegd :: (Array Int -> Array Int) -> VSegd -> VSegd+{-# INLINE_BACKEND updateVSegsOfVSegd #-}+++-- | Update the @vsegids@ of `VSegd`, where the result is guaranteed to+--   cover all physical segments.+--+--   Using this version avoids performing the 'cull' operation which +--   discards unreachable physical segments.+--+--   * The resulting vsegids must cover all physical segments.+--     If they do not then there will be physical segments that are not +--     reachable from some virtual segment, and subsequent operations+--     like @fold_ss@ will have the wrong work complexity.+--+updateVSegsReachableOfVSegd :: (Array Int -> Array Int) -> VSegd -> VSegd+{-# INLINE_BACKEND updateVSegsReachableOfVSegd #-}+++-- | Produce a virtual segment descriptor that describes the result of +--   appending two segmented arrays.+appendVSegd +        :: VSegd        -- ^ Descriptor of first array.+        -> Int          -- ^ Number of flat physical arrays for first descriptor.+        -> VSegd        -- ^ Descriptor of second array.+        -> Int          -- ^ Number of flat physical arrays for second descriptor.+        -> VSegd+{-# INLINE_BACKEND appendVSegd #-}+++-- | Combine two virtual segment descriptors.+combine2VSegd+        :: Sel2         -- ^ Selector for the combine operation.+        -> VSegd        -- ^ Descriptor of first array.+        -> Int          -- ^ Number of flat physical arrays for first descriptor.+        -> VSegd        -- ^ Descriptor of second array.+        -> Int          -- ^ Number of flat physical arrays for second descriptor.+        -> VSegd+{-# INLINE_BACKEND combine2VSegd #-}++{-# RULES++"updateVSegsOfVSegd/updateVSegsOfVSegd" +  forall f g vsegd+  . updateVSegsOfVSegd f (updateVSegsOfVSegd g vsegd)+  = updateVSegsOfVSegd (f . g) vsegd++"updateVSegsOfVSegd/replicate_s/replicateVSegd"+  forall segd len reps+  . updateVSegsOfVSegd (replicate_s segd) (replicatedVSegd len reps)+  = replicatedVSegd len (elementsSegd segd)++ #-}+++-- Irregular 2D arrays --------------------------------------------------------++-- | O(1). Construct an empty `Arrays` with no elements.+emptys :: Arrays a+{-# INLINE_BACKEND emptys #-}+++-- | O(1). Construct an `Arrays` consisting of a single `Array`.+singletons :: (Elt a, Elts a) => Array a -> Arrays a+{-# INLINE_BACKEND singletons #-}+++-- | O(1). Yield the number of `Array` in an `Arrays`.+lengths :: Elts a => Arrays a -> Int+{-# INLINE_BACKEND lengths #-}+++-- | O(1). Take one of the outer `Array` from an `Arrays`.+unsafeIndexs :: (Elt a, Elts a) => Arrays a -> Int -> Array a+{-# INLINE_BACKEND unsafeIndexs #-}+++-- | O(1). Retrieve a single element from an `Arrays`, +--        given the outer and inner indices.+unsafeIndex2s :: (Elt a, Elts a) => Arrays a -> Int -> Int -> a+{-# INLINE_BACKEND unsafeIndex2s #-}+++-- | O(n). Append two `Arrays`, using work proportional to the length+--         of the outer array.+appends :: (Elt a, Elts a) => Arrays a -> Arrays a -> Arrays a+{-# INLINE_BACKEND appends #-}+++-- | O(number of inner arrays). +--   Convert a boxed vector of `Array` to an `Arrays`.+fromVectors :: (Elt a, Elts a) => VV.Vector (Array a) -> Arrays a+{-# INLINE_BACKEND fromVectors #-}+++-- | O(number of inner arrays). +--   Convert an `Arrays` to a boxed vector of `Array`.+toVectors :: (Elt a, Elts a) => Arrays a -> VV.Vector (Array a)+{-# INLINE_BACKEND toVectors #-}+++-- Random Arrays --------------------------------------------------------------+-- | Generate an array of the given length full of random data. +--   Good for testing.+randoms :: (Elt a, System.Random.Random a, System.Random.RandomGen g)+        => Int -> g -> Array a+{-# INLINE_BACKEND randoms #-}++-- | Generate an array of the given length full of random data.+--   Good for testing.+randomRs :: (Elt a, System.Random.Random a, System.Random.RandomGen g)+          => Int -> (a,a) -> g -> Array a+{-# INLINE_BACKEND randomRs #-}+++-- Array IO -------------------------------------------------------------------+instance IOElt Int+instance IOElt Double+instance (IOElt a, IOElt b) => IOElt (a, b)+++-- | Write an array to a file.+hPut :: IOElt a => Handle -> Array a -> IO ()+{-# INLINE_BACKEND hPut #-}+++-- | Read an array from a file.+hGet :: IOElt a => Handle -> IO (Array a)+{-# INLINE_BACKEND hGet #-}+++-- | Convert an array to a list of elements.+toList :: Elt a => Array a -> [a]+{-# INLINE_BACKEND toList #-}+++-- | Convert a list of elements to an array.+fromList :: Elt a => [a] -> Array a+{-# INLINE_BACKEND fromList #-}+++-- Aliases for primitive operations -------------------------------------------+-- We rename these so we can write rules based on the names, and still+-- control exactly when they get inlined.++dph_mod_index :: Int -> Int -> Int+dph_mod_index by idx = idx `GHC.Base.remInt` by+{-# INLINE_BACKEND dph_mod_index #-}++dph_plus :: Int -> Int -> Int+dph_plus x y = x Prelude.+ y+{-# INLINE_BACKEND dph_plus #-}++{-# RULES++"dph_plus" forall m n.+  dph_plus (GHC.Base.I# m) (GHC.Base.I# n) = GHC.Base.I# m Prelude.+ GHC.Base.I# n++  #-}+++tagZeroes :: Array Int -> Array Tag+tagZeroes xs = map (\x -> fromBool (x==0)) xs+{-# INLINE CONLIKE PHASE_BACKEND tagZeroes #-}+