Add stream functions for VSegd and shortcut fold_ss of a promoted Segd
authorBen Lippmeier <benl@ouroborus.net>
Thu, 15 Dec 2011 07:19:48 +0000 (18:19 +1100)
committerBen Lippmeier <benl@ouroborus.net>
Thu, 15 Dec 2011 07:19:48 +0000 (18:19 +1100)
18 files changed:
dph-lifted-vseg/Data/Array/Parallel/PArray/PData/Double.hs
dph-lifted-vseg/Data/Array/Parallel/PArray/PData/Int.hs
dph-lifted-vseg/Data/Array/Parallel/PArray/PData/Nested.hs
dph-lifted-vseg/Data/Array/Parallel/PArray/PData/Tuple2.hs
dph-lifted-vseg/Data/Array/Parallel/PArray/PData/Tuple3.hs
dph-lifted-vseg/Data/Array/Parallel/PArray/PData/Tuple4.hs
dph-lifted-vseg/Data/Array/Parallel/PArray/PData/Tuple5.hs
dph-lifted-vseg/Data/Array/Parallel/PArray/PData/Unit.hs
dph-lifted-vseg/Data/Array/Parallel/PArray/PData/Void.hs
dph-lifted-vseg/Data/Array/Parallel/PArray/PData/Word8.hs
dph-lifted-vseg/Data/Array/Parallel/PArray/PRepr/Instances.hs
dph-lifted-vseg/Data/Array/Parallel/PArray/Scalar.hs
dph-prim-interface/interface/DPH_Header.h
dph-prim-interface/interface/DPH_Interface.h
dph-prim-par/Data/Array/Parallel/Unlifted/Parallel/Segmented.hs
dph-prim-par/Data/Array/Parallel/Unlifted/Parallel/UPVSegd.hs
dph-prim-seq/Data/Array/Parallel/Unlifted/Stream.hs
dph-prim-seq/Data/Array/Parallel/Unlifted/Stream/Segments.hs

index a1ab538..bbd5eab 100644 (file)
@@ -15,10 +15,10 @@ import qualified Data.Vector                    as V
 
 -------------------------------------------------------------------------------
 data instance PData Double
-        = PDouble  !(U.Array  Double)
+        = PDouble  (U.Array  Double)
 
 data instance PDatas Double
-        = PDoubles !(U.Arrays Double)
+        = PDoubles (U.Arrays Double)
 
 
 -- PR -------------------------------------------------------------------------
@@ -97,7 +97,7 @@ instance PR Double where
   extractssPR (PDoubles arrs) ssegd
         = PDouble $ U.extracts_ass ssegd arrs
 
-  -- {-# INLINE_PDATA extractvsPR #-}
+  {-# INLINE_PDATA extractvsPR #-}
   extractvsPR (PDoubles arrs) vsegd
         = PDouble $ U.extracts_avs vsegd arrs
                 
index fac79c0..d301990 100644 (file)
@@ -74,7 +74,7 @@ instance PR Int where
   indexsPR (PInts pvecs) srcixs
         = PInt $ U.map (\(src, ix) -> U.unsafeIndex2s pvecs src ix) srcixs
 
-  -- {-# INLINE_PDATA indexvsPR #-}
+  {-# INLINE_PDATA indexvsPR #-}
   indexvsPR (PInts arrs) vsegd srcixs 
         = PInt $ U.indexs_avs arrs vsegd srcixs
 
@@ -86,7 +86,7 @@ instance PR Int where
   extractssPR (PInts arrs) ssegd
         = PInt $ U.extracts_ass ssegd arrs
 
-  -- {-# INLINE_PDATA extractvsPR #-}
+  {-# INLINE_PDATA extractvsPR #-}
   extractvsPR (PInts arrs) vsegd
         = PInt $ U.extracts_avs vsegd arrs
 
index 7d284e7..fd419f6 100644 (file)
@@ -29,11 +29,11 @@ import System.IO.Unsafe
 -- Nested arrays --------------------------------------------------------------
 data instance PData (PArray a)
         = PNested
-        { pnested_uvsegd       :: !U.VSegd
+        { pnested_uvsegd        :: U.VSegd
           -- ^ Virtual segmentation descriptor. 
           --   Defines a virtual nested array based on physical data.
 
-        , pnested_psegdata     :: !(PDatas a) 
+        , pnested_psegdata      :: PDatas a
           -- ^ Chunks of array data, where each chunk has a linear index space. 
 
         , pnested_segd          :: U.Segd       -- LAZY FIELD
@@ -635,21 +635,16 @@ concatlPR arr
 --   segmentation of the template array.
 --
 unconcatPR :: PR b => PData (PArray a) -> PData b -> PData (PArray b)
-unconcatPR (PNested vsegd _ _ _) pdata
+unconcatPR (PNested _ _ segd _) pdata
  = {-# SCC "unconcatPD" #-}
-   let  
-        -- Demote the vsegd to a manifest vsegd so it contains all the segment
+   let  -- Demote the vsegd to a manifest vsegd so it contains all the segment
         -- lengths individually without going through the vsegids.
-        !segd'          = U.unsafeDemoteToSegdOfVSegd vsegd
-
-        -- Rebuild the vsegd based on the manifest vsegd. 
+        -- Then Rebuild the vsegd based on the manifest vsegd. 
         -- The vsegids will be just [0..len-1], but this field is constructed
         -- lazilly and consumers aren't required to demand it.
-        !vsegd'         = U.promoteSegdToVSegd segd'
-        
+        vsegd'         = U.promoteSegdToVSegd segd
         pdatas'         = singletondPR pdata
-
-   in   PNested vsegd' pdatas' segd' pdata
+   in   PNested vsegd' pdatas' segd pdata
 {-# INLINE_PDATA unconcatPR #-}
 
 
index 9cb9d06..538abba 100644 (file)
@@ -20,10 +20,10 @@ import qualified Data.Array.Parallel.Unlifted   as U
 
 -------------------------------------------------------------------------------
 data instance PData (a, b)
-        = PTuple2  !(PData a) !(PData b)
+        = PTuple2  (PData a)  (PData b)
 
 data instance PDatas (a, b)
-        = PTuple2s !(PDatas a) !(PDatas b)
+        = PTuple2s (PDatas a) (PDatas b)
 
 
 -- PR -------------------------------------------------------------------------
index 080e6a4..e259e57 100644 (file)
@@ -16,10 +16,10 @@ import qualified Prelude                        as P
 
 -------------------------------------------------------------------------------
 data instance PData (a, b, c)
-        = PTuple3  !(PData a)  !(PData b)  !(PData c)
+        = PTuple3  (PData a)  (PData b)  (PData c)
 
 data instance PDatas (a, b, c)
-        = PTuple3s !(PDatas a) !(PDatas b) !(PDatas c)
+        = PTuple3s (PDatas a) (PDatas b) (PDatas c)
 
 
 -- PR -------------------------------------------------------------------------
index 09f3e32..dcd3fab 100644 (file)
@@ -17,10 +17,10 @@ import qualified Data.List                      as P
 
 -------------------------------------------------------------------------------
 data instance PData (a, b, c, d)
-        = PTuple4  !(PData a)  !(PData b)  !(PData c)  !(PData d)
+        = PTuple4  (PData a)  (PData b)  (PData c)  (PData d)
 
 data instance PDatas (a, b, c, d)
-        = PTuple4s !(PDatas a) !(PDatas b) !(PDatas c) !(PDatas d)
+        = PTuple4s (PDatas a) (PDatas b) (PDatas c) (PDatas d)
 
 
 -- PR -------------------------------------------------------------------------
@@ -275,4 +275,4 @@ instance ( PR a, PR b, PR c, PR d, Show a, Show b, Show c, Show d
                  (V.toList $ toVectorPR ds)
 
                  
-                 
\ No newline at end of file
+                 
index f4adc1b..d20be28 100644 (file)
@@ -17,10 +17,10 @@ import qualified Data.List                      as P
 
 -------------------------------------------------------------------------------
 data instance PData (a, b, c, d, e)
-        = PTuple5  !(PData a)  !(PData b)  !(PData c)  !(PData d)  !(PData e)
+        = PTuple5  (PData a)  (PData b)  (PData c)  (PData d)  (PData e)
 
 data instance PDatas (a, b, c, d, e)
-        = PTuple5s !(PDatas a) !(PDatas b) !(PDatas c) !(PDatas d) !(PDatas e)
+        = PTuple5s (PDatas a) (PDatas b) (PDatas c) (PDatas d) (PDatas e)
 
 
 -- PR -------------------------------------------------------------------------
@@ -300,4 +300,4 @@ instance ( PR a, PR b, PR c, PR d, PR e, Show a, Show b, Show c, Show d, Show e
                  (V.toList $ toVectorPR es)
 
                  
-                 
\ No newline at end of file
+                 
index 997a37a..4b0ddb0 100644 (file)
@@ -14,10 +14,10 @@ import qualified Data.Vector                    as V
 --   and rely on coversPR to check that indices are in bounds, like we do
 --   with arrays of type PData Void.
 data instance PData ()
-        = PUnit  !Int
+        = PUnit  Int
 
 data instance PDatas ()
-        = PUnits !(U.Array Int)
+        = PUnits (U.Array Int)
 
 punit   :: Int -> PData ()
 punit   = PUnit
index d4a17ce..9336966 100644 (file)
@@ -29,7 +29,7 @@ data instance PData Void
 
 -- | PVoids instance counts how many "vectors" of void we have
 data instance PDatas Void
-        = PVoids !Int
+        = PVoids Int
 
 pvoid :: PData Void
 pvoid   = error "Data.Array.Parallel.PData.Void"
index bffdb72..4bfeab7 100644 (file)
@@ -13,10 +13,10 @@ import Data.Array.Parallel.Pretty
 
 -------------------------------------------------------------------------------
 data instance PData Word8
-        = PWord8  !(U.Array Word8)
+        = PWord8  (U.Array Word8)
 
 data instance PDatas Word8
-        = PWord8s !(U.Arrays Word8)
+        = PWord8s (U.Arrays Word8)
 
 
 -- PR -------------------------------------------------------------------------
@@ -94,7 +94,7 @@ instance PR Word8 where
   extractssPR (PWord8s arrs) ssegd
         = PWord8 $ U.extracts_ass ssegd arrs
 
-  -- {-# INLINE_PDATA extractvsPR #-}
+  {-# INLINE_PDATA extractvsPR #-}
   extractvsPR (PWord8s arrs) vsegd
         = PWord8 $ U.extracts_avs vsegd arrs
 
index ee088b7..04d9199 100644 (file)
@@ -130,10 +130,10 @@ type instance PRepr  Ordering
  = Word8
 
 data instance PData Ordering
- = POrdering  !(U.Array Word8)
+ = POrdering  (U.Array Word8)
  
 data instance PDatas Ordering
- = POrderings !(U.Arrays Word8)
+ = POrderings (U.Arrays Word8)
 
 instance PA Ordering where
  {-# INLINE toPRepr #-}
index 492effa..f6772fd 100644 (file)
@@ -95,7 +95,7 @@ instance Scalar Word8 where
   toScalarPDatas                  = PWord8s
 
 instance Scalar Double where
-  fromScalarPData  (PDouble xs)   = xs
+  fromScalarPData  (PDouble xs)   = xs `seq` xs
   fromScalarPDatas (PDoubles xss) = xss
   toScalarPData                   = PDouble
   toScalarPDatas                  = PDoubles
@@ -176,42 +176,24 @@ fold1 f (PArray _ pdata)
 
 
 -- | Segmented fold of an array of arrays.
---   Each segment is folded individually, yielding an array of the fold results.
-{-# INLINE_PA folds #-}
 folds   :: (Scalar a, U.Elts a)
         => (a -> a -> a) -> a -> PArray (PArray a) -> PArray a
 
 folds f z (PArray _ (PNested vsegd pdatas _ _))
- = let  -- Grab all the flat physical arrays.
-        uarrs           = fromScalarPDatas pdatas 
-        
-        -- Sum up each physical segment individually.
-        psegResults     = U.fold_ss f z (U.takeSSegdOfVSegd vsegd) uarrs
-        
-        -- Replicate the physcal results according to the vsegids
-        vsegResults     = U.bpermute psegResults (U.takeVSegidsOfVSegd vsegd) 
-
-   in   fromUArray vsegResults
+  = pdatas `seq`  -- Don't seq on vsegd. See Note: fold/promoteSegd
+    fromUArray $ U.fold_vs f z vsegd $ fromScalarPDatas pdatas
+{-# INLINE_PA folds #-}
            
 
 -- | Segmented fold of an array of arrays, using the first element of each
 --   segment to initialse the state for that segment.
---   Each segment is folded individually, yielding an array of all the fold results.
-{-# INLINE_PA fold1s #-}
 fold1s  :: (Scalar a, U.Elts a)
         => (a -> a -> a) -> PArray (PArray a) -> PArray a
 
 fold1s f (PArray _ (PNested vsegd pdatas _ _))
- = let  -- Grab all the flat physical arrays.
-        uarrs           = fromScalarPDatas pdatas 
-        -- Sum up each physical segment individually.
-        psegResults     = U.fold1_ss f (U.takeSSegdOfVSegd vsegd) uarrs
-        
-        -- Replicate the physcal results according to the vsegids
-        vsegResults     = U.bpermute psegResults (U.takeVSegidsOfVSegd vsegd) 
-
-   in   fromUArray vsegResults
+ = pdatas `seq`  -- Don't seq on vsegd. See Note: fold/promoteSegd
+   fromUArray $ U.fold1_vs f vsegd $ fromScalarPDatas pdatas
+{-# INLINE_PA fold1s #-}
 
 
 -- | Left fold over an array, also passing the index of each element
@@ -220,9 +202,9 @@ fold1Index
         :: Scalar a
         => ((Int, a) -> (Int, a) -> (Int, a)) -> PArray a -> Int
 
-{-# INLINE_PA fold1Index #-}
 fold1Index f
         = fst . U.fold1 f . U.indexed . toUArray
+{-# INLINE_PA fold1Index #-}
 
 
 -- | Segmented fold over an array, also passing the index of each 
@@ -245,6 +227,12 @@ fold1sIndex f (PArray n# pdata)
          $ U.zip (U.indices_s segd)
          $ fromScalarPData xs
 
+{- [Note: fold/promoteSegd]
+   ~~~~~~~~~~~~~~~~~~~~~~~~
+   In the segmented fold functions above, don't seq on the vsegd because we
+   we need to to remain as an argument to the fold function so the 
+   fold/promoteSegdToVSegd rules from DPH_Interface.h fill fire.
+-}
 
 -- Enumerations --------------------------------------------------------------
 -- | Construct a range of integers.
index 1deeed0..111ecc3 100644 (file)
@@ -47,8 +47,8 @@ module Data.Array.Parallel.Unlifted (
   map, zipWith, zipWith3, zipWith4,
 
   -- * Folds and Scans
-  fold,  fold_s,  fold_ss,  fold_r,  
-  fold1, fold1_s, fold1_ss,
+  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, 
index 2449546..926ea59 100644 (file)
@@ -412,23 +412,58 @@ zipWith4 f as bs cs ds
 fold :: Elt a => (a -> a -> a) -> a -> Array a -> a
 {-# INLINE_BACKEND fold #-}
 
+
 -- | Undirected segmented fold.
 --   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.
 --   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.
+--   Same preconditions as fold_ss
+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.
@@ -437,12 +472,14 @@ fold_r :: Elt a => (a -> a -> a) -> a -> Int -> Array a -> Array a
 fold1 :: Elt a => (a -> a -> a) -> Array a -> a
 {-# INLINE_BACKEND fold1 #-}
 
+
 -- | Undirected segmented fold,
 --   using the first element of each segment to initialise the state of that segment.
 --   Same preconditions as `fold`.
 fold1_s :: Elt a => (a -> a -> a) -> Segd -> Array a -> Array a
 {-# INLINE_BACKEND fold1_s #-}
 
+
 -- | Undirected scattered segmented fold over an array, 
 --   using the first element of each segment to initialise the state of that segment.
 --   Same preconditions as `fold`.
@@ -451,6 +488,37 @@ fold1_ss :: (Elts a, Elt a)
 {-# INLINE_BACKEND fold1_ss #-}
 
 
+-- | Undirected fold over virtual segments.
+--   Same preconditions as fold_ss
+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 -------------------------------
 -- | Sum the elements of an array.
 sum :: (Num a, Elt a) => Array a -> a
@@ -928,14 +996,14 @@ singletonVSegd :: Int -> VSegd
 --   The result contains one virtual segment for every physical segment
 --   the provided `Segd`.
 promoteSegdToVSegd :: Segd -> VSegd
-{-# INLINE_BACKEND promoteSegdToVSegd #-}
+{-# 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_BACKEND promoteSSegdToVSegd #-}
+{-# INLINE CONLIKE PHASE_BACKEND promoteSSegdToVSegd #-}
 
 
 -- | O(1). Checks whether all the segments are manifest (unshared / non-virtual).
@@ -1073,6 +1141,18 @@ combine2VSegd
         -> VSegd
 {-# INLINE_BACKEND combine2VSegd #-}
 
+{-# RULES
+
+"updateVSegsOfVSegd/updateVSegsOfVSegd" forall f g vsegd.
+  updateVSegsOfVSegd f (updateVSegsOfVSegd g vsegd)
+   = updateVSegsOfVSegd (f . g) vsegd
+
+ #-}
+
+
+-- Irregular 2D arrays --------------------------------------------------------
+singletons :: (Elt a, Elts a) => Array a -> Arrays a
+{-# INLINE_BACKEND singletons #-}
 
 -- Random Arrays --------------------------------------------------------------
 randoms :: (Elt a, System.Random.Random a, System.Random.RandomGen g)
index 74e6df2..aacddaa 100644 (file)
@@ -27,6 +27,7 @@ import Data.Array.Parallel.Unlifted.Vectors                             (Vectors
 import qualified Data.Array.Parallel.Unlifted.Parallel.UPSegd           as UPSegd
 import qualified Data.Array.Parallel.Unlifted.Parallel.UPSSegd          as UPSSegd
 import qualified Data.Array.Parallel.Unlifted.Parallel.UPVSegd          as UPVSegd
+import qualified Data.Array.Parallel.Unlifted.Sequential.UVSegd         as UVSegd
 import qualified Data.Array.Parallel.Unlifted.Vectors                   as US
 import qualified Data.Array.Parallel.Unlifted.Stream                    as US
 import qualified Data.Array.Parallel.Unlifted.Sequential                as Seq
@@ -214,8 +215,9 @@ extractsFromVectorsWithUPVSegd
 
 extractsFromVectorsWithUPVSegd upvsegd vectors
         = Seq.unstream 
-        $ US.streamSegsFromVectorsUSSegd
-                vectors         -- TODD: avoid demote, use the vsegd directly.
-                (UPSSegd.takeUSSegd $ UPVSegd.demoteToUPSSegd upvsegd)
+        $ US.streamSegsFromVectorsUVSegd vectors
+        $ UVSegd.mkUVSegd 
+                (UPVSegd.takeVSegidsRedundant upvsegd)
+                (UPSSegd.takeUSSegd $ UPVSegd.takeUPSSegdRedundant upvsegd)
 {-# INLINE_UP extractsFromVectorsWithUPVSegd #-}
 
index 94f261e..f48df3e 100644 (file)
@@ -1,6 +1,5 @@
 {-# LANGUAGE CPP #-}
 #include "fusion-phases.h"
-
 {-# OPTIONS -Wall -fno-warn-orphans -fno-warn-missing-signatures #-}
 
 -- | Parallel virtual segment descriptors.
index b21df1f..806e8d1 100644 (file)
@@ -10,7 +10,8 @@ module Data.Array.Parallel.Unlifted.Stream
 
           -- * Segment streamers.
         , streamSegsFromNestedUSSegd
-        , streamSegsFromVectorsUSSegd)
+        , streamSegsFromVectorsUSSegd
+        , streamSegsFromVectorsUVSegd)
 where
 import Data.Array.Parallel.Unlifted.Stream.Ixs
 import Data.Array.Parallel.Unlifted.Stream.Elems
index d2e2a06..067dc58 100644 (file)
@@ -2,22 +2,24 @@
 #include "fusion-phases.h"
 module Data.Array.Parallel.Unlifted.Stream.Segments
         ( streamSegsFromNestedUSSegd
-        , streamSegsFromVectorsUSSegd)
+        , streamSegsFromVectorsUSSegd
+        , streamSegsFromVectorsUVSegd)
 where
 import Data.Vector.Fusion.Stream.Size
 import Data.Vector.Fusion.Stream.Monadic
-import Data.Vector.Unboxed                                       (Unbox,   Vector)
-import Data.Array.Parallel.Unlifted.Vectors                      (Unboxes, Vectors)
-import Data.Array.Parallel.Unlifted.Sequential.USSegd            (USSegd(..))
-import qualified Data.Array.Parallel.Unlifted.Vectors            as US
-import qualified Data.Array.Parallel.Unlifted.Sequential.USegd   as USegd
-import qualified Data.Array.Parallel.Unlifted.Sequential.USSegd  as USSegd
-import qualified Data.Vector.Unboxed                             as U
-import qualified Data.Vector                                     as V
-import qualified Data.Primitive.ByteArray                        as P
+import Data.Vector.Unboxed                                      (Unbox,   Vector)
+import Data.Array.Parallel.Unlifted.Vectors                     (Unboxes, Vectors)
+import Data.Array.Parallel.Unlifted.Sequential.USSegd           (USSegd(..))
+import Data.Array.Parallel.Unlifted.Sequential.UVSegd          (UVSegd(..))
+import qualified Data.Array.Parallel.Unlifted.Vectors           as US
+import qualified Data.Array.Parallel.Unlifted.Sequential.USegd  as USegd
+import qualified Data.Array.Parallel.Unlifted.Sequential.USSegd as USSegd
+import qualified Data.Array.Parallel.Unlifted.Sequential.UVSegd        as UVSegd
+import qualified Data.Vector.Unboxed                            as U
+import qualified Data.Vector                                    as V
+import qualified Data.Primitive.ByteArray                       as P
 import System.IO.Unsafe
 
-
 -- Nested -----------------------------------------------------------------------------------------
 -- | Stream some physical segments from many data arrays.
 -- 
@@ -29,7 +31,6 @@ import System.IO.Unsafe
 --           about jumping between segments. EXCEPT that this information must be
 --           statically visible else streamSegs won't fuse, so we can't have an 
 --           ifThenElse checking the manifest flag.
-
 streamSegsFromNestedUSSegd
         :: (Unbox a, Monad m)
         => V.Vector (Vector a)  -- ^ Source arrays.
@@ -91,7 +92,7 @@ streamSegsFromVectorsUSSegd
  
         -- Total number of elements to stream.
         !elements       = USegd.takeElements usegd
+
         -- seg, ix of that seg in usegd, length of seg, elem in seg
         {-# INLINE_INNER fnSeg #-}
         fnSeg (ixSeg, baSeg, ixEnd, ixElem)
@@ -118,7 +119,7 @@ streamSegsFromVectorsUSSegd
                  -- Stream the next element from the segment.
             else let !result  = P.indexByteArray baSeg ixElem
                  in  return   $ Yield result (ixSeg, baSeg, ixEnd, ixElem + 1)
-
+                                
         -- Starting state of the stream.
         -- CAREFUL:
         --  The ussegd might not contain any segments, so we can't initialise the state
@@ -141,3 +142,73 @@ streamSegsFromVectorsUSSegd
    in   Stream fnSeg initState (Exact elements) 
 {-# INLINE_STREAM streamSegsFromVectorsUSSegd #-}
 
+
+
+-- Vectors ----------------------------------------------------------------------------------------
+-- | Stream segments from a `Vectors`.
+-- 
+--   * There must be at least one segment in the `USSegd`, but this is not checked.
+-- 
+--   * No bounds checking is done for the `USSegd`.
+--
+streamSegsFromVectorsUVSegd
+        :: (Unboxes a, Monad m)
+        => Vectors a            -- ^ Vectors holding source data.
+        -> UVSegd               -- ^ Scattered segment descriptor
+        -> Stream m a
+
+streamSegsFromVectorsUVSegd
+        vectors
+        uvsegd@(UVSegd _ vsegids (USSegd _ segStarts segSources _usegd) )
+ = segStarts `seq` segSources `seq` uvsegd `seq` vectors `seq`
+   let  -- Length of each segment.
+        !segLens        = UVSegd.takeLengths uvsegd
+        !elemsTotal    = U.sum segLens
+
+        -- Total number of segments.
+        !segsTotal      = UVSegd.length uvsegd
+        -- seg, ix of that seg in usegd, length of seg, elem in seg
+        {-# INLINE_INNER fnSeg #-}
+        fnSeg (ixSeg, baSeg, ixEnd, ixElem)
+         = ixSeg `seq` baSeg `seq`
+           if ixElem >= ixEnd                   -- Was that the last elem in the current seg?
+            then if ixSeg + 1 >= segsTotal      -- Was that last seg?
+
+                       -- That was the last seg, we're done.
+                  then return $ Done
+                  
+                       -- Move to the next seg.
+                  else let ixSeg'       = ixSeg + 1
+                          ixPSeg       = U.unsafeIndex vsegids    ixSeg'                               
+                           sourceSeg    = U.unsafeIndex segSources ixPSeg
+                           startSeg     = U.unsafeIndex segStarts  ixPSeg
+                           lenSeg       = U.unsafeIndex segLens    ixPSeg
+                           (arr, startArr, _) 
+                                        = US.unsafeIndexUnpack vectors sourceSeg
+                       in  return $ Skip
+                                  ( ixSeg'
+                                  , arr
+                                  , startArr + startSeg + lenSeg
+                                  , startArr + startSeg)
+
+                 -- Stream the next element from the segment.
+            else let !result  = P.indexByteArray baSeg ixElem
+                 in  return   $ Yield result (ixSeg, baSeg, ixEnd, ixElem + 1)
+                                
+        -- Starting state of the stream.
+        !dummy  = unsafePerformIO 
+                $ P.newByteArray 0 >>= P.unsafeFreezeByteArray
+
+        !initState
+         =      ( -1    -- force fnSeg loop to load first seg
+                , dummy -- dummy array data to start with
+                , 0     -- force fnSeg loop to load first seg
+                , 0)           
+
+        -- It's important that we set the result stream size, so Data.Vector
+        -- doesn't need to add code to grow the result when it overflows.
+   in   Stream fnSeg initState (Exact elemsTotal)
+{-# INLINE_STREAM streamSegsFromVectorsUVSegd #-}
+
+