Revert rename of dph-common for now
[packages/dph.git] / dph-common / Data / Array / Parallel / Lifted / Combinators.hs
1 {-# LANGUAGE CPP, BangPatterns #-}
2
3 #include "fusion-phases.h"
4
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
8 --
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.
12 --
13 -- The *PA_l version is the "lifted" version that also works
14 -- on arrays of arrays.
15 --
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"
20 --
21 -- TODO: combine2PA_l isn't implemented and will just `error` if you
22 -- try to use it. None of our benchmarks do yet...
23 --
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,
29
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
34 ) where
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
42
43 import qualified Data.Array.Parallel.Unlifted as U
44 import Data.Array.Parallel.Base (Tag)
45
46 import GHC.Exts (Int(..), (+#))
47
48
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
54
55 lengthPA_v :: PA a => PArray a -> Int
56 {-# INLINE_PA lengthPA_v #-}
57 lengthPA_v xs = I# (lengthPA# xs)
58
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)
62 where
63 segd = segdPA# xss
64
65
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
71
72 replicatePA_v :: PA a => Int -> a -> PArray a
73 {-# INLINE_PA replicatePA_v #-}
74 replicatePA_v (I# n#) x = replicatePA# n# x
75
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))
80 where
81 segd = U.lengthsToSegd ns
82
83
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
89
90 singletonPA_v :: PA a => a -> PArray a
91 {-# INLINE_PA singletonPA_v #-}
92 singletonPA_v x = replicatePA_v 1 x
93
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#))
99 (I# n#))
100 xs)
101
102
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
106 {-# INLINE mapPA #-}
107 mapPA = closure2 mapPA_v mapPA_l
108
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.
111 --
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".
117 --
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
121
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)
126 = PArray n#
127 $ case xss of { PNested segd xs ->
128 PNested segd
129 $ liftedApply (case U.elementsSegd segd of { I# k# -> k# })
130 (replicatelPD segd clo)
131 xs }
132
133
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
139
140 crossMapPA_v :: (PA a, PA b) => PArray a -> (a :-> PArray b) -> PArray (a,b)
141 {-# INLINE_PA crossMapPA_v #-}
142 crossMapPA_v as f
143 = zipPA# (replicatelPA# (segdPA# bss) as) (concatPA# bss)
144 where
145 bss = mapPA_v f as
146
147 crossMapPA_l :: (PA a, PA b)
148 => PArray (PArray a)
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))
153 where
154 bsss = mapPA_l fs ass
155 bss = concatPA_l bsss
156 as' = replicatelPA# (segdPA# (concatPA# bsss)) (concatPA# ass)
157
158
159 -- zip ------------------------------------------------------------------------
160 -- |Turns a tuple of arrays into an array of the corresponding tuples.
161 --
162 -- If one array is short, excess elements of the longer array are discarded.
163
164 zipPA :: (PA a, PA b) => PArray a :-> PArray b :-> PArray (a, b)
165 {-# INLINE zipPA #-}
166 zipPA = closure2 zipPA_v zipPA_l
167
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
171
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))
177
178
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
182
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
186
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))
192
193
194 -- zipWith --------------------------------------------------------------------
195 -- |Map a function over multiple arrays at once.
196
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
201
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
206
207 zipWithPA_l :: (PA a, PA b, PA c)
208 => PArray (a :-> b :-> c) -> PArray (PArray a) -> PArray (PArray b)
209 -> PArray (PArray c)
210 {-# INLINE_PA zipWithPA_l #-}
211 zipWithPA_l fs ass bss
212 = copySegdPA# ass
213 (replicatelPA# (segdPA# ass) fs $:^ concatPA# ass $:^ concatPA# bss)
214
215
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
220
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
225
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)
229 -> PArray (PArray d)
230 {-# INLINE_PA zipWith3PA_l #-}
231 zipWith3PA_l fs ass bss css
232 = copySegdPA# ass
233 (replicatelPA# (segdPA# ass) fs $:^ concatPA# ass $:^ concatPA# bss $:^ concatPA# css)
234
235
236 -- unzip ----------------------------------------------------------------------
237 -- |Transform an array of tuples into a tuple of arrays.
238
239 unzipPA :: (PA a, PA b) => PArray (a, b) :-> (PArray a, PArray b)
240 {-# INLINE unzipPA #-}
241 unzipPA = closure1 unzipPA_v unzipPA_l
242
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'
246
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)
250 where
251 (xs, ys) = unzipPA# (concatPA# xyss)
252
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
256
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'
260
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)
264 where
265 (xs, ys, zs) = unzip3PA# (concatPA# xyzss)
266
267
268 -- packPA ---------------------------------------------------------------------
269 -- | Select the elements of an array that have their tag set as True.
270 --
271 -- @
272 -- packPA [12, 24, 42, 93] [True, False, False, True]
273 -- = [24, 42]
274 -- @
275 --
276 packPA :: PA a => PArray a :-> PArray Bool :-> PArray a
277 {-# INLINE packPA #-}
278 packPA = closure2 packPA_v packPA_l
279
280 packPA_v :: PA a => PArray a -> PArray Bool -> PArray a
281 {-# INLINE_PA packPA_v #-}
282 packPA_v xs bs
283 = packByTagPA# xs (elementsSel2_1# sel) (U.tagsSel2 sel) 1#
284 where
285 sel = boolSel bs
286
287 packPA_l :: PA a
288 => PArray (PArray a) -> PArray (PArray Bool) -> PArray (PArray a)
289 {-# INLINE_PA packPA_l #-}
290 packPA_l (PArray n# xss) (PArray _ bss)
291 = PArray n#
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# }}
296
297 boolSel :: PArray Bool -> U.Sel2
298 {-# INLINE boolSel #-}
299 boolSel (PArray _ (PBool sel)) = sel
300
301
302 -- combine --------------------------------------------------------------------
303 -- | Combine two arrays, using a tag array to tell us where to get each element from.
304 --
305 -- @combine2 [1,2,3] [4,5,6] [T,F,F,T,T,F] = [1,4,5,2,3,6]@
306 --
307 -- TODO: should the selector be a boolean array?
308 --
309 combine2PA:: PA a => PArray a :-> PArray a :-> PArray Tag :-> PArray a
310 {-# INLINE_PA combine2PA #-}
311 combine2PA = closure3 combine2PA_v combine2PA_l
312
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))
318 xs ys
319
320 combine2PA_l
321 :: PA a
322 => PArray (PArray a) -> PArray (PArray a)
323 -> PArray (PArray Tag)
324 -> PArray (PArray a)
325 {-# INLINE_PA combine2PA_l #-}
326 combine2PA_l _ _ _
327 = error "dph-common:Data.Array.Parallel.Lifted.Combinators: combinePA_l isn't implemented"
328
329
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
335
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)
339
340 filterPA_l :: PA a
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)
344
345
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
351
352 indexPA_v :: PA a => PArray a -> Int -> a
353 {-# INLINE_PA indexPA_v #-}
354 indexPA_v xs (I# i#) = indexPA# xs i#
355
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)
359 = PArray n#
360 $ bpermutePD xs n#
361 (U.zipWith (+) (U.indicesSegd segd)
362 (fromScalarPData is))
363
364
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
370
371 concatPA_v :: PA a => PArray (PArray a) -> PArray a
372 {-# INLINE_PA concatPA_v #-}
373 concatPA_v xss = concatPA# xss
374
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)))
378 = PArray m#
379 (PNested (U.mkSegd (U.sum_s segd1 (U.lengthsSegd segd2))
380 (U.bpermute (U.indicesSegd segd2) (U.indicesSegd segd1))
381 (U.elementsSegd segd2))
382 xs)
383
384
385 -- app (append) ---------------------------------------------------------------
386 -- | Append two arrays.
387 appPA :: PA a => PArray a :-> PArray a :-> PArray a
388 {-# INLINE appPA #-}
389 appPA = closure2 appPA_v appPA_l
390
391 appPA_v :: PA a => PArray a -> PArray a -> PArray a
392 {-# INLINE_PA appPA_v #-}
393 appPA_v xs ys = appPA# xs ys
394
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)
398 = PArray (m# +# n#)
399 $ case pxss of { PNested xsegd xs ->
400 case pyss of { PNested ysegd ys ->
401 let
402 segd = U.plusSegd xsegd ysegd
403 in
404 PNested segd (applPD segd xsegd xs ysegd ys) }}
405
406
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
412
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)
416
417 distance :: Int -> Int -> Int
418 {-# INLINE_STREAM distance #-}
419 distance m n = max 0 (n - m + 1)
420
421 enumFromToPA_l :: PArray Int -> PArray Int -> PArray (PArray Int)
422 {-# INLINE_PA enumFromToPA_l #-}
423 enumFromToPA_l (PArray m# ms) (PArray _ ns)
424 = PArray m#
425 $ PNested segd
426 $ toScalarPData
427 $ U.enumFromStepLenEach (U.elementsSegd segd)
428 (fromScalarPData ms) (U.replicate (U.elementsSegd segd) 1) lens
429 where
430 lens = U.zipWith distance (fromScalarPData ms) (fromScalarPData ns)
431 segd = U.lengthsToSegd lens
432
433
434 -- indexed --------------------------------------------------------------------
435 -- | Tag each element of an array with its index.
436 --
437 -- @indexed [42, 93, 13] = [(0, 42), (1, 93), (2, 13)]@
438 --
439 indexedPA :: PA a => PArray a :-> PArray (Int,a)
440 {-# INLINE indexedPA #-}
441 indexedPA = closure1 indexedPA_v indexedPA_l
442
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)
447
448 indexedPA_l :: PA a => PArray (PArray a) -> PArray (PArray (Int,a))
449 {-# INLINE indexedPA_l #-}
450 indexedPA_l (PArray n# xss)
451 = PArray n#
452 $ case xss of { PNested segd xs ->
453 PNested segd (P_2 (toScalarPData $ U.indices_s segd) xs) }
454
455
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.
460 --
461 slicePA :: PA a => Int :-> Int :-> PArray a :-> PArray a
462 {-# INLINE slicePA #-}
463 slicePA = closure3 slicePA_v slicePA_l
464
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
469
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)
474 = PArray n#
475 $ case xss of { PNested segd xs ->
476 PNested segd'
477 $ bpermutePD xs (elementsSegd# segd')
478 (U.zipWith (+) (U.indices_s segd')
479 (U.replicate_s segd'
480 (U.zipWith (+) (fromScalarPData is)
481 (U.indicesSegd segd)))) }
482 where
483 segd' = U.lengthsToSegd (fromScalarPData lens)
484
485
486
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
492
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)
497
498 updatePA_l
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)
502 = PArray m#
503 $ case xss of { PNested segd xs ->
504 case pss of { PNested segd' (P_2 is ys) ->
505 PNested segd
506 $ updatePD xs (U.zipWith (+) (fromScalarPData is)
507 (U.replicate_s segd' (U.indicesSegd segd)))
508 ys }}
509
510
511 -- bpermute -------------------------------------------------------------------
512 -- | Backwards permutation of array elements.
513 --
514 -- @bpermute [50, 60, 20, 30] [0, 3, 2] = [50, 30, 20]@
515 --
516 bpermutePA :: PA a => PArray a :-> PArray Int :-> PArray a
517 {-# INLINE bpermutePA #-}
518 bpermutePA = closure2 bpermutePA_v bpermutePA_l
519
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)
523
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)
527 = PArray n#
528 $ case xss of { PNested segd xs ->
529 case iss of { PNested isegd is ->
530 PNested isegd
531 $ bpermutePD xs (elementsSegd# isegd)
532 (U.zipWith (+) (fromScalarPData is)
533 (U.replicate_s isegd (U.indicesSegd segd))) }}
534
535