1 {-# LANGUAGE CPP, BangPatterns #-}
3 #include
"fusion-phases.h"
5 -- | Define the closures for the array combinators the vectoriser uses.
6 -- The closures themselves use the *PD primitives defined in
7 -- dph-common:Data.Array.Parallel.Lifted.Combinators
9 -- For each combinator:
10 -- The *PA_v version is the "vectorised" version that has had its
11 -- parameters closure converted. See zipWithPA_v for an example.
13 -- The *PA_l version is the "lifted" version that also works
14 -- on arrays of arrays.
16 -- The *PA version contains both of these wrapped up into a closure.
17 -- The output of the vectoriser uses these *PA versions directly,
18 -- with applications being performed by the liftedApply function
19 -- from "Data.Array.Parallel.Lifted.Closure"
21 -- TODO: combine2PA_l isn't implemented and will just `error` if you
22 -- try to use it. None of our benchmarks do yet...
24 module Data
.Array.Parallel
.Lifted
.Combinators
(
25 lengthPA
, replicatePA
, singletonPA
, mapPA
, crossMapPA
,
26 zipPA
, zip3PA
, zipWithPA
, zipWith3PA
, unzipPA
, unzip3PA
,
27 packPA
, filterPA
, combine2PA
, indexPA
, concatPA
, appPA
, enumFromToPA_Int
,
28 indexedPA
, slicePA
, updatePA
, bpermutePA
,
30 -- * Functions re-exported by Data.Array.Parallel.PArray
31 lengthPA_v
, replicatePA_v
, singletonPA_v
, zipPA_v
, unzipPA_v
,
32 packPA_v
, concatPA_v
, indexedPA_v
, updatePA_v
, bpermutePA_v
,
33 slicePA_v
, indexPA_v
, appPA_v
, enumFromToPA_v
35 import Data
.Array.Parallel
.Lifted
.PArray
36 import Data
.Array.Parallel
.Lifted
.Closure
37 import Data
.Array.Parallel
.Lifted
.Unboxed
38 import Data
.Array.Parallel
.Lifted
.Scalar
39 import Data
.Array.Parallel
.PArray
.PReprInstances
40 import Data
.Array.Parallel
.PArray
.PDataInstances
41 import Data
.Array.Parallel
.PArray
.ScalarInstances
43 import qualified Data
.Array.Parallel
.Unlifted
as U
44 import Data
.Array.Parallel
.Base
(Tag
)
46 import GHC
.Exts
(Int(..), (+#))
49 -- length ---------------------------------------------------------------------
50 -- | Take the number of elements in an array.
51 lengthPA
:: PA a
=> PArray a
:-> Int
52 {-# INLINE lengthPA #-}
53 lengthPA
= closure1 lengthPA_v lengthPA_l
55 lengthPA_v
:: PA a
=> PArray a
-> Int
56 {-# INLINE_PA lengthPA_v #-}
57 lengthPA_v xs
= I
# (lengthPA
# xs
)
59 lengthPA_l
:: PA a
=> PArray
(PArray a
) -> PArray
Int
60 {-# INLINE_PA lengthPA_l #-}
61 lengthPA_l xss
= fromUArrPA
(U
.elementsSegd segd
) (U
.lengthsSegd segd
)
66 -- replicate ------------------------------------------------------------------
67 -- | Produce a new array by replicating a single element the given number of times.
68 replicatePA
:: PA a
=> Int :-> a
:-> PArray a
69 {-# INLINE replicatePA #-}
70 replicatePA
= closure2 replicatePA_v replicatePA_l
72 replicatePA_v
:: PA a
=> Int -> a
-> PArray a
73 {-# INLINE_PA replicatePA_v #-}
74 replicatePA_v
(I
# n
#) x
= replicatePA
# n
# x
76 replicatePA_l
:: PA a
=> PArray
Int -> PArray a
-> PArray
(PArray a
)
77 {-# INLINE_PA replicatePA_l #-}
78 replicatePA_l
(PArray n
# (PInt ns
)) (PArray _ xs
)
79 = PArray n
# (PNested segd
(replicatelPD segd xs
))
81 segd
= U
.lengthsToSegd ns
84 -- singleton ------------------------------------------------------------------
85 -- | Produce an array containing a single element.
86 singletonPA
:: PA a
=> a
:-> PArray a
87 {-# INLINE singletonPA #-}
88 singletonPA
= closure1 singletonPA_v singletonPA_l
90 singletonPA_v
:: PA a
=> a
-> PArray a
91 {-# INLINE_PA singletonPA_v #-}
92 singletonPA_v x
= replicatePA_v
1 x
94 singletonPA_l
:: PA a
=> PArray a
-> PArray
(PArray a
)
95 {-# INLINE_PA singletonPA_l #-}
96 singletonPA_l
(PArray n
# xs
)
97 = PArray n
# (PNested
(U
.mkSegd
(U
.replicate (I
# n
#) 1)
98 (U
.enumFromStepLen
0 1 (I
# n
#))
103 -- map ------------------------------------------------------------------------
104 -- | Apply a worker function to each element of an array, yielding a new array.
105 mapPA
:: (PA a
, PA b
) => (a
:-> b
) :-> PArray a
:-> PArray b
107 mapPA
= closure2 mapPA_v mapPA_l
109 -- | When performing a map we `replicate` the function into an array, then use
110 -- lifted-application to apply each function to its corresponding argument.
112 -- Note that this is a virtual replicate only, meaning that we can use
113 -- the same vectorised and lifted worker functions, provided we replicate
114 -- the environment part of the closure. The instance for repliatePA# in
115 -- PRepr class does exactly this, and it's defined in
116 -- "Data.Array.Parallel.Lifted.Closure".
118 mapPA_v
:: (PA a
, PA b
) => (a
:-> b
) -> PArray a
-> PArray b
119 {-# INLINE_PA mapPA_v #-}
120 mapPA_v f
as = replicatePA
# (lengthPA
# as) f
$:^
as
122 mapPA_l
:: (PA a
, PA b
)
123 => PArray
(a
:-> b
) -> PArray
(PArray a
) -> PArray
(PArray b
)
124 {-# INLINE_PA mapPA_l #-}
125 mapPA_l
(PArray n
# clo
) (PArray _ xss
)
127 $ case xss
of { PNested segd xs
->
129 $ liftedApply
(case U
.elementsSegd segd
of { I
# k
# -> k
# })
130 (replicatelPD segd clo
)
134 -- crossMap -------------------------------------------------------------------
135 -- TODO: What does this do?
136 crossMapPA
:: (PA a
, PA b
) => (PArray a
:-> (a
:-> PArray b
) :-> PArray
(a
,b
))
137 {-# INLINE crossMapPA #-}
138 crossMapPA
= closure2 crossMapPA_v crossMapPA_l
140 crossMapPA_v
:: (PA a
, PA b
) => PArray a
-> (a
:-> PArray b
) -> PArray
(a
,b
)
141 {-# INLINE_PA crossMapPA_v #-}
143 = zipPA
# (replicatelPA
# (segdPA
# bss
) as) (concatPA
# bss
)
147 crossMapPA_l
:: (PA a
, PA b
)
149 -> PArray
(a
:-> PArray b
)
150 -> PArray
(PArray
(a
,b
))
151 {-# INLINE_PA crossMapPA_l #-}
152 crossMapPA_l ass fs
= copySegdPA
# bss
(zipPA
# as' (concatPA
# bss
))
154 bsss
= mapPA_l fs ass
155 bss
= concatPA_l bsss
156 as' = replicatelPA
# (segdPA
# (concatPA
# bsss
)) (concatPA
# ass
)
159 -- zip ------------------------------------------------------------------------
160 -- |Turns a tuple of arrays into an array of the corresponding tuples.
162 -- If one array is short, excess elements of the longer array are discarded.
164 zipPA
:: (PA a
, PA b
) => PArray a
:-> PArray b
:-> PArray
(a
, b
)
166 zipPA
= closure2 zipPA_v zipPA_l
168 zipPA_v
:: (PA a
, PA b
) => PArray a
-> PArray b
-> PArray
(a
, b
)
169 {-# INLINE_PA zipPA_v #-}
170 zipPA_v xs ys
= zipPA
# xs ys
172 zipPA_l
:: (PA a
, PA b
)
173 => PArray
(PArray a
) -> PArray
(PArray b
) -> PArray
(PArray
(a
, b
))
174 {-# INLINE_PA zipPA_l #-}
175 zipPA_l
(PArray n
# (PNested segd xs
)) (PArray _
(PNested _ ys
))
176 = PArray n
# (PNested segd
(P_2 xs ys
))
179 zip3PA
:: (PA a
, PA b
, PA c
) => PArray a
:-> PArray b
:-> PArray c
:-> PArray
(a
, b
, c
)
180 {-# INLINE zip3PA #-}
181 zip3PA
= closure3 zip3PA_v zip3PA_l
183 zip3PA_v
:: (PA a
, PA b
, PA c
) => PArray a
-> PArray b
-> PArray c
-> PArray
(a
, b
, c
)
184 {-# INLINE_PA zip3PA_v #-}
185 zip3PA_v xs ys
= zip3PA
# xs ys
187 zip3PA_l
:: (PA a
, PA b
, PA c
)
188 => PArray
(PArray a
) -> PArray
(PArray b
) -> PArray
(PArray c
) -> PArray
(PArray
(a
, b
, c
))
189 {-# INLINE_PA zip3PA_l #-}
190 zip3PA_l
(PArray n
# (PNested segd xs
)) (PArray _
(PNested _ ys
)) (PArray _
(PNested _ zs
))
191 = PArray n
# (PNested segd
(P_3 xs ys zs
))
194 -- zipWith --------------------------------------------------------------------
195 -- |Map a function over multiple arrays at once.
197 zipWithPA
:: (PA a
, PA b
, PA c
)
198 => (a
:-> b
:-> c
) :-> PArray a
:-> PArray b
:-> PArray c
199 {-# INLINE zipWithPA #-}
200 zipWithPA
= closure3 zipWithPA_v zipWithPA_l
202 zipWithPA_v
:: (PA a
, PA b
, PA c
)
203 => (a
:-> b
:-> c
) -> PArray a
-> PArray b
-> PArray c
204 {-# INLINE_PA zipWithPA_v #-}
205 zipWithPA_v f
as bs
= replicatePA
# (lengthPA
# as) f
$:^
as $:^ bs
207 zipWithPA_l
:: (PA a
, PA b
, PA c
)
208 => PArray
(a
:-> b
:-> c
) -> PArray
(PArray a
) -> PArray
(PArray b
)
210 {-# INLINE_PA zipWithPA_l #-}
211 zipWithPA_l fs ass bss
213 (replicatelPA
# (segdPA
# ass
) fs
$:^ concatPA
# ass
$:^ concatPA
# bss
)
216 zipWith3PA
:: (PA a
, PA b
, PA c
, PA d
)
217 => (a
:-> b
:-> c
:-> d
) :-> PArray a
:-> PArray b
:-> PArray c
:-> PArray d
218 {-# INLINE zipWith3PA #-}
219 zipWith3PA
= closure4 zipWith3PA_v zipWith3PA_l
221 zipWith3PA_v
:: (PA a
, PA b
, PA c
, PA d
)
222 => (a
:-> b
:-> c
:-> d
) -> PArray a
-> PArray b
-> PArray c
-> PArray d
223 {-# INLINE_PA zipWith3PA_v #-}
224 zipWith3PA_v f
as bs cs
= replicatePA
# (lengthPA
# as) f
$:^
as $:^ bs
$:^ cs
226 zipWith3PA_l
:: (PA a
, PA b
, PA c
, PA d
)
227 => PArray
(a
:-> b
:-> c
:-> d
)
228 -> PArray
(PArray a
) -> PArray
(PArray b
) -> PArray
(PArray c
)
230 {-# INLINE_PA zipWith3PA_l #-}
231 zipWith3PA_l fs ass bss css
233 (replicatelPA
# (segdPA
# ass
) fs
$:^ concatPA
# ass
$:^ concatPA
# bss
$:^ concatPA
# css
)
236 -- unzip ----------------------------------------------------------------------
237 -- |Transform an array of tuples into a tuple of arrays.
239 unzipPA
:: (PA a
, PA b
) => PArray
(a
, b
) :-> (PArray a
, PArray b
)
240 {-# INLINE unzipPA #-}
241 unzipPA
= closure1 unzipPA_v unzipPA_l
243 unzipPA_v
:: (PA a
, PA b
) => PArray
(a
, b
) -> (PArray a
, PArray b
)
244 {-# INLINE_PA unzipPA_v #-}
245 unzipPA_v
abs' = unzipPA
# abs'
247 unzipPA_l
:: (PA a
, PA b
) => PArray
(PArray
(a
, b
)) -> PArray
(PArray a
, PArray b
)
248 {-# INLINE_PA unzipPA_l #-}
249 unzipPA_l xyss
= zipPA
# (copySegdPA
# xyss xs
) (copySegdPA
# xyss ys
)
251 (xs
, ys
) = unzipPA
# (concatPA
# xyss
)
253 unzip3PA
:: (PA a
, PA b
, PA c
) => PArray
(a
, b
, c
) :-> (PArray a
, PArray b
, PArray c
)
254 {-# INLINE unzip3PA #-}
255 unzip3PA
= closure1 unzip3PA_v unzip3PA_l
257 unzip3PA_v
:: (PA a
, PA b
, PA c
) => PArray
(a
, b
, c
) -> (PArray a
, PArray b
, PArray c
)
258 {-# INLINE_PA unzip3PA_v #-}
259 unzip3PA_v
abs' = unzip3PA
# abs'
261 unzip3PA_l
:: (PA a
, PA b
) => PArray
(PArray
(a
, b
, c
)) -> PArray
(PArray a
, PArray b
, PArray c
)
262 {-# INLINE_PA unzip3PA_l #-}
263 unzip3PA_l xyzss
= zip3PA
# (copySegdPA
# xyzss xs
) (copySegdPA
# xyzss ys
) (copySegdPA
# xyzss zs
)
265 (xs
, ys
, zs
) = unzip3PA
# (concatPA
# xyzss
)
268 -- packPA ---------------------------------------------------------------------
269 -- | Select the elements of an array that have their tag set as True.
272 -- packPA [12, 24, 42, 93] [True, False, False, True]
276 packPA
:: PA a
=> PArray a
:-> PArray
Bool :-> PArray a
277 {-# INLINE packPA #-}
278 packPA
= closure2 packPA_v packPA_l
280 packPA_v
:: PA a
=> PArray a
-> PArray
Bool -> PArray a
281 {-# INLINE_PA packPA_v #-}
283 = packByTagPA
# xs
(elementsSel2_1
# sel
) (U
.tagsSel2 sel
) 1#
288 => PArray
(PArray a
) -> PArray
(PArray
Bool) -> PArray
(PArray a
)
289 {-# INLINE_PA packPA_l #-}
290 packPA_l
(PArray n
# xss
) (PArray _ bss
)
292 $ case xss
of { PNested segd xs
->
293 case bss
of { PNested _
(PBool sel
) ->
294 PNested
(U
.lengthsToSegd
$ U
.count_s segd
(U
.tagsSel2 sel
) 1)
295 $ packByTagPD xs
(elementsSel2_1
# sel
) (U
.tagsSel2 sel
) 1# }}
297 boolSel
:: PArray
Bool -> U
.Sel2
298 {-# INLINE boolSel #-}
299 boolSel
(PArray _
(PBool sel
)) = sel
302 -- combine --------------------------------------------------------------------
303 -- | Combine two arrays, using a tag array to tell us where to get each element from.
305 -- @combine2 [1,2,3] [4,5,6] [T,F,F,T,T,F] = [1,4,5,2,3,6]@
307 -- TODO: should the selector be a boolean array?
309 combine2PA
:: PA a
=> PArray a
:-> PArray a
:-> PArray Tag
:-> PArray a
310 {-# INLINE_PA combine2PA #-}
311 combine2PA
= closure3 combine2PA_v combine2PA_l
313 combine2PA_v
:: PA a
=> PArray a
-> PArray a
-> PArray Tag
-> PArray a
314 {-# INLINE_PA combine2PA_v #-}
315 combine2PA_v xs ys bs
316 = combine2PA
# (lengthPA
# xs
+# lengthPA
# ys
)
317 (U
.tagsToSel2
(toUArrPA bs
))
322 => PArray
(PArray a
) -> PArray
(PArray a
)
323 -> PArray
(PArray Tag
)
325 {-# INLINE_PA combine2PA_l #-}
327 = error "dph-common:Data.Array.Parallel.Lifted.Combinators: combinePA_l isn't implemented"
330 -- filter ---------------------------------------------------------------------
331 -- | Extract the elements from an array that match the given predicate.
332 filterPA
:: PA a
=> (a
:-> Bool) :-> PArray a
:-> PArray a
333 {-# INLINE filterPA #-}
334 filterPA
= closure2 filterPA_v filterPA_l
336 filterPA_v
:: PA a
=> (a
:-> Bool) -> PArray a
-> PArray a
337 {-# INLINE_PA filterPA_v #-}
338 filterPA_v p xs
= packPA_v xs
(mapPA_v p xs
)
341 => PArray
(a
:-> Bool) -> PArray
(PArray a
) -> PArray
(PArray a
)
342 {-# INLINE_PA filterPA_l #-}
343 filterPA_l ps xss
= packPA_l xss
(mapPA_l ps xss
)
346 -- index ----------------------------------------------------------------------
347 -- | Retrieve the array element with the given index.
348 indexPA
:: PA a
=> PArray a
:-> Int :-> a
349 {-# INLINE indexPA #-}
350 indexPA
= closure2 indexPA_v indexPA_l
352 indexPA_v
:: PA a
=> PArray a
-> Int -> a
353 {-# INLINE_PA indexPA_v #-}
354 indexPA_v xs
(I
# i
#) = indexPA
# xs i
#
356 indexPA_l
:: PA a
=> PArray
(PArray a
) -> PArray
Int -> PArray a
357 {-# INLINE_PA indexPA_l #-}
358 indexPA_l
(PArray _
(PNested segd xs
)) (PArray n
# is
)
361 (U
.zipWith (+) (U
.indicesSegd segd
)
362 (fromScalarPData is
))
365 -- concat ---------------------------------------------------------------------
366 -- | Concatenate an array of arrays into a single array.
367 concatPA
:: PA a
=> PArray
(PArray a
) :-> PArray a
368 {-# INLINE concatPA #-}
369 concatPA
= closure1 concatPA_v concatPA_l
371 concatPA_v
:: PA a
=> PArray
(PArray a
) -> PArray a
372 {-# INLINE_PA concatPA_v #-}
373 concatPA_v xss
= concatPA
# xss
375 concatPA_l
:: PA a
=> PArray
(PArray
(PArray a
)) -> PArray
(PArray a
)
376 {-# INLINE_PA concatPA_l #-}
377 concatPA_l
(PArray m
# (PNested segd1
(PNested segd2 xs
)))
379 (PNested
(U
.mkSegd
(U
.sum_s segd1
(U
.lengthsSegd segd2
))
380 (U
.bpermute
(U
.indicesSegd segd2
) (U
.indicesSegd segd1
))
381 (U
.elementsSegd segd2
))
385 -- app (append) ---------------------------------------------------------------
386 -- | Append two arrays.
387 appPA
:: PA a
=> PArray a
:-> PArray a
:-> PArray a
389 appPA
= closure2 appPA_v appPA_l
391 appPA_v
:: PA a
=> PArray a
-> PArray a
-> PArray a
392 {-# INLINE_PA appPA_v #-}
393 appPA_v xs ys
= appPA
# xs ys
395 appPA_l
:: PA a
=> PArray
(PArray a
) -> PArray
(PArray a
) -> PArray
(PArray a
)
396 {-# INLINE_PA appPA_l #-}
397 appPA_l
(PArray m
# pxss
) (PArray n
# pyss
)
399 $ case pxss
of { PNested xsegd xs
->
400 case pyss
of { PNested ysegd ys
->
402 segd
= U
.plusSegd xsegd ysegd
404 PNested segd
(applPD segd xsegd xs ysegd ys
) }}
407 -- enumFromTo -----------------------------------------------------------------
408 -- | Produce a range of integers.
409 enumFromToPA_Int
:: Int :-> Int :-> PArray
Int
410 {-# INLINE enumFromToPA_Int #-}
411 enumFromToPA_Int
= closure2 enumFromToPA_v enumFromToPA_l
413 enumFromToPA_v
:: Int -> Int -> PArray
Int
414 {-# INLINE_PA enumFromToPA_v #-}
415 enumFromToPA_v m n
= fromUArrPA
(distance m n
) (U
.enumFromTo m n
)
417 distance
:: Int -> Int -> Int
418 {-# INLINE_STREAM distance #-}
419 distance m n
= max 0 (n
- m
+ 1)
421 enumFromToPA_l
:: PArray
Int -> PArray
Int -> PArray
(PArray
Int)
422 {-# INLINE_PA enumFromToPA_l #-}
423 enumFromToPA_l
(PArray m
# ms
) (PArray _ ns
)
427 $ U
.enumFromStepLenEach
(U
.elementsSegd segd
)
428 (fromScalarPData ms
) (U
.replicate (U
.elementsSegd segd
) 1) lens
430 lens
= U
.zipWith distance
(fromScalarPData ms
) (fromScalarPData ns
)
431 segd
= U
.lengthsToSegd lens
434 -- indexed --------------------------------------------------------------------
435 -- | Tag each element of an array with its index.
437 -- @indexed [42, 93, 13] = [(0, 42), (1, 93), (2, 13)]@
439 indexedPA
:: PA a
=> PArray a
:-> PArray
(Int,a
)
440 {-# INLINE indexedPA #-}
441 indexedPA
= closure1 indexedPA_v indexedPA_l
443 indexedPA_v
:: PA a
=> PArray a
-> PArray
(Int,a
)
444 {-# INLINE indexedPA_v #-}
445 indexedPA_v
(PArray n
# xs
)
446 = PArray n
# (P_2
(toScalarPData
$ U
.enumFromStepLen
0 1 (I
# n
#)) xs
)
448 indexedPA_l
:: PA a
=> PArray
(PArray a
) -> PArray
(PArray
(Int,a
))
449 {-# INLINE indexedPA_l #-}
450 indexedPA_l
(PArray n
# xss
)
452 $ case xss
of { PNested segd xs
->
453 PNested segd
(P_2
(toScalarPData
$ U
.indices_s segd
) xs
) }
456 -- slice ----------------------------------------------------------------------
457 -- | Extract a subrange of elements from an array.
458 -- The first argument is the starting index, while the second is the
459 -- length of the slice.
461 slicePA
:: PA a
=> Int :-> Int :-> PArray a
:-> PArray a
462 {-# INLINE slicePA #-}
463 slicePA
= closure3 slicePA_v slicePA_l
465 slicePA_v
:: PA a
=> Int -> Int -> PArray a
-> PArray a
466 {-# INLINE slicePA_v #-}
467 slicePA_v
(I
# from
) (I
# len
) xs
468 = extractPA
# xs from len
470 -- TODO: Can we define this in terms of extractPA?
471 slicePA_l
:: PA a
=> PArray
Int -> PArray
Int -> PArray
(PArray a
) -> PArray
(PArray a
)
472 {-# INLINE slicePA_l #-}
473 slicePA_l
(PArray n
# is
) (PArray _ lens
) (PArray _ xss
)
475 $ case xss
of { PNested segd xs
->
477 $ bpermutePD xs
(elementsSegd
# segd
')
478 (U
.zipWith (+) (U
.indices_s segd
')
480 (U
.zipWith (+) (fromScalarPData is
)
481 (U
.indicesSegd segd
)))) }
483 segd
' = U
.lengthsToSegd
(fromScalarPData lens
)
487 -- update ---------------------------------------------------------------------
488 -- | Copy the source array in the destination, using new values for the given indices.
489 updatePA
:: PA a
=> PArray a
:-> PArray
(Int,a
) :-> PArray a
490 {-# INLINE updatePA #-}
491 updatePA
= closure2 updatePA_v updatePA_l
493 updatePA_v
:: PA a
=> PArray a
-> PArray
(Int,a
) -> PArray a
494 {-# INLINE_PA updatePA_v #-}
495 updatePA_v xs
(PArray n
# (P_2 is ys
))
496 = updatePA
# xs
(fromScalarPData is
) (PArray n
# ys
)
499 :: PA a
=> PArray
(PArray a
) -> PArray
(PArray
(Int,a
)) -> PArray
(PArray a
)
500 {-# INLINE_PA updatePA_l #-}
501 updatePA_l
(PArray m
# xss
) (PArray _ pss
)
503 $ case xss
of { PNested segd xs
->
504 case pss
of { PNested segd
' (P_2 is ys
) ->
506 $ updatePD xs
(U
.zipWith (+) (fromScalarPData is
)
507 (U
.replicate_s segd
' (U
.indicesSegd segd
)))
511 -- bpermute -------------------------------------------------------------------
512 -- | Backwards permutation of array elements.
514 -- @bpermute [50, 60, 20, 30] [0, 3, 2] = [50, 30, 20]@
516 bpermutePA
:: PA a
=> PArray a
:-> PArray
Int :-> PArray a
517 {-# INLINE bpermutePA #-}
518 bpermutePA
= closure2 bpermutePA_v bpermutePA_l
520 bpermutePA_v
:: PA a
=> PArray a
-> PArray
Int -> PArray a
521 {-# INLINE_PA bpermutePA_v #-}
522 bpermutePA_v xs
(PArray n
# is
) = bpermutePA
# xs n
# (fromScalarPData is
)
524 bpermutePA_l
:: PA a
=> PArray
(PArray a
) -> PArray
(PArray
Int) -> PArray
(PArray a
)
525 {-# INLINE_PA bpermutePA_l #-}
526 bpermutePA_l
(PArray _ xss
) (PArray n
# iss
)
528 $ case xss
of { PNested segd xs
->
529 case iss
of { PNested isegd is
->
531 $ bpermutePD xs
(elementsSegd
# isegd
)
532 (U
.zipWith (+) (fromScalarPData is
)
533 (U
.replicate_s isegd
(U
.indicesSegd segd
))) }}