-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | An embedded language for accelerated array processing -- -- Data.Array.Accelerate defines an embedded array language for -- computations for high-performance computing in Haskell. Computations -- on multi-dimensional, regular arrays are expressed in the form of -- parameterised collective operations, such as maps, reductions, and -- permutations. These computations may then be online compiled and -- executed on a range of architectures. -- --
-- dotp :: Acc (Vector Float) -> Acc (Vector Float) -> Acc (Scalar Float) -- dotp xs ys = fold (+) 0 (zipWith (*) xs ys) ---- -- Except for the type, this code is almost the same as the corresponding -- Haskell code on lists of floats. The types indicate that the -- computation may be online-compiled for performance - for example, -- using Data.Array.Accelerate.LLVM.PTX it may be on-the-fly -- off-loaded to the GPU. -- --
-- logBase2 x = finiteBitSize x - 1 - countLeadingZeros x --countLeadingZeros :: FiniteBits b => Exp b -> Exp Int -- | Count the number of zero bits following the least significant set bit. -- The related find-first-set operation can be expressed in terms -- of this as: -- --
-- findFirstSet x = 1 + countTrailingZeros x --countTrailingZeros :: FiniteBits b => Exp b -> Exp Int instance Data.Array.Accelerate.Data.Bits.Bits GHC.Types.Bool instance Data.Array.Accelerate.Data.Bits.Bits GHC.Types.Int instance Data.Array.Accelerate.Data.Bits.Bits GHC.Int.Int8 instance Data.Array.Accelerate.Data.Bits.Bits GHC.Int.Int16 instance Data.Array.Accelerate.Data.Bits.Bits GHC.Int.Int32 instance Data.Array.Accelerate.Data.Bits.Bits GHC.Int.Int64 instance Data.Array.Accelerate.Data.Bits.Bits GHC.Types.Word instance Data.Array.Accelerate.Data.Bits.Bits GHC.Word.Word8 instance Data.Array.Accelerate.Data.Bits.Bits GHC.Word.Word16 instance Data.Array.Accelerate.Data.Bits.Bits GHC.Word.Word32 instance Data.Array.Accelerate.Data.Bits.Bits GHC.Word.Word64 instance Data.Array.Accelerate.Data.Bits.Bits Foreign.C.Types.CInt instance Data.Array.Accelerate.Data.Bits.Bits Foreign.C.Types.CUInt instance Data.Array.Accelerate.Data.Bits.Bits Foreign.C.Types.CLong instance Data.Array.Accelerate.Data.Bits.Bits Foreign.C.Types.CULong instance Data.Array.Accelerate.Data.Bits.Bits Foreign.C.Types.CLLong instance Data.Array.Accelerate.Data.Bits.Bits Foreign.C.Types.CULLong instance Data.Array.Accelerate.Data.Bits.Bits Foreign.C.Types.CShort instance Data.Array.Accelerate.Data.Bits.Bits Foreign.C.Types.CUShort instance Data.Array.Accelerate.Data.Bits.FiniteBits GHC.Types.Bool instance Data.Array.Accelerate.Data.Bits.FiniteBits GHC.Types.Int instance Data.Array.Accelerate.Data.Bits.FiniteBits GHC.Int.Int8 instance Data.Array.Accelerate.Data.Bits.FiniteBits GHC.Int.Int16 instance Data.Array.Accelerate.Data.Bits.FiniteBits GHC.Int.Int32 instance Data.Array.Accelerate.Data.Bits.FiniteBits GHC.Int.Int64 instance Data.Array.Accelerate.Data.Bits.FiniteBits GHC.Types.Word instance Data.Array.Accelerate.Data.Bits.FiniteBits GHC.Word.Word8 instance Data.Array.Accelerate.Data.Bits.FiniteBits GHC.Word.Word16 instance Data.Array.Accelerate.Data.Bits.FiniteBits GHC.Word.Word32 instance Data.Array.Accelerate.Data.Bits.FiniteBits GHC.Word.Word64 instance Data.Array.Accelerate.Data.Bits.FiniteBits Foreign.C.Types.CInt instance Data.Array.Accelerate.Data.Bits.FiniteBits Foreign.C.Types.CUInt instance Data.Array.Accelerate.Data.Bits.FiniteBits Foreign.C.Types.CLong instance Data.Array.Accelerate.Data.Bits.FiniteBits Foreign.C.Types.CULong instance Data.Array.Accelerate.Data.Bits.FiniteBits Foreign.C.Types.CLLong instance Data.Array.Accelerate.Data.Bits.FiniteBits Foreign.C.Types.CULLong instance Data.Array.Accelerate.Data.Bits.FiniteBits Foreign.C.Types.CShort instance Data.Array.Accelerate.Data.Bits.FiniteBits Foreign.C.Types.CUShort -- | Complex numbers module Data.Array.Accelerate.Data.Complex -- | Complex numbers are an algebraic type. -- -- For a complex number z, abs z is a number -- with the magnitude of z, but oriented in the positive real -- direction, whereas signum z has the phase of -- z, but unit magnitude. -- -- The Foldable and Traversable instances traverse the real -- part first. data Complex a :: * -> * -- | forms a complex number from its real and imaginary rectangular -- components. (:+) :: ~a -> ~a -> Complex a -- | Return the real part of a complex number real :: Elt a => Exp (Complex a) -> Exp a -- | Return the imaginary part of a complex number imag :: Elt a => Exp (Complex a) -> Exp a -- | Form a complex number from polar components of magnitude and phase. mkPolar :: forall a. Floating a => Exp a -> Exp a -> Exp (Complex a) -- | cis t is a complex value with magnitude 1 and -- phase t (modulo 2*pi). cis :: forall a. Floating a => Exp a -> Exp (Complex a) -- | The function polar takes a complex number and returns a -- (magnitude, phase) pair in canonical form: the magnitude is -- non-negative, and the phase in the range (-pi, -- pi]; if the magnitude is zero, then so is the phase. polar :: RealFloat a => Exp (Complex a) -> Exp (a, a) -- | The non-negative magnitude of a complex number magnitude :: RealFloat a => Exp (Complex a) -> Exp a -- | The phase of a complex number, in the range (-pi, -- pi]. If the magnitude is zero, then so is the phase. phase :: RealFloat a => Exp (Complex a) -> Exp a -- | Return the complex conjugate of a complex number, defined as -- --
-- conjugate(Z) = X - iY --conjugate :: Num a => Exp (Complex a) -> Exp (Complex a) instance Data.Array.Accelerate.Array.Sugar.Elt a => Data.Array.Accelerate.Array.Sugar.Elt (Data.Complex.Complex a) instance cst a => Data.Array.Accelerate.Product.IsProduct cst (Data.Complex.Complex a) instance (Data.Array.Accelerate.Lift.Lift Data.Array.Accelerate.Smart.Exp a, Data.Array.Accelerate.Array.Sugar.Elt (Data.Array.Accelerate.Lift.Plain a)) => Data.Array.Accelerate.Lift.Lift Data.Array.Accelerate.Smart.Exp (Data.Complex.Complex a) instance Data.Array.Accelerate.Array.Sugar.Elt a => Data.Array.Accelerate.Lift.Unlift Data.Array.Accelerate.Smart.Exp (Data.Complex.Complex (Data.Array.Accelerate.Smart.Exp a)) instance Data.Array.Accelerate.Classes.Eq.Eq a => Data.Array.Accelerate.Classes.Eq.Eq (Data.Complex.Complex a) instance Data.Array.Accelerate.Classes.RealFloat.RealFloat a => GHC.Num.Num (Data.Array.Accelerate.Smart.Exp (Data.Complex.Complex a)) instance Data.Array.Accelerate.Classes.RealFloat.RealFloat a => GHC.Real.Fractional (Data.Array.Accelerate.Smart.Exp (Data.Complex.Complex a)) instance Data.Array.Accelerate.Classes.RealFloat.RealFloat a => GHC.Float.Floating (Data.Array.Accelerate.Smart.Exp (Data.Complex.Complex a)) instance (Data.Array.Accelerate.Classes.FromIntegral.FromIntegral a b, Data.Array.Accelerate.Classes.Num.Num b) => Data.Array.Accelerate.Classes.FromIntegral.FromIntegral a (Data.Complex.Complex b) -- | This interpreter is meant to be a reference implementation of the -- semantics of the embedded array language. The emphasis is on defining -- the semantics clearly, not on performance. module Data.Array.Accelerate.Interpreter -- | Arrays consists of nested tuples of individual Arrays, -- currently up to 15-elements wide. Accelerate computations can thereby -- return multiple results. class (Typeable a, Typeable (ArrRepr a)) => Arrays a -- | Run a complete embedded array program using the reference interpreter. run :: Arrays a => Acc a -> a -- | Prepare and run an embedded array program of one argument run1 :: (Arrays a, Arrays b) => (Acc a -> Acc b) -> a -> b -- | Data.Array.Accelerate defines an embedded language of array -- computations for high-performance computing in Haskell. Computations -- on multi-dimensional, regular arrays are expressed in the form of -- parameterised collective operations such as maps, reductions, and -- permutations. These computations are online compiled and can be -- executed on a range of architectures. -- --
-- ./foo +RTS -A64M -n2M -RTS ---- -- You can make these settings the default by adding the following -- ghc-options to your .cabal file or similar: -- --
-- ghc-options: -with-rtsopts=-n2M -with-rtsopts=-A64M ---- -- To specify RTS options you will also need to compile your program with -- -rtsopts. module Data.Array.Accelerate -- | Accelerate is an embedded language that distinguishes between -- vanilla arrays (e.g. in Haskell memory on the CPU) and embedded arrays -- (e.g. in device memory on a GPU), as well as the computations on both -- of these. Since Accelerate is an embedded language, programs written -- in Accelerate are not compiled by the Haskell compiler (GHC). Rather, -- each Accelerate backend is a runtime compiler which generates -- and executes parallel SIMD code of the target language at application -- runtime. -- -- The type constructor Acc represents embedded collective array -- operations. A term of type Acc a is an Accelerate program -- which, once executed, will produce a value of type a (an -- Array or a tuple of Arrays). Collective operations of -- type Acc a comprise many scalar expressions, wrapped -- in type constructor Exp, which will be executed in parallel. -- Although collective operations comprise many scalar operations -- executed in parallel, scalar operations cannot initiate new -- collective operations: this stratification between scalar operations -- in Exp and array operations in Acc helps statically -- exclude nested data parallelism, which is difficult to execute -- efficiently on constrained hardware such as GPUs. -- -- For example, to compute a vector dot product we could write: -- --
-- dotp :: Num a => Vector a -> Vector a -> Acc (Scalar a) -- dotp xs ys = -- let -- xs' = use xs -- ys' = use ys -- in -- fold (+) 0 ( zipWith (*) xs' ys' ) ---- -- The function dotp consumes two one-dimensional arrays -- (Vectors) of values, and produces a single (Scalar) -- result as output. As the return type is wrapped in the type -- Acc, we see that it is an embedded Accelerate computation - it -- will be evaluated in the object language of dynamically -- generated parallel code, rather than the meta language of -- vanilla Haskell. -- -- As the arguments to dotp are plain Haskell arrays, to make -- these available to Accelerate computations they must be embedded with -- the use function. -- -- An Accelerate backend is used to evaluate the embedded computation and -- return the result back to vanilla Haskell. Calling the run -- function of a backend will generate code for the target architecture, -- compile, and execute it. For example, the following backends are -- available: -- --
-- map -> reverse -> reshape -> map -> map ---- --
-- map -> backpermute -> -- zipWith -> map -- generate -> ---- -- If the consumer operation uses more than one element of the input -- array (typically, via generate indexing an array multiple -- times), then the input array will be completely evaluated first; no -- fusion occurs in this case, because fusing the first operation into -- the second implies duplicating work. -- -- On the other hand, collective operations can fuse their input arrays -- into themselves, but on output always evaluate to an array; collective -- operations will not be fused into a later step. For example: -- --
-- use -> -- zipWith -> fold |-> map -- generate -> ---- -- Here the element-wise sequence (use + generate + -- zipWith) will fuse into a single operation, which then fuses -- into the collective fold operation. At this point in the -- program the fold must now be evaluated. In the final step the -- map reads in the array produced by fold. As there is no -- fusion between the fold and map steps, this program -- consists of two "loops"; one for the use + generate + -- zipWith + fold step, and one for the final map -- step. -- -- You can see how many operations will be executed in the fused program -- by Show-ing the Acc program, or by using the debugging -- option -ddump-dot to save the program as a graphviz DOT file. -- -- As a special note, the operations unzip and reshape, -- when applied to a real array, are executed in constant time, so in -- this situation these operations will not be fused. -- --
-- >>> let mat = fromList (Z:.5:.10) [0..] -- -- >>> mat -- Matrix (Z :. 5 :. 10) -- [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49] ---- --
-- >>> mat ! Z:.1:.2 -- 12 --(!) :: (Shape sh, Elt e) => Acc (Array sh e) -> Exp sh -> Exp e infixl 9 ! -- | Extract the value from an array at the specified linear index. -- Multidimensional arrays in Accelerate are stored in row-major order -- with zero-based indexing. -- --
-- >>> let mat = fromList (Z:.5:.10) [0..] -- -- >>> mat -- Matrix (Z :. 5 :. 10) -- [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49] ---- --
-- >>> mat !! 12 -- 12 --(!!) :: (Shape sh, Elt e) => Acc (Array sh e) -> Exp Int -> Exp e infixl 9 !! -- | Extract the element of a singleton array. -- --
-- the xs == xs ! Z --the :: Elt e => Acc (Scalar e) -> Exp e -- | Test whether an array is empty. null :: (Shape sh, Elt e) => Acc (Array sh e) -> Exp Bool -- | Get the length of a vector. length :: Elt e => Acc (Vector e) -> Exp Int -- | Extract the shape (extent) of an array. shape :: (Shape sh, Elt e) => Acc (Array sh e) -> Exp sh -- | The number of elements in the array size :: (Shape sh, Elt e) => Acc (Array sh e) -> Exp Int -- | The number of elements that would be held by an array of the given -- shape. shapeSize :: Shape sh => Exp sh -> Exp Int -- | Make an array from vanilla Haskell available for processing within -- embedded Accelerate computations. -- -- Depending upon which backend is used to eventually execute array -- computations, use may entail data transfer (e.g. to a GPU). -- -- use is overloaded so that it can accept tuples of -- Arrays: -- --
-- >>> let vec = fromList (Z:.10) [0..] :: Array DIM1 Int -- Vector (Z :. 10) [0,1,2,3,4,5,6,7,8,9] ---- --
-- >>> let mat = fromList (Z:.5:.10) [0..] :: Array DIM2 Int -- -- >>> mat -- Matrix (Z :. 5 :. 10) -- [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49] ---- --
-- >>> let vec' = use vec :: Acc (Array DIM1 Int) -- -- >>> let mat' = use mat :: Acc (Array DIM2 Int) -- -- >>> let tup = use (vec, mat) :: Acc (Array DIM1 Int, Array DIM2 Int) --use :: Arrays arrays => arrays -> Acc arrays -- | Construct a singleton (one element) array from a scalar value (or -- tuple of scalar values). unit :: Elt e => Exp e -> Acc (Scalar e) -- | Construct a new array by applying a function to each index. -- -- For example, the following will generate a one-dimensional array -- (Vector) of three floating point numbers: -- --
-- >>> generate (index1 3) (\_ -> 1.2) -- Vector (Z :. 3) [1.2,1.2,1.2] ---- -- Or equivalently: -- --
-- >>> fill (constant (Z :. 3)) 1.2 -- Vector (Z :. 3) [1.2,1.2,1.2] ---- -- The following will create a vector with the elements [1..10]: -- --
-- >>> generate (index1 10) (\ix -> unindex1 ix + 1) -- Vector (Z :. 10) [1,2,3,4,5,6,7,8,9,10] ---- --
-- >>> enumFromN (constant (Z:.5:.10)) 0 :: Array DIM2 Int -- Matrix (Z :. 5 :. 10) -- [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49] --enumFromN :: (Shape sh, Num e, FromIntegral Int e) => Exp sh -> Exp e -> Acc (Array sh e) -- | Create an array of the given shape containing the values x, -- x+y, x+y+y etc. (in row-major order). -- --
-- >>> enumFromStepN (constant (Z:.5:.10)) 0 0.5 :: Array DIM2 Float -- Matrix (Z :. 5 :. 10) -- [ 0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, -- 5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5, -- 10.0, 10.5, 11.0, 11.5, 12.0, 12.5, 13.0, 13.5, 14.0, 14.5, -- 15.0, 15.5, 16.0, 16.5, 17.0, 17.5, 18.0, 18.5, 19.0, 19.5, -- 20.0, 20.5, 21.0, 21.5, 22.0, 22.5, 23.0, 23.5, 24.0, 24.5] --enumFromStepN :: (Shape sh, Num e, FromIntegral Int e) => Exp sh -> Exp e -> Exp e -> Acc (Array sh e) -- | Concatenate innermost component of two arrays. The extent of the lower -- dimensional component is the intersection of the two arrays. -- --
-- >>> let m1 = fromList (Z:.5:.10) [0..] -- -- >>> m1 -- Matrix (Z :. 5 :. 10) -- [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49] ---- --
-- >>> let m2 = fromList (Z:.10:.3) [0..] -- -- >>> m2 -- Matrix (Z :. 10 :. 3) -- [ 0, 1, 2, -- 3, 4, 5, -- 6, 7, 8, -- 9, 10, 11, -- 12, 13, 14, -- 15, 16, 17, -- 18, 19, 20, -- 21, 22, 23, -- 24, 25, 26, -- 27, 28, 29] ---- --
-- >>> use m1 ++ use m2 -- Matrix (Z :. 5 :. 13) -- [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, -- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 3, 4, 5, -- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 6, 7, 8, -- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 9, 10, 11, -- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 12, 13, 14] --(++) :: forall sh e. (Slice sh, Shape sh, Elt e) => Acc (Array (sh :. Int) e) -> Acc (Array (sh :. Int) e) -> Acc (Array (sh :. Int) e) infixr 5 ++ -- | Infix version of acond. If the predicate evaluates to -- True, the first component of the tuple is returned, else the -- second. -- -- See also: ifThenElse. (?|) :: Arrays a => Exp Bool -> (Acc a, Acc a) -> Acc a infix 0 ?| -- | An array-level if-then-else construct. acond :: Arrays a => Exp Bool -> Acc a -> Acc a -> Acc a -- | An array-level while construct. Continue to apply the given -- function, starting with the initial value, until the test function -- evaluates to False. awhile :: Arrays a => (Acc a -> Acc (Scalar Bool)) -> (Acc a -> Acc a) -> Acc a -> Acc a -- | For use with -XRebindableSyntax, this class provides -- ifThenElse lifted to both scalar and array types. class IfThenElse t where type EltT t a :: Constraint where { type family EltT t a :: Constraint; } ifThenElse :: (IfThenElse t, EltT t a) => Exp Bool -> t a -> t a -> t a -- | Pipelining of two array computations. The first argument will be fully -- evaluated before being passed to the second computation. This can be -- used to prevent the argument being fused into the function, for -- example. -- -- Denotationally, we have -- --
-- (acc1 >-> acc2) arrs = let tmp = acc1 arrs -- in tmp `seq` acc2 tmp --(>->) :: (Arrays a, Arrays b, Arrays c) => (Acc a -> Acc b) -> (Acc b -> Acc c) -> (Acc a -> Acc c) infixl 1 >-> -- | Force an array expression to be evaluated, preventing it from fusing -- with other operations. Forcing operations to be computed to memory, -- rather than being fused into their consuming function, can sometimes -- improve performance. For example, computing a matrix transpose -- could provide better memory locality for the subsequent operation. -- Preventing fusion to split large operations into several simpler steps -- could also help by reducing register pressure. -- -- Preventing fusion also means that the individual operations are -- available to be executed concurrently with other kernels. In -- particular, consider using this if you have a series of operations -- that are compute bound rather than memory bound. -- -- Here is the synthetic example: -- --
-- loop :: Exp Int -> Exp Int -- loop ticks = -- let clockRate = 900000 -- kHz -- in while (\i -> i < clockRate * ticks) (+1) 0 -- -- test :: Acc (Vector Int) -- test = -- zip3 -- (compute $ map loop (use $ fromList (Z:.1) [10])) -- (compute $ map loop (use $ fromList (Z:.1) [10])) -- (compute $ map loop (use $ fromList (Z:.1) [10])) ---- -- Without the use of compute, the operations are fused together -- and the three long-running loops are executed sequentially in a single -- kernel. Instead, the individual operations can now be executed -- concurrently, potentially reducing overall runtime. compute :: Arrays a => Acc a -> Acc a -- | Pair each element with its index indexed :: (Shape sh, Elt a) => Acc (Array sh a) -> Acc (Array sh (sh, a)) -- | Apply the given function element-wise to an array. -- --
-- map f [x1, x2, ... xn] = [f x1, f x2, ... f xn] --map :: (Shape sh, Elt a, Elt b) => (Exp a -> Exp b) -> Acc (Array sh a) -> Acc (Array sh b) -- | Apply a function to every element of an array and its index imap :: (Shape sh, Elt a, Elt b) => (Exp sh -> Exp a -> Exp b) -> Acc (Array sh a) -> Acc (Array sh b) -- | Apply the given binary function element-wise to the two arrays. The -- extent of the resulting array is the intersection of the extents of -- the two source arrays. zipWith :: (Shape sh, Elt a, Elt b, Elt c) => (Exp a -> Exp b -> Exp c) -> Acc (Array sh a) -> Acc (Array sh b) -> Acc (Array sh c) -- | Zip three arrays with the given function, analogous to zipWith. zipWith3 :: (Shape sh, Elt a, Elt b, Elt c, Elt d) => (Exp a -> Exp b -> Exp c -> Exp d) -> Acc (Array sh a) -> Acc (Array sh b) -> Acc (Array sh c) -> Acc (Array sh d) -- | Zip four arrays with the given function, analogous to zipWith. zipWith4 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e) => (Exp a -> Exp b -> Exp c -> Exp d -> Exp e) -> Acc (Array sh a) -> Acc (Array sh b) -> Acc (Array sh c) -> Acc (Array sh d) -> Acc (Array sh e) -- | Zip five arrays with the given function, analogous to zipWith. zipWith5 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f) => (Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp f) -> Acc (Array sh a) -> Acc (Array sh b) -> Acc (Array sh c) -> Acc (Array sh d) -> Acc (Array sh e) -> Acc (Array sh f) -- | Zip six arrays with the given function, analogous to zipWith. zipWith6 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g) => (Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp f -> Exp g) -> Acc (Array sh a) -> Acc (Array sh b) -> Acc (Array sh c) -> Acc (Array sh d) -> Acc (Array sh e) -> Acc (Array sh f) -> Acc (Array sh g) -- | Zip seven arrays with the given function, analogous to zipWith. zipWith7 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h) => (Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp f -> Exp g -> Exp h) -> Acc (Array sh a) -> Acc (Array sh b) -> Acc (Array sh c) -> Acc (Array sh d) -> Acc (Array sh e) -> Acc (Array sh f) -> Acc (Array sh g) -> Acc (Array sh h) -- | Zip eight arrays with the given function, analogous to zipWith. zipWith8 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i) => (Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp f -> Exp g -> Exp h -> Exp i) -> Acc (Array sh a) -> Acc (Array sh b) -> Acc (Array sh c) -> Acc (Array sh d) -> Acc (Array sh e) -> Acc (Array sh f) -> Acc (Array sh g) -> Acc (Array sh h) -> Acc (Array sh i) -- | Zip nine arrays with the given function, analogous to zipWith. zipWith9 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j) => (Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp f -> Exp g -> Exp h -> Exp i -> Exp j) -> Acc (Array sh a) -> Acc (Array sh b) -> Acc (Array sh c) -> Acc (Array sh d) -> Acc (Array sh e) -> Acc (Array sh f) -> Acc (Array sh g) -> Acc (Array sh h) -> Acc (Array sh i) -> Acc (Array sh j) -- | Zip two arrays with a function that also takes the element index izipWith :: (Shape sh, Elt a, Elt b, Elt c) => (Exp sh -> Exp a -> Exp b -> Exp c) -> Acc (Array sh a) -> Acc (Array sh b) -> Acc (Array sh c) -- | Zip three arrays with a function that also takes the element index, -- analogous to izipWith. izipWith3 :: (Shape sh, Elt a, Elt b, Elt c, Elt d) => (Exp sh -> Exp a -> Exp b -> Exp c -> Exp d) -> Acc (Array sh a) -> Acc (Array sh b) -> Acc (Array sh c) -> Acc (Array sh d) -- | Zip four arrays with the given function that also takes the element -- index, analogous to zipWith. izipWith4 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e) => (Exp sh -> Exp a -> Exp b -> Exp c -> Exp d -> Exp e) -> Acc (Array sh a) -> Acc (Array sh b) -> Acc (Array sh c) -> Acc (Array sh d) -> Acc (Array sh e) -- | Zip five arrays with the given function that also takes the element -- index, analogous to zipWith. izipWith5 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f) => (Exp sh -> Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp f) -> Acc (Array sh a) -> Acc (Array sh b) -> Acc (Array sh c) -> Acc (Array sh d) -> Acc (Array sh e) -> Acc (Array sh f) -- | Zip six arrays with the given function that also takes the element -- index, analogous to zipWith. izipWith6 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g) => (Exp sh -> Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp f -> Exp g) -> Acc (Array sh a) -> Acc (Array sh b) -> Acc (Array sh c) -> Acc (Array sh d) -> Acc (Array sh e) -> Acc (Array sh f) -> Acc (Array sh g) -- | Zip seven arrays with the given function that also takes the element -- index, analogous to zipWith. izipWith7 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h) => (Exp sh -> Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp f -> Exp g -> Exp h) -> Acc (Array sh a) -> Acc (Array sh b) -> Acc (Array sh c) -> Acc (Array sh d) -> Acc (Array sh e) -> Acc (Array sh f) -> Acc (Array sh g) -> Acc (Array sh h) -- | Zip eight arrays with the given function that also takes the element -- index, analogous to zipWith. izipWith8 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i) => (Exp sh -> Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp f -> Exp g -> Exp h -> Exp i) -> Acc (Array sh a) -> Acc (Array sh b) -> Acc (Array sh c) -> Acc (Array sh d) -> Acc (Array sh e) -> Acc (Array sh f) -> Acc (Array sh g) -> Acc (Array sh h) -> Acc (Array sh i) -- | Zip nine arrays with the given function that also takes the element -- index, analogous to zipWith. izipWith9 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j) => (Exp sh -> Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp f -> Exp g -> Exp h -> Exp i -> Exp j) -> Acc (Array sh a) -> Acc (Array sh b) -> Acc (Array sh c) -> Acc (Array sh d) -> Acc (Array sh e) -> Acc (Array sh f) -> Acc (Array sh g) -> Acc (Array sh h) -> Acc (Array sh i) -> Acc (Array sh j) -- | Combine the elements of two arrays pairwise. The shape of the result -- is the intersection of the two argument shapes. zip :: (Shape sh, Elt a, Elt b) => Acc (Array sh a) -> Acc (Array sh b) -> Acc (Array sh (a, b)) -- | Take three arrays and return an array of triples, analogous to zip. zip3 :: (Shape sh, Elt a, Elt b, Elt c) => Acc (Array sh a) -> Acc (Array sh b) -> Acc (Array sh c) -> Acc (Array sh (a, b, c)) -- | Take four arrays and return an array of quadruples, analogous to zip. zip4 :: (Shape sh, Elt a, Elt b, Elt c, Elt d) => Acc (Array sh a) -> Acc (Array sh b) -> Acc (Array sh c) -> Acc (Array sh d) -> Acc (Array sh (a, b, c, d)) -- | Take five arrays and return an array of five-tuples, analogous to zip. zip5 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e) => Acc (Array sh a) -> Acc (Array sh b) -> Acc (Array sh c) -> Acc (Array sh d) -> Acc (Array sh e) -> Acc (Array sh (a, b, c, d, e)) -- | Take six arrays and return an array of six-tuples, analogous to zip. zip6 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f) => Acc (Array sh a) -> Acc (Array sh b) -> Acc (Array sh c) -> Acc (Array sh d) -> Acc (Array sh e) -> Acc (Array sh f) -> Acc (Array sh (a, b, c, d, e, f)) -- | Take seven arrays and return an array of seven-tuples, analogous to -- zip. zip7 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g) => Acc (Array sh a) -> Acc (Array sh b) -> Acc (Array sh c) -> Acc (Array sh d) -> Acc (Array sh e) -> Acc (Array sh f) -> Acc (Array sh g) -> Acc (Array sh (a, b, c, d, e, f, g)) -- | Take seven arrays and return an array of seven-tuples, analogous to -- zip. zip8 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h) => Acc (Array sh a) -> Acc (Array sh b) -> Acc (Array sh c) -> Acc (Array sh d) -> Acc (Array sh e) -> Acc (Array sh f) -> Acc (Array sh g) -> Acc (Array sh h) -> Acc (Array sh (a, b, c, d, e, f, g, h)) -- | Take seven arrays and return an array of seven-tuples, analogous to -- zip. zip9 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i) => Acc (Array sh a) -> Acc (Array sh b) -> Acc (Array sh c) -> Acc (Array sh d) -> Acc (Array sh e) -> Acc (Array sh f) -> Acc (Array sh g) -> Acc (Array sh h) -> Acc (Array sh i) -> Acc (Array sh (a, b, c, d, e, f, g, h, i)) -- | The converse of zip, but the shape of the two results is -- identical to the shape of the argument. -- -- If the argument array is manifest in memory, unzip is a NOP. unzip :: (Shape sh, Elt a, Elt b) => Acc (Array sh (a, b)) -> (Acc (Array sh a), Acc (Array sh b)) -- | Take an array of triples and return three arrays, analogous to unzip. unzip3 :: (Shape sh, Elt a, Elt b, Elt c) => Acc (Array sh (a, b, c)) -> (Acc (Array sh a), Acc (Array sh b), Acc (Array sh c)) -- | Take an array of quadruples and return four arrays, analogous to -- unzip. unzip4 :: (Shape sh, Elt a, Elt b, Elt c, Elt d) => Acc (Array sh (a, b, c, d)) -> (Acc (Array sh a), Acc (Array sh b), Acc (Array sh c), Acc (Array sh d)) -- | Take an array of 5-tuples and return five arrays, analogous to unzip. unzip5 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e) => Acc (Array sh (a, b, c, d, e)) -> (Acc (Array sh a), Acc (Array sh b), Acc (Array sh c), Acc (Array sh d), Acc (Array sh e)) -- | Take an array of 6-tuples and return six arrays, analogous to unzip. unzip6 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f) => Acc (Array sh (a, b, c, d, e, f)) -> (Acc (Array sh a), Acc (Array sh b), Acc (Array sh c), Acc (Array sh d), Acc (Array sh e), Acc (Array sh f)) -- | Take an array of 7-tuples and return seven arrays, analogous to unzip. unzip7 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g) => Acc (Array sh (a, b, c, d, e, f, g)) -> (Acc (Array sh a), Acc (Array sh b), Acc (Array sh c), Acc (Array sh d), Acc (Array sh e), Acc (Array sh f), Acc (Array sh g)) -- | Take an array of 8-tuples and return eight arrays, analogous to unzip. unzip8 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h) => Acc (Array sh (a, b, c, d, e, f, g, h)) -> (Acc (Array sh a), Acc (Array sh b), Acc (Array sh c), Acc (Array sh d), Acc (Array sh e), Acc (Array sh f), Acc (Array sh g), Acc (Array sh h)) -- | Take an array of 8-tuples and return eight arrays, analogous to unzip. unzip9 :: (Shape sh, Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i) => Acc (Array sh (a, b, c, d, e, f, g, h, i)) -> (Acc (Array sh a), Acc (Array sh b), Acc (Array sh c), Acc (Array sh d), Acc (Array sh e), Acc (Array sh f), Acc (Array sh g), Acc (Array sh h), Acc (Array sh i)) -- | Change the shape of an array without altering its contents. The -- size of the source and result arrays must be identical. -- --
-- precondition: shapeSize sh == shapeSize sh' ---- -- If the argument array is manifest in memory, reshape is a NOP. -- If the argument is to be fused into a subsequent operation, -- reshape corresponds to an index transformation in the fused -- code. reshape :: (Shape sh, Shape sh', Elt e) => Exp sh -> Acc (Array sh' e) -> Acc (Array sh e) -- | Flatten the given array of arbitrary dimension into a one-dimensional -- vector. As with reshape, this operation performs no work. flatten :: forall sh e. (Shape sh, Elt e) => Acc (Array sh e) -> Acc (Vector e) -- | Replicate an array across one or more dimensions as specified by the -- generalised array index provided as the first argument. -- -- For example, given the following vector: -- --
-- >>> let vec = fromList (Z:.10) [0..] -- Vector (Z :. 10) [0,1,2,3,4,5,6,7,8,9] ---- -- ...we can replicate these elements to form a two-dimensional array -- either by replicating those elements as new rows: -- --
-- >>> replicate (lift (Z :. 4 :. All)) (use vec) -- Matrix (Z :. 4 :. 10) -- [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9] ---- -- ...or as columns: -- --
-- >>> replicate (lift (Z :. All :. 4)) (use vec) -- Matrix (Z :. 10 :. 4) -- [ 0, 0, 0, 0, -- 1, 1, 1, 1, -- 2, 2, 2, 2, -- 3, 3, 3, 3, -- 4, 4, 4, 4, -- 5, 5, 5, 5, -- 6, 6, 6, 6, -- 7, 7, 7, 7, -- 8, 8, 8, 8, -- 9, 9, 9, 9] ---- -- Replication along more than one dimension is also possible. Here we -- replicate twice across the first dimension and three times across the -- third dimension: -- --
-- >>> replicate (lift (Z :. 2 :. All :. 3)) (use vec) -- Array (Z :. 2 :. 10 :. 3) [0,0,0,1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,8,8,8,9,9,9,0,0,0,1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,8,8,8,9,9,9] ---- -- The marker Any can be used in the slice specification to match -- against some arbitrary dimension. For example, here Any matches -- against whatever shape type variable sh takes. -- --
-- rep0 :: (Shape sh, Elt e) => Exp Int -> Acc (Array sh e) -> Acc (Array (sh :. Int) e) -- rep0 n a = replicate (lift (Any :. n)) a ---- --
-- >>> let x = unit 42 :: Acc (Scalar Int) -- -- >>> rep0 10 x -- Vector (Z :. 10) [42,42,42,42,42,42,42,42,42,42] ---- --
-- >>> rep0 5 (use vec) -- Matrix (Z :. 10 :. 5) -- [ 0, 0, 0, 0, 0, -- 1, 1, 1, 1, 1, -- 2, 2, 2, 2, 2, -- 3, 3, 3, 3, 3, -- 4, 4, 4, 4, 4, -- 5, 5, 5, 5, 5, -- 6, 6, 6, 6, 6, -- 7, 7, 7, 7, 7, -- 8, 8, 8, 8, 8, -- 9, 9, 9, 9, 9] ---- -- Of course, Any and All can be used together. -- --
-- rep1 :: (Shape sh, Elt e) => Exp Int -> Acc (Array (sh :. Int) e) -> Acc (Array (sh :. Int :. Int) e) -- rep1 n a = A.replicate (lift (Any :. n :. All)) a ---- --
-- >>> rep1 5 (use vec) -- Matrix (Z :. 5 :. 10) -- [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9] --replicate :: (Slice slix, Elt e) => Exp slix -> Acc (Array (SliceShape slix) e) -> Acc (Array (FullShape slix) e) -- | Index an array with a generalised array index, supplied as the -- second argument. The result is a new array (possibly a singleton) -- containing the selected dimensions (Alls) in their entirety. -- -- slice is the opposite of replicate, and can be used to -- cut out entire dimensions. For example, for the two dimensional -- array mat: -- --
-- >>> let mat = fromList (Z:.5:.10) [0..] -- -- >>> mat -- Matrix (Z :. 5 :. 10) -- [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49] ---- -- ...will can select a specific row to yield a one dimensional result by -- fixing the row index (2) while allowing the column index to vary (via -- All): -- --
-- >>> slice (use mat) (lift (Z :. 2 :. All)) -- Vector (Z :. 10) [20,21,22,23,24,25,26,27,28,29] ---- -- A fully specified index (with no Alls) returns a single element -- (zero dimensional array). -- --
-- >>> slice (use mat) (lift (Z :. 4 :. 2)) -- Scalar Z [42] ---- -- The marker Any can be used in the slice specification to match -- against some arbitrary (lower) dimension. Here Any matches -- whatever shape type variable sh takes: -- --
-- sl0 :: (Shape sh, Elt e) => Acc (Array (sh:.Int) e) -> Exp Int -> Acc (Array sh e) -- sl0 a n = A.slice a (lift (Any :. n)) ---- --
-- >>> let vec = fromList (Z:.10) [0..] -- -- >>> sl0 (use vec) 4 -- Scalar Z [4] ---- --
-- >>> sl0 (use mat) 4 -- Vector (Z :. 5) [4,14,24,34,44] ---- -- Of course, Any and All can be used together. -- --
-- sl1 :: (Shape sh, Elt e) => Acc (Array (sh:.Int:.Int) e) -> Exp Int -> Acc (Array (sh:.Int) e) -- sl1 a n = A.slice a (lift (Any :. n :. All)) ---- --
-- >>> sl1 (use mat) 4 -- Vector (Z :. 10) [40,41,42,43,44,45,46,47,48,49] ---- --
-- >>> let cube = fromList (Z:.3:.4:.5) [0..] -- -- >>> cube -- Array (Z :. 3 :. 4 :. 5) [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59] ---- --
-- >>> sl1 (use cube) 2 -- Matrix (Z :. 3 :. 5) -- [ 10, 11, 12, 13, 14, -- 30, 31, 32, 33, 34, -- 50, 51, 52, 53, 54] --slice :: (Slice slix, Elt e) => Acc (Array (FullShape slix) e) -> Exp slix -> Acc (Array (SliceShape slix) e) -- | Yield all but the elements in the last index of the innermost -- dimension. -- --
-- >>> let mat = fromList (Z:.5:.10) [0..] -- -- >>> mat -- Matrix (Z :. 5 :. 10) -- [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49] ---- --
-- >>> init (use mat) -- Matrix (Z :. 5 :. 9) -- [ 0, 1, 2, 3, 4, 5, 6, 7, 8, -- 10, 11, 12, 13, 14, 15, 16, 17, 18, -- 20, 21, 22, 23, 24, 25, 26, 27, 28, -- 30, 31, 32, 33, 34, 35, 36, 37, 38, -- 40, 41, 42, 43, 44, 45, 46, 47, 48] --init :: forall sh e. (Slice sh, Shape sh, Elt e) => Acc (Array (sh :. Int) e) -> Acc (Array (sh :. Int) e) -- | Yield all but the first element along the innermost dimension of an -- array. The innermost dimension must not be empty. -- --
-- >>> let mat = fromList (Z:.5:.10) [0..] -- -- >>> mat -- Matrix (Z :. 5 :. 10) -- [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49] ---- --
-- >>> tail (use mat) -- Matrix (Z :. 5 :. 9) -- [ 1, 2, 3, 4, 5, 6, 7, 8, 9, -- 11, 12, 13, 14, 15, 16, 17, 18, 19, -- 21, 22, 23, 24, 25, 26, 27, 28, 29, -- 31, 32, 33, 34, 35, 36, 37, 38, 39, -- 41, 42, 43, 44, 45, 46, 47, 48, 49] --tail :: forall sh e. (Slice sh, Shape sh, Elt e) => Acc (Array (sh :. Int) e) -> Acc (Array (sh :. Int) e) -- | Yield the first n elements in the innermost dimension of the -- array (plus all lower dimensional elements). -- --
-- >>> let mat = fromList (Z:.5:.10) [0..] -- -- >>> mat -- Matrix (Z :. 5 :. 10) -- [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49] ---- --
-- >>> take 5 (use mat) -- Matrix (Z :. 5 :. 5) -- [ 0, 1, 2, 3, 4, -- 10, 11, 12, 13, 14, -- 20, 21, 22, 23, 24, -- 30, 31, 32, 33, 34, -- 40, 41, 42, 43, 44] --take :: forall sh e. (Slice sh, Shape sh, Elt e) => Exp Int -> Acc (Array (sh :. Int) e) -> Acc (Array (sh :. Int) e) -- | Yield all but the first n elements along the innermost -- dimension of the array (plus all lower dimensional elements). -- --
-- >>> let mat = fromList (Z:.5:.10) [0..] -- -- >>> mat -- Matrix (Z :. 5 :. 10) -- [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49] ---- --
-- >>> drop 7 (use mat) -- Matrix (Z :. 5 :. 3) -- [ 7, 8, 9, -- 17, 18, 19, -- 27, 28, 29, -- 37, 38, 39, -- 47, 48, 49] --drop :: forall sh e. (Slice sh, Shape sh, Elt e) => Exp Int -> Acc (Array (sh :. Int) e) -> Acc (Array (sh :. Int) e) -- | Yield a slit (slice) of the innermost indices of an array. -- Denotationally, we have: -- --
-- slit i n = take n . drop i --slit :: forall sh e. (Slice sh, Shape sh, Elt e) => Exp Int -> Exp Int -> Acc (Array (sh :. Int) e) -> Acc (Array (sh :. Int) e) -- | Generalised forward permutation operation (array scatter). -- -- Forward permutation specified by a function mapping indices from the -- source array to indices in the result array. The result array is -- initialised with the given defaults and any further values that are -- permuted into the result array are added to the current value using -- the given combination function. -- -- The combination function must be associative and -- commutative. Elements that are mapped to the magic value -- ignore by the permutation function are dropped. -- -- For example, we can use permute to compute the occurrence count -- (histogram) for an array of values in the range [0,10): -- --
-- histogram :: Acc (Vector Int) -> Acc (Vector Int) -- histogram xs = -- let zeros = fill (constant (Z:.10)) 0 -- ones = fill (shape xs) 1 -- in -- permute (+) zeros (\ix -> index1 (xs!ix)) ones ---- --
-- >>> let xs = fromList (Z :. 20) [0,0,1,2,1,1,2,4,8,3,4,9,8,3,2,5,5,3,1,2] -- -- >>> histogram (use xs) -- Vector (Z :. 10) [2,4,4,3,2,2,0,0,2,1] ---- --
-- >>> let to = fromList (Z :. 6) [1,3,7,2,5,8] -- -- >>> let input = fromList (Z :. 7) [1,9,6,4,4,2,5] -- -- >>> scatter (use to) (fill (constant (Z:.10)) 0) (use input) -- Vector (Z :. 10) [0,1,4,9,0,4,0,6,2,0] --scatter :: Elt e => Acc (Vector Int) -> Acc (Vector e) -> Acc (Vector e) -> Acc (Vector e) -- | Generalised backward permutation operation (array gather). -- -- Backward permutation specified by a function mapping indices in the -- destination array to indices in the source array. Elements of the -- output array are thus generated by reading from the corresponding -- index in the source array. -- -- For example, backpermute can be used to transpose a matrix; at -- every index Z:.y:.x in the result array, we get the value at -- that index by reading from the source array at index Z:.x:.y: -- --
-- swap :: Exp DIM2 -> Exp DIM2 -- swap = lift1 $ \(Z:.y:.x) -> Z:.x:.y ---- --
-- >>> let mat = fromList (Z:.5:.10) [0..] -- -- >>> mat -- Matrix (Z :. 5 :. 10) -- [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49] ---- --
-- >>> let mat' = use mat -- -- >>> backpermute (swap (shape mat')) swap mat' -- Matrix (Z :. 10 :. 5) -- [ 0, 10, 20, 30, 40, -- 1, 11, 21, 31, 41, -- 2, 12, 22, 32, 42, -- 3, 13, 23, 33, 43, -- 4, 14, 24, 34, 44, -- 5, 15, 25, 35, 45, -- 6, 16, 26, 36, 46, -- 7, 17, 27, 37, 47, -- 8, 18, 28, 38, 48, -- 9, 19, 29, 39, 49] --backpermute :: (Shape sh, Shape sh', Elt a) => Exp sh' -> (Exp sh' -> Exp sh) -> Acc (Array sh a) -> Acc (Array sh' a) -- | Gather elements from a source array by reading values at the given -- indices. -- --
-- >>> let input = fromList (Z:.9) [1,9,6,4,4,2,0,1,2] -- -- >>> let from = fromList (Z:.6) [1,3,7,2,5,3] -- -- >>> gather (use from) (use input) -- Vector (Z :. 6) [9,4,1,6,2,4] --gather :: (Shape sh, Elt e) => Acc (Array sh Int) -> Acc (Vector e) -> Acc (Array sh e) -- | Reverse the elements of a vector. reverse :: Elt e => Acc (Vector e) -> Acc (Vector e) -- | Transpose the rows and columns of a matrix. transpose :: Elt e => Acc (Array DIM2 e) -> Acc (Array DIM2 e) -- | Drop elements that do not satisfy the predicate. Returns the elements -- which pass the predicate, together with a segment descriptor -- indicating how many elements along each outer dimension were valid. -- --
-- >>> let vec = fromList (Z :. 10) [1..10] :: Vector Int -- -- >>> vec -- Vector (Z :. 10) [1,2,3,4,5,6,7,8,9,10] ---- --
-- >>> filter even (use vec) -- (Vector (Z :. 5) [2,4,6,8,10], Scalar Z [5]) ---- --
-- >>> let mat = fromList (Z :. 4 :. 10) [1,2,3,4,5,6,7,8,9,10,1,1,1,1,1,2,2,2,2,2,2,4,6,8,10,12,14,16,18,20,1,3,5,7,9,11,13,15,17,19] :: Array DIM2 Int -- -- >>> mat -- Matrix (Z :. 4 :. 10) -- [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, -- 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, -- 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, -- 1, 3, 5, 7, 9, 11, 13, 15, 17, 19] ---- --
-- >>> filter odd (use mat) -- (Vector (Z :. 20) [1,3,5,7,9,1,1,1,1,1,1,3,5,7,9,11,13,15,17,19], Vector (Z :. 4) [5,5,0,10]) --filter :: forall sh e. (Shape sh, Slice sh, Elt e) => (Exp e -> Exp Bool) -> Acc (Array (sh :. Int) e) -> Acc (Vector e, Array sh Int) -- | Reduction of the innermost dimension of an array of arbitrary rank. -- The first argument needs to be an associative function to -- enable an efficient parallel implementation. The initial element does -- not need to be an identity element of the combination function. -- --
-- >>> let mat = fromList (Z:.5:.10) [0..] -- -- >>> mat -- Matrix (Z :. 5 :. 10) -- [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49] ---- --
-- >>> fold (+) 42 (use mat) -- Vector (Z :. 5) [87,187,287,387,487] ---- -- Reductions with non-commutative operators are supported. For example, -- the following computes the maximum segment sum problem along each -- innermost dimension of the array. -- -- https://en.wikipedia.org/wiki/Maximum_subarray_problem -- --
-- maximumSegmentSum -- :: forall sh e. (Shape sh, Num e, Ord e) -- => Acc (Array (sh :. Int) e) -- -> Acc (Array sh e) -- maximumSegmentSum -- = map (\v -> let (x,_,_,_) = unlift v :: (Exp e, Exp e, Exp e, Exp e) in x) -- . fold1 f -- . map g -- where -- f :: (Num a, Ord a) => Exp (a,a,a,a) -> Exp (a,a,a,a) -> Exp (a,a,a,a) -- f x y = -- let (mssx, misx, mcsx, tsx) = unlift x -- (mssy, misy, mcsy, tsy) = unlift y -- in -- lift ( mssx `max` (mssy `max` (mcsx+misy)) -- , misx `max` (tsx+misy) -- , mcsy `max` (mcsx+tsy) -- , tsx+tsy -- ) -- -- g :: (Num a, Ord a) => Exp a -> Exp (a,a,a,a) -- g x = let y = max x 0 -- in lift (y,y,y,x) ---- --
-- >>> let vec = fromList (Z:.10) [-2,1,-3,4,-1,2,1,-5,4,0] -- -- >>> maximumSegmentSum (use vec) -- Scalar Z [6] ---- -- See also Fold, which can be a useful way to compute multiple -- results from a single reduction. fold :: (Shape sh, Elt a) => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Array (sh :. Int) a) -> Acc (Array sh a) -- | Variant of fold that requires the reduced array to be non-empty -- and doesn't need an default value. The first argument needs to be an -- associative function to enable an efficient parallel -- implementation. The initial element does not need to be an identity -- element. fold1 :: (Shape sh, Elt a) => (Exp a -> Exp a -> Exp a) -> Acc (Array (sh :. Int) a) -> Acc (Array sh a) -- | Reduction of an array of arbitrary rank to a single scalar value. The -- first argument needs to be an associative function to enable -- efficient parallel implementation. The initial element does not need -- to be an identity element. -- --
-- >>> let vec = fromList (Z:.10) [0..] -- -- >>> foldAll (+) 42 (use vec) -- Scalar Z [87] ---- --
-- >>> let mat = fromList (Z:.5:.10) [0..] -- -- >>> foldAll (+) 0 (use mat) -- Scalar Z [1225] --foldAll :: (Shape sh, Elt a) => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Array sh a) -> Acc (Scalar a) -- | Variant of foldAll that requires the reduced array to be -- non-empty and doesn't need an default value. The first argument must -- be an associative function. fold1All :: (Shape sh, Elt a) => (Exp a -> Exp a -> Exp a) -> Acc (Array sh a) -> Acc (Scalar a) -- | Segmented reduction along the innermost dimension of an array. The -- segment descriptor specifies the lengths of the logical sub-arrays, -- each of which is reduced independently. The innermost dimension must -- contain at least as many elements as required by the segment -- descriptor (sum thereof). -- --
-- >>> let seg = fromList (Z:.4) [1,4,0,3] -- -- >>> seg -- Vector (Z :. 4) [1,4,0,3] ---- --
-- >>> let mat = fromList (Z:.5:.10) [0..] -- -- >>> mat -- Matrix (Z :. 5 :. 10) -- [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49] ---- --
-- >>> foldSeg (+) 0 (use mat) (use seg) -- Matrix (Z :. 5 :. 4) -- [ 0, 10, 0, 18, -- 10, 50, 0, 48, -- 20, 90, 0, 78, -- 30, 130, 0, 108, -- 40, 170, 0, 138] --foldSeg :: (Shape sh, Elt a, Elt i, IsIntegral i) => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Array (sh :. Int) a) -> Acc (Segments i) -> Acc (Array (sh :. Int) a) -- | Variant of foldSeg that requires all segments of the -- reduced array to be non-empty and doesn't need a default value. The -- segment descriptor specifies the length of each of the logical -- sub-arrays. fold1Seg :: (Shape sh, Elt a, Elt i, IsIntegral i) => (Exp a -> Exp a -> Exp a) -> Acc (Array (sh :. Int) a) -> Acc (Segments i) -> Acc (Array (sh :. Int) a) -- | Check if all elements satisfy a predicate all :: (Shape sh, Elt e) => (Exp e -> Exp Bool) -> Acc (Array sh e) -> Acc (Scalar Bool) -- | Check if any element satisfies the predicate any :: (Shape sh, Elt e) => (Exp e -> Exp Bool) -> Acc (Array sh e) -> Acc (Scalar Bool) -- | Check if all elements are True and :: Shape sh => Acc (Array sh Bool) -> Acc (Scalar Bool) -- | Check if any element is True or :: Shape sh => Acc (Array sh Bool) -> Acc (Scalar Bool) -- | Compute the sum of elements sum :: (Shape sh, Num e) => Acc (Array sh e) -> Acc (Scalar e) -- | Compute the product of the elements product :: (Shape sh, Num e) => Acc (Array sh e) -> Acc (Scalar e) -- | Yield the minimum element of an array. The array must not be empty. minimum :: (Shape sh, Ord e) => Acc (Array sh e) -> Acc (Scalar e) -- | Yield the maximum element of an array. The array must not be empty. maximum :: (Shape sh, Ord e) => Acc (Array sh e) -> Acc (Scalar e) -- | Data.List style left-to-right scan along the innermost dimension of an -- arbitrary rank array. The first argument needs to be an -- associative function to enable efficient parallel -- implementation. The initial value (second argument) may be arbitrary. -- --
-- >>> scanl (+) 10 (use $ fromList (Z :. 10) [0..]) -- Array (Z :. 11) [10,10,11,13,16,20,25,31,38,46,55] ---- --
-- >>> scanl (+) 0 (use $ fromList (Z :. 4 :. 10) [0..]) -- Matrix (Z :. 4 :. 11) -- [ 0, 0, 1, 3, 6, 10, 15, 21, 28, 36, 45, -- 0, 10, 21, 33, 46, 60, 75, 91, 108, 126, 145, -- 0, 20, 41, 63, 86, 110, 135, 161, 188, 216, 245, -- 0, 30, 61, 93, 126, 160, 195, 231, 268, 306, 345] --scanl :: (Shape sh, Elt a) => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Array (sh :. Int) a) -> Acc (Array (sh :. Int) a) -- | Data.List style left-to-right scan along the innermost dimension -- without an initial value (aka inclusive scan). The array must not be -- empty. The first argument needs to be an associative function. -- Denotationally, we have: -- --
-- scanl1 f e arr = tail (scanl f e arr) ---- --
-- >>> scanl (+) (use $ fromList (Z:.4:.10) [0..]) -- Matrix (Z :. 4 :. 10) -- [ 0, 1, 3, 6, 10, 15, 21, 28, 36, 45, -- 10, 21, 33, 46, 60, 75, 91, 108, 126, 145, -- 20, 41, 63, 86, 110, 135, 161, 188, 216, 245, -- 30, 61, 93, 126, 160, 195, 231, 268, 306, 345] --scanl1 :: (Shape sh, Elt a) => (Exp a -> Exp a -> Exp a) -> Acc (Array (sh :. Int) a) -> Acc (Array (sh :. Int) a) -- | Variant of scanl, where the last element (final reduction -- result) along each dimension is returned separately. Denotationally we -- have: -- --
-- scanl' f e arr = (init res, unit (res!len)) -- where -- len = shape arr -- res = scanl f e arr ---- --
-- >>> let (res,sum) = scanl' (+) 0 (use $ fromList (Z:.10) [0..]) -- -- >>> res -- Vector (Z :. 10) [0,0,1,3,6,10,15,21,28,36] -- -- >>> sum -- Scalar Z [45] ---- --
-- >>> let (res,sums) = scanl' (+) 0 (use $ fromList (Z:.4:.10) [0..]) -- -- >>> res -- Matrix (Z :. 4 :. 10) -- [ 0, 0, 1, 3, 6, 10, 15, 21, 28, 36, -- 0, 10, 21, 33, 46, 60, 75, 91, 108, 126, -- 0, 20, 41, 63, 86, 110, 135, 161, 188, 216, -- 0, 30, 61, 93, 126, 160, 195, 231, 268, 306] -- -- >>> sums -- Vector (Z :. 4) [45,145,245,345] --scanl' :: (Shape sh, Elt a) => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Array (sh :. Int) a) -> (Acc (Array (sh :. Int) a), Acc (Array sh a)) -- | Right-to-left variant of scanl. scanr :: (Shape sh, Elt a) => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Array (sh :. Int) a) -> Acc (Array (sh :. Int) a) -- | Right-to-left variant of scanl1. scanr1 :: (Shape sh, Elt a) => (Exp a -> Exp a -> Exp a) -> Acc (Array (sh :. Int) a) -> Acc (Array (sh :. Int) a) -- | Right-to-left variant of scanl'. scanr' :: (Shape sh, Elt a) => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Array (sh :. Int) a) -> (Acc (Array (sh :. Int) a), Acc (Array sh a)) -- | Left-to-right prescan (aka exclusive scan). As for scan, the -- first argument must be an associative function. Denotationally, -- we have -- --
-- prescanl f e = Prelude.fst . scanl' f e ---- --
-- >>> let vec = fromList (Z:.10) [1..10] -- -- >>> prescanl (+) 0 (use vec) -- Vector (Z :. 10) [0,0,1,3,6,10,15,21,28,36] --prescanl :: (Shape sh, Elt a) => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Array (sh :. Int) a) -> Acc (Array (sh :. Int) a) -- | Left-to-right postscan, a variant of scanl1 with an initial -- value. As with scanl1, the array must not be empty. -- Denotationally, we have: -- --
-- postscanl f e = map (e `f`) . scanl1 f ---- --
-- >>> let vec = fromList (Z:.10) [1..10] -- -- >>> postscanl (+) 42 (use vec) -- Vector (Z :. 10) [42,43,45,48,52,57,63,70,78,87] --postscanl :: (Shape sh, Elt a) => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Array (sh :. Int) a) -> Acc (Array (sh :. Int) a) -- | Right-to-left prescan (aka exclusive scan). As for scan, the -- first argument must be an associative function. Denotationally, -- we have -- --
-- prescanr f e = Prelude.fst . scanr' f e --prescanr :: (Shape sh, Elt a) => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Array (sh :. Int) a) -> Acc (Array (sh :. Int) a) -- | Right-to-left postscan, a variant of scanr1 with an initial -- value. Denotationally, we have -- --
-- postscanr f e = map (e `f`) . scanr1 f --postscanr :: (Shape sh, Elt a) => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Array (sh :. Int) a) -> Acc (Array (sh :. Int) a) -- | Segmented version of scanl along the innermost dimension of an -- array. The innermost dimension must have at least as many elements as -- the sum of the segment descriptor. -- --
-- >>> let seg = fromList (Z:.4) [1,4,0,3] -- -- >>> seg -- Vector (Z :. 4) [1,4,0,3] ---- --
-- >>> let mat = fromList (Z:.5:.10) [0..] -- -- >>> mat -- Matrix (Z :. 5 :. 10) -- [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49] ---- --
-- >>> scanlSeg (+) 0 (use mat) (use seg) -- Matrix (Z :. 5 :. 12) -- [ 0, 0, 0, 1, 3, 6, 10, 0, 0, 5, 11, 18, -- 0, 10, 0, 11, 23, 36, 50, 0, 0, 15, 31, 48, -- 0, 20, 0, 21, 43, 66, 90, 0, 0, 25, 51, 78, -- 0, 30, 0, 31, 63, 96, 130, 0, 0, 35, 71, 108, -- 0, 40, 0, 41, 83, 126, 170, 0, 0, 45, 91, 138] --scanlSeg :: forall sh e i. (Shape sh, Slice sh, Elt e, Integral i, Bits i, FromIntegral i Int) => (Exp e -> Exp e -> Exp e) -> Exp e -> Acc (Array (sh :. Int) e) -> Acc (Segments i) -> Acc (Array (sh :. Int) e) -- | Segmented version of scanl1 along the innermost dimension. -- -- As with scanl1, the total number of elements considered, in -- this case given by the sum of segment descriptor, must not be -- zero. The input vector must contain at least this many elements. -- -- Zero length segments are allowed, and the behaviour is as if those -- entries were not present in the segment descriptor; that is: -- --
-- scanl1Seg f xs [n,0,0] == scanl1Seg f xs [n] where n /= 0 ---- --
-- >>> let seg = fromList (Z:.4) [1,4,0,3] -- -- >>> seg -- Vector (Z :. 4) [1,4,0,3] ---- --
-- >>> let mat = fromList (Z:.5:.10) [0..] -- -- >>> mat -- Matrix (Z :. 5 :. 10) -- [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49] ---- --
-- >>> scanl1Seg (+) (use mat) (use seg) -- Matrix (Z :. 5 :. 8) -- [ 0, 1, 3, 6, 10, 5, 11, 18, -- 10, 11, 23, 36, 50, 15, 31, 48, -- 20, 21, 43, 66, 90, 25, 51, 78, -- 30, 31, 63, 96, 130, 35, 71, 108, -- 40, 41, 83, 126, 170, 45, 91, 138] --scanl1Seg :: (Shape sh, Slice sh, Elt e, Integral i, Bits i, FromIntegral i Int) => (Exp e -> Exp e -> Exp e) -> Acc (Array (sh :. Int) e) -> Acc (Segments i) -> Acc (Array (sh :. Int) e) -- | Segmented version of scanl' along the innermost dimension of an -- array. The innermost dimension must have at least as many elements as -- the sum of the segment descriptor. -- -- The first element of the resulting tuple is a vector of scanned -- values. The second element is a vector of segment scan totals and has -- the same size as the segment vector. -- --
-- >>> let seg = fromList (Z:.4) [1,4,0,3] -- -- >>> seg -- Vector (Z :. 4) [1,4,0,3] ---- --
-- >>> let mat = fromList (Z:.5:.10) [0..] -- -- >>> mat -- Matrix (Z :. 5 :. 10) -- [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49] ---- --
-- >>> let (res,sums) = scanl'Seg (+) 0 (use mat) (use seg) -- -- >>> res -- Matrix (Z :. 5 :. 8) -- [ 0, 0, 1, 3, 6, 0, 5, 11, -- 0, 0, 11, 23, 36, 0, 15, 31, -- 0, 0, 21, 43, 66, 0, 25, 51, -- 0, 0, 31, 63, 96, 0, 35, 71, -- 0, 0, 41, 83, 126, 0, 45, 91] -- -- >>> sums -- Matrix (Z :. 5 :. 4) -- [ 0, 10, 0, 18, -- 10, 50, 0, 48, -- 20, 90, 0, 78, -- 30, 130, 0, 108, -- 40, 170, 0, 138] --scanl'Seg :: forall sh e i. (Shape sh, Slice sh, Elt e, Integral i, Bits i, FromIntegral i Int) => (Exp e -> Exp e -> Exp e) -> Exp e -> Acc (Array (sh :. Int) e) -> Acc (Segments i) -> Acc (Array (sh :. Int) e, Array (sh :. Int) e) -- | Segmented version of prescanl. prescanlSeg :: (Shape sh, Slice sh, Elt e, Integral i, Bits i, FromIntegral i Int) => (Exp e -> Exp e -> Exp e) -> Exp e -> Acc (Array (sh :. Int) e) -> Acc (Segments i) -> Acc (Array (sh :. Int) e) -- | Segmented version of postscanl. postscanlSeg :: (Shape sh, Slice sh, Elt e, Integral i, Bits i, FromIntegral i Int) => (Exp e -> Exp e -> Exp e) -> Exp e -> Acc (Array (sh :. Int) e) -> Acc (Segments i) -> Acc (Array (sh :. Int) e) -- | Segmented version of scanr along the innermost dimension of an -- array. The innermost dimension must have at least as many elements as -- the sum of the segment descriptor. -- --
-- >>> let seg = fromList (Z:.4) [1,4,0,3] -- -- >>> seg -- Vector (Z :. 4) [1,4,0,3] ---- --
-- >>> let mat = fromList (Z:.5:.10) [0..] -- -- >>> mat -- Matrix (Z :. 5 :. 10) -- [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49] ---- --
-- >>> scanrSeg (+) 0 (use mat) (use seg) -- Matrix (Z :. 5 :. 12) -- [ 2, 0, 18, 15, 11, 6, 0, 0, 24, 17, 9, 0, -- 12, 0, 58, 45, 31, 16, 0, 0, 54, 37, 19, 0, -- 22, 0, 98, 75, 51, 26, 0, 0, 84, 57, 29, 0, -- 32, 0, 138, 105, 71, 36, 0, 0, 114, 77, 39, 0, -- 42, 0, 178, 135, 91, 46, 0, 0, 144, 97, 49, 0] --scanrSeg :: forall sh e i. (Shape sh, Slice sh, Elt e, Integral i, Bits i, FromIntegral i Int) => (Exp e -> Exp e -> Exp e) -> Exp e -> Acc (Array (sh :. Int) e) -> Acc (Segments i) -> Acc (Array (sh :. Int) e) -- | Segmented version of scanr1. -- --
-- >>> let seg = fromList (Z:.4) [1,4,0,3] -- -- >>> seg -- Vector (Z :. 4) [1,4,0,3] ---- --
-- >>> let mat = fromList (Z:.5:.10) [0..] -- -- >>> mat -- Matrix (Z :. 5 :. 10) -- [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49] ---- --
-- >>> scanr1Seg (+) (use mat) (use seg) -- Matrix (Z :. 5 :. 8) -- [ 0, 10, 9, 7, 4, 18, 13, 7, -- 10, 50, 39, 27, 14, 48, 33, 17, -- 20, 90, 69, 47, 24, 78, 53, 27, -- 30, 130, 99, 67, 34, 108, 73, 37, -- 40, 170, 129, 87, 44, 138, 93, 47] --scanr1Seg :: (Shape sh, Slice sh, Elt e, Integral i, Bits i, FromIntegral i Int) => (Exp e -> Exp e -> Exp e) -> Acc (Array (sh :. Int) e) -> Acc (Segments i) -> Acc (Array (sh :. Int) e) -- | Segmented version of scanr'. -- --
-- >>> let seg = fromList (Z:.4) [1,4,0,3] -- -- >>> seg -- Vector (Z :. 4) [1,4,0,3] ---- --
-- >>> let mat = fromList (Z:.5:.10) [0..] -- -- >>> mat -- Matrix (Z :. 5 :. 10) -- [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49] ---- --
-- >>> let (res,sums) = scanr'Seg (+) 0 (use mat) (use seg) -- -- >>> res -- Matrix (Z :. 5 :. 8) -- [ 0, 15, 11, 6, 0, 17, 9, 0, -- 0, 45, 31, 16, 0, 37, 19, 0, -- 0, 75, 51, 26, 0, 57, 29, 0, -- 0, 105, 71, 36, 0, 77, 39, 0, -- 0, 135, 91, 46, 0, 97, 49, 0] -- -- >>> sums -- Matrix (Z :. 5 :. 4) -- [ 2, 18, 0, 24, -- 12, 58, 0, 54, -- 22, 98, 0, 84, -- 32, 138, 0, 114, -- 42, 178, 0, 144] --scanr'Seg :: forall sh e i. (Shape sh, Slice sh, Elt e, Integral i, Bits i, FromIntegral i Int) => (Exp e -> Exp e -> Exp e) -> Exp e -> Acc (Array (sh :. Int) e) -> Acc (Segments i) -> Acc (Array (sh :. Int) e, Array (sh :. Int) e) -- | Segmented version of prescanr. prescanrSeg :: (Shape sh, Slice sh, Elt e, Integral i, Bits i, FromIntegral i Int) => (Exp e -> Exp e -> Exp e) -> Exp e -> Acc (Array (sh :. Int) e) -> Acc (Segments i) -> Acc (Array (sh :. Int) e) -- | Segmented version of postscanr. postscanrSeg :: (Shape sh, Slice sh, Elt e, Integral i, Bits i, FromIntegral i Int) => (Exp e -> Exp e -> Exp e) -> Exp e -> Acc (Array (sh :. Int) e) -> Acc (Segments i) -> Acc (Array (sh :. Int) e) -- | Map a stencil over an array. In contrast to map, the domain of -- a stencil function is an entire neighbourhood of each array -- element. Neighbourhoods are sub-arrays centred around a focal point. -- They are not necessarily rectangular, but they are symmetric and have -- an extent of at least three along each axis. Due to the symmetry -- requirement the extent is necessarily odd. The focal point is the -- array position that is determined by the stencil. -- -- For those array positions where the neighbourhood extends past the -- boundaries of the source array, a boundary condition determines the -- contents of the out-of-bounds neighbourhood positions. -- -- Stencil neighbourhoods are specified via nested tuples, where the -- nesting depth is equal to the dimensionality of the array. For -- example, a 3x1 stencil for a one-dimensional array: -- --
-- s31 :: Stencil3 a -> Exp a -- s31 (l,c,r) = ... ---- -- ...where c is the focal point of the stencil, and l -- and r represent the elements to the left and right of the -- focal point, respectively. Similarly, a 3x3 stencil for a -- two-dimensional array: -- --
-- s33 :: Stencil3x3 a -> Exp a -- s33 ((_,t,_) ---- -- ,(l,c,r) ,(_,b,_)) = ... -- -- ...where c is again the focal point and t, -- b, l and r are the elements to the top, -- bottom, left, and right of the focal point, respectively (the diagonal -- elements have been elided). -- -- For example, the following computes a 5x5 Gaussian blur as a -- separable 2-pass operation. -- --
-- type Stencil5x1 a = (Stencil3 a, Stencil5 a, Stencil3 a) -- type Stencil1x5 a = (Stencil3 a, Stencil3 a, Stencil3 a, Stencil3 a, Stencil3 a) -- -- convolve5x1 :: Num a => [Exp a] -> Stencil5x1 a -> Exp a -- convolve5x1 kernel (_, (a,b,c,d,e), _) -- = Prelude.sum $ Prelude.zipWith (*) kernel [a,b,c,d,e] -- -- convolve1x5 :: Num a => [Exp a] -> Stencil1x5 a -> Exp a -- convolve1x5 kernel ((_,a,_), (_,b,_), (_,c,_), (_,d,_), (_,e,_)) -- = Prelude.sum $ Prelude.zipWith (*) kernel [a,b,c,d,e] -- -- gaussian = [0.06136,0.24477,0.38774,0.24477,0.06136] -- -- blur :: Num a => Acc (Array DIM2 a) -> Acc (Array DIM2 a) -- blur = stencil (convolve5x1 gaussian) Clamp -- . stencil (convolve1x5 gaussian) Clamp --stencil :: (Stencil sh a stencil, Elt b) => (stencil -> Exp b) -> Boundary a -> Acc (Array sh a) -> Acc (Array sh b) -- | Map a binary stencil of an array. The extent of the resulting array is -- the intersection of the extents of the two source arrays. This is the -- stencil equivalent of zipWith. stencil2 :: (Stencil sh a stencil1, Stencil sh b stencil2, Elt c) => (stencil1 -> stencil2 -> Exp c) -> Boundary a -> Acc (Array sh a) -> Boundary b -> Acc (Array sh b) -> Acc (Array sh c) class (Elt (StencilRepr sh stencil), Stencil sh a (StencilRepr sh stencil)) => Stencil sh a stencil -- | Boundary condition specification for stencil operations. data Boundary a -- | clamp coordinates to the extent of the array Clamp :: Boundary a -- | mirror coordinates beyond the array extent Mirror :: Boundary a -- | wrap coordinates around on each dimension Wrap :: Boundary a -- | use a constant value for outlying coordinates Constant :: a -> Boundary a type Stencil3 a = (Exp a, Exp a, Exp a) type Stencil5 a = (Exp a, Exp a, Exp a, Exp a, Exp a) type Stencil7 a = (Exp a, Exp a, Exp a, Exp a, Exp a, Exp a, Exp a) type Stencil9 a = (Exp a, Exp a, Exp a, Exp a, Exp a, Exp a, Exp a, Exp a, Exp a) type Stencil3x3 a = (Stencil3 a, Stencil3 a, Stencil3 a) type Stencil5x3 a = (Stencil5 a, Stencil5 a, Stencil5 a) type Stencil3x5 a = (Stencil3 a, Stencil3 a, Stencil3 a, Stencil3 a, Stencil3 a) type Stencil5x5 a = (Stencil5 a, Stencil5 a, Stencil5 a, Stencil5 a, Stencil5 a) type Stencil3x3x3 a = (Stencil3x3 a, Stencil3x3 a, Stencil3x3 a) type Stencil5x3x3 a = (Stencil5x3 a, Stencil5x3 a, Stencil5x3 a) type Stencil3x5x3 a = (Stencil3x5 a, Stencil3x5 a, Stencil3x5 a) type Stencil3x3x5 a = (Stencil3x3 a, Stencil3x3 a, Stencil3x3 a, Stencil3x3 a, Stencil3x3 a) type Stencil5x5x3 a = (Stencil5x5 a, Stencil5x5 a, Stencil5x5 a) type Stencil5x3x5 a = (Stencil5x3 a, Stencil5x3 a, Stencil5x3 a, Stencil5x3 a, Stencil5x3 a) type Stencil3x5x5 a = (Stencil3x5 a, Stencil3x5 a, Stencil3x5 a, Stencil3x5 a, Stencil3x5 a) type Stencil5x5x5 a = (Stencil5x5 a, Stencil5x5 a, Stencil5x5 a, Stencil5x5 a, Stencil5x5 a) -- | The type Exp represents embedded scalar expressions. The -- collective operations of Accelerate Acc consist of many scalar -- expressions executed in data-parallel. -- -- Note that scalar expressions can not initiate new collective -- operations: doing so introduces nested data parallelism, which -- is difficult to execute efficiently on constrained hardware such as -- GPUs, and is thus currently unsupported. data Exp t -- | The Eq class defines equality == and inequality -- /= for scalar Accelerate expressions. -- -- For convenience, we include Elt as a superclass. class Elt a => Eq a where x == y = mkLNot (x /= y) x /= y = mkLNot (x == y) (==) :: Eq a => Exp a -> Exp a -> Exp Bool (/=) :: Eq a => Exp a -> Exp a -> Exp Bool -- | The Ord class for totally ordered datatypes class Eq a => Ord a where x < y = x /= y && x <= y x > y = not (x <= y) x <= y = not (x > y) x >= y = x == y || not (x <= y) min x y = Exp $ Cond (x <= y) x y max x y = Exp $ Cond (x <= y) y x (<) :: Ord a => Exp a -> Exp a -> Exp Bool (>) :: Ord a => Exp a -> Exp a -> Exp Bool (<=) :: Ord a => Exp a -> Exp a -> Exp Bool (>=) :: Ord a => Exp a -> Exp a -> Exp Bool min :: Ord a => Exp a -> Exp a -> Exp a max :: Ord a => Exp a -> Exp a -> Exp a -- | Name the upper and lower limits of a type. Types which are not totally -- ordered may still have upper and lower bounds. type Bounded a = (Elt a, Bounded (Exp a)) minBound :: Bounded a => a maxBound :: Bounded a => a -- | Basic numeric class type Num a = (Elt a, Num (Exp a)) (+) :: Num a => a -> a -> a (-) :: Num a => a -> a -> a (*) :: Num a => a -> a -> a -- | Unary negation. negate :: Num a => a -> a -- | Absolute value. abs :: Num a => a -> a -- | Sign of a number. The functions abs and signum should -- satisfy the law: -- --
-- abs x * signum x == x ---- -- For real numbers, the signum is either -1 (negative), -- 0 (zero) or 1 (positive). signum :: Num a => a -> a -- | Conversion from an Integer. An integer literal represents the -- application of the function fromInteger to the appropriate -- value of type Integer, so such literals have type -- (Num a) => a. fromInteger :: Num a => Integer -> a -- | Integral numbers, supporting integral division type Integral a = (Enum a, Real a, Integral (Exp a)) -- | integer division truncated toward zero quot :: Integral a => a -> a -> a -- | integer remainder, satisfying -- --
-- (x `quot` y)*y + (x `rem` y) == x --rem :: Integral a => a -> a -> a -- | integer division truncated toward negative infinity div :: Integral a => a -> a -> a -- | integer modulus, satisfying -- --
-- (x `div` y)*y + (x `mod` y) == x --mod :: Integral a => a -> a -> a -- | simultaneous quot and rem quotRem :: Integral a => a -> a -> (a, a) -- | simultaneous div and mod divMod :: Integral a => a -> a -> (a, a) -- | Fractional numbers, supporting real division type Fractional a = (Num a, Fractional (Exp a)) -- | fractional division (/) :: Fractional a => a -> a -> a -- | reciprocal fraction recip :: Fractional a => a -> a -- | Conversion from a Rational (that is Ratio -- Integer). A floating literal stands for an application of -- fromRational to a value of type Rational, so such -- literals have type (Fractional a) => a. fromRational :: Fractional a => Rational -> a -- | Trigonometric and hyperbolic functions and related functions type Floating a = (Fractional a, Floating (Exp a)) pi :: Floating a => a sin :: Floating a => a -> a cos :: Floating a => a -> a tan :: Floating a => a -> a asin :: Floating a => a -> a acos :: Floating a => a -> a atan :: Floating a => a -> a sinh :: Floating a => a -> a cosh :: Floating a => a -> a tanh :: Floating a => a -> a asinh :: Floating a => a -> a acosh :: Floating a => a -> a atanh :: Floating a => a -> a exp :: Floating a => a -> a sqrt :: Floating a => a -> a log :: Floating a => a -> a (**) :: Floating a => a -> a -> a logBase :: Floating a => a -> a -> a -- | Extracting components of fractions. class (Real a, Fractional a) => RealFrac a properFraction :: (RealFrac a, Num b, ToFloating b a, IsIntegral b) => Exp a -> (Exp b, Exp a) -- | truncate x returns the integer nearest x between -- zero and x truncate :: (RealFrac a, Elt b, IsIntegral b) => Exp a -> Exp b -- | round x returns the nearest integer to x; the -- even integer if x is equidistant between two integers round :: (RealFrac a, Elt b, IsIntegral b) => Exp a -> Exp b -- | ceiling x returns the least integer not less than -- x ceiling :: (RealFrac a, Elt b, IsIntegral b) => Exp a -> Exp b -- | floor x returns the greatest integer not greater than -- x floor :: (RealFrac a, Elt b, IsIntegral b) => Exp a -> Exp b -- | Generalisation of div to any instance of RealFrac div' :: (RealFrac a, Elt b, IsIntegral b) => Exp a -> Exp a -> Exp b -- | Generalisation of mod to any instance of RealFrac mod' :: (Floating a, RealFrac a, ToFloating Int a) => Exp a -> Exp a -> Exp a -- | Generalisation of divMod to any instance of RealFrac divMod' :: (Floating a, RealFrac a, Num b, IsIntegral b, ToFloating b a) => Exp a -> Exp a -> (Exp b, Exp a) -- | Efficient, machine-independent access to the components of a -- floating-point number class (RealFrac a, Floating a) => RealFloat a where floatRadix _ = fromInteger (floatRadix (undefined :: a)) floatDigits _ = constant (floatDigits (undefined :: a)) floatRange _ = let (m, n) = floatRange (undefined :: a) in (constant m, constant n) isIEEE _ = constant (isIEEE (undefined :: Float)) decodeFloat = ((\ format_a8DHi kind_a8DHj fn_a8DHk msg_a8DHl -> error (format_a8DHi kind_a8DHj (call fn_a8DHk msg_a8DHl))) (\ kind_a8DHm msg_a8DHn -> message kind_a8DHm ("Data/Array/Accelerate/Classes/RealFloat.hs:99:21: " ++ msg_a8DHn)) Internal) "RealFloat.decodeFloat" "Not implemented yet" encodeFloat = ((\ format_a8DHr kind_a8DHs fn_a8DHt msg_a8DHu -> error (format_a8DHr kind_a8DHs (call fn_a8DHt msg_a8DHu))) (\ kind_a8DHv msg_a8DHw -> message kind_a8DHv ("Data/Array/Accelerate/Classes/RealFloat.hs:100:21: " ++ msg_a8DHw)) Internal) "RealFloat.encodeFloat" "Not implemented yet" exponent = ((\ format_a8DHA kind_a8DHB fn_a8DHC msg_a8DHD -> error (format_a8DHA kind_a8DHB (call fn_a8DHC msg_a8DHD))) (\ kind_a8DHE msg_a8DHF -> message kind_a8DHE ("Data/Array/Accelerate/Classes/RealFloat.hs:101:21: " ++ msg_a8DHF)) Internal) "RealFloat.exponent" "Not implemented yet" significand = ((\ format_a8DHJ kind_a8DHK fn_a8DHL msg_a8DHM -> error (format_a8DHJ kind_a8DHK (call fn_a8DHL msg_a8DHM))) (\ kind_a8DHN msg_a8DHO -> message kind_a8DHN ("Data/Array/Accelerate/Classes/RealFloat.hs:102:21: " ++ msg_a8DHO)) Internal) "RealFloat.significand" "Not implemented yet" scaleFloat = ((\ format_a8DHS kind_a8DHT fn_a8DHU msg_a8DHV -> error (format_a8DHS kind_a8DHT (call fn_a8DHU msg_a8DHV))) (\ kind_a8DHW msg_a8DHX -> message kind_a8DHW ("Data/Array/Accelerate/Classes/RealFloat.hs:103:21: " ++ msg_a8DHX)) Internal) "RealFloat.scaleFloat" "Not implemented yet" isInfinite = ((\ format_a8DI1 kind_a8DI2 fn_a8DI3 msg_a8DI4 -> error (format_a8DI1 kind_a8DI2 (call fn_a8DI3 msg_a8DI4))) (\ kind_a8DI5 msg_a8DI6 -> message kind_a8DI5 ("Data/Array/Accelerate/Classes/RealFloat.hs:104:21: " ++ msg_a8DI6)) Internal) "RealFloat.isInfinite" "Not implemented yet" isDenormalized = ((\ format_a8DIa kind_a8DIb fn_a8DIc msg_a8DId -> error (format_a8DIa kind_a8DIb (call fn_a8DIc msg_a8DId))) (\ kind_a8DIe msg_a8DIf -> message kind_a8DIe ("Data/Array/Accelerate/Classes/RealFloat.hs:105:21: " ++ msg_a8DIf)) Internal) "RealFloat.isDenormalized" "Not implemented yet" isNegativeZero = ((\ format_a8DIj kind_a8DIk fn_a8DIl msg_a8DIm -> error (format_a8DIj kind_a8DIk (call fn_a8DIl msg_a8DIm))) (\ kind_a8DIn msg_a8DIo -> message kind_a8DIn ("Data/Array/Accelerate/Classes/RealFloat.hs:106:21: " ++ msg_a8DIo)) Internal) "RealFloat.isNegativeZero" "Not implemented yet" -- | The radix of the representation (often 2) (constant) floatRadix :: RealFloat a => Exp a -> Exp Int64 -- | The radix of the representation (often 2) (constant) floatRadix :: (RealFloat a, RealFloat a) => Exp a -> Exp Int64 -- | The number of digits of floatRadix in the significand -- (constant) floatDigits :: RealFloat a => Exp a -> Exp Int -- | The number of digits of floatRadix in the significand -- (constant) floatDigits :: (RealFloat a, RealFloat a) => Exp a -> Exp Int -- | The lowest and highest values the exponent may assume (constant) floatRange :: RealFloat a => Exp a -> (Exp Int, Exp Int) -- | The lowest and highest values the exponent may assume (constant) floatRange :: (RealFloat a, RealFloat a) => Exp a -> (Exp Int, Exp Int) -- | Return the significand and an appropriately scaled exponent. if -- (m,n) = decodeFloat x then x = m*b^^n, where -- b is the floating-point radix (floatRadix). -- Furthermore, either m and n are both zero, or -- b^(d-1) <= abs m < b^d, where d = -- floatDigits x. decodeFloat :: RealFloat a => Exp a -> (Exp Int64, Exp Int) -- | Inverse of decodeFloat encodeFloat :: RealFloat a => Exp Int64 -> Exp Int -> Exp a -- | Corresponds to the second component of decodeFloat exponent :: RealFloat a => Exp a -> Exp Int -- | Corresponds to the first component of decodeFloat significand :: RealFloat a => Exp a -> Exp a -- | Multiply a floating point number by an integer power of the radix scaleFloat :: RealFloat a => Exp Int -> Exp a -> Exp a -- | True if the argument is an IEEE "not-a-number" (NaN) value isNaN :: RealFloat a => Exp a -> Exp Bool -- | True if the argument is an IEEE infinity or negative-infinity isInfinite :: RealFloat a => Exp a -> Exp Bool -- | True if the argument is too small to be represented in -- normalized format isDenormalized :: RealFloat a => Exp a -> Exp Bool -- | True if the argument is an IEEE negative zero isNegativeZero :: RealFloat a => Exp a -> Exp Bool -- | True if the argument is an IEEE floating point number isIEEE :: RealFloat a => Exp a -> Exp Bool -- | True if the argument is an IEEE floating point number isIEEE :: (RealFloat a, RealFloat a) => Exp a -> Exp Bool -- | A version of arctangent taking two real floating-point arguments. For -- real floating x and y, atan2 y x -- computes the angle (from the positive x-axis) of the vector from the -- origin to the point (x,y). atan2 y x returns -- a value in the range [-pi, pi]. atan2 :: RealFloat a => Exp a -> Exp a -> Exp a -- | Accelerate lacks a most-general lossless Integer type, which -- the standard fromIntegral function uses as an intermediate -- value when coercing from integral types. Instead, we use this class to -- capture a direct coercion between two types. class FromIntegral a b -- | General coercion from integral types fromIntegral :: (FromIntegral a b, Integral a) => Exp a -> Exp b -- | Accelerate lacks an arbitrary-precision Rational type, which -- the standard realToFrac uses as an intermediate value when -- coercing to floating-point types. Instead, we use this class to -- capture a direct coercion between to types. class ToFloating a b -- | General coercion to floating types toFloating :: (ToFloating a b, Num a, Floating b) => Exp a -> Exp b -- | The class of types e which can be lifted into c. class Lift c e where type Plain e where { type family Plain e; } -- | Lift the given value into a surface type c --- either -- Exp for scalar expressions or Acc for array -- computations. The value may already contain subexpressions in -- c. lift :: Lift c e => e -> c (Plain e) -- | A limited subset of types which can be lifted, can also be unlifted. class Lift c e => Unlift c e -- | Unlift the outermost constructor through the surface type. This is -- only possible if the constructor is fully determined by its type - -- i.e., it is a singleton. unlift :: Unlift c e => c (Plain e) -> e -- | Lift a unary function into Exp. lift1 :: (Unlift Exp a, Lift Exp b) => (a -> b) -> Exp (Plain a) -> Exp (Plain b) -- | Lift a binary function into Exp. lift2 :: (Unlift Exp a, Unlift Exp b, Lift Exp c) => (a -> b -> c) -> Exp (Plain a) -> Exp (Plain b) -> Exp (Plain c) -- | Lift a ternary function into Exp. lift3 :: (Unlift Exp a, Unlift Exp b, Unlift Exp c, Lift Exp d) => (a -> b -> c -> d) -> Exp (Plain a) -> Exp (Plain b) -> Exp (Plain c) -> Exp (Plain d) -- | Lift a unary function to a computation over rank-1 indices. ilift1 :: (Exp Int -> Exp Int) -> Exp DIM1 -> Exp DIM1 -- | Lift a binary function to a computation over rank-1 indices. ilift2 :: (Exp Int -> Exp Int -> Exp Int) -> Exp DIM1 -> Exp DIM1 -> Exp DIM1 -- | Lift a ternary function to a computation over rank-1 indices. ilift3 :: (Exp Int -> Exp Int -> Exp Int -> Exp Int) -> Exp DIM1 -> Exp DIM1 -> Exp DIM1 -> Exp DIM1 -- | Scalar expression inlet: make a Haskell value available for processing -- in an Accelerate scalar expression. -- -- Note that this embeds the value directly into the expression. -- Depending on the backend used to execute the computation, this might -- not always be desirable. For example, a backend that does external -- code generation may embed this constant directly into the generated -- code, which means new code will need to be generated and compiled -- every time the value changes. In such cases, consider instead lifting -- scalar values into (singleton) arrays so that they can be passed as an -- input to the computation and thus the value can change without the -- need to generate fresh code. constant :: Elt t => t -> Exp t -- | Extract the first component of a scalar pair. fst :: forall a b. (Elt a, Elt b) => Exp (a, b) -> Exp a -- | Extract the first component of an array pair. afst :: forall a b. (Arrays a, Arrays b) => Acc (a, b) -> Acc a -- | Extract the second component of a scalar pair. snd :: forall a b. (Elt a, Elt b) => Exp (a, b) -> Exp b -- | Extract the second component of an array pair asnd :: forall a b. (Arrays a, Arrays b) => Acc (a, b) -> Acc b -- | Converts an uncurried function to a curried function. curry :: Lift f (f a, f b) => (f (Plain (f a), Plain (f b)) -> f c) -> f a -> f b -> f c -- | Converts a curried function to a function on pairs. uncurry :: Unlift f (f a, f b) => (f a -> f b -> f c) -> f (Plain (f a), Plain (f b)) -> f c -- | An infix version of cond. If the predicate evaluates to -- True, the first component of the tuple is returned, else the -- second. -- -- See also: ifThenElse. (?) :: Elt t => Exp Bool -> (Exp t, Exp t) -> Exp t infix 0 ? -- | A case-like control structure caseof :: (Elt a, Elt b) => Exp a -> [(Exp a -> Exp Bool, Exp b)] -> Exp b -> Exp b -- | A scalar-level if-then-else construct. cond :: Elt t => Exp Bool -> Exp t -> Exp t -> Exp t -- | While construct. Continue to apply the given function, starting with -- the initial value, until the test function evaluates to False. while :: Elt e => (Exp e -> Exp Bool) -> (Exp e -> Exp e) -> Exp e -> Exp e -- | Repeatedly apply a function a fixed number of times iterate :: forall a. Elt a => Exp Int -> (Exp a -> Exp a) -> Exp a -> Exp a -- | Reduce along an innermost slice of an array sequentially, by -- applying a binary operator to a starting value and the array from left -- to right. sfoldl :: forall sh a b. (Shape sh, Slice sh, Elt a, Elt b) => (Exp a -> Exp b -> Exp a) -> Exp a -> Exp sh -> Acc (Array (sh :. Int) b) -> Exp a -- | Conjunction: True if both arguments are true. This is a short-circuit -- operator, so the second argument will be evaluated only if the first -- is true. (&&) :: Exp Bool -> Exp Bool -> Exp Bool infixr 3 && -- | Disjunction: True if either argument is true. This is a short-circuit -- operator, so the second argument will be evaluated only if the first -- is false. (||) :: Exp Bool -> Exp Bool -> Exp Bool infixr 2 || -- | Logical negation not :: Exp Bool -> Exp Bool -- | subtract is the same as flip (-). subtract :: Num a => Exp a -> Exp a -> Exp a -- | Determine if a number is even even :: Integral a => Exp a -> Exp Bool -- | Determine if a number is odd odd :: Integral a => Exp a -> Exp Bool -- | gcd x y is the non-negative factor of both x -- and y of which every common factor of both x and -- y is also a factor; for example: -- --
-- >>> gcd 4 2 = 2 -- -- >>> gcd (-4) 6 = 2 -- -- >>> gcd 0 4 = 4 -- -- >>> gcd 0 0 = 0 ---- -- That is, the common divisor that is "greatest" in the divisibility -- preordering. gcd :: Integral a => Exp a -> Exp a -> Exp a -- | lcm x y is the smallest positive integer that both -- x and y divide. lcm :: Integral a => Exp a -> Exp a -> Exp a -- | Raise a number to a non-negative integral power (^) :: forall a b. (Num a, Integral b) => Exp a -> Exp b -> Exp a infixr 8 ^ -- | Raise a number to an integral power (^^) :: (Fractional a, Integral b) => Exp a -> Exp b -> Exp a infixr 8 ^^ -- | The one index for a rank-0 array. index0 :: Exp Z -- | Turn an Int expression into a rank-1 indexing expression. index1 :: Elt i => Exp i -> Exp (Z :. i) -- | Turn a rank-1 indexing expression into an Int expression. unindex1 :: Elt i => Exp (Z :. i) -> Exp i -- | Creates a rank-2 index from two Exp Int`s index2 :: (Elt i, Slice (Z :. i)) => Exp i -> Exp i -> Exp ((Z :. i) :. i) -- | Destructs a rank-2 index to an Exp tuple of two Int`s. unindex2 :: forall i. (Elt i, Slice (Z :. i)) => Exp ((Z :. i) :. i) -> Exp (i, i) -- | Create a rank-3 index from three Exp Int`s index3 :: (Elt i, Slice (Z :. i), Slice ((Z :. i) :. i)) => Exp i -> Exp i -> Exp i -> Exp (((Z :. i) :. i) :. i) -- | Destruct a rank-3 index into an Exp tuple of Int`s unindex3 :: forall i. (Elt i, Slice (Z :. i), Slice ((Z :. i) :. i)) => Exp (((Z :. i) :. i) :. i) -> Exp (i, i, i) -- | Get the innermost dimension of a shape indexHead :: (Slice sh, Elt a) => Exp (sh :. a) -> Exp a -- | Get all but the innermost element of a shape indexTail :: (Slice sh, Elt a) => Exp (sh :. a) -> Exp sh -- | Map a multi-dimensional index into a linear, row-major representation -- of an array. toIndex :: Shape sh => Exp sh -> Exp sh -> Exp Int -- | Inverse of toIndex fromIndex :: Shape sh => Exp sh -> Exp Int -> Exp sh -- | Intersection of two shapes intersect :: Shape sh => Exp sh -> Exp sh -> Exp sh -- | Convert a character to an Int. ord :: Exp Char -> Exp Int -- | Convert an Int into a character. chr :: Exp Int -> Exp Char -- | Convert a Boolean value to an Int, where False turns -- into '0' and True into '1'. boolToInt :: Exp Bool -> Exp Int -- | Reinterpret a value as another type. The two representations must have -- the same bit size. bitcast :: (Elt a, Elt b, IsScalar a, IsScalar b, BitSizeEq a b) => Exp a -> Exp b -- | Call a foreign array function. -- -- The form the first argument takes is dependent on the backend being -- targeted. Note that the foreign function only has access to the input -- array(s) passed in as its argument. -- -- In case the operation is being executed on a backend which does not -- support this foreign implementation, the fallback implementation is -- used instead, which itself could be a foreign implementation for a -- (presumably) different backend, or an implementation of pure -- Accelerate. In this way, multiple foreign implementations can be -- supplied, and will be tested for suitability against the target -- backend in sequence. -- -- For an example see the accelerate-fft package. foreignAcc :: (Arrays as, Arrays bs, Foreign asm) => asm (as -> bs) -> (Acc as -> Acc bs) -> Acc as -> Acc bs -- | Call a foreign scalar expression. -- -- The form of the first argument is dependent on the backend being -- targeted. Note that the foreign function only has access to the input -- element(s) passed in as its first argument. -- -- As with foreignAcc, the fallback implementation itself may be a -- (sequence of) foreign implementation(s) for a different backend(s), or -- implemented purely in Accelerate. foreignExp :: (Elt x, Elt y, Foreign asm) => asm (x -> y) -> (Exp x -> Exp y) -> Exp x -> Exp y -- | Rank of an array. arrayRank :: Shape sh => sh -> Int -- | Array shape in plain Haskell code. arrayShape :: Shape sh => Array sh e -> sh -- | Total number of elements in an array of the given Shape. arraySize :: Shape sh => sh -> Int -- | Array indexing in plain Haskell code. indexArray :: Array sh e -> sh -> e -- | Create an array from its representation function, applied at each -- index of the array. fromFunction :: (Shape sh, Elt e) => sh -> (sh -> e) -> Array sh e -- | Convert elements of a list into an Accelerate Array. -- -- This will generate a new multidimensional Array of the -- specified shape and extent by consuming elements from the list and -- adding them to the array in row-major order. -- --
-- >>> fromList (Z:.10) [0..] :: Vector Int -- Vector (Z :. 10) [0,1,2,3,4,5,6,7,8,9] ---- -- Note that we pull elements off the list lazily, so infinite lists are -- accepted: -- --
-- >>> fromList (Z:.5:.10) (repeat 0) :: Array DIM2 Float -- Matrix (Z :. 5 :. 10) -- [ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -- 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -- 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -- 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -- 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] ---- -- You can also make use of the OverloadedLists extension to -- produce one-dimensional vectors from a finite list. -- --
-- >>> [0..9] :: Vector Int -- Vector (Z :. 10) [0,1,2,3,4,5,6,7,8,9] ---- -- Note that this requires first traversing the list to determine its -- length, and then traversing it a second time to collect the elements -- into the array, thus forcing the spine of the list to be manifest on -- the heap. fromList :: (Shape sh, Elt e) => sh -> [e] -> Array sh e -- | Convert an accelerated Array to a list in row-major order. toList :: forall sh e. Array sh e -> [e] -- | Function composition. (.) :: (b -> c) -> (a -> b) -> a -> c infixr 9 . -- | Application operator. This operator is redundant, since ordinary -- application (f x) means the same as (f $ x). -- However, $ has low, right-associative binding precedence, so it -- sometimes allows parentheses to be omitted; for example: -- --
-- f $ g $ h x = f (g (h x)) ---- -- It is also useful in higher-order situations, such as map -- ($ 0) xs, or zipWith ($) fs xs. ($) :: (a -> b) -> a -> b infixr 0 $ -- | error stops execution and displays an error message. error :: HasCallStack => [Char] -> a -- | A special case of error. It is expected that compilers will -- recognize this and insert error messages which are more appropriate to -- the context in which undefined appears. undefined :: HasCallStack => a -- | const x is a unary function which evaluates to x for -- all inputs. -- -- For instance, -- --
-- >>> map (const 42) [0..3] -- [42,42,42,42] --const :: a -> b -> a -- | A fixed-precision integer type with at least the range [-2^29 .. -- 2^29-1]. The exact range for a given implementation can be -- determined by using minBound and maxBound from the -- Bounded class. data Int :: * -- | 8-bit signed integer type data Int8 :: * -- | 16-bit signed integer type data Int16 :: * -- | 32-bit signed integer type data Int32 :: * -- | 64-bit signed integer type data Int64 :: * -- | A Word is an unsigned integral type, with the same size as -- Int. data Word :: * -- | 8-bit unsigned integer type data Word8 :: * -- | 16-bit unsigned integer type data Word16 :: * -- | 32-bit unsigned integer type data Word32 :: * -- | 64-bit unsigned integer type data Word64 :: * -- | Single-precision floating point numbers. It is desirable that this -- type be at least equal in range and precision to the IEEE -- single-precision type. data Float :: * -- | Double-precision floating point numbers. It is desirable that this -- type be at least equal in range and precision to the IEEE -- double-precision type. data Double :: * data Bool :: * False :: Bool True :: Bool -- | The character type Char is an enumeration whose values -- represent Unicode (or equivalently ISO/IEC 10646) characters (see -- http://www.unicode.org/ for details). This set extends the ISO -- 8859-1 (Latin-1) character set (the first 256 characters), which is -- itself an extension of the ASCII character set (the first 128 -- characters). A character literal in Haskell has type Char. -- -- To convert a Char to or from the corresponding Int value -- defined by Unicode, use toEnum and fromEnum from the -- Enum class respectively (or equivalently ord and -- chr). data Char :: * -- | Haskell type representing the C float type. data CFloat :: * -- | Haskell type representing the C double type. data CDouble :: * -- | Haskell type representing the C short type. data CShort :: * -- | Haskell type representing the C unsigned short type. data CUShort :: * -- | Haskell type representing the C int type. data CInt :: * -- | Haskell type representing the C unsigned int type. data CUInt :: * -- | Haskell type representing the C long type. data CLong :: * -- | Haskell type representing the C unsigned long type. data CULong :: * -- | Haskell type representing the C long long type. data CLLong :: * -- | Haskell type representing the C unsigned long long type. data CULLong :: * -- | Haskell type representing the C char type. data CChar :: * -- | Haskell type representing the C signed char type. data CSChar :: * -- | Haskell type representing the C unsigned char type. data CUChar :: * -- | All scalar types class Typeable a => IsScalar a -- | Numeric types class (Num a, IsScalar a) => IsNum a -- | Bounded types class IsBounded a -- | Integral types class (IsScalar a, IsNum a, IsBounded a) => IsIntegral a -- | Floating types class (Floating a, IsScalar a, IsNum a) => IsFloating a -- | Non-numeric types class IsNonNum a -- | Monoid instances for Accelerate module Data.Array.Accelerate.Data.Monoid -- | The class of monoids (types with an associative binary operation that -- has an identity). Instances should satisfy the following laws: -- --
mappend mempty x = x
mappend x mempty = x
mappend x (mappend y z) = mappend (mappend x y) z
mconcat = foldr mappend mempty
-- >>> let sum = Fold (lift . Sum) (getSum . unlift) -- -- >>> let length = Fold (\_ -> 1) (getSum . unlift) ---- -- The key is that Folds can be combined using Applicative -- in order to produce multiple outputs from a single reduction of -- the array. For example: -- --
-- >>> let average = (/) <$> sum <*> length ---- -- This computes both the sum of the array as well as its length in a -- single traversal, then combines both results to compute the average. -- -- Because Fold has some numeric instances, this can also be -- defined more succinctly as: -- --
-- >>> let average = sum / length ---- -- A more complex example: -- --
-- >>> let sumOfSquares = Fold (lift . Sum . (^2)) (getSum . unlift) -- -- >>> let standardDeviation = sqrt ((sumOfSquares / length) - (sum / length) ^ 2) ---- -- These will all execute with a single reduction kernel and a single map -- to summarise (combine) the results. data Fold i o [Fold] :: (Elt w, Monoid (Exp w)) => (i -> Exp w) -> (Exp w -> o) -> Fold i o -- | Apply a Fold to an array. runFold :: (Shape sh, Elt i, Elt o) => Fold (Exp i) (Exp o) -> Acc (Array (sh :. Int) i) -> Acc (Array sh o) instance GHC.Base.Functor (Data.Array.Accelerate.Data.Fold.Fold i) instance GHC.Base.Applicative (Data.Array.Accelerate.Data.Fold.Fold i) instance Data.Array.Accelerate.Classes.Num.Num b => GHC.Num.Num (Data.Array.Accelerate.Data.Fold.Fold a (Data.Array.Accelerate.Smart.Exp b)) instance Data.Array.Accelerate.Classes.Fractional.Fractional b => GHC.Real.Fractional (Data.Array.Accelerate.Data.Fold.Fold a (Data.Array.Accelerate.Smart.Exp b)) instance Data.Array.Accelerate.Classes.Floating.Floating b => GHC.Float.Floating (Data.Array.Accelerate.Data.Fold.Fold a (Data.Array.Accelerate.Smart.Exp b))