dph-examples: More consistent naming in handvec QuickHull.
authorGeorge Roldugin <groldugin@cse.unsw.edu.au>
Mon, 18 Feb 2013 14:46:18 +0000 (01:46 +1100)
committerGeorge Roldugin <groldugin@cse.unsw.edu.au>
Fri, 22 Feb 2013 05:12:32 +0000 (16:12 +1100)
dph-examples/examples/spectral/QuickHull/handvec/Handvec.hs
dph-examples/examples/spectral/QuickHull/handvec/HandvecWrp.hs

index f17426a..d09763b 100644 (file)
@@ -22,6 +22,9 @@ import Debug.Trace as Debug
 import Prelude as P
 
 
+-- | Vectorised version of hsplit.
+--
+-- A closure containing the original scalar version and the lifted version.
 hsplit_v :: PArray Point :-> Line :-> PArray Point
 hsplit_v = closure2 hsplit_s hsplit_l
 {-# NOINLINE hsplit_v #-}
@@ -38,55 +41,57 @@ hsplit_s ps _ = ps
 -- Wrapper for lifted hsplit with the type expected by the vectoriser
 -- (which we still go through to avoid hand vectorising 'HandvecWrp.quickHull'.
 hsplit_l :: PArray (PArray Point) -> PArray Line -> PArray (PArray Point)
-hsplit_l (PArray _ points_s) (PArray nlines# lines)
-  = let result@(PNested segd _) = hsplit_l' nlines# points_s lines
-        !(I# nsegs#) = U.lengthSegd segd                        -- should be 2
-    in  PArray nsegs# result
+hsplit_l (PArray _ points_s) (PArray nLines# lines)
+  = let result@(PNested segd _) = hsplit_l' nLines# points_s lines
+        nsegs = U.lengthSegd segd                        -- should be 2
+    in  PArray (un# nsegs) result
 {-# INLINE hsplit_l #-}
 
 
 -- | Actually the heart of QuickHull.
+--
+-- The extra argument is the lifting context (number of lines/segments).
 hsplit_l' :: Int# -> PData (PArray Point) -> PData Line -> PData (PArray Point)
-hsplit_l' nlines# (PNested segd _) _
+hsplit_l' nLines# (PNested segd _) _
   | Debug.traceEvent ("GANG[1/1] Issuing hsplit_l' " ++
-                      "with " ++ show (I# nlines#) ++ " lines " ++
+                      "with " ++ show (I# nLines#) ++ " lines " ++
                       "and " ++ show (U.elementsSegd segd) ++ " points, " ++
                       "distributed as: " ++ show (U.toList $ U.lengthsSegd segd)) False = undefined
 hsplit_l' 0# _ _ = PNested U.emptySegd (P_2 (PDouble U.empty) (PDouble U.empty))
-hsplit_l' nlines# points_s                                     -- E.g.: nlines#: 6, npts >= 13
+hsplit_l' nLines# points_s                                  -- E.g.: nLines#: 6, npts >= 13
           lines@(P_2 (P_2 (PDouble line_x1s) (PDouble line_y1s))
                      (P_2 (PDouble line_x2s) (PDouble line_y2s)))
   = let -- Find distance-like measures between each point and its respective line.
-        cross_s     = calc_cross_s  points_s lines
+        distances_s = calcCross points_s lines
 
         -- Throw out all the points which are below the line (i.e. distance <= 0).
-        above_s@(PNested aboveSegd (P_2 (PDouble xos) (PDouble yos)))
-                    = calc_above_s points_s cross_s
+        above_s@(PNested aboveSegd (P_2 (PDouble xs) (PDouble ys)))
+                    = calcAbove points_s distances_s
 
         -- For some of the lines there are no more points left (segment length 0).
         -- The recursion for these lines has finished and we'll treat them separately.
-        (aboveSegdLens,_,_) = unpackSegd aboveSegd          -- Segd ( [4, 5, 0, 2, 2,  0]
+        (above_lens,_,_) = unpackSegd aboveSegd             -- Segd ( [4, 5, 0, 2, 2,  0]
                                                             --      , [0, 4, 9, 9, 11, 13]
                                                             --      , 13 )
 
-        -- Empty segments selector (empty -> 1; otherwise -> 0)
-        selE        = U.tagsToSel2                          -- Sel2 ( [0, 0, 1, 0, 0, 1]
+        -- Empty segments emptySelctor (empty -> 1; otherwise -> 0)
+        emptySel    = U.tagsToSel2                          -- Sel2 ( [0, 0, 1, 0, 0, 1]
                     $ U.map B.fromBool                      --      , [0, 1, 0, 2, 3, 1]
-                    $ U.zipWith (P.==) aboveSegdLens        --      , 4, 2 )
-                                       (U.replicate (I# nlines#) 0)
-        tagsE       = U.tagsSel2 selE                       -- [0, 0, 1, 0, 0, 1]
+                    $ U.zipWith (P.==) above_lens           --      , 4, 2 )
+                                       (U.replicate (I# nLines#) 0)
+        emptyTags   = U.tagsSel2 emptySel                   -- [0, 0, 1, 0, 0, 1]
 
         --- *** First take care of the lines for which the recursion hasn't finished *** ---
         --- ***                                                                      *** ---
 
         -- Create segd for the points above those lines, which still have points above them.
         -- This is equivalent to removing all empty segments from 'aboveSegd'.
-        segdNE      = U.lengthsToSegd                       -- Segd ( [4, 5, 2, 2]
-                    $ U.packByTag aboveSegdLens tagsE 0     --      , [0, 4, 9, 11]
+        purgedSegd = U.lengthsToSegd                        -- Segd ( [4, 5, 2, 2]
+                   $ U.packByTag above_lens emptyTags 0     --      , [0, 4, 9, 11]
                                                             --      , 13 )
-        (lensNE, idsNE, _) = unpackSegd segdNE
+        (purged_lens, purged_ids, _) = unpackSegd purgedSegd
 
-        tagsE_r     = U.replicate_s aboveSegd tagsE         -- [0, 0, 0, 0,     -- 4
+        emptyTags_r = U.replicate_s aboveSegd emptyTags     -- [0, 0, 0, 0,     -- 4
                                                             --  0, 0, 0, 0, 0,  -- 5
                                                             --                  -- 0
                                                             --  0, 0,           -- 2
@@ -94,116 +99,117 @@ hsplit_l' nlines# points_s                                     -- E.g.: nlines#:
                                                             --                  -- 0
 
         -- WATCH OUT: Redundant packByTag. Basicaly remove all empty segments from 'aboveSegd',
-        -- without touching the data arrays
-        aboveNE@(PNested _ (P_2 (PDouble xos') (PDouble yos')))
-                    = PNested segdNE (P_2 (PDouble $ U.packByTag xos tagsE_r 0)
-                                          (PDouble $ U.packByTag yos tagsE_r 0))
+        -- without touching the data arrays. I.e. data-wise purged_s = above_s
+        purged_s@(PNested _ (P_2 (PDouble xs') (PDouble ys')))
+                    = PNested purgedSegd (P_2 (PDouble $ U.packByTag xs emptyTags_r 0)
+                                              (PDouble $ U.packByTag ys emptyTags_r 0))
 
         --- *** Prepare segd to call hsplit anew *** ---
         --- ***                                  *** ---
 
         -- Number of non-empty segments
-        !nNE@(I# nNE#) = U.elementsSel2_0 selE              -- 4
+        nFilled     = U.elementsSel2_0 emptySel                   -- 4
 
         -- New segd with one element per non-empty segment of 'aboveSegd' (farthest point)
-        segdNEx1    = U.mkSegd (U.replicate nNE 1)          -- Segd ( [1, 1, 1, 1]
-                               (U.enumFromStepLen 0 1 nNE)  --      , [0, 1, 3, 4]
-                               nNE                          --      , 4 )
+        filled1Segd = U.mkSegd (U.replicate nFilled 1)            -- Segd ( [1, 1, 1, 1]
+                               (U.enumFromStepLen 0 1 nFilled)    --      , [0, 1, 3, 4]
+                               nFilled                            --      , 4 )
+
         -- New segd with two elements per non-empty segment of 'aboveSegd'.
-        -- It's used indirectly in multiple places to denote the fact that we get two lines
-        -- for each line for which the recursion hasn't finished. They share the point farthest
-        -- from the old line.
-        segdNEx2    = segdNEx1 `U.plusSegd` segdNEx1        -- Segd ( [2, 2, 2, 2]
-                                                            --      , [0, 2, 4, 8]
-        (_,_,eltsNEx2) = unpackSegd segdNEx2                --      , 8 )
+        -- Represents the fact that we make two new lines out one current out before making the
+        -- recursive call. They share the point farthest from the old line.
+        filled2Segd = filled1Segd `U.plusSegd` filled1Segd        -- Segd ( [2, 2, 2, 2]
+                                                                  --      , [0, 2, 4, 8]
+        (_,_,filled2_elts) = unpackSegd filled2Segd               --      , 8 )
 
 
         -- Replicate each non-empty segment twice
-        lens_dbl      = U.replicate_s segdNEx2 lensNE       -- Segd ( [4, 4, 5, 5, 2, 2, 2, 2]
-        segd_dbl      = U.lengthsToSegd lens_dbl            --      , [0, 4, 8,13,18,20,22,24]
-        (_,_,elts_dbl)= unpackSegd segd_dbl                 --      ,  26 )
+        dbl_lens    = U.replicate_s filled2Segd purged_lens       -- Segd ( [4, 4, 5, 5, 2, 2, 2, 2]
+        dblSegd     = U.lengthsToSegd dbl_lens                    --      , [0, 4, 8,13,18,20,22,24]
+        (_,_,dbl_elts) = unpackSegd dblSegd                       --      ,  26 )
 
-        -- Find indices to take from the points array to make it adhere to the doubled segd_dbl
+        -- Find indices to take from the points array to make it adhere to the doubled dblSegd
         -- (vsegs to the rescue?)
-        ids_to_take   = U.enumFromStepLenEach elts_dbl                       -- 26 (length hint)
-                                              (U.replicate_s segdNEx2 idsNE) -- [0, 0, 4, 4, 9, 9,11,11]
-                                              (U.replicate   eltsNEx2 1)     -- [1, 1, 1, 1, 1, 1, 1, 1]
-                                              lens_dbl                       -- [4, 4, 5, 5, 2, 2, 2, 2]
+        ids_to_take = U.enumFromStepLenEach
+                           dbl_elts                               -- 26 (length hint)
+                           (U.replicate_s filled2Segd purged_ids) -- [0, 0, 4, 4, 9, 9,11,11]
+                           (U.replicate   filled2_elts 1)         -- [1, 1, 1, 1, 1, 1, 1, 1]
+                           dbl_lens                               -- [4, 4, 5, 5, 2, 2, 2, 2]
         -- ids_to_take: [0,1,2,3, 0,1,2,3, 4,5,6,7,8, 4,5,6,7,8, 9,10, 9,10, 11,12, 11,12]
 
         -- Actually perform doubling of all segments.
         -- Each line now has two identical segments for the points above it.
-        above_dbl   = PNested segd_dbl (P_2 (PDouble $ U.bpermute xos' ids_to_take)
-                                            (PDouble $ U.bpermute yos' ids_to_take))
+        aboveDbl_s  = PNested dblSegd (P_2 (PDouble $ U.bpermute xs' ids_to_take)
+                                           (PDouble $ U.bpermute ys' ids_to_take))
 
         -- Take a moment to find points farthest from each line
         fars@(P_2 (PDouble far_xs) (PDouble far_ys))
-                    = calc_farthest_s points_s cross_s tagsE
+                    = calcFarthest points_s distances_s emptyTags
 
         -- Find lines to and from the farthest points (i.e. [:(p1, pm), (pm, p2):] in the original code).
         -- Remember we are only dealing with lines for which there are still points above them.
         -- The use of segments here is a convenient way to interleave the old line starts, with the
         -- farthest points (also used as line starts in the next iteration).
-        -- segdNEx2 is not used directly and is merely a hint to segmented append.
-        line_1s'    = P_2 (PDouble $ U.append_s segdNEx2
-                                                segdNEx1 (U.packByTag line_x1s tagsE 0)
-                                                segdNEx1 far_xs)
+        -- filled2Segd is not used directly and is merely a hint to segmented append.
+        farLine_1s  = P_2 (PDouble $ U.append_s filled2Segd
+                                                filled1Segd (U.packByTag line_x1s emptyTags 0)
+                                                filled1Segd far_xs)
 
-                          (PDouble $ U.append_s segdNEx2
-                                                segdNEx1 (U.packByTag line_y1s tagsE 0)
-                                                segdNEx1 far_ys)
+                          (PDouble $ U.append_s filled2Segd
+                                                filled1Segd (U.packByTag line_y1s emptyTags 0)
+                                                filled1Segd far_ys)
 
         -- Line ends are interleaved in a similar manner.
-        line_2s'    = P_2 (PDouble $ U.append_s segdNEx2
-                                                segdNEx1 far_xs
-                                                segdNEx1 (U.packByTag line_x2s tagsE 0))
+        farLine_2s  = P_2 (PDouble $ U.append_s filled2Segd
+                                                filled1Segd far_xs
+                                                filled1Segd (U.packByTag line_x2s emptyTags 0))
 
-                          (PDouble $ U.append_s segdNEx2
-                                                segdNEx1 far_ys
-                                                segdNEx1 (U.packByTag line_y2s tagsE 0))
-        lines'      = P_2 line_1s' line_2s'                 -- 8 lines in total
+                          (PDouble $ U.append_s filled2Segd
+                                                filled1Segd far_ys
+                                                filled1Segd (U.packByTag line_y2s emptyTags 0))
+        farLines    = P_2 farLine_1s farLine_2s             -- 8 lines in total
 
-        -- Finally make recursive call to compute convex hull from (when the recursion hasn't finished)
-        !(I# eltsNEx2#) = eltsNEx2
-        hullNE@(PNested hullNE_segd (P_2 (PDouble hullNE_xs) (PDouble hullNE_ys)))
-                    = hsplit_l' eltsNEx2# above_dbl lines'
+        -- Finally make recursive call to compute convex hull (for the list with points still above them)
+        hull_s@(PNested hullSegd (P_2 (PDouble hull_xs) (PDouble hull_ys)))
+                    = hsplit_l' (un# filled2_elts) aboveDbl_s farLines
 
         -- hsplit returns *only* line starts. In the example above we had 4 lines with points above them
-        (hullNE_lens,_,_) = unpackSegd hullNE_segd          -- Segd: [ 2, 1, 2, 2, 1, 1, 2, 1 ]
+        (hull_lens,_,_) = unpackSegd hullSegd               -- Segd: [ 2, 1, 2, 2, 1, 1, 2, 1 ]
                                                             --                    ^          ^
                                                             -- Lines with finished recursion each contribute
                                                             -- one pt to hull. They go where ^ points.
 
         --- *** Now deal with the empty segnments, i.e. lines which have no points above them *** ---
         --- *** and will thus form part of the convex hull                                    *** ---
-        !nE@(I# nE#)= U.elementsSel2_1 selE                -- 2 lines have no more points above them
+        nEmpty      = U.elementsSel2_1 emptySel             -- 2 lines have no more points above them
 
         -- Prepare the final segd to hold both the lines that have no above points as well as the remainder
         -- of the convex hull returned by the recursive call.
-        result_segd = U.lengthsToSegd                       -- Segd: [3, 4, 1, 2, 3, 1]
-                    $ U.combine2 (U.tagsSel2 selE)          -- [0, 0, 1, 0, 0, 1] (actually tagsE)
-                                 (U.repSel2  selE)          -- Distribution across PEs
-                                 (U.sum_s segdNEx2 hullNE_lens)   -- [3, 4, 2, 3]
-                                 (U.replicate nE 1)               -- [1, 1]
+        resultSegd  = U.lengthsToSegd                       -- Segd: [3, 4, 1, 2, 3, 1]
+                    $ U.combine2 (U.tagsSel2 emptySel)      -- [0, 0, 1, 0, 0, 1] (actually emptyTags)
+                                 (U.repSel2  emptySel)      -- Distribution across PEs
+                                 (U.sum_s filled2Segd hull_lens) -- [3, 4, 2, 3]
+                                 (U.replicate nEmpty 1)          -- [1, 1]
 
-        result_sel  = U.tagsToSel2                          -- [0,0,0, 0,0,0,0, 1, 0,0, 0,0,0, 1]
-                    $ (U.replicate_s result_segd tagsE)
-        result_tags = U.tagsSel2  result_sel                -- As above
-        result_repsel = U.repSel2 result_sel                -- Distribution across PEs
+        resultSel   = U.tagsToSel2                          -- [0,0,0, 0,0,0,0, 1, 0,0, 0,0,0, 1]
+                    $ (U.replicate_s resultSegd emptyTags)
+        resultTags  = U.tagsSel2 resultSel                  -- As above
+        resultRepsel= U.repSel2  resultSel                  -- Distribution across PEs
 
         -- Combine data returned from 'hsplit' and the starts of the lines we left alone.
-        result_xs   = U.combine2 result_tags
-                                 result_repsel
-                                 hullNE_xs
-                                 (U.packByTag line_x1s tagsE 1)
-        result_ys   = U.combine2 result_tags
-                                 result_repsel
-                                 hullNE_ys
-                                 (U.packByTag line_y1s tagsE 1)
-
-    in  (PNested result_segd (P_2 (PDouble result_xs) (PDouble result_ys)))
+        result_xs   = U.combine2 resultTags
+                                 resultRepsel
+                                 hull_xs
+                                 (U.packByTag line_x1s emptyTags 1)
+        result_ys   = U.combine2 resultTags
+                                 resultRepsel
+                                 hull_ys
+                                 (U.packByTag line_y1s emptyTags 1)
+
+    in  (PNested resultSegd (P_2 (PDouble result_xs) (PDouble result_ys)))
 {-# INLINE hsplit_l' #-}
 
+
 unpackSegd :: Segd -> (Array Int, Array Int, Int)
 unpackSegd segd = ( U.lengthsSegd  segd
                   , U.indicesSegd  segd
@@ -216,20 +222,20 @@ unpackSegd segd = ( U.lengthsSegd  segd
 -- Each point can be above (positive distance) or below (negative distance)
 -- a line as looking from the center of the convex hull.
 --
--- Corresponds to 'cross' in the original program
+-- Corresponds to 'cross' in the original program:
 -- > cross  = [: distance p line | p <- points :]
-calc_cross_s :: PData (PArray Point) -> PData Line -> PData (PArray Double)
-calc_cross_s (PNested segd (P_2 (PDouble xos) (PDouble yos)))
+calcCross :: PData (PArray Point) -> PData Line -> PData (PArray Double)
+calcCross (PNested segd (P_2 (PDouble xs) (PDouble ys)))
              (P_2 (P_2 (PDouble x1s) (PDouble y1s))
                   (P_2 (PDouble x2s) (PDouble y2s)))
-  = let crosses = U.zipWith6 distance xos
-                                       yos
-                                       (U.replicate_s segd x1s)
-                                       (U.replicate_s segd y1s)
-                                       (U.replicate_s segd x2s)
-                                       (U.replicate_s segd y2s)
+  = let crosses = U.zipWith6 distance xs
+                                      ys
+                                      (U.replicate_s segd x1s)
+                                      (U.replicate_s segd y1s)
+                                      (U.replicate_s segd x2s)
+                                      (U.replicate_s segd y2s)
     in PNested segd (PDouble crosses)
-{-# INLINE calc_cross_s #-}
+{-# INLINE calcCross #-}
 
 
 -- | Calculate cross product between vectors formed between a point and
@@ -250,30 +256,30 @@ distance xo yo x1 y1 x2 y2
 {-# INLINE distance #-}
 
 
--- | Find points above the lines given distance-like measures
+-- | Find points above the lines given distance-like measures.
 --
--- Corresponds to 'packed' in the original program
+-- Corresponds to 'packed' in the original program:
 -- > packed = [: p | (p,c) <- zipP points cross, c D.> 0.0 :]
-calc_above_s :: PData (PArray Point) -> PData (PArray Double) -> PData (PArray Point)
-calc_above_s (PNested segd (P_2 (PDouble xos) (PDouble yos))) -- points_s
-             (PNested _    (PDouble distances))                -- cross_s
+calcAbove :: PData (PArray Point) -> PData (PArray Double) -> PData (PArray Point)
+calcAbove (PNested segd (P_2 (PDouble xs) (PDouble ys))) -- points_s
+          (PNested _    (PDouble distances))             -- cross_s
   = let length    = U.elementsSegd segd
 
-        -- Compute selector for positive elements ((>0) -> 1; otherwise -> 0)
-        selAbove  = U.tagsToSel2
+        -- Compute emptySelctor for positive elements ((>0) -> 1; otherwise -> 0)
+        aboveSel  = U.tagsToSel2
                   $ U.map B.fromBool
                   $ U.zipWith (P.>) distances (U.replicate length 0.0)
 
         -- Compute segd for just the positive elements
-        segdAbove = U.lengthsToSegd (U.count_s segd (tagsSel2 selAbove) 1)
+        aboveSegd = U.lengthsToSegd (U.count_s segd (tagsSel2 aboveSel) 1)
 
         -- Get the actual points corresponding to positive elements
-        tagsAbove = U.tagsSel2 selAbove
-        xosAbove  = U.packByTag xos tagsAbove 1
-        yosAbove  = U.packByTag yos tagsAbove 1
+        aboveTags = U.tagsSel2 aboveSel
+        above_xs  = U.packByTag xs aboveTags 1
+        above_ys  = U.packByTag ys aboveTags 1
 
-    in  (PNested segdAbove (P_2 (PDouble xosAbove) (PDouble yosAbove)))
-{-# INLINE calc_above_s #-}
+    in  (PNested aboveSegd (P_2 (PDouble above_xs) (PDouble above_ys)))
+{-# INLINE calcAbove #-}
 
 
 -- | For each line find a point fartherst from that line.
@@ -283,25 +289,29 @@ calc_above_s (PNested segd (P_2 (PDouble xos) (PDouble yos))) -- points_s
 --
 -- Corresponds to 'pm' in the original program:
 -- > pm = points !: maxIndexP cross
-calc_farthest_s :: PData (PArray Point) -> PData (PArray Double) -> Array Tag -> PData Point
-calc_farthest_s (PNested ptsSegd   (P_2 (PDouble x1s) (PDouble y1s))) -- points_s
-                (PNested distSegd (PDouble distances))                -- cross_s
-                tags
+calcFarthest :: PData (PArray Point) -> PData (PArray Double) -> Array Tag -> PData Point
+calcFarthest (PNested ptsSegd  (P_2 (PDouble xs) (PDouble ys))) -- ^ points_s
+             (PNested distSegd (PDouble distances))             -- ^ cross_s
+             emptyTags                                          -- ^ tag segments with no more
+                                                                --   points above the line
   = let -- Index the distances array, and find the indices corresponding to the
         -- largest distance in each segment
-        indexed  = U.zip (U.indices_s distSegd) distances
-        max_ids  = U.fsts (U.fold1_s maxSnd distSegd indexed)
+        indexed  = U.zip (U.indices_s distSegd)
+                         distances
+        max_ids  = U.fsts
+                 $ U.fold1_s maxSnd distSegd indexed
 
         -- Find indices to take from the points array by offsetting from segment starts
         ids      = U.zipWith (P.+) (U.indicesSegd ptsSegd)
                                    max_ids
-        max_xs   = U.bpermute x1s ids
-        max_ys   = U.bpermute y1s ids
-        -- however we are only interested in the ones which are from the non-empty segments
-        -- (TODO revise comment)
-    in  P_2 (PDouble $ U.packByTag max_xs tags 0)
-            (PDouble $ U.packByTag max_ys tags 0)
-{-# INLINE calc_farthest_s #-}
+        max_xs   = U.bpermute xs ids
+        max_ys   = U.bpermute ys ids
+
+        -- We are only interested in the ones which are above the line
+        -- (thus from segments containing points above line).
+    in  P_2 (PDouble $ U.packByTag max_xs emptyTags 0)
+            (PDouble $ U.packByTag max_ys emptyTags 0)
+{-# INLINE calcFarthest #-}
 
 
 -- | Find pair with the bigest second element.
@@ -310,3 +320,9 @@ maxSnd :: P.Ord b => (a, b) -> (a, b) -> (a, b)
 maxSnd (i,x) (j,y) | x P.>= y    = (i,x)
                    | P.otherwise = (j,y)
 {-# INLINE maxSnd #-}
+
+
+-- | Unbox an integer.
+un# :: Int -> Int#
+un# (I# i#) = i#
+{-# INLINE un# #-}
index 347554a..4f86179 100644 (file)
@@ -12,7 +12,7 @@ import qualified Data.Array.Parallel.Prelude.Int as I
 
 import Prelude as P
 
-import Handvec
+import Handvec ( hsplit_v )
 
 -- Manually override vectorisation of hsplit
 -- hsplit :: [:Point:] -> Line -> [:Point:]
@@ -26,7 +26,8 @@ quickHull :: [:Point:] -> [:Point:]
 quickHull points
   | lengthP points I.== 0 = points
   | otherwise
-  = concatP [: fromPArrayP (hsplit (toPArrayP points) ends) | ends <- [: (minx, maxx), (maxx, minx) :] :]
+  = concatP [: fromPArrayP (hsplit (toPArrayP points) ends)
+               | ends <- [: (minx, maxx), (maxx, minx) :] :]
   where
     xs   = [: x | (x, y) <- points :]
     minx = points PA.!: minIndexP xs