packages feed

accelerate 0.15.1.0 → 1.0.0.0

raw patch · 73 files changed

+21557/−8841 lines, 73 filesdep +Win32dep +asyncdep +base-orphansdep −arraydep −blaze-htmldep −blaze-markupdep ~basedep ~containersdep ~fclabelsPVP ok

version bump matches the API change (PVP)

Dependencies added: Win32, async, base-orphans, deepseq, ekg, ekg-core, exceptions, time, transformers, unique

Dependencies removed: array, blaze-html, blaze-markup, bytestring

Dependency ranges changed: base, containers, fclabels, hashable, hashtables, pretty, text, unix, unordered-containers

API changes (from Hackage documentation)

- Data.Array.Accelerate: (&&*) :: Exp Bool -> Exp Bool -> Exp Bool
- Data.Array.Accelerate: (/=*) :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp Bool
- Data.Array.Accelerate: (<*) :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp Bool
- Data.Array.Accelerate: (<=*) :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp Bool
- Data.Array.Accelerate: (==*) :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp Bool
- Data.Array.Accelerate: (>*) :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp Bool
- Data.Array.Accelerate: (>=*) :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp Bool
- Data.Array.Accelerate: (||*) :: Exp Bool -> Exp Bool -> Exp Bool
- Data.Array.Accelerate: arrayDim :: Shape sh => sh -> Int
- Data.Array.Accelerate: bit :: (Elt t, IsIntegral t) => Exp Int -> Exp t
- Data.Array.Accelerate: clearBit :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t
- Data.Array.Accelerate: complementBit :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t
- Data.Array.Accelerate: foreignAcc2 :: (Arrays acc, Arrays res, Foreign ff1, Foreign ff2) => ff1 acc res -> ff2 acc res -> (Acc acc -> Acc res) -> Acc acc -> Acc res
- Data.Array.Accelerate: foreignAcc3 :: (Arrays acc, Arrays res, Foreign ff1, Foreign ff2, Foreign ff3) => ff1 acc res -> ff2 acc res -> ff3 acc res -> (Acc acc -> Acc res) -> Acc acc -> Acc res
- Data.Array.Accelerate: foreignExp2 :: (Elt e, Elt res, Foreign ff1, Foreign ff2) => ff1 e res -> ff2 e res -> (Exp e -> Exp res) -> Exp e -> Exp res
- Data.Array.Accelerate: foreignExp3 :: (Elt e, Elt res, Foreign ff1, Foreign ff2, Foreign ff3) => ff1 e res -> ff2 e res -> ff3 e res -> (Exp e -> Exp res) -> Exp e -> Exp res
- Data.Array.Accelerate: fromIArray :: (EltRepr ix ~ EltRepr sh, IArray a e, Ix ix, Shape sh, Elt ix, Elt e) => a ix e -> Array sh e
- Data.Array.Accelerate: gatherIf :: (Elt e, Elt e') => Acc (Vector Int) -> Acc (Vector e) -> (Exp e -> Exp Bool) -> Acc (Vector e') -> Acc (Vector e') -> Acc (Vector e')
- Data.Array.Accelerate: rotate :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t
- Data.Array.Accelerate: rotateL :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t
- Data.Array.Accelerate: rotateR :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t
- Data.Array.Accelerate: scatterIf :: (Elt e, Elt e') => Acc (Vector Int) -> Acc (Vector e) -> (Exp e -> Exp Bool) -> Acc (Vector e') -> Acc (Vector e') -> Acc (Vector e')
- Data.Array.Accelerate: setBit :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t
- Data.Array.Accelerate: shift :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t
- Data.Array.Accelerate: shiftL :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t
- Data.Array.Accelerate: shiftR :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t
- Data.Array.Accelerate: testBit :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp Bool
- Data.Array.Accelerate: toIArray :: (EltRepr ix ~ EltRepr sh, IArray a e, Ix ix, Shape sh, Elt ix, Elt e) => Array sh e -> a ix e
- Data.Array.Accelerate.Data.Complex: instance [incoherent] (Elt a, IsFloating a) => Fractional (Exp (Complex a))
- Data.Array.Accelerate.Data.Complex: instance [incoherent] (Elt a, IsFloating a) => Num (Exp (Complex a))
- Data.Array.Accelerate.Data.Complex: instance [incoherent] (Elt a, IsFloating a, RealFloat a) => Floating (Exp (Complex a))
- Data.Array.Accelerate.Data.Complex: instance [incoherent] (Lift Exp a, Elt (Plain a)) => Lift Exp (Complex a)
- Data.Array.Accelerate.Data.Complex: instance [incoherent] Elt a => Elt (Complex a)
- Data.Array.Accelerate.Data.Complex: instance [incoherent] Elt a => Unlift Exp (Complex (Exp a))
- Data.Array.Accelerate.Data.Complex: instance [incoherent] IsTuple (Complex a)
- Data.Array.Accelerate.Interpreter: stream :: (Arrays a, Arrays b) => (Acc a -> Acc b) -> [a] -> [b]
+ Data.Array.Accelerate: ($) :: (a -> b) -> a -> b
+ Data.Array.Accelerate: (&&) :: Exp Bool -> Exp Bool -> Exp Bool
+ Data.Array.Accelerate: (*) :: Num a => a -> a -> a
+ Data.Array.Accelerate: (**) :: Floating a => a -> a -> a
+ Data.Array.Accelerate: (+) :: Num a => a -> a -> a
+ Data.Array.Accelerate: (-) :: Num a => a -> a -> a
+ Data.Array.Accelerate: (.) :: (b -> c) -> (a -> b) -> a -> c
+ Data.Array.Accelerate: (/) :: Fractional a => a -> a -> a
+ Data.Array.Accelerate: (/=) :: Eq a => Exp a -> Exp a -> Exp Bool
+ Data.Array.Accelerate: (<) :: Ord a => Exp a -> Exp a -> Exp Bool
+ Data.Array.Accelerate: (<=) :: Ord a => Exp a -> Exp a -> Exp Bool
+ Data.Array.Accelerate: (==) :: Eq a => Exp a -> Exp a -> Exp Bool
+ Data.Array.Accelerate: (>) :: Ord a => Exp a -> Exp a -> Exp Bool
+ Data.Array.Accelerate: (>=) :: Ord a => Exp a -> Exp a -> Exp Bool
+ Data.Array.Accelerate: (^) :: forall a b. (Num a, Integral b) => Exp a -> Exp b -> Exp a
+ Data.Array.Accelerate: (^^) :: (Fractional a, Integral b) => Exp a -> Exp b -> Exp a
+ Data.Array.Accelerate: (||) :: Exp Bool -> Exp Bool -> Exp Bool
+ Data.Array.Accelerate: False :: Bool
+ Data.Array.Accelerate: True :: Bool
+ Data.Array.Accelerate: abs :: Num a => a -> a
+ Data.Array.Accelerate: acos :: Floating a => a -> a
+ Data.Array.Accelerate: acosh :: Floating a => a -> a
+ Data.Array.Accelerate: arrayRank :: Shape sh => sh -> Int
+ Data.Array.Accelerate: asin :: Floating a => a -> a
+ Data.Array.Accelerate: asinh :: Floating a => a -> a
+ Data.Array.Accelerate: atan :: Floating a => a -> a
+ Data.Array.Accelerate: atan2 :: RealFloat a => Exp a -> Exp a -> Exp a
+ Data.Array.Accelerate: atanh :: Floating a => a -> a
+ Data.Array.Accelerate: bitcast :: (Elt a, Elt b, IsScalar a, IsScalar b, BitSizeEq a b) => Exp a -> Exp b
+ Data.Array.Accelerate: class Elt a => Eq a where x == y = mkLNot (x /= y) x /= y = mkLNot (x == y)
+ Data.Array.Accelerate: class FromIntegral a b
+ Data.Array.Accelerate: class IfThenElse t where type EltT t a :: Constraint where {
+ Data.Array.Accelerate: 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
+ Data.Array.Accelerate: 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"
+ Data.Array.Accelerate: class (Real a, Fractional a) => RealFrac a
+ Data.Array.Accelerate: class ToFloating a b
+ Data.Array.Accelerate: compute :: Arrays a => Acc a -> Acc a
+ Data.Array.Accelerate: const :: a -> b -> a
+ Data.Array.Accelerate: cos :: Floating a => a -> a
+ Data.Array.Accelerate: cosh :: Floating a => a -> a
+ Data.Array.Accelerate: decodeFloat :: RealFloat a => Exp a -> (Exp Int64, Exp Int)
+ Data.Array.Accelerate: div :: Integral a => a -> a -> a
+ Data.Array.Accelerate: div' :: (RealFrac a, Elt b, IsIntegral b) => Exp a -> Exp a -> Exp b
+ Data.Array.Accelerate: divMod :: Integral a => a -> a -> (a, a)
+ Data.Array.Accelerate: divMod' :: (Floating a, RealFrac a, Num b, IsIntegral b, ToFloating b a) => Exp a -> Exp a -> (Exp b, Exp a)
+ Data.Array.Accelerate: encodeFloat :: RealFloat a => Exp Int64 -> Exp Int -> Exp a
+ Data.Array.Accelerate: error :: HasCallStack => [Char] -> a
+ Data.Array.Accelerate: exp :: Floating a => a -> a
+ Data.Array.Accelerate: exponent :: RealFloat a => Exp a -> Exp Int
+ Data.Array.Accelerate: floatDigits :: (RealFloat a, RealFloat a) => Exp a -> Exp Int
+ Data.Array.Accelerate: floatRadix :: (RealFloat a, RealFloat a) => Exp a -> Exp Int64
+ Data.Array.Accelerate: floatRange :: (RealFloat a, RealFloat a) => Exp a -> (Exp Int, Exp Int)
+ Data.Array.Accelerate: fromInteger :: Num a => Integer -> a
+ Data.Array.Accelerate: fromRational :: Fractional a => Rational -> a
+ Data.Array.Accelerate: gcd :: Integral a => Exp a -> Exp a -> Exp a
+ Data.Array.Accelerate: ifThenElse :: (IfThenElse t, EltT t a) => Exp Bool -> t a -> t a -> t a
+ Data.Array.Accelerate: ilift3 :: (Exp Int -> Exp Int -> Exp Int -> Exp Int) -> Exp DIM1 -> Exp DIM1 -> Exp DIM1 -> Exp DIM1
+ Data.Array.Accelerate: imap :: (Shape sh, Elt a, Elt b) => (Exp sh -> Exp a -> Exp b) -> Acc (Array sh a) -> Acc (Array sh b)
+ Data.Array.Accelerate: index3 :: (Elt i, Slice (Z :. i), Slice ((Z :. i) :. i)) => Exp i -> Exp i -> Exp i -> Exp (((Z :. i) :. i) :. i)
+ Data.Array.Accelerate: indexed :: (Shape sh, Elt a) => Acc (Array sh a) -> Acc (Array sh (sh, a))
+ Data.Array.Accelerate: infix 0 ?
+ Data.Array.Accelerate: infixl 1 >->
+ Data.Array.Accelerate: infixl 9 !!
+ Data.Array.Accelerate: infixr 0 $
+ Data.Array.Accelerate: infixr 2 ||
+ Data.Array.Accelerate: infixr 3 &&
+ Data.Array.Accelerate: infixr 5 ++
+ Data.Array.Accelerate: infixr 8 ^^
+ Data.Array.Accelerate: infixr 9 .
+ Data.Array.Accelerate: isDenormalized :: RealFloat a => Exp a -> Exp Bool
+ Data.Array.Accelerate: isIEEE :: (RealFloat a, RealFloat a) => Exp a -> Exp Bool
+ Data.Array.Accelerate: isInfinite :: RealFloat a => Exp a -> Exp Bool
+ Data.Array.Accelerate: isNaN :: RealFloat a => Exp a -> Exp Bool
+ Data.Array.Accelerate: isNegativeZero :: RealFloat a => Exp a -> Exp Bool
+ Data.Array.Accelerate: 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)
+ Data.Array.Accelerate: 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)
+ Data.Array.Accelerate: 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)
+ Data.Array.Accelerate: 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)
+ Data.Array.Accelerate: 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)
+ Data.Array.Accelerate: 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)
+ Data.Array.Accelerate: 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)
+ Data.Array.Accelerate: 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)
+ Data.Array.Accelerate: lcm :: Integral a => Exp a -> Exp a -> Exp a
+ Data.Array.Accelerate: 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)
+ Data.Array.Accelerate: log :: Floating a => a -> a
+ Data.Array.Accelerate: logBase :: Floating a => a -> a -> a
+ Data.Array.Accelerate: max :: Ord a => Exp a -> Exp a -> Exp a
+ Data.Array.Accelerate: maxBound :: Bounded a => a
+ Data.Array.Accelerate: min :: Ord a => Exp a -> Exp a -> Exp a
+ Data.Array.Accelerate: minBound :: Bounded a => a
+ Data.Array.Accelerate: mod :: Integral a => a -> a -> a
+ Data.Array.Accelerate: mod' :: (Floating a, RealFrac a, ToFloating Int a) => Exp a -> Exp a -> Exp a
+ Data.Array.Accelerate: negate :: Num a => a -> a
+ Data.Array.Accelerate: pi :: Floating a => a
+ Data.Array.Accelerate: properFraction :: (RealFrac a, Num b, ToFloating b a, IsIntegral b) => Exp a -> (Exp b, Exp a)
+ Data.Array.Accelerate: quot :: Integral a => a -> a -> a
+ Data.Array.Accelerate: quotRem :: Integral a => a -> a -> (a, a)
+ Data.Array.Accelerate: recip :: Fractional a => a -> a
+ Data.Array.Accelerate: rem :: Integral a => a -> a -> a
+ Data.Array.Accelerate: scaleFloat :: RealFloat a => Exp Int -> Exp a -> Exp a
+ Data.Array.Accelerate: significand :: RealFloat a => Exp a -> Exp a
+ Data.Array.Accelerate: signum :: Num a => a -> a
+ Data.Array.Accelerate: sin :: Floating a => a -> a
+ Data.Array.Accelerate: sinh :: Floating a => a -> a
+ Data.Array.Accelerate: sqrt :: Floating a => a -> a
+ Data.Array.Accelerate: subtract :: Num a => Exp a -> Exp a -> Exp a
+ Data.Array.Accelerate: tan :: Floating a => a -> a
+ Data.Array.Accelerate: tanh :: Floating a => a -> a
+ Data.Array.Accelerate: toFloating :: (ToFloating a b, Num a, Floating b) => Exp a -> Exp b
+ Data.Array.Accelerate: type Bounded a = (Elt a, Bounded (Exp a))
+ Data.Array.Accelerate: type Floating a = (Fractional a, Floating (Exp a))
+ Data.Array.Accelerate: type Fractional a = (Num a, Fractional (Exp a))
+ Data.Array.Accelerate: type Integral a = (Enum a, Real a, Integral (Exp a))
+ Data.Array.Accelerate: type Num a = (Elt a, Num (Exp a))
+ Data.Array.Accelerate: type family Plain e;
+ Data.Array.Accelerate: undefined :: HasCallStack => a
+ Data.Array.Accelerate: unindex3 :: forall i. (Elt i, Slice (Z :. i), Slice ((Z :. i) :. i)) => Exp (((Z :. i) :. i) :. i) -> Exp (i, i, i)
+ Data.Array.Accelerate: }
+ Data.Array.Accelerate.Data.Bits: (.&.) :: Bits a => Exp a -> Exp a -> Exp a
+ Data.Array.Accelerate.Data.Bits: (.|.) :: Bits a => Exp a -> Exp a -> Exp a
+ Data.Array.Accelerate.Data.Bits: bit :: Bits a => Exp Int -> Exp a
+ Data.Array.Accelerate.Data.Bits: class Eq a => Bits a where shift x i = cond (i < 0) (x `shiftR` (- i)) $ cond (i > 0) (x `shiftL` i) $ x rotate x i = cond (i < 0) (x `rotateR` (- i)) $ cond (i > 0) (x `rotateL` i) $ x zeroBits = clearBit (bit 0) 0 setBit x i = x .|. bit i clearBit x i = x .&. complement (bit i) complementBit x i = x `xor` bit i shiftL x i = x `shift` i unsafeShiftL = shiftL shiftR x i = x `shift` (- i) unsafeShiftR = shiftR rotateL x i = x `rotate` i rotateR x i = x `rotate` (- i)
+ Data.Array.Accelerate.Data.Bits: class Bits b => FiniteBits b
+ Data.Array.Accelerate.Data.Bits: clearBit :: Bits a => Exp a -> Exp Int -> Exp a
+ Data.Array.Accelerate.Data.Bits: complement :: Bits a => Exp a -> Exp a
+ Data.Array.Accelerate.Data.Bits: complementBit :: Bits a => Exp a -> Exp Int -> Exp a
+ Data.Array.Accelerate.Data.Bits: countLeadingZeros :: FiniteBits b => Exp b -> Exp Int
+ Data.Array.Accelerate.Data.Bits: countTrailingZeros :: FiniteBits b => Exp b -> Exp Int
+ Data.Array.Accelerate.Data.Bits: finiteBitSize :: FiniteBits b => Exp b -> Exp Int
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.Bits Foreign.C.Types.CInt
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.Bits Foreign.C.Types.CLLong
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.Bits Foreign.C.Types.CLong
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.Bits Foreign.C.Types.CShort
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.Bits Foreign.C.Types.CUInt
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.Bits Foreign.C.Types.CULLong
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.Bits Foreign.C.Types.CULong
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.Bits Foreign.C.Types.CUShort
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.Bits GHC.Int.Int16
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.Bits GHC.Int.Int32
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.Bits GHC.Int.Int64
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.Bits GHC.Int.Int8
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.Bits GHC.Types.Bool
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.Bits GHC.Types.Int
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.Bits GHC.Types.Word
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.Bits GHC.Word.Word16
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.Bits GHC.Word.Word32
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.Bits GHC.Word.Word64
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.Bits GHC.Word.Word8
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.FiniteBits Foreign.C.Types.CInt
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.FiniteBits Foreign.C.Types.CLLong
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.FiniteBits Foreign.C.Types.CLong
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.FiniteBits Foreign.C.Types.CShort
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.FiniteBits Foreign.C.Types.CUInt
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.FiniteBits Foreign.C.Types.CULLong
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.FiniteBits Foreign.C.Types.CULong
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.FiniteBits Foreign.C.Types.CUShort
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.FiniteBits GHC.Int.Int16
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.FiniteBits GHC.Int.Int32
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.FiniteBits GHC.Int.Int64
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.FiniteBits GHC.Int.Int8
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.FiniteBits GHC.Types.Bool
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.FiniteBits GHC.Types.Int
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.FiniteBits GHC.Types.Word
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.FiniteBits GHC.Word.Word16
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.FiniteBits GHC.Word.Word32
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.FiniteBits GHC.Word.Word64
+ Data.Array.Accelerate.Data.Bits: instance Data.Array.Accelerate.Data.Bits.FiniteBits GHC.Word.Word8
+ Data.Array.Accelerate.Data.Bits: isSigned :: Bits a => Exp a -> Exp Bool
+ Data.Array.Accelerate.Data.Bits: popCount :: Bits a => Exp a -> Exp Int
+ Data.Array.Accelerate.Data.Bits: rotate :: Bits a => Exp a -> Exp Int -> Exp a
+ Data.Array.Accelerate.Data.Bits: rotateL :: Bits a => Exp a -> Exp Int -> Exp a
+ Data.Array.Accelerate.Data.Bits: rotateR :: Bits a => Exp a -> Exp Int -> Exp a
+ Data.Array.Accelerate.Data.Bits: setBit :: Bits a => Exp a -> Exp Int -> Exp a
+ Data.Array.Accelerate.Data.Bits: shift :: Bits a => Exp a -> Exp Int -> Exp a
+ Data.Array.Accelerate.Data.Bits: shiftL :: Bits a => Exp a -> Exp Int -> Exp a
+ Data.Array.Accelerate.Data.Bits: shiftR :: Bits a => Exp a -> Exp Int -> Exp a
+ Data.Array.Accelerate.Data.Bits: testBit :: Bits a => Exp a -> Exp Int -> Exp Bool
+ Data.Array.Accelerate.Data.Bits: unsafeShiftL :: Bits a => Exp a -> Exp Int -> Exp a
+ Data.Array.Accelerate.Data.Bits: unsafeShiftR :: Bits a => Exp a -> Exp Int -> Exp a
+ Data.Array.Accelerate.Data.Bits: xor :: Bits a => Exp a -> Exp a -> Exp a
+ Data.Array.Accelerate.Data.Bits: zeroBits :: Bits a => Exp a
+ Data.Array.Accelerate.Data.Complex: 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)
+ Data.Array.Accelerate.Data.Complex: 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)
+ Data.Array.Accelerate.Data.Complex: instance Data.Array.Accelerate.Array.Sugar.Elt a => Data.Array.Accelerate.Array.Sugar.Elt (Data.Complex.Complex a)
+ Data.Array.Accelerate.Data.Complex: 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))
+ Data.Array.Accelerate.Data.Complex: instance Data.Array.Accelerate.Classes.Eq.Eq a => Data.Array.Accelerate.Classes.Eq.Eq (Data.Complex.Complex a)
+ Data.Array.Accelerate.Data.Complex: instance Data.Array.Accelerate.Classes.RealFloat.RealFloat a => GHC.Float.Floating (Data.Array.Accelerate.Smart.Exp (Data.Complex.Complex a))
+ Data.Array.Accelerate.Data.Complex: instance Data.Array.Accelerate.Classes.RealFloat.RealFloat a => GHC.Num.Num (Data.Array.Accelerate.Smart.Exp (Data.Complex.Complex a))
+ Data.Array.Accelerate.Data.Complex: instance Data.Array.Accelerate.Classes.RealFloat.RealFloat a => GHC.Real.Fractional (Data.Array.Accelerate.Smart.Exp (Data.Complex.Complex a))
+ Data.Array.Accelerate.Data.Complex: instance cst a => Data.Array.Accelerate.Product.IsProduct cst (Data.Complex.Complex a)
+ Data.Array.Accelerate.Data.Fold: [Fold] :: (Elt w, Monoid (Exp w)) => (i -> Exp w) -> (Exp w -> o) -> Fold i o
+ Data.Array.Accelerate.Data.Fold: data Fold i o
+ Data.Array.Accelerate.Data.Fold: instance Data.Array.Accelerate.Classes.Floating.Floating b => GHC.Float.Floating (Data.Array.Accelerate.Data.Fold.Fold a (Data.Array.Accelerate.Smart.Exp b))
+ Data.Array.Accelerate.Data.Fold: instance Data.Array.Accelerate.Classes.Fractional.Fractional b => GHC.Real.Fractional (Data.Array.Accelerate.Data.Fold.Fold a (Data.Array.Accelerate.Smart.Exp b))
+ Data.Array.Accelerate.Data.Fold: instance Data.Array.Accelerate.Classes.Num.Num b => GHC.Num.Num (Data.Array.Accelerate.Data.Fold.Fold a (Data.Array.Accelerate.Smart.Exp b))
+ Data.Array.Accelerate.Data.Fold: instance GHC.Base.Applicative (Data.Array.Accelerate.Data.Fold.Fold i)
+ Data.Array.Accelerate.Data.Fold: instance GHC.Base.Functor (Data.Array.Accelerate.Data.Fold.Fold i)
+ Data.Array.Accelerate.Data.Fold: runFold :: (Shape sh, Elt i, Elt o) => Fold (Exp i) (Exp o) -> Acc (Array (sh :. Int) i) -> Acc (Array sh o)
+ Data.Array.Accelerate.Data.Monoid: (<>) :: Monoid m => m -> m -> m
+ Data.Array.Accelerate.Data.Monoid: Product :: a -> Product a
+ Data.Array.Accelerate.Data.Monoid: Sum :: a -> Sum a
+ Data.Array.Accelerate.Data.Monoid: [getProduct] :: Product a -> a
+ Data.Array.Accelerate.Data.Monoid: [getSum] :: Sum a -> a
+ Data.Array.Accelerate.Data.Monoid: class Monoid a
+ Data.Array.Accelerate.Data.Monoid: infixr 6 <>
+ Data.Array.Accelerate.Data.Monoid: instance (Data.Array.Accelerate.Array.Sugar.Elt a, Data.Array.Accelerate.Array.Sugar.Elt b, Data.Array.Accelerate.Array.Sugar.Elt c, Data.Array.Accelerate.Array.Sugar.Elt d, Data.Array.Accelerate.Array.Sugar.Elt e, GHC.Base.Monoid (Data.Array.Accelerate.Smart.Exp a), GHC.Base.Monoid (Data.Array.Accelerate.Smart.Exp b), GHC.Base.Monoid (Data.Array.Accelerate.Smart.Exp c), GHC.Base.Monoid (Data.Array.Accelerate.Smart.Exp d), GHC.Base.Monoid (Data.Array.Accelerate.Smart.Exp e)) => GHC.Base.Monoid (Data.Array.Accelerate.Smart.Exp (a, b, c, d, e))
+ Data.Array.Accelerate.Data.Monoid: instance (Data.Array.Accelerate.Array.Sugar.Elt a, Data.Array.Accelerate.Array.Sugar.Elt b, Data.Array.Accelerate.Array.Sugar.Elt c, Data.Array.Accelerate.Array.Sugar.Elt d, GHC.Base.Monoid (Data.Array.Accelerate.Smart.Exp a), GHC.Base.Monoid (Data.Array.Accelerate.Smart.Exp b), GHC.Base.Monoid (Data.Array.Accelerate.Smart.Exp c), GHC.Base.Monoid (Data.Array.Accelerate.Smart.Exp d)) => GHC.Base.Monoid (Data.Array.Accelerate.Smart.Exp (a, b, c, d))
+ Data.Array.Accelerate.Data.Monoid: instance (Data.Array.Accelerate.Array.Sugar.Elt a, Data.Array.Accelerate.Array.Sugar.Elt b, Data.Array.Accelerate.Array.Sugar.Elt c, GHC.Base.Monoid (Data.Array.Accelerate.Smart.Exp a), GHC.Base.Monoid (Data.Array.Accelerate.Smart.Exp b), GHC.Base.Monoid (Data.Array.Accelerate.Smart.Exp c)) => GHC.Base.Monoid (Data.Array.Accelerate.Smart.Exp (a, b, c))
+ Data.Array.Accelerate.Data.Monoid: instance (Data.Array.Accelerate.Array.Sugar.Elt a, Data.Array.Accelerate.Array.Sugar.Elt b, GHC.Base.Monoid (Data.Array.Accelerate.Smart.Exp a), GHC.Base.Monoid (Data.Array.Accelerate.Smart.Exp b)) => GHC.Base.Monoid (Data.Array.Accelerate.Smart.Exp (a, b))
+ Data.Array.Accelerate.Data.Monoid: 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.Monoid.Product a)
+ Data.Array.Accelerate.Data.Monoid: 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.Monoid.Sum a)
+ Data.Array.Accelerate.Data.Monoid: instance Data.Array.Accelerate.Array.Sugar.Elt a => Data.Array.Accelerate.Array.Sugar.Elt (Data.Monoid.Product a)
+ Data.Array.Accelerate.Data.Monoid: instance Data.Array.Accelerate.Array.Sugar.Elt a => Data.Array.Accelerate.Array.Sugar.Elt (Data.Monoid.Sum a)
+ Data.Array.Accelerate.Data.Monoid: instance Data.Array.Accelerate.Array.Sugar.Elt a => Data.Array.Accelerate.Lift.Unlift Data.Array.Accelerate.Smart.Exp (Data.Monoid.Product (Data.Array.Accelerate.Smart.Exp a))
+ Data.Array.Accelerate.Data.Monoid: instance Data.Array.Accelerate.Array.Sugar.Elt a => Data.Array.Accelerate.Lift.Unlift Data.Array.Accelerate.Smart.Exp (Data.Monoid.Sum (Data.Array.Accelerate.Smart.Exp a))
+ Data.Array.Accelerate.Data.Monoid: instance Data.Array.Accelerate.Array.Sugar.Elt a => Data.Array.Accelerate.Product.IsProduct Data.Array.Accelerate.Array.Sugar.Elt (Data.Monoid.Product a)
+ Data.Array.Accelerate.Data.Monoid: instance Data.Array.Accelerate.Array.Sugar.Elt a => Data.Array.Accelerate.Product.IsProduct Data.Array.Accelerate.Array.Sugar.Elt (Data.Monoid.Sum a)
+ Data.Array.Accelerate.Data.Monoid: instance Data.Array.Accelerate.Classes.Eq.Eq a => Data.Array.Accelerate.Classes.Eq.Eq (Data.Monoid.Product a)
+ Data.Array.Accelerate.Data.Monoid: instance Data.Array.Accelerate.Classes.Eq.Eq a => Data.Array.Accelerate.Classes.Eq.Eq (Data.Monoid.Sum a)
+ Data.Array.Accelerate.Data.Monoid: instance Data.Array.Accelerate.Classes.Num.Num a => GHC.Base.Monoid (Data.Array.Accelerate.Smart.Exp (Data.Monoid.Product a))
+ Data.Array.Accelerate.Data.Monoid: instance Data.Array.Accelerate.Classes.Num.Num a => GHC.Base.Monoid (Data.Array.Accelerate.Smart.Exp (Data.Monoid.Sum a))
+ Data.Array.Accelerate.Data.Monoid: instance Data.Array.Accelerate.Classes.Num.Num a => GHC.Num.Num (Data.Array.Accelerate.Smart.Exp (Data.Monoid.Product a))
+ Data.Array.Accelerate.Data.Monoid: instance Data.Array.Accelerate.Classes.Num.Num a => GHC.Num.Num (Data.Array.Accelerate.Smart.Exp (Data.Monoid.Sum a))
+ Data.Array.Accelerate.Data.Monoid: instance Data.Array.Accelerate.Classes.Ord.Ord a => Data.Array.Accelerate.Classes.Ord.Ord (Data.Monoid.Product a)
+ Data.Array.Accelerate.Data.Monoid: instance Data.Array.Accelerate.Classes.Ord.Ord a => Data.Array.Accelerate.Classes.Ord.Ord (Data.Monoid.Sum a)
+ Data.Array.Accelerate.Data.Monoid: instance GHC.Base.Monoid (Data.Array.Accelerate.Smart.Exp ())
+ Data.Array.Accelerate.Data.Monoid: mappend :: Monoid a => a -> a -> a
+ Data.Array.Accelerate.Data.Monoid: mconcat :: Monoid a => [a] -> a
+ Data.Array.Accelerate.Data.Monoid: mempty :: Monoid a => a
+ Data.Array.Accelerate.Data.Monoid: newtype Product a :: * -> *
+ Data.Array.Accelerate.Data.Monoid: newtype Sum a :: * -> *
+ Data.Array.Accelerate.Interpreter: class (Typeable a, Typeable (ArrRepr a)) => Arrays a
- Data.Array.Accelerate: (!!) :: (Shape ix, Elt e) => Acc (Array ix e) -> Exp Int -> Exp e
+ Data.Array.Accelerate: (!!) :: (Shape sh, Elt e) => Acc (Array sh e) -> Exp Int -> Exp e
- Data.Array.Accelerate: (!) :: (Shape ix, Elt e) => Acc (Array ix e) -> Exp ix -> Exp e
+ Data.Array.Accelerate: (!) :: (Shape sh, Elt e) => Acc (Array sh e) -> Exp sh -> Exp e
- Data.Array.Accelerate: (++) :: (Slice sh, Shape sh, Elt e) => Acc (Array (sh :. Int) e) -> Acc (Array (sh :. Int) e) -> Acc (Array (sh :. Int) e)
+ Data.Array.Accelerate: (++) :: forall sh e. (Slice sh, Shape sh, Elt e) => Acc (Array (sh :. Int) e) -> Acc (Array (sh :. Int) e) -> Acc (Array (sh :. Int) e)
- Data.Array.Accelerate: afst :: (Arrays a, Arrays b) => Acc (a, b) -> Acc a
+ Data.Array.Accelerate: afst :: forall a b. (Arrays a, Arrays b) => Acc (a, b) -> Acc a
- Data.Array.Accelerate: asnd :: (Arrays a, Arrays b) => Acc (a, b) -> Acc b
+ Data.Array.Accelerate: asnd :: forall a b. (Arrays a, Arrays b) => Acc (a, b) -> Acc b
- Data.Array.Accelerate: backpermute :: (Shape ix, Shape ix', Elt a) => Exp ix' -> (Exp ix' -> Exp ix) -> Acc (Array ix a) -> Acc (Array ix' a)
+ Data.Array.Accelerate: backpermute :: (Shape sh, Shape sh', Elt a) => Exp sh' -> (Exp sh' -> Exp sh) -> Acc (Array sh a) -> Acc (Array sh' a)
- Data.Array.Accelerate: ceiling :: (Elt a, Elt b, IsFloating a, IsIntegral b) => Exp a -> Exp b
+ Data.Array.Accelerate: ceiling :: (RealFrac a, Elt b, IsIntegral b) => Exp a -> Exp b
- Data.Array.Accelerate: class (Typeable (ArrRepr a), Typeable (ArrRepr' a), Typeable a) => Arrays a
+ Data.Array.Accelerate: class (Typeable a, Typeable (ArrRepr a)) => Arrays a
- Data.Array.Accelerate: class (Show a, Typeable a, Typeable (EltRepr a), Typeable (EltRepr' a), ArrayElt (EltRepr a), ArrayElt (EltRepr' a)) => Elt a
+ Data.Array.Accelerate: class (Show a, Typeable a, Typeable (EltRepr a), ArrayElt (EltRepr a)) => Elt a
- Data.Array.Accelerate: class Lift c e where type family Plain e
+ Data.Array.Accelerate: class Lift c e where type Plain e where {
- Data.Array.Accelerate: class (Elt sh, Elt (Any sh), Shape (EltRepr sh)) => Shape sh where dim = dim . fromElt size = size . fromElt ignore = toElt ignore intersect sh1 sh2 = toElt (intersect (fromElt sh1) (fromElt sh2)) fromIndex sh ix = toElt (fromIndex (fromElt sh) ix) toIndex sh ix = toIndex (fromElt sh) (fromElt ix) bound sh ix bndy = case bound (fromElt sh) (fromElt ix) bndy of { Left v -> Left v Right ix' -> Right $ toElt ix' } iter sh f c r = iter (fromElt sh) (f . toElt) c r iter1 sh f r = iter1 (fromElt sh) (f . toElt) r rangeToShape (low, high) = toElt (rangeToShape (fromElt low, fromElt high)) shapeToRange ix = let (low, high) = shapeToRange (fromElt ix) in (toElt low, toElt high) shapeToList = shapeToList . fromElt listToShape = toElt . listToShape
+ Data.Array.Accelerate: class (Elt sh, Elt (Any sh), Shape (EltRepr sh), FullShape sh ~ sh, CoSliceShape sh ~ sh, SliceShape sh ~ Z) => Shape sh where rank = rank . fromElt size = size . fromElt empty = toElt empty ignore = toElt ignore intersect sh1 sh2 = toElt (intersect (fromElt sh1) (fromElt sh2)) union sh1 sh2 = toElt (union (fromElt sh1) (fromElt sh2)) fromIndex sh ix = toElt (fromIndex (fromElt sh) ix) toIndex sh ix = toIndex (fromElt sh) (fromElt ix) bound sh ix bndy = case bound (fromElt sh) (fromElt ix) bndy of { Left v -> Left v Right ix' -> Right $ toElt ix' } iter sh f c r = iter (fromElt sh) (f . toElt) c r iter1 sh f r = iter1 (fromElt sh) (f . toElt) r rangeToShape (low, high) = toElt (rangeToShape (fromElt low, fromElt high)) shapeToRange ix = let (low, high) = shapeToRange (fromElt ix) in (toElt low, toElt high) shapeToList = shapeToList . fromElt listToShape = toElt . listToShape
- Data.Array.Accelerate: class (Elt sl, Shape (SliceShape sl), Shape (CoSliceShape sl), Shape (FullShape sl)) => Slice sl where type family SliceShape sl :: * type family CoSliceShape sl :: * type family FullShape sl :: *
+ Data.Array.Accelerate: class (Elt sl, Shape (SliceShape sl), Shape (CoSliceShape sl), Shape (FullShape sl)) => Slice sl where type SliceShape sl :: * type CoSliceShape sl :: * type FullShape sl :: * where {
- Data.Array.Accelerate: drop :: Elt e => Exp Int -> Acc (Vector e) -> Acc (Vector e)
+ Data.Array.Accelerate: drop :: forall sh e. (Slice sh, Shape sh, Elt e) => Exp Int -> Acc (Array (sh :. Int) e) -> Acc (Array (sh :. Int) e)
- Data.Array.Accelerate: enumFromN :: (Shape sh, Elt e, IsNum e) => Exp sh -> Exp e -> Acc (Array sh e)
+ Data.Array.Accelerate: enumFromN :: (Shape sh, Num e, FromIntegral Int e) => Exp sh -> Exp e -> Acc (Array sh e)
- Data.Array.Accelerate: enumFromStepN :: (Shape sh, Elt e, IsNum e) => Exp sh -> Exp e -> Exp e -> Acc (Array sh e)
+ Data.Array.Accelerate: enumFromStepN :: (Shape sh, Num e, FromIntegral Int e) => Exp sh -> Exp e -> Exp e -> Acc (Array sh e)
- Data.Array.Accelerate: even :: (Elt a, IsIntegral a) => Exp a -> Exp Bool
+ Data.Array.Accelerate: even :: Integral a => Exp a -> Exp Bool
- Data.Array.Accelerate: filter :: Elt a => (Exp a -> Exp Bool) -> Acc (Vector a) -> Acc (Vector a)
+ Data.Array.Accelerate: 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)
- Data.Array.Accelerate: flatten :: (Shape ix, Elt a) => Acc (Array ix a) -> Acc (Vector a)
+ Data.Array.Accelerate: flatten :: forall sh e. (Shape sh, Elt e) => Acc (Array sh e) -> Acc (Vector e)
- Data.Array.Accelerate: floor :: (Elt a, Elt b, IsFloating a, IsIntegral b) => Exp a -> Exp b
+ Data.Array.Accelerate: floor :: (RealFrac a, Elt b, IsIntegral b) => Exp a -> Exp b
- Data.Array.Accelerate: fold :: (Shape ix, Elt a) => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Array (ix :. Int) a) -> Acc (Array ix a)
+ Data.Array.Accelerate: fold :: (Shape sh, Elt a) => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Array (sh :. Int) a) -> Acc (Array sh a)
- Data.Array.Accelerate: fold1 :: (Shape ix, Elt a) => (Exp a -> Exp a -> Exp a) -> Acc (Array (ix :. Int) a) -> Acc (Array ix a)
+ Data.Array.Accelerate: fold1 :: (Shape sh, Elt a) => (Exp a -> Exp a -> Exp a) -> Acc (Array (sh :. Int) a) -> Acc (Array sh a)
- Data.Array.Accelerate: fold1Seg :: (Shape ix, Elt a, Elt i, IsIntegral i) => (Exp a -> Exp a -> Exp a) -> Acc (Array (ix :. Int) a) -> Acc (Segments i) -> Acc (Array (ix :. Int) a)
+ Data.Array.Accelerate: 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)
- Data.Array.Accelerate: foldSeg :: (Shape ix, Elt a, Elt i, IsIntegral i) => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Array (ix :. Int) a) -> Acc (Segments i) -> Acc (Array (ix :. Int) a)
+ Data.Array.Accelerate: 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)
- Data.Array.Accelerate: foreignAcc :: (Arrays acc, Arrays res, Foreign ff) => ff acc res -> (Acc acc -> Acc res) -> Acc acc -> Acc res
+ Data.Array.Accelerate: foreignAcc :: (Arrays as, Arrays bs, Foreign asm) => asm (as -> bs) -> (Acc as -> Acc bs) -> Acc as -> Acc bs
- Data.Array.Accelerate: foreignExp :: (Elt e, Elt res, Foreign ff) => ff e res -> (Exp e -> Exp res) -> Exp e -> Exp res
+ Data.Array.Accelerate: foreignExp :: (Elt x, Elt y, Foreign asm) => asm (x -> y) -> (Exp x -> Exp y) -> Exp x -> Exp y
- Data.Array.Accelerate: fromIntegral :: (Elt a, Elt b, IsIntegral a, IsNum b) => Exp a -> Exp b
+ Data.Array.Accelerate: fromIntegral :: (FromIntegral a b, Integral a) => Exp a -> Exp b
- Data.Array.Accelerate: fst :: (Elt a, Elt b) => Exp (a, b) -> Exp a
+ Data.Array.Accelerate: fst :: forall a b. (Elt a, Elt b) => Exp (a, b) -> Exp a
- Data.Array.Accelerate: gather :: Elt e => Acc (Vector Int) -> Acc (Vector e) -> Acc (Vector e)
+ Data.Array.Accelerate: gather :: (Shape sh, Elt e) => Acc (Array sh Int) -> Acc (Vector e) -> Acc (Array sh e)
- Data.Array.Accelerate: generate :: (Shape ix, Elt a) => Exp ix -> (Exp ix -> Exp a) -> Acc (Array ix a)
+ Data.Array.Accelerate: generate :: (Shape sh, Elt a) => Exp sh -> (Exp sh -> Exp a) -> Acc (Array sh a)
- Data.Array.Accelerate: ignore :: Shape ix => Exp ix
+ Data.Array.Accelerate: ignore :: Shape sh => Exp sh
- Data.Array.Accelerate: indexHead :: Slice sh => Exp (sh :. Int) -> Exp Int
+ Data.Array.Accelerate: indexHead :: (Slice sh, Elt a) => Exp (sh :. a) -> Exp a
- Data.Array.Accelerate: indexTail :: Slice sh => Exp (sh :. Int) -> Exp sh
+ Data.Array.Accelerate: indexTail :: (Slice sh, Elt a) => Exp (sh :. a) -> Exp sh
- Data.Array.Accelerate: init :: Elt e => Acc (Vector e) -> Acc (Vector e)
+ Data.Array.Accelerate: init :: forall sh e. (Slice sh, Shape sh, Elt e) => Acc (Array (sh :. Int) e) -> Acc (Array (sh :. Int) e)
- Data.Array.Accelerate: iterate :: Elt a => Exp Int -> (Exp a -> Exp a) -> Exp a -> Exp a
+ Data.Array.Accelerate: iterate :: forall a. Elt a => Exp Int -> (Exp a -> Exp a) -> Exp a -> Exp a
- Data.Array.Accelerate: lift1 :: (Unlift Exp e1, Lift Exp e2) => (e1 -> e2) -> Exp (Plain e1) -> Exp (Plain e2)
+ Data.Array.Accelerate: lift1 :: (Unlift Exp a, Lift Exp b) => (a -> b) -> Exp (Plain a) -> Exp (Plain b)
- Data.Array.Accelerate: lift2 :: (Unlift Exp e1, Unlift Exp e2, Lift Exp e3) => (e1 -> e2 -> e3) -> Exp (Plain e1) -> Exp (Plain e2) -> Exp (Plain e3)
+ Data.Array.Accelerate: lift2 :: (Unlift Exp a, Unlift Exp b, Lift Exp c) => (a -> b -> c) -> Exp (Plain a) -> Exp (Plain b) -> Exp (Plain c)
- Data.Array.Accelerate: map :: (Shape ix, Elt a, Elt b) => (Exp a -> Exp b) -> Acc (Array ix a) -> Acc (Array ix b)
+ Data.Array.Accelerate: map :: (Shape sh, Elt a, Elt b) => (Exp a -> Exp b) -> Acc (Array sh a) -> Acc (Array sh b)
- Data.Array.Accelerate: maximum :: (Shape sh, Elt e, IsScalar e) => Acc (Array sh e) -> Acc (Scalar e)
+ Data.Array.Accelerate: maximum :: (Shape sh, Ord e) => Acc (Array sh e) -> Acc (Scalar e)
- Data.Array.Accelerate: minimum :: (Shape sh, Elt e, IsScalar e) => Acc (Array sh e) -> Acc (Scalar e)
+ Data.Array.Accelerate: minimum :: (Shape sh, Ord e) => Acc (Array sh e) -> Acc (Scalar e)
- Data.Array.Accelerate: null :: (Shape ix, Elt e) => Acc (Array ix e) -> Exp Bool
+ Data.Array.Accelerate: null :: (Shape sh, Elt e) => Acc (Array sh e) -> Exp Bool
- Data.Array.Accelerate: odd :: (Elt a, IsIntegral a) => Exp a -> Exp Bool
+ Data.Array.Accelerate: odd :: Integral a => Exp a -> Exp Bool
- Data.Array.Accelerate: permute :: (Shape ix, Shape ix', Elt a) => (Exp a -> Exp a -> Exp a) -> Acc (Array ix' a) -> (Exp ix -> Exp ix') -> Acc (Array ix a) -> Acc (Array ix' a)
+ Data.Array.Accelerate: permute :: (Shape sh, Shape sh', Elt a) => (Exp a -> Exp a -> Exp a) -> Acc (Array sh' a) -> (Exp sh -> Exp sh') -> Acc (Array sh a) -> Acc (Array sh' a)
- Data.Array.Accelerate: postscanl :: Elt a => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Vector a) -> Acc (Vector a)
+ Data.Array.Accelerate: postscanl :: (Shape sh, Elt a) => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Array (sh :. Int) a) -> Acc (Array (sh :. Int) a)
- Data.Array.Accelerate: postscanlSeg :: (Elt a, Elt i, IsIntegral i) => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Vector a) -> Acc (Segments i) -> Acc (Vector a)
+ Data.Array.Accelerate: 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)
- Data.Array.Accelerate: postscanr :: Elt a => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Vector a) -> Acc (Vector a)
+ Data.Array.Accelerate: postscanr :: (Shape sh, Elt a) => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Array (sh :. Int) a) -> Acc (Array (sh :. Int) a)
- Data.Array.Accelerate: postscanrSeg :: (Elt a, Elt i, IsIntegral i) => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Vector a) -> Acc (Segments i) -> Acc (Vector a)
+ Data.Array.Accelerate: 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)
- Data.Array.Accelerate: prescanl :: Elt a => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Vector a) -> Acc (Vector a)
+ Data.Array.Accelerate: prescanl :: (Shape sh, Elt a) => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Array (sh :. Int) a) -> Acc (Array (sh :. Int) a)
- Data.Array.Accelerate: prescanlSeg :: (Elt a, Elt i, IsIntegral i) => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Vector a) -> Acc (Segments i) -> Acc (Vector a)
+ Data.Array.Accelerate: 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)
- Data.Array.Accelerate: prescanr :: Elt a => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Vector a) -> Acc (Vector a)
+ Data.Array.Accelerate: prescanr :: (Shape sh, Elt a) => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Array (sh :. Int) a) -> Acc (Array (sh :. Int) a)
- Data.Array.Accelerate: prescanrSeg :: (Elt a, Elt i, IsIntegral i) => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Vector a) -> Acc (Segments i) -> Acc (Vector a)
+ Data.Array.Accelerate: 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)
- Data.Array.Accelerate: product :: (Shape sh, Elt e, IsNum e) => Acc (Array sh e) -> Acc (Scalar e)
+ Data.Array.Accelerate: product :: (Shape sh, Num e) => Acc (Array sh e) -> Acc (Scalar e)
- Data.Array.Accelerate: reshape :: (Shape ix, Shape ix', Elt e) => Exp ix -> Acc (Array ix' e) -> Acc (Array ix e)
+ Data.Array.Accelerate: reshape :: (Shape sh, Shape sh', Elt e) => Exp sh -> Acc (Array sh' e) -> Acc (Array sh e)
- Data.Array.Accelerate: round :: (Elt a, Elt b, IsFloating a, IsIntegral b) => Exp a -> Exp b
+ Data.Array.Accelerate: round :: (RealFrac a, Elt b, IsIntegral b) => Exp a -> Exp b
- Data.Array.Accelerate: scanl :: Elt a => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Vector a) -> Acc (Vector a)
+ Data.Array.Accelerate: scanl :: (Shape sh, Elt a) => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Array (sh :. Int) a) -> Acc (Array (sh :. Int) a)
- Data.Array.Accelerate: scanl' :: Elt a => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Vector a) -> (Acc (Vector a), Acc (Scalar a))
+ Data.Array.Accelerate: 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))
- Data.Array.Accelerate: scanl'Seg :: (Elt a, Elt i, IsIntegral i) => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Vector a) -> Acc (Segments i) -> Acc (Vector a, Vector a)
+ Data.Array.Accelerate: 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)
- Data.Array.Accelerate: scanl1 :: Elt a => (Exp a -> Exp a -> Exp a) -> Acc (Vector a) -> Acc (Vector a)
+ Data.Array.Accelerate: scanl1 :: (Shape sh, Elt a) => (Exp a -> Exp a -> Exp a) -> Acc (Array (sh :. Int) a) -> Acc (Array (sh :. Int) a)
- Data.Array.Accelerate: scanl1Seg :: (Elt a, Elt i, IsIntegral i) => (Exp a -> Exp a -> Exp a) -> Acc (Vector a) -> Acc (Segments i) -> Acc (Vector a)
+ Data.Array.Accelerate: 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)
- Data.Array.Accelerate: scanlSeg :: (Elt a, Elt i, IsIntegral i) => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Vector a) -> Acc (Segments i) -> Acc (Vector a)
+ Data.Array.Accelerate: 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)
- Data.Array.Accelerate: scanr :: Elt a => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Vector a) -> Acc (Vector a)
+ Data.Array.Accelerate: scanr :: (Shape sh, Elt a) => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Array (sh :. Int) a) -> Acc (Array (sh :. Int) a)
- Data.Array.Accelerate: scanr' :: Elt a => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Vector a) -> (Acc (Vector a), Acc (Scalar a))
+ Data.Array.Accelerate: 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))
- Data.Array.Accelerate: scanr'Seg :: (Elt a, Elt i, IsIntegral i) => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Vector a) -> Acc (Segments i) -> Acc (Vector a, Vector a)
+ Data.Array.Accelerate: 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)
- Data.Array.Accelerate: scanr1 :: Elt a => (Exp a -> Exp a -> Exp a) -> Acc (Vector a) -> Acc (Vector a)
+ Data.Array.Accelerate: scanr1 :: (Shape sh, Elt a) => (Exp a -> Exp a -> Exp a) -> Acc (Array (sh :. Int) a) -> Acc (Array (sh :. Int) a)
- Data.Array.Accelerate: scanr1Seg :: (Elt a, Elt i, IsIntegral i) => (Exp a -> Exp a -> Exp a) -> Acc (Vector a) -> Acc (Segments i) -> Acc (Vector a)
+ Data.Array.Accelerate: 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)
- Data.Array.Accelerate: scanrSeg :: (Elt a, Elt i, IsIntegral i) => (Exp a -> Exp a -> Exp a) -> Exp a -> Acc (Vector a) -> Acc (Segments i) -> Acc (Vector a)
+ Data.Array.Accelerate: 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)
- Data.Array.Accelerate: sfoldl :: (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
+ Data.Array.Accelerate: 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
- Data.Array.Accelerate: shape :: (Shape ix, Elt e) => Acc (Array ix e) -> Exp ix
+ Data.Array.Accelerate: shape :: (Shape sh, Elt e) => Acc (Array sh e) -> Exp sh
- Data.Array.Accelerate: shapeSize :: Shape ix => Exp ix -> Exp Int
+ Data.Array.Accelerate: shapeSize :: Shape sh => Exp sh -> Exp Int
- Data.Array.Accelerate: size :: (Shape ix, Elt e) => Acc (Array ix e) -> Exp Int
+ Data.Array.Accelerate: size :: (Shape sh, Elt e) => Acc (Array sh e) -> Exp Int
- Data.Array.Accelerate: slit :: Elt e => Exp Int -> Exp Int -> Acc (Vector e) -> Acc (Vector e)
+ Data.Array.Accelerate: slit :: forall sh e. (Slice sh, Shape sh, Elt e) => Exp Int -> Exp Int -> Acc (Array (sh :. Int) e) -> Acc (Array (sh :. Int) e)
- Data.Array.Accelerate: snd :: (Elt a, Elt b) => Exp (a, b) -> Exp b
+ Data.Array.Accelerate: snd :: forall a b. (Elt a, Elt b) => Exp (a, b) -> Exp b
- Data.Array.Accelerate: stencil :: (Shape ix, Elt a, Elt b, Stencil ix a stencil) => (stencil -> Exp b) -> Boundary a -> Acc (Array ix a) -> Acc (Array ix b)
+ Data.Array.Accelerate: stencil :: (Stencil sh a stencil, Elt b) => (stencil -> Exp b) -> Boundary a -> Acc (Array sh a) -> Acc (Array sh b)
- Data.Array.Accelerate: stencil2 :: (Shape ix, Elt a, Elt b, Elt c, Stencil ix a stencil1, Stencil ix b stencil2) => (stencil1 -> stencil2 -> Exp c) -> Boundary a -> Acc (Array ix a) -> Boundary b -> Acc (Array ix b) -> Acc (Array ix c)
+ Data.Array.Accelerate: 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)
- Data.Array.Accelerate: sum :: (Shape sh, Elt e, IsNum e) => Acc (Array sh e) -> Acc (Scalar e)
+ Data.Array.Accelerate: sum :: (Shape sh, Num e) => Acc (Array sh e) -> Acc (Scalar e)
- Data.Array.Accelerate: tail :: Elt e => Acc (Vector e) -> Acc (Vector e)
+ Data.Array.Accelerate: tail :: forall sh e. (Slice sh, Shape sh, Elt e) => Acc (Array (sh :. Int) e) -> Acc (Array (sh :. Int) e)
- Data.Array.Accelerate: take :: Elt e => Exp Int -> Acc (Vector e) -> Acc (Vector e)
+ Data.Array.Accelerate: take :: forall sh e. (Slice sh, Shape sh, Elt e) => Exp Int -> Acc (Array (sh :. Int) e) -> Acc (Array (sh :. Int) e)
- Data.Array.Accelerate: toList :: Array sh e -> [e]
+ Data.Array.Accelerate: toList :: forall sh e. Array sh e -> [e]
- Data.Array.Accelerate: truncate :: (Elt a, Elt b, IsFloating a, IsIntegral b) => Exp a -> Exp b
+ Data.Array.Accelerate: truncate :: (RealFrac a, Elt b, IsIntegral b) => Exp a -> Exp b
- Data.Array.Accelerate: unindex2 :: (Elt i, Slice (Z :. i)) => Exp ((Z :. i) :. i) -> Exp (i, i)
+ Data.Array.Accelerate: unindex2 :: forall i. (Elt i, Slice (Z :. i)) => Exp ((Z :. i) :. i) -> Exp (i, i)
- Data.Array.Accelerate: zipWith :: (Shape ix, Elt a, Elt b, Elt c) => (Exp a -> Exp b -> Exp c) -> Acc (Array ix a) -> Acc (Array ix b) -> Acc (Array ix c)
+ Data.Array.Accelerate: 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)
- Data.Array.Accelerate.Data.Complex: (:+) :: SrictNotUnpackeda -> SrictNotUnpackeda -> Complex a
+ Data.Array.Accelerate.Data.Complex: (:+) :: ~a -> ~a -> Complex a
- Data.Array.Accelerate.Data.Complex: cis :: (Elt a, IsFloating a) => Exp a -> Exp (Complex a)
+ Data.Array.Accelerate.Data.Complex: cis :: forall a. Floating a => Exp a -> Exp (Complex a)
- Data.Array.Accelerate.Data.Complex: conjugate :: (Elt a, IsNum a) => Exp (Complex a) -> Exp (Complex a)
+ Data.Array.Accelerate.Data.Complex: conjugate :: Num a => Exp (Complex a) -> Exp (Complex a)
- Data.Array.Accelerate.Data.Complex: magnitude :: (Elt a, IsFloating a) => Exp (Complex a) -> Exp a
+ Data.Array.Accelerate.Data.Complex: magnitude :: RealFloat a => Exp (Complex a) -> Exp a
- Data.Array.Accelerate.Data.Complex: mkPolar :: (Elt a, IsFloating a) => Exp a -> Exp a -> Exp (Complex a)
+ Data.Array.Accelerate.Data.Complex: mkPolar :: forall a. Floating a => Exp a -> Exp a -> Exp (Complex a)
- Data.Array.Accelerate.Data.Complex: phase :: (Elt a, IsFloating a) => Exp (Complex a) -> Exp a
+ Data.Array.Accelerate.Data.Complex: phase :: RealFloat a => Exp (Complex a) -> Exp a
- Data.Array.Accelerate.Data.Complex: polar :: (Elt a, IsFloating a) => Exp (Complex a) -> Exp (a, a)
+ Data.Array.Accelerate.Data.Complex: polar :: RealFloat a => Exp (Complex a) -> Exp (a, a)

Files

Data/Array/Accelerate.hs view
@@ -1,314 +1,534 @@ -- | -- Module      : Data.Array.Accelerate--- Copyright   : [2008..2014] Manuel M T Chakravarty, Gabriele Keller---               [2008..2009] Sean Lee---               [2009..2014] Trevor L. McDonell---               [2013..2014] Robert Clifton-Everest+-- Copyright   : [2008..2017] Manuel M T Chakravarty, Gabriele Keller+--               [2009..2017] Trevor L. McDonell+--               [2013..2017] Robert Clifton-Everest+--               [2014..2014] Frederik M. Madsen -- License     : BSD3 ----- Maintainer  : Manuel M T Chakravarty <chak@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au> -- Stability   : experimental -- Portability : non-portable (GHC extensions) ----- This module defines an embedded language of array computations for--- high-performance computing. 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 executed on a range of architectures.+-- @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. -- -- [/Abstract interface:/] ----- The types representing array computations are only exported abstractly —--- i.e., client code can generate array computations and submit them for--- execution, but it cannot inspect these computations. This is to allow for--- more flexibility for future extensions of this library.+-- The types representing array computations are only exported abstractly;+-- client code can generate array computations and submit them for execution,+-- but it cannot inspect these computations. This is to allow for more+-- flexibility for future extensions of this library. --+-- [/Stratified language:/]+--+-- Accelerate distinguishes the types of collective operations 'Acc' from the+-- type of scalar operations 'Exp' to achieve a stratified language. Collective+-- operations comprise many scalar computations that are executed in parallel,+-- but scalar computations /can not/ contain collective operations. This+-- separation excludes /nested, irregular/ data-parallelism statically; instead,+-- Accelerate is limited to /flat data-parallelism/ involving only regular,+-- multi-dimensional arrays.+--+-- [/Optimisations:/]+--+-- Accelerate uses a number of scalar and array optimisations, including+-- /array fusion/, in order to improve the performance of programs. Fusing+-- a program entails combining successive traversals (loops) over an array into+-- a single traversal, which reduces memory traffic and eliminates intermediate+-- arrays.+-- -- [/Code execution:/] ----- Access to the various backends is via a 'run' function in backend-specific--- top level modules. Currently, we have the following:+-- Several backends are available which can be used to evaluate accelerate+-- programs: -- -- * "Data.Array.Accelerate.Interpreter": simple interpreter in Haskell as a --   reference implementation defining the semantics of the Accelerate language ----- * "Data.Array.Accelerate.CUDA": an implementation supporting parallel---   execution on CUDA-capable NVIDIA GPUs+-- * <http://hackage.haskell.org/package/accelerate-llvm-native accelerate-llvm-native>:+--   implementation supporting parallel execution on multicore CPUs (e.g. x86). ----- [/Examples and documentation:/]+-- * <http://hackage.haskell.org/package/accelerate-llvm-ptx accelerate-llvm-ptx>:+--   implementation supporting parallel execution on CUDA-capable NVIDIA GPUs. ----- * A (draft) tutorial is available on the GitHub wiki:---   <https://github.com/AccelerateHS/accelerate/wiki>+-- * <http://hackage.haskell.org/package/accelerate-cuda accelerate-cuda>:+--   an older implementation supporting parallel execution on CUDA-capable+--   NVIDIA GPUs. /__NOTE:__ This backend is being deprecated in favour of @accelerate-llvm-ptx@./ ----- * The @accelerate-examples@ package demonstrates a range of computational---   kernels and several complete applications:---   <http://hackage.haskell.org/package/accelerate-examples>+-- [/Examples:/] --+-- * The <http://hackage.haskell.org/package/accelerate-examples accelerate-examples>+--   package demonstrates a range of computational kernels and several complete+--   applications:+--+--      - Implementation of the <https://en.wikipedia.org/wiki/Canny_edge_detector canny edge detector>+--      - Interactive <https://en.wikipedia.org/wiki/Mandelbrot_set Mandelbrot set> generator+--      - <https://en.wikipedia.org/wiki/N-body N-body simulation> of gravitational attraction between large bodies+--      - Implementation of the <https://en.wikipedia.org/wiki/Pagerank PageRank> algorithm+--      - A simple, real-time, interactive <https://en.wikipedia.org/wiki/Ray_tracing ray tracer>.+--      - A particle based simulation of stable fluid flows+--      - A cellular automaton simulation+--      - A "password recovery" tool, for dictionary attacks on MD5 hashes.+--+--      <<http://i.imgur.com/5Tbsp1j.jpg accelerate-mandelbrot>>+--      <<http://i.imgur.com/7ohhKm9.jpg accelerate-ray>>+--+-- * <http://hackage.haskell.org/package/lulesh-accelerate lulesh-accelerate>+--   is an implementation of the Livermore Unstructured Lagrangian Explicit+--   Shock Hydrodynamics (LULESH) application. LULESH is representative of+--   typical hydrodynamics codes, although simplified and hard-coded to solve+--   the Sedov blast problem on an unstructured hexahedron mesh.+--+--      - For more information on LULESH: <https://codesign.llnl.gov/lulesh.php>.+--+--      <<https://codesign.llnl.gov/images/sedov-3d-LLNL.png>>+--+-- [/Additional components:/]+--+-- * <https://hackage.haskell.org/package/accelerate-io accelerate-io>: Fast+-- conversion between Accelerate arrays and other formats (e.g. Repa, Vector).+--+-- * <https://hackage.haskell.org/package/accelerate-fft accelerate-fft>: Fast+-- Fourier transform, with FFI bindings to optimised implementations.+--+-- * <https://hackage.haskell.org/package/accelerate-bignum accelerate-bignum>:+-- Fixed-width large integer arithmetic.+--+-- * <https://hackage.haskell.org/package/colour-accelerate colour-accelerate>:+-- Colour representations in Accelerate (RGB, sRGB, HSV, and HSL).+--+-- * <https://hackage.haskell.org/package/gloss-accelerate gloss-accelerate>:+-- Generate <https://hackage.haskell.org/package/gloss gloss> pictures from+-- Accelerate.+--+-- * <https://hackage.haskell.org/package/gloss-raster-accelerate gloss-raster-accelerate>:+-- Parallel rendering of raster images and animations.+--+-- * <https://hackage.haskell.org/package/lens-accelerate lens-accelerate>:+-- <https://hackage.haskell.org/package/lens Lens> operators for Accelerate+-- types.+--+-- * <https://hackage.haskell.org/package/linear-accelerate linear-accelerate>:+-- <https://hackage.haskell.org/package/linear Linear> vector space types for+-- Accelerate.+--+-- * <https://hackage.haskell.org/package/mwc-random-accelerate mwc-random-accelerate>:+-- Generate Accelerate arrays filled with high-quality pseudorandom numbers.+--+-- [/Contact:/]+--+-- * Mailing list for both use and development discussion:+--+--     * <mailto:accelerate-haskell@googlegroups.com>+--     * http://groups.google.com/group/accelerate-haskell+--+-- * Bug reports: https://github.com/AccelerateHS/accelerate/issues+--+-- * Maintainers:+--+--     * Trevor L. McDonell: <mailto:tmcdonell@cse.unsw.edu.au>+--     * Manuel M T Chakravarty: <mailto:chak@cse.unsw.edu.au>+--+-- [/Tip:/]+--+-- Accelerate tends to stress GHC's garbage collector, so it helps to increase+-- the default GC allocation sizes. This can be done when running an executable+-- by specifying RTS options on the command line, for example:+--+-- > ./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 (    -- * The /Accelerate/ Array Language-  -- ** Array data types-  L.Acc, S.Arrays, S.Array, S.Scalar, S.Vector, S.Segments,+  -- ** Embedded array computations+  Acc, -  -- ** Array element types-  S.Elt,+  -- *** Arrays+  Array, Arrays, Scalar, Vector, Segments, -  -- ** Shapes & Indices-  ---  -- | Array indices are snoc type lists; that is, they are backwards and the-  -- end-of-list token, `Z`, occurs on the left. For example, the type of a-  -- rank-2 array index is @Z :. Int :. Int@.+  -- *** Array elements+  Elt,++  -- *** Array shapes & indices+  -- $shapes_and_indices   ---  S.Z(..), (S.:.)(..), S.Shape, S.All(..), S.Any(..), S.Slice(..),-  S.DIM0, S.DIM1, S.DIM2, S.DIM3, S.DIM4, S.DIM5, S.DIM6, S.DIM7, S.DIM8, S.DIM9,+  Z(..), (:.)(..),+  DIM0, DIM1, DIM2, DIM3, DIM4, DIM5, DIM6, DIM7, DIM8, DIM9,+  Shape, Slice(..), All(..), Any(..),+  -- Split(..), Divide(..), Division(..), -  -- ** Accessors-  -- *** Indexing-  (L.!), (L.!!), P.the,+  -- ** Array access+  -- *** Element indexing+  (!), (!!), the,    -- *** Shape information-  P.null, P.length, L.shape, L.size, L.shapeSize,--  -- *** Extracting sub-arrays-  L.slice,-  P.init, P.tail, P.take, P.drop, P.slit,+  null, length, shape, size, shapeSize,    -- ** Construction   -- *** Introduction-  L.use, L.unit,+  use, unit,    -- *** Initialisation-  L.generate, L.replicate, P.fill,+  generate, fill,    -- *** Enumeration-  P.enumFromN, P.enumFromStepN,+  enumFromN, enumFromStepN,    -- *** Concatenation-  (P.++),+  (++),    -- ** Composition   -- *** Flow control-  (P.?|), L.acond, L.awhile,--  -- *** Pipelining-  (L.>->),--  -- ** Modifying Arrays-  -- *** Shape manipulation-  L.reshape, P.flatten,--  -- *** Permutations-  L.permute, L.backpermute, L.ignore,+  (?|), acond, awhile,+  IfThenElse(..), -  -- *** Specialised permutations-  P.reverse, P.transpose,+  -- *** Controlling execution+  (>->),+  compute,    -- ** Element-wise operations+  -- *** Indexing+  indexed,+   -- *** Mapping-  L.map,+  map, imap,    -- *** Zipping-  L.zipWith, P.zipWith3, P.zipWith4, P.zipWith5, P.zipWith6, P.zipWith7, P.zipWith8, P.zipWith9,-  P.zip, P.zip3, P.zip4, P.zip5, P.zip6, P.zip7, P.zip8, P.zip9,+  zipWith, zipWith3, zipWith4, zipWith5, zipWith6, zipWith7, zipWith8, zipWith9,+  izipWith, izipWith3, izipWith4, izipWith5, izipWith6, izipWith7, izipWith8, izipWith9,+  zip, zip3, zip4, zip5, zip6, zip7, zip8, zip9,    -- *** Unzipping-  P.unzip, P.unzip3, P.unzip4, P.unzip5, P.unzip6, P.unzip7, P.unzip8, P.unzip9,+  unzip, unzip3, unzip4, unzip5, unzip6, unzip7, unzip8, unzip9, -  -- ** Working with predicates-  -- *** Filtering-  P.filter,+  -- ** Modifying Arrays+  -- *** Shape manipulation+  reshape, flatten, -  -- *** Scatter-  P.scatter, P.scatterIf,+  -- *** Replication+  replicate, -  -- *** Gather-  P.gather,  P.gatherIf,+  -- *** Extracting sub-arrays+  slice,+  init, tail, take, drop, slit, +  -- *** Permutations+  -- **** Forward permutation (scatter)+  permute,+  ignore,+  scatter,++  -- **** Backward permutation (gather)+  backpermute,+  gather,++  -- **** Specialised permutations+  reverse, transpose,++  -- *** Filtering+  filter,+   -- ** Folding-  L.fold, L.fold1, P.foldAll, P.fold1All,+  fold, fold1, foldAll, fold1All,    -- *** Segmented reductions-  L.foldSeg, L.fold1Seg,+  foldSeg, fold1Seg, -  -- *** Specialised folds-  P.all, P.any, P.and, P.or, P.sum, P.product, P.minimum, P.maximum,+  -- *** Specialised reductions+  all, any, and, or, sum, product, minimum, maximum, -  -- ** Prefix sums (scans)-  L.scanl, L.scanl1, L.scanl', L.scanr, L.scanr1, L.scanr',-  P.prescanl, P.postscanl, P.prescanr, P.postscanr,+  -- ** Scans (prefix sums)+  scanl, scanl1, scanl', scanr, scanr1, scanr',+  prescanl, postscanl, prescanr, postscanr,    -- *** Segmented scans-  P.scanlSeg, P.scanl1Seg, P.scanl'Seg, P.prescanlSeg, P.postscanlSeg,-  P.scanrSeg, P.scanr1Seg, P.scanr'Seg, P.prescanrSeg, P.postscanrSeg,+  scanlSeg, scanl1Seg, scanl'Seg, prescanlSeg, postscanlSeg,+  scanrSeg, scanr1Seg, scanr'Seg, prescanrSeg, postscanrSeg, -  -- ** Stencil-  L.stencil, L.stencil2,+  -- ** Stencils+  stencil, stencil2, -  -- *** Specification-  L.Stencil, L.Boundary(..),+  -- *** Stencil specification+  Stencil, Boundary(..),    -- *** Common stencil patterns-  L.Stencil3, L.Stencil5, L.Stencil7, L.Stencil9,-  L.Stencil3x3, L.Stencil5x3, L.Stencil3x5, L.Stencil5x5,-  L.Stencil3x3x3, L.Stencil5x3x3, L.Stencil3x5x3, L.Stencil3x3x5, L.Stencil5x5x3, L.Stencil5x3x5,-  L.Stencil3x5x5, L.Stencil5x5x5,+  Stencil3, Stencil5, Stencil7, Stencil9,+  Stencil3x3, Stencil5x3, Stencil3x5, Stencil5x5,+  Stencil3x3x3, Stencil5x3x3, Stencil3x5x3, Stencil3x3x5, Stencil5x5x3, Stencil5x3x5,+  Stencil3x5x5, Stencil5x5x5, -  -- ** Foreign-  L.foreignAcc, L.foreignAcc2, L.foreignAcc3,-  L.foreignExp, L.foreignExp2, L.foreignExp3,+  -- -- ** Sequence operations+  -- collect, -  -- ---------------------------------------------------------------------------+  -- -- ** Sequence producers+  -- streamIn, toSeq, generateSeq, +  -- -- ** Sequence transducers+  -- mapSeq, zipWithSeq, scanSeq,++  -- -- ** Sequence consumers+  -- foldSeq, foldSeqFlatten, fromSeq, fromSeqElems, fromSeqShapes,+  -- toSeqInner, toSeqOuter2, toSeqOuter3,++  -- ---------------------------------------------------------------------------   -- * The /Accelerate/ Expression Language   -- ** Scalar data types-  L.Exp,+  Exp,    -- ** Type classes-  T.IsScalar, T.IsNum, T.IsBounded, T.IsIntegral, T.IsFloating, T.IsNonNum,--  -- ** Element types-  T.Int, T.Int8, T.Int16, T.Int32, T.Int64, T.Word, T.Word8, T.Word16, T.Word32, T.Word64,-  T.CShort, T.CUShort, T.CInt, T.CUInt, T.CLong, T.CULong, T.CLLong, T.CULLong,-  Float, Double, T.CFloat, T.CDouble,-  Bool, Char, T.CChar, T.CSChar, T.CUChar,+  -- *** Basic type classes+  Eq(..),+  Ord(..),+  -- Enum, -- vacuous+  Bounded, minBound, maxBound, -  -- ** Lifting and Unlifting+  -- *** Numeric type classes+  Num, (+), (-), (*), negate, abs, signum, fromInteger,+  -- Real, -- vacuous+  Integral, quot, rem, div, mod, quotRem, divMod,+  Fractional, (/), recip, fromRational,+  Floating, pi, sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh, exp, sqrt, log, (**), logBase,+  RealFrac(..), div', mod', divMod',+  RealFloat(..), -  -- | A value of type `Int` is a plain Haskell value (unlifted), whereas an-  -- @Exp Int@ is a /lifted/ value, that is, an integer lifted into the domain-  -- of expressions (an abstract syntax tree in disguise). Both `Acc` and `Exp`-  -- are /surface types/ into which values may be lifted. Lifting plain array-  -- and scalar surface types is equivalent to 'use' and 'constant'-  -- respectively.-  ---  -- In general an @Exp Int@ cannot be unlifted into an `Int`, because the-  -- actual number will not be available until a later stage of execution (e.g.-  -- during GPU execution, when `run` is called). Similarly an @Acc array@ can-  -- not be unlifted to a vanilla `array`; you should instead `run` the-  -- expression with a specific backend to evaluate it.-  ---  -- Lifting and unlifting are also used to pack and unpack an expression into-  -- and out of constructors such as tuples, respectively. Those expressions, at-  -- runtime, will become tuple dereferences. For example:-  ---  -- > Exp (Z :. Int :. Int)-  -- >     -> unlift    :: (Z :. Exp Int :. Exp Int)-  -- >     -> lift      :: Exp (Z :. Int :. Int)-  -- >     -> ...-  ---  -- > Acc (Scalar Int, Vector Float)-  -- >     -> unlift    :: (Acc (Scalar Int), Acc (Vector Float))-  -- >     -> lift      :: Acc (Scalar Int, Vector Float)-  -- >     -> ...-  ---  P.Lift(..), P.Unlift(..), P.lift1, P.lift2, P.ilift1, P.ilift2,+  -- *** Numeric conversion classes+  FromIntegral(..),+  ToFloating(..), -  -- ** Operations-  ---  -- | Some of the standard Haskell 98 typeclass functions need to be-  -- reimplemented because their types change. If so, function names kept the-  -- same and infix operations are suffixed by an asterisk. If not reimplemented-  -- here, the standard typeclass instances apply.+  -- ** Lifting and Unlifting+  -- $lifting_and_unlifting   --+  Lift(..), Unlift(..),+  lift1, lift2, lift3,+  ilift1, ilift2, ilift3, +  -- ** Scalar operations   -- *** Introduction-  L.constant,+  constant,    -- *** Tuples-  P.fst, P.afst, P.snd, P.asnd, P.curry, P.uncurry,+  fst, afst, snd, asnd, curry, uncurry,    -- *** Flow control-  (P.?), P.caseof, L.cond, L.while, P.iterate,+  (?), caseof, cond, while, iterate,    -- *** Scalar reduction-  P.sfoldl,--  -- *** Basic operations-  (L.&&*), (L.||*), L.not,-  (L.==*), (L./=*), (L.<*), (L.<=*), (L.>*), (L.>=*),+  sfoldl, -  -- *** Numeric functions-  L.truncate, L.round, L.floor, L.ceiling, L.even, L.odd,+  -- *** Logical operations+  (&&), (||), not, -  -- *** Bitwise functions-  L.bit, L.setBit, L.clearBit, L.complementBit, L.testBit,-  L.shift,  L.shiftL,  L.shiftR,-  L.rotate, L.rotateL, L.rotateR,+  -- *** Numeric operations+  subtract, even, odd, gcd, lcm, (^), (^^),    -- *** Shape manipulation-  P.index0, P.index1, P.unindex1, P.index2, P.unindex2,-  L.indexHead, L.indexTail,-  L.toIndex, L.fromIndex,-  L.intersect,+  index0, index1, unindex1, index2, unindex2, index3, unindex3,+  indexHead, indexTail,+  toIndex, fromIndex,+  intersect,    -- *** Conversions-  L.ord, L.chr, L.boolToInt, L.fromIntegral,+  ord, chr, boolToInt, bitcast,    -- ---------------------------------------------------------------------------+  -- * Foreign Function Interface (FFI)+  foreignAcc,+  foreignExp, +  -- ---------------------------------------------------------------------------   -- * Plain arrays   -- ** Operations-  arrayDim, arrayShape, arraySize, indexArray,+  arrayRank, arrayShape, arraySize, indexArray, -  -- ** Conversions-  ---  -- | For additional conversion routines, see the accelerate-io package:-  -- <http://hackage.haskell.org/package/accelerate-io>+  -- ** Getting data in+  -- $getting_data_in    -- *** Function   fromFunction,    -- *** Lists-  S.fromList, S.toList,+  fromList, toList, -  -- *** 'Data.Array.IArray.IArray'-  S.fromIArray, S.toIArray,+  -- ---------------------------------------------------------------------------+  -- * Prelude re-exports+  (.), ($), error, undefined, const, +  -- ---------------------------------------------------------------------------+  -- Types+  Int, Int8, Int16, Int32, Int64,+  Word, Word8, Word16, Word32, Word64,+  Float, Double,+  Bool(..), Char,++  CFloat, CDouble,+  CShort, CUShort, CInt, CUInt, CLong, CULong, CLLong, CULLong,+  CChar, CSChar, CUChar,++  -- | Avoid using these in your own functions wherever possible.+  IsScalar, IsNum, IsBounded, IsIntegral, IsFloating, IsNonNum,+ ) where  -- friends-import Data.Array.Accelerate.Trafo                  () -- show instances-import qualified Data.Array.Accelerate.Array.Sugar  as S-import qualified Data.Array.Accelerate.Language     as L-import qualified Data.Array.Accelerate.Prelude      as P-import qualified Data.Array.Accelerate.Type         as T+import Data.Array.Accelerate.Array.Sugar                            hiding ( (!), rank, shape, size, toIndex, fromIndex, intersect, ignore )+import Data.Array.Accelerate.Classes+import Data.Array.Accelerate.Language+import Data.Array.Accelerate.Prelude+import Data.Array.Accelerate.Trafo                                  () -- show instances+import Data.Array.Accelerate.Type+import qualified Data.Array.Accelerate.Array.Sugar                  as S --- system-import Prelude (Float, Double, Bool, Char)+-- re-exported from D.A.A.Classes.Num but not found (GHC<8 bug)+import Prelude                                                      ( (.), ($), undefined, error, const, fromInteger )   -- Renamings+-- --------- --- -- FIXME: these all need to go into a separate module for separate importing!  -- rename as '(!)' is already used by the EDSL for indexing --- |Array indexing in plain Haskell code.+-- | Array indexing in plain Haskell code. ---indexArray :: S.Array sh e -> sh -> e+indexArray :: Array sh e -> sh -> e indexArray = (S.!)  -- | Rank of an array. ---arrayDim :: S.Shape sh => sh -> T.Int-arrayDim = S.dim--- FIXME: Rename to rank+arrayRank :: Shape sh => sh -> Int+arrayRank = S.rank  -- |Array shape in plain Haskell code. ---arrayShape :: S.Shape sh => S.Array sh e -> sh+arrayShape :: Shape sh => Array sh e -> sh arrayShape = S.shape -- rename as 'shape' is already used by the EDSL to query an array's shape  -- | Total number of elements in an array of the given 'Shape'. ---arraySize :: S.Shape sh => sh -> T.Int+arraySize :: Shape sh => sh -> Int arraySize = S.size --- | Create an array from its representation function.+-- Named documentation chunks+-- --------------------------++-- $shapes_and_indices ---{-# INLINE fromFunction #-}-fromFunction :: (S.Shape sh, S.Elt e) => sh -> (sh -> e) -> S.Array sh e-fromFunction = S.newArray+-- Operations in Accelerate take the form of collective operations over arrays+-- of the type @'Array' sh e@. Much like the+-- <https://hackage.haskell.org/package/repa repa> library, arrays in Accelerate+-- are parameterised by a type /sh/ which determines the dimensionality of the+-- array and the type of each index, as well as the type of each element of the+-- array /e/.+--+-- Shape types, and multidimensional array indices, are built like lists+-- (technically; a heterogeneous snoc-list) using 'Z' and (':.'):+--+-- > data Z = Z+-- > data tail :. head = tail :. head+--+-- Here, the constructor 'Z' corresponds to a shape with zero dimension (or+-- a 'Scalar' array, with one element) and is used to mark the end of the list.+-- The constructor (':.') adds additional dimensions to the shape on the+-- /right/. For example:+--+-- > Z :. Int+--+-- is the type of the shape of a one-dimensional array ('Vector') indexed by an+-- 'Int', while:+--+-- > Z :. Int :. Int+--+-- is the type of the shape of a two-dimensional array (a matrix) indexed by an+-- 'Int' in each dimension.+--+-- This style is used to construct both the /type/ and /value/ of the shape. For+-- example, to define the shape of a vector of ten elements:+--+-- > sh :: Z :. Int+-- > sh = Z :. 10+--+-- Note that the right-most index is the /innermost/ dimension. This is the+-- fastest-varying index, and corresponds to the elements of the array which are+-- adjacent in memory.+--++-- $lifting_and_unlifting+--+-- A value of type 'Int' is a plain Haskell value (unlifted), whereas an @Exp+-- Int@ is a /lifted/ value, that is, an integer lifted into the domain of+-- embedded expressions (an abstract syntax tree in disguise). Both 'Acc' and+-- 'Exp' are /surface types/ into which values may be lifted. Lifting plain+-- array and scalar surface types is equivalent to 'use' and 'constant'+-- respectively.+--+-- In general an @Exp Int@ cannot be unlifted into an 'Int', because the actual+-- number will not be available until a later stage of execution (e.g. during+-- GPU execution, when 'run' is called). Similarly an @Acc array@ can not be+-- unlifted to a vanilla 'array'; you should instead 'run' the expression with+-- a specific backend to evaluate it.+--+-- Lifting and unlifting are also used to pack and unpack an expression into and+-- out of constructors such as tuples, respectively. Those expressions, at+-- runtime, will become tuple dereferences. For example:+--+-- >>> let sh = constant (Z :. 4 :. 10)   :: Exp DIM2+-- >>> let Z :. x :. y = unlift sh        :: Z :. Exp Int :. Exp Int+-- >>> let t = lift (x,y)                 :: Exp (Int, Int)+--+-- >>> let r  = scanl' f z xs             :: (Acc (Vector Int), Acc (Scalar Int))+-- >>> let r' = lift r                    :: Acc (Vector Int, Scalar Int)+--+-- [/Note:/]+--+-- Use of 'lift' and 'unlift' is probably the most common source of type errors+-- when using Accelerate. GHC is not very good at determining the type the+-- [un]lifted expression should have, so it is often necessary to add an+-- explicit type signature.+--+-- For example, in the following GHC will complain that it can not determine the+-- type of 'y', even though we might expect that to be obvious (or for it to not+-- care):+--+-- > fst :: (Elt a, Elt b) => Exp (a,b) -> Exp a+-- > fst t = let (x,y) = unlift t in x+--+-- The fix is to instead add an explicit type signature. Note that this requires+-- the @ScopedTypeVariables@ extension and to bring the type variables @a@ and+-- @b@ into scope with @forall@:+--+-- > fst :: forall a b. (Elt a, Elt b) => Exp (a,b) -> Exp a+-- > fst t = let (x,y) = unlift t  :: (Exp a, Exp b)+-- >         in x+--++-- $getting_data_in+-- #getting_data_in#+--+-- We often need to generate or read data into an 'Array' so that it can be used+-- in Accelerate. The base @accelerate@ library includes basic conversions+-- routines, but for additional functionality see the+-- <http://hackage.haskell.org/package/accelerate-io accelerate-io> package,+-- which includes conversions between:+--+--  * <https://hackage.haskell.org/package/repa repa>: another Haskell library for high-performance parallel arrays+--  * <https://hackage.haskell.org/package/vector vector>: efficient boxed and unboxed one-dimensional arrays+--  * <https://hackage.haskell.org/package/array array>: immutable arrays+--  * <https://hackage.haskell.org/package/bmp BMP>: uncompressed BMP image files+--  * <https://hackage.haskell.org/package/bytestring bytestring> compact, immutable binary data+--  * As well as copying data directly from raw 'Foreign.Ptr.Ptr's+-- 
Data/Array/Accelerate/AST.hs view
@@ -1,8 +1,11 @@+{-# LANGUAGE BangPatterns          #-}+{-# LANGUAGE CPP                   #-} {-# LANGUAGE DeriveDataTypeable    #-} {-# LANGUAGE FlexibleContexts      #-} {-# LANGUAGE FlexibleInstances     #-} {-# LANGUAGE GADTs                 #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE RankNTypes            #-} {-# LANGUAGE ScopedTypeVariables   #-} {-# LANGUAGE StandaloneDeriving    #-} {-# LANGUAGE TemplateHaskell       #-}@@ -12,13 +15,14 @@ {-# OPTIONS_HADDOCK hide #-} -- | -- Module      : Data.Array.Accelerate.AST--- Copyright   : [2008..2014] Manuel M T Chakravarty, Gabriele Keller---               [2008..2009] Sean Lee---               [2009..2014] Trevor L. McDonell+-- Copyright   : [2008..2017] Manuel M T Chakravarty, Gabriele Keller+--               [2009..2017] Trevor L. McDonell --               [2010..2011] Ben Lever+--               [2013..2017] Robert Clifton-Everest+--               [2014..2014] Frederik M. Madsen -- License     : BSD3 ----- Maintainer  : Manuel M T Chakravarty <chak@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -88,10 +92,18 @@   PreOpenAfun(..), OpenAfun, PreAfun, Afun, PreOpenAcc(..), OpenAcc(..), Acc,   Stencil(..), StencilR(..), +  -- * Accelerated sequences+  -- PreOpenSeq(..), Seq,+  -- Producer(..), Consumer(..),+   -- * Scalar expressions   PreOpenFun(..), OpenFun, PreFun, Fun, PreOpenExp(..), OpenExp, PreExp, Exp, PrimConst(..),   PrimFun(..), +  -- NFData+  NFDataAcc,+  rnfPreOpenAfun, rnfPreOpenAcc, rnfPreOpenFun, rnfPreOpenExp,+   -- debugging   showPreAccOp, showPreExpOp, @@ -100,13 +112,16 @@ --standard library import Data.List import Data.Typeable+import Control.DeepSeq  -- friends-import Data.Array.Accelerate.Error import Data.Array.Accelerate.Type-import Data.Array.Accelerate.Tuple-import Data.Array.Accelerate.Array.Representation       ( SliceIndex )+import Data.Array.Accelerate.Product+import Data.Array.Accelerate.Array.Representation       ( SliceIndex(..) ) import Data.Array.Accelerate.Array.Sugar                as Sugar+#if __GLASGOW_HASKELL__ < 800+import Data.Array.Accelerate.Error+#endif   -- Typed de Bruijn indices@@ -153,15 +168,18 @@ prj :: Idx env t -> Val env -> t prj ZeroIdx       (Push _   v) = v prj (SuccIdx idx) (Push val _) = prj idx val+#if __GLASGOW_HASKELL__ < 800 prj _             _            = $internalError "prj" "inconsistent valuation"+#endif  -- Projection of a value from a valuation of array elements using a de Bruijn index -- prjElt :: Idx env t -> ValElt env -> t prjElt ZeroIdx       (PushElt _   v) = Sugar.toElt v prjElt (SuccIdx idx) (PushElt val _) = prjElt idx val+#if __GLASGOW_HASKELL__ < 800 prjElt _             _               = $internalError "prjElt" "inconsistent valuation"-+#endif  -- Array expressions -- -----------------@@ -184,6 +202,18 @@ -- type Afun = OpenAfun () +-- Vanilla open array computations+--+newtype OpenAcc aenv t = OpenAcc (PreOpenAcc OpenAcc aenv t)++-- |Closed array expression aka an array program+--+type Acc = OpenAcc ()++deriving instance Typeable PreOpenAcc+deriving instance Typeable OpenAcc++ -- |Collective array computations parametrised over array variables -- represented with de Bruijn indices. --@@ -218,11 +248,11 @@               -> PreOpenAcc acc aenv arrs    -- Tuples of arrays-  Atuple      :: (Arrays arrs, IsTuple arrs)+  Atuple      :: (Arrays arrs, IsAtuple arrs)               => Atuple    (acc aenv) (TupleRepr arrs)               -> PreOpenAcc acc aenv  arrs -  Aprj        :: (Arrays arrs, IsTuple arrs, Arrays a)+  Aprj        :: (Arrays arrs, IsAtuple arrs, Arrays a)               => TupleIdx (TupleRepr arrs) a               ->            acc aenv arrs               -> PreOpenAcc acc aenv a@@ -240,11 +270,11 @@   -- Apply a backend-specific foreign function to an array, with a pure   -- Accelerate version for use with other backends. The functions must be   -- closed.-  Aforeign    :: (Arrays arrs, Arrays a, Foreign f)-              => f arrs a                                       -- The foreign function for a given backend-              -> PreAfun      acc      (arrs -> a)              -- A pure accelerate version-              -> acc              aenv arrs                     -- Arguments to the function-              -> PreOpenAcc   acc aenv a+  Aforeign    :: (Arrays as, Arrays bs, Foreign asm)+              => asm                   (as -> bs)               -- The foreign function for a given backend+              -> PreAfun      acc      (as -> bs)               -- Fallback implementation(s)+              -> acc              aenv as                       -- Arguments to the function+              -> PreOpenAcc   acc aenv bs    -- If-then-else for array-level computations   Acond       :: Arrays arrs@@ -361,46 +391,46 @@   -- Left-to-right Haskell-style scan of a linear array with a given *associative*   -- function and an initial element (which does not need to be the neutral of the   -- associative operations)-  Scanl       :: Elt e+  Scanl       :: (Shape sh, Elt e)               => PreFun     acc aenv (e -> e -> e)              -- combination function               -> PreExp     acc aenv e                          -- initial value-              -> acc            aenv (Vector e)                 -- linear array-              -> PreOpenAcc acc aenv (Vector e)+              -> acc            aenv (Array (sh:.Int) e)+              -> PreOpenAcc acc aenv (Array (sh:.Int) e)     -- FIXME: Make the scans rank-polymorphic?    -- Like 'Scan', but produces a rightmost fold value and an array with the same length as the input   -- array (the fold value would be the rightmost element in a Haskell-style scan)-  Scanl'      :: Elt e+  Scanl'      :: (Shape sh, Elt e)               => PreFun     acc aenv (e -> e -> e)              -- combination function               -> PreExp     acc aenv e                          -- initial value-              -> acc            aenv (Vector e)                 -- linear array-              -> PreOpenAcc acc aenv (Vector e, Scalar e)+              -> acc            aenv (Array (sh:.Int) e)+              -> PreOpenAcc acc aenv (Array (sh:.Int) e, Array sh e)    -- Haskell-style scan without an initial value-  Scanl1      :: Elt e+  Scanl1      :: (Shape sh, Elt e)               => PreFun     acc aenv (e -> e -> e)              -- combination function-              -> acc            aenv (Vector e)                 -- linear array-              -> PreOpenAcc acc aenv (Vector e)+              -> acc            aenv (Array (sh:.Int) e)+              -> PreOpenAcc acc aenv (Array (sh:.Int) e)    -- Right-to-left version of 'Scanl'-  Scanr       :: Elt e+  Scanr       :: (Shape sh, Elt e)               => PreFun     acc aenv (e -> e -> e)              -- combination function               -> PreExp     acc aenv e                          -- initial value-              -> acc            aenv (Vector e)                 -- linear array-              -> PreOpenAcc acc aenv (Vector e)+              -> acc            aenv (Array (sh:.Int) e)+              -> PreOpenAcc acc aenv (Array (sh:.Int) e)    -- Right-to-left version of 'Scanl\''-  Scanr'      :: Elt e+  Scanr'      :: (Shape sh, Elt e)               => PreFun     acc aenv (e -> e -> e)              -- combination function               -> PreExp     acc aenv e                          -- initial value-              -> acc            aenv (Vector e)                 -- linear array-              -> PreOpenAcc acc aenv (Vector e, Scalar e)+              -> acc            aenv (Array (sh:.Int) e)+              -> PreOpenAcc acc aenv (Array (sh:.Int) e, Array sh e)    -- Right-to-left version of 'Scanl1'-  Scanr1      :: Elt e+  Scanr1      :: (Shape sh, Elt e)               => PreFun     acc aenv (e -> e -> e)              -- combination function-              -> acc            aenv (Vector e)                 -- linear array-              -> PreOpenAcc acc aenv (Vector e)+              -> acc            aenv (Array (sh:.Int) e)+              -> PreOpenAcc acc aenv (Array (sh:.Int) e)    -- Generalised forward permutation is characterised by a permutation function   -- that determines for each element of the source array where it should go in@@ -457,21 +487,132 @@               -> acc            aenv (Array sh e2)              -- source array #2               -> PreOpenAcc acc aenv (Array sh e') +  -- A sequence of operations.+  -- Collect     :: Arrays arrs+  --             => PreOpenSeq acc aenv () arrs+  --             -> PreOpenAcc acc aenv arrs --- Vanilla open array computations----newtype OpenAcc aenv t = OpenAcc (PreOpenAcc OpenAcc aenv t)+{--+data PreOpenSeq acc aenv senv arrs where+  Producer :: Arrays a+           => Producer acc aenv senv a+           -> PreOpenSeq acc aenv (senv, a) arrs+           -> PreOpenSeq acc aenv senv arrs --- deriving instance Typeable PreOpenAcc-deriving instance Typeable OpenAcc+  Consumer :: Arrays arrs+           => Consumer acc aenv senv arrs+           -> PreOpenSeq acc aenv senv arrs --- |Closed array expression aka an array program+  Reify    :: Arrays arrs+           => Idx senv arrs+           -> PreOpenSeq acc aenv senv [arrs]++data Producer acc aenv senv a where+  -- Convert the given Haskell-list of arrays to a sequence.+  StreamIn :: Arrays a+           => [a]+           -> Producer acc aenv senv a++  -- Convert the given array to a sequence.+  ToSeq :: (Elt slix, Shape sl, Shape sh, Elt e)+           => SliceIndex  (EltRepr slix)+                          (EltRepr sl)+                          co+                          (EltRepr sh)+           -> proxy slix+           -> acc aenv (Array sh e)+           -> Producer acc aenv senv (Array sl e)++  -- Apply the given the given function to all elements of the given+  -- sequence.+  MapSeq :: (Arrays a, Arrays b)+         => PreOpenAfun acc aenv (a -> b)+         -> Idx senv a+         -> Producer acc aenv senv b++  -- Apply the given the given function to all elements of the given+  -- sequence.+  ChunkedMapSeq :: (Arrays a, Arrays b)+                => PreOpenAfun acc aenv (Vector' a -> Vector' b)+                -> Idx senv a+                -> Producer acc aenv senv b++  -- Apply a given binary function pairwise to all elements of the+  -- given sequences.+  ZipWithSeq :: (Arrays a, Arrays b, Arrays c)+             => PreOpenAfun acc aenv (a -> b -> c)+             -> Idx senv a+             -> Idx senv b+             -> Producer acc aenv senv c++  -- ScanSeq (+) a0 x. Scan a sequence x by combining each element+  -- using the given binary operation (+). (+) must be associative:+  --+  --   Forall a b c. (a + b) + c = a + (b + c),+  --+  -- and a0 must be the identity element for (+):+  --+  --   Forall a. a0 + a = a = a + a0.+  --+  ScanSeq :: Elt e+          => PreFun acc aenv (e -> e -> e)+          -> PreExp acc aenv e+          -> Idx senv (Scalar e)+          -> Producer acc aenv senv (Scalar e)++data Consumer acc aenv senv a where++  -- FoldSeq (+) a0 x. Fold a sequence x by combining each element+  -- using the given binary operation (+). (+) must be associative:+  --+  --   Forall a b c. (a + b) + c = a + (b + c),+  --+  -- and a0 must be the identity element for (+):+  --+  --   Forall a. a0 + a = a = a + a0.+  --+  FoldSeq :: Elt a+          => PreFun acc aenv (a -> a -> a)+          -> PreExp acc aenv a+          -> Idx senv (Scalar a)+          -> Consumer acc aenv senv (Scalar a)++  -- FoldSeqFlatten f a0 x. A specialized version of FoldSeqAct where+  -- reduction with the companion operator corresponds to+  -- flattening. f must be semi-associative, with vecotor append (++)+  -- as the companion operator:+  --+  --   Forall b sh1 a1 sh2 a2.+  --     f (f b sh1 a1) sh2 a2 = f b (sh1 ++ sh2) (a1 ++ a2).+  --+  -- It is common to ignore the shape vectors, yielding the usual+  -- semi-associativity law:+  --+  --   f b a _ = b + a,+  --+  -- for some (+) satisfying:+  --+  --   Forall b a1 a2. (b + a1) + a2 = b + (a1 ++ a2).+  --+  FoldSeqFlatten :: (Arrays a, Shape sh, Elt e)+                 => PreOpenAfun acc aenv (a -> Vector sh -> Vector e -> a)+                 -> acc aenv a+                 -> Idx senv (Array sh e)+                 -> Consumer acc aenv senv a++  Stuple :: (Arrays a, IsAtuple a)+         => Atuple (Consumer acc aenv senv) (TupleRepr a)+         -> Consumer acc aenv senv a++-- |Closed sequence computation ---type Acc = OpenAcc ()+type Seq = PreOpenSeq OpenAcc () ()+--} + -- |Operations on stencils. ---class (Shape sh, Elt e, IsTuple stencil) => Stencil sh e stencil where+class (Shape sh, Elt e, IsTuple stencil, Elt stencil) => Stencil sh e stencil where   stencil       :: StencilR sh e stencil   stencilAccess :: (sh -> e) -> sh -> stencil @@ -692,6 +833,18 @@ -- type Fun = OpenFun () +-- |Vanilla open expression+--+type OpenExp = PreOpenExp OpenAcc++-- |Parametrised expression without free scalar variables+--+type PreExp acc = PreOpenExp acc ()++-- |Vanilla expression without free scalar variables+--+type Exp = OpenExp ()+ -- |Parametrised open expressions using de Bruijn indices for variables ranging over tuples -- of scalars and arrays of tuples.  All code, except Cond, is evaluated eagerly.  N-tuples are -- represented as nested pairs.@@ -712,8 +865,8 @@                 -> PreOpenExp acc env aenv t    -- Apply a backend-specific foreign function-  Foreign       :: (Foreign f, Elt x, Elt y)-                => f x y+  Foreign       :: (Foreign asm, Elt x, Elt y)+                => asm           (x -> y)                 -> PreFun acc () (x -> y)                 -> PreOpenExp acc env aenv x                 -> PreOpenExp acc env aenv y@@ -829,20 +982,14 @@                 -> PreOpenExp acc env aenv dim                 -> PreOpenExp acc env aenv dim +  -- Union of two shapes+  Union         :: Shape dim+                => PreOpenExp acc env aenv dim+                -> PreOpenExp acc env aenv dim+                -> PreOpenExp acc env aenv dim --- |Vanilla open expression----type OpenExp = PreOpenExp OpenAcc --- |Parametrised expression without free scalar variables----type PreExp acc = PreOpenExp acc ()---- |Vanilla expression without free scalar variables----type Exp = OpenExp ()---- |Primitive GPU constants+-- |Primitive constant values -- data PrimConst ty where @@ -865,22 +1012,28 @@   PrimAbs  :: NumType a -> PrimFun (a      -> a)   PrimSig  :: NumType a -> PrimFun (a      -> a) -  -- operators from Integral & Bits+  -- operators from Integral   PrimQuot     :: IntegralType a -> PrimFun ((a, a)   -> a)   PrimRem      :: IntegralType a -> PrimFun ((a, a)   -> a)+  PrimQuotRem  :: IntegralType a -> PrimFun ((a, a)   -> (a, a))   PrimIDiv     :: IntegralType a -> PrimFun ((a, a)   -> a)   PrimMod      :: IntegralType a -> PrimFun ((a, a)   -> a)-  PrimBAnd     :: IntegralType a -> PrimFun ((a, a)   -> a)-  PrimBOr      :: IntegralType a -> PrimFun ((a, a)   -> a)-  PrimBXor     :: IntegralType a -> PrimFun ((a, a)   -> a)-  PrimBNot     :: IntegralType a -> PrimFun (a        -> a)-  PrimBShiftL  :: IntegralType a -> PrimFun ((a, Int) -> a)-  PrimBShiftR  :: IntegralType a -> PrimFun ((a, Int) -> a)-  PrimBRotateL :: IntegralType a -> PrimFun ((a, Int) -> a)-  PrimBRotateR :: IntegralType a -> PrimFun ((a, Int) -> a)+  PrimDivMod   :: IntegralType a -> PrimFun ((a, a)   -> (a, a)) -  -- operators from Fractional, Floating, RealFrac & RealFloat+  -- operators from Bits & FiniteBits+  PrimBAnd               :: IntegralType a -> PrimFun ((a, a)   -> a)+  PrimBOr                :: IntegralType a -> PrimFun ((a, a)   -> a)+  PrimBXor               :: IntegralType a -> PrimFun ((a, a)   -> a)+  PrimBNot               :: IntegralType a -> PrimFun (a        -> a)+  PrimBShiftL            :: IntegralType a -> PrimFun ((a, Int) -> a)+  PrimBShiftR            :: IntegralType a -> PrimFun ((a, Int) -> a)+  PrimBRotateL           :: IntegralType a -> PrimFun ((a, Int) -> a)+  PrimBRotateR           :: IntegralType a -> PrimFun ((a, Int) -> a)+  PrimPopCount           :: IntegralType a -> PrimFun (a -> Int)+  PrimCountLeadingZeros  :: IntegralType a -> PrimFun (a -> Int)+  PrimCountTrailingZeros :: IntegralType a -> PrimFun (a -> Int) +  -- operators from Fractional and Floating   PrimFDiv        :: FloatingType a -> PrimFun ((a, a) -> a)   PrimRecip       :: FloatingType a -> PrimFun (a      -> a)   PrimSin         :: FloatingType a -> PrimFun (a      -> a)@@ -889,6 +1042,9 @@   PrimAsin        :: FloatingType a -> PrimFun (a      -> a)   PrimAcos        :: FloatingType a -> PrimFun (a      -> a)   PrimAtan        :: FloatingType a -> PrimFun (a      -> a)+  PrimSinh        :: FloatingType a -> PrimFun (a      -> a)+  PrimCosh        :: FloatingType a -> PrimFun (a      -> a)+  PrimTanh        :: FloatingType a -> PrimFun (a      -> a)   PrimAsinh       :: FloatingType a -> PrimFun (a      -> a)   PrimAcosh       :: FloatingType a -> PrimFun (a      -> a)   PrimAtanh       :: FloatingType a -> PrimFun (a      -> a)@@ -897,13 +1053,32 @@   PrimLog         :: FloatingType a -> PrimFun (a      -> a)   PrimFPow        :: FloatingType a -> PrimFun ((a, a) -> a)   PrimLogBase     :: FloatingType a -> PrimFun ((a, a) -> a)-  PrimAtan2       :: FloatingType a -> PrimFun ((a, a) -> a)-  PrimTruncate    :: FloatingType a -> IntegralType b -> PrimFun (a -> b)-  PrimRound       :: FloatingType a -> IntegralType b -> PrimFun (a -> b)-  PrimFloor       :: FloatingType a -> IntegralType b -> PrimFun (a -> b)-  PrimCeiling     :: FloatingType a -> IntegralType b -> PrimFun (a -> b)+   -- FIXME: add missing operations from RealFrac & RealFloat +  -- operators from RealFrac+  PrimTruncate :: FloatingType a -> IntegralType b -> PrimFun (a -> b)+  PrimRound    :: FloatingType a -> IntegralType b -> PrimFun (a -> b)+  PrimFloor    :: FloatingType a -> IntegralType b -> PrimFun (a -> b)+  PrimCeiling  :: FloatingType a -> IntegralType b -> PrimFun (a -> b)+  -- PrimProperFraction :: FloatingType a -> IntegralType b -> PrimFun (a -> (b, a))++  -- operators from RealFloat+  PrimIsNaN :: FloatingType a -> PrimFun (a -> Bool)+  PrimAtan2 :: FloatingType a -> PrimFun ((a, a) -> a)+  -- PrimFloatRadix     :: FloatingType a -> PrimFun (a -> Int)         -- Integer?+  -- PrimFloatDigits    :: FloatingType a -> PrimFun (a -> Int)+  -- PrimFloatRange     :: FloatingType a -> PrimFun (a -> (Int, Int))+  -- PrimDecodeFloat    :: FloatingType a -> PrimFun (a -> (Int, Int))  -- Integer?+  -- PrimEncodeFloat    :: FloatingType a -> PrimFun ((Int, Int) -> a)  -- Integer?+  -- PrimExponent       :: FloatingType a -> PrimFun (a -> Int)+  -- PrimSignificand    :: FloatingType a -> PrimFun (a -> a)+  -- PrimScaleFloat     :: FloatingType a -> PrimFun ((Int, a) -> a)+  -- PrimIsInfinite     :: FloatingType a -> PrimFun (a -> Bool)+  -- PrimIsDenormalized :: FloatingType a -> PrimFun (a -> Bool)+  -- PrimIsNegativeZero :: FloatingType a -> PrimFun (a -> Bool)+  -- PrimIsIEEE         :: FloatingType a -> PrimFun (a -> Bool)+   -- relational and equality operators   PrimLt   :: ScalarType a -> PrimFun ((a, a) -> Bool)   PrimGt   :: ScalarType a -> PrimFun ((a, a) -> Bool)@@ -920,21 +1095,382 @@   PrimLNot :: PrimFun (Bool         -> Bool)    -- character conversions+  -- FIXME: use IntegralType?   PrimOrd  :: PrimFun (Char -> Int)   PrimChr  :: PrimFun (Int  -> Char)-  -- FIXME: use IntegralType? -  -- FIXME: conversions between various integer types-  --        should we have an overloaded functions like 'toInt'?-  --        (or 'fromEnum' for enums?)-  PrimBoolToInt    :: PrimFun (Bool -> Int)+  -- boolean conversion+  PrimBoolToInt :: PrimFun (Bool -> Int)++  -- general conversion between types   PrimFromIntegral :: IntegralType a -> NumType b -> PrimFun (a -> b)+  PrimToFloating   :: NumType a -> FloatingType b -> PrimFun (a -> b) -  -- FIXME: what do we want to do about Enum?  succ and pred are only-  --   moderatly useful without user-defined enumerations, but we want-  --   the range constructs for arrays (but that's not scalar primitives)+  -- reinterpret the bits of a value as a different type+  -- (the two types must have the same bit size)+  PrimCoerce :: ScalarType a -> ScalarType b -> PrimFun (a -> b) +  -- FIXME: Conversions between various integer types: should we have overloaded+  -- functions like 'toInt'? (or 'fromEnum' for enums?) +  -- FIXME: What do we want to do about Enum? 'succ' and 'pred' are only+  -- moderately useful without user-defined enumerations, but we want the range+  -- constructs for arrays (but that's not scalar primitives)+++-- NFData instances+-- ================++instance NFData (OpenAfun aenv f) where+  rnf = rnfOpenAfun++instance NFData (OpenAcc aenv t) where+  rnf = rnfOpenAcc++-- instance NFData (Seq t) where+--   rnf = rnfPreOpenSeq rnfOpenAcc++instance NFData (OpenExp env aenv t) where+  rnf = rnfPreOpenExp rnfOpenAcc++instance NFData (OpenFun env aenv t) where+  rnf = rnfPreOpenFun rnfOpenAcc+++-- Array expressions+-- -----------------++type NFDataAcc acc = forall aenv t. acc aenv t -> ()++rnfIdx :: Idx env t -> ()+rnfIdx ZeroIdx      = ()+rnfIdx (SuccIdx ix) = rnfIdx ix++rnfTupleIdx :: TupleIdx t e -> ()+rnfTupleIdx ZeroTupIdx       = ()+rnfTupleIdx (SuccTupIdx tix) = rnfTupleIdx tix++rnfOpenAfun :: OpenAfun aenv t -> ()+rnfOpenAfun = rnfPreOpenAfun rnfOpenAcc++rnfOpenAcc :: OpenAcc aenv t -> ()+rnfOpenAcc (OpenAcc pacc) = rnfPreOpenAcc rnfOpenAcc pacc++rnfPreOpenAfun :: NFDataAcc acc -> PreOpenAfun acc aenv t -> ()+rnfPreOpenAfun rnfA (Abody b) = rnfA b+rnfPreOpenAfun rnfA (Alam f)  = rnfPreOpenAfun rnfA f++rnfPreOpenAcc :: forall acc aenv t. NFDataAcc acc -> PreOpenAcc acc aenv t -> ()+rnfPreOpenAcc rnfA pacc =+  let+      rnfAF :: PreOpenAfun acc aenv' t' -> ()+      rnfAF = rnfPreOpenAfun rnfA++      rnfE :: PreOpenExp acc env' aenv' t' -> ()+      rnfE = rnfPreOpenExp rnfA++      rnfF :: PreOpenFun acc env' aenv' t' -> ()+      rnfF = rnfPreOpenFun rnfA++      -- rnfS :: PreOpenSeq acc aenv' senv' t' -> ()+      -- rnfS = rnfPreOpenSeq rnfA++      rnfB :: forall aenv' sh e. Elt e => acc aenv' (Array sh e) -> Boundary (EltRepr e) -> ()+      rnfB _ = rnfBoundary (eltType (undefined::e))+  in+  case pacc of+    Alet bnd body             -> rnfA bnd `seq` rnfA body+    Avar ix                   -> rnfIdx ix+    Atuple atup               -> rnfAtuple rnfA atup+    Aprj tix a                -> rnfTupleIdx tix `seq` rnfA a+    Apply afun acc            -> rnfAF afun `seq` rnfA acc+    Aforeign asm afun a       -> rnf (strForeign asm) `seq` rnfAF afun `seq` rnfA a+    Acond p a1 a2             -> rnfE p `seq` rnfA a1 `seq` rnfA a2+    Awhile p f a              -> rnfAF p `seq` rnfAF f `seq` rnfA a+    Use arrs                  -> rnfArrays (arrays (undefined::t)) arrs+    Unit x                    -> rnfE x+    Reshape sh a              -> rnfE sh `seq` rnfA a+    Generate sh f             -> rnfE sh `seq` rnfF f+    Transform sh p f a        -> rnfE sh `seq` rnfF p `seq` rnfF f `seq` rnfA a+    Replicate slice sh a      -> rnfSliceIndex slice `seq` rnfE sh `seq` rnfA a+    Slice slice a sh          -> rnfSliceIndex slice `seq` rnfE sh `seq` rnfA a+    Map f a                   -> rnfF f `seq` rnfA a+    ZipWith f a1 a2           -> rnfF f `seq` rnfA a1 `seq` rnfA a2+    Fold f z a                -> rnfF f `seq` rnfE z `seq` rnfA a+    Fold1 f a                 -> rnfF f `seq` rnfA a+    FoldSeg f z a s           -> rnfF f `seq` rnfE z `seq` rnfA a `seq` rnfA s+    Fold1Seg f a s            -> rnfF f `seq` rnfA a `seq` rnfA s+    Scanl f z a               -> rnfF f `seq` rnfE z `seq` rnfA a+    Scanl1 f a                -> rnfF f `seq` rnfA a+    Scanl' f z a              -> rnfF f `seq` rnfE z `seq` rnfA a+    Scanr f z a               -> rnfF f `seq` rnfE z `seq` rnfA a+    Scanr1 f a                -> rnfF f `seq` rnfA a+    Scanr' f z a              -> rnfF f `seq` rnfE z `seq` rnfA a+    Permute f d p a           -> rnfF f `seq` rnfA d `seq` rnfF p `seq` rnfA a+    Backpermute sh f a        -> rnfE sh `seq` rnfF f `seq` rnfA a+    Stencil f b a             -> rnfF f `seq` rnfB a b `seq` rnfA a+    Stencil2 f b1 a1 b2 a2    -> rnfF f `seq` rnfB a1 b1 `seq` rnfB a2 b2 `seq` rnfA a1 `seq` rnfA a2+    -- Collect s                 -> rnfS s+++rnfAtuple :: NFDataAcc acc -> Atuple (acc aenv) t -> ()+rnfAtuple _    NilAtup          = ()+rnfAtuple rnfA (SnocAtup tup a) = rnfAtuple rnfA tup `seq` rnfA a++rnfArrays :: ArraysR arrs -> arrs -> ()+rnfArrays ArraysRunit           ()      = ()+rnfArrays ArraysRarray          arr     = rnf arr+rnfArrays (ArraysRpair ar1 ar2) (a1,a2) = rnfArrays ar1 a1 `seq` rnfArrays ar2 a2++rnfBoundary :: TupleType t -> Boundary t -> ()+rnfBoundary _ Clamp        = ()+rnfBoundary _ Mirror       = ()+rnfBoundary _ Wrap         = ()+rnfBoundary t (Constant c) = rnfConst t c+++{--+-- Sequence expressions+-- --------------------++rnfPreOpenSeq :: forall acc aenv senv t. NFDataAcc acc -> PreOpenSeq acc aenv senv t -> ()+rnfPreOpenSeq rnfA topSeq =+  let+      rnfS :: PreOpenSeq acc aenv' senv' t' -> ()+      rnfS = rnfPreOpenSeq rnfA++      rnfP :: Producer acc aenv' senv' t' -> ()+      rnfP = rnfSeqProducer rnfA++      rnfC :: Consumer acc aenv' senv' t' -> ()+      rnfC = rnfSeqConsumer rnfA+  in+  case topSeq of+    Producer p s              -> rnfP p `seq` rnfS s+    Consumer c                -> rnfC c+    Reify ix                  -> rnfIdx ix++rnfSeqProducer :: forall acc aenv senv t. NFDataAcc acc -> Producer acc aenv senv t -> ()+rnfSeqProducer rnfA topSeq =+  let+      rnfArrs :: forall a. Arrays a => [a] -> ()+      rnfArrs []     = ()+      rnfArrs (a:as) = rnfArrays (arrays (undefined::a)) (fromArr a) `seq` rnfArrs as++      rnfAF :: PreOpenAfun acc aenv' t' -> ()+      rnfAF = rnfPreOpenAfun rnfA++      rnfF :: PreOpenFun acc env' aenv' t' -> ()+      rnfF = rnfPreOpenFun rnfA++      rnfE :: PreOpenExp acc env' aenv' t' -> ()+      rnfE = rnfPreOpenExp rnfA+  in+  case topSeq of+    StreamIn as               -> rnfArrs as+    ToSeq slice _ a           -> rnfSliceIndex slice `seq` rnfA a+    MapSeq f ix               -> rnfAF f `seq` rnfIdx ix+    ChunkedMapSeq f ix        -> rnfAF f `seq` rnfIdx ix+    ZipWithSeq f ix1 ix2      -> rnfAF f `seq` rnfIdx ix1 `seq` rnfIdx ix2+    ScanSeq f z ix            -> rnfF f `seq` rnfE z `seq` rnfIdx ix++rnfSeqConsumer :: forall acc aenv senv t. NFDataAcc acc -> Consumer acc aenv senv t -> ()+rnfSeqConsumer rnfA topSeq =+  let+      rnfAF :: PreOpenAfun acc aenv' t' -> ()+      rnfAF = rnfPreOpenAfun rnfA++      rnfF :: PreOpenFun acc env' aenv' t' -> ()+      rnfF = rnfPreOpenFun rnfA++      rnfE :: PreOpenExp acc env' aenv' t' -> ()+      rnfE = rnfPreOpenExp rnfA+  in+  case topSeq of+    FoldSeq f z ix            -> rnfF f `seq` rnfE z `seq` rnfIdx ix+    FoldSeqFlatten f a ix     -> rnfAF f `seq` rnfA a `seq` rnfIdx ix+    Stuple stup               -> rnfStuple rnfA stup++rnfStuple :: NFDataAcc acc -> Atuple (Consumer acc aenv senv) t -> ()+rnfStuple _    NilAtup          = ()+rnfStuple rnfA (SnocAtup tup c) = rnfStuple rnfA tup `seq` rnfSeqConsumer rnfA c+--}++-- Scalar expressions+-- ------------------++rnfPreOpenFun :: NFDataAcc acc -> PreOpenFun acc env aenv t -> ()+rnfPreOpenFun rnfA (Body b) = rnfPreOpenExp rnfA b+rnfPreOpenFun rnfA (Lam f)  = rnfPreOpenFun rnfA f++rnfPreOpenExp :: forall acc env aenv t. NFDataAcc acc -> PreOpenExp acc env aenv t -> ()+rnfPreOpenExp rnfA topExp =+  let+      rnfF :: PreOpenFun acc env' aenv' t' -> ()+      rnfF = rnfPreOpenFun rnfA++      rnfE :: PreOpenExp acc env' aenv' t' -> ()+      rnfE = rnfPreOpenExp rnfA+  in+  case topExp of+    Let bnd body              -> rnfE bnd `seq` rnfE body+    Var ix                    -> rnfIdx ix+    Foreign asm f x           -> rnf (strForeign asm) `seq` rnfF f `seq` rnfE x+    Const t                   -> rnfConst (eltType (undefined::t)) t+    Tuple t                   -> rnfTuple rnfA t+    Prj ix e                  -> rnfTupleIdx ix `seq` rnfE e+    IndexNil                  -> ()+    IndexCons sh sz           -> rnfE sh `seq` rnfE sz+    IndexHead sh              -> rnfE sh+    IndexTail sh              -> rnfE sh+    IndexAny                  -> ()+    IndexSlice slice slix sh  -> rnfSliceIndex slice `seq` rnfE slix `seq` rnfE sh+    IndexFull slice slix sl   -> rnfSliceIndex slice `seq` rnfE slix `seq` rnfE sl+    ToIndex sh ix             -> rnfE sh `seq` rnfE ix+    FromIndex sh ix           -> rnfE sh `seq` rnfE ix+    Cond p e1 e2              -> rnfE p `seq` rnfE e1 `seq` rnfE e2+    While p f x               -> rnfF p `seq` rnfF f `seq` rnfE x+    PrimConst c               -> rnfPrimConst c+    PrimApp f x               -> rnfPrimFun f `seq` rnfE x+    Index a ix                -> rnfA a `seq` rnfE ix+    LinearIndex a ix          -> rnfA a `seq` rnfE ix+    Shape a                   -> rnfA a+    ShapeSize sh              -> rnfE sh+    Intersect sh1 sh2         -> rnfE sh1 `seq` rnfE sh2+    Union sh1 sh2             -> rnfE sh1 `seq` rnfE sh2++rnfTuple :: NFDataAcc acc -> Tuple (PreOpenExp acc env aenv) t -> ()+rnfTuple _    NilTup        = ()+rnfTuple rnfA (SnocTup t e) = rnfTuple rnfA t `seq` rnfPreOpenExp rnfA e++rnfConst :: TupleType t -> t -> ()+rnfConst UnitTuple          ()    = ()+rnfConst (SingleTuple t)    !_    = rnfScalarType t  -- scalars should have (nf == whnf)+rnfConst (PairTuple ta tb)  (a,b) = rnfConst ta a `seq` rnfConst tb b++rnfPrimConst :: PrimConst c -> ()+rnfPrimConst (PrimMinBound t) = rnfBoundedType t+rnfPrimConst (PrimMaxBound t) = rnfBoundedType t+rnfPrimConst (PrimPi t)       = rnfFloatingType t++rnfPrimFun :: PrimFun f -> ()+rnfPrimFun (PrimAdd t)                = rnfNumType t+rnfPrimFun (PrimSub t)                = rnfNumType t+rnfPrimFun (PrimMul t)                = rnfNumType t+rnfPrimFun (PrimNeg t)                = rnfNumType t+rnfPrimFun (PrimAbs t)                = rnfNumType t+rnfPrimFun (PrimSig t)                = rnfNumType t+rnfPrimFun (PrimQuot t)               = rnfIntegralType t+rnfPrimFun (PrimRem t)                = rnfIntegralType t+rnfPrimFun (PrimQuotRem t)            = rnfIntegralType t+rnfPrimFun (PrimIDiv t)               = rnfIntegralType t+rnfPrimFun (PrimMod t)                = rnfIntegralType t+rnfPrimFun (PrimDivMod t)             = rnfIntegralType t+rnfPrimFun (PrimBAnd t)               = rnfIntegralType t+rnfPrimFun (PrimBOr t)                = rnfIntegralType t+rnfPrimFun (PrimBXor t)               = rnfIntegralType t+rnfPrimFun (PrimBNot t)               = rnfIntegralType t+rnfPrimFun (PrimBShiftL t)            = rnfIntegralType t+rnfPrimFun (PrimBShiftR t)            = rnfIntegralType t+rnfPrimFun (PrimBRotateL t)           = rnfIntegralType t+rnfPrimFun (PrimBRotateR t)           = rnfIntegralType t+rnfPrimFun (PrimPopCount t)           = rnfIntegralType t+rnfPrimFun (PrimCountLeadingZeros t)  = rnfIntegralType t+rnfPrimFun (PrimCountTrailingZeros t) = rnfIntegralType t+rnfPrimFun (PrimFDiv t)               = rnfFloatingType t+rnfPrimFun (PrimRecip t)              = rnfFloatingType t+rnfPrimFun (PrimSin t)                = rnfFloatingType t+rnfPrimFun (PrimCos t)                = rnfFloatingType t+rnfPrimFun (PrimTan t)                = rnfFloatingType t+rnfPrimFun (PrimAsin t)               = rnfFloatingType t+rnfPrimFun (PrimAcos t)               = rnfFloatingType t+rnfPrimFun (PrimAtan t)               = rnfFloatingType t+rnfPrimFun (PrimSinh t)               = rnfFloatingType t+rnfPrimFun (PrimCosh t)               = rnfFloatingType t+rnfPrimFun (PrimTanh t)               = rnfFloatingType t+rnfPrimFun (PrimAsinh t)              = rnfFloatingType t+rnfPrimFun (PrimAcosh t)              = rnfFloatingType t+rnfPrimFun (PrimAtanh t)              = rnfFloatingType t+rnfPrimFun (PrimExpFloating t)        = rnfFloatingType t+rnfPrimFun (PrimSqrt t)               = rnfFloatingType t+rnfPrimFun (PrimLog t)                = rnfFloatingType t+rnfPrimFun (PrimFPow t)               = rnfFloatingType t+rnfPrimFun (PrimLogBase t)            = rnfFloatingType t+rnfPrimFun (PrimTruncate f i)         = rnfFloatingType f `seq` rnfIntegralType i+rnfPrimFun (PrimRound f i)            = rnfFloatingType f `seq` rnfIntegralType i+rnfPrimFun (PrimFloor f i)            = rnfFloatingType f `seq` rnfIntegralType i+rnfPrimFun (PrimCeiling f i)          = rnfFloatingType f `seq` rnfIntegralType i+rnfPrimFun (PrimIsNaN t)              = rnfFloatingType t+rnfPrimFun (PrimAtan2 t)              = rnfFloatingType t+rnfPrimFun (PrimLt t)                 = rnfScalarType t+rnfPrimFun (PrimGt t)                 = rnfScalarType t+rnfPrimFun (PrimLtEq t)               = rnfScalarType t+rnfPrimFun (PrimGtEq t)               = rnfScalarType t+rnfPrimFun (PrimEq t)                 = rnfScalarType t+rnfPrimFun (PrimNEq t)                = rnfScalarType t+rnfPrimFun (PrimMax t)                = rnfScalarType t+rnfPrimFun (PrimMin t)                = rnfScalarType t+rnfPrimFun PrimLAnd                   = ()+rnfPrimFun PrimLOr                    = ()+rnfPrimFun PrimLNot                   = ()+rnfPrimFun PrimOrd                    = ()+rnfPrimFun PrimChr                    = ()+rnfPrimFun PrimBoolToInt              = ()+rnfPrimFun (PrimFromIntegral i n)     = rnfIntegralType i `seq` rnfNumType n+rnfPrimFun (PrimToFloating n f)       = rnfNumType n `seq` rnfFloatingType f+rnfPrimFun (PrimCoerce a b)           = rnfScalarType a `seq` rnfScalarType b++rnfSliceIndex :: SliceIndex ix slice co sh -> ()+rnfSliceIndex SliceNil        = ()+rnfSliceIndex (SliceAll sh)   = rnfSliceIndex sh+rnfSliceIndex (SliceFixed sh) = rnfSliceIndex sh++rnfScalarType :: ScalarType t -> ()+rnfScalarType (NumScalarType t)    = rnfNumType t+rnfScalarType (NonNumScalarType t) = rnfNonNumType t++rnfBoundedType :: BoundedType t -> ()+rnfBoundedType (IntegralBoundedType t) = rnfIntegralType t+rnfBoundedType (NonNumBoundedType t)   = rnfNonNumType t++rnfNumType :: NumType t -> ()+rnfNumType (IntegralNumType t) = rnfIntegralType t+rnfNumType (FloatingNumType t) = rnfFloatingType t++rnfNonNumType :: NonNumType t -> ()+rnfNonNumType (TypeBool   NonNumDict) = ()+rnfNonNumType (TypeChar   NonNumDict) = ()+rnfNonNumType (TypeCChar  NonNumDict) = ()+rnfNonNumType (TypeCSChar NonNumDict) = ()+rnfNonNumType (TypeCUChar NonNumDict) = ()++rnfIntegralType :: IntegralType t -> ()+rnfIntegralType (TypeInt     IntegralDict) = ()+rnfIntegralType (TypeInt8    IntegralDict) = ()+rnfIntegralType (TypeInt16   IntegralDict) = ()+rnfIntegralType (TypeInt32   IntegralDict) = ()+rnfIntegralType (TypeInt64   IntegralDict) = ()+rnfIntegralType (TypeWord    IntegralDict) = ()+rnfIntegralType (TypeWord8   IntegralDict) = ()+rnfIntegralType (TypeWord16  IntegralDict) = ()+rnfIntegralType (TypeWord32  IntegralDict) = ()+rnfIntegralType (TypeWord64  IntegralDict) = ()+rnfIntegralType (TypeCShort  IntegralDict) = ()+rnfIntegralType (TypeCUShort IntegralDict) = ()+rnfIntegralType (TypeCInt    IntegralDict) = ()+rnfIntegralType (TypeCUInt   IntegralDict) = ()+rnfIntegralType (TypeCLong   IntegralDict) = ()+rnfIntegralType (TypeCULong  IntegralDict) = ()+rnfIntegralType (TypeCLLong  IntegralDict) = ()+rnfIntegralType (TypeCULLong IntegralDict) = ()++rnfFloatingType :: FloatingType t -> ()+rnfFloatingType (TypeFloat   FloatingDict) = ()+rnfFloatingType (TypeDouble  FloatingDict) = ()+rnfFloatingType (TypeCFloat  FloatingDict) = ()+rnfFloatingType (TypeCDouble FloatingDict) = ()++ -- Debugging -- --------- @@ -970,6 +1506,7 @@ showPreAccOp Backpermute{}      = "Backpermute" showPreAccOp Stencil{}          = "Stencil" showPreAccOp Stencil2{}         = "Stencil2"+-- showPreAccOp Collect{}          = "Collect"  showArrays :: forall arrs. Arrays arrs => arrs -> String showArrays = display . collect (arrays (undefined::arrs)) . fromArr@@ -1017,4 +1554,5 @@ showPreExpOp Shape{}            = "Shape" showPreExpOp ShapeSize{}        = "ShapeSize" showPreExpOp Intersect{}        = "Intersect"+showPreExpOp Union{}            = "Union" 
Data/Array/Accelerate/Analysis/Match.hs view
@@ -7,1038 +7,1217 @@ {-# OPTIONS_HADDOCK hide #-} -- | -- Module      : Data.Array.Accelerate.Analysis.Match--- Copyright   : [2012..2014] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell--- License     : BSD3------ Maintainer  : Manuel M T Chakravarty <chak@cse.unsw.edu.au>--- Stability   : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Analysis.Match (--  -- matching expressions-  MatchAcc,-  (:=:)(..),-  matchOpenAcc,  matchPreOpenAcc,-  matchOpenAfun, matchPreOpenAfun,-  matchOpenExp,  matchPreOpenExp,-  matchOpenFun,  matchPreOpenFun,-  matchPrimFun,  matchPrimFun',--  -- auxiliary-  matchIdx, matchTupleType,-  matchIntegralType, matchFloatingType, matchNumType, matchScalarType,--  -- hashing expressions-  HashAcc,-  hashPreOpenAcc, hashOpenAcc,-  hashPreOpenExp, hashOpenExp,-  hashPreOpenFun,--) where---- standard library-import Prelude                                          hiding ( exp )-import Data.Maybe-import Data.Typeable-import Data.Hashable-import System.Mem.StableName-import System.IO.Unsafe                                 ( unsafePerformIO )---- friends-import Data.Array.Accelerate.AST-import Data.Array.Accelerate.Type-import Data.Array.Accelerate.Array.Sugar-import Data.Array.Accelerate.Array.Representation       ( SliceIndex(..) )-import Data.Array.Accelerate.Tuple                      hiding ( Tuple )-import qualified Data.Array.Accelerate.Tuple            as Tuple----- Witness equality between types. A value of a :=: b is a proof that types a--- and b are equal. By pattern matching on REFL this fact is introduced to the--- type checker.----data s :=: t where-  REFL :: s :=: s--deriving instance Show (s :=: t)----- The type of matching array computations----type MatchAcc acc = forall aenv s t. acc aenv s -> acc aenv t -> Maybe (s :=: t)----- Compute the congruence of two array computations. The nodes are congruent if--- they have the same operator and their operands are congruent.----matchOpenAcc :: OpenAcc aenv s -> OpenAcc aenv t -> Maybe (s :=: t)-matchOpenAcc (OpenAcc acc1) (OpenAcc acc2) =-  matchPreOpenAcc matchOpenAcc hashOpenAcc acc1 acc2---matchPreOpenAcc-    :: forall acc aenv s t.-       MatchAcc acc-    -> HashAcc  acc-    -> PreOpenAcc acc aenv s-    -> PreOpenAcc acc aenv t-    -> Maybe (s :=: t)-matchPreOpenAcc matchAcc hashAcc = match-  where-    matchFun :: PreOpenFun acc env' aenv' u -> PreOpenFun acc env' aenv' v -> Maybe (u :=: v)-    matchFun = matchPreOpenFun matchAcc hashAcc--    matchExp :: PreOpenExp acc env' aenv' u -> PreOpenExp acc env' aenv' v -> Maybe (u :=: v)-    matchExp = matchPreOpenExp matchAcc hashAcc--    match :: PreOpenAcc acc aenv s -> PreOpenAcc acc aenv t -> Maybe (s :=: t)-    match (Alet x1 a1) (Alet x2 a2)-      | Just REFL <- matchAcc x1 x2-      , Just REFL <- matchAcc a1 a2-      = Just REFL--    match (Avar v1) (Avar v2)-      = matchIdx v1 v2--    match (Atuple t1) (Atuple t2)-      | Just REFL <- matchAtuple matchAcc t1 t2-      = gcast REFL  -- surface/representation type--    match (Aprj ix1 t1) (Aprj ix2 t2)-      | Just REFL <- matchAcc t1 t2-      , Just REFL <- matchTupleIdx ix1 ix2-      = Just REFL--    match (Apply f1 a1) (Apply f2 a2)-      | Just REFL <- matchPreOpenAfun matchAcc f1 f2-      , Just REFL <- matchAcc                  a1 a2-      = Just REFL--    match (Aforeign ff1 _ a1) (Aforeign ff2 _ a2)-      | Just REFL <- matchAcc a1 a2-      , unsafePerformIO $ do-          sn1 <- makeStableName ff1-          sn2 <- makeStableName ff2-          return $! hashStableName sn1 == hashStableName sn2-      = gcast REFL--    match (Acond p1 t1 e1) (Acond p2 t2 e2)-      | Just REFL <- matchExp p1 p2-      , Just REFL <- matchAcc t1 t2-      , Just REFL <- matchAcc e1 e2-      = Just REFL--    match (Awhile p1 f1 a1) (Awhile p2 f2 a2)-      | Just REFL <- matchAcc a1 a2-      , Just REFL <- matchPreOpenAfun matchAcc p1 p2-      , Just REFL <- matchPreOpenAfun matchAcc f1 f2-      = Just REFL--    match (Use a1) (Use a2)-      | Just REFL <- matchArrays (arrays (undefined::s)) (arrays (undefined::t)) a1 a2-      = gcast REFL--    match (Unit e1) (Unit e2)-      | Just REFL <- matchExp e1 e2-      = Just REFL--    match (Reshape sh1 a1) (Reshape sh2 a2)-      | Just REFL <- matchExp sh1 sh2-      , Just REFL <- matchAcc a1  a2-      = Just REFL--    match (Generate sh1 f1) (Generate sh2 f2)-      | Just REFL <- matchExp sh1 sh2-      , Just REFL <- matchFun f1  f2-      = Just REFL--    match (Transform sh1 ix1 f1 a1) (Transform sh2 ix2 f2 a2)-      | Just REFL <- matchExp sh1 sh2-      , Just REFL <- matchFun ix1 ix2-      , Just REFL <- matchFun f1  f2-      , Just REFL <- matchAcc a1  a2-      = Just REFL--    match (Replicate _ ix1 a1) (Replicate _ ix2 a2)-      | Just REFL <- matchExp ix1 ix2-      , Just REFL <- matchAcc a1  a2-      = gcast REFL  -- slice specification ??--    match (Slice _ a1 ix1) (Slice _ a2 ix2)-      | Just REFL <- matchAcc a1  a2-      , Just REFL <- matchExp ix1 ix2-      = gcast REFL  -- slice specification ??--    match (Map f1 a1) (Map f2 a2)-      | Just REFL <- matchFun f1 f2-      , Just REFL <- matchAcc a1 a2-      = Just REFL--    match (ZipWith f1 a1 b1) (ZipWith f2 a2 b2)-      | Just REFL <- matchFun f1 f2-      , Just REFL <- matchAcc a1 a2-      , Just REFL <- matchAcc b1 b2-      = Just REFL--    match (Fold f1 z1 a1) (Fold f2 z2 a2)-      | Just REFL <- matchFun f1 f2-      , Just REFL <- matchExp z1 z2-      , Just REFL <- matchAcc a1 a2-      = Just REFL--    match (Fold1 f1 a1) (Fold1 f2 a2)-      | Just REFL <- matchFun f1 f2-      , Just REFL <- matchAcc a1 a2-      = Just REFL--    match (FoldSeg f1 z1 a1 s1) (FoldSeg f2 z2 a2 s2)-      | Just REFL <- matchFun f1 f2-      , Just REFL <- matchExp z1 z2-      , Just REFL <- matchAcc a1 a2-      , Just REFL <- matchAcc s1 s2-      = Just REFL--    match (Fold1Seg f1 a1 s1) (Fold1Seg f2 a2 s2)-      | Just REFL <- matchFun f1 f2-      , Just REFL <- matchAcc a1 a2-      , Just REFL <- matchAcc s1 s2-      = Just REFL--    match (Scanl f1 z1 a1) (Scanl f2 z2 a2)-      | Just REFL <- matchFun f1 f2-      , Just REFL <- matchExp z1 z2-      , Just REFL <- matchAcc a1 a2-      = Just REFL--    match (Scanl' f1 z1 a1) (Scanl' f2 z2 a2)-      | Just REFL <- matchFun f1 f2-      , Just REFL <- matchExp z1 z2-      , Just REFL <- matchAcc a1 a2-      = Just REFL--    match (Scanl1 f1 a1) (Scanl1 f2 a2)-      | Just REFL <- matchFun f1 f2-      , Just REFL <- matchAcc a1 a2-      = Just REFL--    match (Scanr f1 z1 a1) (Scanr f2 z2 a2)-      | Just REFL <- matchFun f1 f2-      , Just REFL <- matchExp z1 z2-      , Just REFL <- matchAcc a1 a2-      = Just REFL--    match (Scanr' f1 z1 a1) (Scanr' f2 z2 a2)-      | Just REFL <- matchFun f1 f2-      , Just REFL <- matchExp z1 z2-      , Just REFL <- matchAcc a1 a2-      = Just REFL--    match (Scanr1 f1 a1) (Scanr1 f2 a2)-      | Just REFL <- matchFun f1 f2-      , Just REFL <- matchAcc a1 a2-      = Just REFL--    match (Permute f1 d1 p1 a1) (Permute f2 d2 p2 a2)-      | Just REFL <- matchFun f1 f2-      , Just REFL <- matchAcc d1 d2-      , Just REFL <- matchFun p1 p2-      , Just REFL <- matchAcc a1 a2-      = Just REFL--    match (Backpermute sh1 ix1 a1) (Backpermute sh2 ix2 a2)-      | Just REFL <- matchExp sh1 sh2-      , Just REFL <- matchFun ix1 ix2-      , Just REFL <- matchAcc a1  a2-      = Just REFL--    match (Stencil f1 b1 (a1 :: acc aenv (Array sh1 e1)))-          (Stencil f2 b2 (a2 :: acc aenv (Array sh2 e2)))-      | Just REFL <- matchFun f1 f2-      , Just REFL <- matchAcc a1 a2-      , matchBoundary (eltType (undefined::e1)) b1 b2-      = Just REFL--    match (Stencil2 f1 b1  (a1  :: acc aenv (Array sh1  e1 )) b2  (a2 :: acc aenv (Array sh2  e2 )))-          (Stencil2 f2 b1' (a1' :: acc aenv (Array sh1' e1')) b2' (a2':: acc aenv (Array sh2' e2')))-      | Just REFL <- matchFun f1 f2-      , Just REFL <- matchAcc a1 a1'-      , Just REFL <- matchAcc a2 a2'-      , matchBoundary (eltType (undefined::e1)) b1 b1'-      , matchBoundary (eltType (undefined::e2)) b2 b2'-      = Just REFL--    match _ _-      = Nothing----- Array tuples----matchAtuple-    :: MatchAcc acc-    -> Atuple (acc aenv) s-    -> Atuple (acc aenv) t-    -> Maybe (s :=: t)-matchAtuple matchAcc (SnocAtup t1 a1) (SnocAtup t2 a2)-  | Just REFL <- matchAtuple matchAcc t1 t2-  , Just REFL <- matchAcc             a1 a2-  = Just REFL--matchAtuple _ NilAtup NilAtup = Just REFL-matchAtuple _ _       _       = Nothing----- Array functions----matchOpenAfun :: OpenAfun aenv s -> OpenAfun aenv t -> Maybe (s :=: t)-matchOpenAfun = matchPreOpenAfun matchOpenAcc--matchPreOpenAfun :: MatchAcc acc -> PreOpenAfun acc aenv s -> PreOpenAfun acc aenv t -> Maybe (s :=: t)-matchPreOpenAfun m (Alam s) (Alam t)-  | Just REFL <- matchEnvTop        s t-  , Just REFL <- matchPreOpenAfun m s t-  = Just REFL-  where-    matchEnvTop :: (Arrays s, Arrays t)-                => PreOpenAfun acc (aenv, s) f -> PreOpenAfun acc (aenv, t) g -> Maybe (s :=: t)-    matchEnvTop _ _ = gcast REFL  -- ???--matchPreOpenAfun m (Abody s) (Abody t) = m s t-matchPreOpenAfun _ _         _         = Nothing----- Match stencil boundaries----matchBoundary :: TupleType e -> Boundary e -> Boundary e -> Bool-matchBoundary ty (Constant s) (Constant t) = matchConst ty s t-matchBoundary _  Wrap         Wrap         = True-matchBoundary _  Clamp        Clamp        = True-matchBoundary _  Mirror       Mirror       = True-matchBoundary _  _            _            = False----- Match arrays------ As a convenience, we are just comparing the stable names, but we could also--- walk the structure comparing the underlying ptrsOfArrayData.----matchArrays :: ArraysR s -> ArraysR t -> s -> t -> Maybe (s :=: t)-matchArrays ArraysRunit ArraysRunit () ()-  = Just REFL--matchArrays (ArraysRpair a1 b1) (ArraysRpair a2 b2) (arr1,brr1) (arr2,brr2)-  | Just REFL <- matchArrays a1 a2 arr1 arr2-  , Just REFL <- matchArrays b1 b2 brr1 brr2-  = Just REFL--matchArrays ArraysRarray ArraysRarray (Array _ ad1) (Array _ ad2)-  | unsafePerformIO $ do-      sn1 <- makeStableName ad1-      sn2 <- makeStableName ad2-      return $! hashStableName sn1 == hashStableName sn2-  = gcast REFL--matchArrays _ _ _ _-  = Nothing----- Compute the congruence of two scalar expressions. Two nodes are congruent if--- either:------  1. The nodes label constants and the contents are equal---  2. They have the same operator and their operands are congruent------ The below attempts to use real typed equality, but occasionally still needs--- to use a cast, particularly when we can only match the representation types.----matchOpenExp :: OpenExp env aenv s -> OpenExp env aenv t -> Maybe (s :=: t)-matchOpenExp = matchPreOpenExp matchOpenAcc hashOpenAcc--matchPreOpenExp-    :: forall acc env aenv s t.-       MatchAcc acc-    -> HashAcc  acc-    -> PreOpenExp acc env aenv s-    -> PreOpenExp acc env aenv t-    -> Maybe (s :=: t)-matchPreOpenExp matchAcc hashAcc = match-  where-    match :: forall env' aenv' s' t'. PreOpenExp acc env' aenv' s' -> PreOpenExp acc env' aenv' t' -> Maybe (s' :=: t')-    match (Let x1 e1) (Let x2 e2)-      | Just REFL <- match x1 x2-      , Just REFL <- match e1 e2-      = Just REFL--    match (Var v1) (Var v2)-      = matchIdx v1 v2--    match (Foreign ff1 _ e1) (Foreign ff2 _ e2)-      | Just REFL <- match e1 e2-      , unsafePerformIO $ do-          sn1 <- makeStableName ff1-          sn2 <- makeStableName ff2-          return $! hashStableName sn1 == hashStableName sn2-      = gcast REFL--    match (Const c1) (Const c2)-      | Just REFL <- matchTupleType (eltType (undefined::s')) (eltType (undefined::t'))-      , matchConst (eltType (undefined::s')) c1 c2-      = gcast REFL  -- surface/representation type--    match (Tuple t1) (Tuple t2)-      | Just REFL <- matchTuple matchAcc hashAcc t1 t2-      = gcast REFL  -- surface/representation type--    match (Prj ix1 t1) (Prj ix2 t2)-      | Just REFL <- match         t1  t2-      , Just REFL <- matchTupleIdx ix1 ix2-      = Just REFL--    match IndexAny IndexAny-      = gcast REFL  -- ???--    match IndexNil IndexNil-      = Just REFL--    match (IndexCons sl1 a1) (IndexCons sl2 a2)-      | Just REFL <- match sl1 sl2-      , Just REFL <- match a1 a2-      = Just REFL--    match (IndexHead sl1) (IndexHead sl2)-      | Just REFL <- match sl1 sl2-      = Just REFL--    match (IndexTail sl1) (IndexTail sl2)-      | Just REFL <- match sl1 sl2-      = Just REFL--    match (IndexSlice sliceIndex1 ix1 sh1) (IndexSlice sliceIndex2 ix2 sh2)-      | Just REFL <- match ix1 ix2-      , Just REFL <- match sh1 sh2-      , Just REFL <- matchSliceRestrict sliceIndex1 sliceIndex2-      = gcast REFL  -- SliceIndex representation/surface type--    match (IndexFull sliceIndex1 ix1 sl1) (IndexFull sliceIndex2 ix2 sl2)-      | Just REFL <- match ix1 ix2-      , Just REFL <- match sl1 sl2-      , Just REFL <- matchSliceExtend sliceIndex1 sliceIndex2-      = gcast REFL  -- SliceIndex representation/surface type--    match (ToIndex sh1 i1) (ToIndex sh2 i2)-      | Just REFL <- match sh1 sh2-      , Just REFL <- match i1  i2-      = Just REFL--    match (FromIndex sh1 i1) (FromIndex sh2 i2)-      | Just REFL <- match i1  i2-      , Just REFL <- match sh1 sh2-      = Just REFL--    match (Cond p1 t1 e1) (Cond p2 t2 e2)-      | Just REFL <- match p1 p2-      , Just REFL <- match t1 t2-      , Just REFL <- match e1 e2-      = Just REFL--    match (While p1 f1 x1) (While p2 f2 x2)-      | Just REFL <- match x1 x2-      , Just REFL <- matchPreOpenFun matchAcc hashAcc p1 p2-      , Just REFL <- matchPreOpenFun matchAcc hashAcc f1 f2-      = Just REFL--    match (PrimConst c1) (PrimConst c2)-      = matchPrimConst c1 c2--    match (PrimApp f1 x1) (PrimApp f2 x2)-      | Just x1'  <- commutes hashAcc f1 x1-      , Just x2'  <- commutes hashAcc f2 x2-      , Just REFL <- match        x1' x2'-      , Just REFL <- matchPrimFun f1  f2-      = Just REFL--      | Just REFL <- match x1 x2-      , Just REFL <- matchPrimFun f1 f2-      = Just REFL--    match (Index a1 x1) (Index a2 x2)-      | Just REFL <- matchAcc a1 a2     -- should only be array indices-      , Just REFL <- match    x1 x2-      = Just REFL--    match (LinearIndex a1 x1) (LinearIndex a2 x2)-      | Just REFL <- matchAcc a1 a2-      , Just REFL <- match    x1 x2-      = Just REFL--    match (Shape a1) (Shape a2)-      | Just REFL <- matchAcc a1 a2     -- should only be array indices-      = Just REFL--    match (ShapeSize sh1) (ShapeSize sh2)-      | Just REFL <- match sh1 sh2-      = Just REFL--    match (Intersect sa1 sb1) (Intersect sa2 sb2)-      | Just REFL <- match sa1 sa2-      , Just REFL <- match sb1 sb2-      = Just REFL--    match _ _-      = Nothing----- Match scalar functions----matchOpenFun :: OpenFun env aenv s -> OpenFun env aenv t -> Maybe (s :=: t)-matchOpenFun = matchPreOpenFun matchOpenAcc hashOpenAcc--matchPreOpenFun-    :: MatchAcc acc-    -> HashAcc  acc-    -> PreOpenFun acc env aenv s-    -> PreOpenFun acc env aenv t-    -> Maybe (s :=: t)-matchPreOpenFun m h (Lam s) (Lam t)-  | Just REFL <- matchEnvTop         s t-  , Just REFL <- matchPreOpenFun m h s t-  = Just REFL-  where-    matchEnvTop :: (Elt s, Elt t) => PreOpenFun acc (env, s) aenv f -> PreOpenFun acc (env, t) aenv g -> Maybe (s :=: t)-    matchEnvTop _ _ = gcast REFL  -- ???--matchPreOpenFun m h (Body s) (Body t) = matchPreOpenExp m h s t-matchPreOpenFun _ _ _        _        = Nothing---- Matching constants----matchConst :: TupleType a -> a -> a -> Bool-matchConst UnitTuple         ()      ()      = True-matchConst (SingleTuple ty)  a       b       = evalEq ty (a,b)-matchConst (PairTuple ta tb) (a1,b1) (a2,b2) = matchConst ta a1 a2 && matchConst tb b1 b2--evalEq :: ScalarType a -> (a, a) -> Bool-evalEq (NumScalarType (IntegralNumType ty)) | IntegralDict <- integralDict ty = uncurry (==)-evalEq (NumScalarType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = uncurry (==)-evalEq (NonNumScalarType ty)                | NonNumDict   <- nonNumDict ty   = uncurry (==)----- Environment projection indices----matchIdx :: Idx env s -> Idx env t -> Maybe (s :=: t)-matchIdx ZeroIdx     ZeroIdx     = Just REFL-matchIdx (SuccIdx u) (SuccIdx v) = matchIdx u v-matchIdx _           _           = Nothing----- Tuple projection indices. Given the same tuple expression structure (tup),--- check that the indices project identical elements.----matchTupleIdx :: TupleIdx tup s -> TupleIdx tup t -> Maybe (s :=: t)-matchTupleIdx ZeroTupIdx     ZeroTupIdx     = Just REFL-matchTupleIdx (SuccTupIdx s) (SuccTupIdx t) = matchTupleIdx s t-matchTupleIdx _              _              = Nothing---- Tuples----matchTuple-    :: MatchAcc acc-    -> HashAcc  acc-    -> Tuple.Tuple (PreOpenExp acc env aenv) s-    -> Tuple.Tuple (PreOpenExp acc env aenv) t-    -> Maybe (s :=: t)-matchTuple _ _ NilTup          NilTup           = Just REFL-matchTuple m h (SnocTup t1 e1) (SnocTup t2 e2)-  | Just REFL <- matchTuple      m h t1 t2-  , Just REFL <- matchPreOpenExp m h e1 e2-  = Just REFL--matchTuple _ _ _               _                = Nothing----- Slice specifications----matchSliceRestrict-    :: SliceIndex slix s co  sh-    -> SliceIndex slix t co' sh-    -> Maybe (s :=: t)-matchSliceRestrict SliceNil SliceNil-  = Just REFL--matchSliceRestrict (SliceAll   sl1) (SliceAll   sl2)-  | Just REFL <- matchSliceRestrict sl1 sl2-  = Just REFL--matchSliceRestrict (SliceFixed sl1) (SliceFixed sl2)-  | Just REFL <- matchSliceRestrict sl1 sl2-  = Just REFL--matchSliceRestrict _ _-  = Nothing---matchSliceExtend-    :: SliceIndex slix sl co  s-    -> SliceIndex slix sl co' t-    -> Maybe (s :=: t)-matchSliceExtend SliceNil SliceNil-  = Just REFL--matchSliceExtend (SliceAll   sl1) (SliceAll   sl2)-  | Just REFL <- matchSliceExtend sl1 sl2-  = Just REFL--matchSliceExtend (SliceFixed sl1) (SliceFixed sl2)-  | Just REFL <- matchSliceExtend sl1 sl2-  = Just REFL--matchSliceExtend _ _-  = Nothing----- Primitive constants and functions----matchPrimConst :: (Elt s, Elt t) => PrimConst s -> PrimConst t -> Maybe (s :=: t)-matchPrimConst (PrimMinBound s) (PrimMinBound t) = matchBoundedType s t-matchPrimConst (PrimMaxBound s) (PrimMaxBound t) = matchBoundedType s t-matchPrimConst (PrimPi s)       (PrimPi t)       = matchFloatingType s t-matchPrimConst _                _                = Nothing----- Covariant function matching----matchPrimFun :: (Elt s, Elt t) => PrimFun (a -> s) -> PrimFun (a -> t) -> Maybe (s :=: t)-matchPrimFun (PrimAdd _)            (PrimAdd _)            = Just REFL-matchPrimFun (PrimSub _)            (PrimSub _)            = Just REFL-matchPrimFun (PrimMul _)            (PrimMul _)            = Just REFL-matchPrimFun (PrimNeg _)            (PrimNeg _)            = Just REFL-matchPrimFun (PrimAbs _)            (PrimAbs _)            = Just REFL-matchPrimFun (PrimSig _)            (PrimSig _)            = Just REFL-matchPrimFun (PrimQuot _)           (PrimQuot _)           = Just REFL-matchPrimFun (PrimRem _)            (PrimRem _)            = Just REFL-matchPrimFun (PrimIDiv _)           (PrimIDiv _)           = Just REFL-matchPrimFun (PrimMod _)            (PrimMod _)            = Just REFL-matchPrimFun (PrimBAnd _)           (PrimBAnd _)           = Just REFL-matchPrimFun (PrimBOr _)            (PrimBOr _)            = Just REFL-matchPrimFun (PrimBXor _)           (PrimBXor _)           = Just REFL-matchPrimFun (PrimBNot _)           (PrimBNot _)           = Just REFL-matchPrimFun (PrimBShiftL _)        (PrimBShiftL _)        = Just REFL-matchPrimFun (PrimBShiftR _)        (PrimBShiftR _)        = Just REFL-matchPrimFun (PrimBRotateL _)       (PrimBRotateL _)       = Just REFL-matchPrimFun (PrimBRotateR _)       (PrimBRotateR _)       = Just REFL-matchPrimFun (PrimFDiv _)           (PrimFDiv _)           = Just REFL-matchPrimFun (PrimRecip _)          (PrimRecip _)          = Just REFL-matchPrimFun (PrimSin _)            (PrimSin _)            = Just REFL-matchPrimFun (PrimCos _)            (PrimCos _)            = Just REFL-matchPrimFun (PrimTan _)            (PrimTan _)            = Just REFL-matchPrimFun (PrimAsin _)           (PrimAsin _)           = Just REFL-matchPrimFun (PrimAcos _)           (PrimAcos _)           = Just REFL-matchPrimFun (PrimAtan _)           (PrimAtan _)           = Just REFL-matchPrimFun (PrimAsinh _)          (PrimAsinh _)          = Just REFL-matchPrimFun (PrimAcosh _)          (PrimAcosh _)          = Just REFL-matchPrimFun (PrimAtanh _)          (PrimAtanh _)          = Just REFL-matchPrimFun (PrimExpFloating _)    (PrimExpFloating _)    = Just REFL-matchPrimFun (PrimSqrt _)           (PrimSqrt _)           = Just REFL-matchPrimFun (PrimLog _)            (PrimLog _)            = Just REFL-matchPrimFun (PrimFPow _)           (PrimFPow _)           = Just REFL-matchPrimFun (PrimLogBase _)        (PrimLogBase _)        = Just REFL-matchPrimFun (PrimAtan2 _)          (PrimAtan2 _)          = Just REFL-matchPrimFun (PrimTruncate _ s)     (PrimTruncate _ t)     = matchIntegralType s t-matchPrimFun (PrimRound _ s)        (PrimRound _ t)        = matchIntegralType s t-matchPrimFun (PrimFloor _ s)        (PrimFloor _ t)        = matchIntegralType s t-matchPrimFun (PrimCeiling _ s)      (PrimCeiling _ t)      = matchIntegralType s t-matchPrimFun (PrimLt _)             (PrimLt _)             = Just REFL-matchPrimFun (PrimGt _)             (PrimGt _)             = Just REFL-matchPrimFun (PrimLtEq _)           (PrimLtEq _)           = Just REFL-matchPrimFun (PrimGtEq _)           (PrimGtEq _)           = Just REFL-matchPrimFun (PrimEq _)             (PrimEq _)             = Just REFL-matchPrimFun (PrimNEq _)            (PrimNEq _)            = Just REFL-matchPrimFun (PrimMax _)            (PrimMax _)            = Just REFL-matchPrimFun (PrimMin _)            (PrimMin _)            = Just REFL-matchPrimFun (PrimFromIntegral _ s) (PrimFromIntegral _ t) = matchNumType s t-matchPrimFun PrimLAnd               PrimLAnd               = Just REFL-matchPrimFun PrimLOr                PrimLOr                = Just REFL-matchPrimFun PrimLNot               PrimLNot               = Just REFL-matchPrimFun PrimOrd                PrimOrd                = Just REFL-matchPrimFun PrimChr                PrimChr                = Just REFL-matchPrimFun PrimBoolToInt          PrimBoolToInt          = Just REFL-matchPrimFun _                      _                      = Nothing----- Contravariant function matching----matchPrimFun' :: (Elt s, Elt t) => PrimFun (s -> a) -> PrimFun (t -> a) -> Maybe (s :=: t)-matchPrimFun' (PrimAdd _)            (PrimAdd _)            = Just REFL-matchPrimFun' (PrimSub _)            (PrimSub _)            = Just REFL-matchPrimFun' (PrimMul _)            (PrimMul _)            = Just REFL-matchPrimFun' (PrimNeg _)            (PrimNeg _)            = Just REFL-matchPrimFun' (PrimAbs _)            (PrimAbs _)            = Just REFL-matchPrimFun' (PrimSig _)            (PrimSig _)            = Just REFL-matchPrimFun' (PrimQuot _)           (PrimQuot _)           = Just REFL-matchPrimFun' (PrimRem _)            (PrimRem _)            = Just REFL-matchPrimFun' (PrimIDiv _)           (PrimIDiv _)           = Just REFL-matchPrimFun' (PrimMod _)            (PrimMod _)            = Just REFL-matchPrimFun' (PrimBAnd _)           (PrimBAnd _)           = Just REFL-matchPrimFun' (PrimBOr _)            (PrimBOr _)            = Just REFL-matchPrimFun' (PrimBXor _)           (PrimBXor _)           = Just REFL-matchPrimFun' (PrimBNot _)           (PrimBNot _)           = Just REFL-matchPrimFun' (PrimBShiftL _)        (PrimBShiftL _)        = Just REFL-matchPrimFun' (PrimBShiftR _)        (PrimBShiftR _)        = Just REFL-matchPrimFun' (PrimBRotateL _)       (PrimBRotateL _)       = Just REFL-matchPrimFun' (PrimBRotateR _)       (PrimBRotateR _)       = Just REFL-matchPrimFun' (PrimFDiv _)           (PrimFDiv _)           = Just REFL-matchPrimFun' (PrimRecip _)          (PrimRecip _)          = Just REFL-matchPrimFun' (PrimSin _)            (PrimSin _)            = Just REFL-matchPrimFun' (PrimCos _)            (PrimCos _)            = Just REFL-matchPrimFun' (PrimTan _)            (PrimTan _)            = Just REFL-matchPrimFun' (PrimAsin _)           (PrimAsin _)           = Just REFL-matchPrimFun' (PrimAcos _)           (PrimAcos _)           = Just REFL-matchPrimFun' (PrimAtan _)           (PrimAtan _)           = Just REFL-matchPrimFun' (PrimAsinh _)          (PrimAsinh _)          = Just REFL-matchPrimFun' (PrimAcosh _)          (PrimAcosh _)          = Just REFL-matchPrimFun' (PrimAtanh _)          (PrimAtanh _)          = Just REFL-matchPrimFun' (PrimExpFloating _)    (PrimExpFloating _)    = Just REFL-matchPrimFun' (PrimSqrt _)           (PrimSqrt _)           = Just REFL-matchPrimFun' (PrimLog _)            (PrimLog _)            = Just REFL-matchPrimFun' (PrimFPow _)           (PrimFPow _)           = Just REFL-matchPrimFun' (PrimLogBase _)        (PrimLogBase _)        = Just REFL-matchPrimFun' (PrimAtan2 _)          (PrimAtan2 _)          = Just REFL-matchPrimFun' (PrimTruncate s _)     (PrimTruncate t _)     = matchFloatingType s t-matchPrimFun' (PrimRound s _)        (PrimRound t _)        = matchFloatingType s t-matchPrimFun' (PrimFloor s _)        (PrimFloor t _)        = matchFloatingType s t-matchPrimFun' (PrimCeiling s _)      (PrimCeiling t _)      = matchFloatingType s t-matchPrimFun' (PrimMax _)            (PrimMax _)            = Just REFL-matchPrimFun' (PrimMin _)            (PrimMin _)            = Just REFL-matchPrimFun' (PrimFromIntegral s _) (PrimFromIntegral t _) = matchIntegralType s t-matchPrimFun' PrimLAnd               PrimLAnd               = Just REFL-matchPrimFun' PrimLOr                PrimLOr                = Just REFL-matchPrimFun' PrimLNot               PrimLNot               = Just REFL-matchPrimFun' PrimOrd                PrimOrd                = Just REFL-matchPrimFun' PrimChr                PrimChr                = Just REFL-matchPrimFun' PrimBoolToInt          PrimBoolToInt          = Just REFL-matchPrimFun' (PrimLt s) (PrimLt t)-  | Just REFL <- matchScalarType s t-  = Just REFL--matchPrimFun' (PrimGt s) (PrimGt t)-  | Just REFL <- matchScalarType s t-  = Just REFL--matchPrimFun' (PrimLtEq s) (PrimLtEq t)-  | Just REFL <- matchScalarType s t-  = Just REFL--matchPrimFun' (PrimGtEq s) (PrimGtEq t)-  | Just REFL <- matchScalarType s t-  = Just REFL--matchPrimFun' (PrimEq s) (PrimEq t)-  | Just REFL <- matchScalarType s t-  = Just REFL--matchPrimFun' (PrimNEq s) (PrimNEq t)-  | Just REFL <- matchScalarType s t-  = Just REFL--matchPrimFun' _ _-  = Nothing----- Match reified types----matchTupleType :: TupleType s -> TupleType t -> Maybe (s :=: t)-matchTupleType UnitTuple         UnitTuple         = Just REFL-matchTupleType (SingleTuple s)   (SingleTuple t)   = matchScalarType s t-matchTupleType (PairTuple s1 s2) (PairTuple t1 t2)-  | Just REFL <- matchTupleType s1 t1-  , Just REFL <- matchTupleType s2 t2-  = Just REFL--matchTupleType _ _-  = Nothing----- Match reified type dictionaries----matchScalarType :: ScalarType s -> ScalarType t -> Maybe (s :=: t)-matchScalarType (NumScalarType s)    (NumScalarType t)    = matchNumType s t-matchScalarType (NonNumScalarType s) (NonNumScalarType t) = matchNonNumType s t-matchScalarType _                    _                    = Nothing--matchNumType :: NumType s -> NumType t -> Maybe (s :=: t)-matchNumType (IntegralNumType s) (IntegralNumType t) = matchIntegralType s t-matchNumType (FloatingNumType s) (FloatingNumType t) = matchFloatingType s t-matchNumType _                   _                   = Nothing--matchBoundedType :: BoundedType s -> BoundedType t -> Maybe (s :=: t)-matchBoundedType (IntegralBoundedType s) (IntegralBoundedType t) = matchIntegralType s t-matchBoundedType (NonNumBoundedType s)   (NonNumBoundedType t)   = matchNonNumType s t-matchBoundedType _                       _                       = Nothing--matchIntegralType :: IntegralType s -> IntegralType t -> Maybe (s :=: t)-matchIntegralType (TypeInt _)     (TypeInt _)     = Just REFL-matchIntegralType (TypeInt8 _)    (TypeInt8 _)    = Just REFL-matchIntegralType (TypeInt16 _)   (TypeInt16 _)   = Just REFL-matchIntegralType (TypeInt32 _)   (TypeInt32 _)   = Just REFL-matchIntegralType (TypeInt64 _)   (TypeInt64 _)   = Just REFL-matchIntegralType (TypeWord _)    (TypeWord _)    = Just REFL-matchIntegralType (TypeWord8 _)   (TypeWord8 _)   = Just REFL-matchIntegralType (TypeWord16 _)  (TypeWord16 _)  = Just REFL-matchIntegralType (TypeWord32 _)  (TypeWord32 _)  = Just REFL-matchIntegralType (TypeWord64 _)  (TypeWord64 _)  = Just REFL-matchIntegralType (TypeCShort _)  (TypeCShort _)  = Just REFL-matchIntegralType (TypeCUShort _) (TypeCUShort _) = Just REFL-matchIntegralType (TypeCInt _)    (TypeCInt _)    = Just REFL-matchIntegralType (TypeCUInt _)   (TypeCUInt _)   = Just REFL-matchIntegralType (TypeCLong _)   (TypeCLong _)   = Just REFL-matchIntegralType (TypeCULong _)  (TypeCULong _)  = Just REFL-matchIntegralType (TypeCLLong _)  (TypeCLLong _)  = Just REFL-matchIntegralType (TypeCULLong _) (TypeCULLong _) = Just REFL-matchIntegralType _               _               = Nothing--matchFloatingType :: FloatingType s -> FloatingType t -> Maybe (s :=: t)-matchFloatingType (TypeFloat _)   (TypeFloat _)   = Just REFL-matchFloatingType (TypeDouble _)  (TypeDouble _)  = Just REFL-matchFloatingType (TypeCFloat _)  (TypeCFloat _)  = Just REFL-matchFloatingType (TypeCDouble _) (TypeCDouble _) = Just REFL-matchFloatingType _               _               = Nothing--matchNonNumType :: NonNumType s -> NonNumType t -> Maybe (s :=: t)-matchNonNumType (TypeBool _)   (TypeBool _)   = Just REFL-matchNonNumType (TypeChar _)   (TypeChar _)   = Just REFL-matchNonNumType (TypeCChar _)  (TypeCChar _)  = Just REFL-matchNonNumType (TypeCSChar _) (TypeCSChar _) = Just REFL-matchNonNumType (TypeCUChar _) (TypeCUChar _) = Just REFL-matchNonNumType _              _              = Nothing----- Discriminate binary functions that commute, and if so return the operands in--- a stable ordering such that matching recognises expressions modulo--- commutativity.----commutes-    :: forall acc env aenv a r.-       HashAcc acc-    -> PrimFun (a -> r)-    -> PreOpenExp acc env aenv a-    -> Maybe (PreOpenExp acc env aenv a)-commutes h f x = case f of-  PrimAdd _     -> Just (swizzle x)-  PrimMul _     -> Just (swizzle x)-  PrimBAnd _    -> Just (swizzle x)-  PrimBOr _     -> Just (swizzle x)-  PrimBXor _    -> Just (swizzle x)-  PrimEq _      -> Just (swizzle x)-  PrimNEq _     -> Just (swizzle x)-  PrimMax _     -> Just (swizzle x)-  PrimMin _     -> Just (swizzle x)-  PrimLAnd      -> Just (swizzle x)-  PrimLOr       -> Just (swizzle x)-  _             -> Nothing-  where-    swizzle :: PreOpenExp acc env aenv (a',a') -> PreOpenExp acc env aenv (a',a')-    swizzle exp-      | Tuple (NilTup `SnocTup` a `SnocTup` b)  <- exp-      , hashPreOpenExp h a > hashPreOpenExp h b = Tuple (NilTup `SnocTup` b `SnocTup` a)-      ---      | otherwise                               = exp----- Hashing--- =======--hashIdx :: Idx env t -> Int-hashIdx = hash . idxToInt--hashTupleIdx :: TupleIdx tup e -> Int-hashTupleIdx = hash . tupleIdxToInt----- Array computations--- --------------------type HashAcc acc = forall aenv a. acc aenv a -> Int---hashOpenAcc :: OpenAcc aenv arrs -> Int-hashOpenAcc (OpenAcc pacc) = hashPreOpenAcc hashOpenAcc pacc--hashPreOpenAcc :: forall acc aenv arrs. HashAcc acc -> PreOpenAcc acc aenv arrs -> Int-hashPreOpenAcc hashAcc pacc =-  let-    hashA :: Int -> acc aenv' a -> Int-    hashA salt = hashWithSalt salt . hashAcc--    hashE :: Int -> PreOpenExp acc env' aenv' e -> Int-    hashE salt = hashWithSalt salt . hashPreOpenExp hashAcc--    hashF :: Int -> PreOpenFun acc env' aenv' f -> Int-    hashF salt = hashWithSalt salt . hashPreOpenFun hashAcc--  in case pacc of-    Alet bnd body               -> hash "Alet"          `hashA` bnd `hashA` body-    Avar v                      -> hash "Avar"          `hashWithSalt` hashIdx v-    Atuple t                    -> hash "Atuple"        `hashWithSalt` hashAtuple hashAcc t-    Aprj ix a                   -> hash "Aprj"          `hashWithSalt` hashTupleIdx ix    `hashA` a-    Apply f a                   -> hash "Apply"         `hashWithSalt` hashAfun hashAcc f `hashA` a-    Aforeign _ f a              -> hash "Aforeign"      `hashWithSalt` hashAfun hashAcc f `hashA` a-    Use a                       -> hash "Use"           `hashWithSalt` hashArrays (arrays (undefined::arrs)) a-    Awhile p f a                -> hash "Awhile"        `hashWithSalt` hashAfun hashAcc f `hashWithSalt` hashAfun hashAcc p `hashA` a-    Unit e                      -> hash "Unit"          `hashE` e-    Generate e f                -> hash "Generate"      `hashE` e  `hashF` f-    Acond e a1 a2               -> hash "Acond"         `hashE` e  `hashA` a1 `hashA` a2-    Reshape sh a                -> hash "Reshape"       `hashE` sh `hashA` a-    Transform sh f1 f2 a        -> hash "Transform"     `hashE` sh `hashF` f1 `hashF` f2 `hashA` a-    Replicate spec ix a         -> hash "Replicate"     `hashE` ix `hashA` a  `hashWithSalt` show spec-    Slice spec a ix             -> hash "Slice"         `hashE` ix `hashA` a  `hashWithSalt` show spec-    Map f a                     -> hash "Map"           `hashF` f  `hashA` a-    ZipWith f a1 a2             -> hash "ZipWith"       `hashF` f  `hashA` a1 `hashA` a2-    Fold f e a                  -> hash "Fold"          `hashF` f  `hashE` e  `hashA` a-    Fold1 f a                   -> hash "Fold1"         `hashF` f  `hashA` a-    FoldSeg f e a s             -> hash "FoldSeg"       `hashF` f  `hashE` e  `hashA` a  `hashA` s-    Fold1Seg f a s              -> hash "Fold1Seg"      `hashF` f  `hashA` a  `hashA` s-    Scanl f e a                 -> hash "Scanl"         `hashF` f  `hashE` e  `hashA` a-    Scanl' f e a                -> hash "Scanl'"        `hashF` f  `hashE` e  `hashA` a-    Scanl1 f a                  -> hash "Scanl1"        `hashF` f  `hashA` a-    Scanr f e a                 -> hash "Scanr"         `hashF` f  `hashE` e  `hashA` a-    Scanr' f e a                -> hash "Scanr'"        `hashF` f  `hashE` e  `hashA` a-    Scanr1 f a                  -> hash "Scanr1"        `hashF` f  `hashA` a-    Backpermute sh f a          -> hash "Backpermute"   `hashF` f  `hashE` sh `hashA` a-    Permute f1 a1 f2 a2         -> hash "Permute"       `hashF` f1 `hashA` a1 `hashF` f2 `hashA` a2-    Stencil f b a               -> hash "Stencil"       `hashF` f  `hashA` a             `hashWithSalt` hashBoundary a  b-    Stencil2 f b1 a1 b2 a2      -> hash "Stencil2"      `hashF` f  `hashA` a1 `hashA` a2 `hashWithSalt` hashBoundary a1 b1 `hashWithSalt` hashBoundary a2 b2---hashArrays :: ArraysR a -> a -> Int-hashArrays ArraysRunit         ()       = hash ()-hashArrays (ArraysRpair r1 r2) (a1, a2) = hash ( hashArrays r1 a1, hashArrays r2 a2)-hashArrays ArraysRarray        ad       = unsafePerformIO $! hashStableName `fmap` makeStableName ad--hashAtuple :: HashAcc acc -> Tuple.Atuple (acc aenv) a -> Int-hashAtuple _ NilAtup            = hash "NilAtup"-hashAtuple h (SnocAtup t a)     = hash "SnocAtup"       `hashWithSalt` hashAtuple h t `hashWithSalt` h a--hashAfun :: HashAcc acc -> PreOpenAfun acc aenv f -> Int-hashAfun h (Abody b)            = hash "Abody"          `hashWithSalt` h b-hashAfun h (Alam f)             = hash "Alam"           `hashWithSalt` hashAfun h f--hashBoundary :: forall acc aenv sh e. Elt e => acc aenv (Array sh e) -> Boundary (EltRepr e) -> Int-hashBoundary _ Wrap             = hash "Wrap"-hashBoundary _ Clamp            = hash "Clamp"-hashBoundary _ Mirror           = hash "Mirror"-hashBoundary _ (Constant c)     = hash "Constant"       `hashWithSalt` show (toElt c :: e)----- Scalar expressions--- --------------------hashOpenExp :: OpenExp env aenv exp -> Int-hashOpenExp = hashPreOpenExp hashOpenAcc--hashPreOpenExp :: forall acc env aenv exp. HashAcc acc -> PreOpenExp acc env aenv exp -> Int-hashPreOpenExp hashAcc exp =-  let-    hashA :: Int -> acc aenv' a -> Int-    hashA salt = hashWithSalt salt . hashAcc--    hashE :: Int -> PreOpenExp acc env' aenv' e -> Int-    hashE salt = hashWithSalt salt . hashPreOpenExp hashAcc--  in case exp of-    Let bnd body                -> hash "Let"           `hashE` bnd `hashE` body-    Var ix                      -> hash "Var"           `hashWithSalt` hashIdx ix-    Const c                     -> hash "Const"         `hashWithSalt` show (toElt c :: exp)-    Tuple t                     -> hash "Tuple"         `hashWithSalt` hashTuple hashAcc t-    Prj i e                     -> hash "Prj"           `hashWithSalt` hashTupleIdx i `hashE` e-    IndexAny                    -> hash "IndexAny"-    IndexNil                    -> hash "IndexNil"-    IndexCons sl a              -> hash "IndexCons"     `hashE` sl `hashE` a-    IndexHead sl                -> hash "IndexHead"     `hashE` sl-    IndexTail sl                -> hash "IndexTail"     `hashE` sl-    IndexSlice spec ix sh       -> hash "IndexSlice"    `hashE` ix `hashE` sh `hashWithSalt` show spec-    IndexFull  spec ix sl       -> hash "IndexFull"     `hashE` ix `hashE` sl `hashWithSalt` show spec-    ToIndex sh i                -> hash "ToIndex"       `hashE` sh `hashE` i-    FromIndex sh i              -> hash "FromIndex"     `hashE` sh `hashE` i-    Cond c t e                  -> hash "Cond"          `hashE` c  `hashE` t  `hashE` e-    While p f x                 -> hash "While"         `hashWithSalt` hashPreOpenFun hashAcc p  `hashWithSalt` hashPreOpenFun hashAcc f  `hashE` x-    PrimApp f x                 -> hash "PrimApp"       `hashWithSalt` hashPrimFun f `hashE` fromMaybe x (commutes hashAcc f x)-    PrimConst c                 -> hash "PrimConst"     `hashWithSalt` hashPrimConst c-    Index a ix                  -> hash "Index"         `hashA` a  `hashE` ix-    LinearIndex a ix            -> hash "LinearIndex"   `hashA` a  `hashE` ix-    Shape a                     -> hash "Shape"         `hashA` a-    ShapeSize sh                -> hash "ShapeSize"     `hashE` sh-    Intersect sa sb             -> hash "Intersect"     `hashE` sa `hashE` sb-    Foreign _ f e               -> hash "Foreign"       `hashWithSalt` hashPreOpenFun hashAcc f `hashE` e---hashPreOpenFun :: HashAcc acc -> PreOpenFun acc env aenv f -> Int-hashPreOpenFun h (Body e)       = hash "Body"           `hashWithSalt` hashPreOpenExp h e-hashPreOpenFun h (Lam f)        = hash "Lam"            `hashWithSalt` hashPreOpenFun h f--hashTuple :: HashAcc acc -> Tuple.Tuple (PreOpenExp acc env aenv) e -> Int-hashTuple _ NilTup              = hash "NilTup"-hashTuple h (SnocTup t e)       = hash "SnocTup"        `hashWithSalt` hashTuple h t `hashWithSalt` hashPreOpenExp h e---hashPrimConst :: PrimConst c -> Int-hashPrimConst (PrimMinBound _)  = hash "PrimMinBound"-hashPrimConst (PrimMaxBound _)  = hash "PrimMaxBound"-hashPrimConst (PrimPi _)        = hash "PrimPi"--hashPrimFun :: PrimFun f -> Int-hashPrimFun (PrimAdd _)                 = hash "PrimAdd"-hashPrimFun (PrimSub _)                 = hash "PrimSub"-hashPrimFun (PrimMul _)                 = hash "PrimMul"-hashPrimFun (PrimNeg _)                 = hash "PrimNeg"-hashPrimFun (PrimAbs _)                 = hash "PrimAbs"-hashPrimFun (PrimSig _)                 = hash "PrimSig"-hashPrimFun (PrimQuot _)                = hash "PrimQuot"-hashPrimFun (PrimRem _)                 = hash "PrimRem"-hashPrimFun (PrimIDiv _)                = hash "PrimIDiv"-hashPrimFun (PrimMod _)                 = hash "PrimMod"-hashPrimFun (PrimBAnd _)                = hash "PrimBAnd"-hashPrimFun (PrimBOr _)                 = hash "PrimBOr"-hashPrimFun (PrimBXor _)                = hash "PrimBXor"-hashPrimFun (PrimBNot _)                = hash "PrimBNot"-hashPrimFun (PrimBShiftL _)             = hash "PrimBShiftL"-hashPrimFun (PrimBShiftR _)             = hash "PrimBShiftR"-hashPrimFun (PrimBRotateL _)            = hash "PrimBRotateL"-hashPrimFun (PrimBRotateR _)            = hash "PrimBRotateR"-hashPrimFun (PrimFDiv _)                = hash "PrimFDiv"-hashPrimFun (PrimRecip _)               = hash "PrimRecip"-hashPrimFun (PrimSin _)                 = hash "PrimSin"-hashPrimFun (PrimCos _)                 = hash "PrimCos"-hashPrimFun (PrimTan _)                 = hash "PrimTan"-hashPrimFun (PrimAsin _)                = hash "PrimAsin"-hashPrimFun (PrimAcos _)                = hash "PrimAcos"-hashPrimFun (PrimAtan _)                = hash "PrimAtan"-hashPrimFun (PrimAsinh _)               = hash "PrimAsinh"-hashPrimFun (PrimAcosh _)               = hash "PrimAcosh"-hashPrimFun (PrimAtanh _)               = hash "PrimAtanh"-hashPrimFun (PrimExpFloating _)         = hash "PrimExpFloating"-hashPrimFun (PrimSqrt _)                = hash "PrimSqrt"-hashPrimFun (PrimLog _)                 = hash "PrimLog"-hashPrimFun (PrimFPow _)                = hash "PrimFPow"-hashPrimFun (PrimLogBase _)             = hash "PrimLogBase"-hashPrimFun (PrimAtan2 _)               = hash "PrimAtan2"-hashPrimFun (PrimTruncate _ _)          = hash "PrimTruncate"-hashPrimFun (PrimRound _ _)             = hash "PrimRound"-hashPrimFun (PrimFloor _ _)             = hash "PrimFloor"-hashPrimFun (PrimCeiling _ _)           = hash "PrimCeiling"-hashPrimFun (PrimLt _)                  = hash "PrimLt"-hashPrimFun (PrimGt _)                  = hash "PrimGt"-hashPrimFun (PrimLtEq _)                = hash "PrimLtEq"-hashPrimFun (PrimGtEq _)                = hash "PrimGtEq"-hashPrimFun (PrimEq _)                  = hash "PrimEq"-hashPrimFun (PrimNEq _)                 = hash "PrimNEq"-hashPrimFun (PrimMax _)                 = hash "PrimMax"-hashPrimFun (PrimMin _)                 = hash "PrimMin"-hashPrimFun (PrimFromIntegral _ _)      = hash "PrimFromIntegral"-hashPrimFun PrimLAnd                    = hash "PrimLAnd"-hashPrimFun PrimLOr                     = hash "PrimLOr"-hashPrimFun PrimLNot                    = hash "PrimLNot"-hashPrimFun PrimOrd                     = hash "PrimOrd"-hashPrimFun PrimChr                     = hash "PrimChr"-hashPrimFun PrimBoolToInt               = hash "PrimBoolToInt"+-- Copyright   : [2012..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Analysis.Match (++  -- matching expressions+  MatchAcc,+  (:~:)(..),+  matchOpenAcc,  matchPreOpenAcc,+  matchOpenAfun, matchPreOpenAfun,+  matchOpenExp,  matchPreOpenExp,+  matchOpenFun,  matchPreOpenFun,+  matchPrimFun,  matchPrimFun',++  -- auxiliary+  matchIdx, matchTupleType,+  matchIntegralType, matchFloatingType, matchNumType, matchScalarType,++  -- hashing expressions+  HashAcc,+  hashPreOpenAcc, hashOpenAcc,+  hashPreOpenExp, hashOpenExp,+  hashPreOpenFun,++) where++-- standard library+import Prelude                                          hiding ( exp )+import Data.Maybe+import Data.Typeable+import Data.Hashable+import System.Mem.StableName+import System.IO.Unsafe                                 ( unsafePerformIO )++-- friends+import Data.Array.Accelerate.AST+import Data.Array.Accelerate.Type+import Data.Array.Accelerate.Array.Sugar+import Data.Array.Accelerate.Array.Representation       ( SliceIndex(..) )+import Data.Array.Accelerate.Product+++-- The type of matching array computations+--+type MatchAcc acc = forall aenv s t. acc aenv s -> acc aenv t -> Maybe (s :~: t)+++-- Compute the congruence of two array computations. The nodes are congruent if+-- they have the same operator and their operands are congruent.+--+{-# INLINEABLE matchOpenAcc #-}+matchOpenAcc+    :: OpenAcc aenv s+    -> OpenAcc aenv t+    -> Maybe (s :~: t)+matchOpenAcc (OpenAcc acc1) (OpenAcc acc2) =+  matchPreOpenAcc matchOpenAcc hashOpenAcc acc1 acc2+++matchPreOpenAcc+    :: forall acc aenv s t.+       MatchAcc acc+    -> HashAcc  acc+    -> PreOpenAcc acc aenv s+    -> PreOpenAcc acc aenv t+    -> Maybe (s :~: t)+matchPreOpenAcc matchAcc hashAcc = match+  where+    matchFun :: PreOpenFun acc env' aenv' u -> PreOpenFun acc env' aenv' v -> Maybe (u :~: v)+    matchFun = matchPreOpenFun matchAcc hashAcc++    matchExp :: PreOpenExp acc env' aenv' u -> PreOpenExp acc env' aenv' v -> Maybe (u :~: v)+    matchExp = matchPreOpenExp matchAcc hashAcc++    match :: PreOpenAcc acc aenv s -> PreOpenAcc acc aenv t -> Maybe (s :~: t)+    match (Alet x1 a1) (Alet x2 a2)+      | Just Refl <- matchAcc x1 x2+      , Just Refl <- matchAcc a1 a2+      = Just Refl++    match (Avar v1) (Avar v2)+      = matchIdx v1 v2++    match (Atuple t1) (Atuple t2)+      | Just Refl <- matchAtuple matchAcc t1 t2+      = gcast Refl  -- surface/representation type++    match (Aprj ix1 t1) (Aprj ix2 t2)+      | Just Refl <- matchAcc t1 t2+      , Just Refl <- matchTupleIdx ix1 ix2+      = Just Refl++    match (Apply f1 a1) (Apply f2 a2)+      | Just Refl <- matchPreOpenAfun matchAcc f1 f2+      , Just Refl <- matchAcc                  a1 a2+      = Just Refl++    match (Aforeign ff1 _ a1) (Aforeign ff2 _ a2)+      | Just Refl <- matchAcc a1 a2+      , unsafePerformIO $ do+          sn1 <- makeStableName ff1+          sn2 <- makeStableName ff2+          return $! hashStableName sn1 == hashStableName sn2+      = gcast Refl++    match (Acond p1 t1 e1) (Acond p2 t2 e2)+      | Just Refl <- matchExp p1 p2+      , Just Refl <- matchAcc t1 t2+      , Just Refl <- matchAcc e1 e2+      = Just Refl++    match (Awhile p1 f1 a1) (Awhile p2 f2 a2)+      | Just Refl <- matchAcc a1 a2+      , Just Refl <- matchPreOpenAfun matchAcc p1 p2+      , Just Refl <- matchPreOpenAfun matchAcc f1 f2+      = Just Refl++    match (Use a1) (Use a2)+      | Just Refl <- matchArrays (arrays (undefined::s)) (arrays (undefined::t)) a1 a2+      = gcast Refl++    match (Unit e1) (Unit e2)+      | Just Refl <- matchExp e1 e2+      = Just Refl++    match (Reshape sh1 a1) (Reshape sh2 a2)+      | Just Refl <- matchExp sh1 sh2+      , Just Refl <- matchAcc a1  a2+      = Just Refl++    match (Generate sh1 f1) (Generate sh2 f2)+      | Just Refl <- matchExp sh1 sh2+      , Just Refl <- matchFun f1  f2+      = Just Refl++    match (Transform sh1 ix1 f1 a1) (Transform sh2 ix2 f2 a2)+      | Just Refl <- matchExp sh1 sh2+      , Just Refl <- matchFun ix1 ix2+      , Just Refl <- matchFun f1  f2+      , Just Refl <- matchAcc a1  a2+      = Just Refl++    match (Replicate _ ix1 a1) (Replicate _ ix2 a2)+      | Just Refl <- matchExp ix1 ix2+      , Just Refl <- matchAcc a1  a2+      = gcast Refl  -- slice specification ??++    match (Slice _ a1 ix1) (Slice _ a2 ix2)+      | Just Refl <- matchAcc a1  a2+      , Just Refl <- matchExp ix1 ix2+      = gcast Refl  -- slice specification ??++    match (Map f1 a1) (Map f2 a2)+      | Just Refl <- matchFun f1 f2+      , Just Refl <- matchAcc a1 a2+      = Just Refl++    match (ZipWith f1 a1 b1) (ZipWith f2 a2 b2)+      | Just Refl <- matchFun f1 f2+      , Just Refl <- matchAcc a1 a2+      , Just Refl <- matchAcc b1 b2+      = Just Refl++    match (Fold f1 z1 a1) (Fold f2 z2 a2)+      | Just Refl <- matchFun f1 f2+      , Just Refl <- matchExp z1 z2+      , Just Refl <- matchAcc a1 a2+      = Just Refl++    match (Fold1 f1 a1) (Fold1 f2 a2)+      | Just Refl <- matchFun f1 f2+      , Just Refl <- matchAcc a1 a2+      = Just Refl++    match (FoldSeg f1 z1 a1 s1) (FoldSeg f2 z2 a2 s2)+      | Just Refl <- matchFun f1 f2+      , Just Refl <- matchExp z1 z2+      , Just Refl <- matchAcc a1 a2+      , Just Refl <- matchAcc s1 s2+      = Just Refl++    match (Fold1Seg f1 a1 s1) (Fold1Seg f2 a2 s2)+      | Just Refl <- matchFun f1 f2+      , Just Refl <- matchAcc a1 a2+      , Just Refl <- matchAcc s1 s2+      = Just Refl++    match (Scanl f1 z1 a1) (Scanl f2 z2 a2)+      | Just Refl <- matchFun f1 f2+      , Just Refl <- matchExp z1 z2+      , Just Refl <- matchAcc a1 a2+      = Just Refl++    match (Scanl' f1 z1 a1) (Scanl' f2 z2 a2)+      | Just Refl <- matchFun f1 f2+      , Just Refl <- matchExp z1 z2+      , Just Refl <- matchAcc a1 a2+      = Just Refl++    match (Scanl1 f1 a1) (Scanl1 f2 a2)+      | Just Refl <- matchFun f1 f2+      , Just Refl <- matchAcc a1 a2+      = Just Refl++    match (Scanr f1 z1 a1) (Scanr f2 z2 a2)+      | Just Refl <- matchFun f1 f2+      , Just Refl <- matchExp z1 z2+      , Just Refl <- matchAcc a1 a2+      = Just Refl++    match (Scanr' f1 z1 a1) (Scanr' f2 z2 a2)+      | Just Refl <- matchFun f1 f2+      , Just Refl <- matchExp z1 z2+      , Just Refl <- matchAcc a1 a2+      = Just Refl++    match (Scanr1 f1 a1) (Scanr1 f2 a2)+      | Just Refl <- matchFun f1 f2+      , Just Refl <- matchAcc a1 a2+      = Just Refl++    match (Permute f1 d1 p1 a1) (Permute f2 d2 p2 a2)+      | Just Refl <- matchFun f1 f2+      , Just Refl <- matchAcc d1 d2+      , Just Refl <- matchFun p1 p2+      , Just Refl <- matchAcc a1 a2+      = Just Refl++    match (Backpermute sh1 ix1 a1) (Backpermute sh2 ix2 a2)+      | Just Refl <- matchExp sh1 sh2+      , Just Refl <- matchFun ix1 ix2+      , Just Refl <- matchAcc a1  a2+      = Just Refl++    match (Stencil f1 b1 (a1 :: acc aenv (Array sh1 e1)))+          (Stencil f2 b2 (a2 :: acc aenv (Array sh2 e2)))+      | Just Refl <- matchFun f1 f2+      , Just Refl <- matchAcc a1 a2+      , matchBoundary (eltType (undefined::e1)) b1 b2+      = Just Refl++    match (Stencil2 f1 b1  (a1  :: acc aenv (Array sh1  e1 )) b2  (a2 :: acc aenv (Array sh2  e2 )))+          (Stencil2 f2 b1' (a1' :: acc aenv (Array sh1' e1')) b2' (a2':: acc aenv (Array sh2' e2')))+      | Just Refl <- matchFun f1 f2+      , Just Refl <- matchAcc a1 a1'+      , Just Refl <- matchAcc a2 a2'+      , matchBoundary (eltType (undefined::e1)) b1 b1'+      , matchBoundary (eltType (undefined::e2)) b2 b2'+      = Just Refl++    -- match (Collect s1) (Collect s2)+    --   = matchSeq matchAcc hashAcc s1 s2++    match _ _+      = Nothing+++-- Array tuples+--+matchAtuple+    :: MatchAcc acc+    -> Atuple (acc aenv) s+    -> Atuple (acc aenv) t+    -> Maybe (s :~: t)+matchAtuple matchAcc (SnocAtup t1 a1) (SnocAtup t2 a2)+  | Just Refl <- matchAtuple matchAcc t1 t2+  , Just Refl <- matchAcc             a1 a2+  = Just Refl++matchAtuple _ NilAtup NilAtup = Just Refl+matchAtuple _ _       _       = Nothing+++-- Array functions+--+matchOpenAfun+    :: OpenAfun aenv s+    -> OpenAfun aenv t+    -> Maybe (s :~: t)+matchOpenAfun = matchPreOpenAfun matchOpenAcc++matchPreOpenAfun+    :: MatchAcc acc+    -> PreOpenAfun acc aenv s+    -> PreOpenAfun acc aenv t+    -> Maybe (s :~: t)+matchPreOpenAfun m (Alam s) (Alam t)+  | Just Refl <- matchEnvTop        s t+  , Just Refl <- matchPreOpenAfun m s t+  = Just Refl+  where+    matchEnvTop :: (Arrays s, Arrays t)+                => PreOpenAfun acc (aenv, s) f -> PreOpenAfun acc (aenv, t) g -> Maybe (s :~: t)+    matchEnvTop _ _ = gcast Refl  -- ???++matchPreOpenAfun m (Abody s) (Abody t) = m s t+matchPreOpenAfun _ _         _         = Nothing+++-- Match stencil boundaries+--+matchBoundary :: TupleType e -> Boundary e -> Boundary e -> Bool+matchBoundary ty (Constant s) (Constant t) = matchConst ty s t+matchBoundary _  Wrap         Wrap         = True+matchBoundary _  Clamp        Clamp        = True+matchBoundary _  Mirror       Mirror       = True+matchBoundary _  _            _            = False+++{--+-- Match sequences+--+matchSeq+    :: forall acc aenv senv s t.+       MatchAcc acc+    -> HashAcc acc+    -> PreOpenSeq acc aenv senv s+    -> PreOpenSeq acc aenv senv t+    -> Maybe (s :~: t)+matchSeq m h = match+  where+    matchFun :: PreOpenFun acc env' aenv' u -> PreOpenFun acc env' aenv' v -> Maybe (u :~: v)+    matchFun = matchPreOpenFun m h++    matchExp :: PreOpenExp acc env' aenv' u -> PreOpenExp acc env' aenv' v -> Maybe (u :~: v)+    matchExp = matchPreOpenExp m h++    match :: PreOpenSeq acc aenv senv' u -> PreOpenSeq acc aenv senv' v -> Maybe (u :~: v)+    match (Producer p1 s1)   (Producer p2 s2)+      | Just Refl <- matchP p1 p2+      , Just Refl <- match s1 s2+      = Just Refl+    match (Consumer c1)   (Consumer c2)+      | Just Refl <- matchC c1 c2+      = Just Refl+    match (Reify ix1) (Reify ix2)+      | Just Refl <- matchIdx ix1 ix2+      = Just Refl+    match _ _+      = Nothing++    matchP :: Producer acc aenv senv' u -> Producer acc aenv senv' v -> Maybe (u :~: v)+    matchP (StreamIn arrs1) (StreamIn arrs2)+      | unsafePerformIO $ do+          sn1 <- makeStableName arrs1+          sn2 <- makeStableName arrs2+          return $! hashStableName sn1 == hashStableName sn2+      = gcast Refl+    matchP (ToSeq _ (_::proxy1 slix1) a1) (ToSeq _ (_::proxy2 slix2) a2)+      | Just Refl <- gcast Refl :: Maybe (slix1 :~: slix2) -- Divisions are singleton.+      , Just Refl <- m a1 a2+      = gcast Refl+    matchP (MapSeq f1 x1) (MapSeq f2 x2)+      | Just Refl <- matchPreOpenAfun m f1 f2+      , Just Refl <- matchIdx x1 x2+      = Just Refl+    matchP (ZipWithSeq f1 x1 y1) (ZipWithSeq f2 x2 y2)+      | Just Refl <- matchPreOpenAfun m f1 f2+      , Just Refl <- matchIdx x1 x2+      , Just Refl <- matchIdx y1 y2+      = Just Refl+    matchP (ScanSeq f1 e1 x1) (ScanSeq f2 e2 x2)+      | Just Refl <- matchFun f1 f2+      , Just Refl <- matchIdx x1 x2+      , Just Refl <- matchExp e1 e2+      = Just Refl+    matchP _ _+      = Nothing++    matchC :: Consumer acc aenv senv' u -> Consumer acc aenv senv' v -> Maybe (u :~: v)+    matchC (FoldSeq f1 e1 x1) (FoldSeq f2 e2 x2)+      | Just Refl <- matchIdx x1 x2+      , Just Refl <- matchFun f1 f2+      , Just Refl <- matchExp e1 e2+      = Just Refl+    matchC (FoldSeqFlatten f1 acc1 x1) (FoldSeqFlatten f2 acc2 x2)+      | Just Refl <- matchIdx x1 x2+      , Just Refl <- matchPreOpenAfun m f1 f2+      , Just Refl <- m acc1 acc2+      = Just Refl+    matchC (Stuple s1) (Stuple s2)+      | Just Refl <- matchAtuple matchC s1 s2+      = gcast Refl+    matchC _ _+      = Nothing+--}++-- Match arrays+--+-- As a convenience, we are just comparing the stable names, but we could also+-- walk the structure comparing the underlying ptrsOfArrayData.+--+matchArrays :: ArraysR s -> ArraysR t -> s -> t -> Maybe (s :~: t)+matchArrays ArraysRunit ArraysRunit () ()+  = Just Refl++matchArrays (ArraysRpair a1 b1) (ArraysRpair a2 b2) (arr1,brr1) (arr2,brr2)+  | Just Refl <- matchArrays a1 a2 arr1 arr2+  , Just Refl <- matchArrays b1 b2 brr1 brr2+  = Just Refl++matchArrays ArraysRarray ArraysRarray (Array _ ad1) (Array _ ad2)+  | unsafePerformIO $ do+      sn1 <- makeStableName ad1+      sn2 <- makeStableName ad2+      return $! hashStableName sn1 == hashStableName sn2+  = gcast Refl++matchArrays _ _ _ _+  = Nothing+++-- Compute the congruence of two scalar expressions. Two nodes are congruent if+-- either:+--+--  1. The nodes label constants and the contents are equal+--  2. They have the same operator and their operands are congruent+--+-- The below attempts to use real typed equality, but occasionally still needs+-- to use a cast, particularly when we can only match the representation types.+--+matchOpenExp+    :: OpenExp env aenv s+    -> OpenExp env aenv t+    -> Maybe (s :~: t)+matchOpenExp = matchPreOpenExp matchOpenAcc hashOpenAcc++matchPreOpenExp+    :: forall acc env aenv s t.+       MatchAcc acc+    -> HashAcc  acc+    -> PreOpenExp acc env aenv s+    -> PreOpenExp acc env aenv t+    -> Maybe (s :~: t)+matchPreOpenExp matchAcc hashAcc = match+  where+    match :: forall env' aenv' s' t'.+             PreOpenExp acc env' aenv' s'+          -> PreOpenExp acc env' aenv' t'+          -> Maybe (s' :~: t')+    match (Let x1 e1) (Let x2 e2)+      | Just Refl <- match x1 x2+      , Just Refl <- match e1 e2+      = Just Refl++    match (Var v1) (Var v2)+      = matchIdx v1 v2++    match (Foreign ff1 _ e1) (Foreign ff2 _ e2)+      | Just Refl <- match e1 e2+      , unsafePerformIO $ do+          sn1 <- makeStableName ff1+          sn2 <- makeStableName ff2+          return $! hashStableName sn1 == hashStableName sn2+      = gcast Refl++    match (Const c1) (Const c2)+      | Just Refl <- matchTupleType (eltType (undefined::s')) (eltType (undefined::t'))+      , matchConst (eltType (undefined::s')) c1 c2+      = gcast Refl  -- surface/representation type++    match (Tuple t1) (Tuple t2)+      | Just Refl <- matchTuple matchAcc hashAcc t1 t2+      = gcast Refl  -- surface/representation type++    match (Prj ix1 t1) (Prj ix2 t2)+      | Just Refl <- match         t1  t2+      , Just Refl <- matchTupleIdx ix1 ix2+      = Just Refl++    match IndexAny IndexAny+      = gcast Refl  -- ???++    match IndexNil IndexNil+      = Just Refl++    match (IndexCons sl1 a1) (IndexCons sl2 a2)+      | Just Refl <- match sl1 sl2+      , Just Refl <- match a1 a2+      = Just Refl++    match (IndexHead sl1) (IndexHead sl2)+      | Just Refl <- match sl1 sl2+      = Just Refl++    match (IndexTail sl1) (IndexTail sl2)+      | Just Refl <- match sl1 sl2+      = Just Refl++    match (IndexSlice sliceIndex1 ix1 sh1) (IndexSlice sliceIndex2 ix2 sh2)+      | Just Refl <- match ix1 ix2+      , Just Refl <- match sh1 sh2+      , Just Refl <- matchSliceRestrict sliceIndex1 sliceIndex2+      = gcast Refl  -- SliceIndex representation/surface type++    match (IndexFull sliceIndex1 ix1 sl1) (IndexFull sliceIndex2 ix2 sl2)+      | Just Refl <- match ix1 ix2+      , Just Refl <- match sl1 sl2+      , Just Refl <- matchSliceExtend sliceIndex1 sliceIndex2+      = gcast Refl  -- SliceIndex representation/surface type++    match (ToIndex sh1 i1) (ToIndex sh2 i2)+      | Just Refl <- match sh1 sh2+      , Just Refl <- match i1  i2+      = Just Refl++    match (FromIndex sh1 i1) (FromIndex sh2 i2)+      | Just Refl <- match i1  i2+      , Just Refl <- match sh1 sh2+      = Just Refl++    match (Cond p1 t1 e1) (Cond p2 t2 e2)+      | Just Refl <- match p1 p2+      , Just Refl <- match t1 t2+      , Just Refl <- match e1 e2+      = Just Refl++    match (While p1 f1 x1) (While p2 f2 x2)+      | Just Refl <- match x1 x2+      , Just Refl <- matchPreOpenFun matchAcc hashAcc p1 p2+      , Just Refl <- matchPreOpenFun matchAcc hashAcc f1 f2+      = Just Refl++    match (PrimConst c1) (PrimConst c2)+      = matchPrimConst c1 c2++    match (PrimApp f1 x1) (PrimApp f2 x2)+      | Just x1'  <- commutes hashAcc f1 x1+      , Just x2'  <- commutes hashAcc f2 x2+      , Just Refl <- match        x1' x2'+      , Just Refl <- matchPrimFun f1  f2+      = Just Refl++      | Just Refl <- match x1 x2+      , Just Refl <- matchPrimFun f1 f2+      = Just Refl++    match (Index a1 x1) (Index a2 x2)+      | Just Refl <- matchAcc a1 a2     -- should only be array indices+      , Just Refl <- match    x1 x2+      = Just Refl++    match (LinearIndex a1 x1) (LinearIndex a2 x2)+      | Just Refl <- matchAcc a1 a2+      , Just Refl <- match    x1 x2+      = Just Refl++    match (Shape a1) (Shape a2)+      | Just Refl <- matchAcc a1 a2     -- should only be array indices+      = Just Refl++    match (ShapeSize sh1) (ShapeSize sh2)+      | Just Refl <- match sh1 sh2+      = Just Refl++    match (Intersect sa1 sb1) (Intersect sa2 sb2)+      | Just Refl <- match sa1 sa2+      , Just Refl <- match sb1 sb2+      = Just Refl++    match (Union sa1 sb1) (Union sa2 sb2)+      | Just Refl <- match sa1 sa2+      , Just Refl <- match sb1 sb2+      = Just Refl++    match _ _+      = Nothing+++-- Match scalar functions+--+matchOpenFun+    :: OpenFun env aenv s+    -> OpenFun env aenv t+    -> Maybe (s :~: t)+matchOpenFun = matchPreOpenFun matchOpenAcc hashOpenAcc++matchPreOpenFun+    :: MatchAcc acc+    -> HashAcc  acc+    -> PreOpenFun acc env aenv s+    -> PreOpenFun acc env aenv t+    -> Maybe (s :~: t)+matchPreOpenFun m h (Lam s) (Lam t)+  | Just Refl <- matchEnvTop         s t+  , Just Refl <- matchPreOpenFun m h s t+  = Just Refl+  where+    matchEnvTop :: (Elt s, Elt t) => PreOpenFun acc (env, s) aenv f -> PreOpenFun acc (env, t) aenv g -> Maybe (s :~: t)+    matchEnvTop _ _ = gcast Refl  -- ???++matchPreOpenFun m h (Body s) (Body t) = matchPreOpenExp m h s t+matchPreOpenFun _ _ _        _        = Nothing++-- Matching constants+--+matchConst :: TupleType a -> a -> a -> Bool+matchConst UnitTuple         ()      ()      = True+matchConst (SingleTuple ty)  a       b       = evalEq ty (a,b)+matchConst (PairTuple ta tb) (a1,b1) (a2,b2) = matchConst ta a1 a2 && matchConst tb b1 b2++evalEq :: ScalarType a -> (a, a) -> Bool+evalEq (NumScalarType (IntegralNumType ty)) | IntegralDict <- integralDict ty = uncurry (==)+evalEq (NumScalarType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = uncurry (==)+evalEq (NonNumScalarType ty)                | NonNumDict   <- nonNumDict ty   = uncurry (==)+++-- Environment projection indices+--+matchIdx :: Idx env s -> Idx env t -> Maybe (s :~: t)+matchIdx ZeroIdx     ZeroIdx     = Just Refl+matchIdx (SuccIdx u) (SuccIdx v) = matchIdx u v+matchIdx _           _           = Nothing+++-- Tuple projection indices. Given the same tuple expression structure (tup),+-- check that the indices project identical elements.+--+matchTupleIdx :: TupleIdx tup s -> TupleIdx tup t -> Maybe (s :~: t)+matchTupleIdx ZeroTupIdx     ZeroTupIdx     = Just Refl+matchTupleIdx (SuccTupIdx s) (SuccTupIdx t) = matchTupleIdx s t+matchTupleIdx _              _              = Nothing++-- Tuples+--+matchTuple+    :: MatchAcc acc+    -> HashAcc  acc+    -> Tuple (PreOpenExp acc env aenv) s+    -> Tuple (PreOpenExp acc env aenv) t+    -> Maybe (s :~: t)+matchTuple _ _ NilTup          NilTup           = Just Refl+matchTuple m h (SnocTup t1 e1) (SnocTup t2 e2)+  | Just Refl <- matchTuple      m h t1 t2+  , Just Refl <- matchPreOpenExp m h e1 e2+  = Just Refl++matchTuple _ _ _               _                = Nothing+++-- Slice specifications+--+matchSliceRestrict+    :: SliceIndex slix s co  sh+    -> SliceIndex slix t co' sh+    -> Maybe (s :~: t)+matchSliceRestrict SliceNil SliceNil+  = Just Refl++matchSliceRestrict (SliceAll   sl1) (SliceAll   sl2)+  | Just Refl <- matchSliceRestrict sl1 sl2+  = Just Refl++matchSliceRestrict (SliceFixed sl1) (SliceFixed sl2)+  | Just Refl <- matchSliceRestrict sl1 sl2+  = Just Refl++matchSliceRestrict _ _+  = Nothing+++matchSliceExtend+    :: SliceIndex slix sl co  s+    -> SliceIndex slix sl co' t+    -> Maybe (s :~: t)+matchSliceExtend SliceNil SliceNil+  = Just Refl++matchSliceExtend (SliceAll   sl1) (SliceAll   sl2)+  | Just Refl <- matchSliceExtend sl1 sl2+  = Just Refl++matchSliceExtend (SliceFixed sl1) (SliceFixed sl2)+  | Just Refl <- matchSliceExtend sl1 sl2+  = Just Refl++matchSliceExtend _ _+  = Nothing+++-- Primitive constants and functions+--+matchPrimConst :: PrimConst s -> PrimConst t -> Maybe (s :~: t)+matchPrimConst (PrimMinBound s) (PrimMinBound t) = matchBoundedType s t+matchPrimConst (PrimMaxBound s) (PrimMaxBound t) = matchBoundedType s t+matchPrimConst (PrimPi s)       (PrimPi t)       = matchFloatingType s t+matchPrimConst _                _                = Nothing+++-- Covariant function matching+--+matchPrimFun :: PrimFun (a -> s) -> PrimFun (a -> t) -> Maybe (s :~: t)+matchPrimFun (PrimAdd _)                (PrimAdd _)                = Just Refl+matchPrimFun (PrimSub _)                (PrimSub _)                = Just Refl+matchPrimFun (PrimMul _)                (PrimMul _)                = Just Refl+matchPrimFun (PrimNeg _)                (PrimNeg _)                = Just Refl+matchPrimFun (PrimAbs _)                (PrimAbs _)                = Just Refl+matchPrimFun (PrimSig _)                (PrimSig _)                = Just Refl+matchPrimFun (PrimQuot _)               (PrimQuot _)               = Just Refl+matchPrimFun (PrimRem _)                (PrimRem _)                = Just Refl+matchPrimFun (PrimQuotRem _)            (PrimQuotRem _)            = Just Refl+matchPrimFun (PrimIDiv _)               (PrimIDiv _)               = Just Refl+matchPrimFun (PrimMod _)                (PrimMod _)                = Just Refl+matchPrimFun (PrimDivMod _)             (PrimDivMod _)             = Just Refl+matchPrimFun (PrimBAnd _)               (PrimBAnd _)               = Just Refl+matchPrimFun (PrimBOr _)                (PrimBOr _)                = Just Refl+matchPrimFun (PrimBXor _)               (PrimBXor _)               = Just Refl+matchPrimFun (PrimBNot _)               (PrimBNot _)               = Just Refl+matchPrimFun (PrimBShiftL _)            (PrimBShiftL _)            = Just Refl+matchPrimFun (PrimBShiftR _)            (PrimBShiftR _)            = Just Refl+matchPrimFun (PrimBRotateL _)           (PrimBRotateL _)           = Just Refl+matchPrimFun (PrimBRotateR _)           (PrimBRotateR _)           = Just Refl+matchPrimFun (PrimPopCount _)           (PrimPopCount _)           = Just Refl+matchPrimFun (PrimCountLeadingZeros _)  (PrimCountLeadingZeros _)  = Just Refl+matchPrimFun (PrimCountTrailingZeros _) (PrimCountTrailingZeros _) = Just Refl+matchPrimFun (PrimFDiv _)               (PrimFDiv _)               = Just Refl+matchPrimFun (PrimRecip _)              (PrimRecip _)              = Just Refl+matchPrimFun (PrimSin _)                (PrimSin _)                = Just Refl+matchPrimFun (PrimCos _)                (PrimCos _)                = Just Refl+matchPrimFun (PrimTan _)                (PrimTan _)                = Just Refl+matchPrimFun (PrimAsin _)               (PrimAsin _)               = Just Refl+matchPrimFun (PrimAcos _)               (PrimAcos _)               = Just Refl+matchPrimFun (PrimAtan _)               (PrimAtan _)               = Just Refl+matchPrimFun (PrimSinh _)               (PrimSinh _)               = Just Refl+matchPrimFun (PrimCosh _)               (PrimCosh _)               = Just Refl+matchPrimFun (PrimTanh _)               (PrimTanh _)               = Just Refl+matchPrimFun (PrimAsinh _)              (PrimAsinh _)              = Just Refl+matchPrimFun (PrimAcosh _)              (PrimAcosh _)              = Just Refl+matchPrimFun (PrimAtanh _)              (PrimAtanh _)              = Just Refl+matchPrimFun (PrimExpFloating _)        (PrimExpFloating _)        = Just Refl+matchPrimFun (PrimSqrt _)               (PrimSqrt _)               = Just Refl+matchPrimFun (PrimLog _)                (PrimLog _)                = Just Refl+matchPrimFun (PrimFPow _)               (PrimFPow _)               = Just Refl+matchPrimFun (PrimLogBase _)            (PrimLogBase _)            = Just Refl+matchPrimFun (PrimAtan2 _)              (PrimAtan2 _)              = Just Refl+matchPrimFun (PrimTruncate _ s)         (PrimTruncate _ t)         = matchIntegralType s t+matchPrimFun (PrimRound _ s)            (PrimRound _ t)            = matchIntegralType s t+matchPrimFun (PrimFloor _ s)            (PrimFloor _ t)            = matchIntegralType s t+matchPrimFun (PrimCeiling _ s)          (PrimCeiling _ t)          = matchIntegralType s t+matchPrimFun (PrimIsNaN _)              (PrimIsNaN _)              = Just Refl+matchPrimFun (PrimLt _)                 (PrimLt _)                 = Just Refl+matchPrimFun (PrimGt _)                 (PrimGt _)                 = Just Refl+matchPrimFun (PrimLtEq _)               (PrimLtEq _)               = Just Refl+matchPrimFun (PrimGtEq _)               (PrimGtEq _)               = Just Refl+matchPrimFun (PrimEq _)                 (PrimEq _)                 = Just Refl+matchPrimFun (PrimNEq _)                (PrimNEq _)                = Just Refl+matchPrimFun (PrimMax _)                (PrimMax _)                = Just Refl+matchPrimFun (PrimMin _)                (PrimMin _)                = Just Refl+matchPrimFun (PrimFromIntegral _ s)     (PrimFromIntegral _ t)     = matchNumType s t+matchPrimFun (PrimToFloating _ s)       (PrimToFloating _ t)       = matchFloatingType s t+matchPrimFun (PrimCoerce _ s)           (PrimCoerce _ t)           = matchScalarType s t+matchPrimFun PrimLAnd                   PrimLAnd                   = Just Refl+matchPrimFun PrimLOr                    PrimLOr                    = Just Refl+matchPrimFun PrimLNot                   PrimLNot                   = Just Refl+matchPrimFun PrimOrd                    PrimOrd                    = Just Refl+matchPrimFun PrimChr                    PrimChr                    = Just Refl+matchPrimFun PrimBoolToInt              PrimBoolToInt              = Just Refl+matchPrimFun _                          _                          = Nothing+++-- Contravariant function matching+--+matchPrimFun' :: PrimFun (s -> a) -> PrimFun (t -> a) -> Maybe (s :~: t)+matchPrimFun' (PrimAdd _)                (PrimAdd _)                = Just Refl+matchPrimFun' (PrimSub _)                (PrimSub _)                = Just Refl+matchPrimFun' (PrimMul _)                (PrimMul _)                = Just Refl+matchPrimFun' (PrimNeg _)                (PrimNeg _)                = Just Refl+matchPrimFun' (PrimAbs _)                (PrimAbs _)                = Just Refl+matchPrimFun' (PrimSig _)                (PrimSig _)                = Just Refl+matchPrimFun' (PrimQuot _)               (PrimQuot _)               = Just Refl+matchPrimFun' (PrimRem _)                (PrimRem _)                = Just Refl+matchPrimFun' (PrimQuotRem _)            (PrimQuotRem _)            = Just Refl+matchPrimFun' (PrimIDiv _)               (PrimIDiv _)               = Just Refl+matchPrimFun' (PrimMod _)                (PrimMod _)                = Just Refl+matchPrimFun' (PrimDivMod _)             (PrimDivMod _)             = Just Refl+matchPrimFun' (PrimBAnd _)               (PrimBAnd _)               = Just Refl+matchPrimFun' (PrimBOr _)                (PrimBOr _)                = Just Refl+matchPrimFun' (PrimBXor _)               (PrimBXor _)               = Just Refl+matchPrimFun' (PrimBNot _)               (PrimBNot _)               = Just Refl+matchPrimFun' (PrimBShiftL _)            (PrimBShiftL _)            = Just Refl+matchPrimFun' (PrimBShiftR _)            (PrimBShiftR _)            = Just Refl+matchPrimFun' (PrimBRotateL _)           (PrimBRotateL _)           = Just Refl+matchPrimFun' (PrimBRotateR _)           (PrimBRotateR _)           = Just Refl+matchPrimFun' (PrimPopCount s)           (PrimPopCount t)           = matchIntegralType s t+matchPrimFun' (PrimCountLeadingZeros s)  (PrimCountLeadingZeros t)  = matchIntegralType s t+matchPrimFun' (PrimCountTrailingZeros s) (PrimCountTrailingZeros t) = matchIntegralType s t+matchPrimFun' (PrimFDiv _)               (PrimFDiv _)               = Just Refl+matchPrimFun' (PrimRecip _)              (PrimRecip _)              = Just Refl+matchPrimFun' (PrimSin _)                (PrimSin _)                = Just Refl+matchPrimFun' (PrimCos _)                (PrimCos _)                = Just Refl+matchPrimFun' (PrimTan _)                (PrimTan _)                = Just Refl+matchPrimFun' (PrimAsin _)               (PrimAsin _)               = Just Refl+matchPrimFun' (PrimAcos _)               (PrimAcos _)               = Just Refl+matchPrimFun' (PrimAtan _)               (PrimAtan _)               = Just Refl+matchPrimFun' (PrimSinh _)               (PrimSinh _)               = Just Refl+matchPrimFun' (PrimCosh _)               (PrimCosh _)               = Just Refl+matchPrimFun' (PrimTanh _)               (PrimTanh _)               = Just Refl+matchPrimFun' (PrimAsinh _)              (PrimAsinh _)              = Just Refl+matchPrimFun' (PrimAcosh _)              (PrimAcosh _)              = Just Refl+matchPrimFun' (PrimAtanh _)              (PrimAtanh _)              = Just Refl+matchPrimFun' (PrimExpFloating _)        (PrimExpFloating _)        = Just Refl+matchPrimFun' (PrimSqrt _)               (PrimSqrt _)               = Just Refl+matchPrimFun' (PrimLog _)                (PrimLog _)                = Just Refl+matchPrimFun' (PrimFPow _)               (PrimFPow _)               = Just Refl+matchPrimFun' (PrimLogBase _)            (PrimLogBase _)            = Just Refl+matchPrimFun' (PrimAtan2 _)              (PrimAtan2 _)              = Just Refl+matchPrimFun' (PrimTruncate s _)         (PrimTruncate t _)         = matchFloatingType s t+matchPrimFun' (PrimRound s _)            (PrimRound t _)            = matchFloatingType s t+matchPrimFun' (PrimFloor s _)            (PrimFloor t _)            = matchFloatingType s t+matchPrimFun' (PrimCeiling s _)          (PrimCeiling t _)          = matchFloatingType s t+matchPrimFun' (PrimIsNaN s)              (PrimIsNaN t)              = matchFloatingType s t+matchPrimFun' (PrimMax _)                (PrimMax _)                = Just Refl+matchPrimFun' (PrimMin _)                (PrimMin _)                = Just Refl+matchPrimFun' (PrimFromIntegral s _)     (PrimFromIntegral t _)     = matchIntegralType s t+matchPrimFun' (PrimToFloating s _)       (PrimToFloating t _)       = matchNumType s t+matchPrimFun' (PrimCoerce s _)           (PrimCoerce t _)           = matchScalarType s t+matchPrimFun' PrimLAnd                   PrimLAnd                   = Just Refl+matchPrimFun' PrimLOr                    PrimLOr                    = Just Refl+matchPrimFun' PrimLNot                   PrimLNot                   = Just Refl+matchPrimFun' PrimOrd                    PrimOrd                    = Just Refl+matchPrimFun' PrimChr                    PrimChr                    = Just Refl+matchPrimFun' PrimBoolToInt              PrimBoolToInt              = Just Refl+matchPrimFun' (PrimLt s) (PrimLt t)+  | Just Refl <- matchScalarType s t+  = Just Refl++matchPrimFun' (PrimGt s) (PrimGt t)+  | Just Refl <- matchScalarType s t+  = Just Refl++matchPrimFun' (PrimLtEq s) (PrimLtEq t)+  | Just Refl <- matchScalarType s t+  = Just Refl++matchPrimFun' (PrimGtEq s) (PrimGtEq t)+  | Just Refl <- matchScalarType s t+  = Just Refl++matchPrimFun' (PrimEq s) (PrimEq t)+  | Just Refl <- matchScalarType s t+  = Just Refl++matchPrimFun' (PrimNEq s) (PrimNEq t)+  | Just Refl <- matchScalarType s t+  = Just Refl++matchPrimFun' _ _+  = Nothing+++-- Match reified types+--+matchTupleType :: TupleType s -> TupleType t -> Maybe (s :~: t)+matchTupleType UnitTuple         UnitTuple         = Just Refl+matchTupleType (SingleTuple s)   (SingleTuple t)   = matchScalarType s t+matchTupleType (PairTuple s1 s2) (PairTuple t1 t2)+  | Just Refl <- matchTupleType s1 t1+  , Just Refl <- matchTupleType s2 t2+  = Just Refl++matchTupleType _ _+  = Nothing+++-- Match reified type dictionaries+--+matchScalarType :: ScalarType s -> ScalarType t -> Maybe (s :~: t)+matchScalarType (NumScalarType s)    (NumScalarType t)    = matchNumType s t+matchScalarType (NonNumScalarType s) (NonNumScalarType t) = matchNonNumType s t+matchScalarType _                    _                    = Nothing++matchNumType :: NumType s -> NumType t -> Maybe (s :~: t)+matchNumType (IntegralNumType s) (IntegralNumType t) = matchIntegralType s t+matchNumType (FloatingNumType s) (FloatingNumType t) = matchFloatingType s t+matchNumType _                   _                   = Nothing++matchBoundedType :: BoundedType s -> BoundedType t -> Maybe (s :~: t)+matchBoundedType (IntegralBoundedType s) (IntegralBoundedType t) = matchIntegralType s t+matchBoundedType (NonNumBoundedType s)   (NonNumBoundedType t)   = matchNonNumType s t+matchBoundedType _                       _                       = Nothing++matchIntegralType :: IntegralType s -> IntegralType t -> Maybe (s :~: t)+matchIntegralType (TypeInt _)     (TypeInt _)     = Just Refl+matchIntegralType (TypeInt8 _)    (TypeInt8 _)    = Just Refl+matchIntegralType (TypeInt16 _)   (TypeInt16 _)   = Just Refl+matchIntegralType (TypeInt32 _)   (TypeInt32 _)   = Just Refl+matchIntegralType (TypeInt64 _)   (TypeInt64 _)   = Just Refl+matchIntegralType (TypeWord _)    (TypeWord _)    = Just Refl+matchIntegralType (TypeWord8 _)   (TypeWord8 _)   = Just Refl+matchIntegralType (TypeWord16 _)  (TypeWord16 _)  = Just Refl+matchIntegralType (TypeWord32 _)  (TypeWord32 _)  = Just Refl+matchIntegralType (TypeWord64 _)  (TypeWord64 _)  = Just Refl+matchIntegralType (TypeCShort _)  (TypeCShort _)  = Just Refl+matchIntegralType (TypeCUShort _) (TypeCUShort _) = Just Refl+matchIntegralType (TypeCInt _)    (TypeCInt _)    = Just Refl+matchIntegralType (TypeCUInt _)   (TypeCUInt _)   = Just Refl+matchIntegralType (TypeCLong _)   (TypeCLong _)   = Just Refl+matchIntegralType (TypeCULong _)  (TypeCULong _)  = Just Refl+matchIntegralType (TypeCLLong _)  (TypeCLLong _)  = Just Refl+matchIntegralType (TypeCULLong _) (TypeCULLong _) = Just Refl+matchIntegralType _               _               = Nothing++matchFloatingType :: FloatingType s -> FloatingType t -> Maybe (s :~: t)+matchFloatingType (TypeFloat _)   (TypeFloat _)   = Just Refl+matchFloatingType (TypeDouble _)  (TypeDouble _)  = Just Refl+matchFloatingType (TypeCFloat _)  (TypeCFloat _)  = Just Refl+matchFloatingType (TypeCDouble _) (TypeCDouble _) = Just Refl+matchFloatingType _               _               = Nothing++matchNonNumType :: NonNumType s -> NonNumType t -> Maybe (s :~: t)+matchNonNumType (TypeBool _)   (TypeBool _)   = Just Refl+matchNonNumType (TypeChar _)   (TypeChar _)   = Just Refl+matchNonNumType (TypeCChar _)  (TypeCChar _)  = Just Refl+matchNonNumType (TypeCSChar _) (TypeCSChar _) = Just Refl+matchNonNumType (TypeCUChar _) (TypeCUChar _) = Just Refl+matchNonNumType _              _              = Nothing+++-- Discriminate binary functions that commute, and if so return the operands in+-- a stable ordering such that matching recognises expressions modulo+-- commutativity.+--+commutes+    :: forall acc env aenv a r.+       HashAcc acc+    -> PrimFun (a -> r)+    -> PreOpenExp acc env aenv a+    -> Maybe (PreOpenExp acc env aenv a)+commutes h f x = case f of+  PrimAdd _     -> Just (swizzle x)+  PrimMul _     -> Just (swizzle x)+  PrimBAnd _    -> Just (swizzle x)+  PrimBOr _     -> Just (swizzle x)+  PrimBXor _    -> Just (swizzle x)+  PrimEq _      -> Just (swizzle x)+  PrimNEq _     -> Just (swizzle x)+  PrimMax _     -> Just (swizzle x)+  PrimMin _     -> Just (swizzle x)+  PrimLAnd      -> Just (swizzle x)+  PrimLOr       -> Just (swizzle x)+  _             -> Nothing+  where+    swizzle :: PreOpenExp acc env aenv (a',a') -> PreOpenExp acc env aenv (a',a')+    swizzle exp+      | Tuple (NilTup `SnocTup` a `SnocTup` b)  <- exp+      , hashPreOpenExp h a > hashPreOpenExp h b = Tuple (NilTup `SnocTup` b `SnocTup` a)+      --+      | otherwise                               = exp+++-- Hashing+-- =======++hashIdx :: Idx env t -> Int+hashIdx = hash . idxToInt++hashTupleIdx :: TupleIdx tup e -> Int+hashTupleIdx = hash . tupleIdxToInt+++-- Array computations+-- ------------------++type HashAcc acc = forall aenv a. acc aenv a -> Int+++hashOpenAcc :: OpenAcc aenv arrs -> Int+hashOpenAcc (OpenAcc pacc) = hashPreOpenAcc hashOpenAcc pacc++{--+hashPreOpenSeq :: forall acc aenv senv arrs. HashAcc acc -> PreOpenSeq acc aenv senv arrs -> Int+hashPreOpenSeq hashAcc s =+  let+    hashA :: Int -> acc aenv' a -> Int+    hashA salt = hashWithSalt salt . hashAcc++    hashE :: Int -> PreOpenExp acc env' aenv' e -> Int+    hashE salt = hashWithSalt salt . hashPreOpenExp hashAcc++    hashAF :: Int -> PreOpenAfun acc aenv' f -> Int+    hashAF salt = hashWithSalt salt . hashAfun hashAcc++    hashF :: Int -> PreOpenFun acc env' aenv' f -> Int+    hashF salt = hashWithSalt salt . hashPreOpenFun hashAcc++    hashS :: Int -> PreOpenSeq acc aenv senv' arrs' -> Int+    hashS salt = hashWithSalt salt . hashPreOpenSeq hashAcc++    hashVar :: Int -> Idx senv' a -> Int+    hashVar salt = hashWithSalt salt . idxToInt++    hashP :: Int -> Producer acc aenv senv a -> Int+    hashP salt p =+      case p of+        StreamIn arrs       -> unsafePerformIO $! hashStableName `fmap` makeStableName arrs+        ToSeq spec _ acc    -> hashWithSalt salt "ToSeq"         `hashA`  acc `hashWithSalt` show spec+        MapSeq f x          -> hashWithSalt salt "MapSeq"        `hashAF` f   `hashVar` x+        ChunkedMapSeq f x   -> hashWithSalt salt "ChunkedMapSeq" `hashAF` f   `hashVar` x+        ZipWithSeq f x y    -> hashWithSalt salt "ZipWithSeq"    `hashAF` f   `hashVar` x `hashVar` y+        ScanSeq f e x       -> hashWithSalt salt "ScanSeq"       `hashF`  f   `hashE`   e `hashVar` x++    hashC :: Int -> Consumer acc aenv senv' a -> Int+    hashC salt c =+      case c of+        FoldSeq f e x          -> hashWithSalt salt "FoldSeq"        `hashF`  f `hashE` e   `hashVar` x+        FoldSeqFlatten f acc x -> hashWithSalt salt "FoldSeqFlatten" `hashAF` f `hashA` acc `hashVar` x+        Stuple t               -> hash "Stuple" `hashWithSalt` hashAtuple (hashC salt) t++  in case s of+    Producer   p s' -> hash "Producer"   `hashP` p `hashS` s'+    Consumer   c    -> hash "Consumer"   `hashC` c+    Reify      ix   -> hash "Reify"      `hashVar` ix+--}+++hashPreOpenAcc :: forall acc aenv arrs. HashAcc acc -> PreOpenAcc acc aenv arrs -> Int+hashPreOpenAcc hashAcc pacc =+  let+    hashA :: Int -> acc aenv' a -> Int+    hashA salt = hashWithSalt salt . hashAcc++    hashE :: Int -> PreOpenExp acc env' aenv' e -> Int+    hashE salt = hashWithSalt salt . hashPreOpenExp hashAcc++    hashF :: Int -> PreOpenFun acc env' aenv' f -> Int+    hashF salt = hashWithSalt salt . hashPreOpenFun hashAcc++    -- hashS :: Int -> PreOpenSeq acc aenv senv arrs -> Int+    -- hashS salt = hashWithSalt salt . hashPreOpenSeq hashAcc++  in case pacc of+    Alet bnd body               -> hash "Alet"          `hashA` bnd `hashA` body+    Avar v                      -> hash "Avar"          `hashWithSalt` hashIdx v+    Atuple t                    -> hash "Atuple"        `hashWithSalt` hashAtuple hashAcc t+    Aprj ix a                   -> hash "Aprj"          `hashWithSalt` hashTupleIdx ix    `hashA` a+    Apply f a                   -> hash "Apply"         `hashWithSalt` hashAfun hashAcc f `hashA` a+    Aforeign _ f a              -> hash "Aforeign"      `hashWithSalt` hashAfun hashAcc f `hashA` a+    Use a                       -> hash "Use"           `hashWithSalt` hashArrays (arrays (undefined::arrs)) a+    Awhile p f a                -> hash "Awhile"        `hashWithSalt` hashAfun hashAcc f `hashWithSalt` hashAfun hashAcc p `hashA` a+    Unit e                      -> hash "Unit"          `hashE` e+    Generate e f                -> hash "Generate"      `hashE` e  `hashF` f+    Acond e a1 a2               -> hash "Acond"         `hashE` e  `hashA` a1 `hashA` a2+    Reshape sh a                -> hash "Reshape"       `hashE` sh `hashA` a+    Transform sh f1 f2 a        -> hash "Transform"     `hashE` sh `hashF` f1 `hashF` f2 `hashA` a+    Replicate spec ix a         -> hash "Replicate"     `hashE` ix `hashA` a  `hashWithSalt` show spec+    Slice spec a ix             -> hash "Slice"         `hashE` ix `hashA` a  `hashWithSalt` show spec+    Map f a                     -> hash "Map"           `hashF` f  `hashA` a+    ZipWith f a1 a2             -> hash "ZipWith"       `hashF` f  `hashA` a1 `hashA` a2+    Fold f e a                  -> hash "Fold"          `hashF` f  `hashE` e  `hashA` a+    Fold1 f a                   -> hash "Fold1"         `hashF` f  `hashA` a+    FoldSeg f e a s             -> hash "FoldSeg"       `hashF` f  `hashE` e  `hashA` a  `hashA` s+    Fold1Seg f a s              -> hash "Fold1Seg"      `hashF` f  `hashA` a  `hashA` s+    Scanl f e a                 -> hash "Scanl"         `hashF` f  `hashE` e  `hashA` a+    Scanl' f e a                -> hash "Scanl'"        `hashF` f  `hashE` e  `hashA` a+    Scanl1 f a                  -> hash "Scanl1"        `hashF` f  `hashA` a+    Scanr f e a                 -> hash "Scanr"         `hashF` f  `hashE` e  `hashA` a+    Scanr' f e a                -> hash "Scanr'"        `hashF` f  `hashE` e  `hashA` a+    Scanr1 f a                  -> hash "Scanr1"        `hashF` f  `hashA` a+    Backpermute sh f a          -> hash "Backpermute"   `hashF` f  `hashE` sh `hashA` a+    Permute f1 a1 f2 a2         -> hash "Permute"       `hashF` f1 `hashA` a1 `hashF` f2 `hashA` a2+    Stencil f b a               -> hash "Stencil"       `hashF` f  `hashA` a             `hashWithSalt` hashBoundary a  b+    Stencil2 f b1 a1 b2 a2      -> hash "Stencil2"      `hashF` f  `hashA` a1 `hashA` a2 `hashWithSalt` hashBoundary a1 b1 `hashWithSalt` hashBoundary a2 b2+    -- Collect s                   -> hash "Seq"           `hashS` s+++hashArrays :: ArraysR a -> a -> Int+hashArrays ArraysRunit         ()       = hash ()+hashArrays (ArraysRpair r1 r2) (a1, a2) = hash ( hashArrays r1 a1, hashArrays r2 a2)+hashArrays ArraysRarray        ad       = unsafePerformIO $! hashStableName `fmap` makeStableName ad++hashAtuple :: HashAcc acc -> Atuple (acc aenv) a -> Int+hashAtuple _ NilAtup            = hash "NilAtup"+hashAtuple h (SnocAtup t a)     = hash "SnocAtup"       `hashWithSalt` hashAtuple h t `hashWithSalt` h a++hashAfun :: HashAcc acc -> PreOpenAfun acc aenv f -> Int+hashAfun h (Abody b)            = hash "Abody"          `hashWithSalt` h b+hashAfun h (Alam f)             = hash "Alam"           `hashWithSalt` hashAfun h f++hashBoundary :: forall acc aenv sh e. Elt e => acc aenv (Array sh e) -> Boundary (EltRepr e) -> Int+hashBoundary _ Wrap             = hash "Wrap"+hashBoundary _ Clamp            = hash "Clamp"+hashBoundary _ Mirror           = hash "Mirror"+hashBoundary _ (Constant c)     = hash "Constant"       `hashWithSalt` show (toElt c :: e)+++-- Scalar expressions+-- ------------------++hashOpenExp :: OpenExp env aenv exp -> Int+hashOpenExp = hashPreOpenExp hashOpenAcc++hashPreOpenExp :: forall acc env aenv exp. HashAcc acc -> PreOpenExp acc env aenv exp -> Int+hashPreOpenExp hashAcc exp =+  let+    hashA :: Int -> acc aenv' a -> Int+    hashA salt = hashWithSalt salt . hashAcc++    hashE :: Int -> PreOpenExp acc env' aenv' e -> Int+    hashE salt = hashWithSalt salt . hashPreOpenExp hashAcc++  in case exp of+    Let bnd body                -> hash "Let"           `hashE` bnd `hashE` body+    Var ix                      -> hash "Var"           `hashWithSalt` hashIdx ix+    Const c                     -> hash "Const"         `hashWithSalt` show (toElt c :: exp)+    Tuple t                     -> hash "Tuple"         `hashWithSalt` hashTuple hashAcc t+    Prj i e                     -> hash "Prj"           `hashWithSalt` hashTupleIdx i `hashE` e+    IndexAny                    -> hash "IndexAny"+    IndexNil                    -> hash "IndexNil"+    IndexCons sl a              -> hash "IndexCons"     `hashE` sl `hashE` a+    IndexHead sl                -> hash "IndexHead"     `hashE` sl+    IndexTail sl                -> hash "IndexTail"     `hashE` sl+    IndexSlice spec ix sh       -> hash "IndexSlice"    `hashE` ix `hashE` sh `hashWithSalt` show spec+    IndexFull  spec ix sl       -> hash "IndexFull"     `hashE` ix `hashE` sl `hashWithSalt` show spec+    ToIndex sh i                -> hash "ToIndex"       `hashE` sh `hashE` i+    FromIndex sh i              -> hash "FromIndex"     `hashE` sh `hashE` i+    Cond c t e                  -> hash "Cond"          `hashE` c  `hashE` t  `hashE` e+    While p f x                 -> hash "While"         `hashWithSalt` hashPreOpenFun hashAcc p  `hashWithSalt` hashPreOpenFun hashAcc f  `hashE` x+    PrimApp f x                 -> hash "PrimApp"       `hashWithSalt` hashPrimFun f `hashE` fromMaybe x (commutes hashAcc f x)+    PrimConst c                 -> hash "PrimConst"     `hashWithSalt` hashPrimConst c+    Index a ix                  -> hash "Index"         `hashA` a  `hashE` ix+    LinearIndex a ix            -> hash "LinearIndex"   `hashA` a  `hashE` ix+    Shape a                     -> hash "Shape"         `hashA` a+    ShapeSize sh                -> hash "ShapeSize"     `hashE` sh+    Intersect sa sb             -> hash "Intersect"     `hashE` sa `hashE` sb+    Union sa sb                 -> hash "Union"         `hashE` sa `hashE` sb+    Foreign _ f e               -> hash "Foreign"       `hashWithSalt` hashPreOpenFun hashAcc f `hashE` e+++hashPreOpenFun :: HashAcc acc -> PreOpenFun acc env aenv f -> Int+hashPreOpenFun h (Body e)       = hash "Body"           `hashWithSalt` hashPreOpenExp h e+hashPreOpenFun h (Lam f)        = hash "Lam"            `hashWithSalt` hashPreOpenFun h f++hashTuple :: HashAcc acc -> Tuple (PreOpenExp acc env aenv) e -> Int+hashTuple _ NilTup              = hash "NilTup"+hashTuple h (SnocTup t e)       = hash "SnocTup"        `hashWithSalt` hashTuple h t `hashWithSalt` hashPreOpenExp h e+++hashPrimConst :: PrimConst c -> Int+hashPrimConst PrimMinBound{}    = hash "PrimMinBound"+hashPrimConst PrimMaxBound{}    = hash "PrimMaxBound"+hashPrimConst PrimPi{}          = hash "PrimPi"++hashPrimFun :: PrimFun f -> Int+hashPrimFun PrimAdd{}                = hash "PrimAdd"+hashPrimFun PrimSub{}                = hash "PrimSub"+hashPrimFun PrimMul{}                = hash "PrimMul"+hashPrimFun PrimNeg{}                = hash "PrimNeg"+hashPrimFun PrimAbs{}                = hash "PrimAbs"+hashPrimFun PrimSig{}                = hash "PrimSig"+hashPrimFun PrimQuot{}               = hash "PrimQuot"+hashPrimFun PrimRem{}                = hash "PrimRem"+hashPrimFun PrimQuotRem{}            = hash "PrimQuotRem"+hashPrimFun PrimIDiv{}               = hash "PrimIDiv"+hashPrimFun PrimMod{}                = hash "PrimMod"+hashPrimFun PrimDivMod{}             = hash "PrimDivMod"+hashPrimFun PrimBAnd{}               = hash "PrimBAnd"+hashPrimFun PrimBOr{}                = hash "PrimBOr"+hashPrimFun PrimBXor{}               = hash "PrimBXor"+hashPrimFun PrimBNot{}               = hash "PrimBNot"+hashPrimFun PrimBShiftL{}            = hash "PrimBShiftL"+hashPrimFun PrimBShiftR{}            = hash "PrimBShiftR"+hashPrimFun PrimBRotateL{}           = hash "PrimBRotateL"+hashPrimFun PrimBRotateR{}           = hash "PrimBRotateR"+hashPrimFun PrimPopCount{}           = hash "PrimPopCount"+hashPrimFun PrimCountLeadingZeros{}  = hash "PrimCountLeadingZeros"+hashPrimFun PrimCountTrailingZeros{} = hash "PrimCountTrailingZeros"+hashPrimFun PrimFDiv{}               = hash "PrimFDiv"+hashPrimFun PrimRecip{}              = hash "PrimRecip"+hashPrimFun PrimSin{}                = hash "PrimSin"+hashPrimFun PrimCos{}                = hash "PrimCos"+hashPrimFun PrimTan{}                = hash "PrimTan"+hashPrimFun PrimAsin{}               = hash "PrimAsin"+hashPrimFun PrimAcos{}               = hash "PrimAcos"+hashPrimFun PrimAtan{}               = hash "PrimAtan"+hashPrimFun PrimSinh{}               = hash "PrimSinh"+hashPrimFun PrimCosh{}               = hash "PrimCosh"+hashPrimFun PrimTanh{}               = hash "PrimTanh"+hashPrimFun PrimAsinh{}              = hash "PrimAsinh"+hashPrimFun PrimAcosh{}              = hash "PrimAcosh"+hashPrimFun PrimAtanh{}              = hash "PrimAtanh"+hashPrimFun PrimExpFloating{}        = hash "PrimExpFloating"+hashPrimFun PrimSqrt{}               = hash "PrimSqrt"+hashPrimFun PrimLog{}                = hash "PrimLog"+hashPrimFun PrimFPow{}               = hash "PrimFPow"+hashPrimFun PrimLogBase{}            = hash "PrimLogBase"+hashPrimFun PrimAtan2{}              = hash "PrimAtan2"+hashPrimFun PrimTruncate{}           = hash "PrimTruncate"+hashPrimFun PrimRound{}              = hash "PrimRound"+hashPrimFun PrimFloor{}              = hash "PrimFloor"+hashPrimFun PrimCeiling{}            = hash "PrimCeiling"+hashPrimFun PrimIsNaN{}              = hash "PrimIsNaN"+hashPrimFun PrimLt{}                 = hash "PrimLt"+hashPrimFun PrimGt{}                 = hash "PrimGt"+hashPrimFun PrimLtEq{}               = hash "PrimLtEq"+hashPrimFun PrimGtEq{}               = hash "PrimGtEq"+hashPrimFun PrimEq{}                 = hash "PrimEq"+hashPrimFun PrimNEq{}                = hash "PrimNEq"+hashPrimFun PrimMax{}                = hash "PrimMax"+hashPrimFun PrimMin{}                = hash "PrimMin"+hashPrimFun PrimFromIntegral{}       = hash "PrimFromIntegral"+hashPrimFun PrimToFloating{}         = hash "PrimToFloating"+hashPrimFun PrimCoerce{}             = hash "PrimCoerce"+hashPrimFun PrimLAnd                 = hash "PrimLAnd"+hashPrimFun PrimLOr                  = hash "PrimLOr"+hashPrimFun PrimLNot                 = hash "PrimLNot"+hashPrimFun PrimOrd                  = hash "PrimOrd"+hashPrimFun PrimChr                  = hash "PrimChr"+hashPrimFun PrimBoolToInt            = hash "PrimBoolToInt" 
Data/Array/Accelerate/Analysis/Shape.hs view
@@ -1,14 +1,15 @@+{-# LANGUAGE CPP                 #-} {-# LANGUAGE GADTs               #-} {-# LANGUAGE RankNTypes          #-} {-# LANGUAGE ScopedTypeVariables #-} {-# OPTIONS_HADDOCK hide #-} -- | -- Module      : Data.Array.Accelerate.Analysis.Shape--- Copyright   : [2008..2014] Manuel M T Chakravarty, Gabriele Keller---               [2009..2014] Trevor L. McDonell+-- Copyright   : [2008..2017] Manuel M T Chakravarty, Gabriele Keller+--               [2009..2017] Trevor L. McDonell -- License     : BSD3 ----- Maintainer  : Manuel M T Chakravarty <chak@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -45,29 +46,47 @@ preAccDim k pacc =   case pacc of     Alet  _ acc          -> k acc-    Avar _               -> case arrays' (undefined :: Array sh e) of+    Avar _               -> case arrays (undefined :: Array sh e) of                               ArraysRarray -> ndim (eltType (undefined::sh))+#if __GLASGOW_HASKELL__ < 800                               _            -> error "halt, fiend!"+#endif -    Apply _ _            -> case arrays' (undefined :: Array sh e) of+    Apply _ _            -> case arrays (undefined :: Array sh e) of                               ArraysRarray -> ndim (eltType (undefined::sh))+#if __GLASGOW_HASKELL__ < 800                               _            -> error "umm, hello"+#endif -    Aforeign _ _ _      -> case arrays' (undefined :: Array sh e) of+    Aforeign _ _ _      -> case arrays (undefined :: Array sh e) of                               ArraysRarray -> ndim (eltType (undefined::sh))+#if __GLASGOW_HASKELL__ < 800                               _            -> error "I don't even like snails!"+#endif -    Atuple _             -> case arrays' (undefined :: Array sh e) of+    Atuple _             -> case arrays (undefined :: Array sh e) of                               ArraysRarray -> ndim (eltType (undefined::sh))+#if __GLASGOW_HASKELL__ < 800                               _            -> error "can we keep him?"+#endif -    Aprj _ _             -> case arrays' (undefined :: Array sh e) of+    Aprj _ _             -> case arrays (undefined :: Array sh e) of                               ArraysRarray -> ndim (eltType (undefined::sh))+#if __GLASGOW_HASKELL__ < 800                               _            -> error "inconceivable!"+#endif +{--+    Collect _            -> case arrays (undefined :: Array sh e) of+                              ArraysRarray -> ndim (eltType (undefined::sh))+#if __GLASGOW_HASKELL__ < 800+                              _            -> error "ppbbbbbt~"+#endif+--}+     Acond _ acc _        -> k acc     Awhile _ _ acc       -> k acc-    Use ((),(Array _ _)) -> ndim (eltType (undefined::sh))+    Use Array{}          -> ndim (eltType (undefined::sh))     Unit _               -> 0     Generate _ _         -> ndim (eltType (undefined::sh))     Transform _ _ _ _    -> ndim (eltType (undefined::sh))
Data/Array/Accelerate/Analysis/Stencil.hs view
@@ -3,12 +3,12 @@ {-# LANGUAGE TypeOperators       #-} {-# OPTIONS_HADDOCK hide #-} -- |--- Module      : Data.Array.Accelerate.CUDA.Analysis.Stencil+-- Module      : Data.Array.Accelerate.Analysis.Stencil -- Copyright   : [2010..2011] Ben Lever---               [2010..2014] Trevor L. McDonell+--               [2010..2017] Trevor L. McDonell -- License     : BSD3 ----- Maintainer  : Manuel M T Chakravarty <chak@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --
Data/Array/Accelerate/Analysis/Type.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP                 #-} {-# LANGUAGE GADTs               #-} {-# LANGUAGE PatternGuards       #-} {-# LANGUAGE RankNTypes          #-}@@ -6,11 +7,11 @@ {-# OPTIONS_HADDOCK hide #-} -- | -- Module      : Data.Array.Accelerate.Analysis.Type--- Copyright   : [2008..2014] Manuel M T Chakravarty, Gabriele Keller---               [2009..2014] Trevor L. McDonell+-- Copyright   : [2008..2017] Manuel M T Chakravarty, Gabriele Keller+--               [2009..2017] Trevor L. McDonell -- License     : BSD3 ----- Maintainer  : Manuel M T Chakravarty <chak@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -81,29 +82,47 @@     -- The following all contain impossible pattern matches, but GHC's type     -- checker does no grok that     ---    Avar _              -> case arrays' (undefined :: (Array sh e)) of+    Avar _              -> case arrays (undefined :: (Array sh e)) of                              ArraysRarray -> eltType (undefined::e)+#if __GLASGOW_HASKELL__ < 800                              _            -> error "When I get sad, I stop being sad and be AWESOME instead."+#endif -    Apply _ _           -> case arrays' (undefined :: Array sh e) of+    Apply _ _           -> case arrays (undefined :: Array sh e) of                              ArraysRarray -> eltType (undefined::e)+#if __GLASGOW_HASKELL__ < 800                              _            -> error "TRUE STORY."+#endif -    Atuple _            -> case arrays' (undefined :: Array sh e) of+    Atuple _            -> case arrays (undefined :: Array sh e) of                              ArraysRarray -> eltType (undefined::e)+#if __GLASGOW_HASKELL__ < 800                              _            -> error "I made you a cookie, but I eated it."+#endif -    Aprj _ _            -> case arrays' (undefined :: Array sh e) of+    Aprj _ _            -> case arrays (undefined :: Array sh e) of                              ArraysRarray -> eltType (undefined::e)+#if __GLASGOW_HASKELL__ < 800                              _            -> error "Hey look! even the leaves are falling for you."+#endif -    Aforeign _ _ _      -> case arrays' (undefined :: Array sh e) of+    Aforeign _ _ _      -> case arrays (undefined :: Array sh e) of                              ArraysRarray -> eltType (undefined::e)+#if __GLASGOW_HASKELL__ < 800                              _            -> error "Who on earth wrote all these weird error messages?"+#endif +{--+    Collect _           -> case arrays (undefined :: Array sh e) of+                             ArraysRarray -> eltType (undefined::e)+#if __GLASGOW_HASKELL__ < 800+                             _            -> error "rob you are terrible at this game"+#endif+--}+     Acond _ acc _       -> k acc     Awhile _ _ acc      -> k acc-    Use ((),a)          -> arrayType a+    Use a               -> arrayType a     Unit _              -> eltType (undefined::e)     Generate _ _        -> eltType (undefined::e)     Transform _ _ _ _   -> eltType (undefined::e)@@ -166,6 +185,7 @@     Shape _           -> eltType (undefined::t)     ShapeSize _       -> eltType (undefined::t)     Intersect _ _     -> eltType (undefined::t)+    Union _ _         -> eltType (undefined::t)     Foreign _ _ _     -> eltType (undefined::t)  
Data/Array/Accelerate/Array/Data.hs view
@@ -1,26 +1,19 @@-{-# LANGUAGE CPP                 #-} {-# LANGUAGE DeriveDataTypeable  #-}-{-# LANGUAGE FlexibleContexts    #-}-{-# LANGUAGE FlexibleInstances   #-} {-# LANGUAGE GADTs               #-} {-# LANGUAGE MagicHash           #-}-{-# LANGUAGE RankNTypes          #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving  #-} {-# LANGUAGE TemplateHaskell     #-} {-# LANGUAGE TypeFamilies        #-} {-# LANGUAGE UnboxedTuples       #-}-{-# OPTIONS_GHC -fno-warn-missing-methods #-}-{-# OPTIONS_GHC -fno-warn-orphans         #-} {-# OPTIONS_HADDOCK hide #-} -- | -- Module      : Data.Array.Accelerate.Array.Data--- Copyright   : [2008..2014] Manuel M T Chakravarty, Gabriele Keller---               [2008..2009] Sean Lee---               [2009..2014] Trevor L. McDonell+-- Copyright   : [2008..2017] Manuel M T Chakravarty, Gabriele Keller+--               [2009..2017] Trevor L. McDonell -- License     : BSD3 ----- Maintainer  : Manuel M T Chakravarty <chak@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -42,34 +35,37 @@   -- * Type macros   HTYPE_INT, HTYPE_WORD, HTYPE_LONG, HTYPE_UNSIGNED_LONG, HTYPE_CCHAR, +  -- * Allocator internals+  registerForeignPtrAllocator,+ ) where +-- friends+import Data.Array.Accelerate.Array.Unique+import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.Debug.Flags+import Data.Array.Accelerate.Debug.Trace+ -- standard libraries-import Foreign                                  ( Ptr )-import Foreign.C.Types-import Data.Bits-import Data.Functor-import Data.Typeable                            ( Typeable )+import Control.Applicative import Control.Monad-#ifdef ACCELERATE_UNSAFE_CHECKS-import qualified Data.Array.Base                as MArray ( readArray, writeArray )-#else-import qualified Data.Array.Base                as MArray ( unsafeRead, unsafeWrite )-#endif-import Data.Array.Storable.Internals-import Foreign.ForeignPtr.Unsafe-import System.IO.Unsafe-import Data.Array.MArray                        ( MArray )-import Data.Array.Base                          ( unsafeNewArray_ )+import Data.Bits+import Data.IORef+import Data.Typeable                                                ( Typeable )+import Foreign.C.Types+import Foreign.ForeignPtr+import Foreign.Ptr+import Foreign.Storable import Language.Haskell.TH+import System.IO.Unsafe+import Text.Printf import Prelude --- friends-import Data.Array.Accelerate.Type+import GHC.Base                                                     ( Int(..), IO(..), unsafeCoerce#, newAlignedPinnedByteArray#, byteArrayContents# )+import GHC.ForeignPtr                                               ( ForeignPtr(..), ForeignPtrContents(..) ) --- Add needed Typeable instance for StorableArray----deriving instance Typeable StorableArray  -- Determine the underlying type of a Haskell CLong or CULong. --@@ -112,7 +108,7 @@  -- |Mutable array representation ---type MutableArrayData e = GArrayData (StorableArray Int) e+type MutableArrayData e = GArrayData UniqueArray e  -- Array representation in dependence on the element type, but abstracting -- over the basic array type (in particular, abstracting over mutability)@@ -194,400 +190,618 @@  class ArrayElt e where   type ArrayPtrs e+  arrayElt               :: ArrayEltR e   --   unsafeIndexArrayData   :: ArrayData e -> Int -> e   ptrsOfArrayData        :: ArrayData e -> ArrayPtrs e+  touchArrayData         :: ArrayData e -> IO ()   --   newArrayData           :: Int -> IO (MutableArrayData e)   unsafeReadArrayData    :: MutableArrayData e -> Int      -> IO e   unsafeWriteArrayData   :: MutableArrayData e -> Int -> e -> IO ()   unsafeFreezeArrayData  :: MutableArrayData e -> IO (ArrayData e)-  unsafeFreezeArrayData  = return   ptrsOfMutableArrayData :: MutableArrayData e -> IO (ArrayPtrs e)-  ptrsOfMutableArrayData = return . ptrsOfArrayData   ---  arrayElt               :: ArrayEltR e+  {-# INLINE unsafeFreezeArrayData  #-}+  {-# INLINE ptrsOfMutableArrayData #-}+  unsafeFreezeArrayData  = return+  ptrsOfMutableArrayData = return . ptrsOfArrayData  instance ArrayElt () where   type ArrayPtrs () = ()-  unsafeIndexArrayData AD_Unit i    = i `seq` ()-  ptrsOfArrayData AD_Unit           = ()-  newArrayData size                 = size `seq` return AD_Unit-  unsafeReadArrayData AD_Unit i     = i `seq` return ()-  unsafeWriteArrayData AD_Unit i () = i `seq` return ()-  arrayElt                          = ArrayEltRunit+  arrayElt          = ArrayEltRunit+  {-# INLINE unsafeIndexArrayData #-}+  unsafeIndexArrayData AD_Unit i          = i `seq` ()+  {-# INLINE ptrsOfArrayData #-}+  ptrsOfArrayData AD_Unit                 = ()+  {-# INLINE touchArrayData #-}+  touchArrayData AD_Unit                  = return ()+  {-# INLINE newArrayData #-}+  newArrayData size                       = size `seq` return AD_Unit+  {-# INLINE unsafeReadArrayData #-}+  unsafeReadArrayData AD_Unit i           = i `seq` return ()+  {-# INLINE unsafeWriteArrayData #-}+  unsafeWriteArrayData AD_Unit i ()       = i `seq` return ()  instance ArrayElt Int where   type ArrayPtrs Int = Ptr Int-  unsafeIndexArrayData (AD_Int ba) i   = unsafeIndexArray ba i-  ptrsOfArrayData (AD_Int ba)          = storableArrayPtr ba-  newArrayData size                    = liftM AD_Int $ unsafeNewArray_ (0,size-1)-  unsafeReadArrayData (AD_Int ba) i    = unsafeReadArray ba i-  unsafeWriteArrayData (AD_Int ba) i e = unsafeWriteArray ba i e-  arrayElt                             = ArrayEltRint+  arrayElt           = ArrayEltRint+  {-# INLINE unsafeIndexArrayData #-}+  unsafeIndexArrayData (AD_Int ba) i      = unsafeIndexArray ba i+  {-# INLINE ptrsOfArrayData #-}+  ptrsOfArrayData (AD_Int ba)             = unsafeUniqueArrayPtr ba+  {-# INLINE touchArrayData #-}+  touchArrayData (AD_Int ba)              = touchUniqueArray ba+  {-# INLINE newArrayData #-}+  newArrayData size                       = AD_Int <$> newArrayData' size+  {-# INLINE unsafeReadArrayData #-}+  unsafeReadArrayData (AD_Int ba) i       = unsafeReadArray ba i+  {-# INLINE unsafeWriteArrayData #-}+  unsafeWriteArrayData (AD_Int ba) i e    = unsafeWriteArray ba i e  instance ArrayElt Int8 where   type ArrayPtrs Int8 = Ptr Int8-  unsafeIndexArrayData (AD_Int8 ba) i   = unsafeIndexArray ba i-  ptrsOfArrayData (AD_Int8 ba)          = storableArrayPtr ba-  newArrayData size                     = liftM AD_Int8 $ unsafeNewArray_ (0,size-1)-  unsafeReadArrayData (AD_Int8 ba) i    = unsafeReadArray ba i-  unsafeWriteArrayData (AD_Int8 ba) i e = unsafeWriteArray ba i e-  arrayElt                              = ArrayEltRint8+  arrayElt            = ArrayEltRint8+  {-# INLINE unsafeIndexArrayData #-}+  unsafeIndexArrayData (AD_Int8 ba) i     = unsafeIndexArray ba i+  {-# INLINE ptrsOfArrayData #-}+  ptrsOfArrayData (AD_Int8 ba)            = unsafeUniqueArrayPtr ba+  {-# INLINE touchArrayData #-}+  touchArrayData (AD_Int8 ba)             = touchUniqueArray ba+  {-# INLINE newArrayData #-}+  newArrayData size                       = AD_Int8 <$> newArrayData' size+  {-# INLINE unsafeReadArrayData #-}+  unsafeReadArrayData (AD_Int8 ba) i      = unsafeReadArray ba i+  {-# INLINE unsafeWriteArrayData #-}+  unsafeWriteArrayData (AD_Int8 ba) i e   = unsafeWriteArray ba i e  instance ArrayElt Int16 where   type ArrayPtrs Int16 = Ptr Int16-  unsafeIndexArrayData (AD_Int16 ba) i   = unsafeIndexArray ba i-  ptrsOfArrayData (AD_Int16 ba)          = storableArrayPtr ba-  newArrayData size                      = liftM AD_Int16 $ unsafeNewArray_ (0,size-1)-  unsafeReadArrayData (AD_Int16 ba) i    = unsafeReadArray ba i-  unsafeWriteArrayData (AD_Int16 ba) i e = unsafeWriteArray ba i e-  arrayElt                               = ArrayEltRint16+  arrayElt             = ArrayEltRint16+  {-# INLINE unsafeIndexArrayData #-}+  unsafeIndexArrayData (AD_Int16 ba) i    = unsafeIndexArray ba i+  {-# INLINE ptrsOfArrayData #-}+  ptrsOfArrayData (AD_Int16 ba)           = unsafeUniqueArrayPtr ba+  {-# INLINE touchArrayData #-}+  touchArrayData (AD_Int16 ba)            = touchUniqueArray ba+  {-# INLINE newArrayData #-}+  newArrayData size                       = AD_Int16 <$> newArrayData' size+  {-# INLINE unsafeReadArrayData #-}+  unsafeReadArrayData (AD_Int16 ba) i     = unsafeReadArray ba i+  {-# INLINE unsafeWriteArrayData #-}+  unsafeWriteArrayData (AD_Int16 ba) i e  = unsafeWriteArray ba i e  instance ArrayElt Int32 where   type ArrayPtrs Int32 = Ptr Int32-  unsafeIndexArrayData (AD_Int32 ba) i   = unsafeIndexArray ba i-  ptrsOfArrayData (AD_Int32 ba)          = storableArrayPtr ba-  newArrayData size                      = liftM AD_Int32 $ unsafeNewArray_ (0,size-1)-  unsafeReadArrayData (AD_Int32 ba) i    = unsafeReadArray ba i-  unsafeWriteArrayData (AD_Int32 ba) i e = unsafeWriteArray ba i e-  arrayElt                               = ArrayEltRint32+  arrayElt             = ArrayEltRint32+  {-# INLINE unsafeIndexArrayData #-}+  unsafeIndexArrayData (AD_Int32 ba) i    = unsafeIndexArray ba i+  {-# INLINE ptrsOfArrayData #-}+  ptrsOfArrayData (AD_Int32 ba)           = unsafeUniqueArrayPtr ba+  {-# INLINE touchArrayData #-}+  touchArrayData (AD_Int32 ba)            = touchUniqueArray ba+  {-# INLINE newArrayData #-}+  newArrayData size                       = AD_Int32 <$> newArrayData' size+  {-# INLINE unsafeReadArrayData #-}+  unsafeReadArrayData (AD_Int32 ba) i     = unsafeReadArray ba i+  {-# INLINE unsafeWriteArrayData #-}+  unsafeWriteArrayData (AD_Int32 ba) i e  = unsafeWriteArray ba i e  instance ArrayElt Int64 where   type ArrayPtrs Int64 = Ptr Int64-  unsafeIndexArrayData (AD_Int64 ba) i   = unsafeIndexArray ba i-  ptrsOfArrayData (AD_Int64 ba)          = storableArrayPtr ba-  newArrayData size                      = liftM AD_Int64 $ unsafeNewArray_ (0,size-1)-  unsafeReadArrayData (AD_Int64 ba) i    = unsafeReadArray ba i-  unsafeWriteArrayData (AD_Int64 ba) i e = unsafeWriteArray ba i e-  arrayElt                               = ArrayEltRint64+  arrayElt             = ArrayEltRint64+  {-# INLINE unsafeIndexArrayData #-}+  unsafeIndexArrayData (AD_Int64 ba) i    = unsafeIndexArray ba i+  {-# INLINE ptrsOfArrayData #-}+  ptrsOfArrayData (AD_Int64 ba)           = unsafeUniqueArrayPtr ba+  {-# INLINE touchArrayData #-}+  touchArrayData (AD_Int64 ba)            = touchUniqueArray ba+  {-# INLINE newArrayData #-}+  newArrayData size                       = AD_Int64 <$> newArrayData' size+  {-# INLINE unsafeReadArrayData #-}+  unsafeReadArrayData (AD_Int64 ba) i     = unsafeReadArray ba i+  {-# INLINE unsafeWriteArrayData #-}+  unsafeWriteArrayData (AD_Int64 ba) i e  = unsafeWriteArray ba i e  instance ArrayElt Word where   type ArrayPtrs Word = Ptr Word-  unsafeIndexArrayData (AD_Word ba) i   = unsafeIndexArray ba i-  ptrsOfArrayData (AD_Word ba)          = storableArrayPtr ba-  newArrayData size                     = liftM AD_Word $ unsafeNewArray_ (0,size-1)-  unsafeReadArrayData (AD_Word ba) i    = unsafeReadArray ba i-  unsafeWriteArrayData (AD_Word ba) i e = unsafeWriteArray ba i e-  arrayElt                              = ArrayEltRword+  arrayElt            = ArrayEltRword+  {-# INLINE unsafeIndexArrayData #-}+  unsafeIndexArrayData (AD_Word ba) i     = unsafeIndexArray ba i+  {-# INLINE ptrsOfArrayData #-}+  ptrsOfArrayData (AD_Word ba)            = unsafeUniqueArrayPtr ba+  {-# INLINE touchArrayData #-}+  touchArrayData (AD_Word ba)             = touchUniqueArray ba+  {-# INLINE newArrayData #-}+  newArrayData size                       = AD_Word <$> newArrayData' size+  {-# INLINE unsafeReadArrayData #-}+  unsafeReadArrayData (AD_Word ba) i      = unsafeReadArray ba i+  {-# INLINE unsafeWriteArrayData #-}+  unsafeWriteArrayData (AD_Word ba) i e   = unsafeWriteArray ba i e  instance ArrayElt Word8 where   type ArrayPtrs Word8 = Ptr Word8-  unsafeIndexArrayData (AD_Word8 ba) i   = unsafeIndexArray ba i-  ptrsOfArrayData (AD_Word8 ba)          = storableArrayPtr ba-  newArrayData size                      = liftM AD_Word8 $ unsafeNewArray_ (0,size-1)-  unsafeReadArrayData (AD_Word8 ba) i    = unsafeReadArray ba i-  unsafeWriteArrayData (AD_Word8 ba) i e = unsafeWriteArray ba i e-  arrayElt                               = ArrayEltRword8+  arrayElt             = ArrayEltRword8+  {-# INLINE unsafeIndexArrayData #-}+  unsafeIndexArrayData (AD_Word8 ba) i    = unsafeIndexArray ba i+  {-# INLINE ptrsOfArrayData #-}+  ptrsOfArrayData (AD_Word8 ba)           = unsafeUniqueArrayPtr ba+  {-# INLINE touchArrayData #-}+  touchArrayData (AD_Word8 ba)            = touchUniqueArray ba+  {-# INLINE newArrayData #-}+  newArrayData size                       = AD_Word8 <$> newArrayData' size+  {-# INLINE unsafeReadArrayData #-}+  unsafeReadArrayData (AD_Word8 ba) i     = unsafeReadArray ba i+  {-# INLINE unsafeWriteArrayData #-}+  unsafeWriteArrayData (AD_Word8 ba) i e  = unsafeWriteArray ba i e  instance ArrayElt Word16 where   type ArrayPtrs Word16 = Ptr Word16+  arrayElt              = ArrayEltRword16+  {-# INLINE unsafeIndexArrayData #-}   unsafeIndexArrayData (AD_Word16 ba) i   = unsafeIndexArray ba i-  ptrsOfArrayData (AD_Word16 ba)          = storableArrayPtr ba-  newArrayData size                       = liftM AD_Word16 $ unsafeNewArray_ (0,size-1)+  {-# INLINE ptrsOfArrayData #-}+  ptrsOfArrayData (AD_Word16 ba)          = unsafeUniqueArrayPtr ba+  {-# INLINE touchArrayData #-}+  touchArrayData (AD_Word16 ba)           = touchUniqueArray ba+  {-# INLINE newArrayData #-}+  newArrayData size                       = AD_Word16 <$> newArrayData' size+  {-# INLINE unsafeReadArrayData #-}   unsafeReadArrayData (AD_Word16 ba) i    = unsafeReadArray ba i+  {-# INLINE unsafeWriteArrayData #-}   unsafeWriteArrayData (AD_Word16 ba) i e = unsafeWriteArray ba i e-  arrayElt                                = ArrayEltRword16  instance ArrayElt Word32 where   type ArrayPtrs Word32 = Ptr Word32+  arrayElt              = ArrayEltRword32+  {-# INLINE unsafeIndexArrayData #-}   unsafeIndexArrayData (AD_Word32 ba) i   = unsafeIndexArray ba i-  ptrsOfArrayData (AD_Word32 ba)          = storableArrayPtr ba-  newArrayData size                       = liftM AD_Word32 $ unsafeNewArray_ (0,size-1)+  {-# INLINE ptrsOfArrayData #-}+  ptrsOfArrayData (AD_Word32 ba)          = unsafeUniqueArrayPtr ba+  {-# INLINE touchArrayData #-}+  touchArrayData (AD_Word32 ba)           = touchUniqueArray ba+  {-# INLINE newArrayData #-}+  newArrayData size                       = AD_Word32 <$> newArrayData' size+  {-# INLINE unsafeReadArrayData #-}   unsafeReadArrayData (AD_Word32 ba) i    = unsafeReadArray ba i+  {-# INLINE unsafeWriteArrayData #-}   unsafeWriteArrayData (AD_Word32 ba) i e = unsafeWriteArray ba i e-  arrayElt                                = ArrayEltRword32  instance ArrayElt Word64 where   type ArrayPtrs Word64 = Ptr Word64+  arrayElt              = ArrayEltRword64+  {-# INLINE unsafeIndexArrayData #-}   unsafeIndexArrayData (AD_Word64 ba) i   = unsafeIndexArray ba i-  ptrsOfArrayData (AD_Word64 ba)          = storableArrayPtr ba-  newArrayData size                       = liftM AD_Word64 $ unsafeNewArray_ (0,size-1)+  {-# INLINE ptrsOfArrayData #-}+  ptrsOfArrayData (AD_Word64 ba)          = unsafeUniqueArrayPtr ba+  {-# INLINE touchArrayData #-}+  touchArrayData (AD_Word64 ba)           = touchUniqueArray ba+  {-# INLINE newArrayData #-}+  newArrayData size                       = AD_Word64 <$> newArrayData' size+  {-# INLINE unsafeReadArrayData #-}   unsafeReadArrayData (AD_Word64 ba) i    = unsafeReadArray ba i+  {-# INLINE unsafeWriteArrayData #-}   unsafeWriteArrayData (AD_Word64 ba) i e = unsafeWriteArray ba i e-  arrayElt                                = ArrayEltRword64  instance ArrayElt CShort where   type ArrayPtrs CShort = Ptr Int16+  arrayElt              = ArrayEltRcshort+  {-# INLINE unsafeIndexArrayData #-}   unsafeIndexArrayData (AD_CShort ba) i   = CShort $ unsafeIndexArray ba i-  ptrsOfArrayData (AD_CShort ba)          = storableArrayPtr ba-  newArrayData size                       = liftM AD_CShort $ unsafeNewArray_ (0,size-1)+  {-# INLINE ptrsOfArrayData #-}+  ptrsOfArrayData (AD_CShort ba)          = unsafeUniqueArrayPtr ba+  {-# INLINE touchArrayData #-}+  touchArrayData (AD_CShort ba)           = touchUniqueArray ba+  {-# INLINE newArrayData #-}+  newArrayData size                       = AD_CShort <$> newArrayData' size+  {-# INLINE unsafeReadArrayData #-}   unsafeReadArrayData (AD_CShort ba) i    = CShort <$> unsafeReadArray ba i+  {-# INLINE unsafeWriteArrayData #-}   unsafeWriteArrayData (AD_CShort ba) i (CShort e)     = unsafeWriteArray ba i e-  arrayElt                                = ArrayEltRcshort  instance ArrayElt CUShort where   type ArrayPtrs CUShort = Ptr Word16-  unsafeIndexArrayData (AD_CUShort ba) i   = CUShort $ unsafeIndexArray ba i-  ptrsOfArrayData (AD_CUShort ba)          = storableArrayPtr ba-  newArrayData size                        = liftM AD_CUShort $ unsafeNewArray_ (0,size-1)-  unsafeReadArrayData (AD_CUShort ba) i    = CUShort <$> unsafeReadArray ba i+  arrayElt               = ArrayEltRcushort+  {-# INLINE unsafeIndexArrayData #-}+  unsafeIndexArrayData (AD_CUShort ba) i  = CUShort $ unsafeIndexArray ba i+  {-# INLINE ptrsOfArrayData #-}+  ptrsOfArrayData (AD_CUShort ba)         = unsafeUniqueArrayPtr ba+  {-# INLINE touchArrayData #-}+  touchArrayData (AD_CUShort ba)          = touchUniqueArray ba+  {-# INLINE newArrayData #-}+  newArrayData size                       = AD_CUShort <$> newArrayData' size+  {-# INLINE unsafeReadArrayData #-}+  unsafeReadArrayData (AD_CUShort ba) i   = CUShort <$> unsafeReadArray ba i+  {-# INLINE unsafeWriteArrayData #-}   unsafeWriteArrayData (AD_CUShort ba) i (CUShort e)     = unsafeWriteArray ba i e-  arrayElt                                 = ArrayEltRcushort  instance ArrayElt CInt where   type ArrayPtrs CInt = Ptr Int32-  unsafeIndexArrayData (AD_CInt ba) i   = CInt $ unsafeIndexArray ba i-  ptrsOfArrayData (AD_CInt ba)          = storableArrayPtr ba-  newArrayData size                     = liftM AD_CInt $ unsafeNewArray_ (0,size-1)-  unsafeReadArrayData (AD_CInt ba) i    = CInt <$> unsafeReadArray ba i+  arrayElt            = ArrayEltRcint+  {-# INLINE unsafeIndexArrayData #-}+  unsafeIndexArrayData (AD_CInt ba) i     = CInt $ unsafeIndexArray ba i+  {-# INLINE ptrsOfArrayData #-}+  ptrsOfArrayData (AD_CInt ba)            = unsafeUniqueArrayPtr ba+  {-# INLINE touchArrayData #-}+  touchArrayData (AD_CInt ba)             = touchUniqueArray ba+  {-# INLINE newArrayData #-}+  newArrayData size                       = AD_CInt <$> newArrayData' size+  {-# INLINE unsafeReadArrayData #-}+  unsafeReadArrayData (AD_CInt ba) i      = CInt <$> unsafeReadArray ba i+  {-# INLINE unsafeWriteArrayData #-}   unsafeWriteArrayData (AD_CInt ba) i (CInt e)     = unsafeWriteArray ba i e-  arrayElt                              = ArrayEltRcint  instance ArrayElt CUInt where   type ArrayPtrs CUInt = Ptr Word32-  unsafeIndexArrayData (AD_CUInt ba) i   = CUInt $ unsafeIndexArray ba i-  ptrsOfArrayData (AD_CUInt ba)          = storableArrayPtr ba-  newArrayData size                      = liftM AD_CUInt $ unsafeNewArray_ (0,size-1)-  unsafeReadArrayData (AD_CUInt ba) i    = CUInt <$> unsafeReadArray ba i+  arrayElt             = ArrayEltRcuint+  {-# INLINE unsafeIndexArrayData #-}+  unsafeIndexArrayData (AD_CUInt ba) i    = CUInt $ unsafeIndexArray ba i+  {-# INLINE ptrsOfArrayData #-}+  ptrsOfArrayData (AD_CUInt ba)           = unsafeUniqueArrayPtr ba+  {-# INLINE touchArrayData #-}+  touchArrayData (AD_CUInt ba)            = touchUniqueArray ba+  {-# INLINE newArrayData #-}+  newArrayData size                       = AD_CUInt <$> newArrayData' size+  {-# INLINE unsafeReadArrayData #-}+  unsafeReadArrayData (AD_CUInt ba) i     = CUInt <$> unsafeReadArray ba i+  {-# INLINE unsafeWriteArrayData #-}   unsafeWriteArrayData (AD_CUInt ba) i (CUInt e)     = unsafeWriteArray ba i e-  arrayElt                               = ArrayEltRcuint  instance ArrayElt CLong where   type ArrayPtrs CLong = Ptr HTYPE_LONG-  unsafeIndexArrayData (AD_CLong ba) i   = CLong $ unsafeIndexArray ba i-  ptrsOfArrayData (AD_CLong ba)          = storableArrayPtr ba-  newArrayData size                      = liftM AD_CLong $ unsafeNewArray_ (0,size-1)-  unsafeReadArrayData (AD_CLong ba) i    = CLong <$> unsafeReadArray ba i+  arrayElt             = ArrayEltRclong+  {-# INLINE unsafeIndexArrayData #-}+  unsafeIndexArrayData (AD_CLong ba) i    = CLong $ unsafeIndexArray ba i+  {-# INLINE ptrsOfArrayData #-}+  ptrsOfArrayData (AD_CLong ba)           = unsafeUniqueArrayPtr ba+  {-# INLINE touchArrayData #-}+  touchArrayData (AD_CLong ba)            = touchUniqueArray ba+  {-# INLINE newArrayData #-}+  newArrayData size                       = AD_CLong <$> newArrayData' size+  {-# INLINE unsafeReadArrayData #-}+  unsafeReadArrayData (AD_CLong ba) i     = CLong <$> unsafeReadArray ba i+  {-# INLINE unsafeWriteArrayData #-}   unsafeWriteArrayData (AD_CLong ba) i (CLong e)     = unsafeWriteArray ba i e-  arrayElt                               = ArrayEltRclong  instance ArrayElt CULong where   type ArrayPtrs CULong = Ptr HTYPE_UNSIGNED_LONG+  arrayElt              = ArrayEltRculong+  {-# INLINE unsafeIndexArrayData #-}   unsafeIndexArrayData (AD_CULong ba) i   = CULong $ unsafeIndexArray ba i-  ptrsOfArrayData (AD_CULong ba)          = storableArrayPtr ba-  newArrayData size                       = liftM AD_CULong $ unsafeNewArray_ (0,size-1)+  {-# INLINE ptrsOfArrayData #-}+  ptrsOfArrayData (AD_CULong ba)          = unsafeUniqueArrayPtr ba+  {-# INLINE touchArrayData #-}+  touchArrayData (AD_CULong ba)           = touchUniqueArray ba+  {-# INLINE newArrayData #-}+  newArrayData size                       = AD_CULong <$> newArrayData' size+  {-# INLINE unsafeReadArrayData #-}   unsafeReadArrayData (AD_CULong ba) i    = CULong <$> unsafeReadArray ba i+  {-# INLINE unsafeWriteArrayData #-}   unsafeWriteArrayData (AD_CULong ba) i (CULong e)     = unsafeWriteArray ba i e-  arrayElt                                = ArrayEltRculong  instance ArrayElt CLLong where   type ArrayPtrs CLLong = Ptr Int64+  arrayElt              = ArrayEltRcllong+  {-# INLINE unsafeIndexArrayData #-}   unsafeIndexArrayData (AD_CLLong ba) i   = CLLong $ unsafeIndexArray ba i-  ptrsOfArrayData (AD_CLLong ba)          = storableArrayPtr ba-  newArrayData size                       = liftM AD_CLLong $ unsafeNewArray_ (0,size-1)+  {-# INLINE ptrsOfArrayData #-}+  ptrsOfArrayData (AD_CLLong ba)          = unsafeUniqueArrayPtr ba+  {-# INLINE touchArrayData #-}+  touchArrayData (AD_CLLong ba)           = touchUniqueArray ba+  {-# INLINE newArrayData #-}+  newArrayData size                       = AD_CLLong <$> newArrayData' size+  {-# INLINE unsafeReadArrayData #-}   unsafeReadArrayData (AD_CLLong ba) i    = CLLong <$> unsafeReadArray ba i+  {-# INLINE unsafeWriteArrayData #-}   unsafeWriteArrayData (AD_CLLong ba) i (CLLong e)     = unsafeWriteArray ba i e-  arrayElt                                = ArrayEltRcllong  instance ArrayElt CULLong where   type ArrayPtrs CULLong = Ptr Word64-  unsafeIndexArrayData (AD_CULLong ba) i   = CULLong $ unsafeIndexArray ba i-  ptrsOfArrayData (AD_CULLong ba)          = storableArrayPtr ba-  newArrayData size                        = liftM AD_CULLong $ unsafeNewArray_ (0,size-1)-  unsafeReadArrayData (AD_CULLong ba) i    = CULLong <$> unsafeReadArray ba i+  arrayElt               = ArrayEltRcullong+  {-# INLINE unsafeIndexArrayData #-}+  unsafeIndexArrayData (AD_CULLong ba) i  = CULLong $ unsafeIndexArray ba i+  {-# INLINE ptrsOfArrayData #-}+  ptrsOfArrayData (AD_CULLong ba)         = unsafeUniqueArrayPtr ba+  {-# INLINE touchArrayData #-}+  touchArrayData (AD_CULLong ba)          = touchUniqueArray ba+  {-# INLINE newArrayData #-}+  newArrayData size                       = AD_CULLong <$> newArrayData' size+  {-# INLINE unsafeReadArrayData #-}+  unsafeReadArrayData (AD_CULLong ba) i   = CULLong <$> unsafeReadArray ba i+  {-# INLINE unsafeWriteArrayData #-}   unsafeWriteArrayData (AD_CULLong ba) i (CULLong e)     = unsafeWriteArray ba i e-  arrayElt                                 = ArrayEltRcullong  instance ArrayElt Float where   type ArrayPtrs Float = Ptr Float-  unsafeIndexArrayData (AD_Float ba) i   = unsafeIndexArray ba i-  ptrsOfArrayData (AD_Float ba)          = storableArrayPtr ba-  newArrayData size                      = liftM AD_Float $ unsafeNewArray_ (0,size-1)-  unsafeReadArrayData (AD_Float ba) i    = unsafeReadArray ba i-  unsafeWriteArrayData (AD_Float ba) i e = unsafeWriteArray ba i e-  arrayElt                               = ArrayEltRfloat+  arrayElt             = ArrayEltRfloat+  {-# INLINE unsafeIndexArrayData #-}+  unsafeIndexArrayData (AD_Float ba) i    = unsafeIndexArray ba i+  {-# INLINE ptrsOfArrayData #-}+  ptrsOfArrayData (AD_Float ba)           = unsafeUniqueArrayPtr ba+  {-# INLINE touchArrayData #-}+  touchArrayData (AD_Float ba)            = touchUniqueArray ba+  {-# INLINE newArrayData #-}+  newArrayData size                       = AD_Float <$> newArrayData' size+  {-# INLINE unsafeReadArrayData #-}+  unsafeReadArrayData (AD_Float ba) i     = unsafeReadArray ba i+  {-# INLINE unsafeWriteArrayData #-}+  unsafeWriteArrayData (AD_Float ba) i e  = unsafeWriteArray ba i e  instance ArrayElt Double where   type ArrayPtrs Double = Ptr Double+  arrayElt              = ArrayEltRdouble+  {-# INLINE unsafeIndexArrayData #-}   unsafeIndexArrayData (AD_Double ba) i   = unsafeIndexArray ba i-  ptrsOfArrayData (AD_Double ba)          = storableArrayPtr ba-  newArrayData size                       = liftM AD_Double $ unsafeNewArray_ (0,size-1)+  {-# INLINE ptrsOfArrayData #-}+  ptrsOfArrayData (AD_Double ba)          = unsafeUniqueArrayPtr ba+  {-# INLINE touchArrayData #-}+  touchArrayData (AD_Double ba)           = touchUniqueArray ba+  {-# INLINE newArrayData #-}+  newArrayData size                       = AD_Double <$> newArrayData' size+  {-# INLINE unsafeReadArrayData #-}   unsafeReadArrayData (AD_Double ba) i    = unsafeReadArray ba i+  {-# INLINE unsafeWriteArrayData #-}   unsafeWriteArrayData (AD_Double ba) i e = unsafeWriteArray ba i e-  arrayElt                                = ArrayEltRdouble  instance ArrayElt CFloat where   type ArrayPtrs CFloat = Ptr Float+  arrayElt              = ArrayEltRcfloat+  {-# INLINE unsafeIndexArrayData #-}   unsafeIndexArrayData (AD_CFloat ba) i   = CFloat $ unsafeIndexArray ba i-  ptrsOfArrayData (AD_CFloat ba)          = storableArrayPtr ba-  newArrayData size                       = liftM AD_CFloat $ unsafeNewArray_ (0,size-1)+  {-# INLINE ptrsOfArrayData #-}+  ptrsOfArrayData (AD_CFloat ba)          = unsafeUniqueArrayPtr ba+  {-# INLINE touchArrayData #-}+  touchArrayData (AD_CFloat ba)           = touchUniqueArray ba+  {-# INLINE newArrayData #-}+  newArrayData size                       = AD_CFloat <$> newArrayData' size+  {-# INLINE unsafeReadArrayData #-}   unsafeReadArrayData (AD_CFloat ba) i    = CFloat <$> unsafeReadArray ba i+  {-# INLINE unsafeWriteArrayData #-}   unsafeWriteArrayData (AD_CFloat ba) i (CFloat e)     = unsafeWriteArray ba i e-  arrayElt                                = ArrayEltRcfloat  instance ArrayElt CDouble where   type ArrayPtrs CDouble = Ptr Double-  unsafeIndexArrayData (AD_CDouble ba) i   = CDouble $ unsafeIndexArray ba i-  ptrsOfArrayData (AD_CDouble ba)          = storableArrayPtr ba-  newArrayData size                        = liftM AD_CDouble $ unsafeNewArray_ (0,size-1)-  unsafeReadArrayData (AD_CDouble ba) i    = CDouble <$> unsafeReadArray ba i+  arrayElt               = ArrayEltRcdouble+  {-# INLINE unsafeIndexArrayData #-}+  unsafeIndexArrayData (AD_CDouble ba) i  = CDouble $ unsafeIndexArray ba i+  {-# INLINE ptrsOfArrayData #-}+  ptrsOfArrayData (AD_CDouble ba)         = unsafeUniqueArrayPtr ba+  {-# INLINE touchArrayData #-}+  touchArrayData (AD_CDouble ba)          = touchUniqueArray ba+  {-# INLINE newArrayData #-}+  newArrayData size                       = AD_CDouble <$> newArrayData' size+  {-# INLINE unsafeReadArrayData #-}+  unsafeReadArrayData (AD_CDouble ba) i   = CDouble <$> unsafeReadArray ba i+  {-# INLINE unsafeWriteArrayData #-}   unsafeWriteArrayData (AD_CDouble ba) i (CDouble e)     = unsafeWriteArray ba i e-  arrayElt                                 = ArrayEltRcdouble  -- Bool arrays are stored as arrays of bytes. While this is memory inefficient,--- it is better suited to parallel backends than the native Unboxed Bool--- array representation that uses packed bit vectors, as that would require--- atomic operations when writing data necessarily serialising threads.+-- it is better suited to parallel backends than a packed bit-vector+-- representation. -- instance ArrayElt Bool where   type ArrayPtrs Bool = Ptr Word8-  unsafeIndexArrayData (AD_Bool ba) i   = toBool (unsafeIndexArray ba i)-  ptrsOfArrayData (AD_Bool ba)          = storableArrayPtr ba-  newArrayData size                     = liftM AD_Bool $ unsafeNewArray_ (0,size-1)-  unsafeReadArrayData (AD_Bool ba) i    = liftM toBool  $ unsafeReadArray ba i-  unsafeWriteArrayData (AD_Bool ba) i e = unsafeWriteArray ba i (fromBool e)-  arrayElt                              = ArrayEltRbool--{-# INLINE toBool #-}-toBool :: Word8 -> Bool-toBool 0 = False-toBool _ = True--{-# INLINE fromBool #-}-fromBool :: Bool -> Word8-fromBool True  = 1-fromBool False = 0-+  arrayElt            = ArrayEltRbool+  {-# INLINE unsafeIndexArrayData #-}+  unsafeIndexArrayData (AD_Bool ba) i     = toBool (unsafeIndexArray ba i)+  {-# INLINE ptrsOfArrayData #-}+  ptrsOfArrayData (AD_Bool ba)            = unsafeUniqueArrayPtr ba+  {-# INLINE touchArrayData #-}+  touchArrayData (AD_Bool ba)             = touchUniqueArray ba+  {-# INLINE newArrayData #-}+  newArrayData size                       = AD_Bool <$> newArrayData' size+  {-# INLINE unsafeReadArrayData #-}+  unsafeReadArrayData (AD_Bool ba) i      = toBool  <$> unsafeReadArray ba i+  {-# INLINE unsafeWriteArrayData #-}+  unsafeWriteArrayData (AD_Bool ba) i e   = unsafeWriteArray ba i (fromBool e)  -- Unboxed Char is stored as a wide character, which is 4-bytes -- instance ArrayElt Char where   type ArrayPtrs Char = Ptr Char-  unsafeIndexArrayData (AD_Char ba) i   = unsafeIndexArray ba i-  ptrsOfArrayData (AD_Char ba)          = storableArrayPtr ba-  newArrayData size                     = liftM AD_Char $ unsafeNewArray_ (0,size-1)-  unsafeReadArrayData (AD_Char ba) i    = unsafeReadArray ba i-  unsafeWriteArrayData (AD_Char ba) i e = unsafeWriteArray ba i e-  arrayElt                              = ArrayEltRchar+  arrayElt            = ArrayEltRchar+  {-# INLINE unsafeIndexArrayData #-}+  unsafeIndexArrayData (AD_Char ba) i     = unsafeIndexArray ba i+  {-# INLINE ptrsOfArrayData #-}+  ptrsOfArrayData (AD_Char ba)            = unsafeUniqueArrayPtr ba+  {-# INLINE touchArrayData #-}+  touchArrayData (AD_Char ba)             = touchUniqueArray ba+  {-# INLINE newArrayData #-}+  newArrayData size                       = AD_Char <$> newArrayData' size+  {-# INLINE unsafeReadArrayData #-}+  unsafeReadArrayData (AD_Char ba) i      = unsafeReadArray ba i+  {-# INLINE unsafeWriteArrayData #-}+  unsafeWriteArrayData (AD_Char ba) i e   = unsafeWriteArray ba i e  instance ArrayElt CChar where   type ArrayPtrs CChar = Ptr HTYPE_CCHAR-  unsafeIndexArrayData (AD_CChar ba) i   = CChar $ unsafeIndexArray ba i-  ptrsOfArrayData (AD_CChar ba)          = storableArrayPtr ba-  newArrayData size                      = liftM AD_CChar $ unsafeNewArray_ (0,size-1)-  unsafeReadArrayData (AD_CChar ba) i    = CChar <$> unsafeReadArray ba i+  arrayElt             = ArrayEltRcchar+  {-# INLINE unsafeIndexArrayData #-}+  unsafeIndexArrayData (AD_CChar ba) i    = CChar $ unsafeIndexArray ba i+  {-# INLINE ptrsOfArrayData #-}+  ptrsOfArrayData (AD_CChar ba)           = unsafeUniqueArrayPtr ba+  {-# INLINE touchArrayData #-}+  touchArrayData (AD_CChar ba)            = touchUniqueArray ba+  {-# INLINE newArrayData #-}+  newArrayData size                       = AD_CChar <$> newArrayData' size+  {-# INLINE unsafeReadArrayData #-}+  unsafeReadArrayData (AD_CChar ba) i     = CChar <$> unsafeReadArray ba i+  {-# INLINE unsafeWriteArrayData #-}   unsafeWriteArrayData (AD_CChar ba) i (CChar e)     = unsafeWriteArray ba i e-  arrayElt                               = ArrayEltRcchar  instance ArrayElt CSChar where   type ArrayPtrs CSChar = Ptr Int8+  arrayElt              = ArrayEltRcschar+  {-# INLINE unsafeIndexArrayData #-}   unsafeIndexArrayData (AD_CSChar ba) i   = CSChar $ unsafeIndexArray ba i-  ptrsOfArrayData (AD_CSChar ba)          = storableArrayPtr ba-  newArrayData size                       = liftM AD_CSChar $ unsafeNewArray_ (0,size-1)+  {-# INLINE ptrsOfArrayData #-}+  ptrsOfArrayData (AD_CSChar ba)          = unsafeUniqueArrayPtr ba+  {-# INLINE touchArrayData #-}+  touchArrayData (AD_CSChar ba)           = touchUniqueArray ba+  {-# INLINE newArrayData #-}+  newArrayData size                       = AD_CSChar <$> newArrayData' size+  {-# INLINE unsafeReadArrayData #-}   unsafeReadArrayData (AD_CSChar ba) i    = CSChar <$> unsafeReadArray ba i+  {-# INLINE unsafeWriteArrayData #-}   unsafeWriteArrayData (AD_CSChar ba) i (CSChar e)     = unsafeWriteArray ba i e-  arrayElt                                = ArrayEltRcschar  instance ArrayElt CUChar where   type ArrayPtrs CUChar = Ptr Word8+  arrayElt              = ArrayEltRcuchar+  {-# INLINE unsafeIndexArrayData #-}   unsafeIndexArrayData (AD_CUChar ba) i   = CUChar $ unsafeIndexArray ba i-  ptrsOfArrayData (AD_CUChar ba)          = storableArrayPtr ba-  newArrayData size                       = liftM AD_CUChar $ unsafeNewArray_ (0,size-1)+  {-# INLINE ptrsOfArrayData #-}+  ptrsOfArrayData (AD_CUChar ba)          = unsafeUniqueArrayPtr ba+  {-# INLINE touchArrayData #-}+  touchArrayData (AD_CUChar ba)           = touchUniqueArray ba+  {-# INLINE newArrayData #-}+  newArrayData size                       = AD_CUChar <$> newArrayData' size+  {-# INLINE unsafeReadArrayData #-}   unsafeReadArrayData (AD_CUChar ba) i    = CUChar <$> unsafeReadArray ba i+  {-# INLINE unsafeWriteArrayData #-}   unsafeWriteArrayData (AD_CUChar ba) i (CUChar e)     = unsafeWriteArray ba i e-  arrayElt                                = ArrayEltRcuchar  instance (ArrayElt a, ArrayElt b) => ArrayElt (a, b) where-  type ArrayPtrs (a, b)                = (ArrayPtrs a, ArrayPtrs b)-  unsafeIndexArrayData (AD_Pair a b) i = (unsafeIndexArrayData a i, unsafeIndexArrayData b i)-  ptrsOfArrayData (AD_Pair a b)        = (ptrsOfArrayData a, ptrsOfArrayData b)-  newArrayData size-    = do-        a <- newArrayData size-        b <- newArrayData size-        return $ AD_Pair a b-  unsafeReadArrayData (AD_Pair a b) i-    = do-        x <- unsafeReadArrayData a i-        y <- unsafeReadArrayData b i-        return (x, y)-  unsafeWriteArrayData (AD_Pair a b) i (x, y)-    = do-        unsafeWriteArrayData a i x-        unsafeWriteArrayData b i y-  unsafeFreezeArrayData (AD_Pair a b)-    = do-        a' <- unsafeFreezeArrayData a-        b' <- unsafeFreezeArrayData b-        return $ AD_Pair a' b'-  ptrsOfMutableArrayData (AD_Pair a b)-    = do-        aptr <- ptrsOfMutableArrayData a-        bptr <- ptrsOfMutableArrayData b-        return (aptr, bptr)-  arrayElt = ArrayEltRpair arrayElt arrayElt+  type ArrayPtrs (a, b) = (ArrayPtrs a, ArrayPtrs b)+  arrayElt              = ArrayEltRpair arrayElt arrayElt+  {-# INLINE unsafeIndexArrayData #-}+  unsafeIndexArrayData (AD_Pair a b) i        = (unsafeIndexArrayData a i, unsafeIndexArrayData b i)+  {-# INLINE ptrsOfArrayData #-}+  ptrsOfArrayData (AD_Pair a b)               = (ptrsOfArrayData a, ptrsOfArrayData b)+  {-# INLINE touchArrayData #-}+  touchArrayData (AD_Pair a b)                = touchArrayData a >> touchArrayData b+  {-# INLINE unsafeWriteArrayData #-}+  unsafeWriteArrayData (AD_Pair a b) i (x, y) = unsafeWriteArrayData a i x >> unsafeWriteArrayData b i y+  {-# INLINE newArrayData #-}+  newArrayData size                           = AD_Pair <$> newArrayData size <*> newArrayData size+  {-# INLINE unsafeFreezeArrayData #-}+  unsafeFreezeArrayData (AD_Pair a b)         = AD_Pair <$> unsafeFreezeArrayData a <*> unsafeFreezeArrayData b+  {-# INLINE unsafeReadArrayData #-}+  unsafeReadArrayData  (AD_Pair a b) i        = (,) <$> unsafeReadArrayData a i <*> unsafeReadArrayData b i+  {-# INLINE ptrsOfMutableArrayData #-}+  ptrsOfMutableArrayData (AD_Pair a b)        = (,) <$> ptrsOfMutableArrayData a <*> ptrsOfMutableArrayData b --- |Safe combination of creating and fast freezing of array data.----{-# INLINE runArrayData #-}-runArrayData :: ArrayElt e-             => IO (MutableArrayData e, e) -> (ArrayData e, e)-runArrayData st = unsafePerformIO $ do-                    (mad, r) <- st-                    return (mad, r)  -- Array tuple operations -- ---------------------- +{-# INLINE fstArrayData #-} fstArrayData :: ArrayData (a, b) -> ArrayData a fstArrayData (AD_Pair x _) = x +{-# INLINE sndArrayData #-} sndArrayData :: ArrayData (a, b) -> ArrayData b sndArrayData (AD_Pair _ y) = y +{-# INLINE pairArrayData #-} pairArrayData :: ArrayData a -> ArrayData b -> ArrayData (a, b) pairArrayData = AD_Pair  - -- Auxiliary functions -- ------------------- --- Returns the element of an immutable array at the specified index.+{-# INLINE toBool #-}+toBool :: Word8 -> Bool+toBool 0 = False+toBool _ = True++{-# INLINE fromBool #-}+fromBool :: Bool -> Word8+fromBool True  = 1+fromBool False = 0++-- | Safe combination of creating and fast freezing of array data. ----- This does no bounds checking unless you configured with -funsafe-checks. This--- is usually OK, since the functions that convert from multidimensional to--- linear indexing do bounds checking by default.+{-# INLINE runArrayData #-}+runArrayData+    :: IO (MutableArrayData e, e)+    -> (ArrayData e, e)+runArrayData st = unsafePerformIO $ do+  (mad, r) <- st+  return (mad, r)++-- Returns the element of an immutable array at the specified index. This does+-- no bounds checking. -- {-# INLINE unsafeIndexArray #-}-unsafeIndexArray :: MArray a e IO => a Int e -> Int -> e-unsafeIndexArray a i = unsafePerformIO $ unsafeReadArray a i+unsafeIndexArray :: Storable e => UniqueArray e -> Int -> e+unsafeIndexArray ua i = unsafePerformIO $! unsafeReadArray ua i --- Read an element from a mutable array.------ This does no bounds checking unless you configured with -funsafe-checks. This--- is usually OK, since the functions that convert from multidimensional to--- linear indexing do bounds checking by default.+-- Read an element from a mutable array at the given index. This does no bounds+-- checking. -- {-# INLINE unsafeReadArray #-}-unsafeReadArray :: MArray a e m => a Int e -> Int -> m e-#ifdef ACCELERATE_UNSAFE_CHECKS-unsafeReadArray = MArray.readArray-#else-unsafeReadArray = MArray.unsafeRead-#endif+unsafeReadArray :: Storable e => UniqueArray e -> Int -> IO e+unsafeReadArray ua i =+  withUniqueArrayPtr ua $ \ptr -> peekElemOff ptr i --- Write an element into a mutable array.------ This does no bounds checking unless you configured with -funsafe-checks. This--- is usually OK, since the functions that convert from multidimensional to--- linear indexing do bounds checking by default.+-- Write an element into a mutable array at the given index. This does no bounds+-- checking. -- {-# INLINE unsafeWriteArray #-}-unsafeWriteArray :: MArray a e m => a Int e -> Int -> e -> m ()-#ifdef ACCELERATE_UNSAFE_CHECKS-unsafeWriteArray = MArray.writeArray-#else-unsafeWriteArray = MArray.unsafeWrite-#endif+unsafeWriteArray :: Storable e => UniqueArray e -> Int -> e -> IO ()+unsafeWriteArray ua i e =+  withUniqueArrayPtr ua $ \ptr -> pokeElemOff ptr i e --- Obtains a pointer to the payload of an storable array.+-- Allocate a new array with enough storage to hold the given number of+-- elements. ---{-# INLINE storableArrayPtr #-}-storableArrayPtr :: StorableArray i a -> Ptr a-storableArrayPtr (StorableArray _ _ _ fp) = unsafeForeignPtrToPtr fp+-- The array is uninitialised and, in particular, allocated lazily. The latter+-- is important because it means that for backends that have discrete memory+-- spaces (e.g. GPUs), we will not increase host memory pressure simply to track+-- intermediate arrays that contain meaningful data only on the device.+--+{-# INLINE newArrayData' #-}+newArrayData' :: forall e. Storable e => Int -> IO (UniqueArray e)+newArrayData' size+  = $internalCheck "newArrayData" "size must be >= 0" (size >= 0)+  $ newUniqueArray <=< unsafeInterleaveIO $ do+      let bytes = size * sizeOf (undefined :: e)+      new <- readIORef __mallocForeignPtrBytes+      ptr <- new bytes+      traceIO dump_gc $ printf "gc: allocated new host array (size=%d, ptr=%s)" bytes (show ptr)+      return (castForeignPtr ptr)++-- | Register the given function as the callback to use to allocate new array+-- data on the host containing the specified number of bytes. The returned array+-- must be pinned (with respect to Haskell's GC), so that it can be passed to+-- foreign code.+--+registerForeignPtrAllocator+    :: (Int -> IO (ForeignPtr Word8))+    -> IO ()+registerForeignPtrAllocator new = do+  traceIO dump_gc "registering new array allocator"+  atomicWriteIORef __mallocForeignPtrBytes new++{-# NOINLINE __mallocForeignPtrBytes #-}+__mallocForeignPtrBytes :: IORef (Int -> IO (ForeignPtr Word8))+__mallocForeignPtrBytes = unsafePerformIO $! newIORef mallocPlainForeignPtrBytesAligned++-- | Allocate the given number of bytes with 16-byte alignment. This is+-- essential for SIMD instructions.+--+-- Additionally, we return a plain ForeignPtr, which unlike a regular ForeignPtr+-- created with 'mallocForeignPtr' carries no finalisers. It is an error to try+-- to add a finaliser to the plain ForeignPtr. For our purposes this is fine,+-- since in Accelerate finalisers are handled using Lifetime+--+mallocPlainForeignPtrBytesAligned :: Int -> IO (ForeignPtr a)+mallocPlainForeignPtrBytesAligned (I# size) = IO $ \s ->+  case newAlignedPinnedByteArray# size 16# s of+    (# s', mbarr# #) -> (# s', ForeignPtr (byteArrayContents# (unsafeCoerce# mbarr#)) (PlainPtr mbarr#) #) 
+ Data/Array/Accelerate/Array/Lifted.hs view
@@ -0,0 +1,283 @@+{-# LANGUAGE ConstraintKinds       #-}+{-# LANGUAGE DeriveDataTypeable    #-}+{-# LANGUAGE GADTs                 #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PatternGuards         #-}+{-# LANGUAGE RankNTypes            #-}+{-# LANGUAGE ScopedTypeVariables   #-}+{-# LANGUAGE TypeFamilies          #-}+{-# LANGUAGE UndecidableInstances  #-}+-- |+-- Module      : Data.Array.Accelerate.Array.Lifted+-- Copyright   : [2012..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell, Robert Clifton-Everest+-- License     : BSD3+--+-- Maintainer  : Robert Clifton-Everest <robertce@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- Lifted array representation. Vector of arrays represented as segmented+-- vectors.+--++module Data.Array.Accelerate.Array.Lifted (++  Vector'(..), LiftedArray,++  LiftedTupleRepr,++  IsConstrained(..),++  isArraysFlat,++  elements', shapes', empty', length', drop', vec2Vec', fromList', toList'++) where++import Prelude                                                  hiding ( concat )+import Data.Typeable++-- friends+import Data.Array.Accelerate.Product+import Data.Array.Accelerate.Array.Sugar+import qualified Data.Array.Accelerate.Array.Representation     as Repr+++-- Lifted arrays+-- ----------------+--+-- We specify a special new type of surface tuple to represent the lifted version of members of the+-- `Arrays' class. We do this in order to convince the type checker that the lifted arrays or tuples+-- of arrays, are still members of the 'Arrays' class.++newtype Vector' a = Vector' (LiftedRepr (ArrRepr a) a)+  deriving Typeable++type family LiftedRepr r a where+  LiftedRepr ()     ()                 = ((),Scalar Int)+  LiftedRepr (Array sh e) (Array sh e) = (((),Segments sh), Vector e)+  LiftedRepr (l,r) a                   = LiftedTupleRepr (TupleRepr a)++type family LiftedTupleRepr t :: *+type instance LiftedTupleRepr () = ()+type instance LiftedTupleRepr (b, a) = (LiftedTupleRepr b, Vector' a)++type LiftedArray sh e = Vector' (Array sh e)++instance Arrays t => IsProduct Arrays (Vector' t) where+  type ProdRepr (Vector' t) = LiftedRepr (ArrRepr t) t+  fromProd _ (Vector' t) = t+  toProd _ = Vector'+  prod _ _ = case flavour (undefined :: t) of+                ArraysFunit  -> ProdRsnoc ProdRunit+                ArraysFarray -> ProdRsnoc (ProdRsnoc ProdRunit)+                ArraysFtuple -> tup $ prod (Proxy :: Proxy Arrays) (undefined :: t)+    where+      tup :: forall a. ProdR Arrays a -> ProdR Arrays (LiftedTupleRepr a)+      tup ProdRunit     = ProdRunit+      tup (ProdRsnoc t) = swiz+        where+          swiz :: forall l r. (a ~ (l,r), Arrays r) => ProdR Arrays (LiftedTupleRepr a)+          swiz | IsC <- isArraysFlat (undefined :: r)+               = ProdRsnoc (tup t)+++type instance ArrRepr (Vector' a) = ArrRepr (TupleRepr (Vector' a))+++instance (Arrays t, Typeable (ArrRepr (Vector' t))) => Arrays (Vector' t) where+  arrays _ = arrs (prod (Proxy :: Proxy Arrays) (undefined :: Vector' t))+    where+      arrs :: forall a. ProdR Arrays a -> ArraysR (ArrRepr a)+      arrs ProdRunit     = ArraysRunit+      arrs (ProdRsnoc t) = ArraysRpair (ArraysRpair ArraysRunit (arrs t)) (arrays t')+        where t' :: (a ~ (l,r)) => r+              t' = undefined+  flavour _ = case flavour (undefined :: t) of+                ArraysFunit  -> ArraysFtuple+                ArraysFarray -> ArraysFtuple+                ArraysFtuple | ProdRsnoc _ <- prod (Proxy :: Proxy Arrays) (undefined::t)+                             -> ArraysFtuple+                             | otherwise -> error "Absurd"+  --+  fromArr (Vector' vt) = fa (prod (Proxy :: Proxy Arrays) (undefined :: Vector' t)) vt+    where+      fa :: forall a. ProdR Arrays a -> a -> ArrRepr a+      fa ProdRunit     ()    = ()+      fa (ProdRsnoc t) (l,a) = (((), fa t l), fromArr a)+  toArr = Vector' . ta (prod (Proxy :: Proxy Arrays) (undefined :: Vector' t))+    where+      ta :: forall a. ProdR Arrays a -> ArrRepr a -> a+      ta ProdRunit     ()         = ()+      ta (ProdRsnoc t) (((),l),a) = (ta t l, toArr a)++data IsConstrained c where+  IsC :: c => IsConstrained c++type IsTypeableArrRepr t = IsConstrained (Typeable (ArrRepr t))++type IsArraysFlat t = IsConstrained (Arrays (Vector' t))++isTypeableArrRepr :: forall t. Arrays t => {- dummy -} t -> IsTypeableArrRepr (Vector' t)+isTypeableArrRepr _ =+  case flavour (undefined :: t) of+    ArraysFunit  -> IsC+    ArraysFarray -> IsC+    ArraysFtuple | IsC <- isT (prod (Proxy :: Proxy Arrays) (undefined :: Vector' t))+                 -> IsC+  where+    isT :: ProdR Arrays t' -> IsTypeableArrRepr t'+    isT ProdRunit                    = IsC+    isT (ProdRsnoc t) | IsC <- isT t = IsC++isArraysFlat :: forall t. Arrays t => {- dummy -} t -> IsArraysFlat t+isArraysFlat t = case flavour t of+                   ArraysFunit  -> IsC+                   ArraysFtuple | IsC <- isTypeableArrRepr t+                                -> IsC+                   ArraysFarray -> IsC+++-- Useful helper-functions (not exported)+-- --------------------------------------++scalar :: Elt a => a -> Scalar a+scalar n = fromList Z [n]++emptyVec :: Elt a => Vector a+emptyVec = fromList (Z :. (0 :: Int)) []++flatten :: Array sh e -> Vector e+flatten (Array sh e) = Array ((), Repr.size sh) e+++-- Useful helper-functions for Vector'+-- ----------------------------------++-- Get all the elements. O(1).+--+elements' :: Vector' (Array sh e) -> Vector e+elements' (Vector' (_, elts)) = elts++-- Get all the shapes. O(1).+--+shapes' :: Vector' (Array sh a) -> Vector sh+shapes' (Vector' (((), shapes), _)) = shapes++-- The empty Vector'. O(1).+empty' :: forall a. Arrays a => Vector' a+empty' = Vector' $+  case flavour (undefined :: a) of+    ArraysFunit  -> ((), scalar 0)+    ArraysFarray -> (((), emptyVec), emptyVec)+    ArraysFtuple -> tup (prod (Proxy :: Proxy Arrays) (undefined :: a))+  where+    tup :: forall t. ProdR Arrays t -> LiftedTupleRepr t+    tup ProdRunit = ()+    tup (ProdRsnoc t) = (tup t, empty')++-- Number of arrays in Vector'. O(1).+--+length' :: forall a. Arrays a => Vector' a -> Int+length' (Vector' x) =+  case flavour (undefined :: a) of+    ArraysFunit  | ((), n) <- x+                 -> n ! Z+    ArraysFarray | (((), Array ((), n) _), _) <- x+                 -> n+    ArraysFtuple -> tup (prod (Proxy :: Proxy Arrays) (undefined :: a)) x+  where+    tup :: forall t. ProdR Arrays t -> LiftedTupleRepr t -> Int+    tup ProdRunit () = error "unreachable"+    tup (ProdRsnoc _) (_, b) = length' b++-- Drop a number of arrays from a Vector'.+--+drop' :: forall a. Arrays a+      -- Implementation specific drop for basic vectors:+      => (forall e. Elt e => Int -> Vector e -> Vector e)+      -- Implementation specific segments-to-offsets:+      -> (forall sh. Shape sh => Segments sh -> Vector Int)+      -> Int -> Vector' a -> Vector' a+drop' dropVec s2o k (Vector' x) = Vector' $+  case flavour (undefined :: a) of+    ArraysFunit |  ((), n                         ) <- x+                -> ((), scalar (n ! Z - k `max` 0))+    ArraysFarray | (((), segs), vals) <- x+                 , Array ((), n) _ <- segs+                 , k < n+                 -> let offsets = s2o segs+                        k' = offsets ! (Z :. k)+                    in (((), dropVec k segs), dropVec k' vals)+    ArraysFarray -> (((), emptyVec), emptyVec)+    ArraysFtuple -> tup (prod (Proxy :: Proxy Arrays) (undefined :: a)) x+  where+    tup :: forall t. ProdR Arrays t -> LiftedTupleRepr t -> LiftedTupleRepr t+    tup ProdRunit () = ()+    tup (ProdRsnoc t) (a, b) = (tup t a, drop' dropVec s2o k b)++-- Convert a vector to a Vector' of scalars.+--+vec2Vec' :: Elt e => Vector e -> Vector' (Scalar e)+vec2Vec' v = Vector' (((), undefined), v) -- TODO undefined Vector of Z's?++toList' :: forall a. Arrays a+        -- Implementation-specific fetchAll:+        => (forall sh e. (Shape sh, Elt e) => Segments sh -> Vector e -> [Array sh e])+        -> Vector' a -> [a]+toList' fetchAll (Vector' x) =+  case flavour (undefined :: a) of+    ArraysFunit | ((), n) <- x -> replicate (n ! Z) ()+    ArraysFarray | (((), lens), vals) <- x+                 -> fetchAll lens vals+    ArraysFtuple -> map (toProd (Proxy :: Proxy Arrays)) (tup (prod (Proxy :: Proxy Arrays) (undefined :: a)) x)+  where+    tup :: forall t. ProdR Arrays t -> LiftedTupleRepr t -> [t]+    tup ProdRunit () = repeat ()+    tup (ProdRsnoc t) (a, b) = tup t a `zip` toList' fetchAll b++fromList' :: forall a. Arrays a+          -- Implementation specific concat+          => (forall e. Elt e => [Vector e] -> Vector e)+          -> [a] -> Vector' a+fromList' concat xs = Vector' $+  case flavour (undefined :: a) of+    ArraysFunit -> ((), scalar (length xs))+    ArraysFarray ->+      let segs = map shape xs+          vals = concat (map flatten xs)+      in (((), fromList (Z :. length segs) segs), vals)+    ArraysFtuple -> tup (prod (Proxy :: Proxy Arrays) (undefined :: a)) (map (fromProd (Proxy :: Proxy Arrays)) xs)+  where+    tup :: forall t. ProdR Arrays t -> [t] -> LiftedTupleRepr t+    tup ProdRunit _     = ()+    tup (ProdRsnoc t) a = (tup t (Prelude.map fst a), fromList' concat (map snd a))++{-+map' :: (Arrays a, Arrays b)+     => (forall e. Elt e => [Vector e] -> Vector e)+     -> (forall sh e. (Shape sh, Elt e) => Segments sh -> Vector e -> [Array sh e])+     -> (a -> b) -> Vector' a -> Vector' b+map' concat fetchAll f x = fromList' concat $ map f (toList' fetchAll x)+-}++{-+helper :: forall a r. Arrays a+       => (Scalar Int -> r ())+       -> (forall sh e. (Shape sh, Elt e) => Segments sh -> Vector e -> r (Array sh e))+       -> r ()+       -> (forall t s. r t -> r s -> r (t, s))+       -> (forall t. r (ProdRepr t) -> r t)+       -> Vector' a -> r a+helper units arr unit pair fix (Vector' x) =+  case flavour (undefined :: a) of+    ArraysFunit | ((), n) <- x -> units n+    ArraysFarray | (((), lens), vals) <- x+                 -> arr lens vals+    ArraysFtuple -> fix $ tup (prod (Proxy :: Proxy Arrays) (undefined :: a)) x+  where+    tup :: forall t. ProdR Arrays t -> LiftedTupleRepr t -> r t+    tup ProdRunit () = unit+    tup (ProdRsnoc t) (x, y) = tup t x `pair` helper units arr unit pair fix y+-}+
+ Data/Array/Accelerate/Array/Remote.hs view
@@ -0,0 +1,26 @@+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.Array.Remote+-- Copyright   : [2015..2017] Manuel M T Chakravarty, Gabriele Keller, Robert Clifton-Everest+--               [2016..2017] Trevor L. McDonell+-- License     : BSD3+--+-- Maintainer  : Robert Clifton-Everest <robertce@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- Umbrella module for the remote memory management facilities. To implement an+-- LRU cache for your backend, provide an instance of the 'RemoteMemory' class,+-- and, if required, specialise or overload the LRU functions to your particular+-- memory table types.+--++module Data.Array.Accelerate.Array.Remote (++  module Remote++) where++import Data.Array.Accelerate.Array.Remote.Class         as Remote+import Data.Array.Accelerate.Array.Remote.LRU           as Remote+
+ Data/Array/Accelerate/Array/Remote/Class.hs view
@@ -0,0 +1,81 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE TypeFamilies    #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.Array.Remote.Class+-- Copyright   : [2015..2017] Manuel M T Chakravarty, Gabriele Keller, Robert Clifton-Everest+--               [2016..2017] Trevor L. McDonell+-- License     : BSD3+--+-- Maintainer  : Robert Clifton-Everest <robertce@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- This module define a class of operations over pointers in a remote memory+-- space. Backends provide an instance of this class, and then can use (or+-- extend upon) one of the following modules in order to manage the remote+-- memory:+--+-- * 'Data.Array.Accelerate.Array.Remote.Table': basic, unmanaged memory tables,+--   mapping accelerate arrays on the host to the corresponding array in the+--   remote memory space.+--+-- * 'Data.Array.Accelerate.Array.Remote.LRU': managed memory tables which+--   additionally evict old entries from the device if the remote memory is+--   exhausted.+--++module Data.Array.Accelerate.Array.Remote.Class (++  RemoteMemory(..), PrimElt++) where++import Data.Array.Accelerate.Array.Data++import Control.Applicative+import Control.Monad.Catch+import Data.Int+import Data.Word+import Data.Typeable+import Foreign.Ptr+import Foreign.Storable+import Prelude+++-- | Matches array element types to primitive types.+--+type PrimElt e a = (ArrayElt e, Storable a, ArrayPtrs e ~ Ptr a, Typeable e, Typeable a)++-- | Accelerate backends can provide an instance of this class in order to take+-- advantage of the automated memory managers we provide as part of the base+-- package.+--+class (Applicative m, Monad m, MonadCatch m, MonadMask m) => RemoteMemory m where++  -- | Pointers into this particular remote memory.+  type RemotePtr m :: * -> *++  -- | Attempt to allocate the given number of bytes in the remote memory space.+  -- Returns Nothing on failure.+  mallocRemote :: Int -> m (Maybe (RemotePtr m Word8))++  -- | Copy the given number of elements from the host array into remote memory.+  pokeRemote :: PrimElt e a => Int -> RemotePtr m a -> ArrayData e -> m ()++  -- | Copy the given number of elements from remote memory to the host array.+  peekRemote :: PrimElt e a => Int -> RemotePtr m a -> MutableArrayData e -> m ()++  -- | Cast a remote pointer.+  castRemotePtr :: proxy m -> RemotePtr m a -> RemotePtr m b++  -- | Returns the total remote memory available in bytes.+  totalRemoteMem :: m Int64++  -- | Returns, in bytes, the available remote memory.+  availableRemoteMem :: m Int64++  -- | The chunk allocation size (bytes).+  remoteAllocationSize :: m Int+  remoteAllocationSize = return 1024+
+ Data/Array/Accelerate/Array/Remote/LRU.hs view
@@ -0,0 +1,399 @@+{-# LANGUAGE BangPatterns        #-}+{-# LANGUAGE ConstraintKinds     #-}+{-# LANGUAGE DoAndIfThenElse     #-}+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE PatternGuards       #-}+{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell     #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.Array.Remote.Cache+-- Copyright   : [2015..2017] Manuel M T Chakravarty, Gabriele Keller, Robert Clifton-Everest+--               [2016..2017] Trevor L. McDonell+-- License     : BSD3+--+-- Maintainer  : Robert Clifton-Everest <robertce@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- This module extends the memory tables provided by+-- 'Data.Array.Accelerate.Array.Remote.Table' with an LRU caching policy that+-- evicts old arrays from the remote memory space once it runs out of memory.+-- Consequently, use of this module requires the backend client to keep track of+-- which remote arrays are currently being used, so that they will not be+-- evicted. See: 'withRemote' for more details on this requirement.+--+module Data.Array.Accelerate.Array.Remote.LRU (++  -- Tables for host/device memory associations+  MemoryTable, new, withRemote, malloc, free, insertUnmanaged, reclaim,++  -- Asynchronous tasks+  Task(..)++) where++import Data.Functor+import Data.Maybe                                               ( isNothing )+import Data.Proxy+import Control.Monad                                            ( filterM )+import Control.Monad.Catch+import Control.Monad.IO.Class                                   ( MonadIO, liftIO )+import Control.Concurrent.MVar                                  ( MVar, newMVar, takeMVar, putMVar, mkWeakMVar )+import System.CPUTime+import System.Mem.Weak                                          ( Weak, deRefWeak, finalize )+import Prelude                                                  hiding ( lookup )++import qualified Data.HashTable.IO                              as HT++import qualified Data.Array.Accelerate.Debug                    as D+import Data.Array.Accelerate.Error                              ( internalError )+import Data.Array.Accelerate.Array.Data                         ( ArrayData, touchArrayData )+import Data.Array.Accelerate.Array.Remote.Class+import Data.Array.Accelerate.Array.Remote.Table                 ( StableArray, makeWeakArrayData )+import qualified Data.Array.Accelerate.Array.Remote.Table       as Basic+++-- We build cached memory tables on top of a basic memory table.+--+-- A key invariant is that the arrays in the MemoryTable are a subset of the+-- arrays in the UseTable. The UseTable reflects all arrays that have ever been+-- in the cache.+--+data MemoryTable p task = MemoryTable {-# UNPACK #-} !(Basic.MemoryTable p)+                                      {-# UNPACK #-} !(UseTable task)+                                      {-# UNPACK #-} !(Weak (UseTable task))++type UT task            = HT.BasicHashTable StableArray (Used task)+type UseTable task      = MVar (UT task)++data Status = Clean     -- Array in remote memory matches array in host memory.+            | Dirty     -- Array in remote memory has been modified.+            | Unmanaged -- Array in remote memory was injected by FFI, so we+                        -- cannot remove it under any circumstance.+            | Evicted   -- Array has been evicted from remote memory+            deriving Eq++type Timestamp = Integer++data Used task where+  Used :: PrimElt e a+       => !Timestamp+       -> !Status+       -> {-# UNPACK #-} !Int                   -- Use count+       -> ![task]                               -- Asynchronous tasks using the array+       -> {-# UNPACK #-} !Int                   -- Array size+       -> {-# UNPACK #-} !(Weak (ArrayData e))+       -> Used task++-- |A Task represents a process executing asynchronously that can be polled for+-- its status. This is necessary for backends that work asynchronously (i.e.+-- the CUDA backend). If a backend is synchronous, the () instance can be used.+--+class Task task where+  -- |Returns true when the task has finished.+  completed :: task -> IO Bool++instance Task () where+  completed () = return True++-- |Create a new memory cache from host to remote arrays.+--+-- The function supplied should be the `free` for the remote pointers being+-- stored. This function will be called by the GC, which typically runs on a+-- different thread. Unlike the `free` in `RemoteMemory`, this function cannot+-- depend on any state.+--+new :: (forall a. ptr a -> IO ()) -> IO (MemoryTable ptr task)+new release = do+  mt        <- Basic.new release+  utbl      <- HT.new+  ref       <- newMVar utbl+  weak_utbl <- mkWeakMVar ref (cache_finalizer utbl)+  return    $! MemoryTable mt ref weak_utbl++-- |Perform some action that requires the remote pointer corresponding to+-- the given array. Returns `Nothing` if the array have NEVER been in the+-- cache. If the array was previously in the cache, but was evicted due to its+-- age, then the array will be copied back from host memory.+--+-- The continuation passed as the third argument needs to obey some precise+-- properties. As with all bracketed functions, the supplied remote pointer must+-- not leak out of the function, as it is only guaranteed to be valid within it.+-- If it is required that it does leak (e.g. the backend is uses concurrency to+-- interleave execution of different parts of the program), then `completed` on+-- the returned task should not return true until it is guaranteed there are no+-- more accesses of the remote pointer.+--+withRemote+    :: forall task m a b c. (PrimElt a b, Task task, RemoteMemory m, MonadIO m, Functor m)+    => MemoryTable (RemotePtr m) task+    -> ArrayData a+    -> (RemotePtr m b -> m (task, c))+    -> m (Maybe c)+withRemote (MemoryTable !mt !ref _) !arr run = do+  key <- Basic.makeStableArray arr+  mp  <- withMVar' ref $ \utbl -> do+    mu <- liftIO $ HT.lookup utbl key+    case mu of+      Nothing -> do message ("withRemote/array has never been malloc'd: " ++ show key)+                    return Nothing+      Just u  -> do+        mp <- liftIO $ do HT.insert utbl key (incCount u)+                          Basic.lookup mt arr+        case mp of+          Nothing | isEvicted u -> Just <$> copy utbl (incCount u)+          Just p                -> return (Just p)+          _                     -> do message ("lost array " ++ show key)+                                      $internalError "withRemote" "non-evicted array has been lost"+  --+  case mp of+    Just p  -> Just <$> run' p+    Nothing -> return Nothing -- The array was never in the table.+  where+    updateTask :: Maybe (Used task) -> task -> IO (Used task)+    updateTask mu task = do+      ts  <- getCPUTime+      case mu of+        Nothing -> $internalError "withRemote" "Invariant violated"+        Just (Used _ status count tasks n weak_arr) -> do+          tasks'  <- cleanUses tasks+          return (Used ts status (count - 1) (task : tasks') n weak_arr)++    copy :: UT task -> Used task -> m (RemotePtr m b)+    copy utbl (Used ts _ count tasks n weak_arr) = do+      message "withRemote/reuploading-evicted-array"+      p <- mallocWithUsage mt utbl arr (Used ts Clean count tasks n weak_arr)+      pokeRemote n p arr+      return p++    run' :: RemotePtr m b -> m c+    run' p = do+      key <- Basic.makeStableArray arr+      message ("withRemote/using: " ++ show key)+      (task, c) <- run p+      withMVar' ref $ \utbl -> liftIO $ do+        mu       <- HT.lookup utbl key+        u        <- updateTask mu task+        HT.insert utbl key u+      liftIO $ touchArrayData arr+      return c+++-- | Allocate a new device array to be associated with the given host-side array.+-- This has similar behaviour to malloc in Data.Array.Accelerate.Array.Memory.Table+-- but also will copy remote arrays back to main memory in order to make space.+--+-- The third argument indicates that the array should be considered frozen.+-- That is to say the array arrays contents will never change. In the event that+-- the array has to be evicted from the remote memory, the copy already residing+-- in host memory should be considered valid.+--+-- If malloc is called on an array that is already contained within the cache,+-- it becomes a no-op.+--+-- On return, 'True' indicates that we allocated some remote memory, and 'False'+-- indicates that we did not need to.+--+malloc :: forall a e m task. (PrimElt e a, RemoteMemory m, MonadIO m, Task task)+       => MemoryTable (RemotePtr m) task+       -> ArrayData e+       -> Bool                               -- ^True if host array is frozen.+       -> Int+       -> m Bool+malloc (MemoryTable mt ref weak_utbl) !ad !frozen !n = do+  ts  <- liftIO $ getCPUTime+  key <- Basic.makeStableArray ad+  --+  let status = if frozen+                 then Clean+                 else Dirty+  --+  withMVar' ref $ \utbl -> do+    mu <- liftIO $ HT.lookup utbl key+    if isNothing mu+      then do+        weak_arr <- liftIO $ makeWeakArrayData ad ad (Just $ finalizer key weak_utbl)+        _        <- mallocWithUsage mt utbl ad (Used ts status 0 [] n weak_arr)+        return True+      else+        return False++mallocWithUsage+    :: forall a e m task. (PrimElt e a, RemoteMemory m, MonadIO m, Task task)+    => Basic.MemoryTable (RemotePtr m)+    -> UT task+    -> ArrayData e+    -> Used task+    -> m (RemotePtr m a)+mallocWithUsage !mt utbl !ad !usage@(Used _ _ _ _ n _) = malloc'+  where+    malloc' = do+      mp <- Basic.malloc mt ad n :: m (Maybe (RemotePtr m a))+      case mp of+        Nothing -> do+          success <- evictLRU utbl mt+          if success then malloc' else $internalError "malloc" "Remote memory exhausted"+        Just p -> liftIO $ do+          key <- Basic.makeStableArray ad+          HT.insert utbl key usage+          return p++evictLRU :: forall m task. (RemoteMemory m, MonadIO m, Task task)+         => UT task+         -> Basic.MemoryTable (RemotePtr m)+         -> m Bool+evictLRU utbl mt = trace "evictLRU/evicting-eldest-array" $  do+  mused <- liftIO $ HT.foldM eldest Nothing utbl+  case mused of+    Just (sa, Used ts status count tasks n weak_arr) -> do+      mad <- liftIO $ deRefWeak weak_arr+      case mad of+        Nothing -> liftIO $ do+          -- This can only happen if our eviction process was interrupted by+          -- garbage collection. In which case, even though we didn't actually+          -- evict anything, we should return true, as we know some remote+          -- memory is now free.+          --+          -- Small caveat: Due to finalisers being delayed, it's a good idea+          -- to free the array here.+          Basic.freeStable (Proxy :: Proxy m) mt sa+          delete utbl sa+          message "evictLRU/Accelerate GC interrupted by GHC GC"+        Just arr -> do+          message ("evictLRU/evicting " ++ show sa)+          copyIfNecessary status n arr+          liftIO $ Basic.freeStable (Proxy :: Proxy m) mt sa+          liftIO $ HT.insert utbl sa (Used ts Evicted count tasks n weak_arr)+      return True+    _ -> trace "evictLRU/All arrays in use, unable to evict" $ return False+  where+    -- Find the eldest, not currently in use, array.+    eldest :: (Maybe (StableArray, Used task)) -> (StableArray, Used task) -> IO (Maybe (StableArray, Used task))+    eldest prev (sa, used@(Used ts status count tasks n weak_arr)) | count == 0+                                                                   , evictable status = do+      tasks' <- cleanUses tasks+      HT.insert utbl sa (Used ts status count tasks' n weak_arr)+      case tasks' of+        [] | Just (_, Used ts' _ _ _ _ _) <- prev+           , ts < ts'        -> return (Just (sa, used))+           | Nothing <- prev -> return (Just (sa, used))+        _  -> return prev+    eldest prev _ = return prev++    evictable :: Status -> Bool+    evictable Clean     = True+    evictable Dirty     = True+    evictable Unmanaged = False+    evictable Evicted   = False++    copyIfNecessary :: PrimElt e a => Status -> Int -> ArrayData e -> m ()+    copyIfNecessary Clean     _ _  = return ()+    copyIfNecessary Unmanaged _ _  = return ()+    copyIfNecessary Evicted   _ _  = $internalError "evictLRU" "Attempting to evict already evicted array"+    copyIfNecessary Dirty     n ad = do+      mp <- liftIO $ Basic.lookup mt ad+      case mp of+        Nothing -> return () -- RCE: I think this branch is actually impossible.+        Just p  -> peekRemote n p ad++-- | Deallocate the device array associated with the given host-side array.+-- Typically this should only be called in very specific circumstances. This+-- operation is not thread-safe.+--+free :: (RemoteMemory m, PrimElt a b)+     => proxy m+     -> MemoryTable (RemotePtr m) task+     -> ArrayData a+     -> IO ()+free proxy (MemoryTable !mt !ref _) !arr = withMVar' ref $ \utbl -> do+  key <- Basic.makeStableArray arr+  delete utbl key+  Basic.freeStable proxy mt key++-- |Record an association between a host-side array and a remote memory area+-- that was not allocated by accelerate. The remote memory will NOT be re-used+-- once the host-side array is garbage collected.+--+-- This typically only has use for backends that provide an FFI.+--+insertUnmanaged+    :: (PrimElt e a, MonadIO m)+    => MemoryTable p task+    -> ArrayData e+    -> p a+    -> m ()+insertUnmanaged (MemoryTable mt ref weak_utbl) !arr !ptr = liftIO . withMVar' ref $ \utbl -> do+  key <- Basic.makeStableArray arr+  Basic.insertUnmanaged mt arr ptr+  ts <- getCPUTime+  weak_arr <- makeWeakArrayData arr arr (Just $ finalizer key weak_utbl)+  HT.insert utbl key (Used ts Unmanaged 0 [] 0 weak_arr)+++-- Removing entries+-- ----------------++finalizer :: StableArray -> Weak (UseTable task) -> IO ()+finalizer !key !weak_utbl = do+  mref <- deRefWeak weak_utbl+  case mref of+    Nothing  -> message "finalize cache/dead table"+    Just ref -> trace  ("finalize cache: " ++ show key) $ withMVar' ref (`delete` key)++delete :: UT task -> StableArray -> IO ()+delete utbl key = do+  mu <- HT.lookup utbl key+  case mu of+    Nothing -> return ()+    Just _  -> HT.delete utbl key++-- |Initiate garbage collection and `free` any remote arrays that no longer+-- have matching host-side equivalents.+--+reclaim+    :: forall m task. (RemoteMemory m, MonadIO m)+    => MemoryTable (RemotePtr m) task+    -> m ()+reclaim (MemoryTable !mt _ _) = Basic.reclaim mt++cache_finalizer :: UT task -> IO ()+cache_finalizer !tbl+  = trace "cache finaliser"+  $ HT.mapM_ (\(_,u) -> f u)+             tbl+  where+    f :: Used task -> IO ()+    f (Used _ _ _ _ _ w) = finalize w++-- Miscellaneous+-- -------------++cleanUses :: Task task => [task] -> IO [task]+cleanUses = filterM (fmap not . completed)++incCount :: Used task -> Used task+incCount (Used ts status count uses n weak_arr) = Used ts status (count + 1) uses n weak_arr++isEvicted :: Used task -> Bool+isEvicted (Used _ status _ _ _ _) = status == Evicted++withMVar' :: (MonadIO m, MonadMask m) => MVar a -> (a -> m b) -> m b+withMVar' m f = mask $ \restore -> do+  a <- liftIO $ takeMVar m+  b <- restore (f a) `onException` (liftIO $ putMVar m a)+  liftIO $ putMVar m a+  return b++-- Debug+-- -----++{-# INLINE trace #-}+trace :: MonadIO m => String -> m a -> m a+trace msg next = message msg >> next++{-# INLINE message #-}+message :: MonadIO m => String -> m ()+message msg = liftIO $ D.traceIO D.dump_gc ("gc: " ++ msg)+
+ Data/Array/Accelerate/Array/Remote/Nursery.hs view
@@ -0,0 +1,122 @@+{-# LANGUAGE BangPatterns    #-}+{-# LANGUAGE TemplateHaskell #-}+-- |+-- Module      : Data.Array.Accelerate.Array.Remote.Nursery+-- Copyright   : [2008..2017] Manuel M T Chakravarty, Gabriele Keller+--               [2009..2017] Trevor L. McDonell+--               [2015..2017] Robert Clifton-Everest+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Array.Remote.Nursery (++  Nursery(..), NRS, new, lookup, insert, cleanup, size++) where++-- friends+import Data.Array.Accelerate.Error+import qualified Data.Array.Accelerate.Debug                    as D++-- libraries+import Prelude                                                  hiding ( lookup )+import Control.Concurrent.MVar+import Data.Int+import Data.IntMap                                              ( IntMap )+import Data.Sequence                                            ( Seq )+import Data.Word+import System.Mem.Weak                                          ( Weak )+import qualified Data.IntMap.Strict                             as IM+import qualified Data.Sequence                                  as Seq+import qualified Data.Traversable                               as Seq+++-- The nursery is a place to store remote memory arrays that are no longer+-- needed. Often it is quicker to reuse an existing array, rather than call out+-- to the external API to allocate fresh memory.+--+-- The nursery is wrapped in an MVar so that several threads may safely access+-- it concurrently.+--+data Nursery ptr        = Nursery {-# UNPACK #-} !(NRS ptr)+                                  {-# UNPACK #-} !(Weak (NRS ptr))+type NRS ptr            = MVar (N ptr)++data N ptr              = N !(IntMap (Seq (ptr Word8)))       -- #bytes -> ptr+                            {-# UNPACK #-} !Int64             -- total allocated bytes+++-- | Create a fresh nursery.+--+-- When the nursery is garbage collected, the provided function will be run on+-- each value to free the retained memory.+--+{-# INLINEABLE new #-}+new :: (ptr Word8 -> IO ()) -> IO (Nursery ptr)+new delete = do+  message "initialise nursery"+  ref    <- newMVar ( N IM.empty 0 )+  weak   <- mkWeakMVar ref (cleanup delete ref)+  return $! Nursery ref weak+++-- | Look for an entry with the requested size.+--+{-# INLINEABLE lookup #-}+lookup :: Int -> Nursery ptr -> IO (Maybe (ptr Word8))+lookup !key (Nursery !ref !_) =+  modifyMVar ref $ \nrs@( N im sz ) ->+    let+        (mv, nrs')  = IM.updateLookupWithKey f key im         -- returns _original_ value, if located+        f _k v      =+          case Seq.viewl v of+            Seq.EmptyL  -> $internalError "lookup" "expected non-empty sequence"+            _ Seq.:< vs -> if Seq.null vs then Nothing        -- delete this entry in the map+                                          else Just vs        -- re-insert the tail+    in+    case fmap Seq.viewl mv of+      Just (v Seq.:< _) -> return ( N nrs' (sz - fromIntegral key) , Just v  )+      _                 -> return ( nrs,                             Nothing )+++-- | Add an entry to the nursery+--+{-# INLINEABLE insert #-}+insert :: Int -> ptr Word8 -> Nursery ptr -> IO ()+insert !key !val (Nursery !ref _) =+  let+      f Nothing   = Just (Seq.singleton val)+      f (Just vs) = Just (vs Seq.|> val)+  in+  modifyMVar_ ref $ \(N im sz) ->+    return $! N (IM.alter f key im) (sz + fromIntegral key)+++-- | Delete all entries from the nursery+--+{-# INLINEABLE cleanup #-}+cleanup :: (ptr Word8 -> IO ()) -> NRS ptr -> IO ()+cleanup delete !ref = do+  message "nursery cleanup"+  modifyMVar_ ref $ \(N nrs _) -> do mapM_ (Seq.mapM delete) (IM.elems nrs)+                                     return ( N IM.empty 0 )+++-- | The total number of bytes retained by the nursery+--+{-# INLINEABLE size #-}+size :: Nursery ptr -> IO Int64+size (Nursery ref _) = withMVar ref $ \(N _ sz) -> return sz+++-- Debug+-- -----++{-# INLINE message #-}+message :: String -> IO ()+message msg = D.traceIO D.dump_gc ("gc: " ++ msg)+
+ Data/Array/Accelerate/Array/Remote/Table.hs view
@@ -0,0 +1,466 @@+{-# LANGUAGE BangPatterns               #-}+{-# LANGUAGE CPP                        #-}+{-# LANGUAGE ConstraintKinds            #-}+{-# LANGUAGE GADTs                      #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MagicHash                  #-}+{-# LANGUAGE PatternGuards              #-}+{-# LANGUAGE RankNTypes                 #-}+{-# LANGUAGE ScopedTypeVariables        #-}+{-# LANGUAGE TemplateHaskell            #-}+{-# LANGUAGE UnboxedTuples              #-}+{-# LANGUAGE ViewPatterns               #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.Array.Remote.Table+-- Copyright   : [2008..2017] Manuel M T Chakravarty, Gabriele Keller+--               [2009..2017] Trevor L. McDonell+--               [2015..2017] Robert Clifton-Everest+-- License     : BSD3+--+-- Maintainer  : Robert Clifton-Everest <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- Accelerate backends often need to copy arrays to a remote memory before they+-- can be used in computation. This module provides an automated method for+-- doing so. Keeping track of arrays in a `MemoryTable` ensures that any memory+-- allocated for them will be freed when GHC's garbage collector collects the+-- host array.+--+module Data.Array.Accelerate.Array.Remote.Table (++  -- Tables for host/device memory associations+  MemoryTable, new, lookup, malloc, free, freeStable, insertUnmanaged, reclaim,++  -- Internals+  StableArray, makeStableArray,+  makeWeakArrayData++) where++import Control.Concurrent                                       ( yield )+import Control.Concurrent.MVar                                  ( MVar, newMVar, withMVar, mkWeakMVar )+import Control.Concurrent.Unique                                ( Unique )+import Control.Monad.IO.Class                                   ( MonadIO, liftIO )+import Data.Functor+import Data.Hashable                                            ( hash, Hashable )+import Data.Maybe                                               ( isJust )+import Data.Proxy+import Data.Typeable                                            ( Typeable, gcast )+import Data.Word+import Foreign.Storable                                         ( sizeOf )+import System.Mem                                               ( performGC )+import System.Mem.Weak                                          ( Weak, deRefWeak )+import Prelude                                                  hiding ( lookup, id )+import qualified Data.HashTable.IO                              as HT++import GHC.Exts                                                 ( Ptr(..) )++import Data.Array.Accelerate.Error                              ( internalError )+import Data.Array.Accelerate.Array.Unique                       ( UniqueArray(..) )+import Data.Array.Accelerate.Array.Data                         ( ArrayData, GArrayData(..),+                                                                  ArrayPtrs, ArrayElt, arrayElt, ArrayEltR(..) )+import Data.Array.Accelerate.Array.Remote.Class+import Data.Array.Accelerate.Array.Remote.Nursery               ( Nursery(..) )+import Data.Array.Accelerate.Lifetime+import qualified Data.Array.Accelerate.Array.Remote.Nursery     as N+import qualified Data.Array.Accelerate.Debug                    as D+++-- We use an MVar to the hash table, so that several threads may safely access+-- it concurrently. This includes the finalisation threads that remove entries+-- from the table.+--+-- It is important that we can garbage collect old entries from the table when+-- the key is no longer reachable in the heap. Hence the value part of each+-- table entry is a (Weak val), where the stable name 'key' is the key for the+-- memo table, and the 'val' is the value of this table entry. When the key+-- becomes unreachable, a finaliser will fire and remove this entry from the+-- hash buckets, and further attempts to dereference the weak pointer will+-- return Nothing. References from 'val' to the key are ignored (see the+-- semantics of weak pointers in the documentation).+--+type HashTable key val  = HT.BasicHashTable key val+type MT p               = MVar ( HashTable StableArray (RemoteArray p) )+data MemoryTable p      = MemoryTable {-# UNPACK #-} !(MT p)+                                      {-# UNPACK #-} !(Weak (MT p))+                                      {-# UNPACK #-} !(Nursery p)+                                      (p Word8 -> IO ())++data RemoteArray p where+  RemoteArray :: Typeable e+              => {-# UNPACK #-} !(Weak ())  -- Keep track of host array liveness+              -> !(p e)                     -- The actual remote pointer+              -> {-# UNPACK #-} !Int        -- The array size in bytes+              -> RemoteArray p++-- | An untyped reference to an array, similar to a StableName.+--+newtype StableArray = StableArray Unique+  deriving (Eq, Hashable)++instance Show StableArray where+  show (StableArray u) = show (hash u)++-- |Create a new memory table from host to remote arrays.+--+-- The function supplied should be the `free` for the remote pointers being+-- stored. This function will be called by the GC, which typically runs on a+-- different thread. Unlike the `free` in `RemoteMemory`, this function cannot+-- depend on any state.+--+new :: (forall a. ptr a -> IO ()) -> IO (MemoryTable ptr)+new release = do+  message "initialise memory table"+  tbl  <- HT.new+  ref  <- newMVar tbl+  nrs  <- N.new release+  weak <- mkWeakMVar ref (return ())+  return $! MemoryTable ref weak nrs release+++-- | Look for the remote pointer corresponding to a given host-side array.+--+lookup+    :: (PrimElt a b)+    => MemoryTable p+    -> ArrayData a+    -> IO (Maybe (p b))+lookup (MemoryTable !ref _ _ _) !arr = do+  sa <- makeStableArray arr+  mw <- withMVar ref (`HT.lookup` sa)+  case mw of+    Nothing              -> trace ("lookup/not found: " ++ show sa) $ return Nothing+    Just (RemoteArray w p _) -> do+      mv <- deRefWeak w+      case mv of+        Just _ | Just p' <- gcast p -> trace ("lookup/found: " ++ show sa) $ return (Just p')+               | otherwise          -> $internalError "lookup" $ "type mismatch"++        -- Note: [Weak pointer weirdness]+        --+        -- After the lookup is successful, there might conceivably be no further+        -- references to 'arr'. If that is so, and a garbage collection+        -- intervenes, the weak pointer might get tombstoned before 'deRefWeak'+        -- gets to it. In that case we throw an error (below). However, because+        -- we have used 'arr' in the continuation, this ensures that 'arr' is+        -- reachable in the continuation of 'deRefWeak' and thus 'deRefWeak'+        -- always succeeds. This sort of weirdness, typical of the world of weak+        -- pointers, is why we can not reuse the stable name 'sa' computed+        -- above in the error message.+        --+        Nothing                     ->+          makeStableArray arr >>= \x -> $internalError "lookup" $ "dead weak pair: " ++ show x+++-- | Allocate a new device array to be associated with the given host-side array.+-- This may not always use the `malloc` provided by the `RemoteMemory` instance.+-- In order to reduce the number of raw allocations, previously allocated remote+-- arrays will be re-used. In the event that the remote memory is exhausted,+-- 'Nothing' is returned.+--+malloc :: forall a b m. (PrimElt a b, RemoteMemory m, MonadIO m)+       => MemoryTable (RemotePtr m)+       -> ArrayData a+       -> Int+       -> m (Maybe (RemotePtr m b))+malloc mt@(MemoryTable _ _ !nursery _) !ad !n = do+  -- Note: [Allocation sizes]+  --+  -- Instead of allocating the exact number of elements requested, we round up to+  -- a fixed chunk size as specified by RemoteMemory.remoteAllocationSize. This+  -- means there is a greater chance the nursery will get a hit, and moreover+  -- that we can search the nursery for an exact size.+  --+  chunk <- remoteAllocationSize+  let -- next highest multiple of f from x+      multiple x f      = (x + (f-1)) `div` f+      bytes             = chunk * multiple (n * sizeOf (undefined::b)) chunk+  --+  message ("malloc: " ++ showBytes bytes)+  mp <-+    fmap (castRemotePtr (Proxy :: Proxy m))+    <$> attempt "malloc/nursery" (liftIO $ N.lookup bytes nursery)+        `orElse`+        attempt "malloc/new" (mallocRemote bytes)+        `orElse` do message "malloc/remote-malloc-failed (cleaning)"+                    clean mt+                    liftIO $ N.lookup bytes nursery+        `orElse` do message "malloc/remote-malloc-failed (purging)"+                    purge mt+                    mallocRemote bytes+        `orElse` do message "malloc/remote-malloc-failed (non-recoverable)"+                    return Nothing+  case mp of+    Nothing -> return Nothing+    Just p' -> do+      insert mt ad p' bytes+      return (Just p')++  where+    orElse :: m (Maybe x) -> m (Maybe x) -> m (Maybe x)+    orElse ra rb = do+      ma <- ra+      case ma of+        Nothing -> rb+        Just a  -> return (Just a)++    attempt :: String -> m (Maybe x) -> m (Maybe x)+    attempt msg next = do+      ma <- next+      case ma of+        Nothing -> return Nothing+        Just a  -> trace msg (return (Just a))++++-- | Deallocate the device array associated with the given host-side array.+-- Typically this should only be called in very specific circumstances.+--+free :: (RemoteMemory m, PrimElt a b)+     => proxy m+     -> MemoryTable (RemotePtr m)+     -> ArrayData a+     -> IO ()+free proxy mt !arr = do+  sa <- makeStableArray arr+  freeStable proxy mt sa+++-- | Deallocate the device array associated with the given StableArray. This+-- is useful for other memory managers built on top of the memory table.+--+freeStable+    :: RemoteMemory m+    => proxy m+    -> MemoryTable (RemotePtr m)+    -> StableArray+    -> IO ()+freeStable proxy (MemoryTable !ref _ !nrs _) !sa =+  withMVar ref $ \mt -> do+    mw <- mt `HT.lookup` sa+    case mw of+      Nothing                        -> message ("free/already-removed: " ++ show sa)+      Just (RemoteArray _ !p !bytes) -> do+        message ("free/evict: " ++ show sa ++ " of " ++ showBytes bytes)+        N.insert bytes (castRemotePtr proxy p) nrs+        mt `HT.delete` sa+++-- Record an association between a host-side array and a new device memory area.+-- The device memory will be freed when the host array is garbage collected.+--+insert :: forall m a b. (PrimElt a b, RemoteMemory m, MonadIO m)+       => MemoryTable (RemotePtr m)+       -> ArrayData a+       -> RemotePtr m b+       -> Int+       -> m ()+insert mt@(MemoryTable !ref _ _ _) !arr !ptr !bytes = do+  key  <- makeStableArray  arr+  weak <- liftIO $ makeWeakArrayData arr () (Just $ freeStable (Proxy :: Proxy m) mt key)+  message $ "insert: " ++ show key+  liftIO  $ withMVar ref $ \tbl -> HT.insert tbl key (RemoteArray weak ptr bytes)+++-- |Record an association between a host-side array and a remote memory area+-- that was not allocated by accelerate. The remote memory will NOT be re-used+-- once the host-side array is garbage collected.+--+-- This typically only has use for backends that provide an FFI.+--+insertUnmanaged+    :: (PrimElt a b, MonadIO m)+    => MemoryTable p+    -> ArrayData a+    -> p b+    -> m ()+insertUnmanaged (MemoryTable !ref !weak_ref _ _) !arr !ptr = do+  key  <- makeStableArray  arr+  weak <- liftIO $ makeWeakArrayData arr () (Just $ remoteFinalizer weak_ref key)+  message $ "insertUnmanaged: " ++ show key+  liftIO $ withMVar ref $ \tbl -> HT.insert tbl key (RemoteArray weak ptr 0)+++-- Removing entries+-- ----------------++-- |Initiate garbage collection and mark any arrays that no longer have host-side+-- equivalents as reusable.+--+clean :: forall m. (RemoteMemory m, MonadIO m) => MemoryTable (RemotePtr m) -> m ()+clean mt@(MemoryTable _ weak_ref nrs _) = management "clean" nrs . liftIO $ do+  -- Unfortunately there is no real way to force a GC then wait for it to+  -- finish. Calling performGC then yielding works moderately well in+  -- single-threaded cases, but tends to fall down otherwise. Either way, given+  -- that finalizers are often significantly delayed, it is worth our while+  -- traversing the table and explicitly freeing any dead entires.+  --+  performGC+  yield+  mr <- deRefWeak weak_ref+  case mr of+    Nothing  -> return ()+    Just ref -> do+      rs <- withMVar ref $ HT.foldM removable []  -- collect arrays that can be removed+      mapM_ (freeStable (Proxy :: Proxy m) mt) rs -- remove them all+  where+    removable rs (sa, RemoteArray w _ _) = do+      alive <- isJust <$> deRefWeak w+      if alive+        then return rs+        else return (sa:rs)+++-- | Call `free` on all arrays that are not currently associated with host-side+-- arrays.+--+purge :: (RemoteMemory m, MonadIO m) => MemoryTable (RemotePtr m) -> m ()+purge (MemoryTable _ _ nursery@(Nursery nrs _) release)+  = management "purge" nursery+  $ liftIO (N.cleanup release nrs)+++-- |Initiate garbage collection and `free` any remote arrays that no longer+-- have matching host-side equivalents.+--+reclaim :: forall m. (RemoteMemory m, MonadIO m) => MemoryTable (RemotePtr m) -> m ()+reclaim mt = clean mt >> purge mt++remoteFinalizer :: Weak (MT p) -> StableArray -> IO ()+remoteFinalizer !weak_ref !key = do+  mr <- deRefWeak weak_ref+  case mr of+    Nothing  -> message ("finalise/dead table: " ++ show key)+    Just ref -> trace   ("finalise: "            ++ show key) $ withMVar ref (`HT.delete` key)+++-- Miscellaneous+-- -------------++-- | Make a new 'StableArray'.+--+{-# INLINE makeStableArray #-}+makeStableArray+    :: (MonadIO m, Typeable a, Typeable e, ArrayPtrs a ~ Ptr e, ArrayElt a)+    => ArrayData a+    -> m StableArray+makeStableArray !ad = return $! StableArray (id arrayElt ad)+  where+    id :: ArrayEltR e -> ArrayData e -> Unique+    id ArrayEltRint     (AD_Int ua)     = uniqueArrayId ua+    id ArrayEltRint8    (AD_Int8 ua)    = uniqueArrayId ua+    id ArrayEltRint16   (AD_Int16 ua)   = uniqueArrayId ua+    id ArrayEltRint32   (AD_Int32 ua)   = uniqueArrayId ua+    id ArrayEltRint64   (AD_Int64 ua)   = uniqueArrayId ua+    id ArrayEltRword    (AD_Word ua)    = uniqueArrayId ua+    id ArrayEltRword8   (AD_Word8 ua)   = uniqueArrayId ua+    id ArrayEltRword16  (AD_Word16 ua)  = uniqueArrayId ua+    id ArrayEltRword32  (AD_Word32 ua)  = uniqueArrayId ua+    id ArrayEltRword64  (AD_Word64 ua)  = uniqueArrayId ua+    id ArrayEltRcshort  (AD_CShort ua)  = uniqueArrayId ua+    id ArrayEltRcushort (AD_CUShort ua) = uniqueArrayId ua+    id ArrayEltRcint    (AD_CInt ua)    = uniqueArrayId ua+    id ArrayEltRcuint   (AD_CUInt ua)   = uniqueArrayId ua+    id ArrayEltRclong   (AD_CLong ua)   = uniqueArrayId ua+    id ArrayEltRculong  (AD_CULong ua)  = uniqueArrayId ua+    id ArrayEltRcllong  (AD_CLLong ua)  = uniqueArrayId ua+    id ArrayEltRcullong (AD_CULLong ua) = uniqueArrayId ua+    id ArrayEltRfloat   (AD_Float ua)   = uniqueArrayId ua+    id ArrayEltRdouble  (AD_Double ua)  = uniqueArrayId ua+    id ArrayEltRcfloat  (AD_CFloat ua)  = uniqueArrayId ua+    id ArrayEltRcdouble (AD_CDouble ua) = uniqueArrayId ua+    id ArrayEltRbool    (AD_Bool ua)    = uniqueArrayId ua+    id ArrayEltRchar    (AD_Char ua)    = uniqueArrayId ua+    id ArrayEltRcchar   (AD_CChar ua)   = uniqueArrayId ua+    id ArrayEltRcschar  (AD_CSChar ua)  = uniqueArrayId ua+    id ArrayEltRcuchar  (AD_CUChar ua)  = uniqueArrayId ua+    id _                _               = error "I do have a cause, though. It is obscenity. I'm for it."++-- Weak arrays+-- ----------------------++-- |Make a weak pointer using an array as a key. Unlike the standard `mkWeak`,+-- this guarantees finalisers won't fire early.+--+makeWeakArrayData+    :: forall a e c. (ArrayElt e, ArrayPtrs e ~ Ptr a)+    => ArrayData e+    -> c+    -> Maybe (IO ())+    -> IO (Weak c)+makeWeakArrayData !ad !c !mf = mw arrayElt ad+  where+    mw :: ArrayEltR e -> ArrayData e -> IO (Weak c)+    mw ArrayEltRint     (AD_Int ua)     = mkWeak' ua+    mw ArrayEltRint8    (AD_Int8 ua)    = mkWeak' ua+    mw ArrayEltRint16   (AD_Int16 ua)   = mkWeak' ua+    mw ArrayEltRint32   (AD_Int32 ua)   = mkWeak' ua+    mw ArrayEltRint64   (AD_Int64 ua)   = mkWeak' ua+    mw ArrayEltRword    (AD_Word ua)    = mkWeak' ua+    mw ArrayEltRword8   (AD_Word8 ua)   = mkWeak' ua+    mw ArrayEltRword16  (AD_Word16 ua)  = mkWeak' ua+    mw ArrayEltRword32  (AD_Word32 ua)  = mkWeak' ua+    mw ArrayEltRword64  (AD_Word64 ua)  = mkWeak' ua+    mw ArrayEltRcshort  (AD_CShort ua)  = mkWeak' ua+    mw ArrayEltRcushort (AD_CUShort ua) = mkWeak' ua+    mw ArrayEltRcint    (AD_CInt ua)    = mkWeak' ua+    mw ArrayEltRcuint   (AD_CUInt ua)   = mkWeak' ua+    mw ArrayEltRclong   (AD_CLong ua)   = mkWeak' ua+    mw ArrayEltRculong  (AD_CULong ua)  = mkWeak' ua+    mw ArrayEltRcllong  (AD_CLLong ua)  = mkWeak' ua+    mw ArrayEltRcullong (AD_CULLong ua) = mkWeak' ua+    mw ArrayEltRfloat   (AD_Float ua)   = mkWeak' ua+    mw ArrayEltRdouble  (AD_Double ua)  = mkWeak' ua+    mw ArrayEltRcfloat  (AD_CFloat ua)  = mkWeak' ua+    mw ArrayEltRcdouble (AD_CDouble ua) = mkWeak' ua+    mw ArrayEltRbool    (AD_Bool ua)    = mkWeak' ua+    mw ArrayEltRchar    (AD_Char ua)    = mkWeak' ua+    mw ArrayEltRcchar   (AD_CChar ua)   = mkWeak' ua+    mw ArrayEltRcschar  (AD_CSChar ua)  = mkWeak' ua+    mw ArrayEltRcuchar  (AD_CUChar ua)  = mkWeak' ua+#if __GLASGOW_HASKELL__ < 800+    mw _                _               = error "Base eight is just like base ten really - if you're missing two fingers."+#endif++    mkWeak' :: UniqueArray a -> IO (Weak c)+    mkWeak' !ua = do+      let !uad = uniqueArrayData ua+      case mf of+        Nothing -> return ()+        Just f  -> addFinalizer uad f+      mkWeak uad c+++-- Debug+-- -----++{-# INLINE showBytes #-}+showBytes :: Integral n => n -> String+showBytes x = D.showFFloatSIBase (Just 0) 1024 (fromIntegral x :: Double) "B"++{-# INLINE trace #-}+trace :: MonadIO m => String -> m a -> m a+trace msg next = message msg >> next++{-# INLINE message #-}+message :: MonadIO m => String -> m ()+message msg = liftIO $ D.traceIO D.dump_gc ("gc: " ++ msg)++{-# INLINE management #-}+management :: (RemoteMemory m, MonadIO m) => String -> Nursery p -> m a -> m a+management msg nrs next = do+  before     <- availableRemoteMem+  before_nrs <- liftIO $ N.size nrs+  total      <- totalRemoteMem+  r          <- next+  D.when D.dump_gc $ do+    after     <- availableRemoteMem+    after_nrs <- liftIO $ N.size nrs+    message $ msg ++ " (freed: "     ++ showBytes (after - before)+                  ++ ", stashed: "   ++ showBytes (before_nrs - after_nrs)+                  ++ ", remaining: " ++ showBytes after+                  ++ " of "          ++ showBytes total ++ ")"+  return r+
Data/Array/Accelerate/Array/Representation.hs view
@@ -3,17 +3,19 @@ {-# LANGUAGE GADTs               #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TemplateHaskell     #-}+{-# LANGUAGE TupleSections       #-} {-# LANGUAGE TypeFamilies        #-} {-# LANGUAGE TypeOperators       #-} {-# OPTIONS_HADDOCK hide #-} -- | -- Module      : Data.Array.Accelerate.Array.Representation--- Copyright   : [2008..2014] Manuel M T Chakravarty, Gabriele Keller---               [2008..2009] Sean Lee---               [2009..2014] Trevor L. McDonell+-- Copyright   : [2008..2017] Manuel M T Chakravarty, Gabriele Keller+--               [2009..2017] Trevor L. McDonell+--               [2013..2017] Robert Clifton-Everest+--               [2014..2014] Frederik M. Madsen -- License     : BSD3 ----- Maintainer  : Manuel M T Chakravarty <chak@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -23,6 +25,9 @@   -- * Array shapes, indices, and slices   Shape(..), Slice(..), SliceIndex(..), +  -- * Slice shape functions+  sliceShape, enumSlices,+ ) where  -- friends@@ -40,11 +45,13 @@ -- class (Eq sh, Slice sh) => Shape sh where   -- user-facing methods-  dim       :: sh -> Int             -- ^number of dimensions (>= 0); rank of the array+  rank      :: sh -> Int             -- ^number of dimensions (>= 0); rank of the array   size      :: sh -> Int             -- ^total number of elements in an array of this /shape/+  empty     :: sh                    -- ^empty shape.    -- internal methods   intersect :: sh -> sh -> sh  -- yield the intersection of two shapes+  union     :: sh -> sh -> sh  -- yield the union of two shapes   ignore    :: sh              -- identifies ignored elements in 'permute'   toIndex   :: sh -> sh -> Int -- yield the index position in a linear, row-major representation of                                -- the array (first argument is the shape)@@ -72,11 +79,12 @@   listToShape :: [Int] -> sh    -- convert a list of dimensions into a shape  instance Shape () where-  dim _             = 0-  size ()           = 1--  () `intersect` () = ()+  rank _            = 0+  empty             = ()   ignore            = ()+  () `intersect` () = ()+  () `union` ()     = ()+  size ()           = 1   toIndex () ()     = 0   fromIndex () _    = ()   bound () () _     = Right ()@@ -91,11 +99,15 @@   listToShape _  = $internalError "listToShape" "non-empty list when converting to unit"  instance Shape sh => Shape (sh, Int) where-  dim _                             = dim (undefined :: sh) + 1-  size (sh, sz)                     = size sh * sz--  (sh1, sz1) `intersect` (sh2, sz2) = (sh1 `intersect` sh2, sz1 `min` sz2)+  rank _                            = rank (undefined :: sh) + 1+  empty                             = (empty, 0)   ignore                            = (ignore, -1)+  (sh1, sz1) `intersect` (sh2, sz2) = (sh1 `intersect` sh2, sz1 `min` sz2)+  (sh1, sz1) `union` (sh2, sz2)     = (sh1 `union` sh2, sz1 `max` sz2)++  size (sh, sz)                     = $boundsCheck "size" "negative shape dimension" (sz >= 0)+                                    $ size sh * sz+   toIndex (sh, sz) (ix, i)          = $indexCheck "toIndex" i sz                                     $ toIndex sh ix * sz + i @@ -104,22 +116,30 @@     -- the remainder for the highest dimension since i < sz must hold.     --     where-      r | dim sh == 0   = $indexCheck "fromIndex" i sz i+      r | rank sh == 0  = $indexCheck "fromIndex" i sz i         | otherwise     = i `remInt` sz    bound (sh, sz) (ix, i) bndy     | i < 0                         = case bndy of-                                        Clamp      -> bound sh ix bndy `addDim` 0-                                        Mirror     -> bound sh ix bndy `addDim` (-i)-                                        Wrap       -> bound sh ix bndy `addDim` (sz+i)+                                        Clamp      -> next `addDim` 0+                                        Mirror     -> next `addDim` (-i)+                                        Wrap       -> next `addDim` (sz+i)                                         Constant e -> Left e     | i >= sz                       = case bndy of-                                        Clamp      -> bound sh ix bndy `addDim` (sz-1)-                                        Mirror     -> bound sh ix bndy `addDim` (sz-(i-sz+2))-                                        Wrap       -> bound sh ix bndy `addDim` (i-sz)+                                        Clamp      -> next `addDim` (sz-1)+                                        Mirror     -> next `addDim` (sz-(i-sz+2))+                                        Wrap       -> next `addDim` (i-sz)                                         Constant e -> Left e-    | otherwise                     = bound sh ix bndy `addDim` i+    | otherwise                     = next `addDim` i     where+      -- This function is quite difficult to optimize due to the deep recursion+      -- that is can generate with high-dimensional arrays. If we let 'next' be+      -- inlined into each alternative of the cases above the size of this+      -- function on an n-dimensional array will grow as 7^n. This quickly causes+      -- GHC's head to explode. See GHC Trac #10491 for more details.+      next = bound sh ix bndy+      {-# NOINLINE next #-}+       Right ds `addDim` d = Right (ds, d)       Left e   `addDim` _ = Left e @@ -190,4 +210,28 @@   show SliceNil          = "SliceNil"   show (SliceAll rest)   = "SliceAll (" ++ show rest ++ ")"   show (SliceFixed rest) = "SliceFixed (" ++ show rest ++ ")"++-- | Project the shape of a slice from the full shape.+--+sliceShape :: forall slix co sl dim.+              SliceIndex slix sl co dim+           -> dim+           -> sl+sliceShape SliceNil        ()      = ()+sliceShape (SliceAll   sl) (sh, n) = (sliceShape sl sh, n)+sliceShape (SliceFixed sl) (sh, _) = sliceShape sl sh+++-- | Enumerate all slices within a given bound. The innermost dimension changes+-- most rapidly.+--+-- See 'Data.Array.Accelerate.Array.Sugar.enumSlices' for an example.+--+enumSlices :: forall slix co sl dim.+              SliceIndex slix sl co dim+           -> dim+           -> [slix]+enumSlices SliceNil        ()       = [()]+enumSlices (SliceAll   sl) (sh, _)  = [ (sh', ()) | sh' <- enumSlices sl sh]+enumSlices (SliceFixed sl) (sh, n)  = [ (sh', i)  | sh' <- enumSlices sl sh, i <- [0..n-1]] 
Data/Array/Accelerate/Array/Sugar.hs view
@@ -1,1148 +1,1292 @@-{-# LANGUAGE BangPatterns        #-}-{-# LANGUAGE CPP                 #-}-{-# LANGUAGE DeriveDataTypeable  #-}-{-# LANGUAGE FlexibleContexts    #-}-{-# LANGUAGE FlexibleInstances   #-}-{-# LANGUAGE GADTs               #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE StandaloneDeriving  #-}-{-# LANGUAGE TupleSections       #-}-{-# LANGUAGE TypeFamilies        #-}-{-# LANGUAGE TypeOperators       #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module      : Data.Array.Accelerate.Array.Sugar--- Copyright   : [2008..2014] Manuel M T Chakravarty, Gabriele Keller---               [2008..2009] Sean Lee---               [2009..2014] Trevor L. McDonell---               [2013..2014] Robert Clifton-Everest--- License     : BSD3------ Maintainer  : Manuel M T Chakravarty <chak@cse.unsw.edu.au>--- Stability   : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Array.Sugar (--  -- * Array representation-  Array(..), Scalar, Vector, Segments,-  Arrays(..), ArraysR(..), ArrRepr, ArrRepr',--  -- * Class of supported surface element types and their mapping to representation types-  Elt(..), EltRepr, EltRepr',--  -- * Derived functions-  liftToElt, liftToElt2, sinkFromElt, sinkFromElt2,--  -- * Array shapes-  DIM0, DIM1, DIM2, DIM3, DIM4, DIM5, DIM6, DIM7, DIM8, DIM9,--  -- * Array indexing and slicing-  Z(..), (:.)(..), All(..), Any(..), Shape(..), Slice(..),--  -- * Array shape query, indexing, and conversions-  shape, (!), newArray, allocateArray, fromIArray, toIArray, fromList, toList,--  -- * Miscellaneous-  showShape, Foreign(..)--) where---- standard library-import Data.Typeable-import Data.Array.IArray                                        ( IArray )-import qualified Data.Array.IArray                              as IArray--import GHC.Exts                                                 ( IsList )-import qualified GHC.Exts                                       as GHC---- friends-import Data.Array.Accelerate.Type-import Data.Array.Accelerate.Array.Data-import qualified Data.Array.Accelerate.Array.Representation     as Repr----- Surface types representing array indices and slices--- --------------------------------------------------------- Array indices are snoc type lists.  That is, they're backwards ----- the end-of-list token, `Z`, occurs first.  For example, the type of a--- rank-2 array index is @Z :. Int :. Int@.------ In Accelerate the rightmost dimension is the /fastest varying/ or innermost.---- |Rank-0 index----data Z = Z-  deriving (Typeable, Show, Eq)---- |Increase an index rank by one dimension.  The `:.` operator is---  used to construct both values and types.----infixl 3 :.-data tail :. head = tail :. head-  deriving (Typeable, Show, Eq)---- | Marker for entire dimensions in slice descriptors.------ For example, when used in slices passed to `Data.Array.Accelerate.replicate`,--- the occurrences of `All` indicate the dimensions into which the array's--- existing extent will be placed, rather than the new dimensions introduced by--- replication.----data All = All-  deriving (Typeable, Show, Eq)---- |Marker for arbitrary shapes in slice descriptors.  Such arbitrary---  shapes may include an unknown number of dimensions.------  `Any` can be used in the leftmost position of a slice instead of---  `Z`, for example @(Any :. _ :. _)@.  In the following definition---  `Any` is used to match against whatever shape the type variable---  `sh` takes:------ > repN :: (Shape sh, Elt e) => Int -> Acc (Array sh e) -> Acc (Array (sh:.Int) e)--- > repN n a = replicate (constant $ Any :. n) a----data Any sh = Any-  deriving (Typeable, Show, Eq)---- Representation change for array element types--- ------------------------------------------------- | Type representation mapping------ We represent tuples by using '()' and '(,)' as type-level nil and snoc to--- construct snoc-lists of types.----type family EltRepr a :: *-type instance EltRepr () = ()-type instance EltRepr Z = ()-type instance EltRepr (t:.h) = (EltRepr t, EltRepr' h)-type instance EltRepr All = ((), ())-type instance EltRepr (Any Z) = ()-type instance EltRepr (Any (sh:.Int)) = (EltRepr (Any sh), ())-type instance EltRepr Int = ((), Int)-type instance EltRepr Int8 = ((), Int8)-type instance EltRepr Int16 = ((), Int16)-type instance EltRepr Int32 = ((), Int32)-type instance EltRepr Int64 = ((), Int64)-type instance EltRepr Word = ((), Word)-type instance EltRepr Word8 = ((), Word8)-type instance EltRepr Word16 = ((), Word16)-type instance EltRepr Word32 = ((), Word32)-type instance EltRepr Word64 = ((), Word64)-type instance EltRepr CShort = ((), CShort)-type instance EltRepr CUShort = ((), CUShort)-type instance EltRepr CInt = ((), CInt)-type instance EltRepr CUInt = ((), CUInt)-type instance EltRepr CLong = ((), CLong)-type instance EltRepr CULong = ((), CULong)-type instance EltRepr CLLong = ((), CLLong)-type instance EltRepr CULLong = ((), CULLong)-type instance EltRepr Float = ((), Float)-type instance EltRepr Double = ((), Double)-type instance EltRepr CFloat = ((), CFloat)-type instance EltRepr CDouble = ((), CDouble)-type instance EltRepr Bool = ((), Bool)-type instance EltRepr Char = ((), Char)-type instance EltRepr CChar = ((), CChar)-type instance EltRepr CSChar = ((), CSChar)-type instance EltRepr CUChar = ((), CUChar)-type instance EltRepr (a, b) = (EltRepr a, EltRepr' b)-type instance EltRepr (a, b, c) = (EltRepr (a, b), EltRepr' c)-type instance EltRepr (a, b, c, d) = (EltRepr (a, b, c), EltRepr' d)-type instance EltRepr (a, b, c, d, e) = (EltRepr (a, b, c, d), EltRepr' e)-type instance EltRepr (a, b, c, d, e, f) = (EltRepr (a, b, c, d, e), EltRepr' f)-type instance EltRepr (a, b, c, d, e, f, g) = (EltRepr (a, b, c, d, e, f), EltRepr' g)-type instance EltRepr (a, b, c, d, e, f, g, h) = (EltRepr (a, b, c, d, e, f, g), EltRepr' h)-type instance EltRepr (a, b, c, d, e, f, g, h, i)-  = (EltRepr (a, b, c, d, e, f, g, h), EltRepr' i)---- To avoid overly nested pairs, we use a flattened representation at the--- leaves.----type family EltRepr' a :: *-type instance EltRepr' () = ()-type instance EltRepr' Z = ()-type instance EltRepr' (t:.h) = (EltRepr t, EltRepr' h)-type instance EltRepr' All = ()-type instance EltRepr' (Any Z) = ()-type instance EltRepr' (Any (sh:.Int)) = (EltRepr' (Any sh), ())-type instance EltRepr' Int = Int-type instance EltRepr' Int8 = Int8-type instance EltRepr' Int16 = Int16-type instance EltRepr' Int32 = Int32-type instance EltRepr' Int64 = Int64-type instance EltRepr' Word = Word-type instance EltRepr' Word8 = Word8-type instance EltRepr' Word16 = Word16-type instance EltRepr' Word32 = Word32-type instance EltRepr' Word64 = Word64-type instance EltRepr' CShort = CShort-type instance EltRepr' CUShort = CUShort-type instance EltRepr' CInt = CInt-type instance EltRepr' CUInt = CUInt-type instance EltRepr' CLong = CLong-type instance EltRepr' CULong = CULong-type instance EltRepr' CLLong = CLLong-type instance EltRepr' CULLong = CULLong-type instance EltRepr' Float = Float-type instance EltRepr' Double = Double-type instance EltRepr' CFloat = CFloat-type instance EltRepr' CDouble = CDouble-type instance EltRepr' Bool = Bool-type instance EltRepr' Char = Char-type instance EltRepr' CChar = CChar-type instance EltRepr' CSChar = CSChar-type instance EltRepr' CUChar = CUChar-type instance EltRepr' (a, b) = (EltRepr a, EltRepr' b)-type instance EltRepr' (a, b, c) = (EltRepr (a, b), EltRepr' c)-type instance EltRepr' (a, b, c, d) = (EltRepr (a, b, c), EltRepr' d)-type instance EltRepr' (a, b, c, d, e) = (EltRepr (a, b, c, d), EltRepr' e)-type instance EltRepr' (a, b, c, d, e, f) = (EltRepr (a, b, c, d, e), EltRepr' f)-type instance EltRepr' (a, b, c, d, e, f, g) = (EltRepr (a, b, c, d, e, f), EltRepr' g)-type instance EltRepr' (a, b, c, d, e, f, g, h) = (EltRepr (a, b, c, d, e, f, g), EltRepr' h)-type instance EltRepr' (a, b, c, d, e, f, g, h, i)-  = (EltRepr (a, b, c, d, e, f, g, h), EltRepr' i)----- Array elements (tuples of scalars)--- -------------------------------------- | Accelerate supports as array elements only simple atomic types, and tuples--- thereof. These element types are stored efficiently in memory, unpacked as--- consecutive elements without pointers.------ This class characterises the types of values that can be array elements, and--- hence, appear in scalar Accelerate expressions.----class (Show a, Typeable a,-       Typeable (EltRepr a), Typeable (EltRepr' a),-       ArrayElt (EltRepr a), ArrayElt (EltRepr' a))-      => Elt a where-  eltType  :: {-dummy-} a -> TupleType (EltRepr a)-  fromElt  :: a -> EltRepr a-  toElt    :: EltRepr a -> a--  eltType' :: {-dummy-} a -> TupleType (EltRepr' a)-  fromElt' :: a -> EltRepr' a-  toElt'   :: EltRepr' a -> a--instance Elt () where-  eltType _ = UnitTuple-  fromElt = id-  toElt   = id--  eltType' _ = UnitTuple-  fromElt' = id-  toElt'   = id--instance Elt Z where-  eltType _ = UnitTuple-  fromElt Z = ()-  toElt ()  = Z--  eltType' _ = UnitTuple-  fromElt' Z = ()-  toElt' ()  = Z--instance (Elt t, Elt h) => Elt (t:.h) where-  eltType (_::(t:.h)) = PairTuple (eltType (undefined :: t)) (eltType' (undefined :: h))-  fromElt (t:.h)      = (fromElt t, fromElt' h)-  toElt (t, h)        = toElt t :. toElt' h--  eltType' (_::(t:.h)) = PairTuple (eltType (undefined :: t)) (eltType' (undefined :: h))-  fromElt' (t:.h)      = (fromElt t, fromElt' h)-  toElt' (t, h)        = toElt t :. toElt' h--instance Elt All where-  eltType _      = PairTuple UnitTuple UnitTuple-  fromElt All    = ((), ())-  toElt ((), ()) = All--  eltType' _     = UnitTuple-  fromElt' All   = ()-  toElt' ()      = All--instance Elt (Any Z) where-  eltType _ = UnitTuple-  fromElt _ = ()-  toElt _   = Any--  eltType' _ = UnitTuple-  fromElt' _ = ()-  toElt' _   = Any--instance Shape sh => Elt (Any (sh:.Int)) where-  eltType _ = PairTuple (eltType (undefined::Any sh)) UnitTuple-  fromElt _ = (fromElt (undefined :: Any sh), ())-  toElt _   = Any--  eltType' _ = PairTuple (eltType' (undefined::Any sh)) UnitTuple-  fromElt' _ = (fromElt' (undefined :: Any sh), ())-  toElt' _   = Any--instance Elt Int where-  eltType       = singletonScalarType-  fromElt v     = ((), v)-  toElt ((), v) = v--  eltType' _    = SingleTuple scalarType-  fromElt'      = id-  toElt'        = id--instance Elt Int8 where-  eltType       = singletonScalarType-  fromElt v     = ((), v)-  toElt ((), v) = v--  eltType' _    = SingleTuple scalarType-  fromElt'      = id-  toElt'        = id--instance Elt Int16 where-  eltType       = singletonScalarType-  fromElt v     = ((), v)-  toElt ((), v) = v--  eltType' _    = SingleTuple scalarType-  fromElt'      = id-  toElt'        = id--instance Elt Int32 where-  eltType       = singletonScalarType-  fromElt v     = ((), v)-  toElt ((), v) = v--  eltType' _    = SingleTuple scalarType-  fromElt'      = id-  toElt'        = id--instance Elt Int64 where-  eltType       = singletonScalarType-  fromElt v     = ((), v)-  toElt ((), v) = v--  eltType' _    = SingleTuple scalarType-  fromElt'      = id-  toElt'        = id--instance Elt Word where-  eltType       = singletonScalarType-  fromElt v     = ((), v)-  toElt ((), v) = v--  eltType' _    = SingleTuple scalarType-  fromElt'      = id-  toElt'        = id--instance Elt Word8 where-  eltType       = singletonScalarType-  fromElt v     = ((), v)-  toElt ((), v) = v--  eltType' _    = SingleTuple scalarType-  fromElt'      = id-  toElt'        = id--instance Elt Word16 where-  eltType       = singletonScalarType-  fromElt v     = ((), v)-  toElt ((), v) = v--  eltType' _    = SingleTuple scalarType-  fromElt'      = id-  toElt'        = id--instance Elt Word32 where-  eltType       = singletonScalarType-  fromElt v     = ((), v)-  toElt ((), v) = v--  eltType' _    = SingleTuple scalarType-  fromElt'      = id-  toElt'        = id--instance Elt Word64 where-  eltType       = singletonScalarType-  fromElt v     = ((), v)-  toElt ((), v) = v--  eltType' _    = SingleTuple scalarType-  fromElt'      = id-  toElt'        = id---instance Elt CShort where-  eltType       = singletonScalarType-  fromElt v     = ((), v)-  toElt ((), v) = v--  eltType' _    = SingleTuple scalarType-  fromElt'      = id-  toElt'        = id--instance Elt CUShort where-  eltType       = singletonScalarType-  fromElt v     = ((), v)-  toElt ((), v) = v--  eltType' _    = SingleTuple scalarType-  fromElt'      = id-  toElt'        = id--instance Elt CInt where-  eltType       = singletonScalarType-  fromElt v     = ((), v)-  toElt ((), v) = v--  eltType' _    = SingleTuple scalarType-  fromElt'      = id-  toElt'        = id--instance Elt CUInt where-  eltType       = singletonScalarType-  fromElt v     = ((), v)-  toElt ((), v) = v--  eltType' _    = SingleTuple scalarType-  fromElt'      = id-  toElt'        = id--instance Elt CLong where-  eltType       = singletonScalarType-  fromElt v     = ((), v)-  toElt ((), v) = v--  eltType' _    = SingleTuple scalarType-  fromElt'      = id-  toElt'        = id--instance Elt CULong where-  eltType       = singletonScalarType-  fromElt v     = ((), v)-  toElt ((), v) = v--  eltType' _    = SingleTuple scalarType-  fromElt'      = id-  toElt'        = id--instance Elt CLLong where-  eltType       = singletonScalarType-  fromElt v     = ((), v)-  toElt ((), v) = v--  eltType' _    = SingleTuple scalarType-  fromElt'      = id-  toElt'        = id--instance Elt CULLong where-  eltType       = singletonScalarType-  fromElt v     = ((), v)-  toElt ((), v) = v--  eltType' _    = SingleTuple scalarType-  fromElt'      = id-  toElt'        = id--instance Elt Float where-  eltType       = singletonScalarType-  fromElt v     = ((), v)-  toElt ((), v) = v--  eltType' _    = SingleTuple scalarType-  fromElt'      = id-  toElt'        = id--instance Elt Double where-  eltType       = singletonScalarType-  fromElt v     = ((), v)-  toElt ((), v) = v--  eltType' _    = SingleTuple scalarType-  fromElt'      = id-  toElt'        = id--instance Elt CFloat where-  eltType       = singletonScalarType-  fromElt v     = ((), v)-  toElt ((), v) = v--  eltType' _    = SingleTuple scalarType-  fromElt'      = id-  toElt'        = id--instance Elt CDouble where-  eltType       = singletonScalarType-  fromElt v     = ((), v)-  toElt ((), v) = v--  eltType' _    = SingleTuple scalarType-  fromElt'      = id-  toElt'        = id---instance Elt Bool where-  eltType       = singletonScalarType-  fromElt v     = ((), v)-  toElt ((), v) = v--  eltType' _    = SingleTuple scalarType-  fromElt'      = id-  toElt'        = id--instance Elt Char where-  eltType       = singletonScalarType-  fromElt v     = ((), v)-  toElt ((), v) = v--  eltType' _    = SingleTuple scalarType-  fromElt'      = id-  toElt'        = id--instance Elt CChar where-  eltType       = singletonScalarType-  fromElt v     = ((), v)-  toElt ((), v) = v--  eltType' _    = SingleTuple scalarType-  fromElt'      = id-  toElt'        = id--instance Elt CSChar where-  eltType       = singletonScalarType-  fromElt v     = ((), v)-  toElt ((), v) = v--  eltType' _    = SingleTuple scalarType-  fromElt'      = id-  toElt'        = id--instance Elt CUChar where-  eltType       = singletonScalarType-  fromElt v     = ((), v)-  toElt ((), v) = v--  eltType' _    = SingleTuple scalarType-  fromElt'      = id-  toElt'        = id--instance (Elt a, Elt b) => Elt (a, b) where-  eltType (_::(a, b))-    = PairTuple (eltType (undefined :: a)) (eltType' (undefined :: b))-  fromElt (a, b)  = (fromElt a, fromElt' b)-  toElt (a, b)  = (toElt a, toElt' b)--  eltType' (_::(a, b))-    = PairTuple (eltType (undefined :: a)) (eltType' (undefined :: b))-  fromElt' (a, b) = (fromElt a, fromElt' b)-  toElt' (a, b) = (toElt a, toElt' b)--instance (Elt a, Elt b, Elt c) => Elt (a, b, c) where-  eltType (_::(a, b, c))-    = PairTuple (eltType (undefined :: (a, b))) (eltType' (undefined :: c))-  fromElt (a, b, c) = (fromElt (a, b), fromElt' c)-  toElt (ab, c) = let (a, b) = toElt ab in (a, b, toElt' c)--  eltType' (_::(a, b, c))-    = PairTuple (eltType (undefined :: (a, b))) (eltType' (undefined :: c))-  fromElt' (a, b, c) = (fromElt (a, b), fromElt' c)-  toElt' (ab, c) = let (a, b) = toElt ab in (a, b, toElt' c)--instance (Elt a, Elt b, Elt c, Elt d) => Elt (a, b, c, d) where-  eltType (_::(a, b, c, d))-    = PairTuple (eltType (undefined :: (a, b, c))) (eltType' (undefined :: d))-  fromElt (a, b, c, d) = (fromElt (a, b, c), fromElt' d)-  toElt (abc, d) = let (a, b, c) = toElt abc in (a, b, c, toElt' d)--  eltType' (_::(a, b, c, d))-    = PairTuple (eltType (undefined :: (a, b, c))) (eltType' (undefined :: d))-  fromElt' (a, b, c, d) = (fromElt (a, b, c), fromElt' d)-  toElt' (abc, d) = let (a, b, c) = toElt abc in (a, b, c, toElt' d)--instance (Elt a, Elt b, Elt c, Elt d, Elt e) => Elt (a, b, c, d, e) where-  eltType (_::(a, b, c, d, e))-    = PairTuple (eltType (undefined :: (a, b, c, d)))-                (eltType' (undefined :: e))-  fromElt (a, b, c, d, e) = (fromElt (a, b, c, d), fromElt' e)-  toElt (abcd, e) = let (a, b, c, d) = toElt abcd in (a, b, c, d, toElt' e)--  eltType' (_::(a, b, c, d, e))-    = PairTuple (eltType (undefined :: (a, b, c, d)))-                (eltType' (undefined :: e))-  fromElt' (a, b, c, d, e) = (fromElt (a, b, c, d), fromElt' e)-  toElt' (abcd, e) = let (a, b, c, d) = toElt abcd in (a, b, c, d, toElt' e)--instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f) => Elt (a, b, c, d, e, f) where-  eltType (_::(a, b, c, d, e, f))-    = PairTuple (eltType (undefined :: (a, b, c, d, e)))-                (eltType' (undefined :: f))-  fromElt (a, b, c, d, e, f) = (fromElt (a, b, c, d, e), fromElt' f)-  toElt (abcde, f) = let (a, b, c, d, e) = toElt abcde in (a, b, c, d, e, toElt' f)--  eltType' (_::(a, b, c, d, e, f))-    = PairTuple (eltType (undefined :: (a, b, c, d, e)))-                (eltType' (undefined :: f))-  fromElt' (a, b, c, d, e, f) = (fromElt (a, b, c, d, e), fromElt' f)-  toElt' (abcde, f) = let (a, b, c, d, e) = toElt abcde in (a, b, c, d, e, toElt' f)--instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g)-  => Elt (a, b, c, d, e, f, g) where-  eltType (_::(a, b, c, d, e, f, g))-    = PairTuple (eltType (undefined :: (a, b, c, d, e, f)))-                (eltType' (undefined :: g))-  fromElt (a, b, c, d, e, f, g) = (fromElt (a, b, c, d, e, f), fromElt' g)-  toElt (abcdef, g) = let (a, b, c, d, e, f) = toElt abcdef in (a, b, c, d, e, f, toElt' g)--  eltType' (_::(a, b, c, d, e, f, g))-    = PairTuple (eltType (undefined :: (a, b, c, d, e, f)))-                (eltType' (undefined :: g))-  fromElt' (a, b, c, d, e, f, g) = (fromElt (a, b, c, d, e, f), fromElt' g)-  toElt' (abcdef, g) = let (a, b, c, d, e, f) = toElt abcdef in (a, b, c, d, e, f, toElt' g)--instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h)-  => Elt (a, b, c, d, e, f, g, h) where-  eltType (_::(a, b, c, d, e, f, g, h))-    = PairTuple (eltType (undefined :: (a, b, c, d, e, f, g)))-                (eltType' (undefined :: h))-  fromElt (a, b, c, d, e, f, g, h) = (fromElt (a, b, c, d, e, f, g), fromElt' h)-  toElt (abcdefg, h) = let (a, b, c, d, e, f, g) = toElt abcdefg-                        in (a, b, c, d, e, f, g, toElt' h)--  eltType' (_::(a, b, c, d, e, f, g, h))-    = PairTuple (eltType (undefined :: (a, b, c, d, e, f, g)))-                (eltType' (undefined :: h))-  fromElt' (a, b, c, d, e, f, g, h) = (fromElt (a, b, c, d, e, f, g), fromElt' h)-  toElt' (abcdefg, h) = let (a, b, c, d, e, f, g) = toElt abcdefg-                         in (a, b, c, d, e, f, g, toElt' h)--instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i)-  => Elt (a, b, c, d, e, f, g, h, i) where-  eltType (_::(a, b, c, d, e, f, g, h, i))-    = PairTuple (eltType (undefined :: (a, b, c, d, e, f, g, h)))-                (eltType' (undefined :: i))-  fromElt (a, b, c, d, e, f, g, h, i) = (fromElt (a, b, c, d, e, f, g, h), fromElt' i)-  toElt (abcdefgh, i) = let (a, b, c, d, e, f, g, h) = toElt abcdefgh-                        in (a, b, c, d, e, f, g, h, toElt' i)--  eltType' (_::(a, b, c, d, e, f, g, h, i))-    = PairTuple (eltType (undefined :: (a, b, c, d, e, f, g, h)))-                (eltType' (undefined :: i))-  fromElt' (a, b, c, d, e, f, g, h, i) = (fromElt (a, b, c, d, e, f, g, h), fromElt' i)-  toElt' (abcdefgh, i) = let (a, b, c, d, e, f, g, h) = toElt abcdefgh-                         in (a, b, c, d, e, f, g, h, toElt' i)---- |Convenience functions-----singletonScalarType :: IsScalar a => a -> TupleType ((), a)-singletonScalarType _ = PairTuple UnitTuple (SingleTuple scalarType)--liftToElt :: (Elt a, Elt b)-          => (EltRepr a -> EltRepr b)-          -> (a -> b)-{-# INLINE liftToElt #-}-liftToElt f = toElt . f . fromElt--liftToElt2 :: (Elt a, Elt b, Elt c)-           => (EltRepr a -> EltRepr b -> EltRepr c)-           -> (a -> b -> c)-{-# INLINE liftToElt2 #-}-liftToElt2 f = \x y -> toElt $ f (fromElt x) (fromElt y)--sinkFromElt :: (Elt a, Elt b)-            => (a -> b)-            -> (EltRepr a -> EltRepr b)-{-# INLINE sinkFromElt #-}-sinkFromElt f = fromElt . f . toElt--sinkFromElt2 :: (Elt a, Elt b, Elt c)-             => (a -> b -> c)-             -> (EltRepr a -> EltRepr b -> EltRepr c)-{-# INLINE sinkFromElt2 #-}-sinkFromElt2 f = \x y -> fromElt $ f (toElt x) (toElt y)--{-# RULES--"fromElt/toElt" forall e.-  fromElt (toElt e) = e--"toElt/fromElt" forall e.-  toElt (fromElt e) = e #-}----- Foreign functions--- --------------------- Class for backends to choose their own representation of foreign functions.--- By default it has no instances. If a backend wishes to have an FFI it must--- provide an instance.----class Typeable f => Foreign (f :: * -> * -> *) where--  -- Backends should be able to produce a string representation of the foreign-  -- function for pretty printing, typically the name of the function.-  strForeign :: f args results -> String----- Surface arrays--- ------------------ We represent tuples of arrays in the same way as tuples of scalars; using--- '()' and '(,)' as type-level nil and snoc. This characterises the domain of--- results of Accelerate array computations.----type family ArrRepr a :: *-type instance ArrRepr () = ()-type instance ArrRepr (Array sh e) = ((), Array sh e)-type instance ArrRepr (b, a) = (ArrRepr b, ArrRepr' a)-type instance ArrRepr (c, b, a) = (ArrRepr (c, b), ArrRepr' a)-type instance ArrRepr (d, c, b, a) = (ArrRepr (d, c, b), ArrRepr' a)-type instance ArrRepr (e, d, c, b, a) = (ArrRepr (e, d, c, b), ArrRepr' a)-type instance ArrRepr (f, e, d, c, b, a) = (ArrRepr (f, e, d, c, b), ArrRepr' a)-type instance ArrRepr (g, f, e, d, c, b, a) = (ArrRepr (g, f, e, d, c, b), ArrRepr' a)-type instance ArrRepr (h, g, f, e, d, c, b, a) = (ArrRepr (h, g, f, e, d, c, b), ArrRepr' a)-type instance ArrRepr (i, h, g, f, e, d, c, b, a) = (ArrRepr (i, h, g, f, e, d, c, b), ArrRepr' a)--type family ArrRepr' a :: *-type instance ArrRepr' () = ()-type instance ArrRepr' (Array sh e) = Array sh e-type instance ArrRepr' (b, a) = (ArrRepr b, ArrRepr' a)-type instance ArrRepr' (c, b, a) = (ArrRepr (c, b), ArrRepr' a)-type instance ArrRepr' (d, c, b, a) = (ArrRepr (d, c, b), ArrRepr' a)-type instance ArrRepr' (e, d, c, b, a) = (ArrRepr (e, d, c, b), ArrRepr' a)-type instance ArrRepr' (f, e, d, c, b, a) = (ArrRepr (f, e, d, c, b), ArrRepr' a)-type instance ArrRepr' (g, f, e, d, c, b, a) = (ArrRepr (g, f, e, d, c, b), ArrRepr' a)-type instance ArrRepr' (h, g, f, e, d, c, b, a) = (ArrRepr (h, g, f, e, d, c, b), ArrRepr' a)-type instance ArrRepr' (i, h, g, f, e, d, c, b, a) = (ArrRepr (i, h, g, f, e, d, c, b), ArrRepr' a)---- Array type reification----data ArraysR arrs where-  ArraysRunit  ::                                   ArraysR ()-  ArraysRarray :: (Shape sh, Elt e) =>              ArraysR (Array sh e)-  ArraysRpair  :: ArraysR arrs1 -> ArraysR arrs2 -> ArraysR (arrs1, arrs2)--class (Typeable (ArrRepr a), Typeable (ArrRepr' a), Typeable a) => Arrays a where-  arrays   :: a {- dummy -} -> ArraysR (ArrRepr  a)-  arrays'  :: a {- dummy -} -> ArraysR (ArrRepr' a)-  ---  toArr    :: ArrRepr  a -> a-  toArr'   :: ArrRepr' a -> a-  fromArr  :: a -> ArrRepr  a-  fromArr' :: a -> ArrRepr' a---instance Arrays () where-  arrays  _ = ArraysRunit-  arrays' _ = ArraysRunit-  ---  toArr     = id-  toArr'    = id-  fromArr   = id-  fromArr'  = id--instance (Shape sh, Elt e) => Arrays (Array sh e) where-  arrays  _       = ArraysRpair ArraysRunit ArraysRarray-  arrays' _       = ArraysRarray-  ---  toArr ((), arr) = arr-  toArr'          = id-  fromArr arr     = ((), arr)-  fromArr'        = id--instance (Arrays b, Arrays a) => Arrays (b, a) where-  arrays  _ = ArraysRpair (arrays (undefined::b)) (arrays' (undefined::a))-  arrays' _ = ArraysRpair (arrays (undefined::b)) (arrays' (undefined::a))-  ---  toArr    (b, a) = (toArr b, toArr' a)-  toArr'   (b, a) = (toArr b, toArr' a)-  fromArr  (b, a) = (fromArr b, fromArr' a)-  fromArr' (b, a) = (fromArr b, fromArr' a)--instance (Arrays c, Arrays b, Arrays a) => Arrays (c, b, a) where-  arrays  _ = ArraysRpair (arrays (undefined::(c,b))) (arrays' (undefined::a))-  arrays' _ = ArraysRpair (arrays (undefined::(c,b))) (arrays' (undefined::a))-  ---  toArr    (cb, a) = let (c, b) = toArr cb in (c, b, toArr' a)-  toArr'   (cb, a) = let (c, b) = toArr cb in (c, b, toArr' a)-  fromArr  (c, b, a) = (fromArr (c, b), fromArr' a)-  fromArr' (c, b, a) = (fromArr (c, b), fromArr' a)--instance (Arrays d, Arrays c, Arrays b, Arrays a) => Arrays (d, c, b, a) where-  arrays  _ = ArraysRpair (arrays (undefined::(d,c,b))) (arrays' (undefined::a))-  arrays' _ = ArraysRpair (arrays (undefined::(d,c,b))) (arrays' (undefined::a))-  ---  toArr    (dcb, a) = let (d, c, b) = toArr dcb in (d, c, b, toArr' a)-  toArr'   (dcb, a) = let (d, c, b) = toArr dcb in (d, c, b, toArr' a)-  fromArr  (d, c, b, a) = (fromArr (d, c, b), fromArr' a)-  fromArr' (d, c, b, a) = (fromArr (d, c, b), fromArr' a)--instance (Arrays e, Arrays d, Arrays c, Arrays b, Arrays a) => Arrays (e, d, c, b, a) where-  arrays  _ = ArraysRpair (arrays (undefined::(e,d,c,b))) (arrays' (undefined::a))-  arrays' _ = ArraysRpair (arrays (undefined::(e,d,c,b))) (arrays' (undefined::a))-  ---  toArr    (edcb, a) = let (e, d, c, b) = toArr edcb in (e, d, c, b, toArr' a)-  toArr'   (edcb, a) = let (e, d, c, b) = toArr edcb in (e, d, c, b, toArr' a)-  fromArr  (e, d, c, b, a) = (fromArr (e, d, c, b), fromArr' a)-  fromArr' (e, d, c, b, a) = (fromArr (e, d, c, b), fromArr' a)--instance (Arrays f, Arrays e, Arrays d, Arrays c, Arrays b, Arrays a)-  => Arrays (f, e, d, c, b, a) where-  arrays  _ = ArraysRpair (arrays (undefined::(f,e,d,c,b))) (arrays' (undefined::a))-  arrays' _ = ArraysRpair (arrays (undefined::(f,e,d,c,b))) (arrays' (undefined::a))-  ---  toArr    (fedcb, a) = let (f, e, d, c, b) = toArr fedcb in (f, e, d, c, b, toArr' a)-  toArr'   (fedcb, a) = let (f, e, d, c, b) = toArr fedcb in (f, e, d, c, b, toArr' a)-  fromArr  (f, e, d, c, b, a) = (fromArr (f, e, d, c, b), fromArr' a)-  fromArr' (f, e, d, c, b, a) = (fromArr (f, e, d, c, b), fromArr' a)--instance (Arrays g, Arrays f, Arrays e, Arrays d, Arrays c, Arrays b, Arrays a)-  => Arrays (g, f, e, d, c, b, a) where-  arrays  _ = ArraysRpair (arrays (undefined::(g,f,e,d,c,b))) (arrays' (undefined::a))-  arrays' _ = ArraysRpair (arrays (undefined::(g,f,e,d,c,b))) (arrays' (undefined::a))-  ---  toArr    (gfedcb, a) = let (g, f, e, d, c, b) = toArr gfedcb in (g, f, e, d, c, b, toArr' a)-  toArr'   (gfedcb, a) = let (g, f, e, d, c, b) = toArr gfedcb in (g, f, e, d, c, b, toArr' a)-  fromArr  (g, f, e, d, c, b, a) = (fromArr (g, f, e, d, c, b), fromArr' a)-  fromArr' (g, f, e, d, c, b, a) = (fromArr (g, f, e, d, c, b), fromArr' a)--instance (Arrays h, Arrays g, Arrays f, Arrays e, Arrays d, Arrays c, Arrays b, Arrays a)-  => Arrays (h, g, f, e, d, c, b, a) where-  arrays  _ = ArraysRpair (arrays (undefined::(h,g,f,e,d,c,b))) (arrays' (undefined::a))-  arrays' _ = ArraysRpair (arrays (undefined::(h,g,f,e,d,c,b))) (arrays' (undefined::a))-  ---  toArr    (hgfedcb, a) = let (h, g, f, e, d, c, b) = toArr hgfedcb in (h, g, f, e, d, c, b, toArr' a)-  toArr'   (hgfedcb, a) = let (h, g, f, e, d, c, b) = toArr hgfedcb in (h, g, f, e, d, c, b, toArr' a)-  fromArr  (h, g, f, e, d, c, b, a) = (fromArr (h, g, f, e, d, c, b), fromArr' a)-  fromArr' (h, g, f, e, d, c, b, a) = (fromArr (h, g, f, e, d, c, b), fromArr' a)--instance (Arrays i, Arrays h, Arrays g, Arrays f, Arrays e, Arrays d, Arrays c, Arrays b, Arrays a)-  => Arrays (i, h, g, f, e, d, c, b, a) where-  arrays  _ = ArraysRpair (arrays (undefined::(i,h,g,f,e,d,c,b))) (arrays' (undefined::a))-  arrays' _ = ArraysRpair (arrays (undefined::(i,h,g,f,e,d,c,b))) (arrays' (undefined::a))-  ---  toArr    (ihgfedcb, a) = let (i, h, g, f, e, d, c, b) = toArr ihgfedcb in (i, h, g, f, e, d, c, b, toArr' a)-  toArr'   (ihgfedcb, a) = let (i, h, g, f, e, d, c, b) = toArr ihgfedcb in (i, h, g, f, e, d, c, b, toArr' a)-  fromArr  (i, h, g, f, e, d, c, b, a) = (fromArr (i, h, g, f, e, d, c, b), fromArr' a)-  fromArr' (i, h, g, f, e, d, c, b, a) = (fromArr (i, h, g, f, e, d, c, b), fromArr' a)--{-# RULES--"fromArr/toArr" forall a.-  fromArr (toArr a) = a--"toArr/fromArr" forall a.-  toArr (fromArr a) = a #-}----- |Multi-dimensional arrays for array processing.------ If device and host memory are separate, arrays will be transferred to the--- device when necessary (if possible asynchronously and in parallel with other--- tasks) and cached on the device if sufficient memory is available.----data Array sh e where-  Array :: (Shape sh, Elt e)-        => EltRepr sh                 -- extent of dimensions = shape-        -> ArrayData (EltRepr e)      -- array payload-        -> Array sh e--deriving instance Typeable Array---- |Scalars arrays hold a single element----type Scalar e = Array DIM0 e---- |Vectors are one-dimensional arrays----type Vector e = Array DIM1 e---- |Segment descriptor (vector of segment lengths).------ To represent nested one-dimensional arrays, we use a flat array of data--- values in conjunction with a /segment descriptor/, which stores the lengths--- of the subarrays.----type Segments i = Vector i---- Shorthand for common shape types----type DIM0 = Z-type DIM1 = DIM0:.Int-type DIM2 = DIM1:.Int-type DIM3 = DIM2:.Int-type DIM4 = DIM3:.Int-type DIM5 = DIM4:.Int-type DIM6 = DIM5:.Int-type DIM7 = DIM6:.Int-type DIM8 = DIM7:.Int-type DIM9 = DIM8:.Int---- Shape constraints and indexing--- ---------------------------------- |Shapes and indices of multi-dimensional arrays----class (Elt sh, Elt (Any sh), Repr.Shape (EltRepr sh)) => Shape sh where--  -- |Number of dimensions of a /shape/ or /index/ (>= 0).-  dim    :: sh -> Int--  -- |Total number of elements in an array of the given /shape/.-  size   :: sh -> Int--  -- |Magic value identifying elements ignored in 'permute'.-  ignore :: sh--  -- |Yield the intersection of two shapes-  intersect :: sh -> sh -> sh--  -- |Map a multi-dimensional index into one in a linear, row-major-  -- representation of the array (first argument is the /shape/, second-  -- argument is the index).-  toIndex   :: sh -> sh -> Int--  -- |Inverse of 'toIndex'.-  fromIndex :: sh -> Int -> sh--  -- |Apply a boundary condition to an index.-  bound  :: sh -> sh -> Boundary a -> Either a sh--  -- |Iterate through the entire shape, applying the function; third argument-  -- combines results and fourth is returned in case of an empty iteration-  -- space; the index space is traversed in row-major order.-  iter  :: sh -> (sh -> a) -> (a -> a -> a) -> a -> a--  -- |Variant of 'iter' without an initial value-  iter1 :: sh -> (sh -> a) -> (a -> a -> a) -> a--  -- |Convert a minpoint-maxpoint index into a /shape/.-  rangeToShape ::  (sh, sh) -> sh--  -- |Convert a /shape/ into a minpoint-maxpoint index.-  shapeToRange ::  sh -> (sh, sh)--  -- |Convert a shape to a list of dimensions.-  shapeToList :: sh -> [Int]--  -- |Convert a list of dimensions into a shape.-  listToShape :: [Int] -> sh--  -- | The slice index for slice specifier 'Any sh'-  sliceAnyIndex :: sh -> Repr.SliceIndex (EltRepr (Any sh)) (EltRepr sh) () (EltRepr sh)--  dim                   = Repr.dim . fromElt-  size                  = Repr.size . fromElt-  -- (#) must be individually defined, as it holds for all instances *except*-  -- the one with the largest arity--  ignore                = toElt Repr.ignore-  intersect sh1 sh2     = toElt (Repr.intersect (fromElt sh1) (fromElt sh2))-  fromIndex sh ix       = toElt (Repr.fromIndex (fromElt sh) ix)-  toIndex sh ix         = Repr.toIndex (fromElt sh) (fromElt ix)--  bound sh ix bndy      = case Repr.bound (fromElt sh) (fromElt ix) bndy of-                            Left v    -> Left v-                            Right ix' -> Right $ toElt ix'--  iter sh f c r         = Repr.iter  (fromElt sh) (f . toElt) c r-  iter1 sh f r          = Repr.iter1 (fromElt sh) (f . toElt) r--  rangeToShape (low, high)-    = toElt (Repr.rangeToShape (fromElt low, fromElt high))-  shapeToRange ix-    = let (low, high) = Repr.shapeToRange (fromElt ix)-      in-      (toElt low, toElt high)--  shapeToList = Repr.shapeToList . fromElt-  listToShape = toElt . Repr.listToShape--instance Shape Z where-  sliceAnyIndex _ = Repr.SliceNil--instance Shape sh => Shape (sh:.Int) where-  sliceAnyIndex _ = Repr.SliceAll (sliceAnyIndex (undefined :: sh))---- | Slices, aka generalised indices, as /n/-tuples and mappings of slice--- indices to slices, co-slices, and slice dimensions----class (Elt sl, Shape (SliceShape sl), Shape (CoSliceShape sl), Shape (FullShape sl))-       => Slice sl where-  type SliceShape   sl :: *     -- the projected slice-  type CoSliceShape sl :: *     -- the complement of the slice-  type FullShape    sl :: *     -- the combined dimension-  sliceIndex :: sl {- dummy -} -> Repr.SliceIndex (EltRepr sl)-                                    (EltRepr (SliceShape   sl))-                                    (EltRepr (CoSliceShape sl))-                                    (EltRepr (FullShape    sl))--instance Slice Z where-  type SliceShape   Z = Z-  type CoSliceShape Z = Z-  type FullShape    Z = Z-  sliceIndex _ = Repr.SliceNil--instance Slice sl => Slice (sl:.All) where-  type SliceShape   (sl:.All) = SliceShape   sl :. Int-  type CoSliceShape (sl:.All) = CoSliceShape sl-  type FullShape    (sl:.All) = FullShape    sl :. Int-  sliceIndex _ = Repr.SliceAll (sliceIndex (undefined :: sl))--instance Slice sl => Slice (sl:.Int) where-  type SliceShape   (sl:.Int) = SliceShape   sl-  type CoSliceShape (sl:.Int) = CoSliceShape sl :. Int-  type FullShape    (sl:.Int) = FullShape    sl :. Int-  sliceIndex _ = Repr.SliceFixed (sliceIndex (undefined :: sl))--instance Shape sh => Slice (Any sh) where-  type SliceShape   (Any sh) = sh-  type CoSliceShape (Any sh) = Z-  type FullShape    (Any sh) = sh-  sliceIndex _ = sliceAnyIndex (undefined :: sh)----- Array operations--- -------------------- |Yield an array's shape----shape :: Shape sh => Array sh e -> sh-shape (Array sh _) = toElt sh---- |Array indexing----infixl 9 !-(!) :: Array sh e -> sh -> e-{-# INLINE (!) #-}--- (Array sh adata) ! ix = toElt (adata `indexArrayData` index sh ix)--- FIXME: using this due to a bug in 6.10.x-(!) (Array sh adata) ix = toElt (adata `unsafeIndexArrayData` toIndex (toElt sh) ix)---- |Create an array from its representation function----newArray :: (Shape sh, Elt e) => sh -> (sh -> e) -> Array sh e-{-# INLINE newArray #-}-newArray sh f = adata `seq` Array (fromElt sh) adata-  where-    (adata, _) = runArrayData $ do-                   arr <- newArrayData (size sh)-                   let write ix = unsafeWriteArrayData arr (toIndex sh ix)-                                                           (fromElt (f ix))-                   iter sh write (>>) (return ())-                   return (arr, undefined)---- | Creates a new, uninitialized Accelerate array.----allocateArray :: (Shape sh, Elt e) => sh -> IO (Array sh e)-{-# INLINE allocateArray #-}-allocateArray sh = adata `seq` return (Array (fromElt sh) adata)-  where-    (adata, _) = runArrayData $ (,undefined) `fmap` newArrayData (size sh)----- | Convert an 'IArray' to an accelerated array.------ While the type signature mentions Accelerate internals that are not exported,--- in practice satisfying the type equality is straight forward. The index type--- @ix@ must be the unit type @()@ for singleton arrays, or an @Int@ or tuple of--- @Int@'s for multidimensional arrays.----fromIArray :: (EltRepr ix ~ EltRepr sh, IArray a e, IArray.Ix ix, Shape sh, Elt ix, Elt e)-           => a ix e -> Array sh e-fromIArray iarr = newArray (toElt sh) (\ix -> iarr IArray.! toElt (fromElt ix))-  where-    (lo,hi) = IArray.bounds iarr-    sh      = Repr.rangeToShape (fromElt lo, fromElt hi)---- | Convert an accelerated array to an 'IArray'.----toIArray :: (EltRepr ix ~ EltRepr sh, IArray a e, IArray.Ix ix, Shape sh, Elt ix, Elt e)-         => Array sh e -> a ix e-toIArray arr = IArray.array bnds [(ix, arr ! toElt (fromElt ix)) | ix <- IArray.range bnds]-  where-    (lo,hi) = Repr.shapeToRange (fromElt (shape arr))-    bnds    = (toElt lo, toElt hi)---- | Convert a list, with elements in row-major order, into an accelerated array.----fromList :: (Shape sh, Elt e) => sh -> [e] -> Array sh e-{-# INLINE fromList #-}-fromList sh xs = adata `seq` Array (fromElt sh) adata-  where-    -- Assume the array is in dense row-major order. This is safe because-    -- otherwise backends would not be able to directly memcpy.-    ---    !n          = size sh-    (adata, _)  = runArrayData $ do-                    arr <- newArrayData n-                    let go !i _ | i >= n = return ()-                        go !i (v:vs)     = unsafeWriteArrayData arr i (fromElt v) >> go (i+1) vs-                        go _  []         = error "Data.Array.Accelerate.fromList: not enough input data"-                    ---                    go 0 xs-                    return (arr, undefined)---- | Convert an accelerated array to a list in row-major order.----toList :: forall sh e. Array sh e -> [e]-{-# INLINE toList #-}-toList (Array sh adata) = go 0-  where-    -- Assume underling array is in row-major order. This is safe because-    -- otherwise backends would not be able to directly memcpy.-    ---    !n                  = Repr.size sh-    go !i | i >= n      = []-          | otherwise   = toElt (adata `unsafeIndexArrayData` i) : go (i+1)---- Convert an array to a string----instance Show (Array sh e) where-  show arr@Array{}-    = "Array (" ++ showShape (shape arr) ++ ") " ++ show (toList arr)--instance Elt e => IsList (Vector e) where-  type Item (Vector e) = e-  toList         = toList-  fromListN n xs = fromList (Z:.n) xs-  fromList xs    = GHC.fromListN (length xs) xs--{----- Specialised Show instances for dimensions zero, one, and two. Requires--- overlapping instances.------ TODO:---   * Formatting of the matrix should be better, such as aligning the columns?---   * Make matrix formatting optional? It is more difficult to copy/paste the---     result, for example.----instance Show (Scalar e) where-  show arr@Array{}-    = "Scalar Z " ++ show (toList arr)--instance Show (Vector e) where-  show arr@Array{}-    = "Vector (" ++ showShape (shape arr) ++ ") " ++ show (toList arr)--instance Show (Array DIM2 e) where-  show arr@Array{}-    = "Array (" ++ showShape (shape arr) ++ ") \n " ++ showMat (toMatrix (toList arr))-    where-      showRow xs        = intercalate "," (map show xs)-      showMat mat       = "[" ++ intercalate "\n ," (map showRow mat) ++ "]"--      Z :. _ :. cols    = shape arr-      toMatrix []       = []-      toMatrix xs       = let (r,rs) = splitAt cols xs-                          in  r : toMatrix rs---}---- | Nicely format a shape as a string----showShape :: Shape sh => sh -> String-showShape = foldr (\sh str -> str ++ " :. " ++ show sh) "Z" . shapeToList+{-# LANGUAGE CPP                   #-}+{-# LANGUAGE BangPatterns          #-}+{-# LANGUAGE ConstraintKinds       #-}+{-# LANGUAGE DeriveDataTypeable    #-}+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE GADTs                 #-}+{-# LANGUAGE ScopedTypeVariables   #-}+{-# LANGUAGE StandaloneDeriving    #-}+{-# LANGUAGE TupleSections         #-}+{-# LANGUAGE TypeFamilies          #-}+{-# LANGUAGE TypeOperators         #-}+{-# LANGUAGE UndecidableInstances  #-}+#if __GLASGOW_HASKELL__ <= 708+{-# OPTIONS_GHC -fno-warn-unrecognised-pragmas #-}+#endif+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.Array.Sugar+-- Copyright   : [2008..2017] Manuel M T Chakravarty, Gabriele Keller+--               [2009..2017] Trevor L. McDonell+--               [2013..2017] Robert Clifton-Everest+--               [2014..2014] Frederik M. Madsen+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Array.Sugar (++  -- * Array representation+  Array(..), Scalar, Vector, Segments,+  Arrays(..), ArraysR(..), ArraysFlavour(..), ArrRepr,++  -- * Class of supported surface element types and their mapping to representation types+  Elt(..), EltRepr,++  -- * Derived functions+  liftToElt, liftToElt2, sinkFromElt, sinkFromElt2,++  -- * Array shapes+  DIM0, DIM1, DIM2, DIM3, DIM4, DIM5, DIM6, DIM7, DIM8, DIM9,++  -- * Array indexing and slicing+  Z(..), (:.)(..), All(..), Split(..), Any(..), Divide(..), Shape(..), Slice(..), Division(..),++  -- * Array shape query, indexing, and conversions+  shape, (!), allocateArray, fromFunction, fromList, toList, concatVectors,++  -- * Tuples+  TupleR, TupleRepr, tuple,+  Tuple(..), IsTuple, fromTuple, toTuple,+  Atuple(..), IsAtuple, fromAtuple, toAtuple,++  -- * Miscellaneous+  showShape, Foreign(..), sliceShape, enumSlices,++) where++-- standard library+import Control.DeepSeq+import Data.List                                                ( intercalate, transpose )+import Data.Typeable++import GHC.Exts                                                 ( IsList )+import qualified GHC.Exts                                       as GHC++-- friends+import Data.Array.Accelerate.Type+import Data.Array.Accelerate.Array.Data+import Data.Array.Accelerate.Product+import qualified Data.Array.Accelerate.Array.Representation     as Repr+++-- Surface types representing array indices and slices+-- ---------------------------------------------------+--+-- Array indices are snoc type lists.  That is, they're backwards --+-- the end-of-list token, `Z`, occurs first.  For example, the type of a+-- rank-2 array index is @Z :. Int :. Int@.+--+-- In Accelerate the rightmost dimension is the /fastest varying/ or innermost.++-- |Rank-0 index+--+data Z = Z+  deriving (Typeable, Show, Eq)++-- |Increase an index rank by one dimension.  The `:.` operator is+--  used to construct both values and types.+--+infixl 3 :.+data tail :. head = tail :. head+  deriving (Typeable, Eq)++-- We don't we use a derived Show instance for (:.) because this will insert+-- parenthesis to demonstrate which order the operator is applied, i.e.:+--+--   (((Z :. z) :. y) :. x)+--+-- This is fine, but I find it a little unsightly. Instead, we drop all+-- parenthesis and just display the shape thus:+--+--   Z :. z :. y :. x+--+-- and then require the down-stream user to wrap the whole thing in parentheses.+-- This works fine for the most important case, which is to show Acc and Exp+-- expressions via the pretty printer, although Show-ing a Shape directly+-- results in no parenthesis being displayed.+--+-- One way around this might be to have specialised instances for DIM1, DIM2,+-- etc.+--+instance (Show sh, Show sz) => Show (sh :. sz) where+  show (sh :. sz) = show sh ++ " :. " ++ show sz++-- | Marker for entire dimensions in 'Data.Array.Accelerate.Language.slice' and+-- 'Data.Array.Accelerate.Language.replicate' descriptors.+--+-- Occurrences of 'All' indicate the dimensions into which the array's existing+-- extent will be placed unchanged.+--+-- See 'Data.Array.Accelerate.Language.slice' and+-- 'Data.Array.Accelerate.Language.replicate' for examples.+--+data All = All+  deriving (Typeable, Show, Eq)++-- | Marker for arbitrary dimensions in 'Data.Array.Accelerate.Language.slice'+-- and 'Data.Array.Accelerate.Language.replicate' descriptors.+--+-- 'Any' can be used in the leftmost position of a slice instead of 'Z',+-- indicating that any dimensionality is admissible in that position.+--+-- See 'Data.Array.Accelerate.Language.slice' and+-- 'Data.Array.Accelerate.Language.replicate' for examples.+--+data Any sh = Any+  deriving (Typeable, Show, Eq)++-- | Marker for splitting along an entire dimension in division descriptors.+--+-- For example, when used in a division descriptor passed to+-- 'Data.Array.Accelerate.toSeq', a `Split` indicates that the array should be+-- divided along this dimension forming the elements of the output sequence.+--+data Split = Split+  deriving (Typeable, Show, Eq)++-- | Marker for arbitrary shapes in slices descriptors, where it is desired to+-- split along an unknown number of dimensions.+--+-- For example, in the following definition, 'Divide' matches against any shape+-- and flattens everything but the innermost dimension.+--+-- > vectors :: (Shape sh, Elt e) => Acc (Array (sh:.Int) e) -> Seq [Vector e]+-- > vectors = toSeq (Divide :. All)+--+data Divide sh = Divide+  deriving (Typeable, Show, Eq)+++-- Representation change for array element types+-- ---------------------------------------------++-- | Type representation mapping+--+-- We represent tuples by using '()' and '(,)' as type-level nil and snoc to+-- construct snoc-lists of types, and are flattened all the way down to+-- primitive types.+--+type family EltRepr a :: *+type instance EltRepr ()              = ()+type instance EltRepr Z               = ()+type instance EltRepr (t:.h)          = (EltRepr t, EltRepr h)+type instance EltRepr All             = ()+type instance EltRepr (Any Z)         = ()+type instance EltRepr (Any (sh:.Int)) = (EltRepr (Any sh), ())+type instance EltRepr Int             = Int+type instance EltRepr Int8            = Int8+type instance EltRepr Int16           = Int16+type instance EltRepr Int32           = Int32+type instance EltRepr Int64           = Int64+type instance EltRepr Word            = Word+type instance EltRepr Word8           = Word8+type instance EltRepr Word16          = Word16+type instance EltRepr Word32          = Word32+type instance EltRepr Word64          = Word64+type instance EltRepr CShort          = CShort+type instance EltRepr CUShort         = CUShort+type instance EltRepr CInt            = CInt+type instance EltRepr CUInt           = CUInt+type instance EltRepr CLong           = CLong+type instance EltRepr CULong          = CULong+type instance EltRepr CLLong          = CLLong+type instance EltRepr CULLong         = CULLong+type instance EltRepr Float           = Float+type instance EltRepr Double          = Double+type instance EltRepr CFloat          = CFloat+type instance EltRepr CDouble         = CDouble+type instance EltRepr Bool            = Bool+type instance EltRepr Char            = Char+type instance EltRepr CChar           = CChar+type instance EltRepr CSChar          = CSChar+type instance EltRepr CUChar          = CUChar+type instance EltRepr (a, b)          = TupleRepr (EltRepr a, EltRepr b)+type instance EltRepr (a, b, c)       = TupleRepr (EltRepr a, EltRepr b, EltRepr c)+type instance EltRepr (a, b, c, d)    = TupleRepr (EltRepr a, EltRepr b, EltRepr c, EltRepr d)+type instance EltRepr (a, b, c, d, e) = TupleRepr (EltRepr a, EltRepr b, EltRepr c, EltRepr d, EltRepr e)+type instance EltRepr (a, b, c, d, e, f) = TupleRepr (EltRepr a, EltRepr b, EltRepr c, EltRepr d, EltRepr e, EltRepr f)+type instance EltRepr (a, b, c, d, e, f, g) = TupleRepr (EltRepr a, EltRepr b, EltRepr c, EltRepr d, EltRepr e, EltRepr f, EltRepr g)+type instance EltRepr (a, b, c, d, e, f, g, h) = TupleRepr (EltRepr a, EltRepr b, EltRepr c, EltRepr d, EltRepr e, EltRepr f, EltRepr g, EltRepr h)+type instance EltRepr (a, b, c, d, e, f, g, h, i) = TupleRepr (EltRepr a, EltRepr b, EltRepr c, EltRepr d, EltRepr e, EltRepr f, EltRepr g, EltRepr h, EltRepr i)+type instance EltRepr (a, b, c, d, e, f, g, h, i, j) = TupleRepr (EltRepr a, EltRepr b, EltRepr c, EltRepr d, EltRepr e, EltRepr f, EltRepr g, EltRepr h, EltRepr i, EltRepr j)+type instance EltRepr (a, b, c, d, e, f, g, h, i, j, k) = TupleRepr (EltRepr a, EltRepr b, EltRepr c, EltRepr d, EltRepr e, EltRepr f, EltRepr g, EltRepr h, EltRepr i, EltRepr j, EltRepr k)+type instance EltRepr (a, b, c, d, e, f, g, h, i, j, k, l) = TupleRepr (EltRepr a, EltRepr b, EltRepr c, EltRepr d, EltRepr e, EltRepr f, EltRepr g, EltRepr h, EltRepr i, EltRepr j, EltRepr k, EltRepr l)+type instance EltRepr (a, b, c, d, e, f, g, h, i, j, k, l, m) = TupleRepr (EltRepr a, EltRepr b, EltRepr c, EltRepr d, EltRepr e, EltRepr f, EltRepr g, EltRepr h, EltRepr i, EltRepr j, EltRepr k, EltRepr l, EltRepr m)+type instance EltRepr (a, b, c, d, e, f, g, h, i, j, k, l, m, n) = TupleRepr (EltRepr a, EltRepr b, EltRepr c, EltRepr d, EltRepr e, EltRepr f, EltRepr g, EltRepr h, EltRepr i, EltRepr j, EltRepr k, EltRepr l, EltRepr m, EltRepr n)+type instance EltRepr (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) = TupleRepr (EltRepr a, EltRepr b, EltRepr c, EltRepr d, EltRepr e, EltRepr f, EltRepr g, EltRepr h, EltRepr i, EltRepr j, EltRepr k, EltRepr l, EltRepr m, EltRepr n, EltRepr o)++type IsTuple = IsProduct Elt++fromTuple :: IsTuple tup => tup -> TupleRepr tup+fromTuple = fromProd (Proxy :: Proxy Elt)++toTuple :: IsTuple tup => TupleRepr tup -> tup+toTuple = toProd (Proxy :: Proxy Elt)+++-- Array elements (tuples of scalars)+-- ----------------------------------++-- | The 'Elt' class characterises the allowable array element types, and hence+-- the types which can appear in scalar Accelerate expressions.+--+-- Accelerate arrays consist of simple atomic types as well as nested tuples+-- thereof, stored efficiently in memory as consecutive unpacked elements+-- without pointers. It roughly consists of:+--+--  * Signed and unsigned integers (8, 16, 32, and 64-bits wide)+--  * Floating point numbers (single and double precision)+--  * 'Char'+--  * 'Bool'+--  * ()+--  * Shapes formed from 'Z' and (':.')+--  * Nested tuples of all of these, currently up to 15-elements wide+--+-- Adding new instances for 'Elt' consists of explaining to Accelerate how to+-- map between your data type and a (tuple of) primitive values. For examples+-- see:+--+--  * "Data.Array.Accelerate.Data.Complex"+--  * "Data.Array.Accelerate.Data.Monoid"+--  * <https://hackage.haskell.org/package/linear-accelerate linear-accelerate>+--  * <https://hackage.haskell.org/package/colour-accelerate colour-accelerate>+--+class (Show a, Typeable a, Typeable (EltRepr a), ArrayElt (EltRepr a))+      => Elt a where+  eltType  :: {-dummy-} a -> TupleType (EltRepr a)+  fromElt  :: a -> EltRepr a+  toElt    :: EltRepr a -> a++instance Elt () where+  eltType _ = UnitTuple+  fromElt   = id+  toElt     = id++instance Elt Z where+  eltType _  = UnitTuple+  fromElt Z  = ()+  toElt ()   = Z++instance (Elt t, Elt h) => Elt (t:.h) where+  eltType (_::(t:.h))   = PairTuple (eltType (undefined :: t)) (eltType (undefined :: h))+  fromElt (t:.h)        = (fromElt t, fromElt h)+  toElt (t, h)          = toElt t :. toElt h++instance Elt All where+  eltType _     = UnitTuple+  fromElt All   = ()+  toElt ()      = All++instance Elt (Any Z) where+  eltType _     = UnitTuple+  fromElt _     = ()+  toElt _       = Any++instance Shape sh => Elt (Any (sh:.Int)) where+  eltType _     = PairTuple (eltType (undefined::Any sh)) UnitTuple+  fromElt _     = (fromElt (undefined :: Any sh), ())+  toElt _       = Any++instance Elt Int where+  eltType       = singletonScalarType+  fromElt       = id+  toElt         = id++instance Elt Int8 where+  eltType       = singletonScalarType+  fromElt       = id+  toElt         = id++instance Elt Int16 where+  eltType       = singletonScalarType+  fromElt       = id+  toElt         = id++instance Elt Int32 where+  eltType       = singletonScalarType+  fromElt       = id+  toElt         = id++instance Elt Int64 where+  eltType       = singletonScalarType+  fromElt       = id+  toElt         = id++instance Elt Word where+  eltType       = singletonScalarType+  fromElt       = id+  toElt         = id++instance Elt Word8 where+  eltType       = singletonScalarType+  fromElt       = id+  toElt         = id++instance Elt Word16 where+  eltType       = singletonScalarType+  fromElt       = id+  toElt         = id++instance Elt Word32 where+  eltType       = singletonScalarType+  fromElt       = id+  toElt         = id++instance Elt Word64 where+  eltType       = singletonScalarType+  fromElt       = id+  toElt         = id++instance Elt CShort where+  eltType       = singletonScalarType+  fromElt       = id+  toElt         = id++instance Elt CUShort where+  eltType       = singletonScalarType+  fromElt       = id+  toElt         = id++instance Elt CInt where+  eltType       = singletonScalarType+  fromElt       = id+  toElt         = id++instance Elt CUInt where+  eltType       = singletonScalarType+  fromElt       = id+  toElt         = id++instance Elt CLong where+  eltType       = singletonScalarType+  fromElt       = id+  toElt         = id++instance Elt CULong where+  eltType       = singletonScalarType+  fromElt       = id+  toElt         = id++instance Elt CLLong where+  eltType       = singletonScalarType+  fromElt       = id+  toElt         = id++instance Elt CULLong where+  eltType       = singletonScalarType+  fromElt       = id+  toElt         = id++instance Elt Float where+  eltType       = singletonScalarType+  fromElt       = id+  toElt         = id++instance Elt Double where+  eltType       = singletonScalarType+  fromElt       = id+  toElt         = id++instance Elt CFloat where+  eltType       = singletonScalarType+  fromElt       = id+  toElt         = id++instance Elt CDouble where+  eltType       = singletonScalarType+  fromElt       = id+  toElt         = id++instance Elt Bool where+  eltType       = singletonScalarType+  fromElt       = id+  toElt         = id++instance Elt Char where+  eltType       = singletonScalarType+  fromElt       = id+  toElt         = id++instance Elt CChar where+  eltType       = singletonScalarType+  fromElt       = id+  toElt         = id++instance Elt CSChar where+  eltType       = singletonScalarType+  fromElt       = id+  toElt         = id++instance Elt CUChar where+  eltType       = singletonScalarType+  fromElt       = id+  toElt         = id++instance (Elt a, Elt b) => Elt (a, b) where+  eltType _             = PairTuple (PairTuple UnitTuple (eltType (undefined::a))) (eltType (undefined::b))+  fromElt (a,b)         = (((), fromElt a), fromElt b)+  toElt (((),a),b)      = (toElt a, toElt b)++instance (Elt a, Elt b, Elt c) => Elt (a, b, c) where+  eltType _             = PairTuple (eltType (undefined :: (a, b))) (eltType (undefined :: c))+  fromElt (a, b, c)     = (fromElt (a, b), fromElt c)+  toElt (ab, c)         = let (a, b) = toElt ab in (a, b, toElt c)++instance (Elt a, Elt b, Elt c, Elt d) => Elt (a, b, c, d) where+  eltType _             = PairTuple (eltType (undefined :: (a, b, c))) (eltType (undefined :: d))+  fromElt (a, b, c, d)  = (fromElt (a, b, c), fromElt d)+  toElt (abc, d)        = let (a, b, c) = toElt abc in (a, b, c, toElt d)++instance (Elt a, Elt b, Elt c, Elt d, Elt e) => Elt (a, b, c, d, e) where+  eltType _               = PairTuple (eltType (undefined :: (a, b, c, d))) (eltType (undefined :: e))+  fromElt (a, b, c, d, e) = (fromElt (a, b, c, d), fromElt e)+  toElt (abcd, e)         = let (a, b, c, d) = toElt abcd in (a, b, c, d, toElt e)++instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f) => Elt (a, b, c, d, e, f) where+  eltType _+    = PairTuple (eltType (undefined :: (a, b, c, d, e)))+                (eltType (undefined :: f))+  fromElt (a, b, c, d, e, f) = (fromElt (a, b, c, d, e), fromElt f)+  toElt (abcde, f) = let (a, b, c, d, e) = toElt abcde in (a, b, c, d, e, toElt f)++instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g)+  => Elt (a, b, c, d, e, f, g) where+  eltType _+    = PairTuple (eltType (undefined :: (a, b, c, d, e, f)))+                (eltType (undefined :: g))+  fromElt (a, b, c, d, e, f, g) = (fromElt (a, b, c, d, e, f), fromElt g)+  toElt (abcdef, g) = let (a, b, c, d, e, f) = toElt abcdef+                      in  (a, b, c, d, e, f, toElt g)++instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h)+  => Elt (a, b, c, d, e, f, g, h) where+  eltType _+    = PairTuple (eltType (undefined :: (a, b, c, d, e, f, g)))+                (eltType (undefined :: h))+  fromElt (a, b, c, d, e, f, g, h) = (fromElt (a, b, c, d, e, f, g), fromElt h)+  toElt (abcdefg, h) = let (a, b, c, d, e, f, g) = toElt abcdefg+                       in  (a, b, c, d, e, f, g, toElt h)++instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i)+  => Elt (a, b, c, d, e, f, g, h, i) where+  eltType _+    = PairTuple (eltType (undefined :: (a, b, c, d, e, f, g, h)))+                (eltType (undefined :: i))+  fromElt (a, b, c, d, e, f, g, h, i) = (fromElt (a, b, c, d, e, f, g, h), fromElt i)+  toElt (abcdefgh, i) = let (a, b, c, d, e, f, g, h) = toElt abcdefgh+                        in  (a, b, c, d, e, f, g, h, toElt i)++instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j)+  => Elt (a, b, c, d, e, f, g, h, i, j) where+  eltType _+    = PairTuple (eltType (undefined :: (a, b, c, d, e, f, g, h, i)))+                (eltType (undefined :: j))+  fromElt (a, b, c, d, e, f, g, h, i, j) = (fromElt (a, b, c, d, e, f, g, h, i), fromElt j)+  toElt (abcdefghi, j) = let (a, b, c, d, e, f, g, h, i) = toElt abcdefghi+                         in  (a, b, c, d, e, f, g, h, i, toElt j)++instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k)+  => Elt (a, b, c, d, e, f, g, h, i, j, k) where+  eltType _+    = PairTuple (eltType (undefined :: (a, b, c, d, e, f, g, h, i, j)))+                (eltType (undefined :: k))+  fromElt (a, b, c, d, e, f, g, h, i, j, k) = (fromElt (a, b, c, d, e, f, g, h, i, j), fromElt k)+  toElt (abcdefghij, k) = let (a, b, c, d, e, f, g, h, i, j) = toElt abcdefghij+                          in  (a, b, c, d, e, f, g, h, i, j, toElt k)++instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l)+  => Elt (a, b, c, d, e, f, g, h, i, j, k, l) where+  eltType _+    = PairTuple (eltType (undefined :: (a, b, c, d, e, f, g, h, i, j, k)))+                (eltType (undefined :: l))+  fromElt (a, b, c, d, e, f, g, h, i, j, k, l) = (fromElt (a, b, c, d, e, f, g, h, i, j, k), fromElt l)+  toElt (abcdefghijk, l) = let (a, b, c, d, e, f, g, h, i, j, k) = toElt abcdefghijk+                           in  (a, b, c, d, e, f, g, h, i, j, k, toElt l)++instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l, Elt m)+  => Elt (a, b, c, d, e, f, g, h, i, j, k, l, m) where+  eltType _+    = PairTuple (eltType (undefined :: (a, b, c, d, e, f, g, h, i, j, k, l)))+                (eltType (undefined :: m))+  fromElt (a, b, c, d, e, f, g, h, i, j, k, l, m) = (fromElt (a, b, c, d, e, f, g, h, i, j, k, l), fromElt m)+  toElt (abcdefghijkl, m) = let (a, b, c, d, e, f, g, h, i, j, k, l) = toElt abcdefghijkl+                            in  (a, b, c, d, e, f, g, h, i, j, k, l, toElt m)++instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l, Elt m, Elt n)+  => Elt (a, b, c, d, e, f, g, h, i, j, k, l, m, n) where+  eltType _+    = PairTuple (eltType (undefined :: (a, b, c, d, e, f, g, h, i, j, k, l, m)))+                (eltType (undefined :: n))+  fromElt (a, b, c, d, e, f, g, h, i, j, k, l, m, n) = (fromElt (a, b, c, d, e, f, g, h, i, j, k, l, m), fromElt n)+  toElt (abcdefghijklm, n) = let (a, b, c, d, e, f, g, h, i, j, k, l, m) = toElt abcdefghijklm+                             in  (a, b, c, d, e, f, g, h, i, j, k, l, m, toElt n)++instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l, Elt m, Elt n, Elt o)+  => Elt (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) where+  eltType _+    = PairTuple (eltType (undefined :: (a, b, c, d, e, f, g, h, i, j, k, l, m, n)))+                (eltType (undefined :: o))+  fromElt (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) = (fromElt (a, b, c, d, e, f, g, h, i, j, k, l, m, n), fromElt o)+  toElt (abcdefghijklmn, o) = let (a, b, c, d, e, f, g, h, i, j, k, l, m, n) = toElt abcdefghijklmn+                              in  (a, b, c, d, e, f, g, h, i, j, k, l, m, n, toElt o)+++-- |Convenience functions+--++singletonScalarType :: IsScalar a => a -> TupleType a+singletonScalarType _ = SingleTuple scalarType++liftToElt :: (Elt a, Elt b)+          => (EltRepr a -> EltRepr b)+          -> (a -> b)+{-# INLINE liftToElt #-}+liftToElt f = toElt . f . fromElt++liftToElt2 :: (Elt a, Elt b, Elt c)+           => (EltRepr a -> EltRepr b -> EltRepr c)+           -> (a -> b -> c)+{-# INLINE liftToElt2 #-}+liftToElt2 f = \x y -> toElt $ f (fromElt x) (fromElt y)++sinkFromElt :: (Elt a, Elt b)+            => (a -> b)+            -> (EltRepr a -> EltRepr b)+{-# INLINE sinkFromElt #-}+sinkFromElt f = fromElt . f . toElt++sinkFromElt2 :: (Elt a, Elt b, Elt c)+             => (a -> b -> c)+             -> (EltRepr a -> EltRepr b -> EltRepr c)+{-# INLINE sinkFromElt2 #-}+sinkFromElt2 f = \x y -> fromElt $ f (toElt x) (toElt y)++-- {-# RULES+-- "fromElt/toElt" forall e. fromElt (toElt e) = e+-- "toElt/fromElt" forall e. toElt (fromElt e) = e+-- #-}+++-- Foreign functions+-- -----------------++-- Class for backends to choose their own representation of foreign functions.+-- By default it has no instances. If a backend wishes to have an FFI it must+-- provide an instance.+--+class Typeable asm => Foreign asm where++  -- Backends should be able to produce a string representation of the foreign+  -- function for pretty printing, typically the name of the function.+  strForeign :: asm args -> String+++-- Surface arrays+-- --------------++-- We represent tuples of arrays in the same way as tuples of scalars; using+-- '()' and '(,)' as type-level nil and snoc. This characterises the domain of+-- results of Accelerate array computations.+--+type family ArrRepr a :: *+type instance ArrRepr ()           = ()+type instance ArrRepr (Array sh e) = Array sh e+type instance ArrRepr (a, b)       = TupleRepr (ArrRepr a, ArrRepr b)+type instance ArrRepr (a, b, c)    = TupleRepr (ArrRepr a, ArrRepr b, ArrRepr c)+type instance ArrRepr (a, b, c, d) = TupleRepr (ArrRepr a, ArrRepr b, ArrRepr c, ArrRepr d)+type instance ArrRepr (a, b, c, d, e) = TupleRepr (ArrRepr a, ArrRepr b, ArrRepr c, ArrRepr d, ArrRepr e)+type instance ArrRepr (a, b, c, d, e, f) = TupleRepr (ArrRepr a, ArrRepr b, ArrRepr c, ArrRepr d, ArrRepr e, ArrRepr f)+type instance ArrRepr (a, b, c, d, e, f, g) = TupleRepr (ArrRepr a, ArrRepr b, ArrRepr c, ArrRepr d, ArrRepr e, ArrRepr f, ArrRepr g)+type instance ArrRepr (a, b, c, d, e, f, g, h) = TupleRepr (ArrRepr a, ArrRepr b, ArrRepr c, ArrRepr d, ArrRepr e, ArrRepr f, ArrRepr g, ArrRepr h)+type instance ArrRepr (a, b, c, d, e, f, g, h, i) = TupleRepr (ArrRepr a, ArrRepr b, ArrRepr c, ArrRepr d, ArrRepr e, ArrRepr f, ArrRepr g, ArrRepr h, ArrRepr i)+type instance ArrRepr (a, b, c, d, e, f, g, h, i, j) = TupleRepr (ArrRepr a, ArrRepr b, ArrRepr c, ArrRepr d, ArrRepr e, ArrRepr f, ArrRepr g, ArrRepr h, ArrRepr i, ArrRepr j)+type instance ArrRepr (a, b, c, d, e, f, g, h, i, j, k) = TupleRepr (ArrRepr a, ArrRepr b, ArrRepr c, ArrRepr d, ArrRepr e, ArrRepr f, ArrRepr g, ArrRepr h, ArrRepr i, ArrRepr j, ArrRepr k)+type instance ArrRepr (a, b, c, d, e, f, g, h, i, j, k, l) = TupleRepr (ArrRepr a, ArrRepr b, ArrRepr c, ArrRepr d, ArrRepr e, ArrRepr f, ArrRepr g, ArrRepr h, ArrRepr i, ArrRepr j, ArrRepr k, ArrRepr l)+type instance ArrRepr (a, b, c, d, e, f, g, h, i, j, k, l, m) = TupleRepr (ArrRepr a, ArrRepr b, ArrRepr c, ArrRepr d, ArrRepr e, ArrRepr f, ArrRepr g, ArrRepr h, ArrRepr i, ArrRepr j, ArrRepr k, ArrRepr l, ArrRepr m)+type instance ArrRepr (a, b, c, d, e, f, g, h, i, j, k, l, m, n) = TupleRepr (ArrRepr a, ArrRepr b, ArrRepr c, ArrRepr d, ArrRepr e, ArrRepr f, ArrRepr g, ArrRepr h, ArrRepr i, ArrRepr j, ArrRepr k, ArrRepr l, ArrRepr m, ArrRepr n)+type instance ArrRepr (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) = TupleRepr (ArrRepr a, ArrRepr b, ArrRepr c, ArrRepr d, ArrRepr e, ArrRepr f, ArrRepr g, ArrRepr h, ArrRepr i, ArrRepr j, ArrRepr k, ArrRepr l, ArrRepr m, ArrRepr n, ArrRepr o)++type IsAtuple = IsProduct Arrays++fromAtuple :: IsAtuple tup => tup -> TupleRepr tup+fromAtuple = fromProd (Proxy :: Proxy Arrays)++toAtuple :: IsAtuple tup => TupleRepr tup -> tup+toAtuple = toProd (Proxy :: Proxy Arrays)++-- Array type reification+--+data ArraysR arrs where+  ArraysRunit  ::                                   ArraysR ()+  ArraysRarray :: (Shape sh, Elt e) =>              ArraysR (Array sh e)+  ArraysRpair  :: ArraysR arrs1 -> ArraysR arrs2 -> ArraysR (arrs1, arrs2)++data ArraysFlavour arrs where+  ArraysFunit  ::                                          ArraysFlavour ()+  ArraysFarray :: (Shape sh, Elt e)                     => ArraysFlavour (Array sh e)+  ArraysFtuple :: (IsAtuple arrs, ArrRepr arrs ~ (l,r)) => ArraysFlavour arrs++-- | 'Arrays' consists of nested tuples of individual 'Array's, currently up to+-- 15-elements wide. Accelerate computations can thereby return multiple+-- results.+--+class (Typeable a, Typeable (ArrRepr a)) => Arrays a where+  arrays   :: a {- dummy -} -> ArraysR (ArrRepr a)+  flavour  :: a {- dummy -} -> ArraysFlavour a+  --+  toArr    :: ArrRepr  a -> a+  fromArr  :: a -> ArrRepr  a+++instance Arrays () where+  arrays  _ = ArraysRunit+  flavour _ = ArraysFunit+  --+  toArr     = id+  fromArr   = id++instance (Shape sh, Elt e) => Arrays (Array sh e) where+  arrays _      = ArraysRarray+  flavour _     = ArraysFarray+  --+  toArr         = id+  fromArr       = id++instance (Arrays a, Arrays b) => Arrays (a, b) where+  arrays  _             = ArraysRpair (ArraysRpair ArraysRunit (arrays (undefined::a))) (arrays (undefined::b))+  flavour _             = ArraysFtuple+  --+  toArr    (((),a), b)  = (toArr a, toArr b)+  fromArr  (a, b)       = (((), fromArr a), fromArr b)++instance (Arrays a, Arrays b, Arrays c) => Arrays (a, b, c) where+  arrays  _             = ArraysRpair (arrays (undefined :: (a, b))) (arrays (undefined::c))+  flavour _             = ArraysFtuple+  --+  toArr    (ab, c)      = let (a, b) = toArr ab in (a, b, toArr c)+  fromArr  (a, b, c)    = (fromArr (a, b), fromArr c)++instance (Arrays a, Arrays b, Arrays c, Arrays d) => Arrays (a, b, c, d) where+  arrays  _             = ArraysRpair (arrays (undefined :: (a, b, c))) (arrays (undefined::d))+  flavour _             = ArraysFtuple+  --+  toArr    (abc, d)     = let (a, b, c) = toArr abc in (a, b, c, toArr d)+  fromArr  (a, b, c, d) = (fromArr (a, b, c), fromArr d)++instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e) => Arrays (a, b, c, d, e) where+  arrays  _             = ArraysRpair (arrays (undefined :: (a, b, c, d))) (arrays (undefined::e))+  flavour _             = ArraysFtuple+  --+  toArr    (abcd, e)    = let (a, b, c, d) = toArr abcd in (a, b, c, d, toArr e)+  fromArr  (a, b, c, d, e) = (fromArr (a, b, c, d), fromArr e)++instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f)+  => Arrays (a, b, c, d, e, f) where+  arrays  _             = ArraysRpair (arrays (undefined :: (a, b, c, d, e))) (arrays (undefined::f))+  flavour _             = ArraysFtuple+  --+  toArr    (abcde, f)   = let (a, b, c, d, e) = toArr abcde in (a, b, c, d, e, toArr f)+  fromArr  (a, b, c, d, e, f) = (fromArr (a, b, c, d, e), fromArr f)++instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g)+  => Arrays (a, b, c, d, e, f, g) where+  arrays  _             = ArraysRpair (arrays (undefined :: (a, b, c, d, e, f))) (arrays (undefined::g))+  flavour _             = ArraysFtuple+  --+  toArr    (abcdef, g)   = let (a, b, c, d, e, f) = toArr abcdef in (a, b, c, d, e, f, toArr g)+  fromArr  (a, b, c, d, e, f, g) = (fromArr (a, b, c, d, e, f), fromArr g)++instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h)+  => Arrays (a, b, c, d, e, f, g, h) where+  arrays  _             = ArraysRpair (arrays (undefined :: (a, b, c, d, e, f, g))) (arrays (undefined::h))+  flavour _             = ArraysFtuple+  --+  toArr    (abcdefg, h)   = let (a, b, c, d, e, f, g) = toArr abcdefg in (a, b, c, d, e, f, g, toArr h)+  fromArr  (a, b, c, d, e, f, g, h) = (fromArr (a, b, c, d, e, f, g), fromArr h)++instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i)+  => Arrays (a, b, c, d, e, f, g, h, i) where+  arrays  _             = ArraysRpair (arrays (undefined :: (a, b, c, d, e, f, g, h))) (arrays (undefined::i))+  flavour _             = ArraysFtuple+  --+  toArr    (abcdefgh, i) = let (a, b, c, d, e, f, g, h) = toArr abcdefgh in (a, b, c, d, e, f, g, h, toArr i)+  fromArr  (a, b, c, d, e, f, g, h, i) = (fromArr (a, b, c, d, e, f, g, h), fromArr i)++instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j)+  => Arrays (a, b, c, d, e, f, g, h, i, j) where+  arrays  _             = ArraysRpair (arrays (undefined :: (a, b, c, d, e, f, g, h, i))) (arrays (undefined::j))+  flavour _             = ArraysFtuple+  --+  toArr    (abcdefghi, j) = let (a, b, c, d, e, f, g, h, i) = toArr abcdefghi in (a, b, c, d, e, f, g, h, i, toArr j)+  fromArr  (a, b, c, d, e, f, g, h, i, j) = (fromArr (a, b, c, d, e, f, g, h, i), fromArr j)++instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k)+  => Arrays (a, b, c, d, e, f, g, h, i, j, k) where+  arrays  _             = ArraysRpair (arrays (undefined :: (a, b, c, d, e, f, g, h, i, j))) (arrays (undefined::k))+  flavour _             = ArraysFtuple+  --+  toArr    (abcdefghij, k) = let (a, b, c, d, e, f, g, h, i, j) = toArr abcdefghij in (a, b, c, d, e, f, g, h, i, j, toArr k)+  fromArr  (a, b, c, d, e, f, g, h, i, j, k) = (fromArr (a, b, c, d, e, f, g, h, i, j), fromArr k)++instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l)+  => Arrays (a, b, c, d, e, f, g, h, i, j, k, l) where+  arrays  _             = ArraysRpair (arrays (undefined :: (a, b, c, d, e, f, g, h, i, j, k))) (arrays (undefined::l))+  flavour _             = ArraysFtuple+  --+  toArr    (abcdefghijk, l) = let (a, b, c, d, e, f, g, h, i, j, k) = toArr abcdefghijk in (a, b, c, d, e, f, g, h, i, j, k, toArr l)+  fromArr  (a, b, c, d, e, f, g, h, i, j, k, l) = (fromArr (a, b, c, d, e, f, g, h, i, j, k), fromArr l)++instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l, Arrays m)+  => Arrays (a, b, c, d, e, f, g, h, i, j, k, l, m) where+  arrays  _             = ArraysRpair (arrays (undefined :: (a, b, c, d, e, f, g, h, i, j, k, l))) (arrays (undefined::m))+  flavour _             = ArraysFtuple+  --+  toArr    (abcdefghijkl, m) = let (a, b, c, d, e, f, g, h, i, j, k, l) = toArr abcdefghijkl in (a, b, c, d, e, f, g, h, i, j, k, l, toArr m)+  fromArr  (a, b, c, d, e, f, g, h, i, j, k, l, m) = (fromArr (a, b, c, d, e, f, g, h, i, j, k, l), fromArr m)++instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l, Arrays m, Arrays n)+  => Arrays (a, b, c, d, e, f, g, h, i, j, k, l, m, n) where+  arrays  _             = ArraysRpair (arrays (undefined :: (a, b, c, d, e, f, g, h, i, j, k, l, m))) (arrays (undefined::n))+  flavour _             = ArraysFtuple+  --+  toArr    (abcdefghijklm, n) = let (a, b, c, d, e, f, g, h, i, j, k, l, m) = toArr abcdefghijklm in (a, b, c, d, e, f, g, h, i, j, k, l, m, toArr n)+  fromArr  (a, b, c, d, e, f, g, h, i, j, k, l, m, n) = (fromArr (a, b, c, d, e, f, g, h, i, j, k, l, m), fromArr n)++instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l, Arrays m, Arrays n, Arrays o)+  => Arrays (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) where+  arrays  _             = ArraysRpair (arrays (undefined :: (a, b, c, d, e, f, g, h, i, j, k, l, m, n))) (arrays (undefined::o))+  flavour _             = ArraysFtuple+  --+  toArr    (abcdefghijklmn, o) = let (a, b, c, d, e, f, g, h, i, j, k, l, m, n) = toArr abcdefghijklmn in (a, b, c, d, e, f, g, h, i, j, k, l, m, n, toArr o)+  fromArr  (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) = (fromArr (a, b, c, d, e, f, g, h, i, j, k, l, m, n), fromArr o)+++-- {-# RULES+-- "fromArr/toArr" forall a. fromArr (toArr a) = a+-- "toArr/fromArr" forall a. toArr (fromArr a) = a+-- #-}+++-- Tuple representation+-- --------------------++-- |The tuple representation is equivalent to the product representation.+--+type TupleRepr a = ProdRepr a++-- |We represent tuples as heterogeneous lists, typed by a type list.+--+data Tuple c t where+  NilTup  ::                              Tuple c ()+  SnocTup :: Elt t => Tuple c s -> c t -> Tuple c (s, t)++-- TLM: It is irritating that we need a separate data type for tuples of scalars+--   vs. arrays, purely to carry the class constraint.+--+-- | Tuples of Arrays.  Note that this carries the `Arrays` class+--   constraint rather than `Elt` in the case of tuples of scalars.+--+data Atuple c t where+  NilAtup  ::                                  Atuple c ()+  SnocAtup :: Arrays a => Atuple c s -> c a -> Atuple c (s, a)++-- |Tuple reification+--+type TupleR a = ProdR Elt a++tuple :: IsTuple tup => {- dummy -} tup -> TupleR (TupleRepr tup)+tuple = prod (Proxy :: Proxy Elt)+++-- | Dense, regular, multi-dimensional arrays.+--+-- The 'Array' is the core computational unit of Accelerate; all programs in+-- Accelerate take zero or more arrays as input and produce one or more arrays+-- as output. The 'Array' type has two type parameters:+--+--  * /sh/: is the shape of the array, tracking the dimensionality and extent of+--    each dimension of the array; for example, 'DIM1' for one-dimensional+--    'Vector's, 'DIM2' for two-dimensional matrices, and so on.+--  * /e/: represents the type of each element of the array; for example,+--    'Int', 'Float', et cetera.+--+-- Array data is store unboxed in an unzipped struct-of-array representation.+-- Elements are laid out in row-major order (the right-most index of a 'Shape'+-- is the fastest varying). The allowable array element types are members of the+-- 'Elt' class, which roughly consists of:+--+--  * Signed and unsigned integers (8, 16, 32, and 64-bits wide).+--  * Floating point numbers (single and double precision)+--  * 'Char'+--  * 'Bool'+--  * ()+--  * Shapes formed from 'Z' and (':.')+--  * Nested tuples of all of these, currently up to 15-elements wide.+--+-- Note that 'Array' itself is not an allowable element type---there are no+-- nested arrays in Accelerate, regular arrays only!+--+-- If device and host memory are separate, arrays will be transferred to the+-- device when necessary (possibly asynchronously and in parallel with other+-- tasks) and cached on the device if sufficient memory is available. Arrays are+-- made available to embedded language computations via+-- 'Data.Array.Accelerate.use'.+--+-- Section "Getting data in" lists functions for getting data into and out of+-- the 'Array' type.+--+data Array sh e where+  Array :: (Shape sh, Elt e)+        => EltRepr sh                 -- extent of dimensions = shape+        -> ArrayData (EltRepr e)      -- array payload+        -> Array sh e++deriving instance Typeable Array++instance (Eq sh, Eq e) => Eq (Array sh e) where+  arr1@Array{} == arr2@Array{} = shape arr1 == shape arr2 && toList arr1 == toList arr2+  arr1@Array{} /= arr2@Array{} = shape arr1 /= shape arr2 || toList arr1 /= toList arr2++#if __GLASGOW_HASKELL__ >= 710+-- Convert an array to a string, using specialised instances for dimensions+-- zero, one, and two. These are available for ghc-7.10 and later only (earlier+-- versions of ghc would require -XIncoherentInstances in the client module).+--+-- TODO:+--   * Make special formatting optional? It is more difficult to copy/paste the+--     result, for example. Also it does not look good if the matrix row does+--     not fit on a single line.+--   * The AST pretty printer does not use these instances+--+instance Show (Scalar e) where+  show arr@Array{} =+    "Scalar Z " ++ show (toList arr)++instance Show (Vector e) where+  show arr@Array{} =+    "Vector (" ++ showShape (shape arr) ++ ") " ++ show (toList arr)++instance Show (Array DIM2 e) where+  show arr@Array{} =+    "Matrix (" ++ showShape (shape arr) ++ ") " ++ showMat (toMatrix (toList arr))+    where+      Z :. _ :. cols    = shape arr+      toMatrix []       = []+      toMatrix xs       = let (r,rs) = splitAt cols xs+                          in  r : toMatrix rs+      --+      showMat []        = "[]"+      showMat mat       = "\n  " ++ ppMat (map (map show) mat)+      --+      ppRow row         = concatMap (++",") row+      ppMat mat         = "[" ++ init (intercalate "\n   " (map ppRow (ppColumns mat))) ++ "]"+      ppColumns         = transpose . map (\col -> pad (width col) col) . transpose+        where+          extra = 0+          width = maximum . map length+          pad w = map (\x -> replicate (w - length x + extra) ' ' ++ x)+#endif++-- This is a bit unfortunate, but we need to use an INCOHERENT instance because+-- GHC can't determine that with the above specialisations, a DIM3+ instance+-- covers all remaining possibilities, and lacking a general instance is+-- problematic for operations which want a 'Show (Array sh e)' constraint.+-- Furthermore, those clients are likely to pick this instance, rather than the+-- more specific ones above, which is (perhaps) a little unfortunate.+--+instance {-# INCOHERENT #-} Show (Array sh e) where+  show arr@Array{} =+    "Array (" ++ showShape (shape arr) ++ ") " ++ show (toList arr)++instance Elt e => IsList (Vector e) where+  type Item (Vector e) = e+  toList         = toList+  fromListN n xs = fromList (Z:.n) xs+  fromList xs    = GHC.fromListN (length xs) xs++instance NFData (Array sh e) where+  rnf (Array sh ad) = Repr.size sh `seq` go arrayElt ad `seq` ()+    where+      go :: ArrayEltR e' -> ArrayData e' -> ()+      go ArrayEltRunit         AD_Unit         = ()+      go ArrayEltRint          (AD_Int ua)     = rnf ua+      go ArrayEltRint8         (AD_Int8 ua)    = rnf ua+      go ArrayEltRint16        (AD_Int16 ua)   = rnf ua+      go ArrayEltRint32        (AD_Int32 ua)   = rnf ua+      go ArrayEltRint64        (AD_Int64 ua)   = rnf ua+      go ArrayEltRword         (AD_Word ua)    = rnf ua+      go ArrayEltRword8        (AD_Word8 ua)   = rnf ua+      go ArrayEltRword16       (AD_Word16 ua)  = rnf ua+      go ArrayEltRword32       (AD_Word32 ua)  = rnf ua+      go ArrayEltRword64       (AD_Word64 ua)  = rnf ua+      go ArrayEltRcshort       (AD_CShort ua)  = rnf ua+      go ArrayEltRcushort      (AD_CUShort ua) = rnf ua+      go ArrayEltRcint         (AD_CInt ua)    = rnf ua+      go ArrayEltRcuint        (AD_CUInt ua)   = rnf ua+      go ArrayEltRclong        (AD_CLong ua)   = rnf ua+      go ArrayEltRculong       (AD_CULong ua)  = rnf ua+      go ArrayEltRcllong       (AD_CLLong ua)  = rnf ua+      go ArrayEltRcullong      (AD_CULLong ua) = rnf ua+      go ArrayEltRfloat        (AD_Float ua)   = rnf ua+      go ArrayEltRdouble       (AD_Double ua)  = rnf ua+      go ArrayEltRcfloat       (AD_CFloat ua)  = rnf ua+      go ArrayEltRcdouble      (AD_CDouble ua) = rnf ua+      go ArrayEltRbool         (AD_Bool ua)    = rnf ua+      go ArrayEltRchar         (AD_Char ua)    = rnf ua+      go ArrayEltRcchar        (AD_CChar ua)   = rnf ua+      go ArrayEltRcschar       (AD_CSChar ua)  = rnf ua+      go ArrayEltRcuchar       (AD_CUChar ua)  = rnf ua+      go (ArrayEltRpair r1 r2) (AD_Pair a1 a2) = go r1 a1 `seq` go r2 a2 `seq` ()++-- |Scalars arrays hold a single element+--+type Scalar e = Array DIM0 e++-- |Vectors are one-dimensional arrays+--+type Vector e = Array DIM1 e++-- |Segment descriptor (vector of segment lengths).+--+-- To represent nested one-dimensional arrays, we use a flat array of data+-- values in conjunction with a /segment descriptor/, which stores the lengths+-- of the subarrays.+--+type Segments i = Vector i++-- Shorthand for common shape types+--+type DIM0 = Z+type DIM1 = DIM0:.Int+type DIM2 = DIM1:.Int+type DIM3 = DIM2:.Int+type DIM4 = DIM3:.Int+type DIM5 = DIM4:.Int+type DIM6 = DIM5:.Int+type DIM7 = DIM6:.Int+type DIM8 = DIM7:.Int+type DIM9 = DIM8:.Int+++-- Shape constraints and indexing+-- ------------------------------++-- |Shapes and indices of multi-dimensional arrays+--+class (Elt sh, Elt (Any sh), Repr.Shape (EltRepr sh), FullShape sh ~ sh, CoSliceShape sh ~ sh, SliceShape sh ~ Z)+       => Shape sh where++  -- |Number of dimensions of a /shape/ or /index/ (>= 0).+  rank   :: sh -> Int++  -- |Total number of elements in an array of the given /shape/.+  size   :: sh -> Int++  -- |Empty /shape/.+  empty :: sh++  -- |Magic value identifying elements ignored in 'permute'.+  ignore :: sh++  -- |Yield the intersection of two shapes+  intersect :: sh -> sh -> sh++  -- |Yield the union of two shapes+  union :: sh -> sh -> sh++  -- |Map a multi-dimensional index into one in a linear, row-major+  -- representation of the array (first argument is the /shape/, second+  -- argument is the index).+  toIndex   :: sh -> sh -> Int++  -- |Inverse of 'toIndex'.+  fromIndex :: sh -> Int -> sh++  -- |Apply a boundary condition to an index.+  bound  :: sh -> sh -> Boundary a -> Either a sh++  -- |Iterate through the entire shape, applying the function; third argument+  -- combines results and fourth is returned in case of an empty iteration+  -- space; the index space is traversed in row-major order.+  iter  :: sh -> (sh -> a) -> (a -> a -> a) -> a -> a++  -- |Variant of 'iter' without an initial value+  iter1 :: sh -> (sh -> a) -> (a -> a -> a) -> a++  -- |Convert a minpoint-maxpoint index into a /shape/.+  rangeToShape ::  (sh, sh) -> sh++  -- |Convert a /shape/ into a minpoint-maxpoint index.+  shapeToRange ::  sh -> (sh, sh)++  -- |Convert a shape to a list of dimensions.+  shapeToList :: sh -> [Int]++  -- |Convert a list of dimensions into a shape.+  listToShape :: [Int] -> sh++  -- | The slice index for slice specifier 'Any sh'+  sliceAnyIndex :: sh -> Repr.SliceIndex (EltRepr (Any sh)) (EltRepr sh) () (EltRepr sh)++  -- | The slice index for specifying a slice with only the Z component projected+  sliceNoneIndex :: sh -> Repr.SliceIndex (EltRepr sh) () (EltRepr sh) (EltRepr sh)++  rank                  = Repr.rank . fromElt+  size                  = Repr.size . fromElt+  empty                 = toElt Repr.empty+  -- (#) must be individually defined, as it holds for all instances *except*+  -- the one with the largest arity++  ignore                = toElt Repr.ignore+  intersect sh1 sh2     = toElt (Repr.intersect (fromElt sh1) (fromElt sh2))+  union sh1 sh2         = toElt (Repr.union (fromElt sh1) (fromElt sh2))+  fromIndex sh ix       = toElt (Repr.fromIndex (fromElt sh) ix)+  toIndex sh ix         = Repr.toIndex (fromElt sh) (fromElt ix)++  bound sh ix bndy      = case Repr.bound (fromElt sh) (fromElt ix) bndy of+                            Left v    -> Left v+                            Right ix' -> Right $ toElt ix'++  iter sh f c r         = Repr.iter  (fromElt sh) (f . toElt) c r+  iter1 sh f r          = Repr.iter1 (fromElt sh) (f . toElt) r++  rangeToShape (low, high)+    = toElt (Repr.rangeToShape (fromElt low, fromElt high))+  shapeToRange ix+    = let (low, high) = Repr.shapeToRange (fromElt ix)+      in+      (toElt low, toElt high)++  shapeToList = Repr.shapeToList . fromElt+  listToShape = toElt . Repr.listToShape++instance Shape Z where+  sliceAnyIndex  _ = Repr.SliceNil+  sliceNoneIndex _ = Repr.SliceNil++instance Shape sh => Shape (sh:.Int) where+  sliceAnyIndex  _ = Repr.SliceAll   (sliceAnyIndex  (undefined :: sh))+  sliceNoneIndex _ = Repr.SliceFixed (sliceNoneIndex (undefined :: sh))++-- | Slices, aka generalised indices, as /n/-tuples and mappings of slice+-- indices to slices, co-slices, and slice dimensions+--+class (Elt sl, Shape (SliceShape sl), Shape (CoSliceShape sl), Shape (FullShape sl))+       => Slice sl where+  type SliceShape   sl :: *     -- the projected slice+  type CoSliceShape sl :: *     -- the complement of the slice+  type FullShape    sl :: *     -- the combined dimension+  sliceIndex :: sl {- dummy -} -> Repr.SliceIndex (EltRepr sl)+                                    (EltRepr (SliceShape   sl))+                                    (EltRepr (CoSliceShape sl))+                                    (EltRepr (FullShape    sl))++instance Slice Z where+  type SliceShape   Z = Z+  type CoSliceShape Z = Z+  type FullShape    Z = Z+  sliceIndex _ = Repr.SliceNil++instance Slice sl => Slice (sl:.All) where+  type SliceShape   (sl:.All) = SliceShape   sl :. Int+  type CoSliceShape (sl:.All) = CoSliceShape sl+  type FullShape    (sl:.All) = FullShape    sl :. Int+  sliceIndex _ = Repr.SliceAll (sliceIndex (undefined :: sl))++instance Slice sl => Slice (sl:.Int) where+  type SliceShape   (sl:.Int) = SliceShape   sl+  type CoSliceShape (sl:.Int) = CoSliceShape sl :. Int+  type FullShape    (sl:.Int) = FullShape    sl :. Int+  sliceIndex _ = Repr.SliceFixed (sliceIndex (undefined :: sl))++instance Shape sh => Slice (Any sh) where+  type SliceShape   (Any sh) = sh+  type CoSliceShape (Any sh) = Z+  type FullShape    (Any sh) = sh+  sliceIndex _ = sliceAnyIndex (undefined :: sh)+++-- | Generalised array division, like above but use for splitting an array into+-- many subarrays, as opposed to extracting a single subarray.+--+class (Slice (DivisionSlice sl))+       => Division sl where+  type DivisionSlice sl :: *     -- the slice+  slicesIndex :: slix ~ DivisionSlice sl+              => sl {- dummy -}+              -> Repr.SliceIndex (EltRepr slix)+                                 (EltRepr (SliceShape   slix))+                                 (EltRepr (CoSliceShape slix))+                                 (EltRepr (FullShape    slix))++instance Division Z where+  type DivisionSlice   Z = Z+  slicesIndex _ = Repr.SliceNil++instance Division sl => Division (sl:.All) where+  type DivisionSlice  (sl:.All) = DivisionSlice sl :. All+  slicesIndex _ = Repr.SliceAll (slicesIndex (undefined :: sl))++instance Division sl => Division (sl:.Split) where+  type DivisionSlice (sl:.Split) = DivisionSlice sl :. Int+  slicesIndex _ = Repr.SliceFixed (slicesIndex (undefined :: sl))++instance Shape sh => Division (Any sh) where+  type DivisionSlice (Any sh) = Any sh+  slicesIndex _ = sliceAnyIndex (undefined :: sh)++instance (Shape sh, Slice sh) => Division (Divide sh) where+  type DivisionSlice (Divide sh) = sh+  slicesIndex _ = sliceNoneIndex (undefined :: sh)+++-- Array operations+-- ----------------++-- |Yield an array's shape+--+shape :: Shape sh => Array sh e -> sh+shape (Array sh _) = toElt sh++-- | Array indexing+--+infixl 9 !+(!) :: Array sh e -> sh -> e+{-# INLINE (!) #-}+-- (Array sh adata) ! ix = toElt (adata `indexArrayData` index sh ix)+-- FIXME: using this due to a bug in 6.10.x+(!) (Array sh adata) ix = toElt (adata `unsafeIndexArrayData` toIndex (toElt sh) ix)++-- | 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+{-# INLINE fromFunction #-}+fromFunction sh f = adata `seq` Array (fromElt sh) adata+  where+    (adata, _) = runArrayData $ do+                   arr <- newArrayData (size sh)+                   let write ix = unsafeWriteArrayData arr (toIndex sh ix)+                                                           (fromElt (f ix))+                   iter sh write (>>) (return ())+                   return (arr, undefined)+++-- | Create a vector from the concatenation of the given list of vectors.+--+concatVectors :: Elt e => [Vector e] -> Vector e+{-# INLINE concatVectors #-}+concatVectors vs = adata `seq` Array ((), len) adata+  where+    offsets     = scanl (+) 0 (map (size . shape) vs)+    len         = last offsets+    (adata, _)  = runArrayData $ do+              arr <- newArrayData len+              sequence_ [ unsafeWriteArrayData arr (i + k) (unsafeIndexArrayData ad i)+                        | (Array ((), n) ad, k) <- vs `zip` offsets+                        , i <- [0 .. n - 1] ]+              return (arr, undefined)++-- | Creates a new, uninitialized Accelerate array.+--+allocateArray :: (Shape sh, Elt e) => sh -> IO (Array sh e)+{-# INLINE allocateArray #-}+allocateArray sh = adata `seq` return (Array (fromElt sh) adata)+  where+    (adata, _) = runArrayData $ (,undefined) `fmap` newArrayData (size sh)+++-- | 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+{-# INLINE fromList #-}+fromList sh xs = adata `seq` Array (fromElt sh) adata+  where+    -- Assume the array is in dense row-major order. This is safe because+    -- otherwise backends would not be able to directly memcpy.+    --+    !n          = size sh+    (adata, _)  = runArrayData $ do+                    arr <- newArrayData n+                    let go !i _ | i >= n = return ()+                        go !i (v:vs)     = unsafeWriteArrayData arr i (fromElt v) >> go (i+1) vs+                        go _  []         = error "Data.Array.Accelerate.fromList: not enough input data"+                    --+                    go 0 xs+                    return (arr, undefined)++-- | Convert an accelerated 'Array' to a list in row-major order.+--+toList :: forall sh e. Array sh e -> [e]+{-# INLINE toList #-}+toList (Array sh adata) = go 0+  where+    -- Assume underling array is in row-major order. This is safe because+    -- otherwise backends would not be able to directly memcpy.+    --+    !n                  = Repr.size sh+    go !i | i >= n      = []+          | otherwise   = toElt (adata `unsafeIndexArrayData` i) : go (i+1)++-- | Nicely format a shape as a string+--+showShape :: Shape sh => sh -> String+showShape = foldr (\sh str -> str ++ " :. " ++ show sh) "Z" . shapeToList++-- | Project the shape of a slice from the full shape.+--+sliceShape :: forall slix co sl dim. (Shape sl, Shape dim)+           => Repr.SliceIndex slix (EltRepr sl) co (EltRepr dim)+           -> dim+           -> sl+sliceShape slix = toElt . Repr.sliceShape slix . fromElt++-- | Enumerate all slices within a given bound. The innermost dimension+-- changes most rapidly.+--+-- Example:+--+-- > let slix = sliceIndex (undefined :: Z :. Int :. Int :. All)+-- >     sh   = Z :. 2 :. 3 :. 1 :: DIM3+-- > in+-- > enumSlices slix sh :: [ Z :. Int :. Int :. All ]+--+enumSlices :: forall slix co sl dim. (Elt slix, Elt dim)+           => Repr.SliceIndex (EltRepr slix) sl co (EltRepr dim)+           -> dim    -- Bounds+           -> [slix] -- All slices within bounds.+enumSlices slix = map toElt . Repr.enumSlices slix . fromElt 
+ Data/Array/Accelerate/Array/Unique.hs view
@@ -0,0 +1,94 @@+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.Array.Unique+-- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell, Robert Clifton-Everest+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Array.Unique (++  UniqueArray(..),+  newUniqueArray,+  withUniqueArrayPtr,+  unsafeUniqueArrayPtr,+  touchUniqueArray,++) where++-- library+import Control.Applicative+import Control.Concurrent.Unique+import Control.DeepSeq+import Foreign.ForeignPtr+import Foreign.ForeignPtr.Unsafe+import Foreign.Ptr+import Prelude++-- friends+import Data.Array.Accelerate.Lifetime+++-- | A uniquely identifiable array.+--+-- For the purposes of memory management, we use arrays as keys in a table. For+-- this reason we need a way to uniquely identify each array we create. We do+-- this by attaching a unique identifier to each array.+--+-- Note: [Unique array strictness]+--+-- The actual array data is in many cases unnecessary. For discrete memory+-- backends such as for GPUs, we require the unique identifier to track the data+-- in the remote memory space, but the data will in most cases never be copied+-- back to the host. Thus, the array payload field is only lazily allocated, and+-- we should be careful not to make this field overly strict.+--+data UniqueArray e = UniqueArray+    { uniqueArrayId   :: {-# UNPACK #-} !Unique+    , uniqueArrayData :: {-# UNPACK #-} !(Lifetime (ForeignPtr e))+    }++instance NFData (UniqueArray e) where+  rnf (UniqueArray _ ad) = unsafeGetValue ad `seq` ()+++-- | Create a new UniqueArray+--+newUniqueArray :: ForeignPtr e -> IO (UniqueArray e)+newUniqueArray fp = UniqueArray <$> newUnique <*> newLifetime fp++-- | Access the pointer backing the unique array.+--+-- The array data is kept alive at least during the whole action, even if it is+-- not directly used inside. Note that it is not safe to return the pointer from+-- the action and use it after the action completes. All uses of the pointer+-- should be inside the bracketed function.+--+withUniqueArrayPtr :: UniqueArray a -> (Ptr a -> IO b) -> IO b+withUniqueArrayPtr ua go =+  withLifetime (uniqueArrayData ua) $ \fp -> withForeignPtr fp go+++-- | Extract the pointer backing the unique array.+--+-- This is potentially unsafe, as if the argument is the last occurrence of this+-- unique array then the finalisers will be run, potentially invalidating the+-- plain pointer just obtained.+--+-- See also: 'unsafeGetValue', 'unsafeForeignPtrToPtr'.+--+unsafeUniqueArrayPtr :: UniqueArray a -> Ptr a+unsafeUniqueArrayPtr = unsafeForeignPtrToPtr . unsafeGetValue . uniqueArrayData+++-- | Ensure that the unique array is alive at the given place in a sequence of+-- IO actions. Note that this does not force the actual array payload.+--+-- See: [Unique array strictness]+--+touchUniqueArray :: UniqueArray a -> IO ()+touchUniqueArray = touchLifetime . uniqueArrayData+
+ Data/Array/Accelerate/Async.hs view
@@ -0,0 +1,103 @@+{-# LANGUAGE CPP           #-}+{-# LANGUAGE MagicHash     #-}+{-# LANGUAGE UnboxedTuples #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.Async+-- Copyright   : [2009..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Async (++  -- * Asynchronous actions+  Async,++  -- ** Spawning+  async, asyncOn, asyncBound,++  -- ** Querying 'Async's+  wait, poll, cancel,++) where++import Control.Exception+import Control.Concurrent++import GHC.Exts+import GHC.Conc+import GHC.IO+++-- We need to execute the main thread asynchronously to give finalisers a chance+-- to run. Make sure to catch exceptions to avoid "blocked indefinitely on MVar"+-- errors.+--+data Async a = Async {-# UNPACK #-} !ThreadId+                     {-# UNPACK #-} !(MVar (Either SomeException a))++-- | Spawn an asynchronous action in a separate thread.+--+async :: IO a -> IO (Async a)+async = inline asyncUsing rawForkIO++-- | Like 'async', but using 'forkOn' internally.+--+asyncOn :: Int -> IO a -> IO (Async a)+asyncOn cpu = inline asyncUsing (rawForkOn cpu)++-- | Like 'async', but using 'forkOS' internally.+--+asyncBound :: IO a -> IO (Async a)+asyncBound = inline asyncUsing forkOS++asyncUsing :: (IO () -> IO ThreadId) -> IO a -> IO (Async a)+asyncUsing fork action = do+   var <- newEmptyMVar+   tid <- mask $ \restore ->+            fork $ try (restore action) >>= putMVar var+   return (Async tid var)++-- | Block the calling thread until the computation completes, then return the+-- result.+--+{-# INLINE wait #-}+wait :: Async a -> IO a+wait (Async _ var) = either throwIO return =<< readMVar var++-- | Test whether the asynchronous computation has already completed. If so,+-- return the result, else 'Nothing'.+--+{-# INLINE poll #-}+poll :: Async a -> IO (Maybe a)+poll (Async _ var) =+  maybe (return Nothing) (either throwIO (return . Just)) =<< tryTakeMVar var++-- | Cancel a running asynchronous computation.+--+{-# INLINE cancel #-}+cancel :: Async a -> IO ()+cancel (Async tid _) = throwTo tid ThreadKilled+++-- A version of 'forkIO' that does not include the outer exception handler. This+-- saves a bit of time when we will be installing our own exception handler.+--+-- Stolen from Simon Marlow's 'async' package (BSD).+--+{-# INLINE rawForkIO #-}+rawForkIO :: IO () -> IO ThreadId+rawForkIO action = IO $ \s ->+  case fork# action s of+    (# s', tid #) -> (# s', ThreadId tid #)++{-# INLINE rawForkOn #-}+rawForkOn :: Int -> IO () -> IO ThreadId+rawForkOn (I# cpu) action = IO $ \s ->+  case forkOn# cpu action s of+    (# s', tid #) -> (# s', ThreadId tid #)+
+ Data/Array/Accelerate/Classes.hs view
@@ -0,0 +1,52 @@+{-# LANGUAGE NoImplicitPrelude #-}+-- |+-- Module      : Data.Array.Accelerate.Classes+-- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- This module provides instances for standard Haskell 98 classes where+-- possible, and provides new implementations of those classes where the types+-- do not match.+--++module Data.Array.Accelerate.Classes (++  -- *** Basic type classes+  module Eq,+  module Ord,+  module Enum,+  module Bounded,++  -- *** Numeric type classes+  module Num,+  module Real,+  module Integral,+  module Fractional,+  module Floating,+  module RealFrac,+  module RealFloat,++  -- *** Numeric conversions+  module FromIntegral,+  module ToFloating,++) where++import Data.Array.Accelerate.Classes.Bounded                        as Bounded+import Data.Array.Accelerate.Classes.Enum                           as Enum+import Data.Array.Accelerate.Classes.Eq                             as Eq+import Data.Array.Accelerate.Classes.Floating                       as Floating+import Data.Array.Accelerate.Classes.Fractional                     as Fractional+import Data.Array.Accelerate.Classes.FromIntegral                   as FromIntegral+import Data.Array.Accelerate.Classes.Integral                       as Integral+import Data.Array.Accelerate.Classes.Num                            as Num+import Data.Array.Accelerate.Classes.Ord                            as Ord+import Data.Array.Accelerate.Classes.Real                           as Real+import Data.Array.Accelerate.Classes.RealFloat                      as RealFloat+import Data.Array.Accelerate.Classes.RealFrac                       as RealFrac+import Data.Array.Accelerate.Classes.ToFloating                     as ToFloating+
+ Data/Array/Accelerate/Classes/Bounded.hs view
@@ -0,0 +1,214 @@+{-# LANGUAGE ConstraintKinds   #-}+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE FlexibleInstances #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- |+-- Module      : Data.Array.Accelerate.Classes.Bounded+-- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Classes.Bounded (++  Bounded,+  P.minBound, P.maxBound,++) where++import Data.Array.Accelerate.Array.Sugar+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Type++import qualified Prelude                                            as P+++-- | 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, P.Bounded (Exp a))+++instance P.Bounded (Exp ()) where+  minBound = constant ()+  maxBound = constant ()++instance P.Bounded (Exp Int) where+  minBound = mkMinBound+  maxBound = mkMaxBound++instance P.Bounded (Exp Int8) where+  minBound = mkMinBound+  maxBound = mkMaxBound++instance P.Bounded (Exp Int16) where+  minBound = mkMinBound+  maxBound = mkMaxBound++instance P.Bounded (Exp Int32) where+  minBound = mkMinBound+  maxBound = mkMaxBound++instance P.Bounded (Exp Int64) where+  minBound = mkMinBound+  maxBound = mkMaxBound++instance P.Bounded (Exp Word) where+  minBound = mkMinBound+  maxBound = mkMaxBound++instance P.Bounded (Exp Word8) where+  minBound = mkMinBound+  maxBound = mkMaxBound++instance P.Bounded (Exp Word16) where+  minBound = mkMinBound+  maxBound = mkMaxBound++instance P.Bounded (Exp Word32) where+  minBound = mkMinBound+  maxBound = mkMaxBound++instance P.Bounded (Exp Word64) where+  minBound = mkMinBound+  maxBound = mkMaxBound++instance P.Bounded (Exp CShort) where+  minBound = mkMinBound+  maxBound = mkMaxBound++instance P.Bounded (Exp CUShort) where+  minBound = mkMinBound+  maxBound = mkMaxBound++instance P.Bounded (Exp CInt) where+  minBound = mkMinBound+  maxBound = mkMaxBound++instance P.Bounded (Exp CUInt) where+  minBound = mkMinBound+  maxBound = mkMaxBound++instance P.Bounded (Exp CLong) where+  minBound = mkMinBound+  maxBound = mkMaxBound++instance P.Bounded (Exp CULong) where+  minBound = mkMinBound+  maxBound = mkMaxBound++instance P.Bounded (Exp CLLong) where+  minBound = mkMinBound+  maxBound = mkMaxBound++instance P.Bounded (Exp CULLong) where+  minBound = mkMinBound+  maxBound = mkMaxBound++instance P.Bounded (Exp Bool) where+  minBound = mkMinBound+  maxBound = mkMaxBound++instance P.Bounded (Exp Char) where+  minBound = mkMinBound+  maxBound = mkMaxBound++instance P.Bounded (Exp CChar) where+  minBound = mkMinBound+  maxBound = mkMaxBound++instance P.Bounded (Exp CSChar) where+  minBound = mkMinBound+  maxBound = mkMaxBound++instance P.Bounded (Exp CUChar) where+  minBound = mkMinBound+  maxBound = mkMaxBound++instance ( P.Bounded (Exp a), P.Bounded (Exp b)+         , Elt a, Elt b+         ) => P.Bounded (Exp (a,b)) where+  minBound = tup2 (P.minBound, P.minBound)+  maxBound = tup2 (P.maxBound, P.maxBound)++instance ( P.Bounded (Exp a), P.Bounded (Exp b), P.Bounded (Exp c)+         , Elt a, Elt b, Elt c+         ) => P.Bounded (Exp (a,b,c)) where+  minBound = tup3 (P.minBound, P.minBound, P.minBound)+  maxBound = tup3 (P.maxBound, P.maxBound, P.maxBound)++instance ( P.Bounded (Exp a), P.Bounded (Exp b), P.Bounded (Exp c), P.Bounded (Exp d)+         , Elt a, Elt b, Elt c, Elt d+         ) => P.Bounded (Exp (a,b,c,d)) where+  minBound = tup4 (P.minBound, P.minBound, P.minBound, P.minBound)+  maxBound = tup4 (P.maxBound, P.maxBound, P.maxBound, P.maxBound)++instance ( P.Bounded (Exp a), P.Bounded (Exp b), P.Bounded (Exp c), P.Bounded (Exp d), P.Bounded (Exp e)+         , Elt a, Elt b, Elt c, Elt d, Elt e+         ) => P.Bounded (Exp (a,b,c,d,e)) where+  minBound = tup5 (P.minBound, P.minBound, P.minBound, P.minBound, P.minBound)+  maxBound = tup5 (P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound)++instance ( P.Bounded (Exp a), P.Bounded (Exp b), P.Bounded (Exp c), P.Bounded (Exp d), P.Bounded (Exp e), P.Bounded (Exp f)+         , Elt a, Elt b, Elt c, Elt d, Elt e, Elt f+         ) => P.Bounded (Exp (a,b,c,d,e,f)) where+  minBound = tup6 (P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound)+  maxBound = tup6 (P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound)++instance ( P.Bounded (Exp a), P.Bounded (Exp b), P.Bounded (Exp c), P.Bounded (Exp d), P.Bounded (Exp e), P.Bounded (Exp f), P.Bounded (Exp g)+         , Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g+         ) => P.Bounded (Exp (a,b,c,d,e,f,g)) where+  minBound = tup7 (P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound)+  maxBound = tup7 (P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound)++instance ( P.Bounded (Exp a), P.Bounded (Exp b), P.Bounded (Exp c), P.Bounded (Exp d), P.Bounded (Exp e), P.Bounded (Exp f), P.Bounded (Exp g), P.Bounded (Exp h)+         , Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h+         ) => P.Bounded (Exp (a,b,c,d,e,f,g,h)) where+  minBound = tup8 (P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound)+  maxBound = tup8 (P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound)++instance ( P.Bounded (Exp a), P.Bounded (Exp b), P.Bounded (Exp c), P.Bounded (Exp d), P.Bounded (Exp e), P.Bounded (Exp f), P.Bounded (Exp g), P.Bounded (Exp h), P.Bounded (Exp i)+         , Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i+         ) => P.Bounded (Exp (a,b,c,d,e,f,g,h,i)) where+  minBound = tup9 (P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound)+  maxBound = tup9 (P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound)++instance ( P.Bounded (Exp a), P.Bounded (Exp b), P.Bounded (Exp c), P.Bounded (Exp d), P.Bounded (Exp e), P.Bounded (Exp f), P.Bounded (Exp g), P.Bounded (Exp h), P.Bounded (Exp i), P.Bounded (Exp j)+         , Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j+         ) => P.Bounded (Exp (a,b,c,d,e,f,g,h,i,j)) where+  minBound = tup10 (P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound)+  maxBound = tup10 (P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound)++instance ( P.Bounded (Exp a), P.Bounded (Exp b), P.Bounded (Exp c), P.Bounded (Exp d), P.Bounded (Exp e), P.Bounded (Exp f), P.Bounded (Exp g), P.Bounded (Exp h), P.Bounded (Exp i), P.Bounded (Exp j), P.Bounded (Exp k)+         , Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k+         ) => P.Bounded (Exp (a,b,c,d,e,f,g,h,i,j,k)) where+  minBound = tup11 (P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound)+  maxBound = tup11 (P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound)++instance ( P.Bounded (Exp a), P.Bounded (Exp b), P.Bounded (Exp c), P.Bounded (Exp d), P.Bounded (Exp e), P.Bounded (Exp f), P.Bounded (Exp g), P.Bounded (Exp h), P.Bounded (Exp i), P.Bounded (Exp j), P.Bounded (Exp k), P.Bounded (Exp l)+         , Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l+         ) => P.Bounded (Exp (a,b,c,d,e,f,g,h,i,j,k,l)) where+  minBound = tup12 (P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound)+  maxBound = tup12 (P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound)++instance ( P.Bounded (Exp a), P.Bounded (Exp b), P.Bounded (Exp c), P.Bounded (Exp d), P.Bounded (Exp e), P.Bounded (Exp f), P.Bounded (Exp g), P.Bounded (Exp h), P.Bounded (Exp i), P.Bounded (Exp j), P.Bounded (Exp k), P.Bounded (Exp l), P.Bounded (Exp m)+         , Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l, Elt m+         ) => P.Bounded (Exp (a,b,c,d,e,f,g,h,i,j,k,l,m)) where+  minBound = tup13 (P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound)+  maxBound = tup13 (P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound)++instance ( P.Bounded (Exp a), P.Bounded (Exp b), P.Bounded (Exp c), P.Bounded (Exp d), P.Bounded (Exp e), P.Bounded (Exp f), P.Bounded (Exp g), P.Bounded (Exp h), P.Bounded (Exp i), P.Bounded (Exp j), P.Bounded (Exp k), P.Bounded (Exp l), P.Bounded (Exp m), P.Bounded (Exp n)+         , Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l, Elt m, Elt n+         ) => P.Bounded (Exp (a,b,c,d,e,f,g,h,i,j,k,l,m,n)) where+  minBound = tup14 (P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound)+  maxBound = tup14 (P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound)++instance ( P.Bounded (Exp a), P.Bounded (Exp b), P.Bounded (Exp c), P.Bounded (Exp d), P.Bounded (Exp e), P.Bounded (Exp f), P.Bounded (Exp g), P.Bounded (Exp h), P.Bounded (Exp i), P.Bounded (Exp j), P.Bounded (Exp k), P.Bounded (Exp l), P.Bounded (Exp m), P.Bounded (Exp n), P.Bounded (Exp o)+         , Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l, Elt m, Elt n, Elt o+         ) => P.Bounded (Exp (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o)) where+  minBound = tup15 (P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound, P.minBound)+  maxBound = tup15 (P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound, P.maxBound)+
+ Data/Array/Accelerate/Classes/Enum.hs view
@@ -0,0 +1,70 @@+{-# LANGUAGE ConstraintKinds   #-}+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE FlexibleInstances #-}+{-# OPTIONS_GHC -fno-warn-missing-methods #-}+{-# OPTIONS_GHC -fno-warn-orphans         #-}+-- |+-- Module      : Data.Array.Accelerate.Classes.Enum+-- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Classes.Enum (++  Enum,++) where++import Data.Array.Accelerate.Smart+import Text.Printf++import Prelude                                                      ( String, error )+import qualified Prelude                                            as P+++-- | Operations over sequentially ordered types+--+type Enum a = P.Enum (Exp a)+++-- Instances of 'Enum' don't make sense in Accelerate at the moment. These are+-- only provided to fulfil superclass constraints; e.g. Integral.+--+instance P.Enum (Exp a) where+  toEnum   = preludeError "toEnum"+  fromEnum = preludeError "fromEnum"++preludeError :: String -> a+preludeError x = error (printf "Prelude.%s not supported Accelerate types" x)++-- instance Enum (Exp Int8)+-- instance Enum (Exp Int16)+-- instance Enum (Exp Int32)+-- instance Enum (Exp Int64)+-- instance Enum (Exp Word)+-- instance Enum (Exp Word8)+-- instance Enum (Exp Word16)+-- instance Enum (Exp Word32)+-- instance Enum (Exp Word64)+-- instance Enum (Exp CInt)+-- instance Enum (Exp CUInt)+-- instance Enum (Exp CLong)+-- instance Enum (Exp CULong)+-- instance Enum (Exp CLLong)+-- instance Enum (Exp CULLong)+-- instance Enum (Exp CShort)+-- instance Enum (Exp CUShort)+-- instance Enum (Exp Bool)+-- instance Enum (Exp Char)+-- instance Enum (Exp CChar)+-- instance Enum (Exp CUChar)+-- instance Enum (Exp CSChar)+-- instance Enum (Exp Float)+-- instance Enum (Exp Double)+-- instance Enum (Exp CFloat)+-- instance Enum (Exp CDouble)+
+ Data/Array/Accelerate/Classes/Eq.hs view
@@ -0,0 +1,304 @@+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE FlexibleInstances #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- |+-- Module      : Data.Array.Accelerate.Classes.Eq+-- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Classes.Eq (++  Eq(..),+  (&&),+  (||),+  not,++) where++import Data.Array.Accelerate.Array.Sugar+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Type++import Text.Printf+import Prelude                                                      ( String, error)+import qualified Prelude                                            as P+++infix 4 ==+infix 4 /=++-- | 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.+--+infixr 3 &&+(&&) :: Exp Bool -> Exp Bool -> Exp Bool+(&&) = mkLAnd++-- | 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.+--+infixr 2 ||+(||) :: Exp Bool -> Exp Bool -> Exp Bool+(||) = mkLOr++-- | Logical negation+--+not :: Exp Bool -> Exp Bool+not = mkLNot+++-- | 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+  (==) :: Exp a -> Exp a -> Exp Bool+  (/=) :: Exp a -> Exp a -> Exp Bool+  {-# MINIMAL (==) | (/=) #-}+  x == y = mkLNot (x /= y)+  x /= y = mkLNot (x == y)+++instance Eq () where+  _ == _ = constant True   -- force arguments?+  _ /= _ = constant False  -- force arguments?++instance Eq Int where+  (==) = mkEq+  (/=) = mkNEq++instance Eq Int8 where+  (==) = mkEq+  (/=) = mkNEq++instance Eq Int16 where+  (==) = mkEq+  (/=) = mkNEq++instance Eq Int32 where+  (==) = mkEq+  (/=) = mkNEq++instance Eq Int64 where+  (==) = mkEq+  (/=) = mkNEq++instance Eq Word where+  (==) = mkEq+  (/=) = mkNEq++instance Eq Word8 where+  (==) = mkEq+  (/=) = mkNEq++instance Eq Word16 where+  (==) = mkEq+  (/=) = mkNEq++instance Eq Word32 where+  (==) = mkEq+  (/=) = mkNEq++instance Eq Word64 where+  (==) = mkEq+  (/=) = mkNEq++instance Eq CInt where+  (==) = mkEq+  (/=) = mkNEq++instance Eq CUInt where+  (==) = mkEq+  (/=) = mkNEq++instance Eq CLong where+  (==) = mkEq+  (/=) = mkNEq++instance Eq CULong where+  (==) = mkEq+  (/=) = mkNEq++instance Eq CLLong where+  (==) = mkEq+  (/=) = mkNEq++instance Eq CULLong where+  (==) = mkEq+  (/=) = mkNEq++instance Eq CShort where+  (==) = mkEq+  (/=) = mkNEq++instance Eq CUShort where+  (==) = mkEq+  (/=) = mkNEq++instance Eq Bool where+  (==) = mkEq+  (/=) = mkNEq++instance Eq Char where+  (==) = mkEq+  (/=) = mkNEq++instance Eq CChar where+  (==) = mkEq+  (/=) = mkNEq++instance Eq CUChar where+  (==) = mkEq+  (/=) = mkNEq++instance Eq CSChar where+  (==) = mkEq+  (/=) = mkNEq++instance Eq Float where+  (==) = mkEq+  (/=) = mkNEq++instance Eq Double where+  (==) = mkEq+  (/=) = mkNEq++instance Eq CFloat where+  (==) = mkEq+  (/=) = mkNEq++instance Eq CDouble where+  (==) = mkEq+  (/=) = mkNEq++instance (Eq a, Eq b) => Eq (a, b) where+  x == y = let (a1,b1) = untup2 x+               (a2,b2) = untup2 y+           in a1 == a2 && b1 == b2+  x /= y = let (a1,b1) = untup2 x+               (a2,b2) = untup2 y+           in a1 /= a2 || b1 /= b2++instance (Eq a, Eq b, Eq c) => Eq (a, b, c) where+  x == y = let (a1,b1,c1) = untup3 x+               (a2,b2,c2) = untup3 y+           in a1 == a2 && b1 == b2 && c1 == c2+  x /= y = let (a1,b1,c1) = untup3 x+               (a2,b2,c2) = untup3 y+           in a1 /= a2 || b1 /= b2 || c1 /= c2++instance (Eq a, Eq b, Eq c, Eq d) => Eq (a, b, c, d) where+  x == y = let (a1,b1,c1,d1) = untup4 x+               (a2,b2,c2,d2) = untup4 y+           in a1 == a2 && b1 == b2 && c1 == c2 && d1 == d2+  x /= y = let (a1,b1,c1,d1) = untup4 x+               (a2,b2,c2,d2) = untup4 y+           in a1 /= a2 || b1 /= b2 || c1 /= c2 || d1 /= d2++instance (Eq a, Eq b, Eq c, Eq d, Eq e) => Eq (a, b, c, d, e) where+  x == y = let (a1,b1,c1,d1,e1) = untup5 x+               (a2,b2,c2,d2,e2) = untup5 y+           in a1 == a2 && b1 == b2 && c1 == c2 && d1 == d2 && e1 == e2+  x /= y = let (a1,b1,c1,d1,e1) = untup5 x+               (a2,b2,c2,d2,e2) = untup5 y+           in a1 /= a2 || b1 /= b2 || c1 /= c2 || d1 /= d2 || e1 /= e2++instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f) => Eq (a, b, c, d, e, f) where+  x == y = let (a1,b1,c1,d1,e1,f1) = untup6 x+               (a2,b2,c2,d2,e2,f2) = untup6 y+           in a1 == a2 && b1 == b2 && c1 == c2 && d1 == d2 && e1 == e2 && f1 == f2+  x /= y = let (a1,b1,c1,d1,e1,f1) = untup6 x+               (a2,b2,c2,d2,e2,f2) = untup6 y+           in a1 /= a2 || b1 /= b2 || c1 /= c2 || d1 /= d2 || e1 /= e2 || f1 /= f2++instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g) => Eq (a, b, c, d, e, f, g) where+  x == y = let (a1,b1,c1,d1,e1,f1,g1) = untup7 x+               (a2,b2,c2,d2,e2,f2,g2) = untup7 y+           in a1 == a2 && b1 == b2 && c1 == c2 && d1 == d2 && e1 == e2 && f1 == f2 && g1 == g2+  x /= y = let (a1,b1,c1,d1,e1,f1,g1) = untup7 x+               (a2,b2,c2,d2,e2,f2,g2) = untup7 y+           in a1 /= a2 || b1 /= b2 || c1 /= c2 || d1 /= d2 || e1 /= e2 || f1 /= f2 || g1 /= g2++instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g, Eq h) => Eq (a, b, c, d, e, f, g, h) where+  x == y = let (a1,b1,c1,d1,e1,f1,g1,h1) = untup8 x+               (a2,b2,c2,d2,e2,f2,g2,h2) = untup8 y+           in a1 == a2 && b1 == b2 && c1 == c2 && d1 == d2 && e1 == e2 && f1 == f2 && g1 == g2 && h1 == h2+  x /= y = let (a1,b1,c1,d1,e1,f1,g1,h1) = untup8 x+               (a2,b2,c2,d2,e2,f2,g2,h2) = untup8 y+           in a1 /= a2 || b1 /= b2 || c1 /= c2 || d1 /= d2 || e1 /= e2 || f1 /= f2 || g1 /= g2 || h1 /= h2++instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g, Eq h, Eq i) => Eq (a, b, c, d, e, f, g, h, i) where+  x == y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1) = untup9 x+               (a2,b2,c2,d2,e2,f2,g2,h2,i2) = untup9 y+           in a1 == a2 && b1 == b2 && c1 == c2 && d1 == d2 && e1 == e2 && f1 == f2 && g1 == g2 && h1 == h2 && i1 == i2+  x /= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1) = untup9 x+               (a2,b2,c2,d2,e2,f2,g2,h2,i2) = untup9 y+           in a1 /= a2 || b1 /= b2 || c1 /= c2 || d1 /= d2 || e1 /= e2 || f1 /= f2 || g1 /= g2 || h1 /= h2 || i1 /= i2++instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g, Eq h, Eq i, Eq j) => Eq (a, b, c, d, e, f, g, h, i, j) where+  x == y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1) = untup10 x+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2) = untup10 y+           in a1 == a2 && b1 == b2 && c1 == c2 && d1 == d2 && e1 == e2 && f1 == f2 && g1 == g2 && h1 == h2 && i1 == i2 && j1 == j2+  x /= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1) = untup10 x+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2) = untup10 y+           in a1 /= a2 || b1 /= b2 || c1 /= c2 || d1 /= d2 || e1 /= e2 || f1 /= f2 || g1 /= g2 || h1 /= h2 || i1 /= i2 || j1 /= j2++instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g, Eq h, Eq i, Eq j, Eq k) => Eq (a, b, c, d, e, f, g, h, i, j, k) where+  x == y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1) = untup11 x+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2) = untup11 y+           in a1 == a2 && b1 == b2 && c1 == c2 && d1 == d2 && e1 == e2 && f1 == f2 && g1 == g2 && h1 == h2 && i1 == i2 && j1 == j2 && k1 == k2+  x /= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1) = untup11 x+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2) = untup11 y+           in a1 /= a2 || b1 /= b2 || c1 /= c2 || d1 /= d2 || e1 /= e2 || f1 /= f2 || g1 /= g2 || h1 /= h2 || i1 /= i2 || j1 /= j2 || k1 /= k2++instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g, Eq h, Eq i, Eq j, Eq k, Eq l) => Eq (a, b, c, d, e, f, g, h, i, j, k, l) where+  x == y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1) = untup12 x+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2) = untup12 y+           in a1 == a2 && b1 == b2 && c1 == c2 && d1 == d2 && e1 == e2 && f1 == f2 && g1 == g2 && h1 == h2 && i1 == i2 && j1 == j2 && k1 == k2 && l1 == l2+  x /= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1) = untup12 x+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2) = untup12 y+           in a1 /= a2 || b1 /= b2 || c1 /= c2 || d1 /= d2 || e1 /= e2 || f1 /= f2 || g1 /= g2 || h1 /= h2 || i1 /= i2 || j1 /= j2 || k1 /= k2 || l1 /= l2++instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g, Eq h, Eq i, Eq j, Eq k, Eq l, Eq m) => Eq (a, b, c, d, e, f, g, h, i, j, k, l, m) where+  x == y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1) = untup13 x+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2) = untup13 y+           in a1 == a2 && b1 == b2 && c1 == c2 && d1 == d2 && e1 == e2 && f1 == f2 && g1 == g2 && h1 == h2 && i1 == i2 && j1 == j2 && k1 == k2 && l1 == l2 && m1 == m2+  x /= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1) = untup13 x+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2) = untup13 y+           in a1 /= a2 || b1 /= b2 || c1 /= c2 || d1 /= d2 || e1 /= e2 || f1 /= f2 || g1 /= g2 || h1 /= h2 || i1 /= i2 || j1 /= j2 || k1 /= k2 || l1 /= l2 || m1 /= m2++instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g, Eq h, Eq i, Eq j, Eq k, Eq l, Eq m, Eq n) => Eq (a, b, c, d, e, f, g, h, i, j, k, l, m, n) where+  x == y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1) = untup14 x+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2) = untup14 y+           in a1 == a2 && b1 == b2 && c1 == c2 && d1 == d2 && e1 == e2 && f1 == f2 && g1 == g2 && h1 == h2 && i1 == i2 && j1 == j2 && k1 == k2 && l1 == l2 && m1 == m2 && n1 == n2+  x /= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1) = untup14 x+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2) = untup14 y+           in a1 /= a2 || b1 /= b2 || c1 /= c2 || d1 /= d2 || e1 /= e2 || f1 /= f2 || g1 /= g2 || h1 /= h2 || i1 /= i2 || j1 /= j2 || k1 /= k2 || l1 /= l2 || m1 /= m2 || n1 /= n2++instance (Eq a, Eq b, Eq c, Eq d, Eq e, Eq f, Eq g, Eq h, Eq i, Eq j, Eq k, Eq l, Eq m, Eq n, Eq o) => Eq (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) where+  x == y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,o1) = untup15 x+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2,o2) = untup15 y+           in a1 == a2 && b1 == b2 && c1 == c2 && d1 == d2 && e1 == e2 && f1 == f2 && g1 == g2 && h1 == h2 && i1 == i2 && j1 == j2 && k1 == k2 && l1 == l2 && m1 == m2 && n1 == n2 && o1 == o2+  x /= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,o1) = untup15 x+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2,o2) = untup15 y+           in a1 /= a2 || b1 /= b2 || c1 /= c2 || d1 /= d2 || e1 /= e2 || f1 /= f2 || g1 /= g2 || h1 /= h2 || i1 /= i2 || j1 /= j2 || k1 /= k2 || l1 /= l2 || m1 /= m2 || n1 /= n2 || o1 /= o2+++-- Instances of 'Prelude.Eq' don't make sense with the standard signatures as+-- the return type is fixed to 'Bool'. This instance is provided to provide+-- a useful error message.+--+instance P.Eq (Exp a) where+  (==) = preludeError "Eq.==" "(==)"+  (/=) = preludeError "Eq./=" "(/=)"++preludeError :: String -> String -> a+preludeError x y = error (printf "Prelude.%s applied to EDSL types: use Data.Array.Accelerate.%s instead" x y)+
+ Data/Array/Accelerate/Classes/Floating.hs view
@@ -0,0 +1,123 @@+{-# LANGUAGE ConstraintKinds   #-}+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE FlexibleInstances #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- |+-- Module      : Data.Array.Accelerate.Classes.Floating+-- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Classes.Floating (++  Floating,+  P.pi,+  P.sin, P.cos, P.tan,+  P.asin, P.acos, P.atan,+  P.sinh, P.cosh, P.tanh,+  P.asinh, P.acosh, P.atanh,+  P.exp,+  P.sqrt,+  P.log,+  (P.**),+  P.logBase,++) where++import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.Classes.Fractional++import qualified Prelude                                            as P+++-- | Trigonometric and hyperbolic functions and related functions+--+type Floating a = (Fractional a, P.Floating (Exp a))+++instance P.Floating (Exp Float) where+  pi      = mkPi+  sin     = mkSin+  cos     = mkCos+  tan     = mkTan+  asin    = mkAsin+  acos    = mkAcos+  atan    = mkAtan+  sinh    = mkSinh+  cosh    = mkCosh+  tanh    = mkTanh+  asinh   = mkAsinh+  acosh   = mkAcosh+  atanh   = mkAtanh+  exp     = mkExpFloating+  sqrt    = mkSqrt+  log     = mkLog+  (**)    = mkFPow+  logBase = mkLogBase++instance P.Floating (Exp Double) where+  pi      = mkPi+  sin     = mkSin+  cos     = mkCos+  tan     = mkTan+  asin    = mkAsin+  acos    = mkAcos+  atan    = mkAtan+  sinh    = mkSinh+  cosh    = mkCosh+  tanh    = mkTanh+  asinh   = mkAsinh+  acosh   = mkAcosh+  atanh   = mkAtanh+  exp     = mkExpFloating+  sqrt    = mkSqrt+  log     = mkLog+  (**)    = mkFPow+  logBase = mkLogBase++instance P.Floating (Exp CFloat) where+  pi      = mkPi+  sin     = mkSin+  cos     = mkCos+  tan     = mkTan+  asin    = mkAsin+  acos    = mkAcos+  atan    = mkAtan+  sinh    = mkSinh+  cosh    = mkCosh+  tanh    = mkTanh+  asinh   = mkAsinh+  acosh   = mkAcosh+  atanh   = mkAtanh+  exp     = mkExpFloating+  sqrt    = mkSqrt+  log     = mkLog+  (**)    = mkFPow+  logBase = mkLogBase++instance P.Floating (Exp CDouble) where+  pi      = mkPi+  sin     = mkSin+  cos     = mkCos+  tan     = mkTan+  asin    = mkAsin+  acos    = mkAcos+  atan    = mkAtan+  sinh    = mkSinh+  cosh    = mkCosh+  tanh    = mkTanh+  asinh   = mkAsinh+  acosh   = mkAcosh+  atanh   = mkAtanh+  exp     = mkExpFloating+  sqrt    = mkSqrt+  log     = mkLog+  (**)    = mkFPow+  logBase = mkLogBase+
+ Data/Array/Accelerate/Classes/Fractional.hs view
@@ -0,0 +1,55 @@+{-# LANGUAGE ConstraintKinds   #-}+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE FlexibleInstances #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- |+-- Module      : Data.Array.Accelerate.Classes.Fractional+-- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Classes.Fractional (++  Fractional,+  (P./), P.recip, P.fromRational,++) where++import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.Classes.Num++import Prelude                                                      ( (.), fromRational )+import qualified Prelude                                            as P+++-- | Fractional numbers, supporting real division+--+type Fractional a = (Num a, P.Fractional (Exp a))+++instance P.Fractional (Exp Float) where+  (/)          = mkFDiv+  recip        = mkRecip+  fromRational = constant . fromRational++instance P.Fractional (Exp Double) where+  (/)          = mkFDiv+  recip        = mkRecip+  fromRational = constant . fromRational++instance P.Fractional (Exp CFloat) where+  (/)          = mkFDiv+  recip        = mkRecip+  fromRational = constant . fromRational++instance P.Fractional (Exp CDouble) where+  (/)          = mkFDiv+  recip        = mkRecip+  fromRational = constant . fromRational+
+ Data/Array/Accelerate/Classes/FromIntegral.hs view
@@ -0,0 +1,85 @@+{-# LANGUAGE CPP                   #-}+{-# LANGUAGE ConstraintKinds       #-}+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TemplateHaskell       #-}+-- |+-- Module      : Data.Array.Accelerate.Classes.FromIntegral+-- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Classes.FromIntegral (++  FromIntegral(..),++) where++import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.Classes.Integral++import Language.Haskell.TH                                          hiding ( Exp )+import Prelude                                                      hiding ( Integral )+++-- | Accelerate lacks a most-general lossless 'Prelude.Integer' type, which the+-- standard 'Prelude.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 where+  -- | General coercion from integral types+  fromIntegral :: Integral a => Exp a -> Exp b++-- instance {-# OVERLAPPABLE #-} (Elt a, Elt b, IsIntegral a, IsNum b) => FromIntegral a b where+--   fromIntegral = mkFromIntegral+++-- Reify in ghci:+--+-- $( stringE . show =<< reify ''Thing )++-- Generate all the standard instances explicitly. This gives us sensible error+-- messages when we don't have an instance available, rather than a "can not+-- deduce IsNum..." style error (which the user can do nothing about).+--+$(runQ $ do+    let+        -- Get all the types that our dictionaries reify+        digItOut :: Name -> Q [Name]+        digItOut name = do+#if __GLASGOW_HASKELL__ < 800+          TyConI (DataD _ _ _   cons _) <- reify name+#else+          TyConI (DataD _ _ _ _ cons _) <- reify name+#endif+          let+            dig (NormalC _ [(_, AppT (ConT n) (VarT _))])               = digItOut n+#if __GLASGOW_HASKELL__ < 800+            dig (ForallC _ _ (NormalC _ [(_, AppT (ConT _) (ConT n))])) = return [n]+#else+            dig (GadtC _ _ (AppT (ConT _) (ConT n)))                    = return [n]+#endif+            dig _ = error "Unexpected case generating FromIntegral instances"+            --+          concat `fmap` mapM dig cons++        thFromIntegral :: Name -> Name -> Q Dec+        thFromIntegral a b =+          let+              ty  = AppT (AppT (ConT (mkName "FromIntegral")) (ConT a)) (ConT b)+              dec = ValD (VarP (mkName "fromIntegral")) (NormalB (VarE (mkName "mkFromIntegral"))) []+          in+          instanceD (return []) (return ty) [return dec]+    --+    as <- digItOut ''IntegralType+    bs <- digItOut ''NumType+    sequence [ thFromIntegral a b | a <- as, b <- bs ]+ )+
+ Data/Array/Accelerate/Classes/Integral.hs view
@@ -0,0 +1,203 @@+{-# LANGUAGE ConstraintKinds   #-}+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE FlexibleInstances #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- |+-- Module      : Data.Array.Accelerate.Classes.Integral+-- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Classes.Integral (++  Integral,+  P.quot,+  P.rem,+  P.div,+  P.mod,+  P.quotRem,+  P.divMod,++) where++import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.Classes.Enum+import Data.Array.Accelerate.Classes.Real++import Prelude                                                      ( error )+import qualified Prelude                                            as P+++-- | Integral numbers, supporting integral division+--+type Integral a = (Enum a, Real a, P.Integral (Exp a))+++instance P.Integral (Exp Int) where+  quot      = mkQuot+  rem       = mkRem+  div       = mkIDiv+  mod       = mkMod+  quotRem   = mkQuotRem+  divMod    = mkDivMod+  toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp Int8) where+  quot      = mkQuot+  rem       = mkRem+  div       = mkIDiv+  mod       = mkMod+  quotRem   = mkQuotRem+  divMod    = mkDivMod+  toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp Int16) where+  quot      = mkQuot+  rem       = mkRem+  div       = mkIDiv+  mod       = mkMod+  quotRem   = mkQuotRem+  divMod    = mkDivMod+  toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp Int32) where+  quot      = mkQuot+  rem       = mkRem+  div       = mkIDiv+  mod       = mkMod+  quotRem   = mkQuotRem+  divMod    = mkDivMod+  toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp Int64) where+  quot      = mkQuot+  rem       = mkRem+  div       = mkIDiv+  mod       = mkMod+  quotRem   = mkQuotRem+  divMod    = mkDivMod+  toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp Word) where+  quot      = mkQuot+  rem       = mkRem+  div       = mkIDiv+  mod       = mkMod+  quotRem   = mkQuotRem+  divMod    = mkDivMod+  toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp Word8) where+  quot      = mkQuot+  rem       = mkRem+  div       = mkIDiv+  mod       = mkMod+  quotRem   = mkQuotRem+  divMod    = mkDivMod+  toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp Word16) where+  quot      = mkQuot+  rem       = mkRem+  div       = mkIDiv+  mod       = mkMod+  quotRem   = mkQuotRem+  divMod    = mkDivMod+  toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp Word32) where+  quot      = mkQuot+  rem       = mkRem+  div       = mkIDiv+  mod       = mkMod+  quotRem   = mkQuotRem+  divMod    = mkDivMod+  toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp Word64) where+  quot      = mkQuot+  rem       = mkRem+  div       = mkIDiv+  mod       = mkMod+  quotRem   = mkQuotRem+  divMod    = mkDivMod+  toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp CInt) where+  quot      = mkQuot+  rem       = mkRem+  div       = mkIDiv+  mod       = mkMod+  quotRem   = mkQuotRem+  divMod    = mkDivMod+  toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp CUInt) where+  quot      = mkQuot+  rem       = mkRem+  div       = mkIDiv+  mod       = mkMod+  quotRem   = mkQuotRem+  divMod    = mkDivMod+  toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp CLong) where+  quot      = mkQuot+  rem       = mkRem+  div       = mkIDiv+  mod       = mkMod+  quotRem   = mkQuotRem+  divMod    = mkDivMod+  toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp CULong) where+  quot      = mkQuot+  rem       = mkRem+  div       = mkIDiv+  mod       = mkMod+  quotRem   = mkQuotRem+  divMod    = mkDivMod+  toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp CLLong) where+  quot      = mkQuot+  rem       = mkRem+  div       = mkIDiv+  mod       = mkMod+  quotRem   = mkQuotRem+  divMod    = mkDivMod+  toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp CULLong) where+  quot      = mkQuot+  rem       = mkRem+  div       = mkIDiv+  mod       = mkMod+  quotRem   = mkQuotRem+  divMod    = mkDivMod+  toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp CShort) where+  quot      = mkQuot+  rem       = mkRem+  div       = mkIDiv+  mod       = mkMod+  quotRem   = mkQuotRem+  divMod    = mkDivMod+  toInteger = error "Prelude.toInteger not supported for Accelerate types"++instance P.Integral (Exp CUShort) where+  quot      = mkQuot+  rem       = mkRem+  div       = mkIDiv+  mod       = mkMod+  quotRem   = mkQuotRem+  divMod    = mkDivMod+  toInteger = error "Prelude.toInteger not supported for Accelerate types"+
+ Data/Array/Accelerate/Classes/Num.hs view
@@ -0,0 +1,245 @@+{-# LANGUAGE ConstraintKinds   #-}+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE FlexibleInstances #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- |+-- Module      : Data.Array.Accelerate.Classes.Num+-- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Classes.Num (++  Num,+  (P.+), (P.-), (P.*), P.negate, P.abs, P.signum, P.fromInteger,++) where++import Data.Array.Accelerate.Array.Sugar+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Type++import Prelude                                                      ( (.) )+import qualified Prelude                                            as P+++-- Should we replace 'Prelude.Num' with our own version, as we did with 'Ord'+-- and 'Eq'? That might require clients to enable RebindableSyntax in order to+-- get the correct 'fromInteger' (or miss out on special magic and need to add+-- 'constant' instead).+--+-- I think that we should, because otherwise we require FlexibleContexts and+-- constraints are going to be inconsistent, e.g.:+--+-- f :: (P.Num (Exp a), A.Ord a) => ...+--+-- A light-weight alternative is the following constraint kind:+--++-- | Basic numeric class+--+type Num a = (Elt a, P.Num (Exp a))+++instance P.Num (Exp Int) where+  (+)         = mkAdd+  (-)         = mkSub+  (*)         = mkMul+  negate      = mkNeg+  abs         = mkAbs+  signum      = mkSig+  fromInteger = constant . P.fromInteger++instance P.Num (Exp Int8) where+  (+)         = mkAdd+  (-)         = mkSub+  (*)         = mkMul+  negate      = mkNeg+  abs         = mkAbs+  signum      = mkSig+  fromInteger = constant . P.fromInteger++instance P.Num (Exp Int16) where+  (+)         = mkAdd+  (-)         = mkSub+  (*)         = mkMul+  negate      = mkNeg+  abs         = mkAbs+  signum      = mkSig+  fromInteger = constant . P.fromInteger++instance P.Num (Exp Int32) where+  (+)         = mkAdd+  (-)         = mkSub+  (*)         = mkMul+  negate      = mkNeg+  abs         = mkAbs+  signum      = mkSig+  fromInteger = constant . P.fromInteger++instance P.Num (Exp Int64) where+  (+)         = mkAdd+  (-)         = mkSub+  (*)         = mkMul+  negate      = mkNeg+  abs         = mkAbs+  signum      = mkSig+  fromInteger = constant . P.fromInteger++instance P.Num (Exp Word) where+  (+)         = mkAdd+  (-)         = mkSub+  (*)         = mkMul+  negate      = mkNeg+  abs         = mkAbs+  signum      = mkSig+  fromInteger = constant . P.fromInteger++instance P.Num (Exp Word8) where+  (+)         = mkAdd+  (-)         = mkSub+  (*)         = mkMul+  negate      = mkNeg+  abs         = mkAbs+  signum      = mkSig+  fromInteger = constant . P.fromInteger++instance P.Num (Exp Word16) where+  (+)         = mkAdd+  (-)         = mkSub+  (*)         = mkMul+  negate      = mkNeg+  abs         = mkAbs+  signum      = mkSig+  fromInteger = constant . P.fromInteger++instance P.Num (Exp Word32) where+  (+)         = mkAdd+  (-)         = mkSub+  (*)         = mkMul+  negate      = mkNeg+  abs         = mkAbs+  signum      = mkSig+  fromInteger = constant . P.fromInteger++instance P.Num (Exp Word64) where+  (+)         = mkAdd+  (-)         = mkSub+  (*)         = mkMul+  negate      = mkNeg+  abs         = mkAbs+  signum      = mkSig+  fromInteger = constant . P.fromInteger++instance P.Num (Exp CInt) where+  (+)         = mkAdd+  (-)         = mkSub+  (*)         = mkMul+  negate      = mkNeg+  abs         = mkAbs+  signum      = mkSig+  fromInteger = constant . P.fromInteger++instance P.Num (Exp CUInt) where+  (+)         = mkAdd+  (-)         = mkSub+  (*)         = mkMul+  negate      = mkNeg+  abs         = mkAbs+  signum      = mkSig+  fromInteger = constant . P.fromInteger++instance P.Num (Exp CLong) where+  (+)         = mkAdd+  (-)         = mkSub+  (*)         = mkMul+  negate      = mkNeg+  abs         = mkAbs+  signum      = mkSig+  fromInteger = constant . P.fromInteger++instance P.Num (Exp CULong) where+  (+)         = mkAdd+  (-)         = mkSub+  (*)         = mkMul+  negate      = mkNeg+  abs         = mkAbs+  signum      = mkSig+  fromInteger = constant . P.fromInteger++instance P.Num (Exp CLLong) where+  (+)         = mkAdd+  (-)         = mkSub+  (*)         = mkMul+  negate      = mkNeg+  abs         = mkAbs+  signum      = mkSig+  fromInteger = constant . P.fromInteger++instance P.Num (Exp CULLong) where+  (+)         = mkAdd+  (-)         = mkSub+  (*)         = mkMul+  negate      = mkNeg+  abs         = mkAbs+  signum      = mkSig+  fromInteger = constant . P.fromInteger++instance P.Num (Exp CShort) where+  (+)         = mkAdd+  (-)         = mkSub+  (*)         = mkMul+  negate      = mkNeg+  abs         = mkAbs+  signum      = mkSig+  fromInteger = constant . P.fromInteger++instance P.Num (Exp CUShort) where+  (+)         = mkAdd+  (-)         = mkSub+  (*)         = mkMul+  negate      = mkNeg+  abs         = mkAbs+  signum      = mkSig+  fromInteger = constant . P.fromInteger++instance P.Num (Exp Float) where+  (+)         = mkAdd+  (-)         = mkSub+  (*)         = mkMul+  negate      = mkNeg+  abs         = mkAbs+  signum      = mkSig+  fromInteger = constant . P.fromInteger++instance P.Num (Exp Double) where+  (+)         = mkAdd+  (-)         = mkSub+  (*)         = mkMul+  negate      = mkNeg+  abs         = mkAbs+  signum      = mkSig+  fromInteger = constant . P.fromInteger++instance P.Num (Exp CFloat) where+  (+)         = mkAdd+  (-)         = mkSub+  (*)         = mkMul+  negate      = mkNeg+  abs         = mkAbs+  signum      = mkSig+  fromInteger = constant . P.fromInteger++instance P.Num (Exp CDouble) where+  (+)         = mkAdd+  (-)         = mkSub+  (*)         = mkMul+  negate      = mkNeg+  abs         = mkAbs+  signum      = mkSig+  fromInteger = constant . P.fromInteger+
+ Data/Array/Accelerate/Classes/Ord.hs view
@@ -0,0 +1,493 @@+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE FlexibleInstances #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- |+-- Module      : Data.Array.Accelerate.Classes.Ord+-- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Classes.Ord (++  Ord(..),++) where++import Data.Array.Accelerate.Classes.Eq+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Type++import Text.Printf+import Prelude                                                      ( ($), String, error)+import qualified Prelude                                            as P+++infix 4 <+infix 4 >+infix 4 <=+infix 4 >=++-- | The 'Ord' class for totally ordered datatypes+--+class Eq a => Ord a where+  {-# MINIMAL (<=) #-}+  (<)  :: Exp a -> Exp a -> Exp Bool+  (>)  :: Exp a -> Exp a -> Exp Bool+  (<=) :: Exp a -> Exp a -> Exp Bool+  (>=) :: Exp a -> Exp a -> Exp Bool+  min  :: Exp a -> Exp a -> Exp a+  max  :: Exp a -> Exp a -> Exp a+  --+  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+++instance Ord () where+  (<)  _ _ = constant False+  (>)  _ _ = constant False+  (>=) _ _ = constant True+  (<=) _ _ = constant True+  min  _ _ = constant ()+  max  _ _ = constant ()++instance Ord Int where+  (<)  = mkLt+  (>)  = mkGt+  (<=) = mkLtEq+  (>=) = mkGtEq+  min  = mkMin+  max  = mkMax++instance Ord Int8 where+  (<)  = mkLt+  (>)  = mkGt+  (<=) = mkLtEq+  (>=) = mkGtEq+  min  = mkMin+  max  = mkMax++instance Ord Int16 where+  (<)  = mkLt+  (>)  = mkGt+  (<=) = mkLtEq+  (>=) = mkGtEq+  min  = mkMin+  max  = mkMax++instance Ord Int32 where+  (<)  = mkLt+  (>)  = mkGt+  (<=) = mkLtEq+  (>=) = mkGtEq+  min  = mkMin+  max  = mkMax++instance Ord Int64 where+  (<)  = mkLt+  (>)  = mkGt+  (<=) = mkLtEq+  (>=) = mkGtEq+  min  = mkMin+  max  = mkMax++instance Ord Word where+  (<)  = mkLt+  (>)  = mkGt+  (<=) = mkLtEq+  (>=) = mkGtEq+  min  = mkMin+  max  = mkMax++instance Ord Word8 where+  (<)  = mkLt+  (>)  = mkGt+  (<=) = mkLtEq+  (>=) = mkGtEq+  min  = mkMin+  max  = mkMax++instance Ord Word16 where+  (<)  = mkLt+  (>)  = mkGt+  (<=) = mkLtEq+  (>=) = mkGtEq+  min  = mkMin+  max  = mkMax++instance Ord Word32 where+  (<)  = mkLt+  (>)  = mkGt+  (<=) = mkLtEq+  (>=) = mkGtEq+  min  = mkMin+  max  = mkMax++instance Ord Word64 where+  (<)  = mkLt+  (>)  = mkGt+  (<=) = mkLtEq+  (>=) = mkGtEq+  min  = mkMin+  max  = mkMax++instance Ord CInt where+  (<)  = mkLt+  (>)  = mkGt+  (<=) = mkLtEq+  (>=) = mkGtEq+  min  = mkMin+  max  = mkMax++instance Ord CUInt where+  (<)  = mkLt+  (>)  = mkGt+  (<=) = mkLtEq+  (>=) = mkGtEq+  min  = mkMin+  max  = mkMax++instance Ord CLong where+  (<)  = mkLt+  (>)  = mkGt+  (<=) = mkLtEq+  (>=) = mkGtEq+  min  = mkMin+  max  = mkMax++instance Ord CULong where+  (<)  = mkLt+  (>)  = mkGt+  (<=) = mkLtEq+  (>=) = mkGtEq+  min  = mkMin+  max  = mkMax++instance Ord CLLong where+  (<)  = mkLt+  (>)  = mkGt+  (<=) = mkLtEq+  (>=) = mkGtEq+  min  = mkMin+  max  = mkMax++instance Ord CULLong where+  (<)  = mkLt+  (>)  = mkGt+  (<=) = mkLtEq+  (>=) = mkGtEq+  min  = mkMin+  max  = mkMax++instance Ord CShort where+  (<)  = mkLt+  (>)  = mkGt+  (<=) = mkLtEq+  (>=) = mkGtEq+  min  = mkMin+  max  = mkMax++instance Ord CUShort where+  (<)  = mkLt+  (>)  = mkGt+  (<=) = mkLtEq+  (>=) = mkGtEq+  min  = mkMin+  max  = mkMax++instance Ord Bool where+  (<)  = mkLt+  (>)  = mkGt+  (<=) = mkLtEq+  (>=) = mkGtEq+  min  = mkMin+  max  = mkMax++instance Ord Char where+  (<)  = mkLt+  (>)  = mkGt+  (<=) = mkLtEq+  (>=) = mkGtEq+  min  = mkMin+  max  = mkMax++instance Ord CChar where+  (<)  = mkLt+  (>)  = mkGt+  (<=) = mkLtEq+  (>=) = mkGtEq+  min  = mkMin+  max  = mkMax++instance Ord CUChar where+  (<)  = mkLt+  (>)  = mkGt+  (<=) = mkLtEq+  (>=) = mkGtEq+  min  = mkMin+  max  = mkMax++instance Ord CSChar where+  (<)  = mkLt+  (>)  = mkGt+  (<=) = mkLtEq+  (>=) = mkGtEq+  min  = mkMin+  max  = mkMax++instance Ord Float where+  (<)  = mkLt+  (>)  = mkGt+  (<=) = mkLtEq+  (>=) = mkGtEq+  min  = mkMin+  max  = mkMax++instance Ord Double where+  (<)  = mkLt+  (>)  = mkGt+  (<=) = mkLtEq+  (>=) = mkGtEq+  min  = mkMin+  max  = mkMax++instance Ord CFloat where+  (<)  = mkLt+  (>)  = mkGt+  (<=) = mkLtEq+  (>=) = mkGtEq+  min  = mkMin+  max  = mkMax++instance Ord CDouble where+  (<)  = mkLt+  (>)  = mkGt+  (<=) = mkLtEq+  (>=) = mkGtEq+  min  = mkMin+  max  = mkMax++instance (Ord a, Ord b) => Ord (a, b) where+  x <= y = let (a1,b1) = untup2 x+               (a2,b2) = untup2 y+           in a1 < a2 || (a1 == a2 && b1 <= b2)+  x >= y = let (a1,b1) = untup2 x+               (a2,b2) = untup2 y+           in a1 > a2 || (a1 == a2 && b1 >= b2)+  x < y  = let (a1,b1) = untup2 x+               (a2,b2) = untup2 y+           in a1 < a2 || (a1 == a2 && b1 < b2)+  x > y  = let (a1,b1) = untup2 x+               (a2,b2) = untup2 y+           in a1 > a2 || (a1 == a2 && b1 > b2)++instance (Ord a, Ord b, Ord c) => Ord (a, b, c) where+  x <= y = let (a1,b1,c1) = untup3 x; x' = tup2 (b1,c1)+               (a2,b2,c2) = untup3 y; y' = tup2 (b2,c2)+           in a1 < a2 || (a1 == a2 && x' <= y')+  x >= y = let (a1,b1,c1) = untup3 x; x' = tup2 (b1,c1)+               (a2,b2,c2) = untup3 y; y' = tup2 (b2,c2)+           in a1 > a2 || (a1 == a2 && x' >= y')+  x < y  = let (a1,b1,c1) = untup3 x; x' = tup2 (b1,c1)+               (a2,b2,c2) = untup3 y; y' = tup2 (b2,c2)+           in a1 < a2 || (a1 == a2 && x' < y')+  x > y  = let (a1,b1,c1) = untup3 x; x' = tup2 (b1,c1)+               (a2,b2,c2) = untup3 y; y' = tup2 (b2,c2)+           in a1 > a2 || (a1 == a2 && x' > y')++instance (Ord a, Ord b, Ord c, Ord d) => Ord (a, b, c, d) where+  x <= y = let (a1,b1,c1,d1) = untup4 x; x' = tup3 (b1,c1,d1)+               (a2,b2,c2,d2) = untup4 y; y' = tup3 (b2,c2,d2)+           in a1 < a2 || (a1 == a2 && x' <= y')+  x >= y = let (a1,b1,c1,d1) = untup4 x; x' = tup3 (b1,c1,d1)+               (a2,b2,c2,d2) = untup4 y; y' = tup3 (b2,c2,d2)+           in a1 > a2 || (a1 == a2 && x' >= y')+  x < y  = let (a1,b1,c1,d1) = untup4 x; x' = tup3 (b1,c1,d1)+               (a2,b2,c2,d2) = untup4 y; y' = tup3 (b2,c2,d2)+           in a1 < a2 || (a1 == a2 && x' < y')+  x > y  = let (a1,b1,c1,d1) = untup4 x; x' = tup3 (b1,c1,d1)+               (a2,b2,c2,d2) = untup4 y; y' = tup3 (b2,c2,d2)+           in a1 > a2 || (a1 == a2 && x' > y')++instance (Ord a, Ord b, Ord c, Ord d, Ord e) => Ord (a, b, c, d, e) where+  x <= y = let (a1,b1,c1,d1,e1) = untup5 x; x' = tup4 (b1,c1,d1,e1)+               (a2,b2,c2,d2,e2) = untup5 y; y' = tup4 (b2,c2,d2,e2)+           in a1 < a2 || (a1 == a2 && x' <= y')+  x >= y = let (a1,b1,c1,d1,e1) = untup5 x; x' = tup4 (b1,c1,d1,e1)+               (a2,b2,c2,d2,e2) = untup5 y; y' = tup4 (b2,c2,d2,e2)+           in a1 > a2 || (a1 == a2 && x' >= y')+  x < y  = let (a1,b1,c1,d1,e1) = untup5 x; x' = tup4 (b1,c1,d1,e1)+               (a2,b2,c2,d2,e2) = untup5 y; y' = tup4 (b2,c2,d2,e2)+           in a1 < a2 || (a1 == a2 && x' < y')+  x > y  = let (a1,b1,c1,d1,e1) = untup5 x; x' = tup4 (b1,c1,d1,e1)+               (a2,b2,c2,d2,e2) = untup5 y; y' = tup4 (b2,c2,d2,e2)+           in a1 > a2 || (a1 == a2 && x' > y')++instance (Ord a, Ord b, Ord c, Ord d, Ord e, Ord f) => Ord (a, b, c, d, e, f) where+  x <= y = let (a1,b1,c1,d1,e1,f1) = untup6 x; x' = tup5 (b1,c1,d1,e1,f1)+               (a2,b2,c2,d2,e2,f2) = untup6 y; y' = tup5 (b2,c2,d2,e2,f2)+           in a1 < a2 || (a1 == a2 && x' <= y')+  x >= y = let (a1,b1,c1,d1,e1,f1) = untup6 x; x' = tup5 (b1,c1,d1,e1,f1)+               (a2,b2,c2,d2,e2,f2) = untup6 y; y' = tup5 (b2,c2,d2,e2,f2)+           in a1 > a2 || (a1 == a2 && x' >= y')+  x < y  = let (a1,b1,c1,d1,e1,f1) = untup6 x; x' = tup5 (b1,c1,d1,e1,f1)+               (a2,b2,c2,d2,e2,f2) = untup6 y; y' = tup5 (b2,c2,d2,e2,f2)+           in a1 < a2 || (a1 == a2 && x' < y')+  x > y  = let (a1,b1,c1,d1,e1,f1) = untup6 x; x' = tup5 (b1,c1,d1,e1,f1)+               (a2,b2,c2,d2,e2,f2) = untup6 y; y' = tup5 (b2,c2,d2,e2,f2)+           in a1 > a2 || (a1 == a2 && x' > y')++instance (Ord a, Ord b, Ord c, Ord d, Ord e, Ord f, Ord g) => Ord (a, b, c, d, e, f, g) where+  x <= y = let (a1,b1,c1,d1,e1,f1,g1) = untup7 x; x' = tup6 (b1,c1,d1,e1,f1,g1)+               (a2,b2,c2,d2,e2,f2,g2) = untup7 y; y' = tup6 (b2,c2,d2,e2,f2,g2)+           in a1 < a2 || (a1 == a2 && x' <= y')+  x >= y = let (a1,b1,c1,d1,e1,f1,g1) = untup7 x; x' = tup6 (b1,c1,d1,e1,f1,g1)+               (a2,b2,c2,d2,e2,f2,g2) = untup7 y; y' = tup6 (b2,c2,d2,e2,f2,g2)+           in a1 > a2 || (a1 == a2 && x' >= y')+  x < y  = let (a1,b1,c1,d1,e1,f1,g1) = untup7 x; x' = tup6 (b1,c1,d1,e1,f1,g1)+               (a2,b2,c2,d2,e2,f2,g2) = untup7 y; y' = tup6 (b2,c2,d2,e2,f2,g2)+           in a1 < a2 || (a1 == a2 && x' < y')+  x > y  = let (a1,b1,c1,d1,e1,f1,g1) = untup7 x; x' = tup6 (b1,c1,d1,e1,f1,g1)+               (a2,b2,c2,d2,e2,f2,g2) = untup7 y; y' = tup6 (b2,c2,d2,e2,f2,g2)+           in a1 > a2 || (a1 == a2 && x' > y')++instance (Ord a, Ord b, Ord c, Ord d, Ord e, Ord f, Ord g, Ord h) => Ord (a, b, c, d, e, f, g, h) where+  x <= y = let (a1,b1,c1,d1,e1,f1,g1,h1) = untup8 x; x' = tup7 (b1,c1,d1,e1,f1,g1,h1)+               (a2,b2,c2,d2,e2,f2,g2,h2) = untup8 y; y' = tup7 (b2,c2,d2,e2,f2,g2,h2)+           in a1 < a2 || (a1 == a2 && x' <= y')+  x >= y = let (a1,b1,c1,d1,e1,f1,g1,h1) = untup8 x; x' = tup7 (b1,c1,d1,e1,f1,g1,h1)+               (a2,b2,c2,d2,e2,f2,g2,h2) = untup8 y; y' = tup7 (b2,c2,d2,e2,f2,g2,h2)+           in a1 > a2 || (a1 == a2 && x' >= y')+  x < y  = let (a1,b1,c1,d1,e1,f1,g1,h1) = untup8 x; x' = tup7 (b1,c1,d1,e1,f1,g1,h1)+               (a2,b2,c2,d2,e2,f2,g2,h2) = untup8 y; y' = tup7 (b2,c2,d2,e2,f2,g2,h2)+           in a1 < a2 || (a1 == a2 && x' < y')+  x > y  = let (a1,b1,c1,d1,e1,f1,g1,h1) = untup8 x; x' = tup7 (b1,c1,d1,e1,f1,g1,h1)+               (a2,b2,c2,d2,e2,f2,g2,h2) = untup8 y; y' = tup7 (b2,c2,d2,e2,f2,g2,h2)+           in a1 > a2 || (a1 == a2 && x' > y')++instance (Ord a, Ord b, Ord c, Ord d, Ord e, Ord f, Ord g, Ord h, Ord i) => Ord (a, b, c, d, e, f, g, h, i) where+  x <= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1) = untup9 x; x' = tup8 (b1,c1,d1,e1,f1,g1,h1,i1)+               (a2,b2,c2,d2,e2,f2,g2,h2,i2) = untup9 y; y' = tup8 (b2,c2,d2,e2,f2,g2,h2,i2)+           in a1 < a2 || (a1 == a2 && x' <= y')+  x >= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1) = untup9 x; x' = tup8 (b1,c1,d1,e1,f1,g1,h1,i1)+               (a2,b2,c2,d2,e2,f2,g2,h2,i2) = untup9 y; y' = tup8 (b2,c2,d2,e2,f2,g2,h2,i2)+           in a1 > a2 || (a1 == a2 && x' >= y')+  x < y  = let (a1,b1,c1,d1,e1,f1,g1,h1,i1) = untup9 x; x' = tup8 (b1,c1,d1,e1,f1,g1,h1,i1)+               (a2,b2,c2,d2,e2,f2,g2,h2,i2) = untup9 y; y' = tup8 (b2,c2,d2,e2,f2,g2,h2,i2)+           in a1 < a2 || (a1 == a2 && x' < y')+  x > y  = let (a1,b1,c1,d1,e1,f1,g1,h1,i1) = untup9 x; x' = tup8 (b1,c1,d1,e1,f1,g1,h1,i1)+               (a2,b2,c2,d2,e2,f2,g2,h2,i2) = untup9 y; y' = tup8 (b2,c2,d2,e2,f2,g2,h2,i2)+           in a1 > a2 || (a1 == a2 && x' > y')++instance (Ord a, Ord b, Ord c, Ord d, Ord e, Ord f, Ord g, Ord h, Ord i, Ord j) => Ord (a, b, c, d, e, f, g, h, i, j) where+  x <= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1) = untup10 x; x' = tup9 (b1,c1,d1,e1,f1,g1,h1,i1,j1)+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2) = untup10 y; y' = tup9 (b2,c2,d2,e2,f2,g2,h2,i2,j2)+           in a1 < a2 || (a1 == a2 && x' <= y')+  x >= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1) = untup10 x; x' = tup9 (b1,c1,d1,e1,f1,g1,h1,i1,j1)+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2) = untup10 y; y' = tup9 (b2,c2,d2,e2,f2,g2,h2,i2,j2)+           in a1 > a2 || (a1 == a2 && x' >= y')+  x < y  = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1) = untup10 x; x' = tup9 (b1,c1,d1,e1,f1,g1,h1,i1,j1)+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2) = untup10 y; y' = tup9 (b2,c2,d2,e2,f2,g2,h2,i2,j2)+           in a1 < a2 || (a1 == a2 && x' < y')+  x > y  = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1) = untup10 x; x' = tup9 (b1,c1,d1,e1,f1,g1,h1,i1,j1)+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2) = untup10 y; y' = tup9 (b2,c2,d2,e2,f2,g2,h2,i2,j2)+           in a1 > a2 || (a1 == a2 && x' > y')++instance (Ord a, Ord b, Ord c, Ord d, Ord e, Ord f, Ord g, Ord h, Ord i, Ord j, Ord k) => Ord (a, b, c, d, e, f, g, h, i, j, k) where+  x <= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1) = untup11 x; x' = tup10 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1)+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2) = untup11 y; y' = tup10 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2)+           in a1 < a2 || (a1 == a2 && x' <= y')+  x >= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1) = untup11 x; x' = tup10 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1)+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2) = untup11 y; y' = tup10 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2)+           in a1 > a2 || (a1 == a2 && x' >= y')+  x < y  = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1) = untup11 x; x' = tup10 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1)+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2) = untup11 y; y' = tup10 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2)+           in a1 < a2 || (a1 == a2 && x' < y')+  x > y  = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1) = untup11 x; x' = tup10 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1)+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2) = untup11 y; y' = tup10 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2)+           in a1 > a2 || (a1 == a2 && x' > y')++instance (Ord a, Ord b, Ord c, Ord d, Ord e, Ord f, Ord g, Ord h, Ord i, Ord j, Ord k, Ord l) => Ord (a, b, c, d, e, f, g, h, i, j, k, l) where+  x <= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1) = untup12 x; x' = tup11 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1)+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2) = untup12 y; y' = tup11 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2)+           in a1 < a2 || (a1 == a2 && x' <= y')+  x >= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1) = untup12 x; x' = tup11 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1)+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2) = untup12 y; y' = tup11 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2)+           in a1 > a2 || (a1 == a2 && x' >= y')+  x < y  = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1) = untup12 x; x' = tup11 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1)+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2) = untup12 y; y' = tup11 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2)+           in a1 < a2 || (a1 == a2 && x' < y')+  x > y  = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1) = untup12 x; x' = tup11 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1)+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2) = untup12 y; y' = tup11 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2)+           in a1 > a2 || (a1 == a2 && x' > y')++instance (Ord a, Ord b, Ord c, Ord d, Ord e, Ord f, Ord g, Ord h, Ord i, Ord j, Ord k, Ord l, Ord m) => Ord (a, b, c, d, e, f, g, h, i, j, k, l, m) where+  x <= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1) = untup13 x; x' = tup12 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1)+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2) = untup13 y; y' = tup12 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2)+           in a1 < a2 || (a1 == a2 && x' <= y')+  x >= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1) = untup13 x; x' = tup12 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1)+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2) = untup13 y; y' = tup12 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2)+           in a1 > a2 || (a1 == a2 && x' >= y')+  x < y  = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1) = untup13 x; x' = tup12 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1)+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2) = untup13 y; y' = tup12 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2)+           in a1 < a2 || (a1 == a2 && x' < y')+  x > y  = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1) = untup13 x; x' = tup12 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1)+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2) = untup13 y; y' = tup12 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2)+           in a1 > a2 || (a1 == a2 && x' > y')++instance (Ord a, Ord b, Ord c, Ord d, Ord e, Ord f, Ord g, Ord h, Ord i, Ord j, Ord k, Ord l, Ord m, Ord n) => Ord (a, b, c, d, e, f, g, h, i, j, k, l, m, n) where+  x <= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1) = untup14 x; x' = tup13 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1)+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2) = untup14 y; y' = tup13 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2)+           in a1 < a2 || (a1 == a2 && x' <= y')+  x >= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1) = untup14 x; x' = tup13 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1)+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2) = untup14 y; y' = tup13 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2)+           in a1 > a2 || (a1 == a2 && x' >= y')+  x < y  = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1) = untup14 x; x' = tup13 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1)+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2) = untup14 y; y' = tup13 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2)+           in a1 < a2 || (a1 == a2 && x' < y')+  x > y  = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1) = untup14 x; x' = tup13 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1)+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2) = untup14 y; y' = tup13 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2)+           in a1 > a2 || (a1 == a2 && x' > y')++instance (Ord a, Ord b, Ord c, Ord d, Ord e, Ord f, Ord g, Ord h, Ord i, Ord j, Ord k, Ord l, Ord m, Ord n, Ord o) => Ord (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) where+  x <= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,o1) = untup15 x; x' = tup14 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,o1)+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2,o2) = untup15 y; y' = tup14 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2,o2)+           in a1 < a2 || (a1 == a2 && x' <= y')+  x >= y = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,o1) = untup15 x; x' = tup14 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,o1)+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2,o2) = untup15 y; y' = tup14 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2,o2)+           in a1 > a2 || (a1 == a2 && x' >= y')+  x < y  = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,o1) = untup15 x; x' = tup14 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,o1)+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2,o2) = untup15 y; y' = tup14 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2,o2)+           in a1 < a2 || (a1 == a2 && x' < y')+  x > y  = let (a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,o1) = untup15 x; x' = tup14 (b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,o1)+               (a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2,o2) = untup15 y; y' = tup14 (b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2,o2)+           in a1 > a2 || (a1 == a2 && x' > y')+++-- Instances of 'Prelude.Ord' (mostly) don't make sense with the standard+-- signatures as the return type is fixed to 'Bool'. This instance is provided+-- to provide a useful error message.+--+-- Note that 'min' and 'max' are implementable, so we do hook those into the+-- accelerate instances defined here. This allows us to use operations such as+-- 'Prelude.minimum' and 'Prelude.maximum'.+--+instance Ord a => P.Ord (Exp a) where+  compare = error "Prelude.Ord.compare applied to EDSL types"+  (<)     = preludeError "Ord.<"  "(<)"+  (<=)    = preludeError "Ord.<=" "(<=)"+  (>)     = preludeError "Ord.>"  "(>)"+  (>=)    = preludeError "Ord.>=" "(>=)"+  min     = min+  max     = max++preludeError :: String -> String -> a+preludeError x y = error (printf "Prelude.%s applied to EDSL types: use Data.Array.Accelerate.%s instead" x y)+
+ Data/Array/Accelerate/Classes/Real.hs view
@@ -0,0 +1,40 @@+{-# LANGUAGE ConstraintKinds      #-}+{-# LANGUAGE FlexibleContexts     #-}+{-# LANGUAGE FlexibleInstances    #-}+{-# LANGUAGE UndecidableInstances #-}+{-# OPTIONS_GHC -fno-warn-missing-methods #-}+{-# OPTIONS_GHC -fno-warn-orphans         #-}+-- |+-- Module      : Data.Array.Accelerate.Classes.Real+-- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Classes.Real (++  Real,++) where++import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Classes.Num+import Data.Array.Accelerate.Classes.Ord++import qualified Prelude                                            as P+++type Real a = (Num a, Ord a, P.Real (Exp a))++-- Instances of 'Real' don't make sense in Accelerate at the moment. These are+-- only provided to fulfil superclass constraints; e.g. Integral.+--+-- We won't need `toRational' until we support rational numbers in AP+-- computations.+--+instance (Num a, Ord a) => P.Real (Exp a) where+  toRational = P.error "Prelude.toRational not supported for Accelerate types"+
+ Data/Array/Accelerate/Classes/RealFloat.hs view
@@ -0,0 +1,142 @@+{-# LANGUAGE ConstraintKinds     #-}+{-# LANGUAGE DefaultSignatures   #-}+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE FlexibleInstances   #-}+{-# LANGUAGE NoImplicitPrelude   #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell     #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- |+-- Module      : Data.Array.Accelerate.Classes.RealFloat+-- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Classes.RealFloat (++  RealFloat(..),++) where++import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.Classes.Floating+import Data.Array.Accelerate.Classes.RealFrac++import Text.Printf+import Prelude                                                      ( String, error, undefined )+import qualified Prelude                                            as P+++-- | Efficient, machine-independent access to the components of a floating-point+-- number+--+class (RealFrac a, Floating a) => RealFloat a where+  -- | The radix of the representation (often 2) (constant)+  floatRadix     :: Exp a -> Exp Int64  -- Integer+  default floatRadix :: P.RealFloat a => Exp a -> Exp Int64+  floatRadix _    = P.fromInteger (P.floatRadix (undefined::a))++  -- | The number of digits of 'floatRadix' in the significand (constant)+  floatDigits    :: Exp a -> Exp Int+  default floatDigits :: P.RealFloat a => Exp a -> Exp Int+  floatDigits _   = constant (P.floatDigits (undefined::a))++  -- | The lowest and highest values the exponent may assume (constant)+  floatRange     :: Exp a -> (Exp Int, Exp Int)+  default floatRange :: P.RealFloat a => Exp a -> (Exp Int, Exp Int)+  floatRange _    = let (m,n) = P.floatRange (undefined::a)+                    in (constant m, constant n)++  -- | 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    :: Exp a -> (Exp Int64, Exp Int)    -- Integer++  -- | Inverse of 'decodeFloat'+  encodeFloat    :: Exp Int64 -> Exp Int -> Exp a    -- Integer++  -- | Corresponds to the second component of 'decodeFloat'+  exponent       :: Exp a -> Exp Int++  -- | Corresponds to the first component of 'decodeFloat'+  significand    :: Exp a -> Exp a++  -- | Multiply a floating point number by an integer power of the radix+  scaleFloat     :: Exp Int -> Exp a -> Exp a++  -- | 'True' if the argument is an IEEE \"not-a-number\" (NaN) value+  isNaN          :: Exp a -> Exp Bool++  -- | 'True' if the argument is an IEEE infinity or negative-infinity+  isInfinite     :: Exp a -> Exp Bool++  -- | 'True' if the argument is too small to be represented in normalized+  -- format+  isDenormalized :: Exp a -> Exp Bool++  -- | 'True' if the argument is an IEEE negative zero+  isNegativeZero :: Exp a -> Exp Bool++  -- | 'True' if the argument is an IEEE floating point number+  isIEEE         :: Exp a -> Exp Bool+  default isIEEE :: P.RealFloat a => Exp a -> Exp Bool+  isIEEE _        = constant (P.isIEEE (undefined::Float))++  -- | 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          :: Exp a -> Exp a -> Exp a++  decodeFloat     = $internalError "RealFloat.decodeFloat"    "Not implemented yet"+  encodeFloat     = $internalError "RealFloat.encodeFloat"    "Not implemented yet"+  exponent        = $internalError "RealFloat.exponent"       "Not implemented yet"+  significand     = $internalError "RealFloat.significand"    "Not implemented yet"+  scaleFloat      = $internalError "RealFloat.scaleFloat"     "Not implemented yet"+  isInfinite      = $internalError "RealFloat.isInfinite"     "Not implemented yet"+  isDenormalized  = $internalError "RealFloat.isDenormalized" "Not implemented yet"+  isNegativeZero  = $internalError "RealFloat.isNegativeZero" "Not implemented yet"+++instance RealFloat Float where+  isNaN           = mkIsNaN+  atan2           = mkAtan2++instance RealFloat Double where+  isNaN           = mkIsNaN+  atan2           = mkAtan2++instance RealFloat CFloat where+  isNaN           = mkIsNaN+  atan2           = mkAtan2++instance RealFloat CDouble where+  isNaN           = mkIsNaN+  atan2           = mkAtan2+++-- To satisfy superclass constraints+--+instance RealFloat a => P.RealFloat (Exp a) where+  floatRadix     = preludeError "floatRadix"+  floatDigits    = preludeError "floatDigits"+  floatRange     = preludeError "floatRange"+  decodeFloat    = preludeError "decodeFloat"+  encodeFloat    = preludeError "encodeFloat"+  isNaN          = preludeError "isNaN"+  isInfinite     = preludeError "isInfinite"+  isDenormalized = preludeError "isDenormalized"+  isNegativeZero = preludeError "isNegativeZero"+  isIEEE         = preludeError "isIEEE"++preludeError :: String -> a+preludeError x = error (printf "Prelude.%s applied to EDSL types: use Data.Array.Accelerate.%s instead" x)+
+ Data/Array/Accelerate/Classes/RealFrac.hs view
@@ -0,0 +1,165 @@+{-# LANGUAGE ConstraintKinds   #-}+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE NoImplicitPrelude #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- |+-- Module      : Data.Array.Accelerate.Classes.RealFrac+-- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Classes.RealFrac (++  RealFrac(..),+  div', mod', divMod',++) where++import Data.Array.Accelerate.Array.Sugar+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.Classes.Eq+import Data.Array.Accelerate.Classes.Floating+import Data.Array.Accelerate.Classes.Fractional+import Data.Array.Accelerate.Classes.Num+import Data.Array.Accelerate.Classes.Real+import Data.Array.Accelerate.Classes.ToFloating++import Text.Printf+import Prelude                                                      ( ($), String, error )+import qualified Prelude                                            as P+++-- | Generalisation of 'P.div' to any instance of 'RealFrac'+--+div' :: (RealFrac a, Elt b, IsIntegral b) => Exp a -> Exp a -> Exp b+div' n d = floor (n / d)++-- | Generalisation of 'P.mod' to any instance of 'RealFrac'+--+mod' :: (Floating a, RealFrac a, ToFloating Int a) => Exp a -> Exp a -> Exp a+mod' n d = n - (toFloating f) * d+  where+    f :: Exp Int+    f = div' n d++-- | Generalisation of 'P.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)+divMod' n d = (f, n - (toFloating f) * d)+  where+    f = div' n d+++-- | Extracting components of fractions.+--+class (Real a, Fractional a) => RealFrac a where+  -- The function 'properFraction' takes a real fractional number @x@ and+  -- returns a pair @(n,f)@ such that @x = n+f@, and:+  --+  -- * @n@ is an integral number with the same sign as @x@; and+  --+  -- * @f@ is a fraction with the same type and sign as @x@,+  --   and with absolute value less than @1@.+  --+  -- The default definitions of the 'ceiling', 'floor', 'truncate'+  -- and 'round' functions are in terms of 'properFraction'.+  properFraction :: (Num b, ToFloating b a, IsIntegral b) => Exp a -> (Exp b, Exp a)++  -- The function 'splitFraction' takes a real fractional number @x@ and+  -- returns a pair @(n,f)@ such that @x = n+f@, and:+  --+  -- * @n@ is an integral number with the same sign as @x@; and+  --+  -- * @f@ is a fraction with the same type as @x@ in the range [0,1). Note that+  -- this differs from 'Prelude.properFraction'.+  --+  -- splitFraction :: (Elt b, IsIntegral b) => Exp a -> (Exp b, Exp a)++  -- @fraction x@ returns @x@ with the integer part removed.+  -- fraction       :: Exp a -> Exp a++  -- properFraction is part of the standard Haskell'98 RealFrac type classes+  -- splitFraction / fraction are from numeric-prelude Algebra.RealRing++  -- | @truncate x@ returns the integer nearest @x@ between zero and @x@+  truncate       :: (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          :: (Elt b, IsIntegral b) => Exp a -> Exp b++  -- | @'ceiling' x@ returns the least integer not less than @x@+  ceiling        :: (Elt b, IsIntegral b) => Exp a -> Exp b++  -- | @'floor' x@ returns the greatest integer not greater than @x@+  floor          :: (Elt b, IsIntegral b) => Exp a -> Exp b+++instance RealFrac Float where+  properFraction  = defaultProperFraction+  truncate        = mkTruncate+  round           = mkRound+  ceiling         = mkCeiling+  floor           = mkFloor++instance RealFrac Double where+  properFraction  = defaultProperFraction+  truncate        = mkTruncate+  round           = mkRound+  ceiling         = mkCeiling+  floor           = mkFloor++instance RealFrac CFloat where+  properFraction  = defaultProperFraction+  truncate        = mkTruncate+  round           = mkRound+  ceiling         = mkCeiling+  floor           = mkFloor++instance RealFrac CDouble where+  properFraction  = defaultProperFraction+  truncate        = mkTruncate+  round           = mkRound+  ceiling         = mkCeiling+  floor           = mkFloor+++-- Must test for ±0.0 to avoid returning -0.0 in the second component of the+-- pair. Unfortunately the branching costs a lot of performance.+--+defaultProperFraction+    :: (ToFloating a b, RealFrac b, IsIntegral a, Num a, Floating b)+    => Exp b+    -> (Exp a, Exp b)+defaultProperFraction x =+  untup2 $ Exp+         $ Cond (x == 0) (tup2 (0, 0))+                         (tup2 (n, f))+  where+    n = truncate x+    f = x - toFloating n+++-- To satisfy superclass constraints+--+instance RealFrac a => P.RealFrac (Exp a) where+  properFraction = preludeError "properFraction"+  truncate       = preludeError "truncate"+  round          = preludeError "round"+  ceiling        = preludeError "ceiling"+  floor          = preludeError "floor"++preludeError :: String -> a+preludeError x = error (printf "Prelude.%s applied to EDSL types: use Data.Array.Accelerate.%s instead" x)+
+ Data/Array/Accelerate/Classes/ToFloating.hs view
@@ -0,0 +1,82 @@+{-# LANGUAGE CPP                   #-}+{-# LANGUAGE ConstraintKinds       #-}+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE NoImplicitPrelude     #-}+{-# LANGUAGE TemplateHaskell       #-}+-- |+-- Module      : Data.Array.Accelerate.Classes.ToFloating+-- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Classes.ToFloating (++  ToFloating(..),++) where++import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.Classes.Floating+import Data.Array.Accelerate.Classes.Num++import Language.Haskell.TH                                          hiding ( Exp )+import Control.Monad+import Prelude                                                      ( ($), error, concat )+++-- | Accelerate lacks an arbitrary-precision 'Prelude.Rational' type, which the+-- standard 'Prelude.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 where+  -- | General coercion to floating types+  toFloating :: (Num a, Floating b) => Exp a -> Exp b++-- instance (Elt a, Elt b, IsNum a, IsFloating b) => ToFloating a b where+--   toFloating = mkToFloating++-- Generate standard instances explicitly. See also: 'FromIntegral'.+--+$(runQ $ do+    let+        -- Get all the types that our dictionaries reify+        digItOut :: Name -> Q [Name]+        digItOut name = do+#if __GLASGOW_HASKELL__ < 800+          TyConI (DataD _ _ _   cons _) <- reify name+#else+          TyConI (DataD _ _ _ _ cons _) <- reify name+#endif+          let+            dig (NormalC _ [(_, AppT (ConT n) (VarT _))])               = digItOut n+#if __GLASGOW_HASKELL__ < 800+            dig (ForallC _ _ (NormalC _ [(_, AppT (ConT _) (ConT n))])) = return [n]+#else+            dig (GadtC _ _ (AppT (ConT _) (ConT n)))                    = return [n]+#endif+            dig _ = error "Unexpected case generating ToFloating instances"+            --+          concat `fmap` mapM dig cons++        thToFloating :: Name -> Name -> Q Dec+        thToFloating a b =+          let+              ty  = AppT (AppT (ConT (mkName "ToFloating")) (ConT a)) (ConT b)+              dec = ValD (VarP (mkName "toFloating")) (NormalB (VarE (mkName "mkToFloating"))) []+          in+          instanceD (return []) (return ty) [return dec]+    --+    as <- digItOut ''NumType+    bs <- digItOut ''FloatingType+    sequence [ thToFloating a b | a <- as, b <- bs ]+ )+
+ Data/Array/Accelerate/Data/Bits.hs view
@@ -0,0 +1,806 @@+{-# LANGUAGE ConstraintKinds     #-}+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell     #-}+{-# LANGUAGE ViewPatterns        #-}+-- |+-- Module      : Data.Array.Accelerate.Data.Bits+-- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- Bitwise operations for signed and unsigned integer expressions.+--++module Data.Array.Accelerate.Data.Bits (++  Bits(..),+  FiniteBits(..),++) where++import Data.Array.Accelerate.Array.Sugar+import Data.Array.Accelerate.Language+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.Classes.Eq+import Data.Array.Accelerate.Classes.Ord+import Data.Array.Accelerate.Classes.Num+import Data.Array.Accelerate.Classes.Integral                       ()++import Prelude                                                      ( ($), (.), undefined, otherwise )+import qualified Data.Bits                                          as B+++infixl 8 `shift`, `rotate`, `shiftL`, `shiftR`, `rotateL`, `rotateR`+infixl 7 .&.+infixl 6 `xor`+infixl 5 .|.+++-- | The 'Bits' class defines bitwise operations over integral scalar expression+-- types. As usual, bits are numbered from zero, with zero being the least+-- significant bit.+--+class Eq a => Bits a where+  {-# MINIMAL (.&.), (.|.), xor, complement,+              (shift | (shiftL, shiftR)),+              (rotate | (rotateL, rotateR)),+              isSigned, testBit, bit, popCount #-}++  -- | Bitwise "and"+  (.&.)         :: Exp a -> Exp a -> Exp a++  -- | Bitwise "or"+  (.|.)         :: Exp a -> Exp a -> Exp a++  -- | Bitwise "xor"+  xor           :: Exp a -> Exp a -> Exp a++  -- | Reverse all bits in the argument+  complement    :: Exp a -> Exp a++  -- | @'shift' x i@ shifts @x@ left by @i@ bits if @i@ is positive, or right by+  -- @-i@ bits otherwise. Right shifts perform sign extension on signed number+  -- types; i.e. they fill the top bits with 1 if the @x@ is negative and with+  -- 0 otherwise.+  shift         :: Exp a -> Exp Int -> Exp a+  shift x i+    = cond (i < 0) (x `shiftR` (-i))+    $ cond (i > 0) (x `shiftL` i)+    $ x++  -- | @'rotate' x i@ rotates @x@ left by @i@ bits if @i@ is positive, or right+  -- by @-i@ bits otherwise.+  rotate        :: Exp a -> Exp Int -> Exp a+  rotate x i+    = cond (i < 0) (x `rotateR` (-i))+    $ cond (i > 0) (x `rotateL` i)+    $ x++  -- | The value with all bits unset+  zeroBits      :: Exp a+  zeroBits = clearBit (bit 0) 0++  -- | @bit /i/@ is a value with the @/i/@th bit set and all other bits clear.+  bit           :: Exp Int -> Exp a++  -- | @x \`setBit\` i@ is the same as @x .|. bit i@+  setBit        :: Exp a -> Exp Int -> Exp a+  setBit x i = x .|. bit i++  -- | @x \`clearBit\` i@ is the same as @x .&. complement (bit i)@+  clearBit      :: Exp a -> Exp Int -> Exp a+  clearBit x i = x .&. complement (bit i)++  -- | @x \`complementBit\` i@ is the same as @x \`xor\` bit i@+  complementBit :: Exp a -> Exp Int -> Exp a+  complementBit x i = x `xor` bit i++  -- | Return 'True' if the @n@th bit of the argument is 1+  testBit       :: Exp a -> Exp Int -> Exp Bool++  -- | Return 'True' if the argument is a signed type.+  isSigned      :: Exp a -> Exp Bool++  -- | Shift the argument left by the specified number of bits (which must be+  -- non-negative).+  shiftL        :: Exp a -> Exp Int -> Exp a+  shiftL x i = x `shift` i++  -- | Shift the argument left by the specified number of bits. The result is+  -- undefined for negative shift amounts and shift amounts greater or equal to+  -- the 'finiteBitSize'.+  unsafeShiftL  :: Exp a -> Exp Int -> Exp a+  unsafeShiftL = shiftL++  -- | Shift the first argument right by the specified number of bits (which+  -- must be non-negative).+  --+  -- Right shifts perform sign extension on signed number types; i.e. they fill+  -- the top bits with 1 if @x@ is negative and with 0 otherwise.+  shiftR        :: Exp a -> Exp Int -> Exp a+  shiftR x i = x `shift` (-i)++  -- | Shift the first argument right by the specified number of bits. The+  -- result is undefined for negative shift amounts and shift amounts greater or+  -- equal to the 'finiteBitSize'.+  unsafeShiftR  :: Exp a -> Exp Int -> Exp a+  unsafeShiftR = shiftR++  -- | Rotate the argument left by the specified number of bits (which must be+  -- non-negative).+  rotateL       :: Exp a -> Exp Int -> Exp a+  rotateL x i = x `rotate` i++  -- | Rotate the argument right by the specified number of bits (which must be non-negative).+  rotateR       :: Exp a -> Exp Int -> Exp a+  rotateR x i = x `rotate` (-i)++  -- | Return the number of set bits in the argument. This number is known as+  -- the population count or the Hamming weight.+  popCount      :: Exp a -> Exp Int+++class Bits b => FiniteBits b where+  -- | Return the number of bits in the type of the argument.+  finiteBitSize :: Exp b -> Exp Int++  -- | Count the number of zero bits preceding the most significant set bit.+  -- This can be used to compute a base-2 logarithm via:+  --+  -- > logBase2 x = finiteBitSize x - 1 - countLeadingZeros x+  --+  countLeadingZeros :: Exp b -> Exp Int++  -- | Count the number of zero bits following the least significant set bit.+  -- The related+  -- <http://en.wikipedia.org/wiki/Find_first_set find-first-set operation> can+  -- be expressed in terms of this as:+  --+  -- > findFirstSet x = 1 + countTrailingZeros x+  --+  countTrailingZeros :: Exp b -> Exp Int+++-- Instances for Bits+-- ------------------++instance Bits Bool where+  (.&.)        = (&&)+  (.|.)        = (||)+  xor          = (/=)+  complement   = not+  shift x i    = cond (i == 0) x (constant False)+  testBit x i  = cond (i == 0) x (constant False)+  rotate x _   = x+  bit i        = i == 0+  isSigned     = isSignedDefault+  popCount     = mkBoolToInt++instance Bits Int where+  (.&.)        = mkBAnd+  (.|.)        = mkBOr+  xor          = mkBXor+  complement   = mkBNot+  bit          = bitDefault+  testBit      = testBitDefault+  shift        = shiftDefault+  shiftL       = shiftLDefault+  shiftR       = shiftRDefault+  unsafeShiftL = mkBShiftL+  unsafeShiftR = mkBShiftR+  rotate       = rotateDefault+  rotateL      = rotateLDefault+  rotateR      = rotateRDefault+  isSigned     = isSignedDefault+  popCount     = mkPopCount++instance Bits Int8 where+  (.&.)        = mkBAnd+  (.|.)        = mkBOr+  xor          = mkBXor+  complement   = mkBNot+  bit          = bitDefault+  testBit      = testBitDefault+  shift        = shiftDefault+  shiftL       = shiftLDefault+  shiftR       = shiftRDefault+  unsafeShiftL = mkBShiftL+  unsafeShiftR = mkBShiftR+  rotate       = rotateDefault+  rotateL      = rotateLDefault+  rotateR      = rotateRDefault+  isSigned     = isSignedDefault+  popCount     = mkPopCount++instance Bits Int16 where+  (.&.)        = mkBAnd+  (.|.)        = mkBOr+  xor          = mkBXor+  complement   = mkBNot+  bit          = bitDefault+  testBit      = testBitDefault+  shift        = shiftDefault+  shiftL       = shiftLDefault+  shiftR       = shiftRDefault+  unsafeShiftL = mkBShiftL+  unsafeShiftR = mkBShiftR+  rotate       = rotateDefault+  rotateL      = rotateLDefault+  rotateR      = rotateRDefault+  isSigned     = isSignedDefault+  popCount     = mkPopCount++instance Bits Int32 where+  (.&.)        = mkBAnd+  (.|.)        = mkBOr+  xor          = mkBXor+  complement   = mkBNot+  bit          = bitDefault+  testBit      = testBitDefault+  shift        = shiftDefault+  shiftL       = shiftLDefault+  shiftR       = shiftRDefault+  unsafeShiftL = mkBShiftL+  unsafeShiftR = mkBShiftR+  rotate       = rotateDefault+  rotateL      = rotateLDefault+  rotateR      = rotateRDefault+  isSigned     = isSignedDefault+  popCount     = mkPopCount++instance Bits Int64 where+  (.&.)        = mkBAnd+  (.|.)        = mkBOr+  xor          = mkBXor+  complement   = mkBNot+  bit          = bitDefault+  testBit      = testBitDefault+  shift        = shiftDefault+  shiftL       = shiftLDefault+  shiftR       = shiftRDefault+  unsafeShiftL = mkBShiftL+  unsafeShiftR = mkBShiftR+  rotate       = rotateDefault+  rotateL      = rotateLDefault+  rotateR      = rotateRDefault+  isSigned     = isSignedDefault+  popCount     = mkPopCount++instance Bits Word where+  (.&.)        = mkBAnd+  (.|.)        = mkBOr+  xor          = mkBXor+  complement   = mkBNot+  bit          = bitDefault+  testBit      = testBitDefault+  shift        = shiftDefault+  shiftL       = shiftLDefault+  shiftR       = shiftRDefault+  unsafeShiftL = mkBShiftL+  unsafeShiftR = mkBShiftR+  rotate       = rotateDefault+  rotateL      = rotateLDefault+  rotateR      = rotateRDefault+  isSigned     = isSignedDefault+  popCount     = mkPopCount++instance Bits Word8 where+  (.&.)        = mkBAnd+  (.|.)        = mkBOr+  xor          = mkBXor+  complement   = mkBNot+  bit          = bitDefault+  testBit      = testBitDefault+  shift        = shiftDefault+  shiftL       = shiftLDefault+  shiftR       = shiftRDefault+  unsafeShiftL = mkBShiftL+  unsafeShiftR = mkBShiftR+  rotate       = rotateDefault+  rotateL      = rotateLDefault+  rotateR      = rotateRDefault+  isSigned     = isSignedDefault+  popCount     = mkPopCount++instance Bits Word16 where+  (.&.)        = mkBAnd+  (.|.)        = mkBOr+  xor          = mkBXor+  complement   = mkBNot+  bit          = bitDefault+  testBit      = testBitDefault+  shift        = shiftDefault+  shiftL       = shiftLDefault+  shiftR       = shiftRDefault+  unsafeShiftL = mkBShiftL+  unsafeShiftR = mkBShiftR+  rotate       = rotateDefault+  rotateL      = rotateLDefault+  rotateR      = rotateRDefault+  isSigned     = isSignedDefault+  popCount     = mkPopCount++instance Bits Word32 where+  (.&.)        = mkBAnd+  (.|.)        = mkBOr+  xor          = mkBXor+  complement   = mkBNot+  bit          = bitDefault+  testBit      = testBitDefault+  shift        = shiftDefault+  shiftL       = shiftLDefault+  shiftR       = shiftRDefault+  unsafeShiftL = mkBShiftL+  unsafeShiftR = mkBShiftR+  rotate       = rotateDefault+  rotateL      = rotateLDefault+  rotateR      = rotateRDefault+  isSigned     = isSignedDefault+  popCount     = mkPopCount++instance Bits Word64 where+  (.&.)        = mkBAnd+  (.|.)        = mkBOr+  xor          = mkBXor+  complement   = mkBNot+  bit          = bitDefault+  testBit      = testBitDefault+  shift        = shiftDefault+  shiftL       = shiftLDefault+  shiftR       = shiftRDefault+  unsafeShiftL = mkBShiftL+  unsafeShiftR = mkBShiftR+  rotate       = rotateDefault+  rotateL      = rotateLDefault+  rotateR      = rotateRDefault+  isSigned     = isSignedDefault+  popCount     = mkPopCount++instance Bits CInt where+  (.&.)        = mkBAnd+  (.|.)        = mkBOr+  xor          = mkBXor+  complement   = mkBNot+  bit          = bitDefault+  testBit      = testBitDefault+  shift        = shiftDefault+  shiftL       = shiftLDefault+  shiftR       = shiftRDefault+  unsafeShiftL = mkBShiftL+  unsafeShiftR = mkBShiftR+  rotate       = rotateDefault+  rotateL      = rotateLDefault+  rotateR      = rotateRDefault+  isSigned     = isSignedDefault+  popCount     = mkPopCount++instance Bits CUInt where+  (.&.)        = mkBAnd+  (.|.)        = mkBOr+  xor          = mkBXor+  complement   = mkBNot+  bit          = bitDefault+  testBit      = testBitDefault+  shift        = shiftDefault+  shiftL       = shiftLDefault+  shiftR       = shiftRDefault+  unsafeShiftL = mkBShiftL+  unsafeShiftR = mkBShiftR+  rotate       = rotateDefault+  rotateL      = rotateLDefault+  rotateR      = rotateRDefault+  isSigned     = isSignedDefault+  popCount     = mkPopCount++instance Bits CLong where+  (.&.)        = mkBAnd+  (.|.)        = mkBOr+  xor          = mkBXor+  complement   = mkBNot+  bit          = bitDefault+  testBit      = testBitDefault+  shift        = shiftDefault+  shiftL       = shiftLDefault+  shiftR       = shiftRDefault+  unsafeShiftL = mkBShiftL+  unsafeShiftR = mkBShiftR+  rotate       = rotateDefault+  rotateL      = rotateLDefault+  rotateR      = rotateRDefault+  isSigned     = isSignedDefault+  popCount     = mkPopCount++instance Bits CULong where+  (.&.)        = mkBAnd+  (.|.)        = mkBOr+  xor          = mkBXor+  complement   = mkBNot+  bit          = bitDefault+  testBit      = testBitDefault+  shift        = shiftDefault+  shiftL       = shiftLDefault+  shiftR       = shiftRDefault+  unsafeShiftL = mkBShiftL+  unsafeShiftR = mkBShiftR+  rotate       = rotateDefault+  rotateL      = rotateLDefault+  rotateR      = rotateRDefault+  isSigned     = isSignedDefault+  popCount     = mkPopCount++instance Bits CLLong where+  (.&.)        = mkBAnd+  (.|.)        = mkBOr+  xor          = mkBXor+  complement   = mkBNot+  bit          = bitDefault+  testBit      = testBitDefault+  shift        = shiftDefault+  shiftL       = shiftLDefault+  shiftR       = shiftRDefault+  unsafeShiftL = mkBShiftL+  unsafeShiftR = mkBShiftR+  rotate       = rotateDefault+  rotateL      = rotateLDefault+  rotateR      = rotateRDefault+  isSigned     = isSignedDefault+  popCount     = mkPopCount++instance Bits CULLong where+  (.&.)        = mkBAnd+  (.|.)        = mkBOr+  xor          = mkBXor+  complement   = mkBNot+  bit          = bitDefault+  testBit      = testBitDefault+  shift        = shiftDefault+  shiftL       = shiftLDefault+  shiftR       = shiftRDefault+  unsafeShiftL = mkBShiftL+  unsafeShiftR = mkBShiftR+  rotate       = rotateDefault+  rotateL      = rotateLDefault+  rotateR      = rotateRDefault+  isSigned     = isSignedDefault+  popCount     = mkPopCount++instance Bits CShort where+  (.&.)        = mkBAnd+  (.|.)        = mkBOr+  xor          = mkBXor+  complement   = mkBNot+  bit          = bitDefault+  testBit      = testBitDefault+  shift        = shiftDefault+  shiftL       = shiftLDefault+  shiftR       = shiftRDefault+  unsafeShiftL = mkBShiftL+  unsafeShiftR = mkBShiftR+  rotate       = rotateDefault+  rotateL      = rotateLDefault+  rotateR      = rotateRDefault+  isSigned     = isSignedDefault+  popCount     = mkPopCount++instance Bits CUShort where+  (.&.)        = mkBAnd+  (.|.)        = mkBOr+  xor          = mkBXor+  complement   = mkBNot+  bit          = bitDefault+  testBit      = testBitDefault+  shift        = shiftDefault+  shiftL       = shiftLDefault+  shiftR       = shiftRDefault+  unsafeShiftL = mkBShiftL+  unsafeShiftR = mkBShiftR+  rotate       = rotateDefault+  rotateL      = rotateLDefault+  rotateR      = rotateRDefault+  isSigned     = isSignedDefault+  popCount     = mkPopCount++-- instance Bits CChar where+--   (.&.)        = mkBAnd+--   (.|.)        = mkBOr+--   xor          = mkBXor+--   complement   = mkBNot+--   bit          = bitDefault+--   testBit      = testBitDefault+--   shift        = shiftDefault+--   shiftL       = shiftLDefault+--   shiftR       = shiftRDefault+--   unsafeShiftL = mkBShiftL+--   unsafeShiftR = mkBShiftR+--   rotate       = rotateDefault+--   rotateL      = rotateLDefault+--   rotateR      = rotateRDefault+--   isSigned     = isSignedDefault+--   popCount     = mkPopCount++-- instance Bits CUChar where+--   (.&.)        = mkBAnd+--   (.|.)        = mkBOr+--   xor          = mkBXor+--   complement   = mkBNot+--   bit          = bitDefault+--   testBit      = testBitDefault+--   shift        = shiftDefault+--   shiftL       = shiftLDefault+--   shiftR       = shiftRDefault+--   unsafeShiftL = mkBShiftL+--   unsafeShiftR = mkBShiftR+--   rotate       = rotateDefault+--   rotateL      = rotateLDefault+--   rotateR      = rotateRDefault+--   isSigned     = isSignedDefault+--   popCount     = mkPopCount++-- instance Bits CSChar where+--   (.&.)        = mkBAnd+--   (.|.)        = mkBOr+--   xor          = mkBXor+--   complement   = mkBNot+--   bit          = bitDefault+--   testBit      = testBitDefault+--   shift        = shiftDefault+--   shiftL       = shiftLDefault+--   shiftR       = shiftRDefault+--   unsafeShiftL = mkBShiftL+--   unsafeShiftR = mkBShiftR+--   rotate       = rotateDefault+--   rotateL      = rotateLDefault+--   rotateR      = rotateRDefault+--   isSigned     = isSignedDefault+--   popCount     = mkPopCount+++-- Instances for FiniteBits+-- ------------------------++instance FiniteBits Bool where+  finiteBitSize _      = constant (B.finiteBitSize (undefined::Bool))+  countLeadingZeros  x = cond x 0 1+  countTrailingZeros x = cond x 0 1++instance FiniteBits Int where+  finiteBitSize _    = constant (B.finiteBitSize (undefined::Int))+  countLeadingZeros  = mkCountLeadingZeros+  countTrailingZeros = mkCountTrailingZeros++instance FiniteBits Int8 where+  finiteBitSize _    = constant (B.finiteBitSize (undefined::Int8))+  countLeadingZeros  = mkCountLeadingZeros+  countTrailingZeros = mkCountTrailingZeros++instance FiniteBits Int16 where+  finiteBitSize _    = constant (B.finiteBitSize (undefined::Int16))+  countLeadingZeros  = mkCountLeadingZeros+  countTrailingZeros = mkCountTrailingZeros++instance FiniteBits Int32 where+  finiteBitSize _    = constant (B.finiteBitSize (undefined::Int32))+  countLeadingZeros  = mkCountLeadingZeros+  countTrailingZeros = mkCountTrailingZeros++instance FiniteBits Int64 where+  finiteBitSize _    = constant (B.finiteBitSize (undefined::Int64))+  countLeadingZeros  = mkCountLeadingZeros+  countTrailingZeros = mkCountTrailingZeros++instance FiniteBits Word where+  finiteBitSize _    = constant (B.finiteBitSize (undefined::Word))+  countLeadingZeros  = mkCountLeadingZeros+  countTrailingZeros = mkCountTrailingZeros++instance FiniteBits Word8 where+  finiteBitSize _    = constant (B.finiteBitSize (undefined::Word8))+  countLeadingZeros  = mkCountLeadingZeros+  countTrailingZeros = mkCountTrailingZeros++instance FiniteBits Word16 where+  finiteBitSize _    = constant (B.finiteBitSize (undefined::Word16))+  countLeadingZeros  = mkCountLeadingZeros+  countTrailingZeros = mkCountTrailingZeros++instance FiniteBits Word32 where+  finiteBitSize _    = constant (B.finiteBitSize (undefined::Word32))+  countLeadingZeros  = mkCountLeadingZeros+  countTrailingZeros = mkCountTrailingZeros++instance FiniteBits Word64 where+  finiteBitSize _    = constant (B.finiteBitSize (undefined::Word64))+  countLeadingZeros  = mkCountLeadingZeros+  countTrailingZeros = mkCountTrailingZeros++instance FiniteBits CInt where+  finiteBitSize _    = constant (B.finiteBitSize (undefined::CInt))+  countLeadingZeros  = mkCountLeadingZeros+  countTrailingZeros = mkCountTrailingZeros++instance FiniteBits CUInt where+  finiteBitSize _    = constant (B.finiteBitSize (undefined::CUInt))+  countLeadingZeros  = mkCountLeadingZeros+  countTrailingZeros = mkCountTrailingZeros++instance FiniteBits CLong where+  finiteBitSize _    = constant (B.finiteBitSize (undefined::CLong))+  countLeadingZeros  = mkCountLeadingZeros+  countTrailingZeros = mkCountTrailingZeros++instance FiniteBits CULong where+  finiteBitSize _    = constant (B.finiteBitSize (undefined::CULong))+  countLeadingZeros  = mkCountLeadingZeros+  countTrailingZeros = mkCountTrailingZeros++instance FiniteBits CLLong where+  finiteBitSize _    = constant (B.finiteBitSize (undefined::CLLong))+  countLeadingZeros  = mkCountLeadingZeros+  countTrailingZeros = mkCountTrailingZeros++instance FiniteBits CULLong where+  finiteBitSize _    = constant (B.finiteBitSize (undefined::CULLong))+  countLeadingZeros  = mkCountLeadingZeros+  countTrailingZeros = mkCountTrailingZeros++instance FiniteBits CShort where+  finiteBitSize _    = constant (B.finiteBitSize (undefined::CShort))+  countLeadingZeros  = mkCountLeadingZeros+  countTrailingZeros = mkCountTrailingZeros++instance FiniteBits CUShort where+  finiteBitSize _    = constant (B.finiteBitSize (undefined::CUShort))+  countLeadingZeros  = mkCountLeadingZeros+  countTrailingZeros = mkCountTrailingZeros++-- instance FiniteBits CChar+-- instance FiniteBits CUChar+-- instance FiniteBits CSChar+++-- Default implementations+-- -----------------------++bitDefault :: (IsIntegral t, Bits t) => Exp Int -> Exp t+bitDefault x = constant 1 `shiftL` x++testBitDefault :: (IsIntegral t, Bits t) => Exp t -> Exp Int -> Exp Bool+testBitDefault x i = (x .&. bit i) /= constant 0++shiftDefault :: (FiniteBits t, IsIntegral t, B.Bits t) => Exp t -> Exp Int -> Exp t+shiftDefault x i+  = cond (i >= 0) (shiftLDefault x i)+                  (shiftRDefault x (-i))++shiftLDefault :: (FiniteBits t, IsIntegral t) => Exp t -> Exp Int -> Exp t+shiftLDefault x i+  = cond (i >= finiteBitSize x) (constant 0)+  $ mkBShiftL x i++shiftRDefault :: forall t. (B.Bits t, FiniteBits t, IsIntegral t) => Exp t -> Exp Int -> Exp t+shiftRDefault+  | B.isSigned (undefined::t) = shiftRADefault+  | otherwise                 = shiftRLDefault++-- Shift the argument right (signed)+shiftRADefault :: (FiniteBits t, IsIntegral t) => Exp t -> Exp Int -> Exp t+shiftRADefault x i+  = cond (i >= finiteBitSize x) (cond (mkLt x (constant 0)) (constant (-1)) (constant 0))+  $ mkBShiftR x i++-- Shift the argument right (unsigned)+shiftRLDefault :: (FiniteBits t, IsIntegral t) => Exp t -> Exp Int -> Exp t+shiftRLDefault x i+  = cond (i >= finiteBitSize x) (constant 0)+  $ mkBShiftR x i++rotateDefault :: forall t. (FiniteBits t, IsIntegral t) => Exp t -> Exp Int -> Exp t+rotateDefault =+  case (integralType :: IntegralType t) of+    TypeInt{}     -> rotateDefault' (undefined::Word)+    TypeInt8{}    -> rotateDefault' (undefined::Word8)+    TypeInt16{}   -> rotateDefault' (undefined::Word16)+    TypeInt32{}   -> rotateDefault' (undefined::Word32)+    TypeInt64{}   -> rotateDefault' (undefined::Word64)+    TypeWord{}    -> rotateDefault' (undefined::Word)+    TypeWord8{}   -> rotateDefault' (undefined::Word8)+    TypeWord16{}  -> rotateDefault' (undefined::Word16)+    TypeWord32{}  -> rotateDefault' (undefined::Word32)+    TypeWord64{}  -> rotateDefault' (undefined::Word64)+    TypeCShort{}  -> rotateDefault' (undefined::CUShort)+    TypeCUShort{} -> rotateDefault' (undefined::CUShort)+    TypeCInt{}    -> rotateDefault' (undefined::CUInt)+    TypeCUInt{}   -> rotateDefault' (undefined::CUInt)+    TypeCLong{}   -> rotateDefault' (undefined::CULong)+    TypeCULong{}  -> rotateDefault' (undefined::CULong)+    TypeCLLong{}  -> rotateDefault' (undefined::CULLong)+    TypeCULLong{} -> rotateDefault' (undefined::CULLong)++rotateDefault'+    :: forall i w. (Elt w, FiniteBits i, IsIntegral i, IsIntegral w, BitSizeEq i w, BitSizeEq w i)+    => w {- dummy -}+    -> Exp i+    -> Exp Int+    -> Exp i+rotateDefault' _ x i+  = cond (i' == 0) x+  $ w2i ((x' `mkBShiftL` i') `mkBOr` (x' `mkBShiftR` (wsib - i')))+  where+    w2i  = mkBitcast :: Exp w -> Exp i+    i2w  = mkBitcast :: Exp i -> Exp w+    --+    x'   = i2w x+    i'   = i `mkBAnd` (wsib - 1)+    wsib = finiteBitSize x++rotateLDefault :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t+rotateLDefault x i+  = cond (i == 0) x+  $ mkBRotateL x i++rotateRDefault :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t+rotateRDefault x i+  = cond (i == 0) x+  $ mkBRotateR x i++isSignedDefault :: forall b. B.Bits b => Exp b -> Exp Bool+isSignedDefault _ = constant (B.isSigned (undefined::b))++_popCountDefault :: forall a. (B.FiniteBits a, IsScalar a, Bits a, Num a) => Exp a -> Exp Int+_popCountDefault =+  $( [e| case B.finiteBitSize (undefined::a) of+           8  -> popCnt8  . mkUnsafeCoerce+           16 -> popCnt16 . mkUnsafeCoerce+           32 -> popCnt32 . mkUnsafeCoerce+           64 -> popCnt64 . mkUnsafeCoerce+           _  -> popCountKernighan |] )++-- http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan+popCountKernighan :: (Bits a, Num a) => Exp a -> Exp Int+popCountKernighan x = r+  where+    (r,_) = untup2+          $ while (\(untup2 -> (_,v)) -> v /= 0)+                  (\(untup2 -> (c,v)) -> tup2 (c+1, v .&. (v-1)))+                  (tup2 (0,x))++-- http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel+popCnt8 :: Exp Word8 -> Exp Int+popCnt8 v1 = mkFromIntegral c+  where+    v2 = v1 - ((v1 `unsafeShiftR` 1) .&. 0x55)+    v3 = (v2 .&. 0x33) + ((v2 `unsafeShiftR` 2) .&. 0x33)+    v4 = (v3 + (v3 `unsafeShiftR` 4)) .&. 0x0F+    c  = v4 * 0x01++popCnt16 :: Exp Word16 -> Exp Int+popCnt16 v1 = mkFromIntegral c+  where+    v2 = v1 - ((v1 `unsafeShiftR` 1) .&. 0x5555)+    v3 = (v2 .&. 0x3333) + ((v2 `unsafeShiftR` 2) .&. 0x3333)+    v4 = (v3 + (v3 `unsafeShiftR` 4)) .&. 0x0F0F+    c  = (v4 * 0x0101) `unsafeShiftR` 8++popCnt32 :: Exp Word32 -> Exp Int+popCnt32 v1 = mkFromIntegral c+  where+    v2 = v1 - ((v1 `unsafeShiftR` 1) .&. 0x55555555)+    v3 = (v2 .&. 0x33333333) + ((v2 `unsafeShiftR` 2) .&. 0x33333333)+    v4 = (v3 + (v3 `unsafeShiftR` 4)) .&. 0x0F0F0F0F+    c  = (v4 * 0x01010101) `unsafeShiftR` 24++popCnt64 :: Exp Word64 -> Exp Int+popCnt64 v1 = mkFromIntegral c+  where+    v2 = v1 - ((v1 `unsafeShiftR` 1) .&. 0x5555555555555555)+    v3 = (v2 .&. 0x3333333333333333) + ((v2 `unsafeShiftR` 2) .&. 0x3333333333333333)+    v4 = (v3 + (v3 `unsafeShiftR` 4)) .&. 0X0F0F0F0F0F0F0F0F+    c  = (v4 * 0x0101010101010101) `unsafeShiftR` 56+
Data/Array/Accelerate/Data/Complex.hs view
@@ -1,12 +1,24 @@+{-# LANGUAGE CPP                   #-}+{-# LANGUAGE ConstraintKinds       #-} {-# LANGUAGE FlexibleContexts      #-} {-# LANGUAGE FlexibleInstances     #-}-{-# LANGUAGE IncoherentInstances   #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE ScopedTypeVariables   #-} {-# LANGUAGE TypeFamilies          #-} {-# LANGUAGE TypeSynonymInstances  #-}-{-# OPTIONS -fno-warn-orphans #-}-+{-# LANGUAGE UndecidableInstances  #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- |+-- Module      : Data.Array.Accelerate.Data.Complex+-- Copyright   : [2015..2017] Trevor L. McDonell+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- Complex numbers+-- module Data.Array.Accelerate.Data.Complex (    -- * Rectangular from@@ -26,30 +38,32 @@  ) where -import Prelude-import Data.Complex                             ( Complex(..) )-import Data.Array.Accelerate                    as A-import Data.Array.Accelerate.Smart-import Data.Array.Accelerate.Tuple import Data.Array.Accelerate.Array.Sugar+import Data.Array.Accelerate.Classes                                as A+import Data.Array.Accelerate.Language+import Data.Array.Accelerate.Lift+import Data.Array.Accelerate.Product+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Type +import Prelude                                                      ( ($), undefined, fromInteger )+import Data.Complex                                                 ( Complex(..) )+import qualified Data.Complex                                       as C+import qualified Prelude                                            as P -type instance EltRepr  (Complex a) = (EltRepr a, EltRepr' a)-type instance EltRepr' (Complex a) = (EltRepr a, EltRepr' a) -instance Elt a => Elt (Complex a) where-  eltType (_::Complex a)        = eltType (undefined :: (a,a))-  toElt (a,b)                   = toElt a :+ toElt' b-  fromElt (a :+ b)              = (fromElt a, fromElt' b)+type instance EltRepr (Complex a) = EltRepr (a, a) -  eltType' (_::Complex a)       = eltType' (undefined :: (a,a))-  toElt' (a,b)                  = toElt a :+ toElt' b-  fromElt' (a :+ b)             = (fromElt a, fromElt' b)+instance Elt a => Elt (Complex a) where+  eltType _             = eltType (undefined :: (a,a))+  toElt p               = let (a, b) = toElt p in a :+ b+  fromElt (a :+ b)      = fromElt (a, b) -instance IsTuple (Complex a) where-  type TupleRepr (Complex a) = (((), a), a)-  fromTuple (x :+ y)    = (((), x), y)-  toTuple (((), x), y)  = (x :+ y)+instance cst a => IsProduct cst (Complex a) where+  type ProdRepr (Complex a) = ProdRepr (a, a)+  fromProd cst (x :+ y) = fromProd cst (x, y)+  toProd cst p          = let (x, y) = toProd cst p in (x :+ y)+  prod cst _            = prod cst (undefined :: (a, a))  instance (Lift Exp a, Elt (Plain a)) => Lift Exp (Complex a) where   type Plain (Complex a) = Complex (Plain a)@@ -62,43 +76,49 @@       in       x :+ y -instance (Elt a, IsFloating a) => Num (Exp (Complex a)) where+instance A.Eq a => A.Eq (Complex a) where+  x == y = let r1 :+ c1 = unlift x+               r2 :+ c2 = unlift y+           in  r1 == r2 && c1 == c2+  x /= y = let r1 :+ c1 = unlift x+               r2 :+ c2 = unlift y+           in  r1 /= r2 || c1 /= c2++instance A.RealFloat a => P.Num (Exp (Complex a)) where   (+)           = lift2 ((+) :: Complex (Exp a) -> Complex (Exp a) -> Complex (Exp a))   (-)           = lift2 ((-) :: Complex (Exp a) -> Complex (Exp a) -> Complex (Exp a))   (*)           = lift2 ((*) :: Complex (Exp a) -> Complex (Exp a) -> Complex (Exp a))   negate        = lift1 (negate :: Complex (Exp a) -> Complex (Exp a))   signum        = lift1 (signum :: Complex (Exp a) -> Complex (Exp a))   abs           = lift1 (abs :: Complex (Exp a) -> Complex (Exp a))-  fromInteger n = lift (constant (fromInteger n) :+ 0)-+  fromInteger n = lift ((fromInteger n :: Exp a) :+ 0) -instance (Elt a, IsFloating a) => Fractional (Exp (Complex a)) where+instance A.RealFloat a => P.Fractional (Exp (Complex a)) where   c / c'     = let x  :+ y       = unlift c           x' :+ y'      = unlift c'     :: Complex (Exp a)-          den           = x'^(2 :: Int) + y'^(2 :: Int)+          den           = x' P.^ (2 :: Int) + y' P.^ (2 :: Int)           re            = (x * x' + y * y') / den           im            = (y * x' - x * y') / den       in       lift (re :+ im)    fromRational x-    = lift (constant (fromRational x) :+ constant 0)-+    = lift ((fromRational x :: Exp a) :+ 0) -instance (Elt a, IsFloating a, RealFloat a) => Floating (Exp (Complex a)) where+instance A.RealFloat a => P.Floating (Exp (Complex a)) where   sqrt z     = let           x :+ y        = unlift z           v'            = abs y / (u'*2)           u'            = sqrt ((magnitude z + abs x) / 2)-          (u, v)        = unlift ( x A.<* 0 ? ( lift (v',u'), lift (u',v') ) )+          (u, v)        = unlift $ cond (x < 0) (lift (v',u')) (lift (u',v'))       in-      x ==* 0 &&* y ==* 0 ?-        {- then -} ( 0-        {- else -} , lift (u :+ (y A.<* 0 ? (-v,v))) )+      cond (x == 0 && y == 0)+        {- then -} 0+        {- else -} (lift (u :+ (cond (y < 0) (-v) v))) -  pi            = lift (pi :+ constant 0)+  pi            = lift (pi :: Complex (Exp a))   log z         = lift (log (magnitude z) :+ phase z)   exp           = lift1 (exp :: Complex (Exp a) -> Complex (Exp a))   sin           = lift1 (sin :: Complex (Exp a) -> Complex (Exp a))@@ -114,10 +134,13 @@   acosh         = lift1 (acosh :: Complex (Exp a) -> Complex (Exp a))   atanh         = lift1 (atanh :: Complex (Exp a) -> Complex (Exp a)) +instance (A.FromIntegral a b, A.Num b) => A.FromIntegral a (Complex b) where+  fromIntegral x = lift (fromIntegral x :+ (0 :: Exp b)) + -- | The non-negative magnitude of a complex number ---magnitude :: (Elt a, IsFloating a) => Exp (Complex a) -> Exp a+magnitude :: RealFloat a => Exp (Complex a) -> Exp a magnitude c =   let r :+ i    = unlift c   in sqrt (r*r + i*i)@@ -125,7 +148,7 @@ -- | The phase of a complex number, in the range @(-'pi', 'pi']@. If the -- magnitude is zero, then so is the phase. ---phase :: (Elt a, IsFloating a) => Exp (Complex a) -> Exp a+phase :: RealFloat a => Exp (Complex a) -> Exp a phase c =   let x :+ y    = unlift c   in atan2 y x@@ -134,19 +157,27 @@ -- 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 :: (Elt a, IsFloating a) => Exp (Complex a) -> Exp (a,a)+polar :: RealFloat a => Exp (Complex a) -> Exp (a,a) polar z =  lift (magnitude z, phase z)  -- | Form a complex number from polar components of magnitude and phase. ---mkPolar :: (Elt a, IsFloating a) => Exp a -> Exp a -> Exp (Complex a)-mkPolar r theta  =  lift $ r * cos theta :+ r * sin theta+#if __GLASGOW_HASKELL__ <= 708+mkPolar :: forall a. RealFloat a => Exp a -> Exp a -> Exp (Complex a)+#else+mkPolar :: forall a. Floating a  => Exp a -> Exp a -> Exp (Complex a)+#endif+mkPolar = lift2 (C.mkPolar :: Exp a -> Exp a -> Complex (Exp a))  -- | @'cis' t@ is a complex value with magnitude @1@ and phase @t@ (modulo -- @2*'pi'@). ---cis :: (Elt a, IsFloating a) => Exp a -> Exp (Complex a)-cis theta = lift $ cos theta :+ sin theta+#if __GLASGOW_HASKELL__ <= 708+cis :: forall a. RealFloat a => Exp a -> Exp (Complex a)+#else+cis :: forall a. Floating a  => Exp a -> Exp (Complex a)+#endif+cis = lift1 (C.cis :: Exp a -> Complex (Exp a))  -- | Return the real part of a complex number --@@ -166,6 +197,6 @@ -- -- > conjugate(Z) = X - iY ---conjugate :: (Elt a, IsNum a) => Exp (Complex a) -> Exp (Complex a)+conjugate :: Num a => Exp (Complex a) -> Exp (Complex a) conjugate z = lift $ real z :+ (- imag z) 
+ Data/Array/Accelerate/Data/Fold.hs view
@@ -0,0 +1,155 @@+{-# LANGUAGE ConstraintKinds   #-}+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GADTs             #-}+{-# LANGUAGE TypeOperators     #-}+-- |+-- Module      : Data.Array.Accelerate.Data.Fold+-- Copyright   : [2016..2017] Trevor L. McDonell+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- Combine folds in 'Applicative' style to generate multiple results with+-- a single pass over the array. Based on Max Rabkin's "Beautiful Folding" [1]+-- and talks by Gabriel Gonzalez [2].+--+--  1. <http://squing.blogspot.com/2008/11/beautiful-folding.html>+--  2. <https://www.youtube.com/watch?v=6a5Ti0r8Q2s>+--++module Data.Array.Accelerate.Data.Fold (++  Fold(..), runFold,++) where++import Data.Array.Accelerate                                        hiding ( fold, sum, product, length )+import Data.Array.Accelerate.Data.Monoid+import qualified Data.Array.Accelerate                              as A++import Control.Applicative                                          as P+import Prelude                                                      hiding ( sum, product, length )+import qualified Prelude                                            as P+++-- | 'Fold' describes how to process data of some 'i'nput type into some+-- 'o'utput type, via a reduction using some intermediate Monoid 'w'. For+-- example, both 'sum' and 'length' below use the 'Sum' monoid:+--+-- >>> let sum = Fold (lift . Sum) (getSum . unlift)+-- >>> let length = Fold (\_ -> 1) (getSum . unlift)+--+-- The key is that 'Fold's 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 where+  Fold :: (Elt w, Monoid (Exp w))+       => (i -> Exp w)              -- transform input element into internal monoid type+       -> (Exp w -> o)              -- summarise the reduction to retrieve the final result+       -> 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)+runFold (Fold tally summarise) is+  = A.map summarise+  $ A.fold (<>) mempty+  $ A.map tally is+++-- sum :: A.Num e => Fold (Exp e) (Exp e)+-- sum = Fold (lift . Sum) (getSum . unlift)++-- product :: A.Num e => Fold (Exp e) (Exp e)+-- product = Fold (lift . Product) (getProduct . unlift)++-- length :: A.Num i => Fold (Exp e) (Exp i)+-- length = Fold (\_ -> 1) (getSum . unlift)+++-- combine2 :: (Elt a, Elt b) => Exp a -> Exp b -> Exp (a,b)+-- combine2 a b = lift (a,b)++-- combine3 :: (Elt a, Elt b, Elt c) => Exp a -> Exp b -> Exp c -> Exp (a,b,c)+-- combine3 a b c = lift (a,b,c)++-- combine4 :: (Elt a, Elt b, Elt c, Elt d) => Exp a -> Exp b -> Exp c -> Exp d -> Exp (a,b,c,d)+-- combine4 a b c d = lift (a,b,c,d)++-- combine5 :: (Elt a, Elt b, Elt c, Elt d, Elt e) => Exp a -> Exp b -> Exp c -> Exp d -> Exp e -> Exp (a,b,c,d,e)+-- combine5 a b c d e = lift (a,b,c,d,e)+++-- Instances for 'Fold'+-- --------------------++instance P.Functor (Fold i) where+  fmap k (Fold tally summarise) = Fold tally (k . summarise)++instance P.Applicative (Fold i) where+  pure o                    = Fold (\_ -> constant ()) (\_ -> o)+  Fold tF sF <*> Fold tX sX = Fold tally summarise+    where+      tally i     = lift (tF i, tX i)+      summarise t = let (mF, mX) = unlift t+                    in sF mF (sX mX)++instance A.Num b => P.Num (Fold a (Exp b)) where+  (+)           = liftA2 (+)+  (-)           = liftA2 (-)+  (*)           = liftA2 (*)+  negate        = fmap negate+  abs           = fmap abs+  signum        = fmap signum+  fromInteger n = pure (fromInteger n)++instance A.Fractional b => P.Fractional (Fold a (Exp b)) where+  (/)            = liftA2 (/)+  recip          = fmap recip+  fromRational n = pure (fromRational n)++instance A.Floating b => P.Floating (Fold a (Exp b)) where+  pi      = pure pi+  sin     = fmap sin+  cos     = fmap cos+  tan     = fmap tan+  asin    = fmap asin+  acos    = fmap acos+  atan    = fmap atan+  sinh    = fmap sinh+  cosh    = fmap cosh+  tanh    = fmap tanh+  asinh   = fmap asinh+  acosh   = fmap acosh+  atanh   = fmap atanh+  exp     = fmap exp+  sqrt    = fmap sqrt+  log     = fmap log+  (**)    = liftA2 (**)+  logBase = liftA2 logBase+
+ Data/Array/Accelerate/Data/Monoid.hs view
@@ -0,0 +1,172 @@+{-# LANGUAGE ConstraintKinds       #-}+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables   #-}+{-# LANGUAGE TypeFamilies          #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}+-- |+-- Module      : Data.Array.Accelerate.Data.Monoid+-- Copyright   : [2016..2017] Trevor L. McDonell+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- Monoid instances for Accelerate+--++module Data.Array.Accelerate.Data.Monoid (++  Monoid(..), (<>),++  Sum(..),+  Product(..),++) where++import Data.Array.Accelerate                                        as A+import Data.Array.Accelerate.Type                                   as A+import Data.Array.Accelerate.Smart                                  as A ( Exp(..), PreExp(..) )+import Data.Array.Accelerate.Product                                as A+import Data.Array.Accelerate.Array.Sugar                            as A++import Data.Function+import Data.Monoid                                                  hiding ( mconcat )+import qualified Prelude                                            as P+++-- Sum: Monoid under addition+-- --------------------------++type instance EltRepr (Sum a) = ((), EltRepr a)++instance Elt a => Elt (Sum a) where+  eltType _       = PairTuple UnitTuple (eltType (undefined::a))+  toElt ((),x)    = Sum (toElt x)+  fromElt (Sum x) = ((), fromElt x)++instance Elt a => IsProduct Elt (Sum a) where+  type ProdRepr (Sum a) = ((), a)+  toProd _ ((),a)    = Sum a+  fromProd _ (Sum a) = ((),a)+  prod _ _           = ProdRsnoc ProdRunit++instance (Lift Exp a, Elt (Plain a)) => Lift Exp (Sum a) where+  type Plain (Sum a) = Sum (Plain a)+  lift (Sum a)       = Exp $ Tuple $ NilTup `SnocTup` lift a++instance Elt a => Unlift Exp (Sum (Exp a)) where+  unlift t = Sum . Exp $ ZeroTupIdx `Prj` t++instance A.Num a => Monoid (Exp (Sum a)) where+  mempty  = 0+  mappend = lift2 (mappend :: Sum (Exp a) -> Sum (Exp a) -> Sum (Exp a))++instance A.Num a => P.Num (Exp (Sum a)) where+  (+)             = lift2 ((+) :: Sum (Exp a) -> Sum (Exp a) -> Sum (Exp a))+  (-)             = lift2 ((-) :: Sum (Exp a) -> Sum (Exp a) -> Sum (Exp a))+  (*)             = lift2 ((*) :: Sum (Exp a) -> Sum (Exp a) -> Sum (Exp a))+  negate          = lift1 (negate :: Sum (Exp a) -> Sum (Exp a))+  signum          = lift1 (signum :: Sum (Exp a) -> Sum (Exp a))+  abs             = lift1 (signum :: Sum (Exp a) -> Sum (Exp a))+  fromInteger x   = lift (P.fromInteger x :: Sum (Exp a))++instance A.Eq a => A.Eq (Sum a) where+  (==) = lift2 ((==) `on` getSum)+  (/=) = lift2 ((/=) `on` getSum)++instance A.Ord a => A.Ord (Sum a) where+  (<)     = lift2 ((<) `on` getSum)+  (>)     = lift2 ((>) `on` getSum)+  (<=)    = lift2 ((<=) `on` getSum)+  (>=)    = lift2 ((>=) `on` getSum)+  min x y = lift . Sum $ lift2 (min `on` getSum) x y+  max x y = lift . Sum $ lift2 (max `on` getSum) x y+++-- Product: Monoid under multiplication+-- ------------------------------------++type instance EltRepr (Product a) = ((), EltRepr a)++instance Elt a => Elt (Product a) where+  eltType _       = PairTuple UnitTuple (eltType (undefined::a))+  toElt ((),x)    = Product (toElt x)+  fromElt (Product x) = ((), fromElt x)++instance Elt a => IsProduct Elt (Product a) where+  type ProdRepr (Product a) = ((), a)+  toProd _ ((),a)        = Product a+  fromProd _ (Product a) = ((),a)+  prod _ _               = ProdRsnoc ProdRunit++instance (Lift Exp a, Elt (Plain a)) => Lift Exp (Product a) where+  type Plain (Product a) = Product (Plain a)+  lift (Product a)       = Exp $ Tuple $ NilTup `SnocTup` lift a++instance Elt a => Unlift Exp (Product (Exp a)) where+  unlift t = Product . Exp $ ZeroTupIdx `Prj` t++instance A.Num a => Monoid (Exp (Product a)) where+  mempty  = 1+  mappend = lift2 (mappend :: Product (Exp a) -> Product (Exp a) -> Product (Exp a))++instance A.Num a => P.Num (Exp (Product a)) where+  (+)             = lift2 ((+) :: Product (Exp a) -> Product (Exp a) -> Product (Exp a))+  (-)             = lift2 ((-) :: Product (Exp a) -> Product (Exp a) -> Product (Exp a))+  (*)             = lift2 ((*) :: Product (Exp a) -> Product (Exp a) -> Product (Exp a))+  negate          = lift1 (negate :: Product (Exp a) -> Product (Exp a))+  signum          = lift1 (signum :: Product (Exp a) -> Product (Exp a))+  abs             = lift1 (signum :: Product (Exp a) -> Product (Exp a))+  fromInteger x   = lift (P.fromInteger x :: Product (Exp a))++instance A.Eq a => A.Eq (Product a) where+  (==) = lift2 ((==) `on` getProduct)+  (/=) = lift2 ((/=) `on` getProduct)++instance A.Ord a => A.Ord (Product a) where+  (<)     = lift2 ((<) `on` getProduct)+  (>)     = lift2 ((>) `on` getProduct)+  (<=)    = lift2 ((<=) `on` getProduct)+  (>=)    = lift2 ((>=) `on` getProduct)+  min x y = lift . Product $ lift2 (min `on` getProduct) x y+  max x y = lift . Product $ lift2 (max `on` getProduct) x y+++-- Instances for unit and tuples+-- -----------------------------++instance Monoid (Exp ()) where+  mempty      = constant ()+  mappend _ _ = constant ()++instance (Elt a, Elt b, Monoid (Exp a), Monoid (Exp b)) => Monoid (Exp (a,b)) where+  mempty      = lift (mempty :: Exp a, mempty :: Exp b)+  mappend x y = let (a1,b1) = unlift x  :: (Exp a, Exp b)+                    (a2,b2) = unlift y+                in+                lift (a1<>a2, b1<>b2)++instance (Elt a, Elt b, Elt c, Monoid (Exp a), Monoid (Exp b), Monoid (Exp c)) => Monoid (Exp (a,b,c)) where+  mempty      = lift (mempty :: Exp a, mempty :: Exp b, mempty :: Exp c)+  mappend x y = let (a1,b1,c1) = unlift x  :: (Exp a, Exp b, Exp c)+                    (a2,b2,c2) = unlift y+                in+                lift (a1<>a2, b1<>b2, c1<>c2)++instance (Elt a, Elt b, Elt c, Elt d, Monoid (Exp a), Monoid (Exp b), Monoid (Exp c), Monoid (Exp d)) => Monoid (Exp (a,b,c,d)) where+  mempty      = lift (mempty :: Exp a, mempty :: Exp b, mempty :: Exp c, mempty :: Exp d)+  mappend x y = let (a1,b1,c1,d1) = unlift x  :: (Exp a, Exp b, Exp c, Exp d)+                    (a2,b2,c2,d2) = unlift y+                in+                lift (a1<>a2, b1<>b2, c1<>c2, d1<>d2)++instance (Elt a, Elt b, Elt c, Elt d, Elt e, Monoid (Exp a), Monoid (Exp b), Monoid (Exp c), Monoid (Exp d), Monoid (Exp e)) => Monoid (Exp (a,b,c,d,e)) where+  mempty      = lift (mempty :: Exp a, mempty :: Exp b, mempty :: Exp c, mempty :: Exp d, mempty :: Exp e)+  mappend x y = let (a1,b1,c1,d1,e1) = unlift x  :: (Exp a, Exp b, Exp c, Exp d, Exp e)+                    (a2,b2,c2,d2,e2) = unlift y+                in+                lift (a1<>a2, b1<>b2, c1<>c2, d1<>d2, e1<>e2)+
Data/Array/Accelerate/Debug.hs view
@@ -1,353 +1,120 @@-{-# LANGUAGE CPP             #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TypeOperators   #-}-{-# OPTIONS -fno-warn-unused-imports #-}-{-# OPTIONS -fno-warn-unused-binds   #-}+{-# LANGUAGE CPP #-} {-# OPTIONS_HADDOCK hide #-} -- | -- Module      : Data.Array.Accelerate.Debug--- Copyright   : [2008..2014] Manuel M T Chakravarty, Gabriele Keller---               [2009..2014] Trevor L. McDonell+-- Copyright   : [2008..2017] Manuel M T Chakravarty, Gabriele Keller+--               [2009..2017] Trevor L. McDonell -- License     : BSD3 ----- Maintainer  : Manuel M T Chakravarty <chak@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au> -- Stability   : experimental -- Portability : non-portable (GHC extensions) -- -- Embedded array processing language: debugging support (internal). This module--- provides functionality that is useful for developers of the library.  It is+-- provides functionality that is useful for developers of the library. It is -- not meant for library users. --  module Data.Array.Accelerate.Debug ( -  -- * Dynamic debugging flags-  dump_sharing, dump_simpl_stats, dump_simpl_iterations, verbose,-  queryFlag, setFlag,+  module Debug, -  -- * Tracing-  traceMessage, traceEvent, tracePure,+  dumpGraph,+  dumpSimplStats, -  -- * Statistics-  inline, ruleFired, knownBranch, betaReduce, substitution, simplifierDone, fusionDone,-  resetSimplCount, simplCount,+  monitoringIsEnabled,+  debuggingIsEnabled,  ) where --- standard libraries-import Data.Function                            ( on )-import Data.IORef-import Data.Label-import Data.List                                ( groupBy, sortBy, isPrefixOf )-import Data.Ord                                 ( comparing )-import Numeric-import Text.PrettyPrint-import System.CPUTime-import System.Environment-import System.IO.Unsafe                         ( unsafePerformIO )-import qualified Data.Map                       as Map--import Debug.Trace                              ( traceIO, traceEventIO )----- -------------------------------------------------------------------------------- Flag option parsing--data FlagSpec flag = Option String              -- external form-                            flag                -- internal form--data Flags = Flags-  {-    -- debugging-    _dump_sharing               :: !Bool                -- sharing recovery phase-  , _dump_simpl_stats           :: !Bool                -- statistics form fusion/simplification-  , _dump_simpl_iterations      :: !Bool                -- output from each simplifier iteration-  , _verbose                    :: !Bool                -- additional, uncategorised status messages--    -- functionality / phase control-  , _acc_sharing                :: !(Maybe Bool)        -- recover sharing of array computations-  , _exp_sharing                :: !(Maybe Bool)        -- recover sharing of scalar expressions-  , _fusion                     :: !(Maybe Bool)        -- fuse array expressions-  , _simplify                   :: !(Maybe Bool)        -- simplify scalar expressions-  }--$(mkLabels [''Flags])--allFlags :: [FlagSpec (Flags -> Flags)]-allFlags-  =  map (enable  'd') dflags-  ++ map (enable  'f') fflags ++ map (disable 'f') fflags-  where-    enable  p (Option f go) = Option ('-':p:f)        (go True)-    disable p (Option f go) = Option ('-':p:"no-"++f) (go False)----- These @-d\<blah\>@ flags can be reversed with @-dno-\<blah\>@----dflags :: [FlagSpec (Bool -> Flags -> Flags)]-dflags =-  [-    Option "dump-sharing"               (set dump_sharing)              -- print sharing recovery trace-  , Option "dump-simpl-stats"           (set dump_simpl_stats)          -- dump simplifier stats-  , Option "dump-simpl-iterations"      (set dump_simpl_iterations)     -- dump output from each simplifier iteration-  , Option "verbose"                    (set verbose)                   -- print additional information-  ]---- These @-f\<blah\>@ flags can be reversed with @-fno-\<blah\>@----fflags :: [FlagSpec (Bool -> Flags -> Flags)]-fflags =-  [ Option "acc-sharing"                (set' acc_sharing)              -- sharing of array computations-  , Option "exp-sharing"                (set' exp_sharing)              -- sharing of scalar expressions-  , Option "fusion"                     (set' fusion)                   -- fusion of array computations-  , Option "simplify"                   (set' simplify)                 -- scalar expression simplification---  , Option "unfolding-use-threshold"                                  -- the magic cut-off figure for inlining-  ]-  where-    set' f v = set f (Just v)---initialise :: IO Flags-initialise = parse `fmap` getArgs-  where-    defaults            = Flags False False False False Nothing Nothing Nothing Nothing-    parse               = foldl parse1 defaults-    parse1 opts this    =-      case filter (\(Option flag _) -> this `isPrefixOf` flag) allFlags of-        [Option _ go]   -> go opts-        _               -> opts         -- not specified, or ambiguous----- Indicates which tracing messages are to be emitted, and which phases are to--- be run.----{-# NOINLINE options #-}-options :: IORef Flags-options = unsafePerformIO $ newIORef =<< initialise+import Data.Array.Accelerate.Debug.Flags                as Debug+import Data.Array.Accelerate.Debug.Monitoring           as Debug+import Data.Array.Accelerate.Debug.Stats                as Debug+import Data.Array.Accelerate.Debug.Timed                as Debug+import Data.Array.Accelerate.Debug.Trace                as Debug --- Query the status of a flag----queryFlag :: (Flags :-> a) -> IO a-queryFlag f = get f `fmap` readIORef options+import Data.Array.Accelerate.Pretty.Graphviz --- Set the status of a debug flag----setFlag :: (Flags :-> a) -> a -> IO ()-setFlag f v = modifyIORef' options (set f v)+import Control.Monad.Trans                              ( MonadIO ) +#if ACCELERATE_DEBUG+import Control.Exception                                ( bracket )+import Control.Monad.Trans                              ( liftIO )+import System.Directory                                 ( getTemporaryDirectory, createDirectoryIfMissing )+import System.FilePath                                  ( (</>) )+import System.IO                                        ( Handle, openTempFile, hPutStrLn, hPrint, hClose, stderr ) --- Execute an action only if the corresponding flag is set----when :: (Flags :-> Bool) -> IO () -> IO ()-#ifdef ACCELERATE_DEBUG-when f action = do-  enabled <- queryFlag f-  if enabled then action-             else return ()+#if   defined(UNIX)+import System.Posix.Process                             ( getProcessID )+#elif defined(WIN32)+import System.Win32.Process                             ( ProcessId ) #else-when _ _        = return ()+#error "I don't know what operating system I am" #endif+#endif  --- -------------------------------------------------------------------------------- Trace messages---- Emit a trace message if the corresponding debug flag is set.----traceMessage :: (Flags :-> Bool) -> String -> IO ()-#ifdef ACCELERATE_DEBUG-traceMessage f str-  = when f-  $ do psec     <- getCPUTime-       let sec   = fromIntegral psec * 1E-12 :: Double-       traceIO   $ showFFloat (Just 2) sec (':':str)+debuggingIsEnabled :: Bool+#if ACCELERATE_DEBUG+debuggingIsEnabled = True #else-traceMessage _ _ = return ()+debuggingIsEnabled = False #endif --- Emit a message to the event log if the corresponding debug flag is set----traceEvent :: (Flags :-> Bool) -> String -> IO ()-#ifdef ACCELERATE_DEBUG-traceEvent f str = when f (traceEventIO str)+monitoringIsEnabled :: Bool+#if ACCELERATE_MONITORING+monitoringIsEnabled = True #else-traceEvent _ _   = return ()+monitoringIsEnabled = False #endif --- Emit a trace message from a pure computation++-- | Display simplifier statistics. The counts are reset afterwards. ---tracePure :: (Flags :-> Bool) -> String -> a -> a-#ifdef ACCELERATE_DEBUG-tracePure f msg next = unsafePerformIO (traceMessage f msg) `seq` next+{-# INLINEABLE dumpSimplStats #-}+dumpSimplStats :: MonadIO m => m ()+#if ACCELERATE_DEBUG+dumpSimplStats = do+  liftIO $ Debug.when dump_simpl_stats $ do+    stats <- simplCount+    putTraceMsg (show stats)+    resetSimplCount #else-tracePure _ _   next = next+dumpSimplStats = return () #endif  --- -------------------------------------------------------------------------------- Recording statistics--ruleFired, inline, knownBranch, betaReduce, substitution :: String -> a -> a-inline          = annotate Inline-ruleFired       = annotate RuleFired-knownBranch     = annotate KnownBranch-betaReduce      = annotate BetaReduce-substitution    = annotate Substitution--simplifierDone, fusionDone :: a -> a-simplifierDone  = tick SimplifierDone-fusionDone      = tick FusionDone----- Add an entry to the statistics counters+-- | Write a representation of the given input (a closed array expression or+-- function) to file in Graphviz dot format in the temporary directory. ---tick :: Tick -> a -> a-#ifdef ACCELERATE_DEBUG-tick t next = unsafePerformIO (modifyIORef' statistics (simplTick t)) `seq` next+{-# INLINEABLE dumpGraph #-}+dumpGraph :: (MonadIO m, PrettyGraph g) => g -> m ()+#if ACCELERATE_DEBUG+dumpGraph g =+  liftIO $ do+    Debug.when dump_dot       $ writeGraph Full   g+    Debug.when dump_simpl_dot $ writeGraph Simple g #else-tick _ next = next+dumpGraph _ = return () #endif --- Add an entry to the statistics counters with an annotation----annotate :: (Id -> Tick) -> String -> a -> a-annotate name ctx = tick (name (Id ctx))----- Simplifier counts--- -------------------data SimplStats-  = Simple         {-# UNPACK #-} !Int          -- when we don't want detailed stats--  | Detail {-      ticks     :: {-# UNPACK #-} !Int,         -- total ticks-      details   :: !TickCount                   -- how many of each type-    }--instance Show SimplStats where-  show = render . pprSimplCount----- Stores the current statistics counters----{-# NOINLINE statistics #-}-statistics :: IORef SimplStats-statistics = unsafePerformIO $ newIORef =<< initSimplCount+#if ACCELERATE_DEBUG+writeGraph :: PrettyGraph g => Detail -> g -> IO ()+writeGraph simple g = do+  withTemporaryFile "acc.dot" $ \path hdl -> do+    hPrint hdl (ppGraph simple g)+    hPutStrLn stderr ("program graph: " ++ path) +withTemporaryFile :: String -> (FilePath -> Handle -> IO a) -> IO a+withTemporaryFile template go = do+  pid <- getProcessID+  tmp <- getTemporaryDirectory+  let dir = tmp </> "accelerate-" ++ show pid+  createDirectoryIfMissing True dir+  bracket (openTempFile dir template) (hClose . snd) (uncurry go) --- Initialise the statistics counters. If we are dumping the stats--- (-ddump-simpl-stats) record extra information, else just a total tick count.----initSimplCount :: IO SimplStats-#ifdef ACCELERATE_DEBUG-initSimplCount = do-  d <- queryFlag dump_simpl_stats-  return $! if d then Detail { ticks = 0, details = Map.empty }-                 else Simple 0-#else-initSimplCount = return $! Simple 0+#ifdef WIN32+getProcessID :: IO ProcessId+getProcessID = return 0xaaaa #endif---- Reset the statistics counters. Do this at the beginning at each HOAS -> de--- Bruijn conversion + optimisation pass.----resetSimplCount :: IO ()-#ifdef ACCELERATE_DEBUG-resetSimplCount = writeIORef statistics =<< initSimplCount-#else-resetSimplCount = return () #endif---- Tick a counter----simplTick :: Tick -> SimplStats -> SimplStats-simplTick _ (Simple n)     = Simple (n+1)-simplTick t (Detail n dts) = Detail (n+1) (dts `addTick` t)---- Pretty print the tick counts. Remarkably reminiscent of GHC style...----pprSimplCount :: SimplStats -> Doc-pprSimplCount (Simple n)     = text "Total ticks:" <+> int n-pprSimplCount (Detail n dts)-  = vcat [ text "Total ticks:" <+> int n-         , text ""-         , pprTickCount dts-         ]--simplCount :: IO Doc-simplCount = pprSimplCount `fmap` readIORef statistics----- Ticks--- -------type TickCount = Map.Map Tick Int--data Id = Id String-  deriving (Eq, Ord)--data Tick-  = Inline              Id-  | RuleFired           Id-  | KnownBranch         Id-  | BetaReduce          Id-  | Substitution        Id--  -- tick at each iteration-  | SimplifierDone-  | FusionDone-  deriving (Eq, Ord)---addTick :: TickCount -> Tick -> TickCount-addTick tc t =-  let x = 1 + Map.findWithDefault 0 t tc-  in  x `seq` Map.insert t x tc--pprTickCount :: TickCount -> Doc-pprTickCount counts =-  vcat (map pprTickGroup groups)-  where-    groups  = groupBy sameTag (Map.toList counts)-    sameTag = (==) `on` tickToTag . fst--pprTickGroup :: [(Tick,Int)] -> Doc-pprTickGroup []    = error "pprTickGroup"-pprTickGroup group =-  hang (int groupTotal <+> text groupName)-     2 (vcat [ int n <+> pprTickCtx t | (t,n) <- sortBy (flip (comparing snd)) group ])-  where-    groupName  = tickToStr (fst (head group))-    groupTotal = sum [n | (_,n) <- group]--tickToTag :: Tick -> Int-tickToTag Inline{}              = 0-tickToTag RuleFired{}           = 1-tickToTag KnownBranch{}         = 2-tickToTag BetaReduce{}          = 3-tickToTag Substitution{}        = 4-tickToTag SimplifierDone        = 99-tickToTag FusionDone            = 100--tickToStr :: Tick -> String-tickToStr Inline{}              = "Inline"-tickToStr RuleFired{}           = "RuleFired"-tickToStr KnownBranch{}         = "KnownBranch"-tickToStr BetaReduce{}          = "BetaReduce"-tickToStr Substitution{}        = "Substitution"-tickToStr SimplifierDone        = "SimplifierDone"-tickToStr FusionDone            = "FusionDone"--pprTickCtx :: Tick -> Doc-pprTickCtx (Inline v)           = pprId v-pprTickCtx (RuleFired v)        = pprId v-pprTickCtx (KnownBranch v)      = pprId v-pprTickCtx (BetaReduce v)       = pprId v-pprTickCtx (Substitution v)     = pprId v-pprTickCtx SimplifierDone       = empty-pprTickCtx FusionDone           = empty--pprId :: Id -> Doc-pprId (Id s) = text s-
+ Data/Array/Accelerate/Debug/Flags.hs view
@@ -0,0 +1,305 @@+{-# LANGUAGE CPP                      #-}+{-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE TemplateHaskell          #-}+{-# LANGUAGE TypeOperators            #-}+#ifdef ACCELERATE_DEBUG+#if __GLASGOW_HASKELL >= 800+{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}+#endif+#else+{-# OPTIONS_GHC -fno-warn-unused-binds   #-}+{-# OPTIONS_GHC -fno-warn-unused-do-bind #-}+{-# OPTIONS_GHC -fno-warn-unused-imports #-}+#endif+-- |+-- Module      : Data.Array.Accelerate.Debug.Flags+-- Copyright   : [2008..2017] Manuel M T Chakravarty, Gabriele Keller+--               [2009..2017] Trevor L. McDonell+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- Option parsing for debug flags+--++module Data.Array.Accelerate.Debug.Flags (++  Flags, Mode,+  acc_sharing, exp_sharing, fusion, simplify, flush_cache, fast_math, verbose,+  dump_phases, dump_sharing, dump_simpl_stats, dump_simpl_iterations, dump_vectorisation,+  dump_dot, dump_simpl_dot, dump_gc, dump_gc_stats, debug_cc, dump_cc, dump_ld, dump_asm,+  dump_exec, dump_sched,++  accInit,+  queryFlag, setFlag, setFlags, clearFlag, clearFlags,+  when, unless,++) where++import Control.Monad.IO.Class+import Data.IORef+import Data.Label+import Data.List+import System.Environment+import System.IO.Unsafe+import Text.PrettyPrint                         hiding ( Mode )+import qualified Control.Monad                  as M ( when, unless )++import Foreign.C+import Foreign.Marshal+import Foreign.Ptr+import GHC.Foreign                              as GHC+import GHC.IO.Encoding                          ( getFileSystemEncoding )++import Debug.Trace+++data FlagSpec flag = Option String              -- external form+                            flag                -- internal form++-- The runtime debug and control options supported by Accelerate. This is a bit+-- awkward, as we process both frontend as well as backend option flags, but+-- gives some control over error messages and overlapping options.+--+fclabels [d|+  data Flags = Flags+    {+      -- Functionality and phase control+      -- -------------------------------+      --+      -- These are Maybe types because they will only override the backend+      -- options if the user specifies a value+      --+      acc_sharing               :: !(Maybe Bool)        -- recover sharing of array computations+    , exp_sharing               :: !(Maybe Bool)        -- recover sharing of scalar expressions+    , fusion                    :: !(Maybe Bool)        -- fuse array expressions+    , simplify                  :: !(Maybe Bool)        -- simplify scalar expressions+--    , unfolding_use_threshold   :: !(Maybe Int)         -- the magic cut-off figure for inlining+    , flush_cache               :: !(Maybe Bool)        -- delete persistent compilation cache(s)+    , fast_math                 :: !(Maybe Bool)        -- use faster, less precise math library operations++      -- Debug trace+      -- -----------+    , verbose                   :: !Bool                -- be very chatty++      -- optimisation and simplification+    , dump_phases               :: !Bool                -- print information about each phase of the compiler+    , dump_sharing              :: !Bool                -- sharing recovery phase+    , dump_simpl_stats          :: !Bool                -- statistics form fusion/simplification+    , dump_simpl_iterations     :: !Bool                -- output from each simplifier iteration+    , dump_vectorisation        :: !Bool                -- output from the vectoriser+    , dump_dot                  :: !Bool                -- generate dot output of the program+    , dump_simpl_dot            :: !Bool                -- generate simplified dot output++      -- garbage collection+    , dump_gc                   :: !Bool                -- trace garbage collector+    , dump_gc_stats             :: !Bool                -- print final GC statistics++      -- code generation / compilation+    , debug_cc                  :: !Bool                -- compile with debug symbols+    , dump_cc                   :: !Bool                -- trace code generation & compilation+    , dump_ld                   :: !Bool                -- trace runtime linker+    , dump_asm                  :: !Bool                -- trace assembler++      -- execution+    , dump_exec                 :: !Bool                -- trace execution+    , dump_sched                :: !Bool                -- trace scheduler+    }+ |]+++allFlags :: [FlagSpec (Flags -> Flags)]+allFlags+  =  map (enable  'd') dflags+  ++ map (enable  'f') fflags ++ map (disable 'f') fflags+  where+    enable  p (Option f go) = Option ('-':p:f)        (go True)+    disable p (Option f go) = Option ('-':p:"no-"++f) (go False)+++-- These @-f\<blah\>@ phase control flags can be reversed with @-fno-\<blah\>@+--+fflags :: [FlagSpec (Bool -> Flags -> Flags)]+fflags =+  [ Option "acc-sharing"                (set' acc_sharing)+  , Option "exp-sharing"                (set' exp_sharing)+  , Option "fusion"                     (set' fusion)+  , Option "simplify"                   (set' simplify)+  , Option "flush-cache"                (set' flush_cache)+  , Option "fast-math"                  (set' fast_math)+  ]+  where+    set' f v = set f (Just v)++-- These debugging flags default to off and can be enable with @-d\<blah\>@+--+dflags :: [FlagSpec (Bool -> Flags -> Flags)]+dflags =+  [ Option "verbose"                    (set verbose)+  , Option "dump-phases"                (set dump_phases)+  , Option "dump-sharing"               (set dump_sharing)+  , Option "dump-simpl-stats"           (set dump_simpl_stats)+  , Option "dump-simpl-iterations"      (set dump_simpl_iterations)+  , Option "dump-vectorisation"         (set dump_vectorisation)+  , Option "dump-dot"                   (set dump_dot)+  , Option "dump-simpl-dot"             (set dump_simpl_dot)+  , Option "dump-gc"                    (set dump_gc)+  , Option "dump-gc-stats"              (set dump_gc_stats)+  , Option "debug-cc"                   (set debug_cc)+  , Option "dump-cc"                    (set dump_cc)+  , Option "dump-ld"                    (set dump_ld)+  , Option "dump-asm"                   (set dump_asm)+  , Option "dump-exec"                  (set dump_exec)+  , Option "dump-sched"                 (set dump_sched)+  ]+++class DebugFlag a where+  def :: a++instance DebugFlag Bool where+  {-# INLINE def #-}+  def = False++instance DebugFlag (Maybe a) where+  {-# INLINE def #-}+  def = Nothing+++-- | A bit of a hack to get the command line options processing out of the way.+--+-- We would like to have this automatically called once during program+-- initialisation, so that our command-line debug flags between +ACC .. [-ACC]+-- don't interfere with other programs.+--+-- Hacks beget hacks beget hacks...+--+accInit :: IO ()+#ifdef ACCELERATE_DEBUG+accInit = _flags `seq` return ()+#else+accInit = getUpdateArgs >> return ()+#endif++-- Initialise the debugging flags structure. This reads from both the command+-- line arguments as well as the environment variable "ACCELERATE_FLAGS".+-- Where applicable, options on the command line take precedence.+--+-- This is only available when compiled with debugging mode, because trying to+-- access it at any other time is an error.+--+#ifdef ACCELERATE_DEBUG+initialiseFlags :: IO Flags+initialiseFlags = do+  argv  <- getUpdateArgs+  env   <- maybe [] words `fmap` lookupEnv "ACCELERATE_FLAGS"+  return $ parse (env ++ argv)+  where+    defaults            = Flags def def def def def def def def def def def def def def def def def def def def def def++    parse               = foldl parse1 defaults+    parse1 opts this    =+      case filter (\(Option flag _) -> this `isPrefixOf` flag) allFlags of+        [Option _ go]   -> go opts+        []              -> trace unknown opts+        alts            -> case find (\(Option flag _) -> flag == this) alts of+                             Just (Option _ go) -> go opts+                             Nothing            -> trace (ambiguous alts) opts+      where+        unknown         = render $ text "Unknown option:" <+> quotes (text this)+        ambiguous alts  = render $+          vcat [ text "Ambiguous option:" <+> quotes (text this)+               , text ""+               , text "Did you mean one of these?"+               , nest 4 $ vcat (map (\(Option s _) -> text s) alts)+               ]+#endif+++-- If the command line arguments include a section "+ACC ... [-ACC]" then return+-- that section, and update the command line arguments to not include that part.+--+getUpdateArgs :: IO [String]+getUpdateArgs = do+  argv <- getArgs+  --+  let (before, r1)      = span (/= "+ACC") argv+      (flags,  r2)      = span (/= "-ACC") $ dropWhile (== "+ACC") r1+      after             = dropWhile (== "-ACC") r2+  --+#ifdef ACCELERATE_DEBUG+  prog <- getProgName+  setProgArgv (prog : before ++ after)+#else+  M.unless (null flags)+    $ error "Data.Array.Accelerate: Debugging options are disabled. Reinstall package 'accelerate' with '-fdebug' to enable them."+#endif+  return flags+++-- This is only defined in debug mode because to access it at any other time+-- should be an error.+--+#ifdef ACCELERATE_DEBUG+{-# NOINLINE _flags #-}+_flags :: IORef Flags+_flags = unsafePerformIO $ newIORef =<< initialiseFlags+#endif++{-# INLINE queryFlag #-}+queryFlag :: DebugFlag a => (Flags :-> a) -> IO a+#ifdef ACCELERATE_DEBUG+queryFlag f = get f `fmap` readIORef _flags+#else+queryFlag _ = return def+#endif+++type Mode = Flags :-> Bool++setFlag, clearFlag :: Mode -> IO ()+setFlag f   = setFlags [f]+clearFlag f = clearFlags [f]++setFlags, clearFlags :: [Mode] -> IO ()+#ifdef ACCELERATE_DEBUG+setFlags f   = modifyIORef _flags (\opt -> foldr (flip set True)  opt f)+clearFlags f = modifyIORef _flags (\opt -> foldr (flip set False) opt f)+#else+setFlags _   = return ()+clearFlags _ = return ()+#endif+++-- | Conditional execution of a monadic debugging expression+--+{-# INLINEABLE when #-}+when :: MonadIO m => Mode -> m () -> m ()+when f s = do+  yes <- liftIO $ queryFlag f+  M.when yes s++-- | The opposite of 'when'+--+{-# INLINEABLE unless #-}+unless :: MonadIO m => Mode -> m () -> m ()+unless f s = do+  yes <- liftIO $ queryFlag f+  M.unless yes s+++#ifdef ACCELERATE_DEBUG+-- Stolen from System.Environment+--+setProgArgv :: [String] -> IO ()+setProgArgv argv = do+  enc <- getFileSystemEncoding+  vs  <- mapM (GHC.newCString enc) argv >>= newArray0 nullPtr+  c_setProgArgv (genericLength argv) vs++foreign import ccall unsafe "setProgArgv"+  c_setProgArgv  :: CInt -> Ptr CString -> IO ()+#endif+
+ Data/Array/Accelerate/Debug/Monitoring.hs view
@@ -0,0 +1,327 @@+{-# LANGUAGE BangPatterns      #-}+{-# LANGUAGE CPP               #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards   #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.Debug.Monitoring+-- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Debug.Monitoring (++  beginMonitoring,+  initAccMetrics,++  Processor(..),+  withProcessor, addProcessorTime,+  didAllocateBytes,+  didEvictLRU,+  didMajorGC,++) where++#ifdef ACCELERATE_MONITORING+import Data.Atomic                                                  ( Atomic )+import qualified Data.Atomic                                        as Atomic++import System.Metrics+import System.Metrics.Counter                                       ( Counter )+import System.Metrics.Gauge                                         ( Gauge )+import qualified System.Metrics.Counter                             as Counter+import qualified System.Metrics.Gauge                               as Gauge++import Control.Concurrent+import Control.Concurrent.Async+import Control.Monad+import Data.IORef+import Data.Text                                                    ( Text )+import Data.Time.Clock+import System.IO.Unsafe+import System.Remote.Monitoring+import Text.Printf+import qualified Data.HashMap.Strict                                as Map+#endif++import Data.Int+import Prelude+++-- | Launch a monitoring server that will collect statistics on the running+-- application. This should be called as soon as the application starts. The+-- program will need to be run with the RTS option -T.+--+beginMonitoring :: IO ()+#ifdef ACCELERATE_MONITORING+beginMonitoring = do+  store <- initAccMetrics+  registerGcMetrics store+  r     <- withAsync (forkServerWith store "localhost" 8000 >> threadDelay 10000) waitCatch+  case r of+    Right _ -> printf "EKG monitor started at: http://localhost:8000\n"+    Left _  -> printf "Failed to start EKG monitor\n"+#else+beginMonitoring = return ()+#endif+++-- | Initialise and return the Accelerate monitoring store. To enable monitoring+-- of your application:+--+-- > import Data.Array.Accelerate.Debug+-- >+-- > import System.Metrics+-- > import System.Remote.Monitoring+-- >+-- > main :: IO ()+-- > main = do+-- >   store  <- initAccMetrics+-- >   registerGcMetrics store      -- optional+-- >+-- >   server <- forkServerWith store "localhost" 8000+-- >+-- >   ...+--+#ifndef ACCELERATE_MONITORING+initAccMetrics :: IO a+initAccMetrics = error "Data.Array.Accelerate: Monitoring is disabled. Reinstall package 'accelerate' with '-fekg' to enable it."+#else+initAccMetrics :: IO Store+initAccMetrics = do+  store <- newStore++  registerRate    "acc.load.llvm_native"            (calculateProcessorLoad _active_ns_llvm_native) store+  registerRate    "acc.load.llvm_ptx"               (calculateProcessorLoad _active_ns_llvm_ptx)    store+  registerRate    "acc.load.cuda"                   (calculateProcessorLoad _active_ns_cuda)        store+  registerCounter "acc.gc.bytes_allocated"          (Counter.read _bytesAllocated)                  store+  registerCounter "acc.gc.bytes_copied_to_remote"   (Counter.read _bytesCopiedToRemote)             store+  registerCounter "acc.gc.bytes_copied_from_remote" (Counter.read _bytesCopiedFromRemote)           store+  registerGauge   "acc.gc.current_bytes_active"     (Gauge.read   _bytesActive)                     store+  registerGauge   "acc.gc.current_bytes_nursery"    (Gauge.read   _bytesNursery)                    store+  registerCounter "acc.gc.num_gcs"                  (Counter.read _numMajorGC)                      store+  registerCounter "acc.gc.num_lru_evict"            (Counter.read _numEvictions)                    store++  return store+++-- Abusing 'registerGroup' to perform the rate calculation on every wake-up.+--+registerRate :: Text -> (IORef EMAState -> IO Int64) -> Store -> IO ()+registerRate name sample store = do+  now <- getCurrentTime+  st  <- newIORef (ES now 0 0)+  registerGroup (Map.singleton name Gauge) (sample st) store+#endif+++-- Recording metrics+-- -----------------++data Processor = Native | PTX | CUDA++-- | Execute the given action and assign the elapsed wall-clock time as active+-- time for the given processing element.+--+{-# INLINE withProcessor #-}+withProcessor :: Processor -> IO a -> IO a+#ifndef ACCELERATE_MONITORING+withProcessor _      = id+#else+withProcessor Native = withProcessor' _active_ns_llvm_native+withProcessor PTX    = withProcessor' _active_ns_llvm_ptx+withProcessor CUDA   = withProcessor' _active_ns_cuda++withProcessor' :: Atomic -> IO a -> IO a+withProcessor' var action = do+  wall0 <- getCurrentTime+  !r    <- action+  wall1 <- getCurrentTime+  addProcessorTime' var (realToFrac (diffUTCTime wall1 wall0))+  return r+#endif++-- | Record the given number of seconds as active processing time for the given+-- processing element.+--+{-# INLINE addProcessorTime #-}+addProcessorTime :: Processor -> Double -> IO ()+#ifndef ACCELERATE_MONITORING+addProcessorTime _ _    = return ()+#else+addProcessorTime Native = addProcessorTime' _active_ns_llvm_native+addProcessorTime PTX    = addProcessorTime' _active_ns_llvm_ptx+addProcessorTime CUDA   = addProcessorTime' _active_ns_cuda++addProcessorTime' :: Atomic -> Double -> IO ()+addProcessorTime' var secs =+  let ns   = round (secs * 1.0E9)+  in  void $ Atomic.add var ns+#endif+++didAllocateBytes :: Int64 -> IO ()+didEvictLRU      :: IO ()+didMajorGC       :: IO ()++#ifndef ACCELERATE_MONITORING+didAllocateBytes _ = return ()+didEvictLRU        = return ()+didMajorGC         = return ()+#else+didAllocateBytes n = do+  Counter.add _bytesAllocated n+  Gauge.add   _bytesActive    n++didEvictLRU = Counter.inc _numEvictions++didMajorGC  = do+  Counter.inc _numMajorGC+  Gauge.set   _bytesNursery 0    -- ???+#endif+++-- Implementation+-- --------------++#ifdef ACCELERATE_MONITORING++-- In order to calculate the processor load we need to remember the previous+-- values. Storing this state in an IORef has a bit of extra overhead (as+-- indirection) compared to the rest of the monitoring counters (which are+-- unboxed values on the heap manipulated directly with atomic primops), but+-- since 'calculateProcessorLoad' will only be called by the EKG monitor+-- whenever it refreshes the value for display, rather than running continuously+-- in the background, we should be okay.+--+data EMAState = ES+  { old_time  :: {-# UNPACK #-} !UTCTime+  , old_inst  :: {-# UNPACK #-} !Double+  , old_avg   :: {-# UNPACK #-} !Double+  }++-- Estimate the load on the processor as a moving exponential average+--+calculateProcessorLoad :: Atomic -> IORef EMAState -> IO Int64+calculateProcessorLoad !var !ref = do+  ES{..} <- readIORef ref+  time   <- getCurrentTime+  sample <- Atomic.and var 0+  --+  let+      active_ns   = fromIntegral sample+      elapsed_s   = realToFrac (diffUTCTime time old_time)+      elapsed_ns  = 1.0E9 * elapsed_s+      --+      load_inst   = 100 * (active_ns / elapsed_ns)                -- instantaneous load+      load_avg    = ema 0.2 elapsed_s old_avg old_inst load_inst  -- moving average load+  --+  writeIORef ref (ES time load_inst load_avg)+  return (round load_avg)+++{--+-- Compute the current load on a processor as a percentage of time spent working+-- over the elapsed time. This is meant to run continuously by a background+-- thread, updating the gauge each time it wakes up.+--+monitorProcessorLoad :: Gauge -> Atomic -> UTCTime -> Double -> Double -> IO ()+monitorProcessorLoad !gauge !var !old_time !old_inst !old_avg = do+  time   <- getCurrentTime+  sample <- Atomic.and var 0++  let+      active_ns   = fromIntegral sample+      elapsed_s   = realToFrac (diffUTCTime time old_time)+      elapsed_ns  = 1.0E9 * elapsed_s++      load_inst   = 100 * (active_ns / elapsed_ns)                -- instantaneous load+      load_avg    = ema 0.2 elapsed_s old_avg old_inst load_inst  -- moving average load++  -- Set what we thing the processor load over the previous interval should be+  Gauge.set gauge (round load_avg)++  -- Sleep for a bit, then do it all again+  threadDelay 500000    -- 500 ms+  monitorProcessorLoad gauge var time load_inst load_avg+--}++-- Exponential moving average for irregular time series+--+ema :: Double -> Double -> Double -> Double -> Double -> Double+ema !alpha !dt !old_ema !old_sample !new_sample =+  let+      a = dt / alpha+      u = exp ( -a )+      v = ( 1 - u ) / a+  in+  (u * old_ema) + ((v-u) * old_sample) + ((1-v) * new_sample)+++-- Monitoring variables+-- --------------------++-- Number of nanoseconds a backend has spent doing real work since the last+-- check. This is an integer amount because there are no built-in functions for+-- atomic memory access on double precision (as specified by the Intel docs).+--+{-# NOINLINE _active_ns_llvm_native #-}+_active_ns_llvm_native :: Atomic+_active_ns_llvm_native = unsafePerformIO (Atomic.new 0)++{-# NOINLINE _active_ns_llvm_ptx #-}+_active_ns_llvm_ptx :: Atomic+_active_ns_llvm_ptx = unsafePerformIO (Atomic.new 0)++{-# NOINLINE _active_ns_cuda #-}+_active_ns_cuda :: Atomic+_active_ns_cuda = unsafePerformIO (Atomic.new 0)++-- Total number of bytes allocated in the remote address space (e.g. on the GPU)+--+{-# NOINLINE _bytesAllocated #-}+_bytesAllocated :: Counter+_bytesAllocated = unsafePerformIO Counter.new++-- Total number of bytes copied from the host to the remote memory space+--+{-# NOINLINE _bytesCopiedToRemote #-}+_bytesCopiedToRemote :: Counter+_bytesCopiedToRemote = unsafePerformIO Counter.new++-- Total number of bytes copied from the remote memory space back to the device+--+{-# NOINLINE _bytesCopiedFromRemote #-}+_bytesCopiedFromRemote :: Counter+_bytesCopiedFromRemote = unsafePerformIO Counter.new++-- Current working remote memory size+--+{-# NOINLINE _bytesActive #-}+_bytesActive :: Gauge+_bytesActive = unsafePerformIO Gauge.new++-- Current size of the nursery+--+{-# NOINLINE _bytesNursery #-}+_bytesNursery :: Gauge+_bytesNursery = unsafePerformIO Gauge.new++-- Number of times the nursery was flushed+--+{-# NOINLINE _numMajorGC #-}+_numMajorGC :: Counter+_numMajorGC = unsafePerformIO Counter.new++-- number of LRU eviction events+--+{-# NOINLINE _numEvictions #-}+_numEvictions :: Counter+_numEvictions = unsafePerformIO Counter.new++#endif+
+ Data/Array/Accelerate/Debug/Stats.hs view
@@ -0,0 +1,210 @@+{-# LANGUAGE CPP #-}+{-# OPTIONS_GHC -fno-warn-unused-binds   #-}+{-# OPTIONS_GHC -fno-warn-unused-imports #-}+-- |+-- Module      : Data.Array.Accelerate.Debug.Simpl+-- Copyright   : [2008..2017] Manuel M T Chakravarty, Gabriele Keller+--               [2009..2017] Trevor L. McDonell+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- Tick-count statistics collection of the compiler passes, for debugging+-- purposes.+--++module Data.Array.Accelerate.Debug.Stats (++  simplCount, resetSimplCount,+  inline, ruleFired, knownBranch, betaReduce, substitution, simplifierDone, fusionDone,++) where++import Data.Array.Accelerate.Debug.Flags++import Data.Function                            ( on )+import Data.IORef+import Data.List                                ( groupBy, sortBy )+import Data.Ord                                 ( comparing )+import Data.Map                                 ( Map )+import Text.PrettyPrint+import System.IO.Unsafe++import qualified Data.Map                       as Map+++-- Recording statistics+-- --------------------++ruleFired, inline, knownBranch, betaReduce, substitution :: String -> a -> a+inline          = annotate Inline+ruleFired       = annotate RuleFired+knownBranch     = annotate KnownBranch+betaReduce      = annotate BetaReduce+substitution    = annotate Substitution++simplifierDone, fusionDone :: a -> a+simplifierDone  = tick SimplifierDone+fusionDone      = tick FusionDone++-- Add an entry to the statistics counters+--+tick :: Tick -> a -> a+#ifdef ACCELERATE_DEBUG+{-# NOINLINE tick #-}+tick t expr = unsafeDupablePerformIO $ do+  modifyIORef' statistics (simplTick t)+  return expr+#else+{-# INLINE tick #-}+tick _ expr = expr+#endif++-- Add an entry to the statistics counters with an annotation+--+annotate :: (Id -> Tick) -> String -> a -> a+annotate name ctx = tick (name (Id ctx))+++-- Simplifier counts+-- -----------------++data SimplStats+  = Simple         {-# UNPACK #-} !Int          -- when we don't want detailed stats++  | Detail {+      ticks     :: {-# UNPACK #-} !Int,         -- total ticks+      details   :: !TickCount                   -- how many of each type+    }++instance Show SimplStats where+  show = render . pprSimplCount+++-- Stores the current statistics counters+--+{-# NOINLINE statistics #-}+statistics :: IORef SimplStats+statistics = unsafePerformIO $ newIORef =<< initSimplCount++-- Initialise the statistics counters. If we are dumping the stats+-- (-ddump-simpl-stats) record extra information, else just a total tick count.+--+initSimplCount :: IO SimplStats+#ifdef ACCELERATE_DEBUG+initSimplCount = do+  d <- queryFlag dump_simpl_stats+  return $! if d then Detail { ticks = 0, details = Map.empty }+                 else Simple 0+#else+initSimplCount = return $! Simple 0+#endif+++-- Reset the statistics counters. Do this at the beginning at each HOAS -> de+-- Bruijn conversion + optimisation pass.+--+resetSimplCount :: IO ()+#ifdef ACCELERATE_DEBUG+resetSimplCount = writeIORef statistics =<< initSimplCount+#else+resetSimplCount = return ()+#endif+++-- Tick a counter+--+simplTick :: Tick -> SimplStats -> SimplStats+simplTick _ (Simple n)     = Simple (n+1)+simplTick t (Detail n dts) = Detail (n+1) (dts `addTick` t)++-- Pretty print the tick counts. Remarkably reminiscent of GHC style...+--+pprSimplCount :: SimplStats -> Doc+pprSimplCount (Simple n)     = text "Total ticks:" <+> int n+pprSimplCount (Detail n dts)+  = vcat [ text "Total ticks:" <+> int n+         , text ""+         , pprTickCount dts+         ]++simplCount :: IO Doc+simplCount = pprSimplCount `fmap` readIORef statistics+++-- Ticks+-- -----++type TickCount = Map Tick Int++data Id = Id String+  deriving (Eq, Ord)++data Tick+  = Inline              Id+  | RuleFired           Id+  | KnownBranch         Id+  | BetaReduce          Id+  | Substitution        Id++  -- tick at each iteration+  | SimplifierDone+  | FusionDone+  deriving (Eq, Ord)+++addTick :: TickCount -> Tick -> TickCount+addTick tc t =+  Map.alter f t tc+  where+    f Nothing  = Just 1+    f (Just x) = let x' = x+1 in x' `seq` Just x'++pprTickCount :: TickCount -> Doc+pprTickCount counts =+  vcat (map pprTickGroup groups)+  where+    groups  = groupBy sameTag (Map.toList counts)+    sameTag = (==) `on` tickToTag . fst++pprTickGroup :: [(Tick,Int)] -> Doc+pprTickGroup []    = error "pprTickGroup"+pprTickGroup group =+  hang (int groupTotal <+> text groupName)+     2 (vcat [ int n <+> pprTickCtx t | (t,n) <- sortBy (flip (comparing snd)) group ])+  where+    groupName  = tickToStr (fst (head group))+    groupTotal = sum [n | (_,n) <- group]++tickToTag :: Tick -> Int+tickToTag Inline{}              = 0+tickToTag RuleFired{}           = 1+tickToTag KnownBranch{}         = 2+tickToTag BetaReduce{}          = 3+tickToTag Substitution{}        = 4+tickToTag SimplifierDone        = 99+tickToTag FusionDone            = 100++tickToStr :: Tick -> String+tickToStr Inline{}              = "Inline"+tickToStr RuleFired{}           = "RuleFired"+tickToStr KnownBranch{}         = "KnownBranch"+tickToStr BetaReduce{}          = "BetaReduce"+tickToStr Substitution{}        = "Substitution"+tickToStr SimplifierDone        = "SimplifierDone"+tickToStr FusionDone            = "FusionDone"++pprTickCtx :: Tick -> Doc+pprTickCtx (Inline v)           = pprId v+pprTickCtx (RuleFired v)        = pprId v+pprTickCtx (KnownBranch v)      = pprId v+pprTickCtx (BetaReduce v)       = pprId v+pprTickCtx (Substitution v)     = pprId v+pprTickCtx SimplifierDone       = empty+pprTickCtx FusionDone           = empty++pprId :: Id -> Doc+pprId (Id s) = text s+
+ Data/Array/Accelerate/Debug/Timed.hs view
@@ -0,0 +1,109 @@+{-# LANGUAGE CPP #-}+-- |+-- Module      : Data.Array.Accelerate.Debug.Timed+-- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Debug.Timed (++  timed,+  elapsed,++) where++import Data.Array.Accelerate.Debug.Trace+import Data.Array.Accelerate.Debug.Flags++import Control.Monad.Trans                              ( MonadIO )+import Text.Printf++#if ACCELERATE_DEBUG+import Control.Applicative+import Control.Monad.Trans                              ( liftIO )+import Data.Int+import Data.List+import Data.Time.Clock+import System.CPUTime+import Prelude++import GHC.Stats+#endif+++-- | Execute an action and time the results. If GC stats have been enabled (with+-- @+RTS -t@ for example) then timing and memory usage information is displayed,+-- otherwise only timing information is shown.+--+{-# INLINEABLE timed #-}+timed :: MonadIO m => Mode -> (Double -> Double -> String) -> m a -> m a+#ifdef ACCELERATE_DEBUG+timed mode fmt action = do+  enabled <- liftIO $ queryFlag mode+  if enabled+    then do+      with_gc <- liftIO $ (&&) <$> getGCStatsEnabled <*> queryFlag verbose+      if with_gc+        then timed_gc    fmt action+        else timed_simpl fmt action+    else+      action+#else+timed _ _ action = action+#endif++#ifdef ACCELERATE_DEBUG+timed_simpl :: MonadIO m => (Double -> Double -> String) -> m a -> m a+timed_simpl fmt action = do+  wall0 <- liftIO getCurrentTime+  cpu0  <- liftIO getCPUTime+  res   <- action+  wall1 <- liftIO getCurrentTime+  cpu1  <- liftIO getCPUTime+  --+  let wallTime = realToFrac (diffUTCTime wall1 wall0)+      cpuTime  = fromIntegral (cpu1 - cpu0) * 1E-12+  --+  liftIO $ putTraceMsg (fmt wallTime cpuTime)+  return res+++timed_gc :: MonadIO m => (Double -> Double -> String) -> m a -> m a+timed_gc fmt action = do+  gc0 <- liftIO getGCStats+  res <- action+  gc1 <- liftIO getGCStats+  --+  let toDouble :: Int64 -> Double+      toDouble    = fromIntegral+      --+      allocated   = toDouble (bytesAllocated gc1 - bytesAllocated gc0)+      copied      = toDouble (bytesCopied gc1 - bytesCopied gc0)+      totalWall   = wallSeconds gc1 - wallSeconds gc0+      totalCPU    = cpuSeconds gc1 - cpuSeconds gc0+      mutatorWall = mutatorWallSeconds gc1 - mutatorWallSeconds gc0+      mutatorCPU  = mutatorCpuSeconds gc1 - mutatorCpuSeconds gc0+      gcWall      = gcWallSeconds gc1 - gcWallSeconds gc0+      gcCPU       = gcCpuSeconds gc1 - gcCpuSeconds gc0++  liftIO . putTraceMsg $ intercalate "\n"+    [ fmt totalWall totalCPU+    , printf "    %s allocated on the heap" (showFFloatSIBase (Just 1) 1024 allocated "B")+    , printf "    %s copied during GC (%d collections)" (showFFloatSIBase (Just 1) 1024 copied "B") (numGcs gc1 - numGcs gc0)+    , printf "    MUT: %s" (elapsed mutatorWall mutatorCPU)+    , printf "    GC:  %s" (elapsed gcWall gcCPU)+    ]+  --+  return res+#endif++elapsed :: Double -> Double -> String+elapsed wallTime cpuTime =+  printf "%s (wall), %s (cpu)"+    (showFFloatSIBase (Just 3) 1000 wallTime "s")+    (showFFloatSIBase (Just 3) 1000 cpuTime  "s")+
+ Data/Array/Accelerate/Debug/Trace.hs view
@@ -0,0 +1,137 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP          #-}+{-# OPTIONS_GHC -fno-warn-unused-imports #-}+-- |+-- Module      : Data.Array.Accelerate.Debug.Trace+-- Copyright   : [2008..2017] Manuel M T Chakravarty, Gabriele Keller+--               [2009..2017] Trevor L. McDonell+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- Functions for tracing and monitoring execution. These are useful for+-- investigating bugs and performance problems, but by default are not enabled+-- in performance code.+--++module Data.Array.Accelerate.Debug.Trace+  where++import Data.Array.Accelerate.Debug.Flags++import Numeric+import System.CPUTime+import System.IO.Unsafe+import Text.Printf+import qualified Debug.Trace                            as D+++-- | Show a signed 'RealFloat' value using SI unit prefixes. In the call to:+--+-- > showFFloatSIBase prec base val+--+-- If @prec@ is @'Nothing'@ the value is shown to full precision, and if @prec@+-- is @'Just' d@, then at most @d@ digits are shown after the decimal place.+-- Here @base@ represents the increment size between multiples of the original+-- unit. For measures in base-10 this will be 1000 and for values in base-2 this+-- is usually 1024, for example when measuring seconds versus bytes,+-- respectively.+--+showFFloatSIBase :: RealFloat a => Maybe Int -> a -> a -> ShowS+showFFloatSIBase prec !base !k+  = showString+  $ case pow of+      4   -> with "T"+      3   -> with "G"+      2   -> with "M"+      1   -> with "k"+      -1  -> with "m"+      -2  -> with "µ"+      -3  -> with "n"+      -4  -> with "p"+      _   -> showGFloat prec k " "      -- no unit or unhandled SI prefix+  where+    !k'         = k / (base ^^ pow)+    !pow        = floor (logBase base k) :: Int+    with unit   = showFFloat prec k' (' ':unit)+++-- | The 'trace' function outputs the message given as its second argument when+-- the debug mode indicated by the first argument is enabled, before returning+-- the third argument as its result. The message is prefixed with a time stamp.+--+trace :: Mode -> String -> a -> a+#ifdef ACCELERATE_DEBUG+{-# NOINLINE trace #-}+trace f msg expr = unsafePerformIO $ do+  traceIO f msg+  return expr+#else+{-# INLINE trace #-}+trace _ _ expr = expr+#endif+++-- | The 'traceIO' function outputs the trace message together with a time stamp+-- from the IO monad. This sequences the output with respect to other IO+-- actions.++-- TLM: Perhaps we should automatically format the log messages. Namely:+--        * prefix with a description of the mode (e.g. "gc: foo")+--        * align multi-line messages+--+traceIO :: Mode -> String -> IO ()+#ifdef ACCELERATE_DEBUG+traceIO f msg = when f $ putTraceMsg msg+#else+{-# INLINE traceIO #-}+traceIO _ _   = return ()+#endif+++-- | The 'traceEvent' function behaves like 'trace' with the difference that the+-- message is emitted to the eventlog, if eventlog profiling is enabled at+-- runtime.+--+traceEvent :: Mode -> String -> a -> a+#ifdef ACCELERATE_DEBUG+{-# NOINLINE traceEvent #-}+traceEvent f msg expr = unsafePerformIO $ do+  traceEventIO f msg+  return expr+#else+{-# INLINE traceEvent #-}+traceEvent _ _ expr = expr+#endif+++-- | Print a message prefixed with the current CPU time.+--+putTraceMsg :: String -> IO ()+#ifdef ACCELERATE_DEBUG+putTraceMsg msg = do+  psec        <- getCPUTime+  let secs    = fromIntegral psec * 1E-12 :: Double+  D.traceIO   $ printf "[%8.3f] %s" secs msg+#else+putTraceMsg _   = return ()+#endif+++-- | The 'traceEventIO' function emits a message to the eventlog, if eventlog+-- profiling is available and enabled at runtime.+--+-- Compared to 'traceEvent', 'traceEventIO' sequences the event with respect to+-- other IO actions.+--+traceEventIO :: Mode -> String -> IO ()+#ifdef ACCELERATE_DEBUG+traceEventIO f msg = do+  when f $ D.traceEventIO msg+#else+{-# INLINE traceEventIO #-}+traceEventIO _ _ = return ()+#endif+
Data/Array/Accelerate/Error.hs view
@@ -5,10 +5,10 @@ {-# OPTIONS_HADDOCK hide #-} -- | -- Module      : Data.Array.Accelerate.Error--- Copyright   : [2009..2014] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2009..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell -- License     : BSD3 ----- Maintainer  : Manuel M T Chakravarty <chak@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -26,7 +26,6 @@ import Language.Haskell.TH                              hiding ( Unsafe )  data Check = Bounds | Unsafe | Internal-  deriving (Eq)   -- | Issue an internal error message@@ -65,9 +64,9 @@ indexCheck :: Q Exp indexCheck = withLocation   [| \format fn i n x ->-        if not (doChecks Bounds) || (i >= 0 && i < n)-           then x-           else error (format Bounds (call fn ("index out of bounds: " ++ show (i,n)))) x |]+        case not (doChecks Bounds) || (i >= 0 && i < n) of+           True  -> x+           False -> error (format Bounds (call fn ("index out of bounds: " ++ show (i,n)))) x |]   -- | Print a warning message if the condition evaluates to False.@@ -97,16 +96,16 @@ checkQ :: Q Exp checkQ = withLocation   [| \format kind fn msg cond x ->-        if not (doChecks kind) || cond-           then x-           else error (format kind (call fn msg)) |]+        case not (doChecks kind) || cond of+          True  -> x+          False -> error (format kind (call fn msg)) |]  warningQ :: Q Exp warningQ = withLocation   [| \format kind fn msg cond x ->-        if not (doChecks kind) || cond-           then x-           else trace (format kind (call fn msg)) x |]+        case not (doChecks kind) || cond of+          True  -> x+          False -> trace (format kind (call fn msg)) x |]  withLocation :: Q Exp -> Q Exp withLocation f =@@ -126,11 +125,12 @@ message :: Check -> String -> String message kind msg = unlines header ++ msg   where-    header = if kind == Internal-                then [""-                     ,"*** Internal error in package accelerate ***"-                     ,"*** Please submit a bug report at https://github.com/AccelerateHS/accelerate/issues"]-                else []+    header =+      case kind of+        Internal -> [""+                    ,"*** Internal error in package accelerate ***"+                    ,"*** Please submit a bug report at https://github.com/AccelerateHS/accelerate/issues"]+        _        -> []   -- CPP malarky
+ Data/Array/Accelerate/FullList.hs view
@@ -0,0 +1,119 @@+{-# LANGUAGE BangPatterns  #-}+{-# LANGUAGE PatternGuards #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.FullList+-- Copyright   : [2008..2017] Manuel M T Chakravarty, Gabriele Keller+--               [2009..2017] Trevor L. McDonell+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- Non-empty lists of key/value pairs. The lists are strict in the key and lazy+-- in the values. We assume that keys only occur once.+--++module Data.Array.Accelerate.FullList (++  FullList(..),+  List(..),++  singleton,+  cons,+  size,+  mapM_,+  lookup,+  lookupDelete,++) where++import Prelude                  hiding ( lookup, mapM_ )+++data FullList k v = FL !k v !(List k v)+data List k v     = Nil | Cons !k v !(List k v)++infixr 5 `Cons`++instance (Eq k, Eq v) => Eq (FullList k v) where+  (FL k1 v1 xs) == (FL k2 v2 ys)      = k1 == k2 && v1 == v2 && xs == ys+  (FL k1 v1 xs) /= (FL k2 v2 ys)      = k1 /= k2 || v1 /= v2 || xs /= ys++instance (Eq k, Eq v) => Eq (List k v) where+  (Cons k1 v1 xs) == (Cons k2 v2 ys) = k1 == k2 && v1 == v2 && xs == ys+  Nil == Nil = True+  _   == _   = False++  (Cons k1 v1 xs) /= (Cons k2 v2 ys) = k1 /= k2 || v1 /= v2 || xs /= ys+  Nil /= Nil = False+  _   /= _   = True+++-- List-like operations+--+infixr 5 `cons`+cons :: k -> v -> FullList k v -> FullList k v+cons k v (FL k' v' xs) = FL k v (Cons k' v' xs)++singleton :: k -> v -> FullList k v+singleton k v = FL k v Nil++size :: FullList k v -> Int+size (FL _ _ xs) = 1 + sizeL xs++sizeL :: List k v -> Int+sizeL Nil           = 0+sizeL (Cons _ _ xs) = 1 + sizeL xs++lookup :: Eq k => k -> FullList k v -> Maybe v+lookup key (FL k v xs)+  | key == k    = Just v+  | otherwise   = lookupL key xs+{-# INLINABLE  lookup #-}+{-# SPECIALISE lookup :: () -> FullList () v -> Maybe v #-}++lookupL :: Eq k => k -> List k v -> Maybe v+lookupL !key = go+  where+    go Nil              = Nothing+    go (Cons k v xs)+      | key == k        = Just v+      | otherwise       = go xs+{-# INLINABLE  lookupL #-}+{-# SPECIALISE lookupL :: () -> List () v -> Maybe v #-}++lookupDelete :: Eq k => k -> FullList k v -> (Maybe v, Maybe (FullList k v))+lookupDelete key (FL k v xs)+  | key == k+  = case xs of+      Nil               -> (Just v, Nothing)+      Cons k' v' xs'    -> (Just v, Just $ FL k' v' xs')++  | (r, xs') <- lookupDeleteL k xs+  = (r, Just $ FL k v xs')+{-# INLINABLE  lookupDelete #-}+{-# SPECIALISE lookupDelete :: () -> FullList () v -> (Maybe v, Maybe (FullList () v)) #-}++lookupDeleteL :: Eq k => k -> List k v -> (Maybe v, List k v)+lookupDeleteL !key = go+  where+    go Nil                      = (Nothing, Nil)+    go (Cons k v xs)+      | key == k                = (Just v, xs)+      | (r, xs') <- go xs       = (r,      Cons k v xs')+{-# INLINABLE  lookupDeleteL #-}+{-# SPECIALISE lookupDeleteL :: () -> List () v -> (Maybe v, List () v) #-}++mapM_ :: Monad m => (k -> v -> m a) -> FullList k v -> m ()+mapM_ !f (FL k v xs) = f k v >> mapML_ f xs+{-# INLINABLE mapM_ #-}++mapML_ :: Monad m => (k -> v -> m a) -> List k v -> m ()+mapML_ !f = go+  where+    go Nil              = return ()+    go (Cons k v xs)    = f k v >> go xs+{-# INLINABLE mapML_ #-}+
Data/Array/Accelerate/Interpreter.hs view
@@ -1,43 +1,48 @@ {-# LANGUAGE BangPatterns        #-}+{-# LANGUAGE CPP                 #-}+{-# LANGUAGE FlexibleContexts    #-} {-# LANGUAGE GADTs               #-} {-# LANGUAGE PatternGuards       #-} {-# LANGUAGE RankNTypes          #-} {-# LANGUAGE RecordWildCards     #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TemplateHaskell     #-}+{-# LANGUAGE TypeFamilies        #-} {-# LANGUAGE TypeOperators       #-} {-# LANGUAGE ViewPatterns        #-} {-# OPTIONS_GHC -fno-warn-name-shadowing #-} {-# OPTIONS_HADDOCK prune #-} -- | -- Module      : Data.Array.Accelerate.Interpreter--- Copyright   : [2008..2014] Manuel M T Chakravarty, Gabriele Keller---               [2008..2009] Sean Lee---               [2009..2014] Trevor L. McDonell+-- Copyright   : [2008..2017] Manuel M T Chakravarty, Gabriele Keller+--               [2009..2017] Trevor L. McDonell+--               [2014..2014] Frederik M. Madsen -- License     : BSD3 ----- Maintainer  : Manuel M T Chakravarty <chak@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au> -- Stability   : experimental -- Portability : non-portable (GHC extensions) -- -- This interpreter is meant to be a reference implementation of the semantics--- of the embedded array language.  The emphasis is on defining the semantics+-- of the embedded array language. The emphasis is on defining the semantics -- clearly, not on performance. ----- /Surface types versus representation types/++-- [/Surface types versus representation types:/] ----- As a general rule, we perform all computations on representation types and we store all data--- as values of representation types.  To guarantee the type safety of the interpreter, this--- currently implies a lot of conversions between surface and representation types.  Optimising--- the code by eliminating back and forth conversions is fine, but only where it doesn't--- negatively affects clarity — after all, the main purpose of the interpreter is to serve as an--- executable specification.+-- As a general rule, we perform all computations on representation types and we+-- store all data as values of representation types. To guarantee the type+-- safety of the interpreter, this currently implies a lot of conversions+-- between surface and representation types. Optimising the code by eliminating+-- back and forth conversions is fine, but only where it doesn't negatively+-- affects clarity---after all, the main purpose of the interpreter is to serve+-- as an executable specification. --  module Data.Array.Accelerate.Interpreter (    -- * Interpret an array expression-  Arrays, run, run1, stream,+  Arrays, run, run1,    -- Internal (hidden)   evalPrim, evalPrimConst, evalPrj@@ -45,62 +50,84 @@ ) where  -- standard libraries+import Control.DeepSeq+import Control.Exception import Control.Monad import Data.Bits-import Data.Char                                                ( chr, ord )-import Prelude                                                  hiding ( sum )+import Data.Char                                                    ( chr, ord )+import System.IO.Unsafe                                             ( unsafePerformIO )+import Text.Printf                                                  ( printf )+import Unsafe.Coerce                                                ( unsafeCoerce )+import Prelude                                                      hiding ( sum )  -- friends import Data.Array.Accelerate.AST import Data.Array.Accelerate.Array.Data-import Data.Array.Accelerate.Array.Representation               ( SliceIndex(..) )+import Data.Array.Accelerate.Array.Representation                   ( SliceIndex(..) ) import Data.Array.Accelerate.Array.Sugar import Data.Array.Accelerate.Error-import Data.Array.Accelerate.Trafo                              hiding ( Delayed )-import Data.Array.Accelerate.Tuple+import Data.Array.Accelerate.Product+import Data.Array.Accelerate.Trafo                                  hiding ( Delayed ) import Data.Array.Accelerate.Type-import qualified Data.Array.Accelerate.Smart                    as Sugar-import qualified Data.Array.Accelerate.Trafo                    as AST-import qualified Data.Array.Accelerate.Array.Representation     as R+import qualified Data.Array.Accelerate.Array.Representation         as R+import qualified Data.Array.Accelerate.Smart                        as Sugar+import qualified Data.Array.Accelerate.Trafo                        as AST +import qualified Data.Array.Accelerate.Debug                        as D + -- Program execution -- -----------------  -- | Run a complete embedded array program using the reference interpreter. -- run :: Arrays a => Sugar.Acc a -> a-run acc-  = let a = convertAccWith config acc-    in  evalOpenAcc a Empty-+run a = unsafePerformIO execute+  where+    !acc    = convertAccWith config a+    execute = do+      D.dumpGraph $!! acc+      D.dumpSimplStats+      phase "execute" D.elapsed (evaluate (evalOpenAcc acc Empty))  -- | Prepare and run an embedded array program of one argument -- run1 :: (Arrays a, Arrays b) => (Sugar.Acc a -> Sugar.Acc b) -> a -> b-run1 afun-  = let f = convertAfunWith config afun-    in  evalOpenAfun f Empty-+run1 f = \a -> unsafePerformIO (execute a)+  where+    !acc    = convertAfunWith config f+    !afun   = unsafePerformIO $ do+                D.dumpGraph $!! acc+                D.dumpSimplStats+                return acc+    execute x = phase "execute" D.elapsed (evaluate (evalOpenAfun afun Empty x)) --- | Stream a lazily read list of input arrays through the given program,--- collecting results as we go----stream :: (Arrays a, Arrays b) => (Sugar.Acc a -> Sugar.Acc b) -> [a] -> [b]-stream afun arrs = let go = run1 afun-                   in  map go arrs+-- -- | Stream a lazily read list of input arrays through the given program,+-- -- collecting results as we go+-- --+-- streamOut :: Arrays a => Sugar.Seq [a] -> [a]+-- streamOut seq = let seq' = convertSeqWith config seq+--                 in evalDelayedSeq defaultSeqConfig seq'   config :: Phase config =  Phase   { recoverAccSharing      = True   , recoverExpSharing      = True+  , recoverSeqSharing      = True   , floatOutAccFromExp     = True   , enableAccFusion        = True   , convertOffsetOfSegment = False+  -- , vectoriseSequences     = True   } +-- Debugging+-- --------- +phase :: String -> (Double -> Double -> String) -> IO a -> IO a+phase n fmt go = D.timed D.dump_phases (\wall cpu -> printf "phase %s: %s" n (fmt wall cpu)) go++ -- Delayed Arrays -- -------------- @@ -154,8 +181,8 @@   case pacc of     Avar ix                     -> prj ix aenv     Alet acc1 acc2              -> evalOpenAcc acc2 (aenv `Push` manifest acc1)-    Atuple atup                 -> toTuple $ evalAtuple atup aenv-    Aprj ix atup                -> evalPrj ix . fromTuple  $ manifest atup+    Atuple atup                 -> toAtuple $ evalAtuple atup aenv+    Aprj ix atup                -> evalPrj ix . fromAtuple $ manifest atup     Apply afun acc              -> evalOpenAfun afun aenv  $ manifest acc     Aforeign _ afun acc         -> evalOpenAfun afun Empty $ manifest acc     Acond p acc1 acc2@@ -172,6 +199,7 @@      Use arr                     -> toArr arr     Unit e                      -> unitOp (evalE e)+    -- Collect s                   -> evalSeq defaultSeqConfig s aenv      -- Producers     -- ---------@@ -212,7 +240,7 @@ -- ----------------  unitOp :: Elt e => e -> Scalar e-unitOp e = newArray Z (const e)+unitOp e = fromFunction Z (const e)   generateOp@@ -220,18 +248,18 @@     => sh     -> (sh -> e)     -> Array sh e-generateOp = newArray+generateOp = fromFunction   transformOp-    :: (Shape sh, Shape sh', Elt b)+    :: (Shape sh', Elt b)     => sh'     -> (sh' -> sh)     -> (a -> b)     -> Delayed (Array sh a)     -> Array sh' b transformOp sh' p f (Delayed _ xs _)-  = newArray sh' (\ix -> f (xs $ p ix))+  = fromFunction sh' (\ix -> f (xs $ p ix))   reshapeOp@@ -251,7 +279,7 @@     -> Array sl e     -> Array sh e replicateOp slice slix arr-  = newArray (toElt sh) (\ix -> arr ! liftToElt pf ix)+  = fromFunction (toElt sh) (\ix -> arr ! liftToElt pf ix)   where     (sh, pf) = extend slice (fromElt slix) (fromElt (shape arr)) @@ -275,9 +303,9 @@     -> slix     -> Array sl e sliceOp slice arr slix-  = newArray (toElt sh) (\ix -> arr ! liftToElt pf ix)+  = fromFunction (toElt sh') (\ix -> arr ! liftToElt pf ix)   where-    (sh, pf) = restrict slice (fromElt slix) (fromElt (shape arr))+    (sh', pf) = restrict slice (fromElt slix) (fromElt (shape arr))      restrict :: SliceIndex slix sl co sh              -> slix@@ -292,24 +320,39 @@         in  $indexCheck "slice" i sz $ (sl', \ix -> (f' ix, i))  -mapOp :: (Shape sh, Elt a, Elt b)+mapOp :: (Shape sh, Elt b)       => (a -> b)       -> Delayed (Array sh a)       -> Array sh b mapOp f (Delayed sh xs _)-  = newArray sh (\ix -> f (xs ix))+  = fromFunction sh (\ix -> f (xs ix))   zipWithOp-    :: (Shape sh, Elt a, Elt b, Elt c)+    :: (Shape sh, Elt c)     => (a -> b -> c)     -> Delayed (Array sh a)     -> Delayed (Array sh b)     -> Array sh c zipWithOp f (Delayed shx xs _) (Delayed shy ys _)-  = newArray (shx `intersect` shy) (\ix -> f (xs ix) (ys ix))+  = fromFunction (shx `intersect` shy) (\ix -> f (xs ix) (ys ix)) +-- zipWith'Op+--     :: (Shape sh, Elt a)+--     => (a -> a -> a)+--     -> Delayed (Array sh a)+--     -> Delayed (Array sh a)+--     -> Array sh a+-- zipWith'Op f (Delayed shx xs _) (Delayed shy ys _)+--   = fromFunction (shx `union` shy) (\ix -> if ix `outside` shx+--                                            then ys ix+--                                            else if ix `outside` shy+--                                            then xs ix+--                                            else f (xs ix) (ys ix))+--   where+--     a `outside` b = or $ zipWith (>=) (shapeToList a) (shapeToList b) + foldOp     :: (Shape sh, Elt e)     => (e -> e -> e)@@ -318,10 +361,10 @@     -> Array sh e foldOp f z (Delayed (sh :. n) arr _)   | size sh == 0-  = newArray (listToShape . map (max 1) . shapeToList $ sh) (const z)+  = fromFunction (listToShape . map (max 1) . shapeToList $ sh) (const z)    | otherwise-  = newArray sh (\ix -> iter (Z:.n) (\(Z:.i) -> arr (ix :. i)) f z)+  = fromFunction sh (\ix -> iter (Z:.n) (\(Z:.i) -> arr (ix :. i)) f z)   fold1Op@@ -330,11 +373,12 @@     -> Delayed (Array (sh :. Int) e)     -> Array sh e fold1Op f (Delayed (sh :. n) arr _)-  = newArray sh (\ix -> iter1 (Z:.n) (\(Z:.i) -> arr (ix :. i)) f)+  = $boundsCheck "fold1" "empty array" (n > 0)+  $ fromFunction sh (\ix -> iter1 (Z:.n) (\(Z:.i) -> arr (ix :. i)) f)   foldSegOp-    :: forall sh e i. (Shape sh, Elt e, Elt i, IsIntegral i)+    :: forall sh e i. (Elt e, Elt i, IsIntegral i)     => (e -> e -> e)     -> e     -> Delayed (Array (sh :. Int) e)@@ -342,7 +386,7 @@     -> Array (sh :. Int) e foldSegOp f z (Delayed (sh :. _) arr _) seg@(Delayed (Z :. n) _ _)   | IntegralDict <- integralDict (integralType :: IntegralType i)-  = newArray (sh :. n)+  = fromFunction (sh :. n)   $ \(sz :. ix) -> let start = fromIntegral $ offset ! (Z :. ix)                        end   = fromIntegral $ offset ! (Z :. ix+1)                    in@@ -359,149 +403,175 @@     -> Array (sh :. Int) e fold1SegOp f (Delayed (sh :. _) arr _) seg@(Delayed (Z :. n) _ _)   | IntegralDict <- integralDict (integralType :: IntegralType i)-  = newArray (sh :. n)+  = fromFunction (sh :. n)   $ \(sz :. ix) -> let start = fromIntegral $ offset ! (Z :. ix)                        end   = fromIntegral $ offset ! (Z :. ix+1)                    in-                   iter1 (Z :. end-start) (\(Z:.i) -> arr (sz :. start+i)) f+                   $boundsCheck "fold1Seg" "empty segment" (end > start)+                   $ iter1 (Z :. end-start) (\(Z:.i) -> arr (sz :. start+i)) f   where     offset      = scanlOp (+) 0 seg   scanl1Op-    :: Elt e+    :: (Shape sh, Elt e)     => (e -> e -> e)-    -> Delayed (Vector e)-    -> Vector e-scanl1Op f (Delayed sh@(Z :. n) _ ain)-  = adata `seq` Array (fromElt sh) adata+    -> Delayed (Array (sh:.Int) e)+    -> Array (sh:.Int) e+scanl1Op f (Delayed sh@(_ :. n) ain _)+  = $boundsCheck "scanl1" "empty array" (n > 0)+  $ adata `seq` Array (fromElt sh) adata   where     f'          = sinkFromElt2 f     --     (adata, _)  = runArrayData $ do-      aout <- newArrayData n+      aout <- newArrayData (size sh) -      let write (Z:.0) = unsafeWriteArrayData aout 0 (fromElt $ ain 0)-          write (Z:.i) = do-            x <- unsafeReadArrayData aout (i-1)-            y <- return . fromElt $  ain  i-            unsafeWriteArrayData aout i (f' x y)+      let write (sz:.0) = unsafeWriteArrayData aout (toIndex sh (sz:.0)) (fromElt (ain (sz:.0)))+          write (sz:.i) = do+            x <- unsafeReadArrayData aout (toIndex sh (sz:.i-1))+            y <- return $ fromElt (ain (sz:.i))+            unsafeWriteArrayData aout (toIndex sh (sz:.i)) (f' x y)        iter1 sh write (>>)       return (aout, undefined)   scanlOp-    :: Elt e+    :: (Shape sh, Elt e)     => (e -> e -> e)     -> e-    -> Delayed (Vector e)-    -> Vector e-scanlOp f z (Delayed (Z :. n) _ ain)+    -> Delayed (Array (sh:.Int) e)+    -> Array (sh:.Int) e+scanlOp f z (Delayed (sh :. n) ain _)   = adata `seq` Array (fromElt sh') adata   where-    sh'         = Z :. n+1+    sh'         = sh :. n+1     f'          = sinkFromElt2 f     --     (adata, _)  = runArrayData $ do-      aout <- newArrayData (n+1)+      aout <- newArrayData (size sh') -      let write (Z:.0) = unsafeWriteArrayData aout 0 (fromElt z)-          write (Z:.i) = do-            x <- unsafeReadArrayData aout (i-1)-            y <- return . fromElt $  ain  (i-1)-            unsafeWriteArrayData aout i (f' x y)+      let write (sz:.0) = unsafeWriteArrayData aout (toIndex sh' (sz:.0)) (fromElt z)+          write (sz:.i) = do+            x <- unsafeReadArrayData aout (toIndex sh' (sz:.i-1))+            y <- return $ fromElt (ain (sz:.i-1))+            unsafeWriteArrayData aout (toIndex sh' (sz:.i)) (f' x y)        iter sh' write (>>) (return ())       return (aout, undefined)   scanl'Op-    :: Elt e+    :: (Shape sh, Elt e)     => (e -> e -> e)     -> e-    -> Delayed (Vector e)-    -> (Vector e, Scalar e)-scanl'Op f z (scanlOp f z -> arr)-  = let-        arr'    = case arr of Array _ adata -> Array ((), n-1) adata-        sum     = unitOp (arr ! (Z:.n-1))-        n       = size (shape arr)-    in-    (arr', sum)+    -> Delayed (Array (sh:.Int) e)+    -> (Array (sh:.Int) e, Array sh e)+scanl'Op f z (Delayed (sh :. n) ain _)+  = aout `seq` asum `seq` ( Array (fromElt (sh:.n)) aout+                          , Array (fromElt sh)      asum )+  where+    f'          = sinkFromElt2 f+    --+    (AD_Pair aout asum, _) = runArrayData $ do+      aout <- newArrayData (size (sh:.n))+      asum <- newArrayData (size sh) +      let write (sz:.0)+            | n == 0    = unsafeWriteArrayData asum (toIndex sh sz) (fromElt z)+            | otherwise = unsafeWriteArrayData aout (toIndex (sh:.n) (sz:.0)) (fromElt z)+          write (sz:.i) = do+            x <- unsafeReadArrayData aout (toIndex (sh:.n) (sz:.i-1))+            y <- return $ fromElt (ain (sz:.i-1))+            if i == n+              then unsafeWriteArrayData asum (toIndex sh      sz)      (f' x y)+              else unsafeWriteArrayData aout (toIndex (sh:.n) (sz:.i)) (f' x y) +      iter (sh:.n+1) write (>>) (return ())+      return (AD_Pair aout asum, undefined)++ scanrOp-    :: Elt e+    :: (Shape sh, Elt e)     => (e -> e -> e)     -> e-    -> Delayed (Vector e)-    -> Vector e-scanrOp f z (Delayed (Z :. n) _ ain)+    -> Delayed (Array (sh:.Int) e)+    -> Array (sh:.Int) e+scanrOp f z (Delayed (sz :. n) ain _)   = adata `seq` Array (fromElt sh') adata   where-    sh'         = Z :. n+1+    sh'         = sz :. n+1     f'          = sinkFromElt2 f     --     (adata, _)  = runArrayData $ do-      aout <- newArrayData (n+1)+      aout <- newArrayData (size sh') -      let write (Z:.0) = unsafeWriteArrayData aout n (fromElt z)-          write (Z:.i) = do-            x <- unsafeReadArrayData aout (n-i+1)-            y <- return . fromElt $  ain  (n-i)-            unsafeWriteArrayData aout (n-i) (f' x y)+      let write (sz:.0) = unsafeWriteArrayData aout (toIndex sh' (sz:.n)) (fromElt z)+          write (sz:.i) = do+            x <- return $ fromElt (ain (sz:.n-i))+            y <- unsafeReadArrayData aout (toIndex sh' (sz:.n-i+1))+            unsafeWriteArrayData aout (toIndex sh' (sz:.n-i)) (f' x y)        iter sh' write (>>) (return ())       return (aout, undefined)   scanr1Op-    :: Elt e+    :: (Shape sh, Elt e)     => (e -> e -> e)-    -> Delayed (Vector e)-    -> Vector e-scanr1Op f (Delayed sh@(Z :. n) _ ain)-  = adata `seq` Array (fromElt sh) adata+    -> Delayed (Array (sh:.Int) e)+    -> Array (sh:.Int) e+scanr1Op f (Delayed sh@(_ :. n) ain _)+  = $boundsCheck "scanr1" "empty array" (n > 0)+  $ adata `seq` Array (fromElt sh) adata   where     f'          = sinkFromElt2 f     --     (adata, _)  = runArrayData $ do-      aout <- newArrayData n+      aout <- newArrayData (size sh) -      let write (Z:.0) = unsafeWriteArrayData aout (n-1) (fromElt $ ain (n-1))-          write (Z:.i) = do-            x <- unsafeReadArrayData aout (n-i)-            y <- return . fromElt $  ain  (n-i-1)-            unsafeWriteArrayData aout (n-i-1) (f' x y)+      let write (sz:.0) = unsafeWriteArrayData aout (toIndex sh (sz:.n-1)) (fromElt (ain (sz:.n-1)))+          write (sz:.i) = do+            x <- return $ fromElt (ain (sz:.n-i-1))+            y <- unsafeReadArrayData aout (toIndex sh (sz:.n-i))+            unsafeWriteArrayData aout (toIndex sh (sz:.n-i-1)) (f' x y)        iter1 sh write (>>)       return (aout, undefined)   scanr'Op-    :: forall e. Elt e+    :: forall sh e. (Shape sh, Elt e)     => (e -> e -> e)     -> e-    -> Delayed (Vector e)-    -> (Vector e, Scalar e)-scanr'Op f z (Delayed (Z :. n) _ ain)-  = (Array ((),n) adata, unitOp (toElt asum))+    -> Delayed (Array (sh:.Int) e)+    -> (Array (sh:.Int) e, Array sh e)+scanr'Op f z (Delayed (sh :. n) ain _)+  = aout `seq` asum `seq` ( Array (fromElt (sh:.n)) aout+                          , Array (fromElt sh)      asum )   where-    f' x y      = sinkFromElt2 f (fromElt x) y+    f'          = sinkFromElt2 f     ---    (adata, asum) = runArrayData $ do-      aout <- newArrayData n+    (AD_Pair aout asum, _) = runArrayData $ do+      aout <- newArrayData (size (sh:.n))+      asum <- newArrayData (size sh) -      let trav i !y | i < 0     = return y-          trav i y              = do-            unsafeWriteArrayData aout i y-            trav (i-1) (f' (ain i) y)+      let write (sz:.0)+            | n == 0    = unsafeWriteArrayData asum (toIndex sh sz) (fromElt z)+            | otherwise = unsafeWriteArrayData aout (toIndex (sh:.n) (sz:.n-1)) (fromElt z) -      final <- trav (n-1) (fromElt z)-      return (aout, final)+          write (sz:.i) = do+            x <- return $ fromElt (ain (sz:.n-i))+            y <- unsafeReadArrayData aout (toIndex (sh:.n) (sz:.n-i))+            if i == n+              then unsafeWriteArrayData asum (toIndex sh      sz)          (f' x y)+              else unsafeWriteArrayData aout (toIndex (sh:.n) (sz:.n-i-1)) (f' x y) +      iter (sh:.n+1) write (>>) (return ())+      return (AD_Pair aout asum, undefined) + permuteOp     :: (Shape sh, Shape sh', Elt e)     => (e -> e -> e)@@ -544,23 +614,23 @@   backpermuteOp-    :: (Shape sh, Shape sh', Elt e)+    :: (Shape sh', Elt e)     => sh'     -> (sh' -> sh)     -> Delayed (Array sh e)     -> Array sh' e backpermuteOp sh' p (Delayed _ arr _)-  = newArray sh' (\ix -> arr $ p ix)+  = fromFunction sh' (\ix -> arr $ p ix)   stencilOp-    :: (Elt a, Elt b, Stencil sh a stencil)+    :: (Stencil sh a stencil, Elt b)     => (stencil -> b)     -> Boundary (EltRepr a)     -> Array sh a     -> Array sh b stencilOp stencil boundary arr-  = newArray sh f+  = fromFunction sh f   where     f           = stencil . stencilAccess bounded     sh          = shape arr@@ -572,7 +642,7 @@   stencil2Op-    :: (Elt a, Elt b, Elt c, Stencil sh a stencil1, Stencil sh b stencil2)+    :: (Stencil sh a stencil1, Stencil sh b stencil2, Elt c)     => (stencil1 -> stencil2 -> c)     -> Boundary (EltRepr a)     -> Array sh a@@ -580,7 +650,7 @@     -> Array sh b     -> Array sh c stencil2Op stencil boundary1 arr1 boundary2 arr2-  = newArray (sh1 `intersect` sh2) f+  = fromFunction (sh1 `intersect` sh2) f   where     sh1         = shape arr1     sh2         = shape arr2@@ -597,6 +667,16 @@         Left v    -> toElt v         Right ix' -> arr2 ! ix' +-- toSeqOp :: forall slix sl dim co e proxy. (Elt slix, Shape sl, Shape dim, Elt e)+--         => SliceIndex (EltRepr slix)+--                       (EltRepr sl)+--                       co+--                       (EltRepr dim)+--         -> proxy slix+--         -> Array dim e+--         -> [Array sl e]+-- toSeqOp sliceIndex _ arr = map (sliceOp sliceIndex arr :: slix -> Array sl e)+--                                (enumSlices sliceIndex (shape arr))  -- Scalar expression evaluation -- ----------------------------@@ -704,6 +784,7 @@     Shape acc                   -> shape (evalA acc)     ShapeSize sh                -> size (evalE sh)     Intersect sh1 sh2           -> intersect (evalE sh1) (evalE sh2)+    Union sh1 sh2               -> union (evalE sh1) (evalE sh2)     Foreign _ f e               -> evalPreOpenFun evalAcc f EmptyElt Empty $ evalE e  @@ -716,60 +797,71 @@ evalPrimConst (PrimPi       ty) = evalPi ty  evalPrim :: PrimFun p -> p-evalPrim (PrimAdd             ty) = evalAdd ty-evalPrim (PrimSub             ty) = evalSub ty-evalPrim (PrimMul             ty) = evalMul ty-evalPrim (PrimNeg             ty) = evalNeg ty-evalPrim (PrimAbs             ty) = evalAbs ty-evalPrim (PrimSig             ty) = evalSig ty-evalPrim (PrimQuot            ty) = evalQuot ty-evalPrim (PrimRem             ty) = evalRem ty-evalPrim (PrimIDiv            ty) = evalIDiv ty-evalPrim (PrimMod             ty) = evalMod ty-evalPrim (PrimBAnd            ty) = evalBAnd ty-evalPrim (PrimBOr             ty) = evalBOr ty-evalPrim (PrimBXor            ty) = evalBXor ty-evalPrim (PrimBNot            ty) = evalBNot ty-evalPrim (PrimBShiftL         ty) = evalBShiftL ty-evalPrim (PrimBShiftR         ty) = evalBShiftR ty-evalPrim (PrimBRotateL        ty) = evalBRotateL ty-evalPrim (PrimBRotateR        ty) = evalBRotateR ty-evalPrim (PrimFDiv            ty) = evalFDiv ty-evalPrim (PrimRecip           ty) = evalRecip ty-evalPrim (PrimSin             ty) = evalSin ty-evalPrim (PrimCos             ty) = evalCos ty-evalPrim (PrimTan             ty) = evalTan ty-evalPrim (PrimAsin            ty) = evalAsin ty-evalPrim (PrimAcos            ty) = evalAcos ty-evalPrim (PrimAtan            ty) = evalAtan ty-evalPrim (PrimAsinh           ty) = evalAsinh ty-evalPrim (PrimAcosh           ty) = evalAcosh ty-evalPrim (PrimAtanh           ty) = evalAtanh ty-evalPrim (PrimExpFloating     ty) = evalExpFloating ty-evalPrim (PrimSqrt            ty) = evalSqrt ty-evalPrim (PrimLog             ty) = evalLog ty-evalPrim (PrimFPow            ty) = evalFPow ty-evalPrim (PrimLogBase         ty) = evalLogBase ty-evalPrim (PrimTruncate     ta tb) = evalTruncate ta tb-evalPrim (PrimRound        ta tb) = evalRound ta tb-evalPrim (PrimFloor        ta tb) = evalFloor ta tb-evalPrim (PrimCeiling      ta tb) = evalCeiling ta tb-evalPrim (PrimAtan2           ty) = evalAtan2 ty-evalPrim (PrimLt              ty) = evalLt ty-evalPrim (PrimGt              ty) = evalGt ty-evalPrim (PrimLtEq            ty) = evalLtEq ty-evalPrim (PrimGtEq            ty) = evalGtEq ty-evalPrim (PrimEq              ty) = evalEq ty-evalPrim (PrimNEq             ty) = evalNEq ty-evalPrim (PrimMax             ty) = evalMax ty-evalPrim (PrimMin             ty) = evalMin ty-evalPrim PrimLAnd                 = evalLAnd-evalPrim PrimLOr                  = evalLOr-evalPrim PrimLNot                 = evalLNot-evalPrim PrimOrd                  = evalOrd-evalPrim PrimChr                  = evalChr-evalPrim PrimBoolToInt            = evalBoolToInt-evalPrim (PrimFromIntegral ta tb) = evalFromIntegral ta tb+evalPrim (PrimAdd                ty) = evalAdd ty+evalPrim (PrimSub                ty) = evalSub ty+evalPrim (PrimMul                ty) = evalMul ty+evalPrim (PrimNeg                ty) = evalNeg ty+evalPrim (PrimAbs                ty) = evalAbs ty+evalPrim (PrimSig                ty) = evalSig ty+evalPrim (PrimQuot               ty) = evalQuot ty+evalPrim (PrimRem                ty) = evalRem ty+evalPrim (PrimQuotRem            ty) = evalQuotRem ty+evalPrim (PrimIDiv               ty) = evalIDiv ty+evalPrim (PrimMod                ty) = evalMod ty+evalPrim (PrimDivMod             ty) = evalDivMod ty+evalPrim (PrimBAnd               ty) = evalBAnd ty+evalPrim (PrimBOr                ty) = evalBOr ty+evalPrim (PrimBXor               ty) = evalBXor ty+evalPrim (PrimBNot               ty) = evalBNot ty+evalPrim (PrimBShiftL            ty) = evalBShiftL ty+evalPrim (PrimBShiftR            ty) = evalBShiftR ty+evalPrim (PrimBRotateL           ty) = evalBRotateL ty+evalPrim (PrimBRotateR           ty) = evalBRotateR ty+evalPrim (PrimPopCount           ty) = evalPopCount ty+evalPrim (PrimCountLeadingZeros  ty) = evalCountLeadingZeros ty+evalPrim (PrimCountTrailingZeros ty) = evalCountTrailingZeros ty+evalPrim (PrimFDiv               ty) = evalFDiv ty+evalPrim (PrimRecip              ty) = evalRecip ty+evalPrim (PrimSin                ty) = evalSin ty+evalPrim (PrimCos                ty) = evalCos ty+evalPrim (PrimTan                ty) = evalTan ty+evalPrim (PrimAsin               ty) = evalAsin ty+evalPrim (PrimAcos               ty) = evalAcos ty+evalPrim (PrimAtan               ty) = evalAtan ty+evalPrim (PrimSinh               ty) = evalSinh ty+evalPrim (PrimCosh               ty) = evalCosh ty+evalPrim (PrimTanh               ty) = evalTanh ty+evalPrim (PrimAsinh              ty) = evalAsinh ty+evalPrim (PrimAcosh              ty) = evalAcosh ty+evalPrim (PrimAtanh              ty) = evalAtanh ty+evalPrim (PrimExpFloating        ty) = evalExpFloating ty+evalPrim (PrimSqrt               ty) = evalSqrt ty+evalPrim (PrimLog                ty) = evalLog ty+evalPrim (PrimFPow               ty) = evalFPow ty+evalPrim (PrimLogBase            ty) = evalLogBase ty+evalPrim (PrimTruncate        ta tb) = evalTruncate ta tb+evalPrim (PrimRound           ta tb) = evalRound ta tb+evalPrim (PrimFloor           ta tb) = evalFloor ta tb+evalPrim (PrimCeiling         ta tb) = evalCeiling ta tb+evalPrim (PrimAtan2              ty) = evalAtan2 ty+evalPrim (PrimIsNaN              ty) = evalIsNaN ty+evalPrim (PrimLt                 ty) = evalLt ty+evalPrim (PrimGt                 ty) = evalGt ty+evalPrim (PrimLtEq               ty) = evalLtEq ty+evalPrim (PrimGtEq               ty) = evalGtEq ty+evalPrim (PrimEq                 ty) = evalEq ty+evalPrim (PrimNEq                ty) = evalNEq ty+evalPrim (PrimMax                ty) = evalMax ty+evalPrim (PrimMin                ty) = evalMin ty+evalPrim PrimLAnd                    = evalLAnd+evalPrim PrimLOr                     = evalLOr+evalPrim PrimLNot                    = evalLNot+evalPrim PrimOrd                     = evalOrd+evalPrim PrimChr                     = evalChr+evalPrim PrimBoolToInt               = evalBoolToInt+evalPrim (PrimFromIntegral ta tb)    = evalFromIntegral ta tb+evalPrim (PrimToFloating ta tb)      = evalToFloating ta tb+evalPrim PrimCoerce{}                = unsafeCoerce   -- Tuple construction and projection@@ -820,7 +912,18 @@   , FloatingDict <- floatingDict tb   = fromIntegral +evalToFloating :: NumType a -> FloatingType b -> a -> b+evalToFloating (IntegralNumType ta) tb+  | IntegralDict <- integralDict ta+  , FloatingDict <- floatingDict tb+  = realToFrac +evalToFloating (FloatingNumType ta) tb+  | FloatingDict <- floatingDict ta+  , FloatingDict <- floatingDict tb+  = realToFrac++ -- Extract methods from reified dictionaries -- @@ -869,6 +972,15 @@ evalAtan :: FloatingType a -> (a -> a) evalAtan ty | FloatingDict <- floatingDict ty = atan +evalSinh :: FloatingType a -> (a -> a)+evalSinh ty | FloatingDict <- floatingDict ty = sinh++evalCosh :: FloatingType a -> (a -> a)+evalCosh ty | FloatingDict <- floatingDict ty = cosh++evalTanh :: FloatingType a -> (a -> a)+evalTanh ty | FloatingDict <- floatingDict ty = tanh+ evalAsinh :: FloatingType a -> (a -> a) evalAsinh ty | FloatingDict <- floatingDict ty = asinh @@ -920,7 +1032,10 @@ evalAtan2 :: FloatingType a -> ((a, a) -> a) evalAtan2 ty | FloatingDict <- floatingDict ty = uncurry atan2 +evalIsNaN :: FloatingType a -> (a -> Bool)+evalIsNaN ty | FloatingDict <- floatingDict ty = isNaN + -- Methods of Num -- @@ -954,12 +1069,18 @@ evalRem :: IntegralType a -> ((a, a) -> a) evalRem ty | IntegralDict <- integralDict ty = uncurry rem +evalQuotRem :: IntegralType a -> ((a, a) -> (a, a))+evalQuotRem ty | IntegralDict <- integralDict ty = uncurry quotRem+ evalIDiv :: IntegralType a -> ((a, a) -> a) evalIDiv ty | IntegralDict <- integralDict ty = uncurry div  evalMod :: IntegralType a -> ((a, a) -> a) evalMod ty | IntegralDict <- integralDict ty = uncurry mod +evalDivMod :: IntegralType a -> ((a, a) -> (a, a))+evalDivMod ty | IntegralDict <- integralDict ty = uncurry divMod+ evalBAnd :: IntegralType a -> ((a, a) -> a) evalBAnd ty | IntegralDict <- integralDict ty = uncurry (.&.) @@ -984,6 +1105,38 @@ evalBRotateR :: IntegralType a -> ((a, Int) -> a) evalBRotateR ty | IntegralDict <- integralDict ty = uncurry rotateR +evalPopCount :: IntegralType a -> (a -> Int)+evalPopCount ty | IntegralDict <- integralDict ty = popCount++evalCountLeadingZeros :: IntegralType a -> (a -> Int)+#if __GLASGOW_HASKELL__ >= 710+evalCountLeadingZeros ty | IntegralDict <- integralDict ty = countLeadingZeros+#else+evalCountLeadingZeros ty | IntegralDict <- integralDict ty = clz+  where+    clz x = (w-1) - go (w-1)+      where+        go i | i < 0       = i  -- no bit set+             | testBit x i = i+             | otherwise   = go (i-1)+        w = finiteBitSize x+#endif++evalCountTrailingZeros :: IntegralType a -> (a -> Int)+#if __GLASGOW_HASKELL__ >= 710+evalCountTrailingZeros ty | IntegralDict <- integralDict ty = countTrailingZeros+#else+evalCountTrailingZeros ty | IntegralDict <- integralDict ty = ctz+  where+    ctz x = go 0+      where+        go i | i >= w      = i+             | testBit x i = i+             | otherwise   = go (i+1)+        w = finiteBitSize x+#endif++ evalFDiv :: FloatingType a -> ((a, a) -> a) evalFDiv ty | FloatingDict <- floatingDict ty = uncurry (/) @@ -991,7 +1144,6 @@ evalRecip ty | FloatingDict <- floatingDict ty = recip  - evalLt :: ScalarType a -> ((a, a) -> Bool) evalLt (NumScalarType (IntegralNumType ty)) | IntegralDict <- integralDict ty = uncurry (<) evalLt (NumScalarType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = uncurry (<)@@ -1031,4 +1183,458 @@ evalMin (NumScalarType (IntegralNumType ty)) | IntegralDict <- integralDict ty = uncurry min evalMin (NumScalarType (FloatingNumType ty)) | FloatingDict <- floatingDict ty = uncurry min evalMin (NonNumScalarType ty)                | NonNumDict   <- nonNumDict ty   = uncurry min+++{--+-- Sequence evaluation+-- ---------------++-- Position in sequence.+--+type SeqPos = Int++-- Configuration for sequence evaluation.+--+data SeqConfig = SeqConfig+  { chunkSize :: Int -- Allocation limit for a sequence in+                     -- words. Actual runtime allocation should be the+                     -- maximum of this size and the size of the+                     -- largest element in the sequence.+  }++-- Default sequence evaluation configuration for testing purposes.+--+defaultSeqConfig :: SeqConfig+defaultSeqConfig = SeqConfig { chunkSize = 2 }++type Chunk a = Vector' a++-- The empty chunk. O(1).+emptyChunk :: Arrays a => Chunk a+emptyChunk = empty'++-- Number of arrays in chunk. O(1).+--+clen :: Arrays a => Chunk a -> Int+clen = length'++elemsPerChunk :: SeqConfig -> Int -> Int+elemsPerChunk conf n+  | n < 1 = chunkSize conf+  | otherwise =+    let (a,b) = chunkSize conf `quotRem` n+    in a + signum b++-- Drop a number of arrays from a chunk. O(1). Note: Require keeping a+-- scan of element sizes.+--+cdrop :: Arrays a => Int -> Chunk a -> Chunk a+cdrop = drop' dropOp (fst . offsetsOp)++-- Get all the shapes of a chunk of arrays. O(1).+--+chunkShapes :: Chunk (Array sh a) -> Vector sh+chunkShapes = shapes'++-- Get all the elements of a chunk of arrays. O(1).+--+chunkElems :: Chunk (Array sh a) -> Vector a+chunkElems = elements'++-- Convert a vector to a chunk of scalars.+--+vec2Chunk :: Elt e => Vector e -> Chunk (Scalar e)+vec2Chunk = vec2Vec'++-- Convert a list of arrays to a chunk.+--+fromListChunk :: Arrays a => [a] -> Vector' a+fromListChunk = fromList' concatOp++-- Convert a chunk to a list of arrays.+--+toListChunk :: Arrays a => Vector' a -> [a]+toListChunk = toList' fetchAllOp++-- fmap for Chunk. O(n).+--   TODO: Use vectorised function.+mapChunk :: (Arrays a, Arrays b)+         => (a -> b)+         -> Chunk a -> Chunk b+mapChunk f c = fromListChunk $ map f (toListChunk c)++-- zipWith for Chunk. O(n).+--  TODO: Use vectorised function.+zipWithChunk :: (Arrays a, Arrays b, Arrays c)+             => (a -> b -> c)+             -> Chunk a -> Chunk b -> Chunk c+zipWithChunk f c1 c2 = fromListChunk $ zipWith f (toListChunk c1) (toListChunk c2)++-- A window on a sequence.+--+data Window a = Window+  { chunk :: Chunk a   -- Current allocated chunk.+  , wpos  :: SeqPos    -- Position of the window on the sequence, given+                       -- in number of elements.+  }++-- The initial empty window.+--+window0 :: Arrays a => Window a+window0 = Window { chunk = emptyChunk, wpos = 0 }++-- Index the given window by the given index on the sequence.+--+(!#) :: Arrays a => Window a -> SeqPos -> Chunk a+w !# i+  | j <- i - wpos w+  , j >= 0+  = cdrop j (chunk w)+  --+  | otherwise+  = error $ "Window indexed before position. wpos = " ++ show (wpos w) ++ " i = " ++ show i++-- Move the give window by supplying the next chunk.+--+moveWin :: Arrays a => Window a -> Chunk a -> Window a+moveWin w c = w { chunk = c+                , wpos = wpos w + clen (chunk w)+                }++-- A cursor on a sequence.+--+data Cursor senv a = Cursor+  { ref  :: Idx senv a -- Reference to the sequence.+  , cpos :: SeqPos     -- Position of the cursor on the sequence,+                       -- given in number of elements.+  }++-- Initial cursor.+--+cursor0 :: Idx senv a -> Cursor senv a+cursor0 x = Cursor { ref = x, cpos = 0 }++-- Advance cursor by a relative amount.+--+moveCursor :: Int -> Cursor senv a -> Cursor senv a+moveCursor k c = c { cpos = cpos c + k }++-- Valuation for an environment of sequence windows.+--+data Val' senv where+  Empty' :: Val' ()+  Push'  :: Val' senv -> Window t -> Val' (senv, t)++-- Projection of a window from a window valuation using a de Bruijn+-- index.+--+prj' :: Idx senv t -> Val' senv -> Window t+prj' ZeroIdx       (Push' _   v) = v+prj' (SuccIdx idx) (Push' val _) = prj' idx val+#if __GLASGOW_HASKELL__ < 800+prj' _             _             = $internalError "prj" "inconsistent valuation"+#endif++-- Projection of a chunk from a window valuation using a sequence+-- cursor.+--+prjChunk :: Arrays a => Cursor senv a -> Val' senv -> Chunk a+prjChunk c senv = prj' (ref c) senv !# cpos c++-- An executable sequence.+--+data ExecSeq senv arrs where+  ExecP :: Arrays a => Window a -> ExecP senv a -> ExecSeq (senv, a) arrs -> ExecSeq senv  arrs+  ExecC :: Arrays a =>             ExecC senv a ->                           ExecSeq senv  a+  ExecR :: Arrays a =>             Cursor senv a ->                          ExecSeq senv  [a]++-- An executable producer.+--+data ExecP senv a where+  ExecStreamIn :: Int+               -> [a]+               -> ExecP senv a++  ExecMap :: Arrays a+          => (Chunk a -> Chunk b)+          -> Cursor senv a+          -> ExecP senv b++  ExecZipWith :: (Arrays a, Arrays b)+              => (Chunk a -> Chunk b -> Chunk c)+              -> Cursor senv a+              -> Cursor senv b+              -> ExecP senv c++  -- Stream scan skeleton.+  ExecScan :: Arrays a+           => (s -> Chunk a -> (Chunk r, s)) -- Chunk scanner.+           -> s                              -- Accumulator (internal state).+           -> Cursor senv a                  -- Input stream.+           -> ExecP senv r++-- An executable consumer.+--+data ExecC senv a where++  -- Stream reduction skeleton.+  ExecFold :: Arrays a+           => (s -> Chunk a -> s) -- Chunk consumer function.+           -> (s -> r)            -- Finalizer function.+           -> s                   -- Accumulator (internal state).+           -> Cursor senv a       -- Input stream.+           -> ExecC senv r++  ExecStuple :: IsAtuple a+             => Atuple (ExecC senv) (TupleRepr a)+             -> ExecC senv a++minCursor :: ExecSeq senv a -> SeqPos+minCursor s = travS s 0+  where+    travS :: ExecSeq senv a -> Int -> SeqPos+    travS s i =+      case s of+        ExecP _ p s' -> travP p i `min` travS s' (i+1)+        ExecC   c    -> travC c i+        ExecR   _    -> maxBound++    k :: Cursor senv a -> Int -> SeqPos+    k c i+      | i == idxToInt (ref c) = cpos c+      | otherwise             = maxBound++    travP :: ExecP senv a -> Int -> SeqPos+    travP p i =+      case p of+        ExecStreamIn _ _ -> maxBound+        ExecMap _ c -> k c i+        ExecZipWith _ c1 c2 -> k c1 i `min` k c2 i+        ExecScan _ _ c -> k c i++    travT :: Atuple (ExecC senv) t -> Int -> SeqPos+    travT NilAtup        _ = maxBound+    travT (SnocAtup t c) i = travT t i `min` travC c i++    travC :: ExecC senv a -> Int -> SeqPos+    travC c i =+      case c of+        ExecFold _ _ _ cu -> k cu i+        ExecStuple t      -> travT t i+++evalDelayedSeq :: SeqConfig+               -> DelayedSeq arrs+               -> arrs+evalDelayedSeq cfg (DelayedSeq aenv s) | aenv' <- evalExtend aenv Empty+                                       = evalSeq cfg s aenv'++evalSeq :: forall aenv arrs.+            SeqConfig+         -> PreOpenSeq DelayedOpenAcc aenv () arrs+         -> Val aenv -> arrs+evalSeq conf s aenv = evalSeq' s+  where+    evalSeq' :: PreOpenSeq DelayedOpenAcc aenv senv arrs -> arrs+    evalSeq' (Producer _ s) = evalSeq' s+    evalSeq' (Consumer _)   = loop (initSeq aenv s)+    evalSeq' (Reify _)      = reify (initSeq aenv s)++    -- Initialize the producers and the accumulators of the consumers+    -- with the given array enviroment.+    initSeq :: forall senv arrs'.+                Val aenv+             -> PreOpenSeq DelayedOpenAcc aenv senv arrs'+             -> ExecSeq senv arrs'+    initSeq aenv s =+      case s of+        Producer   p s' -> ExecP window0 (initProducer p) (initSeq aenv s')+        Consumer   c    -> ExecC         (initConsumer c)+        Reify      ix   -> ExecR (cursor0 ix)++    -- Generate a list from the sequence.+    reify :: forall arrs. ExecSeq () [arrs]+          -> [arrs]+    reify s = case step s Empty' of+                (Just s', a) -> a ++ reify s'+                (Nothing, a) -> a++    -- Iterate the given sequence until it terminates.+    -- A sequence only terminates when one of the producers are exhausted.+    loop :: Arrays arrs+         => ExecSeq () arrs+         -> arrs+    loop s =+      case step' s of+        (Nothing, arrs) -> arrs+        (Just s', _)    -> loop s'++      where+        step' :: ExecSeq () arrs -> (Maybe (ExecSeq () arrs), arrs)+        step' s = step s Empty'++    -- One iteration of a sequence.+    step :: forall senv arrs'.+            ExecSeq senv arrs'+         -> Val' senv+         -> (Maybe (ExecSeq senv arrs'), arrs')+    step s senv =+      case s of+        ExecP w p s' ->+          let (c, mp')  = produce p senv+              finished  = 0 == clen (w !# minCursor s')+              w'        = if finished then moveWin w c else w+              (ms'', a) = step s' (senv `Push'` w')+          in case ms'' of+            Nothing  -> (Nothing, a)+            Just s'' | finished+                     , Just p' <- mp'+                     -> (Just (ExecP w' p' s''), a)+                     | not finished+                     -> (Just (ExecP w' p  s''), a)+                     | otherwise+                     -> (Nothing, a)+        ExecC   c    -> let (c', acc) = consume c senv+                        in (Just (ExecC c'), acc)+        ExecR ix     -> let c = prjChunk ix senv in (Just (ExecR (moveCursor (clen c) ix)), toListChunk c)++    evalA :: DelayedOpenAcc aenv a -> a+    evalA acc = evalOpenAcc acc aenv++    evalAF :: DelayedOpenAfun aenv f -> f+    evalAF f = evalOpenAfun f aenv++    evalE :: DelayedExp aenv t -> t+    evalE exp = evalPreExp evalOpenAcc exp aenv++    evalF :: DelayedFun aenv f -> f+    evalF fun = evalPreFun evalOpenAcc fun aenv++    initProducer :: forall a senv.+                    Producer DelayedOpenAcc aenv senv a+                 -> ExecP senv a+    initProducer p =+      case p of+        StreamIn arrs -> ExecStreamIn 1 arrs+        ToSeq sliceIndex slix (delayed -> Delayed sh ix _) ->+          let n   = R.size (R.sliceShape sliceIndex (fromElt sh))+              k   = elemsPerChunk conf n+          in ExecStreamIn k (toSeqOp sliceIndex slix (fromFunction sh ix))+        MapSeq     f x       -> ExecMap     (mapChunk (evalAF f)) (cursor0 x)+        ChunkedMapSeq f x    -> ExecMap     (evalAF f) (cursor0 x)+        ZipWithSeq f x y     -> ExecZipWith (zipWithChunk (evalAF f)) (cursor0 x) (cursor0 y)+        ScanSeq    f e x     -> ExecScan scanner (evalE e) (cursor0 x)+          where+            scanner a c =+              let v0 = chunkElems c+                  (v1, a') = scanl'Op (evalF f) a (delayArray v0)+              in (vec2Chunk v1, fromScalar a')++    initConsumer :: forall a senv.+                    Consumer DelayedOpenAcc aenv senv a+                 -> ExecC senv a+    initConsumer c =+      case c of+        FoldSeq f e x ->+          let f' = evalF f+              a0 = fromFunction (Z :. chunkSize conf) (const (evalE e))+              consumer v c = zipWith'Op f' (delayArray v) (delayArray (chunkElems c))+              finalizer = fold1Op f' . delayArray+          in ExecFold consumer finalizer a0 (cursor0 x)+        FoldSeqFlatten f acc x ->+          let f' = evalAF f+              a0 = evalA acc+              consumer a c = f' a (chunkShapes c) (chunkElems c)+          in ExecFold consumer id a0 (cursor0 x)+        Stuple t ->+          let initTup :: Atuple (Consumer DelayedOpenAcc aenv senv) t -> Atuple (ExecC senv) t+              initTup NilAtup        = NilAtup+              initTup (SnocAtup t c) = SnocAtup (initTup t) (initConsumer c)+          in ExecStuple (initTup t)++    delayed :: DelayedOpenAcc aenv (Array sh e) -> Delayed (Array sh e)+    delayed AST.Manifest{}  = $internalError "evalOpenAcc" "expected delayed array"+    delayed AST.Delayed{..} = Delayed (evalPreExp evalOpenAcc extentD aenv)+                                      (evalPreFun evalOpenAcc indexD aenv)+                                      (evalPreFun evalOpenAcc linearIndexD aenv)++produce :: Arrays a => ExecP senv a -> Val' senv -> (Chunk a, Maybe (ExecP senv a))+produce p senv =+  case p of+    ExecStreamIn k xs ->+      let (xs', xs'') = (take k xs, drop k xs)+          c           = fromListChunk xs'+          mp          = if null xs''+                        then Nothing+                        else Just (ExecStreamIn k xs'')+      in (c, mp)+    ExecMap f x ->+      let c = prjChunk x senv+      in (f c, Just $ ExecMap f (moveCursor (clen c) x))+    ExecZipWith f x y ->+      let c1 = prjChunk x senv+          c2 = prjChunk y senv+          k = clen c1 `min` clen c2+      in (f c1 c2, Just $ ExecZipWith f (moveCursor k x) (moveCursor k y))+    ExecScan scanner a x ->+      let c = prjChunk x senv+          (c', a') = scanner a c+          k = clen c+      in (c', Just $ ExecScan scanner a' (moveCursor k x))++consume :: forall senv a. ExecC senv a -> Val' senv -> (ExecC senv a, a)+consume c senv =+  case c of+    ExecFold f g acc x ->+      let c    = prjChunk x senv+          acc' = f acc c+      -- Even though we call g here, lazy evaluation should guarantee it is+      -- only ever called once.+      in (ExecFold f g acc' (moveCursor (clen c) x), g acc')+    ExecStuple t ->+      let consT :: Atuple (ExecC senv) t -> (Atuple (ExecC senv) t, t)+          consT NilAtup        = (NilAtup, ())+          consT (SnocAtup t c) | (c', acc) <- consume c senv+                               , (t', acc') <- consT t+                               = (SnocAtup t' c', (acc', acc))+          (t', acc) = consT t+      in (ExecStuple t', toAtuple acc)++evalExtend :: Extend DelayedOpenAcc aenv aenv' -> Val aenv -> Val aenv'+evalExtend BaseEnv aenv = aenv+evalExtend (PushEnv ext1 ext2) aenv | aenv' <- evalExtend ext1 aenv+                                    = Push aenv' (evalOpenAcc ext2 aenv')++delayArray :: Array sh e -> Delayed (Array sh e)+delayArray arr@(Array _ adata) = Delayed (shape arr) (arr!) (toElt . unsafeIndexArrayData adata)++fromScalar :: Scalar a -> a+fromScalar = (!Z)++concatOp :: forall e. Elt e => [Vector e] -> Vector e+concatOp = concatVectors++fetchAllOp :: (Shape sh, Elt e) => Segments sh -> Vector e -> [Array sh e]+fetchAllOp segs elts+  | (offsets, n) <- offsetsOp segs+  , (n ! Z) <= size (shape elts)+  = [fetch (segs ! (Z :. i)) (offsets ! (Z :. i)) | i <- [0 .. size (shape segs) - 1]]+  | otherwise = error $ "illegal argument to fetchAllOp"+  where+    fetch sh offset = fromFunction sh (\ ix -> elts ! (Z :. ((toIndex sh ix) + offset)))++dropOp :: Elt e => Int -> Vector e -> Vector e+dropOp i v   -- TODO+             --  * Implement using C-style pointer-plus.+             --    ; dropOp is used often (from prjChunk),+             --      so it ought to be efficient O(1).+  | n <- size (shape v)+  , i <= n+  , i >= 0+  = fromFunction (Z :. n - i) (\ (Z :. j) -> v ! (Z :. i + j))+  | otherwise = error $ "illegal argument to drop"++offsetsOp :: Shape sh => Segments sh -> (Vector Int, Scalar Int)+offsetsOp segs = scanl'Op (+) 0 $ delayArray (mapOp size (delayArray segs))+--} 
Data/Array/Accelerate/Language.hs view
@@ -1,932 +1,1238 @@-{-# LANGUAGE OverlappingInstances #-}   -- TLM: required by client code-{-# LANGUAGE TypeOperators        #-}-{-# OPTIONS -fno-warn-missing-methods #-}-{-# OPTIONS -fno-warn-orphans         #-}--- |--- Module      : Data.Array.Accelerate.Language--- Copyright   : [2008..2014] Manuel M T Chakravarty, Gabriele Keller---               [2009..2014] Trevor L. McDonell--- License     : BSD3------ Maintainer  : Manuel M T Chakravarty <chak@cse.unsw.edu.au>--- Stability   : experimental--- Portability : non-portable (GHC extensions)------ We use the dictionary view of overloaded operations (such as arithmetic and--- bit manipulation) to reify such expressions.  With non-overloaded--- operations (such as, the logical connectives) and partially overloaded--- operations (such as comparisons), we use the standard operator names with a--- \'*\' attached.  We keep the standard alphanumeric names as they can be--- easily qualified.-----module Data.Array.Accelerate.Language (--  -- * Array and scalar expressions-  Acc, Exp,                                 -- re-exporting from 'Smart'--  -- * Scalar introduction-  constant,                                 -- re-exporting from 'Smart'--  -- * Array construction-  use, unit, replicate, generate,--  -- * Shape manipulation-  reshape,--  -- * Extraction of subarrays-  slice,--  -- * Map-like functions-  map, zipWith,--  -- * Reductions-  fold, fold1, foldSeg, fold1Seg,--  -- * Scan functions-  scanl, scanl', scanl1, scanr, scanr', scanr1,--  -- * Permutations-  permute, backpermute,--  -- * Stencil operations-  stencil, stencil2,--  -- ** Stencil specification-  Boundary(..), Stencil,--  -- ** Common stencil types-  Stencil3, Stencil5, Stencil7, Stencil9,-  Stencil3x3, Stencil5x3, Stencil3x5, Stencil5x5,-  Stencil3x3x3, Stencil5x3x3, Stencil3x5x3, Stencil3x3x5, Stencil5x5x3, Stencil5x3x5,-  Stencil3x5x5, Stencil5x5x5,--  -- * Foreign functions-  foreignAcc, foreignAcc2, foreignAcc3,-  foreignExp, foreignExp2, foreignExp3,--  -- * Pipelining-  (>->),--  -- * Array-level flow-control-  acond, awhile,--  -- * Index construction and destruction-  indexHead, indexTail, toIndex, fromIndex,-  intersect,--  -- * Flow-control-  cond, while,--  -- * Array operations with a scalar result-  (!), (!!), shape, size, shapeSize,--  -- * Methods of H98 classes that we need to redefine as their signatures change-  (==*), (/=*), (<*), (<=*), (>*), (>=*),-  bit, setBit, clearBit, complementBit, testBit,-  shift,  shiftL,  shiftR,-  rotate, rotateL, rotateR,-  truncate, round, floor, ceiling,-  even, odd,--  -- * Standard functions that we need to redefine as their signatures change-  (&&*), (||*), not,--  -- * Conversions-  ord, chr, boolToInt, fromIntegral,--  -- * Constants-  ignore--  -- Instances of Bounded, Enum, Eq, Ord, Bits, Num, Real, Floating,-  -- Fractional, RealFrac, RealFloat--) where---- standard libraries-import Prelude ( Bounded, Enum, Num, Real, Integral, Floating, Fractional,-  RealFloat, RealFrac, Eq, Ord, Bool, Char, String, (.), ($), error )-import Data.Bits ( Bits((.&.), (.|.), xor, complement) )-import qualified Prelude                                as P-import Text.Printf---- friends-import Data.Array.Accelerate.Type-import Data.Array.Accelerate.Smart-import Data.Array.Accelerate.Array.Sugar                hiding ((!), ignore, shape, size, toIndex, fromIndex, intersect)-import qualified Data.Array.Accelerate.Array.Sugar      as Sugar----- Array introduction--- ---------------------- | Array inlet: makes an array available for processing using the Accelerate--- language.------ Depending upon the backend used to execute array computations, this may--- trigger (asynchronous) data transfer.----use :: Arrays arrays => arrays -> Acc arrays-use = Acc . Use---- | Scalar inlet: injects a scalar (or a tuple of scalars) into a singleton--- array for use in the Accelerate language.----unit :: Elt e => Exp e -> Acc (Scalar e)-unit = Acc . Unit---- | Replicate an array across one or more dimensions as specified by the--- /generalised/ array index provided as the first argument.------ For example, assuming 'arr' is a vector (one-dimensional array),------ > replicate (lift (Z :. (2::Int) :. All :. (3::Int))) arr------ yields a three dimensional array, where 'arr' is replicated twice across the--- first and three times across the third dimension.----replicate :: (Slice slix, Elt e)-          => Exp slix-          -> Acc (Array (SliceShape slix) e)-          -> Acc (Array (FullShape  slix) e)-replicate = Acc $$ Replicate---- | 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)------ Or, equivalently:------ > generate (constant (Z :. (3::Int))) (\_ -> 1.2)------ Finally, the following will create an array equivalent to '[1..10]':------ > generate (index1 10) $ \ ix ->--- >          let (Z :. i) = unlift ix--- >          in fromIntegral i------ [/NOTE:/]------ Using 'generate', it is possible to introduce nested data parallelism, which--- will cause the program to fail.------ If the index given by the scalar function is then used to dispatch further--- parallel work, whose result is returned into 'Exp' terms by array indexing--- operations such as (`!`) or `the`, the program will fail with the error:--- '.\/Data\/Array\/Accelerate\/Trafo\/Sharing.hs:447 (convertSharingExp): inconsistent valuation \@ shared \'Exp\' tree ...'.----generate :: (Shape ix, Elt a)-         => Exp ix-         -> (Exp ix -> Exp a)-         -> Acc (Array ix a)-generate = Acc $$ Generate---- Shape manipulation--- ---------------------- | Change the shape of an array without altering its contents. The 'size' of--- the source and result arrays must be identical.------ > precondition: size ix == size ix'----reshape :: (Shape ix, Shape ix', Elt e)-        => Exp ix-        -> Acc (Array ix' e)-        -> Acc (Array ix e)-reshape = Acc $$ Reshape---- Extraction of sub-arrays--- ---------------------------- | 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 (`All`s) in their entirety.------ This can be used to /cut out/ entire dimensions.  The opposite of--- `replicate`.  For example, if 'mat' is a two dimensional array, the--- following will select a specific row and yield a one dimensional--- result:------ > slice mat (lift (Z :. (2::Int) :. All))------ A fully specified index (with no `All`s) would return a single element (zero--- dimensional array).----slice :: (Slice slix, Elt e)-      => Acc (Array (FullShape slix) e)-      -> Exp slix-      -> Acc (Array (SliceShape slix) e)-slice = Acc $$ Slice---- Map-like functions--- ---------------------- | Apply the given function element-wise to the given array.----map :: (Shape ix, Elt a, Elt b)-    => (Exp a -> Exp b)-    -> Acc (Array ix a)-    -> Acc (Array ix b)-map = Acc $$ Map---- | 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 ix, Elt a, Elt b, Elt c)-        => (Exp a -> Exp b -> Exp c)-        -> Acc (Array ix a)-        -> Acc (Array ix b)-        -> Acc (Array ix c)-zipWith = Acc $$$ ZipWith---- Reductions--- -------------- | 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.----fold :: (Shape ix, Elt a)-     => (Exp a -> Exp a -> Exp a)-     -> Exp a-     -> Acc (Array (ix:.Int) a)-     -> Acc (Array ix a)-fold = Acc $$$ Fold---- | 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.----fold1 :: (Shape ix, Elt a)-      => (Exp a -> Exp a -> Exp a)-      -> Acc (Array (ix:.Int) a)-      -> Acc (Array ix a)-fold1 = Acc $$ Fold1---- | Segmented reduction along the innermost dimension.  Performs one individual--- reduction per segment of the source array.  These reductions proceed in--- parallel.------ The source array must have at least rank 1.  The 'Segments' array determines--- the lengths of the logical sub-arrays, each of which is folded separately.----foldSeg :: (Shape ix, Elt a, Elt i, IsIntegral i)-        => (Exp a -> Exp a -> Exp a)-        -> Exp a-        -> Acc (Array (ix:.Int) a)-        -> Acc (Segments i)-        -> Acc (Array (ix:.Int) a)-foldSeg = Acc $$$$ FoldSeg---- | Variant of 'foldSeg' that requires /all/ segments of the reduced array to--- be non-empty and doesn't need a default value.------ The source array must have at least rank 1. The 'Segments' array determines--- the lengths of the logical sub-arrays, each of which is folded separately.----fold1Seg :: (Shape ix, Elt a, Elt i, IsIntegral i)-         => (Exp a -> Exp a -> Exp a)-         -> Acc (Array (ix:.Int) a)-         -> Acc (Segments i)-         -> Acc (Array (ix:.Int) a)-fold1Seg = Acc $$$ Fold1Seg---- Scan functions--- ------------------ | Data.List style left-to-right scan, but with the additional restriction--- that the first argument needs to be an /associative/ function to enable an--- efficient parallel implementation. The initial value (second argument) may be--- arbitrary.----scanl :: Elt a-      => (Exp a -> Exp a -> Exp a)-      -> Exp a-      -> Acc (Vector a)-      -> Acc (Vector a)-scanl = Acc $$$ Scanl---- | Variant of 'scanl', where the final result of the reduction is returned--- separately. Denotationally, we have------ > scanl' f e arr = (init res, unit (res!len))--- >   where--- >     len = shape arr--- >     res = scanl f e arr----scanl' :: Elt a-       => (Exp a -> Exp a -> Exp a)-       -> Exp a-       -> Acc (Vector a)-       -> (Acc (Vector a), Acc (Scalar a))-scanl' = unatup2 . Acc $$$ Scanl'---- | Data.List style left-to-right scan without an initial value (aka inclusive--- scan).  Again, the first argument needs to be an /associative/ function.--- Denotationally, we have------ > scanl1 f e arr = tail (scanl f e arr)----scanl1 :: Elt a-       => (Exp a -> Exp a -> Exp a)-       -> Acc (Vector a)-       -> Acc (Vector a)-scanl1 = Acc $$ Scanl1---- | Right-to-left variant of 'scanl'.----scanr :: Elt a-      => (Exp a -> Exp a -> Exp a)-      -> Exp a-      -> Acc (Vector a)-      -> Acc (Vector a)-scanr = Acc $$$ Scanr---- | Right-to-left variant of 'scanl''.----scanr' :: Elt a-       => (Exp a -> Exp a -> Exp a)-       -> Exp a-       -> Acc (Vector a)-       -> (Acc (Vector a), Acc (Scalar a))-scanr' = unatup2 . Acc $$$ Scanr'---- | Right-to-left variant of 'scanl1'.----scanr1 :: Elt a-       => (Exp a -> Exp a -> Exp a)-       -> Acc (Vector a)-       -> Acc (Vector a)-scanr1 = Acc $$ Scanr1---- Permutations--- ---------------- | Forward permutation specified by an index mapping. 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.----permute :: (Shape ix, Shape ix', Elt a)-        => (Exp a -> Exp a -> Exp a)    -- ^combination function-        -> Acc (Array ix' a)            -- ^array of default values-        -> (Exp ix -> Exp ix')          -- ^permutation-        -> Acc (Array ix  a)            -- ^array to be permuted-        -> Acc (Array ix' a)-permute = Acc $$$$ Permute---- | Backward permutation specified by an index mapping from the destination--- array specifying which element of the source array to read.----backpermute :: (Shape ix, Shape ix', Elt a)-            => Exp ix'                  -- ^shape of the result array-            -> (Exp ix' -> Exp ix)      -- ^permutation-            -> Acc (Array ix  a)        -- ^source array-            -> Acc (Array ix' a)-backpermute = Acc $$$ Backpermute---- Stencil operations--- ---------------------- Common stencil types------- DIM1 stencil type-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)---- DIM2 stencil type-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)---- DIM3 stencil type-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)----- |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 in each dimension---  and have an extent of at least three in each dimensions — 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 :: (Shape ix, Elt a, Elt b, Stencil ix a stencil)-        => (stencil -> Exp b)                 -- ^stencil function-        -> Boundary a                         -- ^boundary condition-        -> Acc (Array ix a)                   -- ^source array-        -> Acc (Array ix b)                   -- ^destination array-stencil = Acc $$$ Stencil---- | Map a binary stencil of an array.  The extent of the resulting array is the--- intersection of the extents of the two source arrays.----stencil2 :: (Shape ix, Elt a, Elt b, Elt c,-             Stencil ix a stencil1,-             Stencil ix b stencil2)-        => (stencil1 -> stencil2 -> Exp c)    -- ^binary stencil function-        -> Boundary a                         -- ^boundary condition #1-        -> Acc (Array ix a)                   -- ^source array #1-        -> Boundary b                         -- ^boundary condition #2-        -> Acc (Array ix b)                   -- ^source array #2-        -> Acc (Array ix c)                   -- ^destination array-stencil2 = Acc $$$$$ Stencil2---- Foreign function calling--- ---------------------------- | Call a foreign function. The form the function takes is dependent on the backend being used.--- The arguments are passed as either a single array or as a tuple of arrays. In addition a pure--- Accelerate version of the function needs to be provided to support backends other than the one--- being targeted.-foreignAcc :: (Arrays acc, Arrays res, Foreign ff)-           => ff acc res-           -> (Acc acc -> Acc res)-           -> Acc acc-           -> Acc res-foreignAcc = Acc $$$ Aforeign---- | Call a foreign function with foreign implementations for two different backends.-foreignAcc2 :: (Arrays acc, Arrays res, Foreign ff1, Foreign ff2)-            => ff1 acc res-            -> ff2 acc res-            -> (Acc acc -> Acc res)-            -> Acc acc-            -> Acc res-foreignAcc2 ff1 = Acc $$$ Aforeign ff1 $$ Acc $$$ Aforeign---- | Call a foreign function with foreign implementations for three different backends.-foreignAcc3 :: (Arrays acc, Arrays res, Foreign ff1, Foreign ff2, Foreign ff3)-            => ff1 acc res-            -> ff2 acc res-            -> ff3 acc res-            -> (Acc acc -> Acc res)-            -> Acc acc-            -> Acc res-foreignAcc3 ff1 ff2 = Acc $$$ Aforeign ff1 $$ Acc $$$ Aforeign ff2 $$ Acc $$$ Aforeign---- | Call a foreign expression function. The form the function takes is dependent on the--- backend being used. The arguments are passed as either a single scalar element or as a--- tuple of elements. In addition a pure Accelerate version of the function needs to be--- provided to support backends other than the one being targeted.-foreignExp :: (Elt e, Elt res, Foreign ff)-           => ff e res-           -> (Exp e -> Exp res)-           -> Exp e-           -> Exp res-foreignExp = Exp $$$ Foreign---- | Call a foreign function with foreign implementations for two different backends.-foreignExp2 :: (Elt e, Elt res, Foreign ff1, Foreign ff2)-            => ff1 e res-            -> ff2 e res-            -> (Exp e -> Exp res)-            -> Exp e-            -> Exp res-foreignExp2 ff1 = Exp $$$ Foreign ff1 $$ Exp $$$ Foreign---- | Call a foreign function with foreign implementations for three different backends.-foreignExp3 :: (Elt e, Elt res, Foreign ff1, Foreign ff2, Foreign ff3)-            => ff1 e res-            -> ff2 e res-            -> ff3 e res-            -> (Exp e -> Exp res)-            -> Exp e-            -> Exp res-foreignExp3 ff1 ff2 = Exp $$$ Foreign ff1 $$ Exp $$$ Foreign ff2 $$ Exp $$$ Foreign----- Composition of array computations--- ------------------------------------- | Pipelining of two array computations.------ Denotationally, we have------ > (acc1 >-> acc2) arrs = let tmp = acc1 arrs in acc2 tmp----infixl 1 >->-(>->) :: (Arrays a, Arrays b, Arrays c) => (Acc a -> Acc b) -> (Acc b -> Acc c) -> (Acc a -> Acc c)-(>->) = Acc $$$ Pipe----- Flow control constructs--- --------------------------- | An array-level if-then-else construct.----acond :: Arrays a-      => Exp Bool               -- ^ if-condition-      -> Acc a                  -- ^ then-array-      -> Acc a                  -- ^ else-array-      -> Acc a-acond = Acc $$$ Acond---- | An array-level while construct----awhile :: Arrays a-       => (Acc a -> Acc (Scalar Bool))-       -> (Acc a -> Acc a)-       -> Acc a-       -> Acc a-awhile = Acc $$$ Awhile----- Shapes and indices--- ---------------------- | Get the outermost dimension of a shape----indexHead :: Slice sh => Exp (sh :. Int) -> Exp Int-indexHead = Exp . IndexHead---- | Get all but the outermost element of a shape----indexTail :: Slice sh => Exp (sh :. Int) -> Exp sh-indexTail = Exp . IndexTail---- | Map a multi-dimensional index into a linear, row-major representation of an--- array. The first argument is the array shape, the second is the index.----toIndex :: Shape sh => Exp sh -> Exp sh -> Exp Int-toIndex = Exp $$ ToIndex---- | Inverse of 'toIndex'----fromIndex :: Shape sh => Exp sh -> Exp Int -> Exp sh-fromIndex = Exp $$ FromIndex---- | Intersection of two shapes----intersect :: Shape sh => Exp sh -> Exp sh -> Exp sh-intersect = Exp $$ Intersect----- Flow-control--- ---------------- | A scalar-level if-then-else construct.----cond :: Elt t-     => Exp Bool                -- ^ condition-     -> Exp t                   -- ^ then-expression-     -> Exp t                   -- ^ else-expression-     -> Exp t-cond = Exp $$$ Cond---- | While construct. Continue to apply the given function, starting with the--- initial value, until the test function evaluates to true.----while :: Elt e-      => (Exp e -> Exp Bool)-      -> (Exp e -> Exp e)-      -> Exp e-      -> Exp e-while = Exp $$$ While----- Array operations with a scalar result--- ----------------------------------------- |Expression form that extracts a scalar from an array----infixl 9 !-(!) :: (Shape ix, Elt e) => Acc (Array ix e) -> Exp ix -> Exp e-(!) = Exp $$ Index---- |Expression form that extracts a scalar from an array at a linear index----infixl 9 !!-(!!) :: (Shape ix, Elt e) => Acc (Array ix e) -> Exp Int -> Exp e-(!!) = Exp $$ LinearIndex---- |Expression form that yields the shape of an array----shape :: (Shape ix, Elt e) => Acc (Array ix e) -> Exp ix-shape = Exp . Shape---- |Expression form that yields the size of an array----size :: (Shape ix, Elt e) => Acc (Array ix e) -> Exp Int-size = shapeSize . shape---- |The total number of elements in an array of the given 'Shape'----shapeSize :: Shape ix => Exp ix -> Exp Int-shapeSize = Exp . ShapeSize----- Instances of all relevant H98 classes--- ---------------------------------------preludeError :: String -> String -> a-preludeError x y = error (printf "Prelude.%s applied to EDSL types: use %s instead" x y)--instance (Elt t, IsBounded t) => Bounded (Exp t) where-  minBound = mkMinBound-  maxBound = mkMaxBound--instance (Elt t, IsScalar t) => Enum (Exp t)---  succ = mkSucc---  pred = mkPred-  -- FIXME: ops--instance (Elt t, IsScalar t) => Prelude.Eq (Exp t) where-  -- FIXME: instance makes no sense with standard signatures-  (==)  = preludeError "Eq.==" "(==*)"-  (/=)  = preludeError "Eq./=" "(/=*)"--instance (Elt t, IsScalar t) => Prelude.Ord (Exp t) where-  -- FIXME: instance makes no sense with standard signatures-  min           = mkMin-  max           = mkMax-  ---  compare       = error "Prelude.Ord.compare applied to EDSL types"-  (<)           = preludeError "Ord.<"  "(<*)"-  (<=)          = preludeError "Ord.<=" "(<=*)"-  (>)           = preludeError "Ord.>"  "(>*)"-  (>=)          = preludeError "Ord.>=" "(>=*)"--instance (Elt t, IsNum t, IsIntegral t) => Bits (Exp t) where-  (.&.)      = mkBAnd-  (.|.)      = mkBOr-  xor        = mkBXor-  complement = mkBNot-  -- FIXME: argh, the rest have fixed types in their signatures----- | @'shift' x i@ shifts @x@ left by @i@ bits if @i@ is positive, or right by--- @-i@ bits otherwise. Right shifts perform sign extension on signed number--- types; i.e. they fill the top bits with 1 if the @x@ is negative and with 0--- otherwise.----shift :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t-shift  x i-  = cond (i ==* 0) x-  $ cond (i <*  0) (x `shiftR` (-i))-                   (x `shiftL` i)---- | Shift the argument left by the specified number of bits--- (which must be non-negative).----shiftL :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t-shiftL = mkBShiftL---- | Shift the first argument right by the specified number of bits. The result--- is undefined for negative shift amounts and shift amounts greater or equal to--- the 'bitSize'.------ Right shifts perform sign extension on signed number types; i.e. they fill--- the top bits with 1 if the @x@ is negative and with 0 otherwise.----shiftR :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t-shiftR = mkBShiftR---- | @'rotate' x i@ rotates @x@ left by @i@ bits if @i@ is positive, or right by--- @-i@ bits otherwise.----rotate :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t-rotate x i-  = cond (i ==* 0) x-  $ cond (i <*  0) (x `rotateR` (-i))-                   (x `rotateL` i)---- | Rotate the argument left by the specified number of bits--- (which must be non-negative).----rotateL :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t-rotateL = mkBRotateL---- | Rotate the argument right by the specified number of bits--- (which must be non-negative).----rotateR :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t-rotateR = mkBRotateR---- | @bit i@ is a value with the @i@th bit set and all other bits clear----bit :: (Elt t, IsIntegral t) => Exp Int -> Exp t-bit x = 1 `shiftL` x---- | @x \`setBit\` i@ is the same as @x .|. bit i@----setBit :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t-x `setBit` i = x .|. bit i---- | @x \`clearBit\` i@ is the same as @x .&. complement (bit i)@----clearBit :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t-x `clearBit` i = x .&. complement (bit i)---- | @x \`complementBit\` i@ is the same as @x \`xor\` bit i@----complementBit :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t-x `complementBit` i = x `xor` bit i---- | Return 'True' if the @n@th bit of the argument is 1----testBit :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp Bool-x `testBit` i       = (x .&. bit i) /=* 0---instance (Elt t, IsNum t) => Num (Exp t) where-  (+)         = mkAdd-  (-)         = mkSub-  (*)         = mkMul-  negate      = mkNeg-  abs         = mkAbs-  signum      = mkSig-  fromInteger = constant . P.fromInteger--instance (Elt t, IsNum t) => Real (Exp t)-  -- FIXME: Why did we include this class?  We won't need `toRational' until-  --   we support rational numbers in AP computations.--instance (Elt t, IsIntegral t) => Integral (Exp t) where-  quot = mkQuot-  rem  = mkRem-  div  = mkIDiv-  mod  = mkMod---  quotRem =---  divMod  =---  toInteger =  -- makes no sense--instance (Elt t, IsFloating t) => Floating (Exp t) where-  pi      = mkPi-  sin     = mkSin-  cos     = mkCos-  tan     = mkTan-  asin    = mkAsin-  acos    = mkAcos-  atan    = mkAtan-  asinh   = mkAsinh-  acosh   = mkAcosh-  atanh   = mkAtanh-  exp     = mkExpFloating-  sqrt    = mkSqrt-  log     = mkLog-  (**)    = mkFPow-  logBase = mkLogBase--instance (Elt t, IsFloating t) => Fractional (Exp t) where-  (/)          = mkFDiv-  recip        = mkRecip-  fromRational = constant . P.fromRational--instance (Elt t, IsFloating t) => RealFrac (Exp t)-  -- FIXME: add other ops--instance (Elt t, IsFloating t) => RealFloat (Exp t) where-  atan2 = mkAtan2-  -- FIXME: add other ops----- Methods from H98 classes, where we need other signatures--- ----------------------------------------------------------infix 4 ==*, /=*, <*, <=*, >*, >=*---- |Equality lifted into Accelerate expressions.----(==*) :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp Bool-(==*) = mkEq---- |Inequality lifted into Accelerate expressions.----(/=*) :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp Bool-(/=*) = mkNEq---- compare :: a -> a -> Ordering  -- we have no enumerations at the moment--- compare = ...---- |Smaller-than lifted into Accelerate expressions.----(<*) :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp Bool-(<*)  = mkLt---- |Greater-or-equal lifted into Accelerate expressions.----(>=*) :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp Bool-(>=*) = mkGtEq---- |Greater-than lifted into Accelerate expressions.----(>*) :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp Bool-(>*)  = mkGt---- |Smaller-or-equal lifted into Accelerate expressions.----(<=*) :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp Bool-(<=*) = mkLtEq---- Conversions from the RealFrac class------- | @truncate x@ returns the integer nearest @x@ between zero and @x@.----truncate :: (Elt a, Elt b, IsFloating a, IsIntegral b) => Exp a -> Exp b-truncate = mkTruncate---- | @round x@ returns the nearest integer to @x@, or the even integer if @x@ is--- equidistant between two integers.----round :: (Elt a, Elt b, IsFloating a, IsIntegral b) => Exp a -> Exp b-round = mkRound---- | @floor x@ returns the greatest integer not greater than @x@.----floor :: (Elt a, Elt b, IsFloating a, IsIntegral b) => Exp a -> Exp b-floor = mkFloor---- | @ceiling x@ returns the least integer not less than @x@.----ceiling :: (Elt a, Elt b, IsFloating a, IsIntegral b) => Exp a -> Exp b-ceiling = mkCeiling---- | return if the integer is even----even :: (Elt a, IsIntegral a) => Exp a -> Exp Bool-even x = x .&. 1 ==* 0---- | return if the integer is odd----odd :: (Elt a, IsIntegral a) => Exp a -> Exp Bool-odd x = x .&. 1 ==* 1----- Non-overloaded standard functions, where we need other signatures--- --------------------------------------------------------------------- |Conjunction----infixr 3 &&*-(&&*) :: Exp Bool -> Exp Bool -> Exp Bool-(&&*) = mkLAnd---- |Disjunction----infixr 2 ||*-(||*) :: Exp Bool -> Exp Bool -> Exp Bool-(||*) = mkLOr---- |Negation----not :: Exp Bool -> Exp Bool-not = mkLNot----- Conversions--- --------------- |Convert a character to an 'Int'.----ord :: Exp Char -> Exp Int-ord = mkOrd---- |Convert an 'Int' into a character.----chr :: Exp Int -> Exp Char-chr = mkChr---- |Convert a Boolean value to an 'Int', where 'False' turns into '0' and 'True'--- into '1'.----boolToInt :: Exp Bool -> Exp Int-boolToInt = mkBoolToInt---- |General coercion from integral types----fromIntegral :: (Elt a, Elt b, IsIntegral a, IsNum b) => Exp a -> Exp b-fromIntegral = mkFromIntegral----- Constants--- ------------- |Magic value identifying elements that are ignored in a forward permutation.--- Note that this currently does not work for singleton arrays.----ignore :: Shape ix => Exp ix+{-# LANGUAGE ConstraintKinds     #-}+{-# LANGUAGE FlexibleContexts    #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies        #-}+{-# LANGUAGE TypeOperators       #-}+{-# LANGUAGE ViewPatterns        #-}+-- |+-- Module      : Data.Array.Accelerate.Language+-- Copyright   : [2008..2017] Manuel M T Chakravarty, Gabriele Keller+--               [2009..2017] Trevor L. McDonell+--               [2014..2014] Frederik M. Madsen+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- We use the dictionary view of overloaded operations (such as arithmetic and+-- bit manipulation) to reify such expressions.  With non-overloaded+-- operations (such as, the logical connectives) and partially overloaded+-- operations (such as comparisons), we use the standard operator names with a+-- \'*\' attached.  We keep the standard alphanumeric names as they can be+-- easily qualified.+--++module Data.Array.Accelerate.Language (++  -- * Array and scalar expressions+  Acc, Exp,                                 -- re-exporting from 'Smart'++  -- * Scalar introduction+  constant,                                 -- re-exporting from 'Smart'++  -- * Array construction+  use, unit, replicate, generate,++  -- * Shape manipulation+  reshape,++  -- * Extraction of sub-arrays+  slice,++  -- * Map-like functions+  map, zipWith,++  -- -- * Sequence collection+  -- collect,++  -- -- * Sequence producers+  -- streamIn, toSeq,++  -- -- * Sequence transducers+  -- mapSeq, zipWithSeq, scanSeq,++  -- -- * Sequence consumers+  -- foldSeq, foldSeqFlatten,++  -- * Reductions+  fold, fold1, foldSeg, fold1Seg,++  -- * Scan functions+  scanl, scanl', scanl1, scanr, scanr', scanr1,++  -- * Permutations+  permute, backpermute,++  -- * Stencil operations+  stencil, stencil2,++  -- ** Stencil specification+  Boundary(..), Stencil,++  -- ** Common stencil types+  Stencil3, Stencil5, Stencil7, Stencil9,+  Stencil3x3, Stencil5x3, Stencil3x5, Stencil5x5,+  Stencil3x3x3, Stencil5x3x3, Stencil3x5x3, Stencil3x3x5, Stencil5x5x3, Stencil5x3x5,+  Stencil3x5x5, Stencil5x5x5,++  -- * Foreign functions+  foreignAcc,+  foreignExp,++  -- * Pipelining+  (>->),++  -- * Index construction and destruction+  indexHead, indexTail, toIndex, fromIndex,+  intersect, union,++  -- * Flow-control+  acond, awhile,+  cond,  while,++  -- * Array operations with a scalar result+  (!), (!!), shape, size, shapeSize,++  -- * Numeric functions+  subtract, even, odd, gcd, lcm, (^), (^^),++  -- * Conversions+  ord, chr, boolToInt, bitcast,++  -- * Constants+  ignore++) where++-- friends+import Data.Array.Accelerate.Array.Sugar                hiding ((!), ignore, shape, size, toIndex, fromIndex, intersect, union)+import Data.Array.Accelerate.Classes+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Type+import qualified Data.Array.Accelerate.Array.Sugar      as Sugar++-- standard libraries+import Prelude                                          ( ($), (.) )+++-- Array introduction+-- ------------------++-- | 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+use = Acc . Use++-- | Construct a singleton (one element) array from a scalar value (or tuple of+-- scalar values).+--+unit :: Elt e => Exp e -> Acc (Scalar e)+unit = Acc . Unit++-- | 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)+replicate = Acc $$ Replicate++-- | 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]+--+-- [/NOTE:/]+--+-- Using 'generate', it is possible to introduce nested data parallelism, which+-- will cause the program to fail.+--+-- If the index given by the scalar function is then used to dispatch further+-- parallel work, whose result is returned into 'Exp' terms by array indexing+-- operations such as ('!') or 'Data.Array.Accelerate.Prelude.the', the program+-- will fail with the error:+-- '.\/Data\/Array\/Accelerate\/Trafo\/Sharing.hs:447 (convertSharingExp): inconsistent valuation \@ shared \'Exp\' tree ...'.+--+generate+    :: (Shape sh, Elt a)+    => Exp sh+    -> (Exp sh -> Exp a)+    -> Acc (Array sh a)+generate = Acc $$ Generate++-- Shape manipulation+-- ------------------++-- | 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)+reshape = Acc $$ Reshape++-- Extraction of sub-arrays+-- ------------------------++-- | 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 (`All`s) 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 'All's) 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)+slice = Acc $$ Slice++-- Map-like functions+-- ------------------++-- | 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)+map = Acc $$ Map++-- | 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)+zipWith = Acc $$$ ZipWith++-- Reductions+-- ----------++-- | 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 'Data.Array.Accelerate.Data.Fold.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)+fold = Acc $$$ Fold++-- | 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)+fold1 = Acc $$ Fold1++-- | 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)+foldSeg = Acc $$$$ FoldSeg++-- | 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)+fold1Seg = Acc $$$ Fold1Seg++-- Scan functions+-- --------------++-- | 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)+scanl = Acc $$$ Scanl++-- | 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))+scanl' = unatup2 . Acc $$$ Scanl'++-- | 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)+scanl1 = Acc $$ Scanl1++-- | 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)+scanr = Acc $$$ Scanr++-- | 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))+scanr' = unatup2 . Acc $$$ Scanr'++-- | 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)+scanr1 = Acc $$ Scanr1++-- Permutations+-- ------------++-- | 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]+--+-- [/Note:/]+--+-- Regarding array fusion:+--+--   1. The 'permute' operation will always be evaluated; it can not be fused+--      into a later step.+--+--   2. Since the index permutation function might not cover all positions in+--      the output array (the function is not surjective), the array of default+--      values must be evaluated. However, other operations may fuse into this.+--+--   3. The array of source values can fuse into the permutation operation.+--+permute+    :: (Shape sh, Shape sh', Elt a)+    => (Exp a -> Exp a -> Exp a)        -- ^ combination function+    -> Acc (Array sh' a)                -- ^ array of default values+    -> (Exp sh -> Exp sh')              -- ^ index permutation function+    -> Acc (Array sh  a)                -- ^ array of source values to be permuted+    -> Acc (Array sh' a)+permute = Acc $$$$ Permute++-- | 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+-- 'Data.Array.Accelerate.Prelude.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'                          -- ^ shape of the result array+    -> (Exp sh' -> Exp sh)              -- ^ index permutation function+    -> Acc (Array sh  a)                -- ^ source array+    -> Acc (Array sh' a)+backpermute = Acc $$$ Backpermute+++-- Stencil operations+-- ------------------++-- Common stencil types+--++-- DIM1 stencil type+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)++-- DIM2 stencil type+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)++-- DIM3 stencil type+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)+++-- | 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+-- <https://en.wikipedia.org/wiki/Gaussian_blur 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)                     -- ^ stencil function+    -> Boundary a                             -- ^ boundary condition+    -> Acc (Array sh a)                       -- ^ source array+    -> Acc (Array sh b)                       -- ^ destination array+stencil = Acc $$$ Stencil++-- | 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)        -- ^ binary stencil function+    -> Boundary a                             -- ^ boundary condition #1+    -> Acc (Array sh a)                       -- ^ source array #1+    -> Boundary b                             -- ^ boundary condition #2+    -> Acc (Array sh b)                       -- ^ source array #2+    -> Acc (Array sh c)                       -- ^ destination array+stencil2 = Acc $$$$$ Stencil2+++{--+-- Sequence operations+-- ------------------++-- Common sequence types+--++streamIn :: Arrays a+         => [a]+         -> Seq [a]+streamIn arrs = Seq (StreamIn arrs)++-- | Convert the given array to a sequence by dividing the array up into subarrays.+-- The first argument captures how to the division should be performed. The+-- presence of `All` in the division descriptor indicates that elements in the+-- corresponding dimension should be retained in the subarrays, whereas `Split`+-- indicates that the input array should divided along this dimension.+--+toSeq :: (Division slsix, Elt a)+      => slsix+      -> Acc (Array (FullShape (DivisionSlice slsix)) a)+      -> Seq [Array (SliceShape (DivisionSlice slsix)) a]+toSeq spec acc = Seq (ToSeq spec acc)++-- | Apply the given array function element-wise to the given sequence.+--+mapSeq :: (Arrays a, Arrays b)+       => (Acc a -> Acc b)+       -> Seq [a]+       -> Seq [b]+mapSeq = Seq $$ MapSeq++-- | Apply the given binary function element-wise to the two sequences.  The length of the resulting+-- sequence is the minumum of the lengths of the two source sequences.+--+zipWithSeq :: (Arrays a, Arrays b, Arrays c)+           => (Acc a -> Acc b -> Acc c)+           -> Seq [a]+           -> Seq [b]+           -> Seq [c]+zipWithSeq = Seq $$$ ZipWithSeq++-- | scanSeq (+) a0 x seq. Scan a sequence x by combining each+-- element using the given binary operation (+). (+) must be+-- associative:+--+--   Forall a b c. (a + b) + c = a + (b + c),+--+-- and a0 must be the identity element for (+):+--+--   Forall a. a0 + a = a = a + a0.+--+scanSeq :: Elt a+        => (Exp a -> Exp a -> Exp a)+        -> Exp a+        -> Seq [Scalar a]+        -> Seq [Scalar a]+scanSeq = Seq $$$ ScanSeq++-- | foldSeq (+) a0 x seq. Fold a sequence x by combining each+-- element using the given binary operation (+). (+) must be+-- associative:+--+--   Forall a b c. (a + b) + c = a + (b + c),+--+-- and a0 must be the identity element for (+):+--+--   Forall a. a0 + a = a = a + a0.+--+foldSeq :: Elt a+        => (Exp a -> Exp a -> Exp a)+        -> Exp a+        -> Seq [Scalar a]+        -> Seq (Scalar a)+foldSeq = Seq $$$ FoldSeq++-- | foldSeqFlatten f a0 x seq. A specialized version of+-- FoldSeqAct where reduction with the companion operator+-- corresponds to flattening. f must be semi-associative, with vecotor+-- append (++) as the companion operator:+--+--   Forall b sh1 a1 sh2 a2.+--     f (f b sh1 a1) sh2 a2 = f b (sh1 ++ sh2) (a1 ++ a2).+--+-- It is common to ignore the shape vectors, yielding the usual+-- semi-associativity law:+--+--   f b a _ = b + a,+--+-- for some (+) satisfying:+--+--   Forall b a1 a2. (b + a1) + a2 = b + (a1 ++ a2).+--+foldSeqFlatten :: (Arrays a, Shape jx, Elt b)+               => (Acc a -> Acc (Vector jx) -> Acc (Vector b) -> Acc a)+               -> Acc a+               -> Seq [Array jx b]+               -> Seq a+foldSeqFlatten = Seq $$$ FoldSeqFlatten++collect :: Arrays arrs => Seq arrs -> Acc arrs+collect = Acc . Collect+--}++-- Foreign function calling+-- ------------------------++-- | 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 <https://hackage.haskell.org/package/accelerate-fft accelerate-fft> package.+--+foreignAcc+    :: (Arrays as, Arrays bs, Foreign asm)+    => asm (as -> bs)+    -> (Acc as -> Acc bs)+    -> Acc as+    -> Acc bs+foreignAcc = Acc $$$ Aforeign++-- | 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+foreignExp = Exp $$$ Foreign+++-- Composition of array computations+-- ---------------------------------++-- | 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+--+infixl 1 >->+(>->) :: (Arrays a, Arrays b, Arrays c) => (Acc a -> Acc b) -> (Acc b -> Acc c) -> (Acc a -> Acc c)+(>->) = Acc $$$ Pipe+++-- Flow control constructs+-- -----------------------++-- | An array-level if-then-else construct.+--+acond :: Arrays a+      => Exp Bool               -- ^ if-condition+      -> Acc a                  -- ^ then-array+      -> Acc a                  -- ^ else-array+      -> Acc a+acond = Acc $$$ Acond++-- | 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))    -- ^ keep evaluating while this returns 'True'+       -> (Acc a -> Acc a)                -- ^ function to apply+       -> Acc a                           -- ^ initial value+       -> Acc a+awhile = Acc $$$ Awhile+++-- Shapes and indices+-- ------------------++-- | Get the innermost dimension of a shape+--+indexHead :: (Slice sh, Elt a) => Exp (sh :. a) -> Exp a+indexHead = Exp . IndexHead++-- | Get all but the innermost element of a shape+--+indexTail :: (Slice sh, Elt a) => Exp (sh :. a) -> Exp sh+indexTail = Exp . IndexTail++-- | Map a multi-dimensional index into a linear, row-major representation of an+-- array.+--+toIndex+    :: Shape sh+    => Exp sh                     -- ^ extent of the array+    -> Exp sh                     -- ^ index to remap+    -> Exp Int+toIndex = Exp $$ ToIndex++-- | Inverse of 'toIndex'+--+fromIndex :: Shape sh => Exp sh -> Exp Int -> Exp sh+fromIndex = Exp $$ FromIndex++-- | Intersection of two shapes+--+intersect :: Shape sh => Exp sh -> Exp sh -> Exp sh+intersect = Exp $$ Intersect++-- | Union of two shapes+--+union :: Shape sh => Exp sh -> Exp sh -> Exp sh+union = Exp $$ Union+++-- Flow-control+-- ------------++-- | A scalar-level if-then-else construct.+--+cond :: Elt t+     => Exp Bool                -- ^ condition+     -> Exp t                   -- ^ then-expression+     -> Exp t                   -- ^ else-expression+     -> Exp t+cond = Exp $$$ Cond++-- | 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)    -- ^ keep evaluating while this returns 'True'+      -> (Exp e -> Exp e)       -- ^ function to apply+      -> Exp e                  -- ^ initial value+      -> Exp e+while = Exp $$$ While+++-- Array operations with a scalar result+-- -------------------------------------++-- | Multidimensional array indexing. Extract the value from an array at the+-- specified zero-based index.+--+-- >>> 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+--+infixl 9 !+(!) :: (Shape sh, Elt e) => Acc (Array sh e) -> Exp sh -> Exp e+(!) = Exp $$ Index++-- | 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+--+infixl 9 !!+(!!) :: (Shape sh, Elt e) => Acc (Array sh e) -> Exp Int -> Exp e+(!!) = Exp $$ LinearIndex++-- | Extract the shape (extent) of an array.+--+shape :: (Shape sh, Elt e) => Acc (Array sh e) -> Exp sh+shape = Exp . Shape++-- | The number of elements in the array+--+size :: (Shape sh, Elt e) => Acc (Array sh e) -> Exp Int+size = shapeSize . shape++-- | The number of elements that would be held by an array of the given shape.+--+shapeSize :: Shape sh => Exp sh -> Exp Int+shapeSize = Exp . ShapeSize+++-- Numeric functions+-- -----------------++-- | 'subtract' is the same as @'flip' ('-')@.+--+subtract :: Num a => Exp a -> Exp a -> Exp a+subtract x y = y - x++-- | Determine if a number is even+--+even :: Integral a => Exp a -> Exp Bool+even n = n `rem` 2 == 0++-- | Determine if a number is odd+--+odd :: Integral a => Exp a -> Exp Bool+odd n = n `rem` 2 /= 0++-- | @'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+gcd x y = gcd' (abs x) (abs y)+  where+    gcd' :: Integral a => Exp a -> Exp a -> Exp a+    gcd' u v =+      let (r,_) = untup2+                $ while (\(untup2 -> (_,b)) -> b /= 0)+                        (\(untup2 -> (a,b)) -> tup2 (b, a `rem` b))+                        (tup2 (u,v))+      in r+++-- | @'lcm' x y@ is the smallest positive integer that both @x@ and @y@ divide.+--+lcm :: Integral a => Exp a -> Exp a -> Exp a+lcm x y+  = cond (x == 0 || y == 0) 0+  $ abs ((x `quot` (gcd x y)) * y)+++-- | Raise a number to a non-negative integral power+--+infixr 8 ^+(^) :: forall a b. (Num a, Integral b) => Exp a -> Exp b -> Exp a+x0 ^ y0 = cond (y0 <= 0) 1 (f x0 y0)+  where+    f :: Exp a -> Exp b -> Exp a+    f x y =+      let (x',y') = untup2+                  $ while (\(untup2 -> (_,v)) -> even v)+                          (\(untup2 -> (u,v)) -> tup2 (u * u, v `quot` 2))+                          (tup2 (x, y))+      in+      cond (y' == 1) x' (g (x'*x') ((y'-1) `quot` 2) x')++    g :: Exp a -> Exp b -> Exp a -> Exp a+    g x y z =+      let (x',_,z') = untup3+                    $ while (\(untup3 -> (_,v,_)) -> v /= 1)+                            (\(untup3 -> (u,v,w)) ->+                              cond (even v) (tup3 (u*u, v     `quot` 2, w))+                                            (tup3 (u*u, (v-1) `quot` 2, w*u)))+                            (tup3 (x,y,z))+      in+      x' * z'++-- | Raise a number to an integral power+--+infixr 8 ^^+(^^) :: (Fractional a, Integral b) => Exp a -> Exp b -> Exp a+x ^^ n+  = cond (n >= 0)+  {- then -} (x ^ n)+  {- else -} (recip (x ^ (negate n)))+++-- Conversions+-- -----------++-- |Convert a character to an 'Int'.+--+ord :: Exp Char -> Exp Int+ord = mkOrd++-- |Convert an 'Int' into a character.+--+chr :: Exp Int -> Exp Char+chr = mkChr++-- |Convert a Boolean value to an 'Int', where 'False' turns into '0' and 'True'+-- into '1'.+--+boolToInt :: Exp Bool -> Exp Int+boolToInt = mkBoolToInt++-- |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+bitcast = mkBitcast+++-- Constants+-- ---------++-- |Magic value identifying elements that are ignored in a forward permutation.+--+ignore :: Shape sh => Exp sh ignore = constant Sugar.ignore 
+ Data/Array/Accelerate/Lifetime.hs view
@@ -0,0 +1,156 @@+{-# LANGUAGE CPP           #-}+{-# LANGUAGE MagicHash     #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE UnboxedTuples #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.Lifetime+-- Copyright   : [2015..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell, Robert Clifton-Everest+-- License     : BSD3+--+-- Maintainer  : Robert Clifton-Everest <robertce@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--++module Data.Array.Accelerate.Lifetime (++  Lifetime(..),+  newLifetime, withLifetime, touchLifetime,+  addFinalizer, finalize, mkWeak, mkWeakPtr,++  unsafeGetValue,++) where++import Data.Function                ( on )+import Data.IORef                   ( mkWeakIORef, atomicModifyIORef' )+import Prelude++import GHC.Base                     ( touch#, IO(..))+import GHC.IORef                    ( IORef(.. ), newIORef )+import GHC.Prim                     ( mkWeak# )+import GHC.STRef                    ( STRef(..) )+import GHC.Weak                     ( Weak(..) )+++-- | A lifetime represents a value with attached finalizers. This is similar to+-- the functionality provided by "System.Mem.Weak", but has the following+-- stronger properties:+--+-- * Unless explicitly forced, finalizers will not fire until after the+--   'Lifetime' has become unreachable, where \"reachability\" is the same as+--   defined in "System.Mem.Weak". That is to say, there is no issue with+--   creating a 'Lifetime' for a non-primitve type and finalizers firing while+--   an object is still reachable.+--+-- * Finalizers are fired sequentially in reverse of the order in which they+--   were attached.+--+-- * As the finalizers are attached to the 'Lifetime' and not the underlying+--   value, there is no danger in storing it UNPACKED as part of another+--   structure.+--+type LTF        = IORef [IO ()]+data Lifetime a = Lifetime {-# UNPACK #-} !LTF+                           {-# UNPACK #-} !(Weak LTF)+                           {- LAZY -}     a++instance Eq a => Eq (Lifetime a) where+  (==) = (==) `on` unsafeGetValue++-- | Construct a new 'Lifetime' from the given value.+--+newLifetime :: a -> IO (Lifetime a)+newLifetime a = do+  ref  <- newIORef []+  weak <- mkWeakIORef ref (finalizer ref)+  return $! Lifetime ref weak a++-- | This provides a way of looking at the value inside a 'Lifetime'. The+-- supplied function is executed immediately and the 'Lifetime' kept alive+-- throughout its execution. It is important to not let the value /leak/ outside+-- the function, either by returning it or by lazy IO.+--+withLifetime :: Lifetime a -> (a -> IO b) -> IO b+withLifetime (Lifetime ref _ a) f = do+  r <- f a+  touchIORef ref+  return r++-- | Ensure that the lifetime is alive at the given place in a sequence of IO+-- actions. Does not force the payload.+--+touchLifetime :: Lifetime a -> IO ()+touchLifetime (Lifetime ref _ _) = touchIORef ref++-- | Attaches a finalizer to a 'Lifetime'. Like in "System.Mem.Weak", there is+-- no guarantee that the finalizers will eventually run. If they do run,+-- they will be executed in the order in which they were supplied.+--+addFinalizer :: Lifetime a -> IO () -> IO ()+addFinalizer (Lifetime ref _ _) f =+  atomicModifyIORef' ref (\fs -> (f:fs,()))++-- | Causes any finalizers associated with the given lifetime to be run+-- immediately on the calling thread.+--+-- Because the finalizer is run on the calling thread. Care should be taken to+-- ensure that the it does not try to acquire any locks the calling thread might+-- already possess. This can result in deadlock and is in contrast to calling+-- 'System.Mem.Weak.finalize' on 'System.Mem.Weak.Weak'.+--+finalize :: Lifetime a -> IO ()+finalize (Lifetime ref _ _) = finalizer ref++-- | Create a weak pointer from a 'Lifetime' to the supplied value.+--+-- Because weak pointers have their own concept of finalizers, it is important+-- to note these behaviours:+--+-- * Calling 'System.Mem.Weak.finalize' causes the finalizers attached to the+--   lifetime to be scheduled, and run in the correct order, but does not+--   guarantee they will execute on the calling thread.+--+-- * If 'deRefWeak' returns Nothing, there is no guarantee that the finalizers+--   have already run.+--+mkWeak :: Lifetime k -> v -> IO (Weak v)+mkWeak (Lifetime ref@(IORef (STRef r#)) _ _) v = go (finalizer ref)+  where+#if __GLASGOW_HASKELL__ >= 800+    go (IO f)  =  -- GHC-8.x+#else+    go f       =  -- GHC-7.x+#endif+      IO $ \s -> case mkWeak# r# v f s of+                   (# s', w# #) -> (# s', Weak w# #)++-- A specialised version of 'mkWeak' where the key and value are the same+-- 'Lifetime'.+--+-- > mkWeakPtr key = mkWeak key key+--+mkWeakPtr :: Lifetime a -> IO (Weak (Lifetime a))+mkWeakPtr l = mkWeak l l++-- | Retrieve the value from a lifetime. This is unsafe because, unless the+-- 'Lifetime' is still reachable, the finalizers may fire, potentially+-- invalidating the value.+--+unsafeGetValue :: Lifetime a -> a+unsafeGetValue (Lifetime _ _ a) = a++-- The actual finalizer for 'Lifetime's.+--+finalizer :: IORef [IO ()] -> IO ()+finalizer ref = do+  fins <- atomicModifyIORef' ref ([],)+  sequence_ fins++-- Touch an 'IORef', ensuring that it is alive at this point in a sequence of IO+-- actions.+--+touchIORef :: IORef a -> IO ()+touchIORef r = IO $ \s -> case touch# r s of s' -> (# s', () #)+
+ Data/Array/Accelerate/Lift.hs view
@@ -0,0 +1,747 @@+{-# LANGUAGE CPP                   #-}+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies          #-}+{-# LANGUAGE TypeOperators         #-}+#if __GLASGOW_HASKELL__ <= 708+{-# LANGUAGE OverlappingInstances  #-}+{-# OPTIONS_GHC -fno-warn-unrecognised-pragmas #-}+#endif+-- |+-- Module      : Data.Array.Accelerate.Lift+-- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- Lifting and lowering surface expressions through constructors.+--++module Data.Array.Accelerate.Lift (++  -- * Lifting and unlifting+  Lift(..), Unlift(..),++  lift1, lift2, lift3,+  ilift1, ilift2, ilift3,++) where++import Data.Array.Accelerate.Array.Sugar+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Type+++-- |Lift a unary function into 'Exp'.+--+lift1 :: (Unlift Exp a, Lift Exp b)+      => (a -> b)+      -> Exp (Plain a)+      -> Exp (Plain b)+lift1 f = lift . f . unlift++-- |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)+lift2 f x y = lift $ f (unlift x) (unlift y)++-- |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)+lift3 f x y z = lift $ f (unlift x) (unlift y) (unlift z)++-- |Lift a unary function to a computation over rank-1 indices.+--+ilift1 :: (Exp Int -> Exp Int) -> Exp DIM1 -> Exp DIM1+ilift1 f = lift1 (\(Z:.i) -> Z :. f i)++-- |Lift a binary function to a computation over rank-1 indices.+--+ilift2 :: (Exp Int -> Exp Int -> Exp Int) -> Exp DIM1 -> Exp DIM1 -> Exp DIM1+ilift2 f = lift2 (\(Z:.i) (Z:.j) -> Z :. f i j)++-- |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+ilift3 f = lift3 (\(Z:.i) (Z:.j) (Z:.k) -> Z :. f i j k)++++-- | The class of types @e@ which can be lifted into @c@.+class Lift c e where+  -- | An associated-type (i.e. a type-level function) that strips all+  --   instances of surface type constructors @c@ from the input type @e@.+  --+  --   For example, the tuple types @(Exp Int, Int)@ and @(Int, Exp+  --   Int)@ have the same \"Plain\" representation.  That is, the+  --   following type equality holds:+  --+  --    @Plain (Exp Int, Int) ~ (Int,Int) ~ Plain (Int, Exp Int)@+  type 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 :: e -> c (Plain e)++-- | A limited subset of types which can be lifted, can also be unlifted.+class Lift c e => Unlift c e where++  -- | 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 :: c (Plain e) -> e+++-- identity instances++instance Lift Exp (Exp e) where+  type Plain (Exp e) = e+  lift = id++instance Unlift Exp (Exp e) where+  unlift = id++instance Lift Acc (Acc a) where+  type Plain (Acc a) = a+  lift = id++instance Unlift Acc (Acc a) where+  unlift = id++-- instance Lift Seq (Seq a) where+--   type Plain (Seq a) = a+--   lift = id++-- instance Unlift Seq (Seq a) where+--   unlift = id+++-- instances for indices++instance Lift Exp () where+  type Plain () = ()+  lift _ = Exp $ Tuple NilTup++instance Unlift Exp () where+  unlift _ = ()++instance Lift Exp Z where+  type Plain Z = Z+  lift _ = Exp $ IndexNil++instance Unlift Exp Z where+  unlift _ = Z++instance (Slice (Plain ix), Lift Exp ix) => Lift Exp (ix :. Int) where+  type Plain (ix :. Int) = Plain ix :. Int+  lift (ix:.i) = Exp $ IndexCons (lift ix) (Exp $ Const i)++instance (Slice (Plain ix), Lift Exp ix) => Lift Exp (ix :. All) where+  type Plain (ix :. All) = Plain ix :. All+  lift (ix:.i) = Exp $ IndexCons (lift ix) (Exp $ Const i)++instance (Elt e, Slice (Plain ix), Lift Exp ix) => Lift Exp (ix :. Exp e) where+  type Plain (ix :. Exp e) = Plain ix :. e+  lift (ix:.i) = Exp $ IndexCons (lift ix) i++instance {-# OVERLAPPABLE #-} (Elt e, Slice (Plain ix), Unlift Exp ix) => Unlift Exp (ix :. Exp e) where+  unlift e = unlift (Exp $ IndexTail e) :. Exp (IndexHead e)++instance {-# OVERLAPPABLE #-} (Elt e, Slice ix) => Unlift Exp (Exp ix :. Exp e) where+  unlift e = (Exp $ IndexTail e) :. Exp (IndexHead e)++instance Shape sh => Lift Exp (Any sh) where+ type Plain (Any sh) = Any sh+ lift Any = Exp $ IndexAny++-- instances for numeric types++instance Lift Exp Int where+  type Plain Int = Int+  lift = Exp . Const++instance Lift Exp Int8 where+  type Plain Int8 = Int8+  lift = Exp . Const++instance Lift Exp Int16 where+  type Plain Int16 = Int16+  lift = Exp . Const++instance Lift Exp Int32 where+  type Plain Int32 = Int32+  lift = Exp . Const++instance Lift Exp Int64 where+  type Plain Int64 = Int64+  lift = Exp . Const++instance Lift Exp Word where+  type Plain Word = Word+  lift = Exp . Const++instance Lift Exp Word8 where+  type Plain Word8 = Word8+  lift = Exp . Const++instance Lift Exp Word16 where+  type Plain Word16 = Word16+  lift = Exp . Const++instance Lift Exp Word32 where+  type Plain Word32 = Word32+  lift = Exp . Const++instance Lift Exp Word64 where+  type Plain Word64 = Word64+  lift = Exp . Const++instance Lift Exp CShort where+  type Plain CShort = CShort+  lift = Exp . Const++instance Lift Exp CUShort where+  type Plain CUShort = CUShort+  lift = Exp . Const++instance Lift Exp CInt where+  type Plain CInt = CInt+  lift = Exp . Const++instance Lift Exp CUInt where+  type Plain CUInt = CUInt+  lift = Exp . Const++instance Lift Exp CLong where+  type Plain CLong = CLong+  lift = Exp . Const++instance Lift Exp CULong where+  type Plain CULong = CULong+  lift = Exp . Const++instance Lift Exp CLLong where+  type Plain CLLong = CLLong+  lift = Exp . Const++instance Lift Exp CULLong where+  type Plain CULLong = CULLong+  lift = Exp . Const++instance Lift Exp Float where+  type Plain Float = Float+  lift = Exp . Const++instance Lift Exp Double where+  type Plain Double = Double+  lift = Exp . Const++instance Lift Exp CFloat where+  type Plain CFloat = CFloat+  lift = Exp . Const++instance Lift Exp CDouble where+  type Plain CDouble = CDouble+  lift = Exp . Const++instance Lift Exp Bool where+  type Plain Bool = Bool+  lift = Exp . Const++instance Lift Exp Char where+  type Plain Char = Char+  lift = Exp . Const++instance Lift Exp CChar where+  type Plain CChar = CChar+  lift = Exp . Const++instance Lift Exp CSChar where+  type Plain CSChar = CSChar+  lift = Exp . Const++instance Lift Exp CUChar where+  type Plain CUChar = CUChar+  lift = Exp . Const++-- Instances for tuples++instance (Lift Exp a, Lift Exp b, Elt (Plain a), Elt (Plain b)) => Lift Exp (a, b) where+  type Plain (a, b) = (Plain a, Plain b)+  lift (a, b) = tup2 (lift a, lift b)++instance (Elt a, Elt b) => Unlift Exp (Exp a, Exp b) where+  unlift = untup2++instance (Lift Exp a, Lift Exp b, Lift Exp c,+          Elt (Plain a), Elt (Plain b), Elt (Plain c))+  => Lift Exp (a, b, c) where+  type Plain (a, b, c) = (Plain a, Plain b, Plain c)+  lift (a, b, c) = tup3 (lift a, lift b, lift c)++instance (Elt a, Elt b, Elt c) => Unlift Exp (Exp a, Exp b, Exp c) where+  unlift = untup3++instance (Lift Exp a, Lift Exp b, Lift Exp c, Lift Exp d,+          Elt (Plain a), Elt (Plain b), Elt (Plain c), Elt (Plain d))+  => Lift Exp (a, b, c, d) where+  type Plain (a, b, c, d) = (Plain a, Plain b, Plain c, Plain d)+  lift (a, b, c, d) = tup4 (lift a, lift b, lift c, lift d)++instance (Elt a, Elt b, Elt c, Elt d) => Unlift Exp (Exp a, Exp b, Exp c, Exp d) where+  unlift = untup4++instance (Lift Exp a, Lift Exp b, Lift Exp c, Lift Exp d, Lift Exp e,+          Elt (Plain a), Elt (Plain b), Elt (Plain c), Elt (Plain d), Elt (Plain e))+  => Lift Exp (a, b, c, d, e) where+  type Plain (a, b, c, d, e) = (Plain a, Plain b, Plain c, Plain d, Plain e)+  lift (a, b, c, d, e) = tup5 (lift a, lift b, lift c, lift d, lift e)++instance (Elt a, Elt b, Elt c, Elt d, Elt e)+  => Unlift Exp (Exp a, Exp b, Exp c, Exp d, Exp e) where+  unlift = untup5++instance (Lift Exp a, Lift Exp b, Lift Exp c, Lift Exp d, Lift Exp e, Lift Exp f,+          Elt (Plain a), Elt (Plain b), Elt (Plain c), Elt (Plain d), Elt (Plain e), Elt (Plain f))+  => Lift Exp (a, b, c, d, e, f) where+  type Plain (a, b, c, d, e, f) = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f)+  lift (a, b, c, d, e, f) = tup6 (lift a, lift b, lift c, lift d, lift e, lift f)++instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f)+  => Unlift Exp (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f) where+  unlift = untup6++instance (Lift Exp a, Lift Exp b, Lift Exp c, Lift Exp d, Lift Exp e, Lift Exp f, Lift Exp g,+          Elt (Plain a), Elt (Plain b), Elt (Plain c), Elt (Plain d), Elt (Plain e), Elt (Plain f),+          Elt (Plain g))+  => Lift Exp (a, b, c, d, e, f, g) where+  type Plain (a, b, c, d, e, f, g) = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g)+  lift (a, b, c, d, e, f, g) = tup7 (lift a, lift b, lift c, lift d, lift e, lift f, lift g)++instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g)+  => Unlift Exp (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g) where+  unlift = untup7++instance (Lift Exp a, Lift Exp b, Lift Exp c, Lift Exp d, Lift Exp e, Lift Exp f, Lift Exp g, Lift Exp h,+          Elt (Plain a), Elt (Plain b), Elt (Plain c), Elt (Plain d), Elt (Plain e), Elt (Plain f),+          Elt (Plain g), Elt (Plain h))+  => Lift Exp (a, b, c, d, e, f, g, h) where+  type Plain (a, b, c, d, e, f, g, h)+    = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h)+  lift (a, b, c, d, e, f, g, h)+    = tup8 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h)++instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h)+  => Unlift Exp (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h) where+  unlift = untup8++instance (Lift Exp a, Lift Exp b, Lift Exp c, Lift Exp d, Lift Exp e,+          Lift Exp f, Lift Exp g, Lift Exp h, Lift Exp i,+          Elt (Plain a), Elt (Plain b), Elt (Plain c), Elt (Plain d), Elt (Plain e),+          Elt (Plain f), Elt (Plain g), Elt (Plain h), Elt (Plain i))+  => Lift Exp (a, b, c, d, e, f, g, h, i) where+  type Plain (a, b, c, d, e, f, g, h, i)+    = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i)+  lift (a, b, c, d, e, f, g, h, i)+    = tup9 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i)++instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i)+  => Unlift Exp (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i) where+  unlift = untup9++instance (Lift Exp a, Lift Exp b, Lift Exp c, Lift Exp d, Lift Exp e,+          Lift Exp f, Lift Exp g, Lift Exp h, Lift Exp i, Lift Exp j,+          Elt (Plain a), Elt (Plain b), Elt (Plain c), Elt (Plain d), Elt (Plain e),+          Elt (Plain f), Elt (Plain g), Elt (Plain h), Elt (Plain i), Elt (Plain j))+  => Lift Exp (a, b, c, d, e, f, g, h, i, j) where+  type Plain (a, b, c, d, e, f, g, h, i, j)+    = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j)+  lift (a, b, c, d, e, f, g, h, i, j)+    = tup10 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j)++instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j)+  => Unlift Exp (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j) where+  unlift = untup10++instance (Lift Exp a, Lift Exp b, Lift Exp c, Lift Exp d, Lift Exp e,+          Lift Exp f, Lift Exp g, Lift Exp h, Lift Exp i, Lift Exp j, Lift Exp k,+          Elt (Plain a), Elt (Plain b), Elt (Plain c), Elt (Plain d), Elt (Plain e),+          Elt (Plain f), Elt (Plain g), Elt (Plain h), Elt (Plain i), Elt (Plain j), Elt (Plain k))+  => Lift Exp (a, b, c, d, e, f, g, h, i, j, k) where+  type Plain (a, b, c, d, e, f, g, h, i, j, k)+    = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j, Plain k)+  lift (a, b, c, d, e, f, g, h, i, j, k)+    = tup11 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j, lift k)++instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k)+  => Unlift Exp (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j, Exp k) where+  unlift = untup11++instance (Lift Exp a, Lift Exp b, Lift Exp c, Lift Exp d, Lift Exp e, Lift Exp f,+          Lift Exp g, Lift Exp h, Lift Exp i, Lift Exp j, Lift Exp k, Lift Exp l,+          Elt (Plain a), Elt (Plain b), Elt (Plain c), Elt (Plain d), Elt (Plain e), Elt (Plain f),+          Elt (Plain g), Elt (Plain h), Elt (Plain i), Elt (Plain j), Elt (Plain k), Elt (Plain l))+  => Lift Exp (a, b, c, d, e, f, g, h, i, j, k, l) where+  type Plain (a, b, c, d, e, f, g, h, i, j, k, l)+    = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j, Plain k, Plain l)+  lift (a, b, c, d, e, f, g, h, i, j, k, l)+    = tup12 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j, lift k, lift l)++instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l)+  => Unlift Exp (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j, Exp k, Exp l) where+  unlift = untup12++instance (Lift Exp a, Lift Exp b, Lift Exp c, Lift Exp d, Lift Exp e, Lift Exp f,+          Lift Exp g, Lift Exp h, Lift Exp i, Lift Exp j, Lift Exp k, Lift Exp l, Lift Exp m,+          Elt (Plain a), Elt (Plain b), Elt (Plain c), Elt (Plain d), Elt (Plain e), Elt (Plain f),+          Elt (Plain g), Elt (Plain h), Elt (Plain i), Elt (Plain j), Elt (Plain k), Elt (Plain l), Elt (Plain m))+  => Lift Exp (a, b, c, d, e, f, g, h, i, j, k, l, m) where+  type Plain (a, b, c, d, e, f, g, h, i, j, k, l, m)+    = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j, Plain k, Plain l, Plain m)+  lift (a, b, c, d, e, f, g, h, i, j, k, l, m)+    = tup13 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j, lift k, lift l, lift m)++instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l, Elt m)+  => Unlift Exp (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j, Exp k, Exp l, Exp m) where+  unlift = untup13++instance (Lift Exp a, Lift Exp b, Lift Exp c, Lift Exp d, Lift Exp e, Lift Exp f, Lift Exp g,+          Lift Exp h, Lift Exp i, Lift Exp j, Lift Exp k, Lift Exp l, Lift Exp m, Lift Exp n,+          Elt (Plain a), Elt (Plain b), Elt (Plain c), Elt (Plain d), Elt (Plain e), Elt (Plain f), Elt (Plain g),+          Elt (Plain h), Elt (Plain i), Elt (Plain j), Elt (Plain k), Elt (Plain l), Elt (Plain m), Elt (Plain n))+  => Lift Exp (a, b, c, d, e, f, g, h, i, j, k, l, m, n) where+  type Plain (a, b, c, d, e, f, g, h, i, j, k, l, m, n)+    = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j, Plain k, Plain l, Plain m, Plain n)+  lift (a, b, c, d, e, f, g, h, i, j, k, l, m, n)+    = tup14 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j, lift k, lift l, lift m, lift n)++instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l, Elt m, Elt n)+  => Unlift Exp (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j, Exp k, Exp l, Exp m, Exp n) where+  unlift = untup14++instance (Lift Exp a, Lift Exp b, Lift Exp c, Lift Exp d, Lift Exp e, Lift Exp f, Lift Exp g,+          Lift Exp h, Lift Exp i, Lift Exp j, Lift Exp k, Lift Exp l, Lift Exp m, Lift Exp n, Lift Exp o,+          Elt (Plain a), Elt (Plain b), Elt (Plain c), Elt (Plain d), Elt (Plain e), Elt (Plain f), Elt (Plain g),+          Elt (Plain h), Elt (Plain i), Elt (Plain j), Elt (Plain k), Elt (Plain l), Elt (Plain m), Elt (Plain n), Elt (Plain o))+  => Lift Exp (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) where+  type Plain (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)+    = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j, Plain k, Plain l, Plain m, Plain n, Plain o)+  lift (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)+    = tup15 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j, lift k, lift l, lift m, lift n, lift o)++instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l, Elt m, Elt n, Elt o)+  => Unlift Exp (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j, Exp k, Exp l, Exp m, Exp n, Exp o) where+  unlift = untup15++++-- Instances for Arrays class++--instance Lift Acc () where+--  type Plain () = ()+--  lift _ = Acc (Atuple NilAtup)++instance (Shape sh, Elt e) => Lift Acc (Array sh e) where+  type Plain (Array sh e) = Array sh e+  lift = Acc . Use++instance (Lift Acc a, Lift Acc b, Arrays (Plain a), Arrays (Plain b)) => Lift Acc (a, b) where+  type Plain (a, b) = (Plain a, Plain b)+  lift (a, b) = atup2 (lift a, lift b)++instance (Arrays a, Arrays b) => Unlift Acc (Acc a, Acc b) where+  unlift = unatup2++instance (Lift Acc a, Lift Acc b, Lift Acc c,+          Arrays (Plain a), Arrays (Plain b), Arrays (Plain c))+  => Lift Acc (a, b, c) where+  type Plain (a, b, c) = (Plain a, Plain b, Plain c)+  lift (a, b, c) = atup3 (lift a, lift b, lift c)++instance (Arrays a, Arrays b, Arrays c) => Unlift Acc (Acc a, Acc b, Acc c) where+  unlift = unatup3++instance (Lift Acc a, Lift Acc b, Lift Acc c, Lift Acc d,+          Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d))+  => Lift Acc (a, b, c, d) where+  type Plain (a, b, c, d) = (Plain a, Plain b, Plain c, Plain d)+  lift (a, b, c, d) = atup4 (lift a, lift b, lift c, lift d)++instance (Arrays a, Arrays b, Arrays c, Arrays d) => Unlift Acc (Acc a, Acc b, Acc c, Acc d) where+  unlift = unatup4++instance (Lift Acc a, Lift Acc b, Lift Acc c, Lift Acc d, Lift Acc e,+          Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e))+  => Lift Acc (a, b, c, d, e) where+  type Plain (a, b, c, d, e) = (Plain a, Plain b, Plain c, Plain d, Plain e)+  lift (a, b, c, d, e) = atup5 (lift a, lift b, lift c, lift d, lift e)++instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e)+  => Unlift Acc (Acc a, Acc b, Acc c, Acc d, Acc e) where+  unlift = unatup5++instance (Lift Acc a, Lift Acc b, Lift Acc c, Lift Acc d, Lift Acc e, Lift Acc f,+          Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e), Arrays (Plain f))+  => Lift Acc (a, b, c, d, e, f) where+  type Plain (a, b, c, d, e, f) = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f)+  lift (a, b, c, d, e, f) = atup6 (lift a, lift b, lift c, lift d, lift e, lift f)++instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f)+  => Unlift Acc (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f) where+  unlift = unatup6++instance (Lift Acc a, Lift Acc b, Lift Acc c, Lift Acc d, Lift Acc e, Lift Acc f, Lift Acc g,+          Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e), Arrays (Plain f),+          Arrays (Plain g))+  => Lift Acc (a, b, c, d, e, f, g) where+  type Plain (a, b, c, d, e, f, g) = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g)+  lift (a, b, c, d, e, f, g) = atup7 (lift a, lift b, lift c, lift d, lift e, lift f, lift g)++instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g)+  => Unlift Acc (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g) where+  unlift = unatup7++instance (Lift Acc a, Lift Acc b, Lift Acc c, Lift Acc d, Lift Acc e, Lift Acc f, Lift Acc g, Lift Acc h,+          Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e), Arrays (Plain f),+          Arrays (Plain g), Arrays (Plain h))+  => Lift Acc (a, b, c, d, e, f, g, h) where+  type Plain (a, b, c, d, e, f, g, h)+    = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h)+  lift (a, b, c, d, e, f, g, h)+    = atup8 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h)++instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h)+  => Unlift Acc (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h) where+  unlift = unatup8++instance (Lift Acc a, Lift Acc b, Lift Acc c, Lift Acc d, Lift Acc e,+          Lift Acc f, Lift Acc g, Lift Acc h, Lift Acc i,+          Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e),+          Arrays (Plain f), Arrays (Plain g), Arrays (Plain h), Arrays (Plain i))+  => Lift Acc (a, b, c, d, e, f, g, h, i) where+  type Plain (a, b, c, d, e, f, g, h, i)+    = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i)+  lift (a, b, c, d, e, f, g, h, i)+    = atup9 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i)++instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i)+  => Unlift Acc (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i) where+  unlift = unatup9++instance (Lift Acc a, Lift Acc b, Lift Acc c, Lift Acc d, Lift Acc e,+          Lift Acc f, Lift Acc g, Lift Acc h, Lift Acc i, Lift Acc j,+          Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e),+          Arrays (Plain f), Arrays (Plain g), Arrays (Plain h), Arrays (Plain i), Arrays (Plain j))+  => Lift Acc (a, b, c, d, e, f, g, h, i, j) where+  type Plain (a, b, c, d, e, f, g, h, i, j)+    = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j)+  lift (a, b, c, d, e, f, g, h, i, j)+    = atup10 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j)++instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j)+  => Unlift Acc (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j) where+  unlift = unatup10++instance (Lift Acc a, Lift Acc b, Lift Acc c, Lift Acc d, Lift Acc e,+          Lift Acc f, Lift Acc g, Lift Acc h, Lift Acc i, Lift Acc j, Lift Acc k,+          Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e),+          Arrays (Plain f), Arrays (Plain g), Arrays (Plain h), Arrays (Plain i), Arrays (Plain j), Arrays (Plain k))+  => Lift Acc (a, b, c, d, e, f, g, h, i, j, k) where+  type Plain (a, b, c, d, e, f, g, h, i, j, k)+    = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j, Plain k)+  lift (a, b, c, d, e, f, g, h, i, j, k)+    = atup11 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j, lift k)++instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k)+  => Unlift Acc (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j, Acc k) where+  unlift = unatup11++instance (Lift Acc a, Lift Acc b, Lift Acc c, Lift Acc d, Lift Acc e, Lift Acc f,+          Lift Acc g, Lift Acc h, Lift Acc i, Lift Acc j, Lift Acc k, Lift Acc l,+          Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e), Arrays (Plain f),+          Arrays (Plain g), Arrays (Plain h), Arrays (Plain i), Arrays (Plain j), Arrays (Plain k), Arrays (Plain l))+  => Lift Acc (a, b, c, d, e, f, g, h, i, j, k, l) where+  type Plain (a, b, c, d, e, f, g, h, i, j, k, l)+    = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j, Plain k, Plain l)+  lift (a, b, c, d, e, f, g, h, i, j, k, l)+    = atup12 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j, lift k, lift l)++instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l)+  => Unlift Acc (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j, Acc k, Acc l) where+  unlift = unatup12++instance (Lift Acc a, Lift Acc b, Lift Acc c, Lift Acc d, Lift Acc e, Lift Acc f,+          Lift Acc g, Lift Acc h, Lift Acc i, Lift Acc j, Lift Acc k, Lift Acc l, Lift Acc m,+          Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e), Arrays (Plain f),+          Arrays (Plain g), Arrays (Plain h), Arrays (Plain i), Arrays (Plain j), Arrays (Plain k), Arrays (Plain l), Arrays (Plain m))+  => Lift Acc (a, b, c, d, e, f, g, h, i, j, k, l, m) where+  type Plain (a, b, c, d, e, f, g, h, i, j, k, l, m)+    = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j, Plain k, Plain l, Plain m)+  lift (a, b, c, d, e, f, g, h, i, j, k, l, m)+    = atup13 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j, lift k, lift l, lift m)++instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l, Arrays m)+  => Unlift Acc (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j, Acc k, Acc l, Acc m) where+  unlift = unatup13++instance (Lift Acc a, Lift Acc b, Lift Acc c, Lift Acc d, Lift Acc e, Lift Acc f, Lift Acc g,+          Lift Acc h, Lift Acc i, Lift Acc j, Lift Acc k, Lift Acc l, Lift Acc m, Lift Acc n,+          Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e), Arrays (Plain f), Arrays (Plain g),+          Arrays (Plain h), Arrays (Plain i), Arrays (Plain j), Arrays (Plain k), Arrays (Plain l), Arrays (Plain m), Arrays (Plain n))+  => Lift Acc (a, b, c, d, e, f, g, h, i, j, k, l, m, n) where+  type Plain (a, b, c, d, e, f, g, h, i, j, k, l, m, n)+    = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j, Plain k, Plain l, Plain m, Plain n)+  lift (a, b, c, d, e, f, g, h, i, j, k, l, m, n)+    = atup14 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j, lift k, lift l, lift m, lift n)++instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l, Arrays m, Arrays n)+  => Unlift Acc (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j, Acc k, Acc l, Acc m, Acc n) where+  unlift = unatup14++instance (Lift Acc a, Lift Acc b, Lift Acc c, Lift Acc d, Lift Acc e, Lift Acc f, Lift Acc g,+          Lift Acc h, Lift Acc i, Lift Acc j, Lift Acc k, Lift Acc l, Lift Acc m, Lift Acc n, Lift Acc o,+          Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e), Arrays (Plain f), Arrays (Plain g),+          Arrays (Plain h), Arrays (Plain i), Arrays (Plain j), Arrays (Plain k), Arrays (Plain l), Arrays (Plain m), Arrays (Plain n), Arrays (Plain o))+  => Lift Acc (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) where+  type Plain (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)+    = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j, Plain k, Plain l, Plain m, Plain n, Plain o)+  lift (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)+    = atup15 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j, lift k, lift l, lift m, lift n, lift o)++instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l, Arrays m, Arrays n, Arrays o)+  => Unlift Acc (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j, Acc k, Acc l, Acc m, Acc n, Acc o) where+  unlift = unatup15++{--+-- Instances for Seq++instance (Lift Seq a, Lift Seq b, Arrays (Plain a), Arrays (Plain b)) => Lift Seq (a, b) where+  type Plain (a, b) = (Plain a, Plain b)+  lift (a, b) = stup2 (lift a, lift b)++instance (Lift Seq a, Lift Seq b, Lift Seq c,+          Arrays (Plain a), Arrays (Plain b), Arrays (Plain c))+  => Lift Seq (a, b, c) where+  type Plain (a, b, c) = (Plain a, Plain b, Plain c)+  lift (a, b, c) = stup3 (lift a, lift b, lift c)++instance (Lift Seq a, Lift Seq b, Lift Seq c, Lift Seq d,+          Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d))+  => Lift Seq (a, b, c, d) where+  type Plain (a, b, c, d) = (Plain a, Plain b, Plain c, Plain d)+  lift (a, b, c, d) = stup4 (lift a, lift b, lift c, lift d)++instance (Lift Seq a, Lift Seq b, Lift Seq c, Lift Seq d, Lift Seq e,+          Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e))+  => Lift Seq (a, b, c, d, e) where+  type Plain (a, b, c, d, e) = (Plain a, Plain b, Plain c, Plain d, Plain e)+  lift (a, b, c, d, e) = stup5 (lift a, lift b, lift c, lift d, lift e)++instance (Lift Seq a, Lift Seq b, Lift Seq c, Lift Seq d, Lift Seq e, Lift Seq f,+          Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e), Arrays (Plain f))+  => Lift Seq (a, b, c, d, e, f) where+  type Plain (a, b, c, d, e, f) = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f)+  lift (a, b, c, d, e, f) = stup6 (lift a, lift b, lift c, lift d, lift e, lift f)++instance (Lift Seq a, Lift Seq b, Lift Seq c, Lift Seq d, Lift Seq e, Lift Seq f, Lift Seq g,+          Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e), Arrays (Plain f),+          Arrays (Plain g))+  => Lift Seq (a, b, c, d, e, f, g) where+  type Plain (a, b, c, d, e, f, g) = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g)+  lift (a, b, c, d, e, f, g) = stup7 (lift a, lift b, lift c, lift d, lift e, lift f, lift g)++instance (Lift Seq a, Lift Seq b, Lift Seq c, Lift Seq d, Lift Seq e, Lift Seq f, Lift Seq g, Lift Seq h,+          Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e), Arrays (Plain f),+          Arrays (Plain g), Arrays (Plain h))+  => Lift Seq (a, b, c, d, e, f, g, h) where+  type Plain (a, b, c, d, e, f, g, h)+    = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h)+  lift (a, b, c, d, e, f, g, h)+    = stup8 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h)++instance (Lift Seq a, Lift Seq b, Lift Seq c, Lift Seq d, Lift Seq e,+          Lift Seq f, Lift Seq g, Lift Seq h, Lift Seq i,+          Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e),+          Arrays (Plain f), Arrays (Plain g), Arrays (Plain h), Arrays (Plain i))+  => Lift Seq (a, b, c, d, e, f, g, h, i) where+  type Plain (a, b, c, d, e, f, g, h, i)+    = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i)+  lift (a, b, c, d, e, f, g, h, i)+    = stup9 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i)++instance (Lift Seq a, Lift Seq b, Lift Seq c, Lift Seq d, Lift Seq e,+          Lift Seq f, Lift Seq g, Lift Seq h, Lift Seq i, Lift Seq j,+          Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e),+          Arrays (Plain f), Arrays (Plain g), Arrays (Plain h), Arrays (Plain i), Arrays (Plain j))+  => Lift Seq (a, b, c, d, e, f, g, h, i, j) where+  type Plain (a, b, c, d, e, f, g, h, i, j)+    = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j)+  lift (a, b, c, d, e, f, g, h, i, j)+    = stup10 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j)++instance (Lift Seq a, Lift Seq b, Lift Seq c, Lift Seq d, Lift Seq e,+          Lift Seq f, Lift Seq g, Lift Seq h, Lift Seq i, Lift Seq j, Lift Seq k,+          Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e),+          Arrays (Plain f), Arrays (Plain g), Arrays (Plain h), Arrays (Plain i), Arrays (Plain j), Arrays (Plain k))+  => Lift Seq (a, b, c, d, e, f, g, h, i, j, k) where+  type Plain (a, b, c, d, e, f, g, h, i, j, k)+    = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j, Plain k)+  lift (a, b, c, d, e, f, g, h, i, j, k)+    = stup11 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j, lift k)++instance (Lift Seq a, Lift Seq b, Lift Seq c, Lift Seq d, Lift Seq e, Lift Seq f,+          Lift Seq g, Lift Seq h, Lift Seq i, Lift Seq j, Lift Seq k, Lift Seq l,+          Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e), Arrays (Plain f),+          Arrays (Plain g), Arrays (Plain h), Arrays (Plain i), Arrays (Plain j), Arrays (Plain k), Arrays (Plain l))+  => Lift Seq (a, b, c, d, e, f, g, h, i, j, k, l) where+  type Plain (a, b, c, d, e, f, g, h, i, j, k, l)+    = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j, Plain k, Plain l)+  lift (a, b, c, d, e, f, g, h, i, j, k, l)+    = stup12 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j, lift k, lift l)++instance (Lift Seq a, Lift Seq b, Lift Seq c, Lift Seq d, Lift Seq e, Lift Seq f,+          Lift Seq g, Lift Seq h, Lift Seq i, Lift Seq j, Lift Seq k, Lift Seq l, Lift Seq m,+          Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e), Arrays (Plain f),+          Arrays (Plain g), Arrays (Plain h), Arrays (Plain i), Arrays (Plain j), Arrays (Plain k), Arrays (Plain l), Arrays (Plain m))+  => Lift Seq (a, b, c, d, e, f, g, h, i, j, k, l, m) where+  type Plain (a, b, c, d, e, f, g, h, i, j, k, l, m)+    = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j, Plain k, Plain l, Plain m)+  lift (a, b, c, d, e, f, g, h, i, j, k, l, m)+    = stup13 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j, lift k, lift l, lift m)++instance (Lift Seq a, Lift Seq b, Lift Seq c, Lift Seq d, Lift Seq e, Lift Seq f, Lift Seq g,+          Lift Seq h, Lift Seq i, Lift Seq j, Lift Seq k, Lift Seq l, Lift Seq m, Lift Seq n,+          Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e), Arrays (Plain f), Arrays (Plain g),+          Arrays (Plain h), Arrays (Plain i), Arrays (Plain j), Arrays (Plain k), Arrays (Plain l), Arrays (Plain m), Arrays (Plain n))+  => Lift Seq (a, b, c, d, e, f, g, h, i, j, k, l, m, n) where+  type Plain (a, b, c, d, e, f, g, h, i, j, k, l, m, n)+    = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j, Plain k, Plain l, Plain m, Plain n)+  lift (a, b, c, d, e, f, g, h, i, j, k, l, m, n)+    = stup14 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j, lift k, lift l, lift m, lift n)++instance (Lift Seq a, Lift Seq b, Lift Seq c, Lift Seq d, Lift Seq e, Lift Seq f, Lift Seq g,+          Lift Seq h, Lift Seq i, Lift Seq j, Lift Seq k, Lift Seq l, Lift Seq m, Lift Seq n, Lift Seq o,+          Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e), Arrays (Plain f), Arrays (Plain g),+          Arrays (Plain h), Arrays (Plain i), Arrays (Plain j), Arrays (Plain k), Arrays (Plain l), Arrays (Plain m), Arrays (Plain n), Arrays (Plain o))+  => Lift Seq (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) where+  type Plain (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)+    = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i, Plain j, Plain k, Plain l, Plain m, Plain n, Plain o)+  lift (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)+    = stup15 (lift a, lift b, lift c, lift d, lift e, lift f, lift g, lift h, lift i, lift j, lift k, lift l, lift m, lift n, lift o)+--}+
Data/Array/Accelerate/Prelude.hs view
@@ -1,1679 +1,2010 @@-{-# LANGUAGE FlexibleContexts      #-}-{-# LANGUAGE FlexibleInstances     #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE OverlappingInstances  #-}-{-# LANGUAGE ScopedTypeVariables   #-}-{-# LANGUAGE TypeFamilies          #-}-{-# LANGUAGE TypeOperators         #-}--- |--- Module      : Data.Array.Accelerate.Prelude--- Copyright   : [2009..2014] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell---               [2010..2011] Ben Lever--- License     : BSD3------ Maintainer  : Manuel M T Chakravarty <chak@cse.unsw.edu.au>--- Stability   : experimental--- Portability : non-portable (GHC extensions)------ Standard functions that are not part of the core set (directly represented in--- the AST), but are instead implemented in terms of the core set.-----module Data.Array.Accelerate.Prelude (--  -- * Zipping-  zipWith3, zipWith4, zipWith5, zipWith6, zipWith7, zipWith8, zipWith9,-  zip, zip3, zip4, zip5, zip6, zip7, zip8, zip9,--  -- * Unzipping-  unzip, unzip3, unzip4, unzip5, unzip6, unzip7, unzip8, unzip9,--  -- * Reductions-  foldAll, fold1All,--  -- ** Specialised folds-  all, any, and, or, sum, product, minimum, maximum,--  -- * Scans-  prescanl, postscanl, prescanr, postscanr,--  -- ** Segmented scans-  scanlSeg, scanl'Seg, scanl1Seg, prescanlSeg, postscanlSeg,-  scanrSeg, scanr'Seg, scanr1Seg, prescanrSeg, postscanrSeg,--  -- * Shape manipulation-  flatten,--  -- * Enumeration and filling-  fill, enumFromN, enumFromStepN,--  -- * Concatenation-  (++),--  -- * Working with predicates-  -- ** Filtering-  filter,--  -- ** Scatter / Gather-  scatter, scatterIf,-  gather,  gatherIf,--  -- * Permutations-  reverse, transpose,--  -- * Extracting sub-vectors-  init, tail, take, drop, slit,--  -- * Array-level flow control-  (?|),--  -- * Expression-level flow control-  (?), caseof,--  -- * Scalar iteration-  iterate,--  -- * Scalar reduction-  sfoldl, -- sfoldr,--  -- * Lifting and unlifting-  Lift(..), Unlift(..),-  lift1, lift2, ilift1, ilift2,--  -- ** Tuple construction and destruction-  fst, afst, snd, asnd, curry, uncurry,--  -- ** Index construction and destruction-  index0, index1, unindex1, index2, unindex2,--  -- * Array operations with a scalar result-  the, null, length,--) where---- avoid clashes with Prelude functions----import Data.Bits-import Data.Bool-import Prelude ((.), ($), (+), (-), (*), const, subtract, id, min, max, Float,-  Double, Char)-import qualified Prelude as P---- friends-import Data.Array.Accelerate.Array.Sugar hiding ((!), ignore, shape, size, intersect)-import Data.Array.Accelerate.Language-import Data.Array.Accelerate.Smart-import Data.Array.Accelerate.Tuple-import Data.Array.Accelerate.Type----- Map-like composites--- ----------------------- | 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)-zipWith3 f as bs cs-  = generate (shape as `intersect` shape bs `intersect` shape cs)-             (\ix -> f (as ! ix) (bs ! ix) (cs ! ix))---- | 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)-zipWith4 f as bs cs ds-  = generate (shape as `intersect` shape bs `intersect`-              shape cs `intersect` shape ds)-             (\ix -> f (as ! ix) (bs ! ix) (cs ! ix) (ds ! ix))---- | 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)-zipWith5 f as bs cs ds es-  = generate (shape as `intersect` shape bs `intersect` shape cs-                       `intersect` shape ds `intersect` shape es)-             (\ix -> f (as ! ix) (bs ! ix) (cs ! ix) (ds ! ix) (es ! ix))---- | 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)-zipWith6 f as bs cs ds es fs-  = generate (shape as `intersect` shape bs `intersect` shape cs-                       `intersect` shape ds `intersect` shape es-                       `intersect` shape fs)-             (\ix -> f (as ! ix) (bs ! ix) (cs ! ix) (ds ! ix) (es ! ix) (fs ! ix))---- | 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)-zipWith7 f as bs cs ds es fs gs-  = generate (shape as `intersect` shape bs `intersect` shape cs-                       `intersect` shape ds `intersect` shape es-                       `intersect` shape fs `intersect` shape gs)-             (\ix -> f (as ! ix) (bs ! ix) (cs ! ix) (ds ! ix) (es ! ix) (fs ! ix) (gs ! ix))---- | 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)-zipWith8 f as bs cs ds es fs gs hs-  = generate (shape as `intersect` shape bs `intersect` shape cs-                       `intersect` shape ds `intersect` shape es-                       `intersect` shape fs `intersect` shape gs-                       `intersect` shape hs)-             (\ix -> f (as ! ix) (bs ! ix) (cs ! ix) (ds ! ix) (es ! ix) (fs ! ix) (gs ! ix) (hs ! ix))---- | 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)-zipWith9 f as bs cs ds es fs gs hs is-  = generate (shape as `intersect` shape bs `intersect` shape cs-                       `intersect` shape ds `intersect` shape es-                       `intersect` shape fs `intersect` shape gs-                       `intersect` shape hs `intersect` shape is)-             (\ix -> f (as ! ix) (bs ! ix) (cs ! ix) (ds ! ix) (es ! ix) (fs ! ix) (gs ! ix) (hs ! ix) (is ! ix))----- | 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))-zip = zipWith (curry lift)---- | 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))-zip3 = zipWith3 (\a b c -> lift (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))-zip4 = zipWith4 (\a b c d -> lift (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))-zip5 = zipWith5 (\a b c d e -> lift (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))-zip6 = zipWith6 (\a b c d e f -> lift (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))-zip7 = zipWith7 (\a b c d e f g -> lift (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))-zip8 = zipWith8 (\a b c d e f g h -> lift (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))-zip9 = zipWith9 (\a b c d e f g h i -> lift (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.----unzip :: (Shape sh, Elt a, Elt b)-      => Acc (Array sh (a, b))-      -> (Acc (Array sh a), Acc (Array sh b))-unzip arr = (map fst arr, map snd arr)---- | 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))-unzip3 xs = (map get1 xs, map get2 xs, map get3 xs)-  where-    get1 x = let (a,_,_) = untup3 x in a-    get2 x = let (_,b,_) = untup3 x in b-    get3 x = let (_,_,c) = untup3 x in 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))-unzip4 xs = (map get1 xs, map get2 xs, map get3 xs, map get4 xs)-  where-    get1 x = let (a,_,_,_) = untup4 x in a-    get2 x = let (_,b,_,_) = untup4 x in b-    get3 x = let (_,_,c,_) = untup4 x in c-    get4 x = let (_,_,_,d) = untup4 x in 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))-unzip5 xs = (map get1 xs, map get2 xs, map get3 xs, map get4 xs, map get5 xs)-  where-    get1 x = let (a,_,_,_,_) = untup5 x in a-    get2 x = let (_,b,_,_,_) = untup5 x in b-    get3 x = let (_,_,c,_,_) = untup5 x in c-    get4 x = let (_,_,_,d,_) = untup5 x in d-    get5 x = let (_,_,_,_,e) = untup5 x in 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))-unzip6 xs = (map get1 xs, map get2 xs, map get3 xs, map get4 xs, map get5 xs, map get6 xs)-  where-    get1 x = let (a,_,_,_,_,_) = untup6 x in a-    get2 x = let (_,b,_,_,_,_) = untup6 x in b-    get3 x = let (_,_,c,_,_,_) = untup6 x in c-    get4 x = let (_,_,_,d,_,_) = untup6 x in d-    get5 x = let (_,_,_,_,e,_) = untup6 x in e-    get6 x = let (_,_,_,_,_,f) = untup6 x in 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))-unzip7 xs = ( map get1 xs, map get2 xs, map get3 xs-            , map get4 xs, map get5 xs, map get6 xs-            , map get7 xs )-  where-    get1 x = let (a,_,_,_,_,_,_) = untup7 x in a-    get2 x = let (_,b,_,_,_,_,_) = untup7 x in b-    get3 x = let (_,_,c,_,_,_,_) = untup7 x in c-    get4 x = let (_,_,_,d,_,_,_) = untup7 x in d-    get5 x = let (_,_,_,_,e,_,_) = untup7 x in e-    get6 x = let (_,_,_,_,_,f,_) = untup7 x in f-    get7 x = let (_,_,_,_,_,_,g) = untup7 x in 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) )-unzip8 xs = ( map get1 xs, map get2 xs, map get3 xs-            , map get4 xs, map get5 xs, map get6 xs-            , map get7 xs, map get8 xs )-  where-    get1 x = let (a,_,_,_,_,_,_,_) = untup8 x in a-    get2 x = let (_,b,_,_,_,_,_,_) = untup8 x in b-    get3 x = let (_,_,c,_,_,_,_,_) = untup8 x in c-    get4 x = let (_,_,_,d,_,_,_,_) = untup8 x in d-    get5 x = let (_,_,_,_,e,_,_,_) = untup8 x in e-    get6 x = let (_,_,_,_,_,f,_,_) = untup8 x in f-    get7 x = let (_,_,_,_,_,_,g,_) = untup8 x in g-    get8 x = let (_,_,_,_,_,_,_,h) = untup8 x in 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))-unzip9 xs = ( map get1 xs, map get2 xs, map get3 xs-            , map get4 xs, map get5 xs, map get6 xs-            , map get7 xs, map get8 xs, map get9 xs )-  where-    get1 x = let (a,_,_,_,_,_,_,_,_) = untup9 x in a-    get2 x = let (_,b,_,_,_,_,_,_,_) = untup9 x in b-    get3 x = let (_,_,c,_,_,_,_,_,_) = untup9 x in c-    get4 x = let (_,_,_,d,_,_,_,_,_) = untup9 x in d-    get5 x = let (_,_,_,_,e,_,_,_,_) = untup9 x in e-    get6 x = let (_,_,_,_,_,f,_,_,_) = untup9 x in f-    get7 x = let (_,_,_,_,_,_,g,_,_) = untup9 x in g-    get8 x = let (_,_,_,_,_,_,_,h,_) = untup9 x in h-    get9 x = let (_,_,_,_,_,_,_,_,i) = untup9 x in i----- Reductions--- -------------- | Reduction of an array of arbitrary rank to a single scalar value.----foldAll :: (Shape sh, Elt a)-        => (Exp a -> Exp a -> Exp a)-        -> Exp a-        -> Acc (Array sh a)-        -> Acc (Scalar a)-foldAll f e arr = fold f e (flatten arr)---- | Variant of 'foldAll' that requires the reduced array to be non-empty and--- doesn't need an default value.----fold1All :: (Shape sh, Elt a)-         => (Exp a -> Exp a -> Exp a)-         -> Acc (Array sh a)-         -> Acc (Scalar a)-fold1All f arr = fold1 f (flatten arr)----- Specialised reductions--- ---------------------------- Leave the results of these as scalar arrays to make it clear that these are--- array computations, and thus can not be nested.---- | Check if all elements satisfy a predicate----all :: (Shape sh, Elt e)-    => (Exp e -> Exp Bool)-    -> Acc (Array sh e)-    -> Acc (Scalar Bool)-all f = and . map f---- | Check if any element satisfies the predicate----any :: (Shape sh, Elt e)-    => (Exp e -> Exp Bool)-    -> Acc (Array sh e)-    -> Acc (Scalar Bool)-any f = or . map f---- | Check if all elements are 'True'----and :: Shape sh-    => Acc (Array sh Bool)-    -> Acc (Scalar Bool)-and = foldAll (&&*) (constant True)---- | Check if any element is 'True'----or :: Shape sh-   => Acc (Array sh Bool)-   -> Acc (Scalar Bool)-or = foldAll (||*) (constant False)---- | Compute the sum of elements----sum :: (Shape sh, Elt e, IsNum e)-    => Acc (Array sh e)-    -> Acc (Scalar e)-sum = foldAll (+) 0---- | Compute the product of the elements----product :: (Shape sh, Elt e, IsNum e)-        => Acc (Array sh e)-        -> Acc (Scalar e)-product = foldAll (*) 1---- | Yield the minimum element of an array. The array must not be empty.----minimum :: (Shape sh, Elt e, IsScalar e)-        => Acc (Array sh e)-        -> Acc (Scalar e)-minimum = fold1All min---- | Yield the maximum element of an array. The array must not be empty.----maximum :: (Shape sh, Elt e, IsScalar e)-        => Acc (Array sh e)-        -> Acc (Scalar e)-maximum = fold1All max----- Composite scans--- ------------------- |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----prescanl :: Elt a-         => (Exp a -> Exp a -> Exp a)-         -> Exp a-         -> Acc (Vector a)-         -> Acc (Vector a)-prescanl f e = P.fst . scanl' f e---- |Left-to-right postscan, a variant of 'scanl1' with an initial value.  Denotationally, we have------ > postscanl f e = map (e `f`) . scanl1 f----postscanl :: Elt a-          => (Exp a -> Exp a -> Exp a)-          -> Exp a-          -> Acc (Vector a)-          -> Acc (Vector a)-postscanl f e = map (e `f`) . scanl1 f---- |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 :: Elt a-         => (Exp a -> Exp a -> Exp a)-         -> Exp a-         -> Acc (Vector a)-         -> Acc (Vector a)-prescanr f e = P.fst . scanr' f e---- |Right-to-left postscan, a variant of 'scanr1' with an initial value.  Denotationally, we have------ > postscanr f e = map (e `f`) . scanr1 f----postscanr :: Elt a-          => (Exp a -> Exp a -> Exp a)-          -> Exp a-          -> Acc (Vector a)-          -> Acc (Vector a)-postscanr f e = map (`f` e) . scanr1 f----- Segmented scans--- ------------------- |Segmented version of 'scanl'----scanlSeg :: (Elt a, Elt i, IsIntegral i)-         => (Exp a -> Exp a -> Exp a)-         -> Exp a-         -> Acc (Vector a)-         -> Acc (Segments i)-         -> Acc (Vector a)-scanlSeg f z vec seg = scanl1Seg f vec' seg'-  where-    -- Segmented exclusive scan is implemented by first injecting the seed-    -- element at the head of each segment, and then performing a segmented-    -- inclusive scan.-    ---    -- This is done by creating a creating a vector entirely of the seed-    -- element, and overlaying the input data in all places other than at the-    -- start of a segment.-    ---    seg'        = map (+1) seg-    vec'        = permute const-                          (fill (index1 $ size vec + size seg) z)-                          (\ix -> index1' $ unindex1' ix + inc ! ix)-                          vec--    -- Each element in the segments must be shifted to the right one additional-    -- place for each successive segment, to make room for the seed element.-    -- Here, we make use of the fact that the vector returned by 'mkHeadFlags'-    -- contains non-unit entries, which indicate zero length segments.-    ---    flags       = mkHeadFlags seg-    inc         = scanl1 (+) flags----- |Segmented version of 'scanl''------ 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.----scanl'Seg :: forall a i. (Elt a, Elt i, IsIntegral i)-          => (Exp a -> Exp a -> Exp a)-          -> Exp a-          -> Acc (Vector a)-          -> Acc (Segments i)-          -> Acc (Vector a, Vector a)-scanl'Seg f z vec seg = result-  where-    -- Returned the result combined, so that the sub-calculations are shared-    -- should the user require both results.-    ---    result      = lift (body, sums)--    -- Segmented scan' is implemented by deconstructing a segmented exclusive-    -- scan, to separate the final value and scan body.-    ---    -- TLM: Segmented scans, and this version in particular, expend a lot of-    --      effort scanning flag arrays. On inspection it appears that several-    --      of these operations are duplicated, but this will not be picked up-    --      by sharing _observation_. Perhaps a global CSE-style pass would be-    --      beneficial.-    ---    vec'        = scanlSeg f z vec seg--    -- Extract the final reduction value for each segment, which is at the last-    -- index of each segment.-    ---    seg'        = map (+1) seg-    tails       = zipWith (+) seg . P.fst $ scanl' (+) 0 seg'-    sums        = backpermute (shape seg) (\ix -> index1' $ tails ! ix) vec'--    -- Slice out the body of each segment.-    ---    -- Build a head-flags representation based on the original segment-    -- descriptor. This contains the target length of each of the body segments,-    -- which is one fewer element than the actual bodies stored in vec'. Thus,-    -- the flags align with the last element of each body section, and when-    -- scanned, this element will be incremented over.-    ---    offset      = scanl1 (+) seg-    inc         = scanl1 (+)-                $ permute (+) (fill (index1 $ size vec + 1) 0)-                              (\ix -> index1' $ offset ! ix)-                              (fill (shape seg) (1 :: Exp i))--    body        = backpermute (shape vec)-                              (\ix -> index1' $ unindex1' ix + inc ! ix)-                              vec'----- |Segmented version of 'scanl1'.----scanl1Seg :: (Elt a, Elt i, IsIntegral i)-          => (Exp a -> Exp a -> Exp a)-          -> Acc (Vector a)-          -> Acc (Segments i)-          -> Acc (Vector a)-scanl1Seg f vec seg-  = P.snd-  . unzip-  . scanl1 (segmented f)-  $ zip (mkHeadFlags seg) vec---- |Segmented version of 'prescanl'.----prescanlSeg :: (Elt a, Elt i, IsIntegral i)-            => (Exp a -> Exp a -> Exp a)-            -> Exp a-            -> Acc (Vector a)-            -> Acc (Segments i)-            -> Acc (Vector a)-prescanlSeg f e vec seg-  = P.fst-  . unatup2-  $ scanl'Seg f e vec seg---- |Segmented version of 'postscanl'.----postscanlSeg :: (Elt a, Elt i, IsIntegral i)-             => (Exp a -> Exp a -> Exp a)-             -> Exp a-             -> Acc (Vector a)-             -> Acc (Segments i)-             -> Acc (Vector a)-postscanlSeg f e vec seg-  = map (f e)-  $ scanl1Seg f vec seg---- |Segmented version of 'scanr'.----scanrSeg :: (Elt a, Elt i, IsIntegral i)-         => (Exp a -> Exp a -> Exp a)-         -> Exp a-         -> Acc (Vector a)-         -> Acc (Segments i)-         -> Acc (Vector a)-scanrSeg f z vec seg = scanr1Seg f vec' seg'-  where-    -- Using technique described for 'scanlSeg', where we intersperse the array-    -- with the seed element at the start of each segment, and then perform an-    -- inclusive segmented scan.-    ---    inc         = scanl1 (+) (mkHeadFlags seg)-    seg'        = map (+1) seg-    vec'        = permute const-                          (fill (index1 $ size vec + size seg) z)-                          (\ix -> index1' $ unindex1' ix + inc ! ix - 1)-                          vec----- | Segmented version of 'scanr''.----scanr'Seg :: forall a i. (Elt a, Elt i, IsIntegral i)-          => (Exp a -> Exp a -> Exp a)-          -> Exp a-          -> Acc (Vector a)-          -> Acc (Segments i)-          -> Acc (Vector a, Vector a)-scanr'Seg f z vec seg = result-  where-    -- Using technique described for scanl'Seg-    ---    result      = lift (body, sums)-    vec'        = scanrSeg f z vec seg--    -- reduction values-    seg'        = map (+1) seg-    heads       = P.fst $ scanl' (+) 0 seg'-    sums        = backpermute (shape seg) (\ix -> index1' $ heads ! ix) vec'--    -- body segments-    inc         = scanl1 (+) $ mkHeadFlags seg-    body        = backpermute (shape vec)-                              (\ix -> index1' $ unindex1' ix + inc ! ix)-                              vec'----- |Segmented version of 'scanr1'.----scanr1Seg :: (Elt a, Elt i, IsIntegral i)-          => (Exp a -> Exp a -> Exp a)-          -> Acc (Vector a)-          -> Acc (Segments i)-          -> Acc (Vector a)-scanr1Seg f vec seg-  = P.snd-  . unzip-  . scanr1 (segmented f)-  $ zip (mkTailFlags seg) vec---- |Segmented version of 'prescanr'.----prescanrSeg :: (Elt a, Elt i, IsIntegral i)-            => (Exp a -> Exp a -> Exp a)-            -> Exp a-            -> Acc (Vector a)-            -> Acc (Segments i)-            -> Acc (Vector a)-prescanrSeg f e vec seg-  = P.fst-  . unatup2-  $ scanr'Seg f e vec seg---- |Segmented version of 'postscanr'.----postscanrSeg :: (Elt a, Elt i, IsIntegral i)-             => (Exp a -> Exp a -> Exp a)-             -> Exp a-             -> Acc (Vector a)-             -> Acc (Segments i)-             -> Acc (Vector a)-postscanrSeg f e vec seg-  = map (f e)-  $ scanr1Seg f vec seg----- Segmented scan helpers--- -------------------------- |Compute head flags vector from segment vector for left-scans.------ The vector will be full of zeros in the body of a segment, and non-zero--- otherwise. The "flag" value, if greater than one, indicates that several--- empty segments are represented by this single flag entry. This is additional--- data is used by exclusive segmented scan.----mkHeadFlags :: (Elt i, IsIntegral i) => Acc (Segments i) -> Acc (Segments i)-mkHeadFlags seg-  = init-  $ permute (+) zeros (\ix -> index1' (offset ! ix)) ones-  where-    (offset, len)       = scanl' (+) 0 seg-    zeros               = fill (index1' $ the len + 1) 0-    ones                = fill (index1  $ size offset) 1---- |Compute tail flags vector from segment vector for right-scans. That is, the--- flag is placed at the last place in each segment.----mkTailFlags :: (Elt i, IsIntegral i) => Acc (Segments i) -> Acc (Segments i)-mkTailFlags seg-  = init-  $ permute (+) zeros (\ix -> index1' (the len - 1 - offset ! ix)) ones-  where-    (offset, len)       = scanr' (+) 0 seg-    zeros               = fill (index1' $ the len + 1) 0-    ones                = fill (index1  $ size offset) 1---- |Construct a segmented version of a function from a non-segmented version.--- The segmented apply operates on a head-flag value tuple, and follows the--- procedure of Sengupta et. al.----segmented :: (Elt e, Elt i, IsIntegral i)-          => (Exp e -> Exp e -> Exp e)-          -> Exp (i, e) -> Exp (i, e) -> Exp (i, e)-segmented f a b =-  let (aF, aV) = unlift a-      (bF, bV) = unlift b-  in-  lift (aF .|. bF, bF /=* 0 ? (bV, f aV bV))---- |Index construction and destruction generalised to integral types.------ We generalise the segment descriptor to integral types because some--- architectures, such as GPUs, have poor performance for 64-bit types. So,--- there is a tension between performance and requiring 64-bit indices for some--- applications, and we would not like to restrict ourselves to either one.------ As we don't yet support non-Int dimensions in shapes, we will need to convert--- back to concrete Int. However, don't put these generalised forms into the--- base library, because it results in too many ambiguity errors.----index1' ::  (Elt i, IsIntegral i) => Exp i -> Exp DIM1-index1' i = lift (Z :. fromIntegral i)--unindex1' :: (Elt i, IsIntegral i) => Exp DIM1 -> Exp i-unindex1' ix = let Z :. i = unlift ix in fromIntegral i----- Reshaping of arrays--- ----------------------- | Flattens a given array of arbitrary dimension.----flatten :: (Shape ix, Elt a) => Acc (Array ix a) -> Acc (Vector a)-flatten a = reshape (index1 $ size a) a---- Enumeration and filling--- --------------------------- | Create an array where all elements are the same value.----fill :: (Shape sh, Elt e) => Exp sh -> Exp e -> Acc (Array sh e)-fill sh c = generate sh (const c)---- | Create an array of the given shape containing the values x, x+1, etc (in---   row-major order).----enumFromN :: (Shape sh, Elt e, IsNum e) => Exp sh -> Exp e -> Acc (Array sh e)-enumFromN sh x = enumFromStepN sh x 1---- | Create an array of the given shape containing the values @x@, @x+y@,--- @x+y+y@ etc. (in row-major order).----enumFromStepN :: (Shape sh, Elt e, IsNum e)-              => Exp sh-              -> Exp e    -- ^ x: start-              -> Exp e    -- ^ y: step-              -> Acc (Array sh e)-enumFromStepN sh x y-  = reshape sh-  $ generate (index1 $ shapeSize sh)-             (\ix -> (fromIntegral (unindex1 ix :: Exp Int) * y) + x)---- Concatenation--- ----------------- | Concatenate outermost component of two arrays. The extent of the lower---   dimensional component is the intersection of the two arrays.----infixr 5 ++-(++) :: forall sh e. (Slice sh, Shape sh, Elt e)-     => Acc (Array (sh :. Int) e)-     -> Acc (Array (sh :. Int) e)-     -> Acc (Array (sh :. Int) e)-(++) xs ys-  = let sh1 :. n        = unlift (shape xs)     :: Exp sh :. Exp Int-        sh2 :. m        = unlift (shape ys)     :: Exp sh :. Exp Int-    in-    generate (lift (intersect sh1 sh2 :. n + m))-             (\ix -> let sh :. i = unlift ix    :: Exp sh :. Exp Int-                     in  i <* n ? ( xs ! ix, ys ! lift (sh :. i-n)) )----- Filtering--- ------------- | Drop elements that do not satisfy the predicate----filter :: Elt a-       => (Exp a -> Exp Bool)-       -> Acc (Vector a)-       -> Acc (Vector a)-filter p arr-  = let flags            = map (boolToInt . p) arr-        (targetIdx, len) = scanl' (+) 0 flags-        arr'             = backpermute (index1 $ the len) id arr-    in-    permute const arr' (\ix -> flags!ix ==* 0 ? (ignore, index1 $ targetIdx!ix)) arr-    -- FIXME: This is abusing 'permute' in that the first two arguments are-    --        only justified because we know the permutation function will-    --        write to each location in the target exactly once.-    --        Instead, we should have a primitive that directly encodes the-    --        compaction pattern of the permutation function.--{-# NOINLINE filter #-}-{-# RULES-  "ACC filter/filter" forall f g arr.-    filter f (filter g arr) = filter (\x -> g x &&* f x) arr- #-}----- Gather operations--- --------------------- | Copy elements from source array to destination array according to a map. This---   is a backpermute operation where a 'map' vector encodes the output to input---   index mapping.------   For example:------  > input  = [1, 9, 6, 4, 4, 2, 0, 1, 2]---  > from   = [1, 3, 7, 2, 5, 3]---  >---  > output = [9, 4, 1, 6, 2, 4]----gather :: Elt e-       => Acc (Vector Int)      -- ^index mapping-       -> Acc (Vector e)        -- ^input-       -> Acc (Vector e)        -- ^output-gather from input = backpermute (shape from) bpF input-  where-    bpF ix      = index1 (from ! ix)----- | Conditionally copy elements from source array to destination array according---   to an index mapping. This is a backpermute operation where a 'from' vector---   encodes the output to input index mapping. In addition, there is a 'mask'---   vector, and an associated predication function, that specifies whether an---   element will be copied. If not copied, the output array assumes the default---   vector's value.------   For example:------  > default = [6, 6, 6, 6, 6, 6]---  > from    = [1, 3, 7, 2, 5, 3]---  > mask    = [3, 4, 9, 2, 7, 5]---  > pred    = (>* 4)---  > input   = [1, 9, 6, 4, 4, 2, 0, 1, 2]---  >---  > output  = [6, 6, 1, 6, 2, 4]----gatherIf :: (Elt e, Elt e')-         => Acc (Vector Int)    -- ^index mapping-         -> Acc (Vector e)      -- ^mask-         -> (Exp e -> Exp Bool) -- ^predicate-         -> Acc (Vector e')     -- ^default-         -> Acc (Vector e')     -- ^input-         -> Acc (Vector e')     -- ^output-gatherIf from maskV pred defaults input = zipWith zf pf gatheredV-  where-    zf p g      = p ? (unlift g)-    gatheredV   = zip (gather from input) defaults-    pf          = map pred maskV----- Scatter operations--- ---------------------- | Copy elements from source array to destination array according to an index---   mapping. This is a forward-permute operation where a 'to' vector encodes an---   input to output index mapping. Output elements for indices that are not---   mapped assume the default vector's value.------   For example:------  > default = [0, 0, 0, 0, 0, 0, 0, 0, 0]---  > to      = [1, 3, 7, 2, 5, 8]---  > input   = [1, 9, 6, 4, 4, 2, 5]---  >---  > output  = [0, 1, 4, 9, 0, 4, 0, 6, 2]------   Note if the same index appears in the index mapping more than once, the---   result is undefined. It does not makes sense for the 'to' vector to be---   larger than the 'input' vector.----scatter :: Elt e-        => Acc (Vector Int)      -- ^index mapping-        -> Acc (Vector e)        -- ^default-        -> Acc (Vector e)        -- ^input-        -> Acc (Vector e)        -- ^output-scatter to defaults input = permute const defaults pf input'-  where-    pf ix       = index1 (to ! ix)-    input'      = backpermute (shape to `intersect` shape input) id input----- | Conditionally copy elements from source array to destination array according---   to an index mapping. This is a forward-permute operation where a 'to'---   vector encodes an input to output index mapping. In addition, there is a---   'mask' vector, and an associated predicate function. The mapping will only---   occur if the predicate function applied to the mask at that position---   resolves to 'True'. If not copied, the output array assumes the default---   vector's value.------   For example:------  > default = [0, 0, 0, 0, 0, 0, 0, 0, 0]---  > to      = [1, 3, 7, 2, 5, 8]---  > mask    = [3, 4, 9, 2, 7, 5]---  > pred    = (>* 4)---  > input   = [1, 9, 6, 4, 4, 2, 5]---  >---  > output  = [0, 0, 0, 0, 0, 4, 0, 6, 2]------   Note if the same index appears in the mapping more than once, the result is---   undefined. The 'to' and 'mask' vectors must be the same length. It does not---   make sense for these to be larger than the 'input' vector.----scatterIf :: (Elt e, Elt e')-          => Acc (Vector Int)      -- ^index mapping-          -> Acc (Vector e)        -- ^mask-          -> (Exp e -> Exp Bool)   -- ^predicate-          -> Acc (Vector e')       -- ^default-          -> Acc (Vector e')       -- ^input-          -> Acc (Vector e')       -- ^output-scatterIf to maskV pred defaults input = permute const defaults pf input'-  where-    pf ix       = pred (maskV ! ix) ? ( index1 (to ! ix), ignore )-    input'      = backpermute (shape to `intersect` shape input) id input----- Permutations--- ---------------- | Reverse the elements of a vector.----reverse :: Elt e => Acc (Vector e) -> Acc (Vector e)-reverse xs =-  let len       = unindex1 (shape xs)-      pf i      = len - i - 1-  in  backpermute (shape xs) (ilift1 pf) xs---- | Transpose the rows and columns of a matrix.----transpose :: Elt e => Acc (Array DIM2 e) -> Acc (Array DIM2 e)-transpose mat =-  let swap = lift1 $ \(Z:.x:.y) -> Z:.y:.x :: Z:.Exp Int:.Exp Int-  in  backpermute (swap $ shape mat) swap mat----- Extracting sub-vectors--- -------------------------- | Yield the first @n@ elements of the input vector. The vector must contain--- no more than @n@ elements.----take :: Elt e => Exp Int -> Acc (Vector e) -> Acc (Vector e)-take n =-  let n' = the (unit n)-  in  backpermute (index1 n') id---- | Yield all but the first @n@ elements of the input vector. The vector must---   contain no fewer than @n@ elements.----drop :: Elt e => Exp Int -> Acc (Vector e) -> Acc (Vector e)-drop n arr =-  let n' = the (unit n)-  in  backpermute (ilift1 (subtract n') (shape arr)) (ilift1 (+ n')) arr----- | Yield all but the last element of the input vector. The vector must not be---   empty.----init :: Elt e => Acc (Vector e) -> Acc (Vector e)-init arr = backpermute (ilift1 (subtract 1) (shape arr)) id arr----- | Yield all but the first element of the input vector. The vector must not be---   empty.----tail :: Elt e => Acc (Vector e) -> Acc (Vector e)-tail arr = backpermute (ilift1 (subtract 1) (shape arr)) (ilift1 (+1)) arr----- | Yield a slit (slice) from the vector. The vector must contain at least---   @i + n@ elements. Denotationally, we have:------ > slit i n = take n . drop i----slit :: Elt e => Exp Int -> Exp Int -> Acc (Vector e) -> Acc (Vector e)-slit i n =-  let i' = the (unit i)-      n' = the (unit n)-  in  backpermute (index1 n') (ilift1 (+ i'))----- Flow control--- ---------------- | Infix version of 'acond'. If the predicate evaluates to 'True', the first--- component of the tuple is returned, else the second.----infix 0 ?|-(?|) :: (Arrays a) => Exp Bool -> (Acc a, Acc a) -> Acc a-c ?| (t, e) = acond c t e---- | An infix version of 'cond'. If the predicate evaluates to 'True', the first--- component of the tuple is returned, else the second.----infix 0 ?-(?) :: Elt t => Exp Bool -> (Exp t, Exp t) -> Exp t-c ? (t, e) = cond c t e---- | A case-like control structure----caseof :: (Elt a, Elt b)-       => Exp a                         -- ^ case subject-       -> [(Exp a -> Exp Bool, Exp b)]  -- ^ list of cases to attempt-       -> Exp b                         -- ^ default value-       -> Exp b-caseof _ []        e = e-caseof x ((p,b):l) e = cond (p x) b (caseof x l e)----- Scalar iteration--- -------------------- | Repeatedly apply a function a fixed number of times----iterate :: forall a. Elt a-        => Exp Int-        -> (Exp a -> Exp a)-        -> Exp a-        -> Exp a-iterate n f z-  = let step :: (Exp Int, Exp a) -> (Exp Int, Exp a)-        step (i, acc)   = ( i+1, f acc )-    in-    snd $ while (\v -> fst v <* n) (lift1 step) (lift (constant 0, z))----- Scalar bulk operations--- -------------------------- | 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-sfoldl f z ix xs-  = let step :: (Exp Int, Exp a) -> (Exp Int, Exp a)-        step (i, acc)   = ( i+1, acc `f` (xs ! lift (ix :. i)) )-        (_ :. n)        = unlift (shape xs)     :: Exp sh :. Exp Int-    in-    snd $ while (\v -> fst v <* n) (lift1 step) (lift (constant 0, z))----- Lifting surface expressions--- ------------------------------- | The class of types @e@ which can be lifted into @c@.-class Lift c e where-  -- | An associated-type (i.e. a type-level function) that strips all-  --   instances of surface type constructors @c@ from the input type @e@.-  ---  --   For example, the tuple types @(Exp Int, Int)@ and @(Int, Exp-  --   Int)@ have the same \"Plain\" representation.  That is, the-  --   following type equality holds:-  ---  --    @Plain (Exp Int, Int) ~ (Int,Int) ~ Plain (Int, Exp Int)@-  type 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 :: e -> c (Plain e)---- | A limited subset of types which can be lifted, can also be unlifted.-class Lift c e => Unlift c e where--  -- | 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 :: c (Plain e) -> e---- instances for indices--instance Lift Exp () where-  type Plain () = ()-  lift _ = Exp $ Tuple NilTup--instance Unlift Exp () where-  unlift _ = ()--instance Lift Exp Z where-  type Plain Z = Z-  lift _ = Exp $ IndexNil--instance Unlift Exp Z where-  unlift _ = Z--instance (Slice (Plain ix), Lift Exp ix) => Lift Exp (ix :. Int) where-  type Plain (ix :. Int) = Plain ix :. Int-  lift (ix:.i) = Exp $ IndexCons (lift ix) (Exp $ Const i)--instance (Slice (Plain ix), Lift Exp ix) => Lift Exp (ix :. All) where-  type Plain (ix :. All) = Plain ix :. All-  lift (ix:.i) = Exp $ IndexCons (lift ix) (Exp $ Const i)--instance (Elt e, Slice (Plain ix), Lift Exp ix) => Lift Exp (ix :. Exp e) where-  type Plain (ix :. Exp e) = Plain ix :. e-  lift (ix:.i) = Exp $ IndexCons (lift ix) i--instance (Elt e, Slice (Plain ix), Unlift Exp ix) => Unlift Exp (ix :. Exp e) where-  unlift e = unlift (Exp $ IndexTail e) :. Exp (IndexHead e)--instance (Elt e, Slice ix) => Unlift Exp (Exp ix :. Exp e) where-  unlift e = (Exp $ IndexTail e) :. Exp (IndexHead e)--instance Shape sh => Lift Exp (Any sh) where- type Plain (Any sh) = Any sh- lift Any = Exp $ IndexAny---- instances for numeric types--instance Lift Exp Int where-  type Plain Int = Int-  lift = Exp . Const--instance Lift Exp Int8 where-  type Plain Int8 = Int8-  lift = Exp . Const--instance Lift Exp Int16 where-  type Plain Int16 = Int16-  lift = Exp . Const--instance Lift Exp Int32 where-  type Plain Int32 = Int32-  lift = Exp . Const--instance Lift Exp Int64 where-  type Plain Int64 = Int64-  lift = Exp . Const--instance Lift Exp Word where-  type Plain Word = Word-  lift = Exp . Const--instance Lift Exp Word8 where-  type Plain Word8 = Word8-  lift = Exp . Const--instance Lift Exp Word16 where-  type Plain Word16 = Word16-  lift = Exp . Const--instance Lift Exp Word32 where-  type Plain Word32 = Word32-  lift = Exp . Const--instance Lift Exp Word64 where-  type Plain Word64 = Word64-  lift = Exp . Const--instance Lift Exp CShort where-  type Plain CShort = CShort-  lift = Exp . Const--instance Lift Exp CUShort where-  type Plain CUShort = CUShort-  lift = Exp . Const--instance Lift Exp CInt where-  type Plain CInt = CInt-  lift = Exp . Const--instance Lift Exp CUInt where-  type Plain CUInt = CUInt-  lift = Exp . Const--instance Lift Exp CLong where-  type Plain CLong = CLong-  lift = Exp . Const--instance Lift Exp CULong where-  type Plain CULong = CULong-  lift = Exp . Const--instance Lift Exp CLLong where-  type Plain CLLong = CLLong-  lift = Exp . Const--instance Lift Exp CULLong where-  type Plain CULLong = CULLong-  lift = Exp . Const--instance Lift Exp Float where-  type Plain Float = Float-  lift = Exp . Const--instance Lift Exp Double where-  type Plain Double = Double-  lift = Exp . Const--instance Lift Exp CFloat where-  type Plain CFloat = CFloat-  lift = Exp . Const--instance Lift Exp CDouble where-  type Plain CDouble = CDouble-  lift = Exp . Const--instance Lift Exp Bool where-  type Plain Bool = Bool-  lift = Exp . Const--instance Lift Exp Char where-  type Plain Char = Char-  lift = Exp . Const--instance Lift Exp CChar where-  type Plain CChar = CChar-  lift = Exp . Const--instance Lift Exp CSChar where-  type Plain CSChar = CSChar-  lift = Exp . Const--instance Lift Exp CUChar where-  type Plain CUChar = CUChar-  lift = Exp . Const---- Instances for tuples--instance (Lift Exp a, Lift Exp b, Elt (Plain a), Elt (Plain b)) => Lift Exp (a, b) where-  type Plain (a, b) = (Plain a, Plain b)-  lift (x, y) = tup2 (lift x, lift y)--instance (Elt a, Elt b) => Unlift Exp (Exp a, Exp b) where-  unlift = untup2--instance (Lift Exp a, Lift Exp b, Lift Exp c,-          Elt (Plain a), Elt (Plain b), Elt (Plain c))-  => Lift Exp (a, b, c) where-  type Plain (a, b, c) = (Plain a, Plain b, Plain c)-  lift (x, y, z) = tup3 (lift x, lift y, lift z)--instance (Elt a, Elt b, Elt c) => Unlift Exp (Exp a, Exp b, Exp c) where-  unlift = untup3--instance (Lift Exp a, Lift Exp b, Lift Exp c, Lift Exp d,-          Elt (Plain a), Elt (Plain b), Elt (Plain c), Elt (Plain d))-  => Lift Exp (a, b, c, d) where-  type Plain (a, b, c, d) = (Plain a, Plain b, Plain c, Plain d)-  lift (x, y, z, u) = tup4 (lift x, lift y, lift z, lift u)--instance (Elt a, Elt b, Elt c, Elt d) => Unlift Exp (Exp a, Exp b, Exp c, Exp d) where-  unlift = untup4--instance (Lift Exp a, Lift Exp b, Lift Exp c, Lift Exp d, Lift Exp e,-          Elt (Plain a), Elt (Plain b), Elt (Plain c), Elt (Plain d), Elt (Plain e))-  => Lift Exp (a, b, c, d, e) where-  type Plain (a, b, c, d, e) = (Plain a, Plain b, Plain c, Plain d, Plain e)-  lift (x, y, z, u, v) = tup5 (lift x, lift y, lift z, lift u, lift v)--instance (Elt a, Elt b, Elt c, Elt d, Elt e)-  => Unlift Exp (Exp a, Exp b, Exp c, Exp d, Exp e) where-  unlift = untup5--instance (Lift Exp a, Lift Exp b, Lift Exp c, Lift Exp d, Lift Exp e, Lift Exp f,-          Elt (Plain a), Elt (Plain b), Elt (Plain c), Elt (Plain d), Elt (Plain e), Elt (Plain f))-  => Lift Exp (a, b, c, d, e, f) where-  type Plain (a, b, c, d, e, f) = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f)-  lift (x, y, z, u, v, w) = tup6 (lift x, lift y, lift z, lift u, lift v, lift w)--instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f)-  => Unlift Exp (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f) where-  unlift = untup6--instance (Lift Exp a, Lift Exp b, Lift Exp c, Lift Exp d, Lift Exp e, Lift Exp f, Lift Exp g,-          Elt (Plain a), Elt (Plain b), Elt (Plain c), Elt (Plain d), Elt (Plain e), Elt (Plain f),-          Elt (Plain g))-  => Lift Exp (a, b, c, d, e, f, g) where-  type Plain (a, b, c, d, e, f, g) = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g)-  lift (x, y, z, u, v, w, r) = tup7 (lift x, lift y, lift z, lift u, lift v, lift w, lift r)--instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g)-  => Unlift Exp (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g) where-  unlift = untup7--instance (Lift Exp a, Lift Exp b, Lift Exp c, Lift Exp d, Lift Exp e, Lift Exp f, Lift Exp g, Lift Exp h,-          Elt (Plain a), Elt (Plain b), Elt (Plain c), Elt (Plain d), Elt (Plain e), Elt (Plain f),-          Elt (Plain g), Elt (Plain h))-  => Lift Exp (a, b, c, d, e, f, g, h) where-  type Plain (a, b, c, d, e, f, g, h)-    = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h)-  lift (x, y, z, u, v, w, r, s)-    = tup8 (lift x, lift y, lift z, lift u, lift v, lift w, lift r, lift s)--instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h)-  => Unlift Exp (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h) where-  unlift = untup8--instance (Lift Exp a, Lift Exp b, Lift Exp c, Lift Exp d, Lift Exp e,-          Lift Exp f, Lift Exp g, Lift Exp h, Lift Exp i,-          Elt (Plain a), Elt (Plain b), Elt (Plain c), Elt (Plain d), Elt (Plain e),-          Elt (Plain f), Elt (Plain g), Elt (Plain h), Elt (Plain i))-  => Lift Exp (a, b, c, d, e, f, g, h, i) where-  type Plain (a, b, c, d, e, f, g, h, i)-    = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i)-  lift (x, y, z, u, v, w, r, s, t)-    = tup9 (lift x, lift y, lift z, lift u, lift v, lift w, lift r, lift s, lift t)--instance (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i)-  => Unlift Exp (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i) where-  unlift = untup9---- Instance for scalar Accelerate expressions--instance Lift Exp (Exp e) where-  type Plain (Exp e) = e-  lift = id----- Instance for Accelerate array computations--instance Lift Acc (Acc a) where-  type Plain (Acc a) = a-  lift = id---- Instances for Arrays class----instance Lift Acc () where---  type Plain () = ()---  lift _ = Acc (Atuple NilAtup)--instance (Shape sh, Elt e) => Lift Acc (Array sh e) where-  type Plain (Array sh e) = Array sh e-  lift = Acc . Use--instance (Lift Acc a, Lift Acc b, Arrays (Plain a), Arrays (Plain b)) => Lift Acc (a, b) where-  type Plain (a, b) = (Plain a, Plain b)-  lift (x, y) = atup2 (lift x, lift y)--instance (Arrays a, Arrays b) => Unlift Acc (Acc a, Acc b) where-  unlift = unatup2--instance (Lift Acc a, Lift Acc b, Lift Acc c,-          Arrays (Plain a), Arrays (Plain b), Arrays (Plain c))-  => Lift Acc (a, b, c) where-  type Plain (a, b, c) = (Plain a, Plain b, Plain c)-  lift (x, y, z) = atup3 (lift x, lift y, lift z)--instance (Arrays a, Arrays b, Arrays c) => Unlift Acc (Acc a, Acc b, Acc c) where-  unlift = unatup3--instance (Lift Acc a, Lift Acc b, Lift Acc c, Lift Acc d,-          Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d))-  => Lift Acc (a, b, c, d) where-  type Plain (a, b, c, d) = (Plain a, Plain b, Plain c, Plain d)-  lift (x, y, z, u) = atup4 (lift x, lift y, lift z, lift u)--instance (Arrays a, Arrays b, Arrays c, Arrays d) => Unlift Acc (Acc a, Acc b, Acc c, Acc d) where-  unlift = unatup4--instance (Lift Acc a, Lift Acc b, Lift Acc c, Lift Acc d, Lift Acc e,-          Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e))-  => Lift Acc (a, b, c, d, e) where-  type Plain (a, b, c, d, e) = (Plain a, Plain b, Plain c, Plain d, Plain e)-  lift (x, y, z, u, v) = atup5 (lift x, lift y, lift z, lift u, lift v)--instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e)-  => Unlift Acc (Acc a, Acc b, Acc c, Acc d, Acc e) where-  unlift = unatup5--instance (Lift Acc a, Lift Acc b, Lift Acc c, Lift Acc d, Lift Acc e, Lift Acc f,-          Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e), Arrays (Plain f))-  => Lift Acc (a, b, c, d, e, f) where-  type Plain (a, b, c, d, e, f) = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f)-  lift (x, y, z, u, v, w) = atup6 (lift x, lift y, lift z, lift u, lift v, lift w)--instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f)-  => Unlift Acc (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f) where-  unlift = unatup6--instance (Lift Acc a, Lift Acc b, Lift Acc c, Lift Acc d, Lift Acc e, Lift Acc f, Lift Acc g,-          Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e), Arrays (Plain f),-          Arrays (Plain g))-  => Lift Acc (a, b, c, d, e, f, g) where-  type Plain (a, b, c, d, e, f, g) = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g)-  lift (x, y, z, u, v, w, r) = atup7 (lift x, lift y, lift z, lift u, lift v, lift w, lift r)--instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g)-  => Unlift Acc (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g) where-  unlift = unatup7--instance (Lift Acc a, Lift Acc b, Lift Acc c, Lift Acc d, Lift Acc e, Lift Acc f, Lift Acc g, Lift Acc h,-          Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e), Arrays (Plain f),-          Arrays (Plain g), Arrays (Plain h))-  => Lift Acc (a, b, c, d, e, f, g, h) where-  type Plain (a, b, c, d, e, f, g, h)-    = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h)-  lift (x, y, z, u, v, w, r, s)-    = atup8 (lift x, lift y, lift z, lift u, lift v, lift w, lift r, lift s)--instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h)-  => Unlift Acc (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h) where-  unlift = unatup8--instance (Lift Acc a, Lift Acc b, Lift Acc c, Lift Acc d, Lift Acc e,-          Lift Acc f, Lift Acc g, Lift Acc h, Lift Acc i,-          Arrays (Plain a), Arrays (Plain b), Arrays (Plain c), Arrays (Plain d), Arrays (Plain e),-          Arrays (Plain f), Arrays (Plain g), Arrays (Plain h), Arrays (Plain i))-  => Lift Acc (a, b, c, d, e, f, g, h, i) where-  type Plain (a, b, c, d, e, f, g, h, i)-    = (Plain a, Plain b, Plain c, Plain d, Plain e, Plain f, Plain g, Plain h, Plain i)-  lift (x, y, z, u, v, w, r, s, t)-    = atup9 (lift x, lift y, lift z, lift u, lift v, lift w, lift r, lift s, lift t)--instance (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i)-  => Unlift Acc (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i) where-  unlift = unatup9------ |Lift a unary function into 'Exp'.----lift1 :: (Unlift Exp e1, Lift Exp e2)-      => (e1 -> e2)-      -> Exp (Plain e1)-      -> Exp (Plain e2)-lift1 f = lift . f . unlift---- |Lift a binary function into 'Exp'.----lift2 :: (Unlift Exp e1, Unlift Exp e2, Lift Exp e3)-      => (e1 -> e2 -> e3)-      -> Exp (Plain e1)-      -> Exp (Plain e2)-      -> Exp (Plain e3)-lift2 f x y = lift $ f (unlift x) (unlift y)---- |Lift a unary function to a computation over rank-1 indices.----ilift1 :: (Exp Int -> Exp Int) -> Exp DIM1 -> Exp DIM1-ilift1 f = lift1 (\(Z:.i) -> Z :. f i)---- |Lift a binary function to a computation over rank-1 indices.----ilift2 :: (Exp Int -> Exp Int -> Exp Int) -> Exp DIM1 -> Exp DIM1 -> Exp DIM1-ilift2 f = lift2 (\(Z:.i) (Z:.j) -> Z :. f i j)----- Tuples--- ---------- |Extract the first component of a scalar pair.----fst :: forall a b. (Elt a, Elt b) => Exp (a, b) -> Exp a-fst e = let (x, _::Exp b) = unlift e in x---- |Extract the first component of an array pair.-afst :: forall a b. (Arrays a, Arrays b) => Acc (a, b) -> Acc a-afst a = let (x, _::Acc b) = unlift a in x---- |Extract the second component of a scalar pair.----snd :: forall a b. (Elt a, Elt b) => Exp (a, b) -> Exp b-snd e = let (_:: Exp a, y) = unlift e in y---- | Extract the second component of an array pair-asnd :: forall a b. (Arrays a, Arrays b) => Acc (a, b) -> Acc b-asnd a = let (_::Acc a, y) = unlift a in y---- |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-curry f x y = f (lift (x, y))---- |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-uncurry f t = let (x, y) = unlift t in f x y----- Shapes and indices--- ---------------------- |The one index for a rank-0 array.----index0 :: Exp Z-index0 = lift Z---- |Turn an 'Int' expression into a rank-1 indexing expression.----index1 :: Elt i => Exp i -> Exp (Z :. i)-index1 i = lift (Z :. i)---- |Turn a rank-1 indexing expression into an 'Int' expression.----unindex1 :: Elt i => Exp (Z :. i) -> Exp i-unindex1 ix = let Z :. i = unlift ix in 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)-index2 i j = lift (Z :. i :. j)---- | 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)-unindex2 ix-  = let Z :. i :. j = unlift ix :: Z :. Exp i :. Exp i-    in  lift (i, j)---- Array operations with a scalar result--- ----------------------------------------- |Extraction of the element in a singleton array----the :: Elt e => Acc (Scalar e) -> Exp e-the = (!index0)---- |Test whether an array is empty----null :: (Shape ix, Elt e) => Acc (Array ix e) -> Exp Bool-null arr = size arr ==* 0---- |Get the length of a vector----length :: Elt e => Acc (Vector e) -> Exp Int-length = unindex1 . shape+{-# LANGUAGE ConstraintKinds       #-}+{-# LANGUAGE FlexibleContexts      #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PatternGuards         #-}+{-# LANGUAGE RebindableSyntax      #-}+{-# LANGUAGE ScopedTypeVariables   #-}+{-# LANGUAGE TypeFamilies          #-}+{-# LANGUAGE TypeOperators         #-}+-- |+-- Module      : Data.Array.Accelerate.Prelude+-- Copyright   : [2009..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+--               [2010..2011] Ben Lever+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- Standard functions that are not part of the core set (directly represented in+-- the AST), but are instead implemented in terms of the core set.+--++module Data.Array.Accelerate.Prelude (++  -- * Element-wise operations+  indexed,+  imap,++  -- * Zipping+  zipWith3, zipWith4, zipWith5, zipWith6, zipWith7, zipWith8, zipWith9,+  izipWith, izipWith3, izipWith4, izipWith5, izipWith6, izipWith7, izipWith8, izipWith9,+  zip, zip3, zip4, zip5, zip6, zip7, zip8, zip9,++  -- * Unzipping+  unzip, unzip3, unzip4, unzip5, unzip6, unzip7, unzip8, unzip9,++  -- * Reductions+  foldAll, fold1All,++  -- ** Specialised folds+  all, any, and, or, sum, product, minimum, maximum,++  -- * Scans+  prescanl, postscanl, prescanr, postscanr,++  -- ** Segmented scans+  scanlSeg, scanl'Seg, scanl1Seg, prescanlSeg, postscanlSeg,+  scanrSeg, scanr'Seg, scanr1Seg, prescanrSeg, postscanrSeg,++  -- * Shape manipulation+  flatten,++  -- * Enumeration and filling+  fill, enumFromN, enumFromStepN,++  -- * Concatenation+  (++),++  -- * Working with predicates+  -- ** Filtering+  filter,++  -- ** Scatter / Gather+  scatter, scatterIf,+  gather,  gatherIf,++  -- * Permutations+  reverse, transpose,++  -- * Extracting sub-vectors+  init, tail, take, drop, slit,++  -- * Controlling execution+  compute,++  -- * Flow control+  IfThenElse(..),++  -- ** Array-level+  (?|),++  -- ** Expression-level+  (?), caseof,++  -- * Scalar iteration+  iterate,++  -- * Scalar reduction+  sfoldl, -- sfoldr,++  -- * Lifting and unlifting+  Lift(..), Unlift(..),+  lift1, lift2, lift3, ilift1, ilift2, ilift3,++  -- ** Tuple construction and destruction+  fst, afst, snd, asnd, curry, uncurry,++  -- ** Index construction and destruction+  index0, index1, unindex1, index2, unindex2, index3, unindex3,++  -- * Array operations with a scalar result+  the, null, length,++  -- * Sequence operations+  -- fromSeq, fromSeqElems, fromSeqShapes, toSeqInner, toSeqOuter2, toSeqOuter3, generateSeq,++) where++-- avoid clashes with Prelude functions+--+import Data.Typeable                                                ( gcast )+import GHC.Base                                                     ( Constraint )+import Prelude                                                      ( (.), ($), Maybe(..), const, id, fromInteger, flip, undefined, fail )+import qualified Prelude                                            as P++-- friends+import Data.Array.Accelerate.Analysis.Match+import Data.Array.Accelerate.Array.Sugar                            hiding ( (!), ignore, shape, size, intersect, toIndex, fromIndex )+import Data.Array.Accelerate.Classes+import Data.Array.Accelerate.Language+import Data.Array.Accelerate.Lift+import Data.Array.Accelerate.Smart+import Data.Array.Accelerate.Type++import Data.Array.Accelerate.Data.Bits+++-- Element-wise operations+-- -----------------------++-- | Pair each element with its index+--+indexed :: (Shape sh, Elt a) => Acc (Array sh a) -> Acc (Array sh (sh, a))+indexed xs = zip (generate (shape xs) id) xs++-- | 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)+imap f xs = zipWith f (generate (shape xs) id) xs+++-- | 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)+zipWith3 f as bs cs+  = generate (shape as `intersect` shape bs `intersect` shape cs)+             (\ix -> f (as ! ix) (bs ! ix) (cs ! ix))++-- | 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)+zipWith4 f as bs cs ds+  = generate (shape as `intersect` shape bs `intersect`+              shape cs `intersect` shape ds)+             (\ix -> f (as ! ix) (bs ! ix) (cs ! ix) (ds ! ix))++-- | 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)+zipWith5 f as bs cs ds es+  = generate (shape as `intersect` shape bs `intersect` shape cs+                       `intersect` shape ds `intersect` shape es)+             (\ix -> f (as ! ix) (bs ! ix) (cs ! ix) (ds ! ix) (es ! ix))++-- | 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)+zipWith6 f as bs cs ds es fs+  = generate (shape as `intersect` shape bs `intersect` shape cs+                       `intersect` shape ds `intersect` shape es+                       `intersect` shape fs)+             (\ix -> f (as ! ix) (bs ! ix) (cs ! ix) (ds ! ix) (es ! ix) (fs ! ix))++-- | 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)+zipWith7 f as bs cs ds es fs gs+  = generate (shape as `intersect` shape bs `intersect` shape cs+                       `intersect` shape ds `intersect` shape es+                       `intersect` shape fs `intersect` shape gs)+             (\ix -> f (as ! ix) (bs ! ix) (cs ! ix) (ds ! ix) (es ! ix) (fs ! ix) (gs ! ix))++-- | 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)+zipWith8 f as bs cs ds es fs gs hs+  = generate (shape as `intersect` shape bs `intersect` shape cs+                       `intersect` shape ds `intersect` shape es+                       `intersect` shape fs `intersect` shape gs+                       `intersect` shape hs)+             (\ix -> f (as ! ix) (bs ! ix) (cs ! ix) (ds ! ix) (es ! ix) (fs ! ix) (gs ! ix) (hs ! ix))++-- | 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)+zipWith9 f as bs cs ds es fs gs hs is+  = generate (shape as `intersect` shape bs `intersect` shape cs+                       `intersect` shape ds `intersect` shape es+                       `intersect` shape fs `intersect` shape gs+                       `intersect` shape hs `intersect` shape is)+             (\ix -> f (as ! ix) (bs ! ix) (cs ! ix) (ds ! ix) (es ! ix) (fs ! ix) (gs ! ix) (hs ! ix) (is ! ix))+++-- | 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)+izipWith f as bs+  = generate (shape as `intersect` shape bs)+             (\ix -> f ix (as ! ix) (bs ! ix))++-- | 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)+izipWith3 f as bs cs+  = generate (shape as `intersect` shape bs `intersect` shape cs)+             (\ix -> f ix (as ! ix) (bs ! ix) (cs ! ix))++-- | 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)+izipWith4 f as bs cs ds+  = generate (shape as `intersect` shape bs `intersect`+              shape cs `intersect` shape ds)+             (\ix -> f ix (as ! ix) (bs ! ix) (cs ! ix) (ds ! ix))++-- | 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)+izipWith5 f as bs cs ds es+  = generate (shape as `intersect` shape bs `intersect` shape cs+                       `intersect` shape ds `intersect` shape es)+             (\ix -> f ix (as ! ix) (bs ! ix) (cs ! ix) (ds ! ix) (es ! ix))++-- | 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)+izipWith6 f as bs cs ds es fs+  = generate (shape as `intersect` shape bs `intersect` shape cs+                       `intersect` shape ds `intersect` shape es+                       `intersect` shape fs)+             (\ix -> f ix (as ! ix) (bs ! ix) (cs ! ix) (ds ! ix) (es ! ix) (fs ! ix))++-- | 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)+izipWith7 f as bs cs ds es fs gs+  = generate (shape as `intersect` shape bs `intersect` shape cs+                       `intersect` shape ds `intersect` shape es+                       `intersect` shape fs `intersect` shape gs)+             (\ix -> f ix (as ! ix) (bs ! ix) (cs ! ix) (ds ! ix) (es ! ix) (fs ! ix) (gs ! ix))++-- | 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)+izipWith8 f as bs cs ds es fs gs hs+  = generate (shape as `intersect` shape bs `intersect` shape cs+                       `intersect` shape ds `intersect` shape es+                       `intersect` shape fs `intersect` shape gs+                       `intersect` shape hs)+             (\ix -> f ix (as ! ix) (bs ! ix) (cs ! ix) (ds ! ix) (es ! ix) (fs ! ix) (gs ! ix) (hs ! ix))++-- | 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)+izipWith9 f as bs cs ds es fs gs hs is+  = generate (shape as `intersect` shape bs `intersect` shape cs+                       `intersect` shape ds `intersect` shape es+                       `intersect` shape fs `intersect` shape gs+                       `intersect` shape hs `intersect` shape is)+             (\ix -> f ix (as ! ix) (bs ! ix) (cs ! ix) (ds ! ix) (es ! ix) (fs ! ix) (gs ! ix) (hs ! ix) (is ! ix))+++-- | 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))+zip = zipWith (curry lift)++-- | 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))+zip3 = zipWith3 (\a b c -> lift (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))+zip4 = zipWith4 (\a b c d -> lift (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))+zip5 = zipWith5 (\a b c d e -> lift (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))+zip6 = zipWith6 (\a b c d e f -> lift (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))+zip7 = zipWith7 (\a b c d e f g -> lift (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))+zip8 = zipWith8 (\a b c d e f g h -> lift (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))+zip9 = zipWith9 (\a b c d e f g h i -> lift (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))+unzip arr = (map fst arr, map snd arr)++-- | 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))+unzip3 xs = (map get1 xs, map get2 xs, map get3 xs)+  where+    get1 x = let (a,_,_) = untup3 x in a+    get2 x = let (_,b,_) = untup3 x in b+    get3 x = let (_,_,c) = untup3 x in 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))+unzip4 xs = (map get1 xs, map get2 xs, map get3 xs, map get4 xs)+  where+    get1 x = let (a,_,_,_) = untup4 x in a+    get2 x = let (_,b,_,_) = untup4 x in b+    get3 x = let (_,_,c,_) = untup4 x in c+    get4 x = let (_,_,_,d) = untup4 x in 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))+unzip5 xs = (map get1 xs, map get2 xs, map get3 xs, map get4 xs, map get5 xs)+  where+    get1 x = let (a,_,_,_,_) = untup5 x in a+    get2 x = let (_,b,_,_,_) = untup5 x in b+    get3 x = let (_,_,c,_,_) = untup5 x in c+    get4 x = let (_,_,_,d,_) = untup5 x in d+    get5 x = let (_,_,_,_,e) = untup5 x in 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))+unzip6 xs = (map get1 xs, map get2 xs, map get3 xs, map get4 xs, map get5 xs, map get6 xs)+  where+    get1 x = let (a,_,_,_,_,_) = untup6 x in a+    get2 x = let (_,b,_,_,_,_) = untup6 x in b+    get3 x = let (_,_,c,_,_,_) = untup6 x in c+    get4 x = let (_,_,_,d,_,_) = untup6 x in d+    get5 x = let (_,_,_,_,e,_) = untup6 x in e+    get6 x = let (_,_,_,_,_,f) = untup6 x in 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))+unzip7 xs = ( map get1 xs, map get2 xs, map get3 xs+            , map get4 xs, map get5 xs, map get6 xs+            , map get7 xs )+  where+    get1 x = let (a,_,_,_,_,_,_) = untup7 x in a+    get2 x = let (_,b,_,_,_,_,_) = untup7 x in b+    get3 x = let (_,_,c,_,_,_,_) = untup7 x in c+    get4 x = let (_,_,_,d,_,_,_) = untup7 x in d+    get5 x = let (_,_,_,_,e,_,_) = untup7 x in e+    get6 x = let (_,_,_,_,_,f,_) = untup7 x in f+    get7 x = let (_,_,_,_,_,_,g) = untup7 x in 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) )+unzip8 xs = ( map get1 xs, map get2 xs, map get3 xs+            , map get4 xs, map get5 xs, map get6 xs+            , map get7 xs, map get8 xs )+  where+    get1 x = let (a,_,_,_,_,_,_,_) = untup8 x in a+    get2 x = let (_,b,_,_,_,_,_,_) = untup8 x in b+    get3 x = let (_,_,c,_,_,_,_,_) = untup8 x in c+    get4 x = let (_,_,_,d,_,_,_,_) = untup8 x in d+    get5 x = let (_,_,_,_,e,_,_,_) = untup8 x in e+    get6 x = let (_,_,_,_,_,f,_,_) = untup8 x in f+    get7 x = let (_,_,_,_,_,_,g,_) = untup8 x in g+    get8 x = let (_,_,_,_,_,_,_,h) = untup8 x in 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))+unzip9 xs = ( map get1 xs, map get2 xs, map get3 xs+            , map get4 xs, map get5 xs, map get6 xs+            , map get7 xs, map get8 xs, map get9 xs )+  where+    get1 x = let (a,_,_,_,_,_,_,_,_) = untup9 x in a+    get2 x = let (_,b,_,_,_,_,_,_,_) = untup9 x in b+    get3 x = let (_,_,c,_,_,_,_,_,_) = untup9 x in c+    get4 x = let (_,_,_,d,_,_,_,_,_) = untup9 x in d+    get5 x = let (_,_,_,_,e,_,_,_,_) = untup9 x in e+    get6 x = let (_,_,_,_,_,f,_,_,_) = untup9 x in f+    get7 x = let (_,_,_,_,_,_,g,_,_) = untup9 x in g+    get8 x = let (_,_,_,_,_,_,_,h,_) = untup9 x in h+    get9 x = let (_,_,_,_,_,_,_,_,i) = untup9 x in i+++-- Reductions+-- ----------++-- | 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)+foldAll f e arr = fold f e (flatten arr)++-- | 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)+fold1All f arr = fold1 f (flatten arr)+++-- Specialised reductions+-- ----------------------+--+-- Leave the results of these as scalar arrays to make it clear that these are+-- array computations, and thus can not be nested.++-- | Check if all elements satisfy a predicate+--+all :: (Shape sh, Elt e)+    => (Exp e -> Exp Bool)+    -> Acc (Array sh e)+    -> Acc (Scalar Bool)+all f = and . map f++-- | Check if any element satisfies the predicate+--+any :: (Shape sh, Elt e)+    => (Exp e -> Exp Bool)+    -> Acc (Array sh e)+    -> Acc (Scalar Bool)+any f = or . map f++-- | Check if all elements are 'True'+--+and :: Shape sh+    => Acc (Array sh Bool)+    -> Acc (Scalar Bool)+and = foldAll (&&) (constant True)++-- | Check if any element is 'True'+--+or :: Shape sh+   => Acc (Array sh Bool)+   -> Acc (Scalar Bool)+or = foldAll (||) (constant False)++-- | Compute the sum of elements+--+sum :: (Shape sh, Num e)+    => Acc (Array sh e)+    -> Acc (Scalar e)+sum = foldAll (+) 0++-- | Compute the product of the elements+--+product :: (Shape sh, Num e)+        => Acc (Array sh e)+        -> Acc (Scalar e)+product = foldAll (*) 1++-- | 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)+minimum = fold1All min++-- | 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)+maximum = fold1All max+++-- Composite scans+-- ---------------++-- | 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)+prescanl f e = P.fst . scanl' f e++-- | 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)+postscanl f e = map (e `f`) . scanl1 f++-- |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)+prescanr f e = P.fst . scanr' f e++-- |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)+postscanr f e = map (`f` e) . scanr1 f+++-- Segmented scans+-- ---------------++-- | 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)+scanlSeg f z arr seg =+  if null arr || null flags+    then fill (lift (sh:.sz + length seg)) z+    else scanl1Seg f arr' seg'+  where+    sh :. sz    = unlift (shape arr) :: Exp sh :. Exp Int++    -- Segmented exclusive scan is implemented by first injecting the seed+    -- element at the head of each segment, and then performing a segmented+    -- inclusive scan.+    --+    -- This is done by creating a creating a vector entirely of the seed+    -- element, and overlaying the input data in all places other than at the+    -- start of a segment.+    --+    seg'        = map (+1) seg+    arr'        = permute const+                          (fill (lift (sh :. sz + length seg)) z)+                          (\ix -> let sx :. i = unlift ix :: Exp sh :. Exp Int+                                  in  lift (sx :. i + fromIntegral (inc ! index1 i)))+                          (take (length flags) arr)++    -- Each element in the segments must be shifted to the right one additional+    -- place for each successive segment, to make room for the seed element.+    -- Here, we make use of the fact that the vector returned by 'mkHeadFlags'+    -- contains non-unit entries, which indicate zero length segments.+    --+    flags       = mkHeadFlags seg+    inc         = scanl1 (+) flags+++-- | 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)+scanl'Seg f z arr seg =+  if null arr+    then lift (arr,  fill (lift (indexTail (shape arr) :. length seg)) z)+    else lift (body, sums)+  where+    -- Segmented scan' is implemented by deconstructing a segmented exclusive+    -- scan, to separate the final value and scan body.+    --+    -- TLM: Segmented scans, and this version in particular, expend a lot of+    --      effort scanning flag arrays. On inspection it appears that several+    --      of these operations are duplicated, but this will not be picked up+    --      by sharing _observation_. Perhaps a global CSE-style pass would be+    --      beneficial.+    --+    arr'        = scanlSeg f z arr seg++    -- Extract the final reduction value for each segment, which is at the last+    -- index of each segment.+    --+    seg'        = map (+1) seg+    tails       = zipWith (+) seg . P.fst $ scanl' (+) 0 seg'+    sums        = backpermute+                    (lift (indexTail (shape arr') :. length seg))+                    (\ix -> let sz:.i = unlift ix :: Exp sh :. Exp Int+                            in  lift (sz :. fromIntegral (tails ! index1 i)))+                    arr'++    -- Slice out the body of each segment.+    --+    -- Build a head-flags representation based on the original segment+    -- descriptor. This contains the target length of each of the body segments,+    -- which is one fewer element than the actual bodies stored in arr'. Thus,+    -- the flags align with the last element of each body section, and when+    -- scanned, this element will be incremented over.+    --+    offset      = scanl1 (+) seg+    inc         = scanl1 (+)+                $ permute (+) (fill (index1 $ size arr + 1) 0)+                              (\ix -> index1' $ offset ! ix)+                              (fill (shape seg) (1 :: Exp i))++    len         = offset ! index1 (length offset - 1)+    body        = backpermute+                    (lift (indexTail (shape arr) :. fromIntegral len))+                    (\ix -> let sz:.i = unlift ix :: Exp sh :. Exp Int+                            in  lift (sz :. i + fromIntegral (inc ! index1 i)))+                    arr'+++-- | 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)+scanl1Seg f arr seg+  = P.snd+  . unzip+  . scanl1 (segmented f)+  $ zip (replicate (lift (indexTail (shape arr) :. All)) (mkHeadFlags seg)) arr++-- |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)+prescanlSeg f e vec seg+  = afst+  $ scanl'Seg f e vec seg++-- |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)+postscanlSeg f e vec seg+  = map (f e)+  $ scanl1Seg f vec seg++-- | 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)+scanrSeg f z arr seg =+  if null arr || null flags+    then fill (lift (sh :. sz + length seg)) z+    else scanr1Seg f arr' seg'+  where+    sh :. sz    = unlift (shape arr) :: Exp sh :. Exp Int++    -- Using technique described for 'scanlSeg', where we intersperse the array+    -- with the seed element at the start of each segment, and then perform an+    -- inclusive segmented scan.+    --+    flags       = mkHeadFlags seg+    inc         = scanl1 (+) flags++    seg'        = map (+1) seg+    arr'        = permute const+                          (fill (lift (sh :. sz + length seg)) z)+                          (\ix -> let sx :. i = unlift ix :: Exp sh :. Exp Int+                                  in  lift (sx :. i + fromIntegral (inc ! index1 i) - 1))+                          (drop (sz - length flags) arr)+++-- | 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)+scanr'Seg f z arr seg =+  if null arr+    then lift (arr,  fill (lift (indexTail (shape arr) :. length seg)) z)+    else lift (body, sums)+  where+    -- Using technique described for scanl'Seg+    --+    arr'        = scanrSeg f z arr seg++    -- reduction values+    seg'        = map (+1) seg+    heads       = P.fst $ scanl' (+) 0 seg'+    sums        = backpermute+                    (lift (indexTail (shape arr') :. length seg))+                    (\ix -> let sz:.i = unlift ix :: Exp sh :. Exp Int+                            in  lift (sz :. fromIntegral (heads ! index1 i)))+                    arr'++    -- body segments+    flags       = mkHeadFlags seg+    inc         = scanl1 (+) flags+    body        = backpermute+                    (lift (indexTail (shape arr) :. indexHead (shape flags)))+                    (\ix -> let sz:.i = unlift ix :: Exp sh :. Exp Int+                            in  lift (sz :. i + fromIntegral (inc ! index1 i)))+                    arr'+++-- | 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)+scanr1Seg f arr seg+  = P.snd+  . unzip+  . scanr1 (flip (segmented f))+  $ zip (replicate (lift (indexTail (shape arr) :. All)) (mkTailFlags seg)) arr+++-- |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)+prescanrSeg f e vec seg+  = afst+  $ scanr'Seg f e vec seg++-- |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)+postscanrSeg f e vec seg+  = map (f e)+  $ scanr1Seg f vec seg+++-- Segmented scan helpers+-- ----------------------++-- |Compute head flags vector from segment vector for left-scans.+--+-- The vector will be full of zeros in the body of a segment, and non-zero+-- otherwise. The "flag" value, if greater than one, indicates that several+-- empty segments are represented by this single flag entry. This is additional+-- data is used by exclusive segmented scan.+--+mkHeadFlags+    :: (Integral i, FromIntegral i Int)+    => Acc (Segments i)+    -> Acc (Segments i)+mkHeadFlags seg+  = init+  $ permute (+) zeros (\ix -> index1' (offset ! ix)) ones+  where+    (offset, len)       = scanl' (+) 0 seg+    zeros               = fill (index1' $ the len + 1) 0+    ones                = fill (index1  $ size offset) 1++-- |Compute tail flags vector from segment vector for right-scans. That is, the+-- flag is placed at the last place in each segment.+--+mkTailFlags+    :: (Integral i, FromIntegral i Int)+    => Acc (Segments i)+    -> Acc (Segments i)+mkTailFlags seg+  = init+  $ permute (+) zeros (\ix -> index1' (the len - 1 - offset ! ix)) ones+  where+    (offset, len)       = scanr' (+) 0 seg+    zeros               = fill (index1' $ the len + 1) 0+    ones                = fill (index1  $ size offset) 1++-- |Construct a segmented version of a function from a non-segmented version.+-- The segmented apply operates on a head-flag value tuple, and follows the+-- procedure of Sengupta et. al.+--+segmented+    :: (Elt e, Num i, Bits i)+    => (Exp e -> Exp e -> Exp e)+    -> Exp (i, e)+    -> Exp (i, e)+    -> Exp (i, e)+segmented f a b =+  let (aF, aV) = unlift a+      (bF, bV) = unlift b+  in+  lift (aF .|. bF, bF /= 0 ? (bV, f aV bV))++-- |Index construction and destruction generalised to integral types.+--+-- We generalise the segment descriptor to integral types because some+-- architectures, such as GPUs, have poor performance for 64-bit types. So,+-- there is a tension between performance and requiring 64-bit indices for some+-- applications, and we would not like to restrict ourselves to either one.+--+-- As we don't yet support non-Int dimensions in shapes, we will need to convert+-- back to concrete Int. However, don't put these generalised forms into the+-- base library, because it results in too many ambiguity errors.+--+index1' ::  (Integral i, FromIntegral i Int) => Exp i -> Exp DIM1+index1' i = lift (Z :. fromIntegral i)+++-- Reshaping of arrays+-- -------------------++-- | 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)+flatten a+  | Just Refl <- matchShapeType (undefined::sh) (undefined::DIM1)+  = a+flatten a+  = reshape (index1 $ size a) a+++-- Enumeration and filling+-- -----------------------++-- | Create an array where all elements are the same value.+--+fill :: (Shape sh, Elt e) => Exp sh -> Exp e -> Acc (Array sh e)+fill sh c = generate sh (const c)++-- | Create an array of the given shape containing the values @x@, @x+1@, etc.+-- (in row-major order).+--+-- >>> 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)+enumFromN sh x = enumFromStepN sh x 1++-- | 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              -- ^ x: start+    -> Exp e              -- ^ y: step+    -> Acc (Array sh e)+enumFromStepN sh x y+  = reshape sh+  $ generate (index1 $ shapeSize sh)+             (\ix -> (fromIntegral (unindex1 ix :: Exp Int) * y) + x)++-- Concatenation+-- -------------++-- | 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]+--+infixr 5 +++(++) :: forall sh e. (Slice sh, Shape sh, Elt e)+     => Acc (Array (sh :. Int) e)+     -> Acc (Array (sh :. Int) e)+     -> Acc (Array (sh :. Int) e)+(++) xs ys+  = let sh1 :. n        = unlift (shape xs)     :: Exp sh :. Exp Int+        sh2 :. m        = unlift (shape ys)     :: Exp sh :. Exp Int+    in+    generate (lift (intersect sh1 sh2 :. n + m))+             (\ix -> let sh :. i = unlift ix    :: Exp sh :. Exp Int+                     in  i < n ? ( xs ! ix, ys ! lift (sh :. i-n)) )++-- TLM: If we have something like (concat . split) then the source array will+--      have two use sites, but is actually safe (and better) to inline.+++-- Filtering+-- ---------++-- | 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)+filter p arr+  -- Optimise 1-dimensional arrays, where we can avoid additional computations+  -- for the offset indices.+  | Just Refl <- matchShapeType (undefined::sh) (undefined::Z)+  = let+        keep            = map p arr+        (target, len)   = scanl' (+) 0 (map boolToInt keep)+        prj ix          = keep!ix ? ( index1 (target!ix), ignore )+        dummy           = backpermute (index1 (the len)) id arr+        result          = permute const dummy prj arr+    in+    if null arr+      then lift (emptyArray, fill (constant Z) 0)+      else lift (result, len)++filter p arr+  = let+        sz              = indexTail (shape arr)+        keep            = map p arr+        (target, len)   = scanl' (+) 0 (map boolToInt keep)+        (offset, valid) = scanl' (+) 0 (flatten len)+        prj ix          = if keep!ix+                            then index1 $ offset!index1 (toIndex sz (indexTail ix)) + target!ix+                            else ignore+        dummy           = backpermute (index1 (the valid)) id (flatten arr)+        result          = permute const dummy prj arr+    in+    if null arr+      then lift (emptyArray, fill sz 0)+      else lift (result, len)++-- FIXME: [Permute in the filter operation]+--+-- This is abusing 'permute' in that the first two arguments, the combination+-- function and array of default values, are only justified because we know the+-- permutation function will write to each location in the target exactly once.+--+-- Instead, we should have a primitive that directly encodes the compaction+-- pattern of the permutation function. This may be more efficient to compute,+-- and avoids the computation of the defaults array, which is ultimately wasted+-- work.+--++{-# NOINLINE filter #-}+{-# RULES+  "ACC filter/filter" forall f g arr.+    filter f (afst (filter g arr)) = filter (\x -> g x && f x) arr+ #-}+++-- Gather operations+-- -----------------++-- | 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)         -- ^ index of source at each index to gather+    -> Acc (Vector e)             -- ^ source values+    -> Acc (Array sh e)+gather indices input = map (input !!) indices+  -- TLM NOTES:+  --  * (!!) has potential for later optimisation+  --  * We needn't fix the source array to Vector, but this matches the+  --    intuition that 'Int' ~ 'DIM1'.+++-- | Conditionally copy elements from source array to destination array+-- according to an index mapping.+--+-- In addition, the 'mask' vector and associated predication function specifies+-- whether the element is copied or a default value is used instead.+--+-- >>> let defaults = fromList (Z :. 6) [6,6,6,6,6,6]+-- >>> let from     = fromList (Z :. 6) [1,3,7,2,5,3]+-- >>> let mask     = fromList (Z :. 6) [3,4,9,2,7,5]+-- >>> let input    = fromList (Z :. 9) [1,9,6,4,4,2,0,1,2]+-- >>> gatherIf (use from) (use mask) (> 4) (use defaults) (use input)+-- Vector (Z :. 6) [6,6,1,6,2,4]+--+gatherIf+    :: (Elt a, Elt b)+    => Acc (Vector Int)           -- ^ source indices to gather from+    -> Acc (Vector a)             -- ^ mask vector+    -> (Exp a -> Exp Bool)        -- ^ predicate function+    -> Acc (Vector b)             -- ^ default values+    -> Acc (Vector b)             -- ^ source values+    -> Acc (Vector b)+gatherIf from maskV pred defaults input = zipWith zf pf gatheredV+  where+    zf p g      = p ? (unlift g)+    gatheredV   = zip (gather from input) defaults+    pf          = map pred maskV+++-- Scatter operations+-- ------------------++-- | Overwrite elements of the destination by scattering the values of the+-- source array according to the given index mapping.+--+-- Note that if the destination index appears more than once in the mapping the+-- result is undefined.+--+-- >>> 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)           -- ^ destination indices to scatter into+    -> Acc (Vector e)             -- ^ default values+    -> Acc (Vector e)             -- ^ source values+    -> Acc (Vector e)+scatter to defaults input = permute const defaults pf input'+  where+    pf ix       = index1 (to ! ix)+    input'      = backpermute (shape to `intersect` shape input) id input+++-- | Conditionally overwrite elements of the destination by scattering values of+-- the source array according to a given index mapping, whenever the masking+-- function resolves to 'True'.+--+-- Note that if the destination index appears more than once in the mapping the+-- result is undefined.+--+-- >>> let to    = fromList (Z :. 6) [1,3,7,2,5,8]+-- >>> let mask  = fromList (Z :. 6) [3,4,9,2,7,5]+-- >>> let input = fromList (Z :. 7) [1,9,6,4,4,2,5]+-- >>> scatterIf (use to) (use mask) (> 4) (fill (constant (Z:.10)) 0) (use input)+-- Vector (Z :. 10) [0,0,0,0,0,4,0,6,2,0]+--+scatterIf+    :: (Elt e, Elt e')+    => Acc (Vector Int)           -- ^ destination indices to scatter into+    -> Acc (Vector e)             -- ^ mask vector+    -> (Exp e -> Exp Bool)        -- ^ predicate function+    -> Acc (Vector e')            -- ^ default values+    -> Acc (Vector e')            -- ^ source values+    -> Acc (Vector e')+scatterIf to maskV pred defaults input = permute const defaults pf input'+  where+    pf ix       = pred (maskV ! ix) ? ( index1 (to ! ix), ignore )+    input'      = backpermute (shape to `intersect` shape input) id input+++-- Permutations+-- ------------++-- | Reverse the elements of a vector.+--+reverse :: Elt e => Acc (Vector e) -> Acc (Vector e)+reverse xs =+  let len       = unindex1 (shape xs)+      pf i      = len - i - 1+  in  backpermute (shape xs) (ilift1 pf) xs++-- | Transpose the rows and columns of a matrix.+--+transpose :: Elt e => Acc (Array DIM2 e) -> Acc (Array DIM2 e)+transpose mat =+  let swap = lift1 $ \(Z:.x:.y) -> Z:.y:.x :: Z:.Exp Int:.Exp Int+  in  backpermute (swap $ shape mat) swap mat+++-- Extracting sub-vectors+-- ----------------------++-- | 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)+take n acc =+  let n'        = the (unit (n `min` sz))+      sh :. sz  = unlift (shape acc)            :: Exp sh :. Exp Int+  in+  backpermute (lift (sh :. n')) id acc+++-- | 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)+drop n acc =+  let n'        = the (unit n)+      sh :. sz  = unlift (shape acc)            :: Exp sh :. Exp Int+      index ix  = let j :. i = unlift ix        :: Exp sh :. Exp Int+                  in  lift (j :. i + n')+  in+  backpermute (lift (sh :. 0 `max` (sz - n'))) index acc+++-- | 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)+init acc =+  let sh :. sz  = unlift (shape acc)            :: Exp sh :. Exp Int+  in  backpermute (lift (sh :. sz `min` (sz - 1))) id acc+++-- | 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)+tail acc =+  let sh :. sz  = unlift (shape acc)            :: Exp sh :. Exp Int+      index ix  = let j :. i = unlift ix        :: Exp sh :. Exp Int+                  in  lift (j :. i + 1)+  in+  backpermute (lift (sh :. 0 `max` (sz - 1))) index acc+++-- | 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)+slit m n acc =+  let m'        = the (unit m)+      n'        = the (unit n)+      sh :. sz  = unlift (shape acc)            :: Exp sh :. Exp Int+      index ix  = let j :. i = unlift ix        :: Exp sh :. Exp Int+                  in  lift (j :. i + m')+  in+  backpermute (lift (sh :. (n' `min` ((sz - m') `max` 0)))) index acc+++-- Controlling execution+-- ---------------------++-- | 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+compute = id >-> id+++-- Flow control+-- ------------++-- | Infix version of 'acond'. If the predicate evaluates to 'True', the first+-- component of the tuple is returned, else the second.+--+-- See also: 'ifThenElse'.+--+infix 0 ?|+(?|) :: Arrays a => Exp Bool -> (Acc a, Acc a) -> Acc a+c ?| (t, e) = acond c t e++-- | 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'.+--+infix 0 ?+(?) :: Elt t => Exp Bool -> (Exp t, Exp t) -> Exp t+c ? (t, e) = cond c t e++-- | A case-like control structure+--+caseof :: (Elt a, Elt b)+       => Exp a                         -- ^ case subject+       -> [(Exp a -> Exp Bool, Exp b)]  -- ^ list of cases to attempt+       -> Exp b                         -- ^ default value+       -> Exp b+caseof _ []        e = e+caseof x ((p,b):l) e = cond (p x) b (caseof x l e)+++-- | For use with @-XRebindableSyntax@, this class provides 'ifThenElse' lifted+-- to both scalar and array types.+--+class IfThenElse t where+  type EltT t a :: Constraint+  ifThenElse :: EltT t a => Exp Bool -> t a -> t a -> t a++instance IfThenElse Exp where+  type EltT Exp t = Elt t+  ifThenElse = cond++instance IfThenElse Acc where+  type EltT Acc a = Arrays a+  ifThenElse = acond+++-- Scalar iteration+-- ----------------++-- | Repeatedly apply a function a fixed number of times+--+iterate :: forall a. Elt a+        => Exp Int+        -> (Exp a -> Exp a)+        -> Exp a+        -> Exp a+iterate n f z+  = let step :: (Exp Int, Exp a) -> (Exp Int, Exp a)+        step (i, acc)   = ( i+1, f acc )+    in+    snd $ while (\v -> fst v < n) (lift1 step) (lift (constant 0, z))+++-- Scalar bulk operations+-- ----------------------++-- | 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+sfoldl f z ix xs+  = let step :: (Exp Int, Exp a) -> (Exp Int, Exp a)+        step (i, acc)   = ( i+1, acc `f` (xs ! lift (ix :. i)) )+        (_ :. n)        = unlift (shape xs)     :: Exp sh :. Exp Int+    in+    snd $ while (\v -> fst v < n) (lift1 step) (lift (constant 0, z))+++-- Tuples+-- ------++-- |Extract the first component of a scalar pair.+--+fst :: forall a b. (Elt a, Elt b) => Exp (a, b) -> Exp a+fst e = let (x, _::Exp b) = unlift e in x++-- |Extract the first component of an array pair.+afst :: forall a b. (Arrays a, Arrays b) => Acc (a, b) -> Acc a+afst a = let (x, _::Acc b) = unlift a in x++-- |Extract the second component of a scalar pair.+--+snd :: forall a b. (Elt a, Elt b) => Exp (a, b) -> Exp b+snd e = let (_:: Exp a, y) = unlift e in y++-- | Extract the second component of an array pair+asnd :: forall a b. (Arrays a, Arrays b) => Acc (a, b) -> Acc b+asnd a = let (_::Acc a, y) = unlift a in y++-- |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+curry f x y = f (lift (x, y))++-- |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+uncurry f t = let (x, y) = unlift t in f x y+++-- Shapes and indices+-- ------------------++-- |The one index for a rank-0 array.+--+index0 :: Exp Z+index0 = lift Z++-- |Turn an 'Int' expression into a rank-1 indexing expression.+--+index1 :: Elt i => Exp i -> Exp (Z :. i)+index1 i = lift (Z :. i)++-- |Turn a rank-1 indexing expression into an 'Int' expression.+--+unindex1 :: Elt i => Exp (Z :. i) -> Exp i+unindex1 ix = let Z :. i = unlift ix in 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)+index2 i j = lift (Z :. i :. j)++-- | 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)+unindex2 ix+  = let Z :. i :. j = unlift ix :: Z :. Exp i :. Exp i+    in  lift (i, j)++-- | 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)+index3 k j i = lift (Z :. k :. j :. 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)+unindex3 ix = let Z :. k :. j :. i = unlift ix  :: Z :. Exp i :. Exp i :. Exp i+              in  lift (k, j, i)+++-- Array operations with a scalar result+-- -------------------------------------++-- | Extract the element of a singleton array.+--+-- > the xs  ==  xs ! Z+--+the :: Elt e => Acc (Scalar e) -> Exp e+the = (!index0)++-- | Test whether an array is empty.+--+null :: (Shape sh, Elt e) => Acc (Array sh e) -> Exp Bool+null arr = size arr == 0++-- | Get the length of a vector.+--+length :: Elt e => Acc (Vector e) -> Exp Int+length = unindex1 . shape+++{--+-- Sequence operations+-- --------------------------------------++-- | Reduce a sequence by appending all the shapes and all the elements in two+-- separate vectors.+--+fromSeq :: (Shape sh, Elt a) => Seq [Array sh a] -> Seq (Vector sh, Vector a)+fromSeq = foldSeqFlatten f (lift (emptyArray, emptyArray))+  where+    f x sh1 a1 =+      let (sh0, a0) = unlift x+      in lift (sh0 ++ sh1, a0 ++ a1)+++fromSeqElems :: (Shape sh, Elt a) => Seq [Array sh a] -> Seq (Vector a)+fromSeqElems = foldSeqFlatten f emptyArray+  where+    f a0 _ a1 = a0 ++ a1++fromSeqShapes :: (Shape sh, Elt a) => Seq [Array sh a] -> Seq (Vector sh)+fromSeqShapes = foldSeqFlatten f emptyArray+  where+    f sh0 sh1 _ = sh0 ++ sh1++-- | Sequence an array on the innermost dimension.+--+toSeqInner :: (Shape sh, Elt a) => Acc (Array (sh :. Int) a) -> Seq [Array sh a]+toSeqInner a = toSeq (Any :. Split) a++-- | Sequence a 2-dimensional array on the outermost dimension.+--+toSeqOuter2 :: Elt a => Acc (Array DIM2 a) -> Seq [Array DIM1 a]+toSeqOuter2 a = toSeq (Z :. Split :. All) a++-- | Sequence a 3-dimensional array on the outermost dimension.+toSeqOuter3 :: Elt a => Acc (Array DIM3 a) -> Seq [Array DIM2 a]+toSeqOuter3 a = toSeq (Z :. Split :. All :. All) a++-- | Generate a scalar sequence of a fixed given length, by applying+-- the given scalar function at each index.+generateSeq :: Elt a => Exp Int -> (Exp Int -> Exp a) -> Seq [Scalar a]+generateSeq n f = toSeq (Z :. Split) (generate (index1 n) (f . unindex1))+--}++-- Utilities+-- ---------++emptyArray :: (Shape sh, Elt e) => Acc (Array sh e)+emptyArray = use (fromList empty [])+++-- Utilities+-- ---------++matchShapeType :: forall s t. (Shape s, Shape t) => s -> t -> Maybe (s :~: t)+matchShapeType _ _+  | Just Refl <- matchTupleType (eltType (undefined::s)) (eltType (undefined::t))+  = gcast Refl++matchShapeType _ _+  = Nothing 
Data/Array/Accelerate/Pretty.hs view
@@ -1,18 +1,16 @@ {-# LANGUAGE FlexibleInstances    #-} {-# LANGUAGE GADTs                #-}-{-# LANGUAGE OverlappingInstances #-} {-# LANGUAGE ScopedTypeVariables  #-} {-# LANGUAGE TypeSynonymInstances #-} {-# OPTIONS_GHC -fno-warn-orphans #-} {-# OPTIONS_HADDOCK hide #-} -- | -- Module      : Data.Array.Accelerate.Pretty--- Copyright   : [2008..2014] Manuel M T Chakravarty, Gabriele Keller---               [2008..2009] Sean Lee---               [2009..2014] Trevor L. McDonell+-- Copyright   : [2008..2017] Manuel M T Chakravarty, Gabriele Keller+--               [2009..2017] Trevor L. McDonell -- License     : BSD3 ----- Maintainer  : Manuel M T Chakravarty <chak@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -20,7 +18,8 @@ module Data.Array.Accelerate.Pretty (    -- * Pretty printing functions-  module Data.Array.Accelerate.Pretty.Print+  module Data.Array.Accelerate.Pretty.Print,+  module Data.Array.Accelerate.Pretty.Graphviz,    -- * Instances of Show @@ -33,6 +32,7 @@ import Data.Array.Accelerate.AST import Data.Array.Accelerate.Trafo.Base import Data.Array.Accelerate.Pretty.Print+import Data.Array.Accelerate.Pretty.Graphviz  -- |Show instances -- ---------------@@ -48,20 +48,27 @@ -- This matches any type of kind (* -> * -> *), which can cause problems -- interacting with other packages. See Issue #108. ---instance Show (OpenAcc aenv a) where-  show c = renderStyle wide $ prettyAcc 0 noParens c+instance PrettyEnv aenv => Show (OpenAcc aenv a) where+  show c = renderStyle wide $ prettyAcc noParens prettyEnv c -instance Show (DelayedOpenAcc aenv a) where-  show c = renderStyle wide $ prettyAcc 0 noParens c+instance PrettyEnv aenv => Show (DelayedOpenAcc aenv a) where+  show c = renderStyle wide $ prettyAcc noParens prettyEnv c  -- These parameterised instances are fine because there is a concrete kind ---instance Kit acc => Show (PreOpenAfun acc aenv f) where-  show f = renderStyle wide $ prettyPreAfun prettyAcc 0 f+-- TLM: Ugh, his new 'PrettyEnv' constraint really just enforces something+--      that we already know, which is that our environments are nested+--      tuples, but our type parameter 'env' doesn't capture that.+--+instance (Kit acc, PrettyEnv aenv) => Show (PreOpenAfun acc aenv f) where+  show f = renderStyle wide $ prettyPreOpenAfun prettyAcc prettyEnv f -instance Kit acc => Show (PreOpenFun acc env aenv f) where-  show f = renderStyle wide $ prettyPreFun prettyAcc 0 f+instance (Kit acc, PrettyEnv env, PrettyEnv aenv) => Show (PreOpenFun acc env aenv f) where+  show f = renderStyle wide $ prettyPreOpenFun prettyAcc prettyEnv prettyEnv f -instance Kit acc => Show (PreOpenExp acc env aenv t) where-  show e = renderStyle wide $ prettyPreExp prettyAcc 0 0 noParens e+instance (Kit acc, PrettyEnv env, PrettyEnv aenv) => Show (PreOpenExp acc env aenv t) where+  show e = renderStyle wide $ prettyPreOpenExp prettyAcc noParens prettyEnv prettyEnv e++-- instance Kit acc => Show (PreOpenSeq acc aenv senv t) where+--   show s = renderStyle wide $ sep $ punctuate (text ";") $ prettySeq prettyAcc 0 0 noParens s 
Data/Array/Accelerate/Pretty/Graphviz.hs view
@@ -1,152 +1,555 @@-{-# LANGUAGE GADTs, TypeOperators, ScopedTypeVariables #-}+{-# LANGUAGE CPP                  #-}+{-# LANGUAGE FlexibleInstances    #-}+{-# LANGUAGE GADTs                #-}+{-# LANGUAGE OverloadedStrings    #-}+{-# LANGUAGE PatternGuards        #-}+{-# LANGUAGE RankNTypes           #-}+{-# LANGUAGE RecordWildCards      #-}+{-# LANGUAGE ScopedTypeVariables  #-}+{-# LANGUAGE TemplateHaskell      #-}+{-# LANGUAGE TupleSections        #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE ViewPatterns         #-} -- | -- Module      : Data.Array.Accelerate.Pretty.Graphviz--- Copyright   : [2010..2011] Sean Seefried+-- Copyright   : [2015..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell -- License     : BSD3 ----- Maintainer  : Manuel M T Chakravarty <chak@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au> -- Stability   : experimental -- Portability : non-portable (GHC extensions) ----- Functions for printing out Graphviz graphs in DOT format.---- module Data.Array.Accelerate.Pretty.Graphviz ( -  -- * Graphviz printing functions-  dumpAcc+  Graph,+  PrettyGraph(..), Detail(..), +  graphDelayedAcc, graphDelayedAfun,+ ) where  -- standard libraries-import Control.Exception (finally)-import Control.Monad.State-import System.Exit-import System.FilePath-import System.Directory-import System.Posix.Process-import System.IO-import System.IO.Error-import Text.Printf+import Data.List+import Data.Maybe+import Data.HashSet                                     ( HashSet )+import Text.PrettyPrint+import Control.Monad.State                              ( modify, gets, state )+import Control.Arrow                                    ( (&&&) )+import System.IO.Unsafe                                 ( unsafePerformIO )+import Control.Applicative                              hiding ( Const, empty )+import Prelude                                          hiding ( exp )+import qualified Data.Sequence                          as Seq+import qualified Data.HashSet                           as Set  -- friends-import Data.Array.Accelerate.Pretty.Traverse-import Data.Array.Accelerate.AST+import Data.Array.Accelerate.AST                        ( PreOpenAcc(..), PreOpenAfun(..), PreOpenFun(..), PreOpenExp(..), Idx(..) )+import Data.Array.Accelerate.Array.Sugar                ( Array, Elt, EltRepr, Tuple(..), Atuple(..), arrays, toElt, strForeign )+import Data.Array.Accelerate.Type                       ( Boundary(..) )+import Data.Array.Accelerate.Error+import Data.Array.Accelerate.Trafo.Base+import Data.Array.Accelerate.Pretty.Print+import Data.Array.Accelerate.Pretty.Graphviz.Monad+import Data.Array.Accelerate.Pretty.Graphviz.Type --- | Detects if the dot command line tool from the Graphviz package exists.--- If it does outputs a Postscript file, otherwise a ".dot" file.++-- Configuration options+-- ---------------------++cfgIncludeShape, cfgUnique :: Bool+cfgIncludeShape = False             -- draw edges for uses of shape information+cfgUnique       = False             -- draw a single edge per data dependency+++-- Environments+-- ------------++-- This is the standard environment typed by de Bruijn indices, where at each+-- index we need to record both the pretty printed label as well its 'NodeId',+-- which we use to track data dependencies. ---dumpAcc :: String -> OpenAcc aenv a -> IO ()-dumpAcc basename acc = do-  exists <- findExecutable "dot"-  case exists of-    Just dot -> withTempFile "ast.dot" (writePSFile dot)-    Nothing  -> do-      putStrLn "Couldn't find `dot' tool. Just writing DOT file."-      writeDotFile+data Aval env where+  Aempty ::                                Aval ()+  Apush  :: Aval env -> NodeId -> Label -> Aval (env, t)++-- Convert to the 'Val' used by the base pretty printing module by stripping out+-- the 'NodeId' part.+--+avalToVal :: Aval aenv -> Val aenv+avalToVal Aempty           = Empty+avalToVal (Apush aenv _ v) = Push (avalToVal aenv) (text v)++aprj :: Idx aenv t -> Aval aenv -> (NodeId, Label)        -- TLM: (Vertex, Label) ??+aprj ZeroIdx      (Apush _    n v) = (n,v)+aprj (SuccIdx ix) (Apush aenv _ _) = aprj ix aenv+#if __GLASGOW_HASKELL__ < 800+aprj _            _                = $internalError "aprj" "inconsistent valuation"+#endif+++-- Graph construction+-- ------------------++mkNode :: PNode -> Maybe Label -> Dot NodeId+mkNode (PNode ident tree deps) label =+  let node  = Node label ident tree+      edges = Seq.fromList+            $ map (\(from, to) -> Edge from (Vertex ident to))+            $ if cfgUnique then nub deps else deps+  in+  state $ \s ->+    ( ident+    , s { dotNodes = node  Seq.<| dotNodes s+        , dotEdges = edges Seq.>< dotEdges s+        }+    )+++-- Add [T|F] ports underneath the given tree.+--+mkTF :: Tree (Maybe Port, Doc) -> Tree (Maybe Port, Doc)+mkTF this =+  Forest [ this+         , Forest [ Leaf (Just "T", "T")+                  , Leaf (Just "F", "F")+                  ]+         ]+++-- Pretty Printing+-- ===============+--+-- The use of unsafePerformIO in the below is safe in the sense that we only+-- require IO to recover the stable names of terms. At worst, if we do not+-- recover the correct stable name for some reason, we will be left with+-- dandling edges in the graph.+--++class PrettyGraph g where+  ppGraph :: Detail -> g -> Graph++instance PrettyGraph (DelayedAcc a) where+  ppGraph = graphDelayedAcc++instance PrettyGraph (DelayedAfun a) where+  ppGraph = graphDelayedAfun++data Detail = Simple | Full++simple :: Detail -> Bool+simple Simple = True+simple _      = False++-- | Generate a dependency graph for the given computation+--+{-# NOINLINE graphDelayedAcc #-}+graphDelayedAcc :: Detail -> DelayedAcc a -> Graph+graphDelayedAcc detail acc =+  unsafePerformIO $! evalDot (graphDelayedOpenAcc detail Aempty acc)++-- | Generate a dependency graph for an array function+--+{-# NOINLINE graphDelayedAfun #-}+graphDelayedAfun :: Detail -> DelayedAfun f -> Graph+graphDelayedAfun detail afun = unsafePerformIO . evalDot $! do+  l <- prettyDelayedAfun detail Aempty afun+  state $ \s ->+    case Seq.viewl (dotGraph s) of+      g@(Graph l' _) Seq.:< gs | l == l' -> (g, s { dotGraph = gs })+      _                                  -> $internalError "graphDelaydAfun" "unexpected error"+++-- Pretty-printing data-dependency graphs+-- --------------------------------------++-- Partially constructed graph nodes, consists of some body text and a list of+-- vertices which we will draw edges from (and later, the port we connect into).+--+data PDoc  = PDoc Doc [Vertex]+data PNode = PNode NodeId (Tree (Maybe Port, Doc)) [(Vertex, Maybe Port)]++graphDelayedOpenAcc+    :: Detail+    -> Aval aenv+    -> DelayedOpenAcc aenv a+    -> Dot Graph+graphDelayedOpenAcc detail aenv acc = do+  r <- prettyDelayedOpenAcc detail noParens aenv acc+  i <- mkNodeId r+  v <- mkNode r Nothing+  _ <- mkNode (PNode i (Leaf (Nothing,"result")) [(Vertex v Nothing, Nothing)]) Nothing+  mkGraph++-- Generate a graph for the given term.+--+prettyDelayedOpenAcc+    :: forall aenv arrs.+       Detail                               -- simplified output: only print operator name+    -> (Doc -> Doc)+    -> Aval aenv+    -> DelayedOpenAcc aenv arrs+    -> Dot PNode+prettyDelayedOpenAcc _      _    _    Delayed{}            = $internalError "prettyDelayedOpenAcc" "expected manifest array"+prettyDelayedOpenAcc detail wrap aenv atop@(Manifest pacc) =+  case pacc of+    Avar ix                 -> pnode (avar ix)+    Alet bnd body           -> do+      bnd'  <- prettyDelayedOpenAcc detail noParens aenv                 bnd+      a     <- mkLabel+      ident <- mkNode bnd' (Just a)+      body' <- prettyDelayedOpenAcc detail noParens (Apush aenv ident a) body+      return body'++    Acond p t e             -> do+      ident <- mkNodeId atop+      vt    <- lift t+      ve    <- lift e+      PDoc p' vs <- ppE p+      let port = Just "P"+          doc  = mkTF $ Leaf (port, if simple detail then "?|" else p')+          deps = (vt, Just "T") : (ve, Just "F") : map (,port) vs+      return $ PNode ident doc deps++    Apply afun acc          -> apply <$> prettyDelayedAfun    detail        aenv afun+                                     <*> prettyDelayedOpenAcc detail parens aenv acc++    Awhile p f x            -> do+      ident <- mkNodeId atop+      x'    <- replant =<< prettyDelayedOpenAcc detail parens aenv x+      p'    <- prettyDelayedAfun detail aenv p+      f'    <- prettyDelayedAfun detail aenv f+      --+      let PNode _ (Leaf (Nothing,xb)) fvs = x'+          loop                            = wrap $ hang "awhile" 2 (sep [ text p', text f', xb ])+      return $ PNode ident (Leaf (Nothing,loop)) fvs++    Atuple atup             -> prettyDelayedAtuple detail wrap aenv atup+    Aprj ix atup            -> do+      ident                     <- mkNodeId atop+      PNode _ (Leaf (p,d)) deps <- replant =<< prettyDelayedOpenAcc detail parens aenv atup+      return $ PNode ident (Leaf (p, wrap (char '#' <> prettyTupleIdx ix <+> nest 2 d))) deps++    Use arrs                -> "use"         .$ [ return $ PDoc (prettyArrays (arrays (undefined::arrs)) arrs) [] ]+    Unit e                  -> "unit"        .$ [ ppE e ]+    Generate sh f           -> "generate"    .$ [ ppSh sh, ppF f ]+    Transform sh ix f xs    -> "transform"   .$ [ ppSh sh, ppF ix, ppF f, ppA xs ]+    Reshape sh xs           -> "reshape"     .$ [ ppSh sh, ppA xs ]+    Replicate _ty ix xs     -> "replicate"   .$ [ ppSh ix, ppA xs ]+    Slice _ty xs ix         -> "slice"       .$ [ ppA xs, ppSh ix ]+    Map f xs                -> "map"         .$ [ ppF f, ppA xs ]+    ZipWith f xs ys         -> "zipWith"     .$ [ ppF f, ppA xs, ppA ys ]+    Fold f e xs             -> "fold"        .$ [ ppF f, ppE e, ppA xs ]+    Fold1 f xs              -> "fold1"       .$ [ ppF f, ppA xs ]+    FoldSeg f e xs ys       -> "foldSeg"     .$ [ ppF f, ppE e, ppA xs, ppA ys ]+    Fold1Seg f xs ys        -> "fold1Seg"    .$ [ ppF f, ppA xs, ppA ys ]+    Scanl f e xs            -> "scanl"       .$ [ ppF f, ppE e, ppA xs ]+    Scanl' f e xs           -> "scanl'"      .$ [ ppF f, ppE e, ppA xs ]+    Scanl1 f xs             -> "scanl1"      .$ [ ppF f, ppA xs ]+    Scanr f e xs            -> "scanr"       .$ [ ppF f, ppE e, ppA xs ]+    Scanr' f e xs           -> "scanr'"      .$ [ ppF f, ppE e, ppA xs ]+    Scanr1 f xs             -> "scanr1"      .$ [ ppF f, ppA xs ]+    Permute f dfts p xs     -> "permute"     .$ [ ppF f, ppA dfts, ppF p, ppA xs ]+    Backpermute sh p xs     -> "backpermute" .$ [ ppSh sh, ppF p, ppA xs ]+    Stencil sten bndy xs    -> "stencil"     .$ [ ppF sten, ppB xs bndy, ppA xs ]+    Stencil2 sten bndy1 acc1 bndy2 acc2+                            -> "stencil2"    .$ [ ppF sten, ppB acc1 bndy1, ppA acc1,+                                                            ppB acc2 bndy2, ppA acc2 ]+    Aforeign ff _afun xs    -> "aforeign"    .$ [ return (PDoc (text (strForeign ff)) []), {- ppAf afun, -} ppA xs ]+    -- Collect{}               -> error "Collect"+   where-    writePSFile dot file h = do-      hPutStr h (dotAcc acc)-      hFlush h-      let output = basename <.> "ps"-          flags  = [file, "-Tps", "-o" ++ output]-      status <- getProcessStatus True True =<< forkProcess (executeFile dot False flags Nothing)-      case status of-           Just (Exited ExitSuccess) -> putStrLn $ "PS file successfully written to `" ++ output ++ "'"-           _                         -> do-             putStrLn "dot failed to write Postscript file. Just writing the DOT file."-             writeDotFile       -- fall back to writing the dot file+    (.$) :: String -> [Dot PDoc] -> Dot PNode+    name .$ docs = pnode =<< fmt name docs++    fmt :: String -> [Dot PDoc] -> Dot PDoc+    fmt name docs = do+      docs' <- sequence docs+      let args = [ x | PDoc x _ <- docs' ]+          fvs  = [ x | PDoc _ x <- docs' ]+      return $ PDoc (wrap $ hang (text name) 2 (if simple detail then empty else sep args))+                    (concat fvs)++    pnode :: PDoc -> Dot PNode+    pnode (PDoc doc vs) = do+      let port = Nothing+      ident <- mkNodeId atop+      return $ PNode ident (Leaf (port, doc)) (map (,port) vs)++    -- Free variables     ---    writeDotFile :: IO ()-    writeDotFile  = catchIOError writeDotFile' handler-    writeDotFile'  = do-      let path = basename ++ ".dot"-      h <- openFile path WriteMode-      hPutStr h (dotAcc acc)-      putStrLn ("DOT file successfully written to `" ++ path ++ "'")-      hClose h-    handler :: IOError -> IO ()-    handler e =-      case True of-        _ | isAlreadyInUseError e -> putStrLn "isAlreadyInUseError"-          | isDoesNotExistError e -> putStrLn "isDoesNotExistError"-          | isFullError e         -> putStrLn "isFullError"-          | isEOFError e          -> putStrLn "isEOFError"-          | isPermissionError   e -> putStrLn "isPermissionError"-          | isIllegalOperation e  -> putStrLn "isIllegalOperation"-          | isUserError e         -> putStrLn "isUserError"-          | otherwise             -> putStrLn "Unknown error"+    fvA :: FVAcc DelayedOpenAcc+    fvA env (Manifest (Avar ix)) = [ Vertex (fst $ aprj ix env) Nothing ]+    fvA _   _                    = $internalError "graphviz" "expected array variable" +    fvF :: DelayedFun aenv t -> [Vertex]+    fvF = fvPreOpenFun fvA Empty aenv -withTempFile :: String -> (FilePath -> Handle -> IO a) -> IO a-withTempFile pattern f = do-  tempDir <- catchIOError getTemporaryDirectory (\_ -> return ".")-  (tempFile, tempH) <- openTempFile tempDir pattern-  finally (f tempFile tempH) (hClose tempH >> removeFile tempFile)+    fvE :: DelayedExp aenv t -> [Vertex]+    fvE = fvPreOpenExp fvA Empty aenv -dotAcc :: OpenAcc aenv a -> String-dotAcc = toDigraph (travAcc dotLabels combineDot leafDot)+    -- Pretty-printing+    --+    avar :: Idx aenv t -> PDoc+    avar ix = let (ident, v) = aprj ix aenv+              in  PDoc (text v) [Vertex ident Nothing] -data Node     = Node     { nodeId :: String, label :: String, childNodes :: [String], transitions :: [String] }-data DotState = DotState { counter :: Int }+    aenv' :: Val aenv+    aenv' = avalToVal aenv -mkNodeId :: Int -> String-mkNodeId = printf "node%03d"+    ppA :: DelayedOpenAcc aenv a -> Dot PDoc+    ppA (Manifest (Avar ix)) = return (avar ix)+    ppA acc@Manifest{}       = do+      -- Lift out and draw as a separate node. This can occur with the manifest+      -- array arguments to permute (defaults array) and stencil[2].+      acc'  <- prettyDelayedOpenAcc detail noParens aenv acc+      v     <- mkLabel+      ident <- mkNode acc' (Just v)+      return $ PDoc (text v) [Vertex ident Nothing]+    ppA (Delayed sh f _)+      | Shape a    <- sh                                             -- identical shape+      , Just Refl  <- match f (Lam (Body (Index a (Var ZeroIdx))))   -- identity function+      = ppA a+    ppA (Delayed sh f _) = do+      PDoc d v <- "Delayed" `fmt` [ ppSh sh, ppF f ]+      return    $ PDoc (parens d) v -mkNode :: String -> [String] -> [String] -> State DotState Node-mkNode lbl childNodes' transitions' = do-  s <- get-  let c = counter s-  put DotState { counter = c + 1 }-  return Node  { nodeId = mkNodeId c, label = lbl, childNodes = childNodes', transitions = transitions' }+    ppB :: forall sh e. Elt e+        => {-dummy-} DelayedOpenAcc aenv (Array sh e)+        -> Boundary (EltRepr e)+        -> Dot PDoc+    ppB _ Clamp        = return (PDoc "Clamp"  [])+    ppB _ Mirror       = return (PDoc "Mirror" [])+    ppB _ Wrap         = return (PDoc "Wrap"   [])+    ppB _ (Constant e) = return (PDoc (parens $ "Constant" <+> text (show (toElt e :: e))) []) -dotLabels :: Labels-dotLabels = Labels { accFormat = "yellow"-                   , expFormat = "orange"-                   , funFormat = "blue"-                   , tupleFormat = "green"-                   , primFunFormat = "red"-                   , arrayFormat = "purple"-                   , boundaryFormat = "cyan" }+    ppF :: DelayedFun aenv t -> Dot PDoc+    ppF = return . uncurry PDoc . (parens . prettyDelayedFun aenv' &&& fvF) +    ppE :: DelayedExp aenv t -> Dot PDoc+    ppE = return . uncurry PDoc . (prettyDelayedExp parens aenv' &&& fvE) +    ppSh :: DelayedExp aenv sh -> Dot PDoc+    ppSh = return . uncurry PDoc . (parens . prettyDelayedExp noParens aenv' &&& fvE) -combineDot  :: String -> String -> [State DotState Node] -> State DotState Node-combineDot color source targets = do-   targetNodes <- sequence targets-   s <- get-   let newNodeId   = mkNodeId (counter s)-       childNodes1 = [nodeDef newNodeId source color ]-       childNodes2 = concatMap childNodes targetNodes-       lines1      = map (digraphLine newNodeId) targetNodes-       lines2      = concatMap transitions targetNodes-   mkNode source (childNodes1 ++ childNodes2) (lines1 ++ lines2)+    lift :: DelayedOpenAcc aenv a -> Dot Vertex+    lift Delayed{}            = $internalError "prettyDelayedOpenAcc" "expected manifest array"+    lift (Manifest (Avar ix)) = return $ Vertex (fst (aprj ix aenv)) Nothing+    lift acc                  = do+      acc'  <- prettyDelayedOpenAcc detail noParens aenv acc+      ident <- mkNode acc' Nothing+      return $ Vertex ident Nothing++    apply :: Label -> PNode -> PNode+    apply f (PNode ident x vs) =+      let x' = case x of+                 Leaf (p,d) -> Leaf (p, wrap (text f <+> d))+                 Forest ts  -> Forest (Leaf (Nothing,text f) : ts)+      in+      PNode ident x' vs+++-- Pretty print array functions as separate sub-graphs, and return the name of+-- the sub-graph as if it can be called like a function. We will add additional+-- nodes at the top of the graph to represent the bound variables.+--+-- Note: [Edge placement]+--+-- If a node belongs to a particular graph, so too must all its edges (and+-- vertices). This means that if the subgraph references anything from the+-- enclosing environment, we must lift those edges out of this subgraph,+-- otherwise the referenced node will be drawn inside of the subgraph.+--+prettyDelayedAfun+    :: Detail+    -> Aval aenv+    -> DelayedOpenAfun aenv afun+    -> Dot Label+prettyDelayedAfun detail aenv afun = do+  Graph _ ss  <- mkSubgraph (go aenv afun)+  n           <- Seq.length <$> gets dotGraph+  let label         = "afun" ++ show (n+1)+      outer         = collect aenv+      (lifted,ss')  =+        flip partition ss $ \s ->+        case s of+          E (Edge (Vertex ident _) _) -> Set.member ident outer+          _                           -> False+  --+  modify $ \s -> s { dotGraph = dotGraph s                         Seq.|> Graph label ss'+                   , dotEdges = Seq.fromList [ e | E e <- lifted ] Seq.>< dotEdges s+                   }+  return label   where-    digraphLine :: String -> Node -> String-    digraphLine sourceNodeId targetNode =-      sourceNodeId ++ " -> " ++ nodeId targetNode ++ ";"+    go :: Aval aenv' -> DelayedOpenAfun aenv' a' -> Dot Graph+    go aenv' (Abody b) = graphDelayedOpenAcc detail aenv' b+    go aenv' (Alam  f) = do+      a     <- mkLabel+      ident <- mkNodeId f+      _     <- mkNode (PNode ident (Leaf (Nothing, text a)) []) Nothing+      go (Apush aenv' ident a) f -leafDot :: String -> String -> State DotState Node-leafDot color lbl = do-  s <- get-  let c = counter s-  put DotState { counter = c + 1 }-  return Node { nodeId      = mkNodeId c, label = lbl-              , childNodes  = [ nodeDef (mkNodeId c) lbl color ]-              , transitions = [] }+    collect :: Aval aenv' -> HashSet NodeId+    collect Aempty        = Set.empty+    collect (Apush a i _) = Set.insert i (collect a) -nodeDef :: String -> String -> String -> String-nodeDef nodeId' label' color = printf "%s [ color=\"%s\", label=\"%s\" ];" nodeId' color label' -toDigraph :: (a -> State DotState Node) -> a -> String-toDigraph f e =-  header ++ unlines (childNodes node) ++ unlines (transitions node) ++ footer-   where-     node = evalState (f e) DotState { counter = 0 }-     header = unlines [ "/* Automatically generated by Accelerate */"-                      , "digraph AST {"-                      , "size=\"7.5,11\";"-                      , "ratio=\"compress\";"-                      , "node[color=lightblue2, style=filled];"]-     footer = "}"+-- Display array tuples. This is a little tricky...+--+prettyDelayedAtuple+    :: forall aenv atup.+       Detail+    -> (Doc -> Doc)+    -> Aval aenv+    -> Atuple (DelayedOpenAcc aenv) atup+    -> Dot PNode+prettyDelayedAtuple detail wrap aenv atup = do+  ident         <- mkNodeId atup+  (ids, ts, vs) <- unzip3 . map (\(PNode i t v) -> (i,t,v)) <$> collect [] atup+  modify $ \s -> s { dotEdges = fmap (redirect ident ids) (dotEdges s) }+  return $ PNode ident (forest ts) (concat vs)+  where+    collect :: [PNode] -> Atuple (DelayedOpenAcc aenv) t -> Dot [PNode]+    collect acc NilAtup          = return acc+    collect acc (SnocAtup tup a) = do+      a'   <- replant =<< prettyDelayedOpenAcc detail wrap aenv a+      tup' <- collect (a':acc) tup+      return tup'++    -- Redirect any edges that pointed into one of the nodes now part of this+    -- tuple, to instead point to the container node.+    --+    redirect :: NodeId -> [NodeId] -> Edge -> Edge+    redirect new subs edge@(Edge from (Vertex to port))+      | to `elem` subs = Edge from (Vertex new port)+      | otherwise      = edge++    -- Since we have lifted out any non-leaves into separate nodes, we can+    -- simply tuple-up all of the elements.+    --+    forest :: [Tree (Maybe Port, Doc)] -> Tree (Maybe Port, Doc)+    forest leaves = Leaf (Nothing, tuple [ d | Leaf (Nothing,d) <- leaves ])+++-- Lift out anything that isn't a Leaf node and output it to the graph+-- immediately as a new labelled node.+--+replant :: PNode -> Dot PNode+replant pnode@(PNode ident tree _) =+  case tree of+    Leaf (Nothing, _) -> return pnode+    _                 -> do+      vacuous <- mkNodeId pnode+      a       <- mkLabel+      _       <- mkNode pnode (Just a)+      return   $ PNode vacuous (Leaf (Nothing, text a)) [(Vertex ident Nothing, Nothing)]+++-- Pretty printing scalar functions and expressions+-- ------------------------------------------------+--+-- This is done with the usual machinery. Note that we rely on knowing that all+-- array operations will be lifted out of scalar expressions. This means that we+-- don't really need to recurse into the scalar terms to uncover new graph+-- nodes.+--++prettyDelayedFun :: Val aenv -> DelayedFun aenv f -> Doc+prettyDelayedFun = prettyDelayedOpenFun Empty++prettyDelayedExp :: (Doc -> Doc) -> Val aenv -> DelayedExp aenv t -> Doc+prettyDelayedExp wrap = prettyDelayedOpenExp wrap Empty+++prettyDelayedOpenFun+    :: forall env aenv f.+       Val env+    -> Val aenv+    -> DelayedOpenFun env aenv f+    -> Doc+prettyDelayedOpenFun env aenv fun = "\\\\" <> next env fun+  where+    -- graphviz will silently not print a label containing the string "->",+    -- so instead we use the special token "&rarr" for a short right arrow.+    --+    next :: Val env' -> PreOpenFun DelayedOpenAcc env' aenv f' -> Doc+    next env' (Body body) = "&rarr;" <+> prettyDelayedOpenExp noParens env' aenv body+    next env' (Lam fun')  =+      let x = char 'x' <> int (sizeEnv env')+      in  x <+> next (env' `Push` x) fun'++prettyDelayedOpenExp+    :: (Doc -> Doc)+    -> Val env+    -> Val aenv+    -> DelayedOpenExp env aenv t+    -> Doc+prettyDelayedOpenExp = prettyPreOpenExp pp+  where+    pp :: PrettyAcc DelayedOpenAcc+    pp _ aenv (Manifest (Avar ix)) = prj ix aenv+    pp _ _    _                    = $internalError "prettyDelayedOpenExp" "expected array variable"+++-- Data dependencies+-- -----------------+--+-- Return the data-dependencies of the given term. This is just a tree traversal+-- to extract all of the free variables. We will draw an edge from each of those+-- nodes (vertices) into the current term.+--++type FVAcc acc = forall aenv a. Aval aenv -> acc aenv a -> [Vertex]++fvPreOpenFun+    :: forall acc env aenv fun.+       FVAcc acc+    -> Val env+    -> Aval aenv+    -> PreOpenFun acc env aenv fun+    -> [Vertex]+fvPreOpenFun fvA env aenv (Body b) = fvPreOpenExp fvA env                                          aenv b+fvPreOpenFun fvA env aenv (Lam f)  = fvPreOpenFun fvA (env `Push` (char 'x' <> int (sizeEnv env))) aenv f++fvPreOpenExp+    :: forall acc env aenv exp.+       FVAcc acc+    -> Val env+    -> Aval aenv+    -> PreOpenExp acc env aenv exp+    -> [Vertex]+fvPreOpenExp fvA env aenv = fv+  where+    fvT :: Tuple (PreOpenExp acc env aenv) t -> [Vertex]+    fvT NilTup          = []+    fvT (SnocTup tup e) = concat [ fv e, fvT tup ]++    fvF :: PreOpenFun acc env aenv f -> [Vertex]+    fvF = fvPreOpenFun fvA env aenv++    fv :: PreOpenExp acc env aenv e -> [Vertex]+    fv (Shape acc)              = if cfgIncludeShape then fvA aenv acc else []+    fv (Index acc i)            = concat [ fvA aenv acc, fv i ]+    fv (LinearIndex acc i)      = concat [ fvA aenv acc, fv i ]+    --+    fv (Let e1 e2)              = concat [ fv e1, fvPreOpenExp fvA (env `Push` (char 'x' <> int (sizeEnv env))) aenv e2 ]+    fv Var{}                    = []+    fv Const{}                  = []+    fv PrimConst{}              = []+    fv (PrimApp _ x)            = fv x+    fv (Tuple tup)              = fvT tup+    fv (Prj _ e)                = fv e+    fv IndexNil                 = []+    fv IndexAny                 = []+    fv (IndexHead sh)           = fv sh+    fv (IndexTail sh)           = fv sh+    fv (IndexCons t h)          = concat [ fv t, fv h ]+    fv (IndexSlice _ slix sh)   = concat [ fv slix, fv sh ]+    fv (IndexFull _ slix sh)    = concat [ fv slix, fv sh ]+    fv (ToIndex sh ix)          = concat [ fv sh, fv ix ]+    fv (FromIndex sh ix)        = concat [ fv sh, fv ix ]+    fv (Union sh1 sh2)          = concat [ fv sh1, fv sh2 ]+    fv (Intersect sh1 sh2)      = concat [ fv sh1, fv sh2 ]+    fv (ShapeSize sh)           = fv sh+    fv Foreign{}                = []+    fv (Cond p t e)             = concat [ fv p, fv t, fv e ]+    fv (While p f x)            = concat [ fvF p, fvF f, fv x ] 
+ Data/Array/Accelerate/Pretty/Graphviz/Monad.hs view
@@ -0,0 +1,74 @@+{-# LANGUAGE RecordWildCards #-}+-- |+-- Module      : Data.Array.Accelerate.Pretty.Graphviz.Monad+-- Copyright   : [2015..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+module Data.Array.Accelerate.Pretty.Graphviz.Monad+  where++import Control.Applicative+import Control.Monad.State+import Data.Foldable                                    ( toList )+import Data.Sequence                                    ( Seq )+import System.Mem.StableName+import Prelude+import qualified Data.Sequence                          as Seq++import Data.Array.Accelerate.Pretty.Graphviz.Type+++-- Graph construction state ----------------------------------------------------++type Dot a    = StateT DotState IO a+data DotState = DotState+  { fresh       :: !Int+  , dotGraph    :: Seq Graph+  , dotEdges    :: Seq Edge+  , dotNodes    :: Seq Node+  }++emptyState :: DotState+emptyState =  DotState 0 Seq.empty Seq.empty Seq.empty++runDot :: Dot a -> IO (a, DotState)+runDot dot = runStateT dot emptyState++evalDot :: Dot a -> IO a+evalDot dot = fst <$> runDot dot++execDot :: Dot a -> IO DotState+execDot dot = snd <$> runDot dot+++-- Utilities -------------------------------------------------------------------++mkLabel :: Dot Label+mkLabel = state $ \s ->+  let n = fresh s+  in  ( 'a' : show n, s { fresh = n + 1 } )++mkNodeId :: a -> Dot NodeId+mkNodeId node = do+  sn    <- liftIO $ makeStableName node+  return $ NodeId (hashStableName sn)++mkGraph :: Dot Graph+mkGraph =+  state $ \DotState{..} ->+    ( Graph [] (toList $ fmap N dotNodes Seq.>< fmap E dotEdges Seq.>< fmap G dotGraph)+    , emptyState { fresh = fresh }+    )++mkSubgraph :: Dot Graph -> Dot Graph+mkSubgraph g = do+  n       <- gets fresh+  (r, s') <- lift . runDot $ do+    modify $ \s -> s { fresh = n }+    g+  state $ \s -> (r, s { fresh = fresh s' })+
+ Data/Array/Accelerate/Pretty/Graphviz/Type.hs view
@@ -0,0 +1,142 @@+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE ViewPatterns       #-}+-- |+-- Module      : Data.Array.Accelerate.Pretty.Graphviz.Type+-- Copyright   : [2015..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- Simple data types for representing (simple, directed) graphs and+-- pretty-printing to Graphviz dot format.+--+module Data.Array.Accelerate.Pretty.Graphviz.Type+  where++import Data.Maybe+import Data.Hashable+import Data.List+import Text.Printf+import Text.PrettyPrint+++-- Rose tree, with all information at the leaves.+--+data Tree a = Leaf a+            | Forest [Tree a]++instance Functor Tree where+  fmap f (Leaf x)    = Leaf (f x)+  fmap f (Forest xs) = Forest (map (fmap f) xs)+++-- Representation for simple Graphviz graphs+--+data Graph      = Graph Label [Statement]+data Statement  = N Node | E Edge | G Graph++data Node       = Node (Maybe Label) NodeId (Tree (Maybe Port, Doc))+data NodeId     = NodeId !Int++-- XXX: Changed from 'Doc' to 'String' because the version of 'pretty' included+--      with ghc-7.8 does not have an Eq Doc instance, which was added in+--      pretty-1.1.1.2. However, we don't want to simply depend on a newer+--      version of the library, because this will indirectly lead to+--      a dependency on multiple versions (through, e.g., template-haskell).+--+type Label      = String+type Port       = String++data Vertex     = Vertex NodeId (Maybe Port)+data Edge       = Edge {- from -} Vertex+                       {-  to  -} Vertex++deriving instance Eq NodeId+deriving instance Eq Vertex++instance Hashable NodeId where+  hashWithSalt salt (NodeId ident) = hashWithSalt salt ident++instance Show Graph where+  show = show . ppGraph+++-- Pretty print a (directed) graph to dot format+--+ppGraph :: Graph -> Doc+ppGraph (Graph l ss) =+  vcat [ text "digraph" <+> text l <+> lbrace+       , nest 4 $ vcat+                $ punctuate semi+                $ text "graph [compound=true]"+                : text "node  [shape=record,fontsize=10]"+                : map ppStatement ss+       , rbrace+       ]++ppSubgraph :: Graph -> Doc+ppSubgraph (Graph l ss) =+  vcat [ text "subgraph cluster_" <> text l <+> lbrace+       , nest 4 $ vcat+                $ punctuate semi+                $ text "label" <> equals <> text l+                : map ppStatement ss+       , rbrace+       ]++ppStatement :: Statement -> Doc+ppStatement (N n) = ppNode n+ppStatement (E e) = ppEdge e+ppStatement (G g) = ppSubgraph g++ppEdge :: Edge -> Doc+ppEdge (Edge from to) = ppVertex from <+> text "->" <+> ppVertex to++ppVertex :: Vertex -> Doc+ppVertex (Vertex n p) = ppNodeId n <> maybe empty (colon<>) (fmap text p)++ppNode :: Node -> Doc+ppNode (Node label nid body) =+  hcat [ ppNodeId nid+       , brackets+       $ hcat+       $ punctuate comma+       $ catMaybes [ fmap ((text "xlabel" <> equals <>) . doubleQuotes . text) label+                   , Just ( text "label"  <> equals <>    doubleQuotes (ppNodeTree body))+                   ]+       ]++ppNodeTree :: Tree (Maybe Port, Doc) -> Doc+ppNodeTree (Forest trees)      = braces $ hcat (punctuate (char '|') (map ppNodeTree trees))+ppNodeTree (Leaf (port, body)) = maybe empty (\p -> char '<' <> p <> char '>') (fmap text port) <> pp body+  where+    -- In order for the text to be properly rendered by graphviz, we need to+    -- escape some special characters. If the text takes up more than one line,+    -- then newlines '\n' need be be replaced with '\l', to ensure that the text+    -- is left justified rather than centred. The last line also needs a final+    -- '\l'. Single lines of text are left centred, which provides better+    -- formatting for short statements and port labels.+    --+    pp :: Doc -> Doc+    pp (lines . concatMap escape . renderStyle wide -> doc) =+      case doc of+        []  -> empty+        [x] -> text x+        xs  -> text (intercalate "\\l" xs) <> text "\\l"  -- [1] left justify++    wide :: Style+    wide = style { lineLength = 200 }++    escape :: Char -> String+    escape ' '  = "\\ "         -- don't collapse multiple spaces+    escape '>'  = "\\>"+    escape '<'  = "\\<"+    escape '|'  = "\\|"+    -- escape '\n' = "\\l"      -- handled at [1] instead+    escape c    = [c]++ppNodeId :: NodeId -> Doc+ppNodeId (NodeId nid) = text (printf "Node_%#0x" nid)+
− Data/Array/Accelerate/Pretty/HTML.hs
@@ -1,199 +0,0 @@-{-# LANGUAGE GADTs               #-}-{-# LANGUAGE OverloadedStrings   #-}-{-# LANGUAGE ScopedTypeVariables #-}--- |--- Module      : Data.Array.Accelerate.Pretty.HTML--- Copyright   : [2010..2011] Sean Seefried--- License     : BSD3------ Maintainer  : Manuel M T Chakravarty <chak@cse.unsw.edu.au>--- Stability   : experimental--- Portability : non-portable (GHC extensions)-----module Data.Array.Accelerate.Pretty.HTML  (--   -- * HTML printing function-   dumpHtmlAST--) where---- standard libraries-import System.IO.Error-import Control.Exception-import Data.String-import Data.Monoid-import Text.Blaze.Html.Renderer.Utf8-import Text.Blaze.Html4.Transitional                            ( (!) )-import qualified Data.Text                                      as T-import qualified Data.ByteString.Lazy                           as BS-import qualified Text.Blaze.Html4.Transitional                  as H-import qualified Text.Blaze.Html4.Transitional.Attributes       as A---- friends-import Data.Array.Accelerate.AST-import Data.Array.Accelerate.Pretty.Traverse---combineHtml :: String -> String -> [H.Html] -> H.Html-combineHtml cssClass label nodes = do-   let inner = foldl (>>) (return ()) nodes-   H.div ! A.class_ ("node " `mappend` fromString cssClass `mappend` " expanded") $ do-     H.span ! A.class_ "selector" $ H.toMarkup label-     inner-leafHtml :: String -> String -> H.Html-leafHtml cssClass label =-  H.div ! A.class_ ("node " `mappend` fromString cssClass `mappend` " leaf") $-    H.span $ H.toMarkup label--htmlLabels :: Labels-htmlLabels = Labels { accFormat = "array-node"-                    , expFormat = "exp-node"-                    , funFormat = "fun-node"-                    , primFunFormat = "prim-fun-node"-                    , tupleFormat = "tuple-node"-                    , arrayFormat = "array-node"-                    , boundaryFormat = "boundary-node" }----- combine :: Monad m => String -> String -> [m a] -> m a--- combine = undefined------ leafNode :: Monad m => String -> String -> m a--- leafNode = undefined--htmlAST :: OpenAcc aenv a -> H.Html-htmlAST acc = H.docTypeHtml $-    H.head $ do-        H.meta ! A.httpEquiv "Content-Type" ! A.content "text/html; charset=UTF-8"-        H.script ! A.type_ "text/javascript" !-                   A.src "https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js" $ mempty-        H.link ! A.rel "stylesheet" ! A.href "accelerate.css" ! A.type_ "text/css"-        H.script ! A.type_ "text/javascript" $ H.toMarkup $-          T.unlines ["function collapse() {"-                    ,"  var parent=$(this).parent();"-                    ,"  var that = $(this);"-                    ,"  parent.addClass(\"collapsed\").removeClass(\"expanded\");"-                    ,"  parent.children().each(function (i) {"-                    ,"    if ($(this).get(0) != that.get(0)) {"-                    ,"      $(this).hide(100);"-                    ,"    }"-                    ,"  });"-                    ,"  $(this).unbind();"-                    ,"  $(this).click(expand);"-                    ,"}"-                    , ""-                    , "function expand() {"-                    , "var parent=$(this).parent();"-                    , "parent.removeClass(\"collapsed\").addClass(\"expanded\");"-                    , "parent.children().show(100);"-                    , "$(this).show();"-                    , "$(this).unbind();"-                    , "$(this).click(collapse);"-                    , "}"-                    , "$(document).ready(function () {"-                    , "  $('.expanded>.selector').click(collapse);"-                    , "  $('.collapsed>.selector').click(expand);"-                    , "});"]-        H.body $ do-          H.table ! A.border "0" $-            H.tr $ do-              H.td ! A.class_ "acc-node" $ H.span "OpenAcc"-              H.td ! A.class_ "fun-node" $ H.span "OpenFun"-              H.td ! A.class_ "exp-node" $ H.span "OpenExp"-              H.td ! A.class_ "prim-fun-node" $ H.span "PrimFun"-              H.td ! A.class_ "tuple-node" $ H.span "Tuple"-              H.td ! A.class_ "boundary-node" $ H.span "Boundary"-          H.hr-          travAcc htmlLabels combineHtml leafHtml acc--accelerateCSS :: String-accelerateCSS =-  unlines-  [ "body {"-  , "  font-family: Helvetica;"-  , "  font-size: 10pt;"-  , "}"-  , ".node {"-  , "  padding-left: 5px;"-  , ""-  , "}"-  , ""-  , ".expanded .node {"-  , "  padding-left: 12px;"-  , "}"-  , ""-  , ".expanded .node.leaf {"-  , " padding-left: 23px;"-  , "}"-  , ""-  , ".acc-node>span      { color: red; }"-  , ".exp-node>span      { color: blue;}"-  , ".array-node>span    { color: purple;}"-  , ".fun-node>span      { color: orange;}"-  , ".prim-fun-node>span { color: magenta;}"-  , ".tuple-node>span    { color: green;}"-  , ".boundary-node>span { color: darkcyan;}                                            "-  , ""-  , ".selector, .leaf>span {"-  , "  padding: 2px 7px 2px 5px; "-  , "}"-  , ""-  , ".selector:hover, .leaf>span:hover {"-  , "  background: #FC9;"-  , "  -webkit-border-radius: 10px;"-  , "  -moz-border-radius: 10px;"-  , "}"-  , ""-  , ".leaf>span:hover {"-  , "  cursor: default;"-  , "}"-  , ""-  , ".selector:hover {"-  , "  cursor: pointer;"-  , "}"-  , ""-  , ".expanded .selector::before {"-  , "  font-size: 8pt;"-  , "  color: #999;"-  , "  content: \"\\25bc\";"-  , "}"-  , ""-  , ".collapsed .selector::before {"-  , "  font-size: 8pt;"-  , "  color: #999;"-  , "  content: \"\\25ba\";"-  , "  position: relative;"-  , ""-  , "}"-  , ""-  , ".selector:hover::before {"-  , "  color: orange;"-  , "}" ]---dumpHtmlAST :: String -> OpenAcc aenv a -> IO ()-dumpHtmlAST basename acc =-  catch writeHtmlFile handler-  where-    writeHtmlFile = do-      let cssPath = "accelerate.css"-      let path    = basename ++ ".html"-      ---      writeFile cssPath accelerateCSS-      BS.writeFile path (renderHtml $ htmlAST acc)-      putStrLn ("HTML file successfully written to `" ++ path ++ "'\n" ++-                "CSS file written to `" ++ cssPath ++ "'")--    handler :: IOError -> IO ()-    handler e =-      case True of-        _ | isAlreadyInUseError e -> putStrLn "isAlreadyInUseError"-          | isDoesNotExistError e -> putStrLn "isDoesNotExistError"-          | isFullError e         -> putStrLn "isFullError"-          | isEOFError e          -> putStrLn "isEOFError"-          | isPermissionError   e -> putStrLn "isPermissionError"-          | isIllegalOperation e  -> putStrLn "isIllegalOperation"-          | isUserError e         -> putStrLn "isUserError"-          | otherwise             -> putStrLn "Unknown error"-
Data/Array/Accelerate/Pretty/Print.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP                 #-} {-# LANGUAGE FlexibleInstances   #-} {-# LANGUAGE GADTs               #-} {-# LANGUAGE PatternGuards       #-}@@ -6,72 +7,113 @@ {-# LANGUAGE TypeOperators       #-} -- | -- Module      : Data.Array.Accelerate.Pretty.Print--- Copyright   : [2008..2014] Manuel M T Chakravarty, Gabriele Keller---               [2008..2009] Sean Lee---               [2009..2014] Trevor L. McDonell+-- Copyright   : [2008..2017] Manuel M T Chakravarty, Gabriele Keller+--               [2009..2017] Trevor L. McDonell -- License     : BSD3 ----- Maintainer  : Manuel M T Chakravarty <chak@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --  module Data.Array.Accelerate.Pretty.Print ( -  -- * Pretty printing functions+  -- * Pretty printing+  -- ** 'OpenAcc'+  --+  prettyOpenAcc,+  prettyOpenAfun,+  prettyOpenExp,+  prettyOpenFun,++  -- ** 'PreOpenAcc'   PrettyAcc,-  prettyPreAcc,  prettyOpenAcc,-  prettyPreExp,  prettyExp,-  prettyPreAfun, prettyAfun,-  prettyPreFun,  prettyFun,+  prettyPreOpenAcc,+  prettyPreOpenAfun,+  -- prettyPreOpenSeq,+  prettyPreExp, prettyPreOpenExp,+  prettyPreFun, prettyPreOpenFun,   prettyPrim,-  noParens+  prettyArrays,+  prettyTupleIdx, +  -- ** Utilities+  Val(..), PrettyEnv(..), prj, sizeEnv,+  noParens,+  tuple,+ ) where  -- standard libraries-import Prelude                                  hiding ( exp )+import Prelude                                          hiding ( exp, seq ) import Data.List import Text.PrettyPrint  -- friends-import Data.Array.Accelerate.Array.Sugar-import Data.Array.Accelerate.Tuple-import Data.Array.Accelerate.AST+import Data.Array.Accelerate.Array.Sugar                hiding ( tuple )+import Data.Array.Accelerate.Product+import Data.Array.Accelerate.AST                        hiding ( Val(..), prj ) import Data.Array.Accelerate.Type + -- Pretty printing--- ---------------+-- =============== --- The type of pretty printing functions for array computations.----type PrettyAcc acc = forall aenv t. Int -> (Doc -> Doc) -> acc aenv t -> Doc+-- Pretty printing for the knot-tied 'OpenAcc'+-- -------------------------------------------  -- Pretty print an array expression -- prettyOpenAcc :: PrettyAcc OpenAcc-prettyOpenAcc alvl wrap (OpenAcc acc) = prettyPreAcc prettyOpenAcc alvl wrap acc+prettyOpenAcc wrap aenv (OpenAcc acc) = prettyPreOpenAcc prettyOpenAcc wrap aenv acc -prettyPreAcc+prettyOpenAfun :: Val aenv -> OpenAfun aenv t -> Doc+prettyOpenAfun = prettyPreOpenAfun prettyOpenAcc+++-- Pretty print scalar expressions+--+prettyOpenFun :: Val env -> Val aenv -> OpenFun env aenv fun -> Doc+prettyOpenFun = prettyPreOpenFun prettyOpenAcc++prettyOpenExp :: (Doc -> Doc) -> Val env -> Val aenv -> OpenExp env aenv t -> Doc+prettyOpenExp = prettyPreOpenExp prettyOpenAcc+++-- Pretty printing for open 'PreOpenAcc'+-- -------------------------------------++-- The type of pretty printing functions for array computations.+--+type PrettyAcc acc = forall aenv t.+       (Doc -> Doc)+    -> Val aenv+    -> acc aenv t+    -> Doc++prettyPreOpenAcc     :: forall acc aenv arrs.        PrettyAcc acc-    -> Int                                      -- level of array variables     -> (Doc -> Doc)                             -- apply to compound expressions+    -> Val aenv                                 -- environment of array variables     -> PreOpenAcc acc aenv arrs     -> Doc-prettyPreAcc prettyAcc alvl wrap = pp+prettyPreOpenAcc prettyAcc wrap aenv = pp   where-    ppE :: PreOpenExp acc env aenv e -> Doc-    ppE = prettyPreExp prettyAcc 0 alvl parens+    ppE :: PreExp acc aenv e -> Doc+    ppE = prettyPreExp prettyAcc parens aenv -    ppF :: PreOpenFun acc env aenv f -> Doc-    ppF = parens . prettyPreFun prettyAcc alvl+    ppSh :: PreExp acc aenv sh -> Doc+    ppSh = parens . prettyPreExp prettyAcc noParens aenv +    ppF :: PreFun acc aenv f -> Doc+    ppF = parens . prettyPreFun prettyAcc aenv+     ppA :: acc aenv a -> Doc-    ppA = prettyAcc alvl parens+    ppA = prettyAcc parens aenv      ppAF :: PreOpenAfun acc aenv f -> Doc-    ppAF = parens . prettyPreAfun prettyAcc alvl+    ppAF = parens . prettyPreOpenAfun prettyAcc aenv      ppB :: forall sh e. Elt e         => {-dummy-} acc aenv (Array sh e)@@ -97,23 +139,23 @@       where         -- TLM: derp, can't unwrap into a PreOpenAcc to pattern match on Alet         isAlet doc  = "let" `isPrefixOf` render doc-        acc1'       = prettyAcc alvl     noParens acc1-        acc2'       = prettyAcc (alvl+1) noParens acc2-        a           = char 'a' <> int alvl+        acc1'       = prettyAcc noParens aenv            acc1+        acc2'       = prettyAcc noParens (aenv `Push` a) acc2+        a           = char 'a' <> int (sizeEnv aenv)      pp (Awhile p afun acc)      = "awhile" .$ [ppAF p, ppAF afun, ppA acc]-    pp (Atuple tup)             = prettyAtuple prettyAcc alvl tup-    pp (Avar idx)               = text $ 'a' : show (alvl - idxToInt idx - 1)+    pp (Atuple tup)             = prettyAtuple prettyAcc aenv tup+    pp (Avar idx)               = prj idx aenv     pp (Aprj ix arrs)           = wrap $ char '#' <> prettyTupleIdx ix <+> ppA arrs     pp (Apply afun acc)         = wrap $ sep [ ppAF afun, ppA acc ]     pp (Acond e acc1 acc2)      = wrap $ sep [ ppE e, text "?|", tuple [ppA acc1, ppA acc2] ]-    pp (Slice _ty acc ix)       = wrap $ sep [ ppA acc, char '!', prettyPreExp prettyAcc 0 alvl noParens ix ]+    pp (Slice _ty acc ix)       = wrap $ sep [ ppA acc, char '!', prettyPreExp prettyAcc noParens aenv ix ]     pp (Use arrs)               = "use"         .$ [ prettyArrays (arrays (undefined :: arrs)) arrs ]     pp (Unit e)                 = "unit"        .$ [ ppE e ]-    pp (Generate sh f)          = "generate"    .$ [ ppE sh, ppF f ]-    pp (Transform sh ix f acc)  = "transform"   .$ [ ppE sh, ppF ix, ppF f, ppA acc ]-    pp (Reshape sh acc)         = "reshape"     .$ [ ppE sh, ppA acc ]-    pp (Replicate _ty ix acc)   = "replicate"   .$ [ prettyPreExp prettyAcc 0 alvl noParens ix, ppA acc ]+    pp (Generate sh f)          = "generate"    .$ [ ppSh sh, ppF f ]+    pp (Transform sh ix f acc)  = "transform"   .$ [ ppSh sh, ppF ix, ppF f, ppA acc ]+    pp (Reshape sh acc)         = "reshape"     .$ [ ppSh sh, ppA acc ]+    pp (Replicate _ty ix acc)   = "replicate"   .$ [ ppSh ix, ppA acc ]     pp (Map f acc)              = "map"         .$ [ ppF f, ppA acc ]     pp (ZipWith f acc1 acc2)    = "zipWith"     .$ [ ppF f, ppA acc1, ppA acc2 ]     pp (Fold f e acc)           = "fold"        .$ [ ppF f, ppE e, ppA acc ]@@ -127,75 +169,147 @@     pp (Scanr' f e acc)         = "scanr'"      .$ [ ppF f, ppE e, ppA acc ]     pp (Scanr1 f acc)           = "scanr1"      .$ [ ppF f, ppA acc ]     pp (Permute f dfts p acc)   = "permute"     .$ [ ppF f, ppA dfts, ppF p, ppA acc ]-    pp (Backpermute sh p acc)   = "backpermute" .$ [ ppE sh, ppF p, ppA acc ]+    pp (Backpermute sh p acc)   = "backpermute" .$ [ ppSh sh, ppF p, ppA acc ]     pp (Aforeign ff _afun acc)  = "aforeign"    .$ [ text (strForeign ff), {- ppAf afun, -} ppA acc ]     pp (Stencil sten bndy acc)  = "stencil"     .$ [ ppF sten, ppB acc bndy, ppA acc ]     pp (Stencil2 sten bndy1 acc1 bndy2 acc2)                                 = "stencil2"    .$ [ ppF sten, ppB acc1 bndy1, ppA acc1,                                                                ppB acc2 bndy2, ppA acc2 ] +    -- pp (Collect s)              = wrap $ hang (text "collect") 2+    --                                    $ encloseSep lbrace rbrace semi+    --                                    $ prettyPreOpenSeq prettyAcc wrap aenv Empty s --- Pretty print a function over array computations.----prettyAfun :: Int -> OpenAfun aenv t -> Doc-prettyAfun = prettyPreAfun prettyOpenAcc -prettyPreAfun :: forall acc aenv fun. PrettyAcc acc -> Int -> PreOpenAfun acc aenv fun -> Doc-prettyPreAfun pp alvl fun =-  let (n, bodyDoc) = count n fun-  in-  char '\\' <> hsep [text $ 'a' : show idx | idx <- [alvl..alvl + n]] <+>-  text "->" <+> bodyDoc+{--+-- Pretty print a computation over sequences+--+prettyPreOpenSeq+    :: forall acc aenv senv arrs.+       PrettyAcc acc+    -> (Doc -> Doc)                             -- apply to compound expressions+    -> Val aenv                                 -- environment of array variables+    -> Val senv                                 -- environment of sequence variables+    -> PreOpenSeq acc aenv senv arrs+    -> [Doc]+prettyPreOpenSeq prettyAcc wrap aenv senv seq =+  case seq of+    Producer p s' -> prettyP p : prettyPreOpenSeq prettyAcc wrap aenv (senv `Push` var (sizeEnv senv)) s'+    Consumer c    -> [prettyC c]+    Reify ix      -> [var (idxToInt ix)]   where-     count :: Int -> PreOpenAfun acc aenv' fun' -> (Int, Doc)-     count lvl (Abody body) = (-1, pp (lvl + alvl + 1) noParens body)-     count lvl (Alam  fun') = let (n, body) = count lvl fun' in (1 + n, body)+    var n         = char 's' <> int n+    name .$  docs = wrap $ hang (var (sizeEnv senv) <+> text ":=" <+> text name) 2 (sep docs)+    name ..$ docs = wrap $ hang (text name) 2 (sep docs) --- Pretty print a function over scalar expressions.----prettyFun :: Int -> OpenFun env aenv fun -> Doc-prettyFun = prettyPreFun prettyOpenAcc+    ppE :: PreExp acc aenv e -> Doc+    ppE = prettyPreExp prettyAcc parens aenv -prettyPreFun :: PrettyAcc acc -> Int -> PreOpenFun acc env aenv fun -> Doc-prettyPreFun pp = prettyPreOpenFun pp 0+    ppF :: PreFun acc aenv f -> Doc+    ppF = parens . prettyPreFun prettyAcc aenv -prettyPreOpenFun :: forall acc env aenv fun. PrettyAcc acc -> Int -> Int -> PreOpenFun acc env aenv fun -> Doc-prettyPreOpenFun pp lvl alvl fun =-  let (n, bodyDoc) = count n fun-  in-  char '\\' <> hsep [text $ 'x' : show idx | idx <- [lvl..n]] <+>-  text "->" <+> bodyDoc+    ppA :: acc aenv a -> Doc+    ppA = prettyAcc parens aenv++    ppAF :: PreOpenAfun acc aenv f -> Doc+    ppAF = parens . prettyPreOpenAfun prettyAcc aenv++    ppX :: Idx aenv' a -> Doc+    ppX x = var (idxToInt x)++    ppSlix :: SliceIndex slix sl co sh -> Doc+    ppSlix SliceNil       = text "Z"+    ppSlix (SliceAll s)   = ppSlix s <+> text ":." <+> text "All"+    ppSlix (SliceFixed s) = ppSlix s <+> text ":." <+> text "Split"++    prettyP :: forall a. Producer acc aenv senv a -> Doc+    prettyP p =+      case p of+        StreamIn _        -> "streamIn"      .$ [ text "..." ]+        ToSeq slix _ a    -> "toSeq"         .$ [ ppSlix slix, ppA a ]+        MapSeq f x        -> "mapSeq"        .$ [ ppAF f , ppX x ]+        ChunkedMapSeq f x -> "chunkedMapSeq" .$ [ ppAF f , ppX x ]+        ZipWithSeq f x y  -> "zipWithSeq"    .$ [ ppAF f , ppX x , ppX y ]+        ScanSeq f e x     -> "foldSeq"       .$ [ ppF f , ppE e , ppX x ]++    prettyC :: forall a. Consumer acc aenv senv a -> Doc+    prettyC c =+      case c of+        FoldSeq f e x        -> "foldSeq"        ..$ [ ppF f , ppE e , ppX x ]+        FoldSeqFlatten f a x -> "foldSeqFlatten" ..$ [ ppAF f , ppA a , ppX x ]+        Stuple t             -> tuple (prettyT t)++    prettyT :: forall t. Atuple (Consumer acc aenv senv) t -> [Doc]+    prettyT NilAtup        = []+    prettyT (SnocAtup t c) = prettyT t ++ [prettyC c]+--}+++-- Pretty print a function over array computations.+--+prettyPreOpenAfun+    :: forall acc aenv f.+       PrettyAcc acc+    -> Val aenv+    -> PreOpenAfun acc aenv f+    -> Doc+prettyPreOpenAfun pp aenv afun = char '\\' <> next aenv afun   where-     count :: Int -> PreOpenFun acc env' aenv' fun' -> (Int, Doc)-     count l (Body body) = (lvl-1, prettyPreExp pp (l + 1) alvl noParens body)-     count l (Lam  fun') = let (n, body) = count l fun' in (1 + n, body)+    next :: Val aenv' -> PreOpenAfun acc aenv' f' -> Doc+    next aenv' (Abody body) = text "->" <+> pp noParens aenv' body+    next aenv' (Alam afun') =+      let a = char 'a' <> int (sizeEnv aenv')+      in  a <+> next (aenv' `Push` a) afun' --- Pretty print an expression.++-- Pretty print a scalar function. ----- * Apply the wrapping combinator (3rd argument) to any compound expressions.+prettyPreFun :: PrettyAcc acc -> Val aenv -> PreFun acc aenv fun -> Doc+prettyPreFun pp = prettyPreOpenFun pp Empty++prettyPreOpenFun+    :: forall acc env aenv f.+       PrettyAcc acc+    -> Val env                                  -- environment of scalar variables+    -> Val aenv                                 -- environment of array variables+    -> PreOpenFun acc env aenv f+    -> Doc+prettyPreOpenFun pp env aenv fun = char '\\' <> next env fun+  where+    next :: Val env' -> PreOpenFun acc env' aenv f' -> Doc+    next env' (Body body) = text "->" <+> prettyPreOpenExp pp noParens env' aenv body+    next env' (Lam fun')  =+      let x = char 'x' <> int (sizeEnv env')+      in  x <+> next (env' `Push` x) fun'+++-- Pretty print a scalar expression. ---prettyExp :: Int -> Int -> (Doc -> Doc) -> OpenExp env aenv t -> Doc-prettyExp = prettyPreExp prettyOpenAcc+prettyPreExp :: PrettyAcc acc -> (Doc -> Doc) -> Val aenv -> PreExp acc aenv t -> Doc+prettyPreExp pp wrap = prettyPreOpenExp pp wrap Empty -prettyPreExp+prettyPreOpenExp     :: forall acc t env aenv.        PrettyAcc acc-    -> Int                                      -- level of scalar variables-    -> Int                                      -- level of array variables     -> (Doc -> Doc)                             -- apply to compound expressions+    -> Val env                                  -- environment of scalar variables+    -> Val aenv                                 -- environment of array variables     -> PreOpenExp acc env aenv t     -> Doc-prettyPreExp prettyAcc lvl alvl wrap = pp+prettyPreOpenExp prettyAcc wrap env aenv = pp   where     ppE, ppE' :: PreOpenExp acc env aenv e -> Doc-    ppE  = prettyPreExp prettyAcc lvl alvl parens-    ppE' = prettyPreExp prettyAcc lvl alvl noParens+    ppE  = prettyPreOpenExp prettyAcc parens env aenv+    ppE' = prettyPreOpenExp prettyAcc noParens env aenv +    ppSh :: PreOpenExp acc env aenv sh -> Doc+    ppSh = parens . ppE'+     ppF :: PreOpenFun acc env aenv f -> Doc-    ppF = parens . prettyPreOpenFun prettyAcc lvl alvl+    ppF = parens . prettyPreOpenFun prettyAcc env aenv      ppA :: acc aenv a -> Doc-    ppA = prettyAcc alvl parens+    ppA = prettyAcc parens aenv      -- pretty print a named array operation with its arguments     name .$ docs = wrap $ text name <+> sep docs@@ -212,13 +326,13 @@       where         isLet (Let _ _)     = True         isLet _             = False-        e1'                 = prettyPreExp prettyAcc lvl     alvl noParens e1-        e2'                 = prettyPreExp prettyAcc (lvl+1) alvl noParens e2-        x                   = char 'x' <> int lvl+        e1'                 = prettyPreOpenExp prettyAcc noParens env            aenv e1+        e2'                 = prettyPreOpenExp prettyAcc noParens (env `Push` x) aenv e2+        x                   = char 'x' <> int (sizeEnv env)      pp (PrimApp p a)       | infixOp, Tuple (NilTup `SnocTup` x `SnocTup` y) <- a-      = wrap $ ppE x <+> f <+> ppE y+      = wrap $ sep [ppE x, f, ppE y]       | otherwise       = wrap $ f' <+> ppE a       where@@ -229,49 +343,56 @@         f'           = if infixOp then parens f else f      pp (PrimConst a)            = prettyConst a-    pp (Tuple tup)              = prettyTuple prettyAcc lvl alvl tup-    pp (Var idx)                = text $ 'x' : show (lvl - idxToInt idx - 1)+    pp (Tuple tup)              = prettyTuple prettyAcc env aenv tup+    pp (Var idx)                = prj idx env     pp (Const v)                = text $ show (toElt v :: t)     pp (Prj idx e)              = wrap $ char '#' <> prettyTupleIdx idx <+> ppE e     pp (Cond c t e)             = wrap $ sep [ ppE c, char '?' , tuple [ ppE' t, ppE' e ]]     pp IndexNil                 = char 'Z'-    pp (IndexAny)               = text "indexAny"-    pp (IndexCons t h)          = wrap $ ppE' t <+> text ":." <+> ppE' h+    pp IndexAny                 = text "indexAny"+    pp (IndexCons t h)          = ppE' t <+> text ":." <+> ppE' h     pp (IndexHead ix)           = "indexHead"  .$ [ ppE ix ]     pp (IndexTail ix)           = "indexTail"  .$ [ ppE ix ]     pp (IndexSlice _ slix sh)   = "indexSlice" .$ [ ppE slix, ppE sh ]     pp (IndexFull _ slix sl)    = "indexFull"  .$ [ ppE slix, ppE sl ]-    pp (ToIndex sh ix)          = "toIndex"    .$ [ ppE sh, ppE ix ]-    pp (FromIndex sh ix)        = "fromIndex"  .$ [ ppE sh, ppE ix ]+    pp (ToIndex sh ix)          = "toIndex"    .$ [ ppSh sh, ppSh ix ]+    pp (FromIndex sh ix)        = "fromIndex"  .$ [ ppSh sh, ppE ix ]     pp (While p f x)            = "while"      .$ [ ppF p, ppF f, ppE x ]     pp (Foreign ff _f e)        = "foreign"    .$ [ text (strForeign ff), {- ppF f, -} ppE e ]     pp (Shape idx)              = "shape"      .$ [ ppA idx ]-    pp (ShapeSize idx)          = "shapeSize"  .$ [ parens (ppE idx) ]-    pp (Intersect sh1 sh2)      = "intersect"  .$ [ ppE sh1, ppE sh2 ]+    pp (ShapeSize idx)          = "shapeSize"  .$ [ ppSh idx ]+    pp (Intersect sh1 sh2)      = "intersect"  .$ [ ppSh sh1, ppSh sh2 ]+    pp (Union sh1 sh2)          = "union"      .$ [ ppSh sh1, ppSh sh2 ]     pp (Index idx i)            = wrap $ cat [ ppA idx, char '!',  ppE i ]     pp (LinearIndex idx i)      = wrap $ cat [ ppA idx, text "!!", ppE i ]   -- Pretty print nested pairs as a proper tuple. ---prettyAtuple :: forall acc aenv t.-                PrettyAcc acc-             -> Int-             -> Atuple (acc aenv) t-             -> Doc-prettyAtuple pp alvl = tuple . collect+prettyAtuple+    :: forall acc aenv t.+       PrettyAcc acc+    -> Val aenv+    -> Atuple (acc aenv) t+    -> Doc+prettyAtuple pp aenv = tuple . collect   where     collect :: Atuple (acc aenv) t' -> [Doc]     collect NilAtup          = []-    collect (SnocAtup tup a) = collect tup ++ [pp alvl noParens a]+    collect (SnocAtup tup a) = collect tup ++ [pp noParens aenv a] -prettyTuple :: forall acc env aenv t.-               PrettyAcc acc -> Int -> Int -> Tuple (PreOpenExp acc env aenv) t -> Doc-prettyTuple pp lvl alvl = tuple . collect+prettyTuple+    :: forall acc env aenv t.+       PrettyAcc acc+    -> Val env+    -> Val aenv+    -> Tuple (PreOpenExp acc env aenv) t+    -> Doc+prettyTuple pp env aenv = tuple . collect   where     collect :: Tuple (PreOpenExp acc env aenv) t' -> [Doc]     collect NilTup          = []-    collect (SnocTup tup e) = collect tup ++ [prettyPreExp pp lvl alvl noParens e]+    collect (SnocTup tup e) = collect tup ++ [prettyPreOpenExp pp noParens env aenv e]   -- Pretty print an index for a tuple projection@@ -279,7 +400,7 @@ prettyTupleIdx :: TupleIdx t e -> Doc prettyTupleIdx = int . toInt   where-    toInt  :: TupleIdx t e -> Int+    toInt :: TupleIdx t e -> Int     toInt ZeroTupIdx       = 0     toInt (SuccTupIdx tup) = toInt tup + 1 @@ -294,60 +415,71 @@ -- operator should be printed infix. -- prettyPrim :: PrimFun a -> (Bool, Doc)-prettyPrim (PrimAdd _)            = (True,  char '+')-prettyPrim (PrimSub _)            = (True,  char '-')-prettyPrim (PrimMul _)            = (True,  char '*')-prettyPrim (PrimNeg _)            = (False, text "negate")-prettyPrim (PrimAbs _)            = (False, text "abs")-prettyPrim (PrimSig _)            = (False, text "signum")-prettyPrim (PrimQuot _)           = (False, text "quot")-prettyPrim (PrimRem _)            = (False, text "rem")-prettyPrim (PrimIDiv _)           = (False, text "div")-prettyPrim (PrimMod _)            = (False, text "mod")-prettyPrim (PrimBAnd _)           = (True,  text ".&.")-prettyPrim (PrimBOr _)            = (True,  text ".|.")-prettyPrim (PrimBXor _)           = (False, text "xor")-prettyPrim (PrimBNot _)           = (False, text "complement")-prettyPrim (PrimBShiftL _)        = (False, text "shiftL")-prettyPrim (PrimBShiftR _)        = (False, text "shiftR")-prettyPrim (PrimBRotateL _)       = (False, text "rotateL")-prettyPrim (PrimBRotateR _)       = (False, text "rotateR")-prettyPrim (PrimFDiv _)           = (True,  char '/')-prettyPrim (PrimRecip _)          = (False, text "recip")-prettyPrim (PrimSin _)            = (False, text "sin")-prettyPrim (PrimCos _)            = (False, text "cos")-prettyPrim (PrimTan _)            = (False, text "tan")-prettyPrim (PrimAsin _)           = (False, text "asin")-prettyPrim (PrimAcos _)           = (False, text "acos")-prettyPrim (PrimAtan _)           = (False, text "atan")-prettyPrim (PrimAsinh _)          = (False, text "asinh")-prettyPrim (PrimAcosh _)          = (False, text "acosh")-prettyPrim (PrimAtanh _)          = (False, text "atanh")-prettyPrim (PrimExpFloating _)    = (False, text "exp")-prettyPrim (PrimSqrt _)           = (False, text "sqrt")-prettyPrim (PrimLog _)            = (False, text "log")-prettyPrim (PrimFPow _)           = (True,  text "**")-prettyPrim (PrimLogBase _)        = (False, text "logBase")-prettyPrim (PrimTruncate _ _)     = (False, text "truncate")-prettyPrim (PrimRound _ _)        = (False, text "round")-prettyPrim (PrimFloor _ _)        = (False, text "floor")-prettyPrim (PrimCeiling _ _)      = (False, text "ceiling")-prettyPrim (PrimAtan2 _)          = (False, text "atan2")-prettyPrim (PrimLt _)             = (True,  text "<*")-prettyPrim (PrimGt _)             = (True,  text ">*")-prettyPrim (PrimLtEq _)           = (True,  text "<=*")-prettyPrim (PrimGtEq _)           = (True,  text ">=*")-prettyPrim (PrimEq _)             = (True,  text "==*")-prettyPrim (PrimNEq _)            = (True,  text "/=*")-prettyPrim (PrimMax _)            = (False, text "max")-prettyPrim (PrimMin _)            = (False, text "min")-prettyPrim PrimLAnd               = (True,  text "&&*")-prettyPrim PrimLOr                = (True,  text "||*")-prettyPrim PrimLNot               = (False, text "not")-prettyPrim PrimOrd                = (False, text "ord")-prettyPrim PrimChr                = (False, text "chr")-prettyPrim PrimBoolToInt          = (False, text "boolToInt")-prettyPrim (PrimFromIntegral _ _) = (False, text "fromIntegral")+prettyPrim PrimAdd{}                = (True,  char '+')+prettyPrim PrimSub{}                = (True,  char '-')+prettyPrim PrimMul{}                = (True,  char '*')+prettyPrim PrimNeg{}                = (False, text "negate")+prettyPrim PrimAbs{}                = (False, text "abs")+prettyPrim PrimSig{}                = (False, text "signum")+prettyPrim PrimQuot{}               = (False, text "quot")+prettyPrim PrimRem{}                = (False, text "rem")+prettyPrim PrimQuotRem{}            = (False, text "quotRem")+prettyPrim PrimIDiv{}               = (False, text "div")+prettyPrim PrimMod{}                = (False, text "mod")+prettyPrim PrimDivMod{}             = (False, text "divMod")+prettyPrim PrimBAnd{}               = (True,  text ".&.")+prettyPrim PrimBOr{}                = (True,  text ".|.")+prettyPrim PrimBXor{}               = (False, text "xor")+prettyPrim PrimBNot{}               = (False, text "complement")+prettyPrim PrimBShiftL{}            = (False, text "shiftL")+prettyPrim PrimBShiftR{}            = (False, text "shiftR")+prettyPrim PrimBRotateL{}           = (False, text "rotateL")+prettyPrim PrimBRotateR{}           = (False, text "rotateR")+prettyPrim PrimPopCount{}           = (False, text "popCount")+prettyPrim PrimCountLeadingZeros{}  = (False, text "countLeadingZeros")+prettyPrim PrimCountTrailingZeros{} = (False, text "countTrailingZeros")+prettyPrim PrimFDiv{}               = (True,  char '/')+prettyPrim PrimRecip{}              = (False, text "recip")+prettyPrim PrimSin{}                = (False, text "sin")+prettyPrim PrimCos{}                = (False, text "cos")+prettyPrim PrimTan{}                = (False, text "tan")+prettyPrim PrimAsin{}               = (False, text "asin")+prettyPrim PrimAcos{}               = (False, text "acos")+prettyPrim PrimAtan{}               = (False, text "atan")+prettyPrim PrimSinh{}               = (False, text "sinh")+prettyPrim PrimCosh{}               = (False, text "cosh")+prettyPrim PrimTanh{}               = (False, text "tanh")+prettyPrim PrimAsinh{}              = (False, text "asinh")+prettyPrim PrimAcosh{}              = (False, text "acosh")+prettyPrim PrimAtanh{}              = (False, text "atanh")+prettyPrim PrimExpFloating{}        = (False, text "exp")+prettyPrim PrimSqrt{}               = (False, text "sqrt")+prettyPrim PrimLog{}                = (False, text "log")+prettyPrim PrimFPow{}               = (True,  text "**")+prettyPrim PrimLogBase{}            = (False, text "logBase")+prettyPrim PrimTruncate{}           = (False, text "truncate")+prettyPrim PrimRound{}              = (False, text "round")+prettyPrim PrimFloor{}              = (False, text "floor")+prettyPrim PrimCeiling{}            = (False, text "ceiling")+prettyPrim PrimAtan2{}              = (False, text "atan2")+prettyPrim PrimIsNaN{}              = (False, text "isNaN")+prettyPrim PrimLt{}                 = (True,  text "<")+prettyPrim PrimGt{}                 = (True,  text ">")+prettyPrim PrimLtEq{}               = (True,  text "<=")+prettyPrim PrimGtEq{}               = (True,  text ">=")+prettyPrim PrimEq{}                 = (True,  text "==")+prettyPrim PrimNEq{}                = (True,  text "/=")+prettyPrim PrimMax{}                = (False, text "max")+prettyPrim PrimMin{}                = (False, text "min")+prettyPrim PrimLAnd                 = (True,  text "&&")+prettyPrim PrimLOr                  = (True,  text "||")+prettyPrim PrimLNot                 = (False, text "not")+prettyPrim PrimOrd                  = (False, text "ord")+prettyPrim PrimChr                  = (False, text "chr")+prettyPrim PrimBoolToInt            = (False, text "boolToInt")+prettyPrim PrimFromIntegral{}       = (False, text "fromIntegral")+prettyPrim PrimToFloating{}         = (False, text "toFloating")+prettyPrim (PrimCoerce _ t)         = (False, text "reinterpret_cast" <> char '<' <> text (show t) <> char '>')  {- -- Pretty print type@@ -397,8 +529,40 @@     _   -> cat (zipWith (<>) (left : repeat p) ds) <> right  --- Auxiliary ops---+-- Environments+-- ------------++data Val env where+  Empty ::                   Val ()+  Push  :: Val env -> Doc -> Val (env, t)++class PrettyEnv env where+  prettyEnv :: Val env++instance PrettyEnv () where+  prettyEnv = Empty++instance PrettyEnv env => PrettyEnv (env, t) where+  prettyEnv =+    let env = prettyEnv :: Val env+        x   = char 'a' <> int (sizeEnv env)+    in+    env `Push` x++sizeEnv :: Val env -> Int+sizeEnv Empty        = 0+sizeEnv (Push env _) = 1 + sizeEnv env++prj :: Idx env t -> Val env -> Doc+prj ZeroIdx      (Push _ v)   = v+prj (SuccIdx ix) (Push env _) = prj ix env+#if __GLASGOW_HASKELL__ < 800+prj _            _            = error "inconsistent valuation"+#endif+++-- Auxiliary operations+-- --------------------  -- Auxiliary dictionary operations --
− Data/Array/Accelerate/Pretty/Traverse.hs
@@ -1,257 +0,0 @@-{-# LANGUAGE GADTs, ScopedTypeVariables #-}--- |--- Module      : Data.Array.Accelerate.Pretty.Traverse--- Copyright   : [2010..2011] Sean Seefried--- License     : BSD3------ Maintainer  : Manuel M T Chakravarty <chak@cse.unsw.edu.au>--- Stability   : experimental--- Portability : non-portable (GHC extensions)----module Data.Array.Accelerate.Pretty.Traverse-  where---- friends-import Data.Array.Accelerate.Array.Sugar hiding ((!))-import Data.Array.Accelerate.AST-import Data.Array.Accelerate.Tuple-import Data.Array.Accelerate.Type---cat :: Show s => String -> s -> String-cat t s = t ++ show s--data Labels = Labels { accFormat :: String-                     , expFormat :: String-                     , funFormat :: String-                     , tupleFormat :: String-                     , arrayFormat :: String-                     , boundaryFormat :: String-                     , primFunFormat :: String-                     }--travAcc :: forall m b aenv a. Monad m => Labels -> (String -> String -> [m b] -> m b)-       -> (String -> String -> m b) -> OpenAcc aenv a -> m b-travAcc f c l (OpenAcc openAcc) = travAcc' openAcc-  where-    combine = c (accFormat f)-    leaf    = l (accFormat f)--    travAcc' :: PreOpenAcc OpenAcc aenv a -> m b-    travAcc' (Alet acc1 acc2)                      = combine "Alet" [travAcc f c l acc1, travAcc f c l acc2]-    travAcc' (Avar idx)                            = leaf   ("AVar " `cat` idxToInt idx)-    travAcc' (Apply afun acc)                      = combine "Apply" [travAfun f c l afun, travAcc f c l acc]-    travAcc' (Aforeign ff afun acc)                = combine ("Aforeign " ++ strForeign ff) [travAfun f c l afun, travAcc f c l acc]-    travAcc' (Acond e acc1 acc2)                   = combine "Acond" [travExp f c l e, travAcc f c l acc1, travAcc f c l acc2]-    travAcc' (Awhile cond body acc)                = combine "Awhile" [travAfun f c l cond, travAfun f c l body, travAcc f c l acc]-    travAcc' (Atuple tup)                          = combine "Atuple" [ travAtuple f c l tup ]-    travAcc' (Aprj idx a)                          = combine ("Aprj " `cat` tupleIdxToInt idx) [ travAcc f c l a ]-    travAcc' (Use arr)                             = combine "Use" [ travArrays f c l (arrays (undefined::a)) arr ]-    travAcc' (Unit e)                              = combine "Unit" [ travExp f c l e ]-    travAcc' (Generate sh fun)                     = combine "Generate" [ travExp f c l  sh, travFun f c l fun]-    travAcc' (Transform sh pf vf acc)              = combine "Transform" [ travExp f c l sh, travFun f c l pf, travFun f c l vf, travAcc f c l acc ]-    travAcc' (Reshape sh acc)                      = combine "Reshape" [ travExp f c l  sh, travAcc f c l acc ]-    travAcc' (Replicate _ ix acc)                  = combine "Replicate" [ travExp f c l  ix, travAcc f c l acc ]-    travAcc' (Slice _ acc ix)                      = combine "Slice" [ travAcc f c l acc, travExp f c l  ix ]-    travAcc' (Map fun acc)                         = combine "Map" [ travFun f c l fun, travAcc f c l acc ]-    travAcc' (ZipWith fun acc1 acc2)               = combine "ZipWith" [ travFun f c l fun, travAcc f c l acc1, travAcc f c l acc2 ]-    travAcc' (Fold fun e acc)                      = combine "Fold" [ travFun f c l fun, travExp f c l  e, travAcc f c l acc]-    travAcc' (Fold1 fun acc)                       = combine "Fold1" [ travFun f c l fun, travAcc f c l acc]-    travAcc' (FoldSeg fun e acc1 acc2)             = combine "FoldSeg" [ travFun f c l fun, travExp f c l  e-                                                                       , travAcc f c l acc1, travAcc f c l acc2 ]-    travAcc' (Fold1Seg fun acc1 acc2)              = combine "FoldSeg1" [ travFun f c l fun, travAcc f c l acc1, travAcc f c l acc2 ]-    travAcc' (Scanl fun e acc)                     = combine "Scanl" [ travFun f c l fun, travExp f c l  e, travAcc f c l acc ]-    travAcc' (Scanl' fun e acc)                    = combine "Scanl'" [ travFun f c l fun, travExp f c l  e, travAcc f c l acc ]-    travAcc' (Scanl1 fun acc)                      = combine "Scanl1" [ travFun f c l fun, travAcc f c l acc ]-    travAcc' (Scanr fun e acc)                     = combine "Scanr" [ travFun f c l fun, travExp f c l  e, travAcc f c l acc ]-    travAcc' (Scanr' fun e acc)                    = combine "Scanr'" [ travFun f c l fun, travExp f c l  e, travAcc f c l acc ]-    travAcc' (Scanr1 fun acc)                      = combine "Scanr1" [ travFun f c l fun, travAcc f c l acc ]-    travAcc' (Permute fun dfts p acc)              = combine "Permute" [ travFun f c l fun, travAcc f c l dfts-                                                                       , travFun f c l p, travAcc f c l acc]-    travAcc' (Backpermute sh p acc)                = combine "Backpermute" [ travExp f c l  sh, travFun f c l p, travAcc f c l acc]-    travAcc' (Stencil sten bndy acc)               = combine "Stencil" [ travFun f c l sten, travBoundary f l acc bndy-                                                                       , travAcc f c l acc]-    travAcc' (Stencil2 sten bndy1 acc1 bndy2 acc2) = combine "Stencil2" [ travFun f c l sten, travBoundary f l acc1 bndy1-                                                                        , travAcc f c l acc1, travBoundary f l acc2 bndy2-                                                                        , travAcc f c l acc2]--travExp :: forall m env aenv a b . Monad m => Labels-       -> (String -> String -> [m b] -> m b)-       -> (String -> String -> m b)-       -> OpenExp env aenv a -> m b-travExp f c l expr = travExp' expr-  where-    combine = c (expFormat f)-    leaf    = l (expFormat f)--    travExp' :: OpenExp env aenv a -> m b-    travExp' (Let e1 e2)                = combine "Let" [travExp f c l e1, travExp f c l e2]-    travExp' (Var idx)                  = leaf ("Var "   `cat` idxToInt idx)-    travExp' (Const v)                  = leaf ("Const " `cat` (toElt v :: a))-    travExp' (Tuple tup)                = combine "Tuple" [ travTuple f c l tup ]-    travExp' (Prj idx e)                = combine ("Prj " `cat` tupleIdxToInt idx) [ travExp f c l e ]-    travExp' (IndexNil)                 = leaf "IndexNil"-    travExp' (IndexCons t h)            = combine "IndexCons" [ travExp f c l t, travExp f c l h]-    travExp' (IndexHead ix)             = combine "IndexHead" [ travExp f c l ix ]-    travExp' (IndexTail ix)             = combine "IndexTail" [ travExp f c l ix ]-    travExp' (IndexAny)                 = leaf "IndexAny"-    travExp' (IndexSlice _ slix sh)     = combine "IndexSlice" [ travExp f c l slix, travExp f c l sh ]-    travExp' (IndexFull _ slix sl)      = combine "IndexFull" [ travExp f c l slix, travExp f c l sl ]-    travExp' (ToIndex sh ix)            = combine "ToIndex" [ travExp f c l sh, travExp f c l ix ]-    travExp' (FromIndex sh ix)          = combine "FromIndex" [ travExp f c l sh, travExp f c l ix ]-    travExp' (Cond cond thn els)        = combine "Cond" [travExp f c l cond, travExp f c l thn, travExp f c l els]-    travExp' (While cond body x)        = combine "While" [ travFun f c l cond, travFun f c l body, travExp f c l x ]-    travExp' (PrimConst a)              = leaf ("PrimConst " `cat` labelForConst a)-    travExp' (PrimApp p a)              = combine "PrimApp" [ l (primFunFormat f) (labelForPrimFun p), travExp f c l a ]-    travExp' (Index idx i)              = combine "Index" [ travAcc f c l idx, travExp f c l i]-    travExp' (LinearIndex idx i)        = combine "LinearIndex" [ travAcc f c l idx, travExp f c l i]-    travExp' (Shape idx)                = combine "Shape" [ travAcc f c l idx ]-    travExp' (ShapeSize e)              = combine "ShapeSize" [ travExp f c l e ]-    travExp' (Intersect sh1 sh2)        = combine "Intersect" [ travExp f c l sh1, travExp f c l sh2 ]-    travExp' (Foreign ff fun e)         = combine ("Foreign " ++ strForeign ff) [ travFun f c l fun, travExp f c l e ]---travAfun :: forall m b aenv fun. Monad m => Labels -> (String -> String -> [m b] -> m b)-        -> (String -> String -> m b) -> OpenAfun aenv fun -> m b-travAfun f c l openAfun = travAfun' openAfun-  where-    combine = c (funFormat f)-    travAfun' :: OpenAfun aenv fun -> m b-    travAfun' (Abody body) = combine "Abody" [ travAcc f c l body ]-    travAfun' (Alam fun)   = combine "Alam"  [ travAfun f c l fun ]--travArrays-    :: forall m a b. Monad m-    => Labels-    -> (String -> String -> [m b] -> m b)-    -> (String -> String -> m b)-    -> ArraysR a-    -> a-    -> m b-travArrays f c l = trav-  where-    combine = c (accFormat f)-    leaf    = l (accFormat f)-    ---    trav :: ArraysR a' -> a' -> m b-    trav ArraysRunit         ()       = leaf    "ArraysRunit"-    trav ArraysRarray        a        = combine "ArraysRarray" [ travArray f l a ]-    trav (ArraysRpair r1 r2) (a1, a2) = combine "ArraysRpair"  [trav r1 a1, trav r2 a2]--travArray :: forall dim a m b. Monad m => Labels -> (String -> String -> m b) -> Array dim a -> m b-travArray f l (Array sh _) = l (arrayFormat f) ("Array" `cat` (toElt sh :: dim))--travBoundary :: forall aenv dim e m b. (Monad m, Elt e) => Labels -> (String -> String -> m b)-             -> {-dummy-}OpenAcc aenv (Array dim e)-             -> Boundary (EltRepr e) -> m b-travBoundary f l boundary = travBoundary' boundary-  where-    leaf = l (boundaryFormat f)-    travBoundary' :: {-dummy-}OpenAcc aenv (Array dim e) -> Boundary (EltRepr e) -> m b-    travBoundary' _ Clamp        = leaf "Clamp"-    travBoundary' _ Mirror       = leaf "Mirror"-    travBoundary' _ Wrap         = leaf "Wrap"-    travBoundary' _ (Constant e) = leaf ("Constant " `cat` (toElt e :: e))---travAtuple-    :: forall m b aenv t. Monad m-    => Labels-    -> (String -> String -> [m b] -> m b)-    -> (String -> String -> m b)-    -> Atuple (OpenAcc aenv) t-    -> m b-travAtuple f c l = trav-  where-    leaf    = l (tupleFormat f)-    combine = c (tupleFormat f)-    ---    trav :: Atuple (OpenAcc aenv) t' -> m b-    trav NilAtup          = leaf    "NilAtup"-    trav (SnocAtup tup a) = combine "SnocAtup" [ trav tup, travAcc f c l a ]---travFun :: forall m b env aenv fun.Monad m => Labels -> (String -> String -> [m b] -> m b)-        -> (String -> String -> m b) -> OpenFun env aenv fun -> m b-travFun f c l openFun = travFun' openFun-  where-    combine = c (funFormat f)-    travFun' :: OpenFun env aenv fun -> m b-    travFun' (Body body) = combine "Body" [ travExp f c l body ]-    travFun' (Lam fun)   = combine "Lam"  [ travFun f c l fun ]---travTuple :: forall m b env aenv t. Monad m => Labels -> (String -> String -> [m b] -> m b)-          -> (String -> String -> m b) -> Tuple (OpenExp env aenv) t -> m b-travTuple f c l tuple = travTuple' tuple-  where-    leaf    = l (tupleFormat f)-    combine = c (tupleFormat f)-    travTuple' :: Tuple (OpenExp env aenv) t -> m b-    travTuple' NilTup          = leaf     "NilTup"-    travTuple' (SnocTup tup e) = combine "SnocTup" [ travTuple f c l tup, travExp f c l e ]--labelForPrimFun :: PrimFun a -> String-labelForPrimFun (PrimAdd _)            = "PrimAdd"-labelForPrimFun (PrimSub _)            = "PrimSub"-labelForPrimFun (PrimMul _)            = "PrimMul"-labelForPrimFun (PrimNeg _)            = "PrimNeg"-labelForPrimFun (PrimAbs _)            = "PrimAbs"-labelForPrimFun (PrimSig _)            = "PrimSig"-labelForPrimFun (PrimQuot _)           = "PrimQuot"-labelForPrimFun (PrimRem _)            = "PrimRem"-labelForPrimFun (PrimIDiv _)           = "PrimIDiv"-labelForPrimFun (PrimMod _)            = "PrimMod"-labelForPrimFun (PrimBAnd _)           = "PrimBAnd"-labelForPrimFun (PrimBOr _)            = "PrimBOr"-labelForPrimFun (PrimBXor _)           = "PrimBXor"-labelForPrimFun (PrimBNot _)           = "PrimBNot"-labelForPrimFun (PrimBShiftL _)        = "PrimBShiftL"-labelForPrimFun (PrimBShiftR _)        = "PrimBShiftR"-labelForPrimFun (PrimBRotateL _)       = "PrimBRotateL"-labelForPrimFun (PrimBRotateR _)       = "PrimBRotateR"-labelForPrimFun (PrimFDiv _)           = "PrimFDiv"-labelForPrimFun (PrimRecip _)          = "PrimRecip"-labelForPrimFun (PrimSin _)            = "PrimSin"-labelForPrimFun (PrimCos _)            = "PrimCos"-labelForPrimFun (PrimTan _)            = "PrimTan"-labelForPrimFun (PrimAsin _)           = "PrimAsin"-labelForPrimFun (PrimAcos _)           = "PrimAcos"-labelForPrimFun (PrimAtan _)           = "PrimAtan"-labelForPrimFun (PrimAsinh _)          = "PrimAsinh"-labelForPrimFun (PrimAcosh _)          = "PrimAcosh"-labelForPrimFun (PrimAtanh _)          = "PrimAtanh"-labelForPrimFun (PrimExpFloating _)    = "PrimExpFloating"-labelForPrimFun (PrimSqrt _)           = "PrimSqrt"-labelForPrimFun (PrimLog _)            = "PrimLog"-labelForPrimFun (PrimFPow _)           = "PrimFPow"-labelForPrimFun (PrimLogBase _)        = "PrimLogBase"-labelForPrimFun (PrimTruncate _ _)     = "PrimTruncate"-labelForPrimFun (PrimRound _ _)        = "PrimRound"-labelForPrimFun (PrimFloor _ _)        = "PrimFloor"-labelForPrimFun (PrimCeiling _ _)      = "PrimCeiling"-labelForPrimFun (PrimAtan2 _)          = "PrimAtan2"-labelForPrimFun (PrimLt _)             = "PrimLt"-labelForPrimFun (PrimGt _)             = "PrimGt"-labelForPrimFun (PrimLtEq _)           = "PrimLtEq"-labelForPrimFun (PrimGtEq _)           = "PrimGtEq"-labelForPrimFun (PrimEq _)             = "PrimEq"-labelForPrimFun (PrimNEq _)            = "PrimNEq"-labelForPrimFun (PrimMax _)            = "PrimMax"-labelForPrimFun (PrimMin _)            = "PrimMin"-labelForPrimFun PrimLAnd               = "PrimLAnd"-labelForPrimFun PrimLOr                = "PrimLOr"-labelForPrimFun PrimLNot               = "PrimLNot"-labelForPrimFun PrimOrd                = "PrimOrd"-labelForPrimFun PrimChr                = "PrimChr"-labelForPrimFun PrimBoolToInt          = "PrimBoolToInt"-labelForPrimFun (PrimFromIntegral _ _) = "PrimFromIntegral"--labelForConst :: PrimConst a -> String-labelForConst (PrimMinBound _) = "PrimMinBound"-labelForConst (PrimMaxBound _) = "PrimMaxBound"-labelForConst (PrimPi       _) = "PrimPi"---- Auxiliary ops----
+ Data/Array/Accelerate/Product.hs view
@@ -0,0 +1,177 @@+{-# LANGUAGE ConstraintKinds       #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE GADTs                 #-}+{-# LANGUAGE KindSignatures        #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies          #-}+{-# LANGUAGE UndecidableInstances  #-}+{-# OPTIONS_HADDOCK hide #-}+-- |+-- Module      : Data.Array.Accelerate.Product+-- Copyright   : [2008..2017] Manuel M T Chakravarty, Gabriele Keller+--               [2009..2017] Trevor L. McDonell+--               [2013..2017] Robert Clifton-Everest+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- Our representation of products are heterogenous snoc lists, which are typed by+-- type lists, where '()' and '(,)' are type-level nil and snoc, respectively.+-- The components may only be drawn from types that can be used as array+-- elements.+--++module Data.Array.Accelerate.Product (++  -- * Tuple representation+  TupleIdx(..), IsProduct(..), ProdR(..)++) where++-- |Type-safe projection indices for tuples.+--+-- NB: We index tuples by starting to count from the *right*!+--+data TupleIdx t e where+  ZeroTupIdx ::                 TupleIdx (t, s) s+  SuccTupIdx :: TupleIdx t e -> TupleIdx (t, s) e++-- |Product reification+--+data ProdR cst t where+  ProdRunit   :: ProdR cst ()+  ProdRsnoc   :: cst e => ProdR cst t -> ProdR cst (t,e)++-- |Conversion between surface product types and our product representation.+--+-- We parameterise our products by a constraint on their elements (the 'cst' argument). Every element+-- in the product must obey this constraint, but the products themselves do necessarily not have to.+--+class IsProduct cst tup where+  type ProdRepr tup+  fromProd :: proxy cst -> tup -> ProdRepr tup+  toProd   :: proxy cst -> ProdRepr tup -> tup+  prod     :: proxy cst -> {- dummy -} tup -> ProdR cst (ProdRepr tup)++instance IsProduct cst () where+  type ProdRepr ()   = ()+  fromProd _         = id+  toProd _           = id+  prod _ _           = ProdRunit++instance (cst a, cst b) => IsProduct cst (a, b) where+  type ProdRepr (a, b)   = (((), a), b)+  fromProd _ (a, b)      = (((), a), b)+  toProd _ (((), a), b)  = (a, b)+  prod _ _               = ProdRsnoc $ ProdRsnoc ProdRunit++instance (cst a, cst b, cst c) => IsProduct cst (a, b, c) where+  type ProdRepr (a, b, c)    = (ProdRepr (a, b), c)+  fromProd _ (a, b, c)       = ((((), a), b), c)+  toProd _ ((((), a), b), c) = (a, b, c)+  prod p _                   = ProdRsnoc (prod p (undefined :: (a,b)))++instance (cst a, cst b, cst c, cst d) => IsProduct cst (a, b, c, d) where+  type ProdRepr (a, b, c, d)      = (ProdRepr (a, b, c), d)+  fromProd _ (a, b, c, d)         = (((((), a), b), c), d)+  toProd _ (((((), a), b), c), d) = (a, b, c, d)+  prod p _                        = ProdRsnoc (prod p (undefined :: (a,b,c)))++instance (cst a, cst b, cst c, cst d, cst e) => IsProduct cst (a, b, c, d, e) where+  type ProdRepr (a, b, c, d, e)        = (ProdRepr (a, b, c, d), e)+  fromProd _ (a, b, c, d, e)           = ((((((), a), b), c), d), e)+  toProd _ ((((((), a), b), c), d), e) = (a, b, c, d, e)+  prod p _                             = ProdRsnoc (prod p (undefined :: (a,b,c,d)))++instance (cst a, cst b, cst c, cst d, cst e, cst f) => IsProduct cst (a, b, c, d, e, f) where+  type ProdRepr (a, b, c, d, e, f)          = (ProdRepr (a, b, c, d, e), f)+  fromProd _ (a, b, c, d, e, f)             = (((((((), a), b), c), d), e), f)+  toProd _ (((((((), a), b), c), d), e), f) = (a, b, c, d, e, f)+  prod p _                                  = ProdRsnoc (prod p (undefined :: (a,b,c,d,e)))++instance (cst a, cst b, cst c, cst d, cst e, cst f, cst g)+  => IsProduct cst (a, b, c, d, e, f, g) where+  type ProdRepr (a, b, c, d, e, f, g)            = (ProdRepr (a, b, c, d, e, f), g)+  fromProd _ (a, b, c, d, e, f, g)               = ((((((((), a), b), c), d), e), f), g)+  toProd _ ((((((((), a), b), c), d), e), f), g) = (a, b, c, d, e, f, g)+  prod p _                                       = ProdRsnoc (prod p (undefined :: (a,b,c,d,e,f)))++instance (cst a, cst b, cst c, cst d, cst e, cst f, cst g, cst h)+  => IsProduct cst (a, b, c, d, e, f, g, h) where+  type ProdRepr (a, b, c, d, e, f, g, h)              = (ProdRepr (a, b, c, d, e, f, g), h)+  fromProd _ (a, b, c, d, e, f, g, h)                 = (((((((((), a), b), c), d), e), f), g), h)+  toProd _ (((((((((), a), b), c), d), e), f), g), h) = (a, b, c, d, e, f, g, h)+  prod p _                                            = ProdRsnoc (prod p (undefined :: (a,b,c,d,e,f,g)))++instance (cst a, cst b, cst c, cst d, cst e, cst f, cst g, cst h, cst i)+  => IsProduct cst (a, b, c, d, e, f, g, h, i) where+  type ProdRepr (a, b, c, d, e, f, g, h, i) = (ProdRepr (a, b, c, d, e, f, g, h), i)+  fromProd _ (a, b, c, d, e, f, g, h, i)+    = ((((((((((), a), b), c), d), e), f), g), h), i)+  toProd _ ((((((((((), a), b), c), d), e), f), g), h), i)+    = (a, b, c, d, e, f, g, h, i)+  prod p _+    = ProdRsnoc (prod p (undefined :: (a,b,c,d,e,f,g,h)))++instance (cst a, cst b, cst c, cst d, cst e, cst f, cst g, cst h, cst i, cst j)+  => IsProduct cst (a, b, c, d, e, f, g, h, i, j) where+  type ProdRepr (a, b, c, d, e, f, g, h, i, j) = (ProdRepr (a, b, c, d, e, f, g, h, i), j)+  fromProd _ (a, b, c, d, e, f, g, h, i, j)+    = (((((((((((), a), b), c), d), e), f), g), h), i), j)+  toProd _ (((((((((((), a), b), c), d), e), f), g), h), i), j)+    = (a, b, c, d, e, f, g, h, i, j)+  prod p _+    = ProdRsnoc (prod p (undefined :: (a,b,c,d,e,f,g,h,i)))++instance (cst a, cst b, cst c, cst d, cst e, cst f, cst g, cst h, cst i, cst j, cst k)+  => IsProduct cst (a, b, c, d, e, f, g, h, i, j, k) where+  type ProdRepr (a, b, c, d, e, f, g, h, i, j, k) = (ProdRepr (a, b, c, d, e, f, g, h, i, j), k)+  fromProd _ (a, b, c, d, e, f, g, h, i, j, k)+    = ((((((((((((), a), b), c), d), e), f), g), h), i), j), k)+  toProd _ ((((((((((((), a), b), c), d), e), f), g), h), i), j), k)+    = (a, b, c, d, e, f, g, h, i, j, k)+  prod p _+    = ProdRsnoc (prod p (undefined :: (a,b,c,d,e,f,g,h,i,j)))++instance (cst a, cst b, cst c, cst d, cst e, cst f, cst g, cst h, cst i, cst j, cst k, cst l)+  => IsProduct cst (a, b, c, d, e, f, g, h, i, j, k, l) where+  type ProdRepr (a, b, c, d, e, f, g, h, i, j, k, l) = (ProdRepr (a, b, c, d, e, f, g, h, i, j, k), l)+  fromProd _ (a, b, c, d, e, f, g, h, i, j, k, l)+    = (((((((((((((), a), b), c), d), e), f), g), h), i), j), k), l)+  toProd _ (((((((((((((), a), b), c), d), e), f), g), h), i), j), k), l)+    = (a, b, c, d, e, f, g, h, i, j, k, l)+  prod p _+    = ProdRsnoc (prod p (undefined :: (a,b,c,d,e,f,g,h,i,j,k)))++instance (cst a, cst b, cst c, cst d, cst e, cst f, cst g, cst h, cst i, cst j, cst k, cst l, cst m)+  => IsProduct cst (a, b, c, d, e, f, g, h, i, j, k, l, m) where+  type ProdRepr (a, b, c, d, e, f, g, h, i, j, k, l, m) = (ProdRepr (a, b, c, d, e, f, g, h, i, j, k, l), m)+  fromProd _ (a, b, c, d, e, f, g, h, i, j, k, l, m)+    = ((((((((((((((), a), b), c), d), e), f), g), h), i), j), k), l), m)+  toProd _ ((((((((((((((), a), b), c), d), e), f), g), h), i), j), k), l), m)+    = (a, b, c, d, e, f, g, h, i, j, k, l, m)+  prod p _+    = ProdRsnoc (prod p (undefined :: (a,b,c,d,e,f,g,h,i,j,k,l)))++instance (cst a, cst b, cst c, cst d, cst e, cst f, cst g, cst h, cst i, cst j, cst k, cst l, cst m, cst n)+  => IsProduct cst (a, b, c, d, e, f, g, h, i, j, k, l, m, n) where+  type ProdRepr (a, b, c, d, e, f, g, h, i, j, k, l, m, n) = (ProdRepr (a, b, c, d, e, f, g, h, i, j, k, l, m), n)+  fromProd _ (a, b, c, d, e, f, g, h, i, j, k, l, m, n)+    = (((((((((((((((), a), b), c), d), e), f), g), h), i), j), k), l), m), n)+  toProd _ (((((((((((((((), a), b), c), d), e), f), g), h), i), j), k), l), m), n)+    = (a, b, c, d, e, f, g, h, i, j, k, l, m, n)+  prod p _+    = ProdRsnoc (prod p (undefined :: (a,b,c,d,e,f,g,h,i,j,k,l,m)))++instance (cst a, cst b, cst c, cst d, cst e, cst f, cst g, cst h, cst i, cst j, cst k, cst l, cst m, cst n, cst o)+  => IsProduct cst (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) where+  type ProdRepr (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) = (ProdRepr (a, b, c, d, e, f, g, h, i, j, k, l, m, n), o)+  fromProd _ (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)+    = ((((((((((((((((), a), b), c), d), e), f), g), h), i), j), k), l), m), n), o)+  toProd _ ((((((((((((((((), a), b), c), d), e), f), g), h), i), j), k), l), m), n), o)+    = (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)+  prod p _+    = ProdRsnoc (prod p (undefined :: (a,b,c,d,e,f,g,h,i,j,k,l,m,n)))+
Data/Array/Accelerate/Smart.hs view
@@ -10,1110 +10,1800 @@ {-# OPTIONS_HADDOCK hide #-} -- | -- Module      : Data.Array.Accelerate.Smart--- Copyright   : [2008..2014] Manuel M T Chakravarty, Gabriele Keller---               [2008..2009] Sean Lee---               [2009..2014] Trevor L. McDonell---               [2013..2014] Robert Clifton-Everest--- License     : BSD3------ Maintainer  : Manuel M T Chakravarty <chak@cse.unsw.edu.au>--- Stability   : experimental--- Portability : non-portable (GHC extensions)------ This modules defines the AST of the user-visible embedded language using more--- convenient higher-order abstract syntax (instead of de Bruijn indices).--- Moreover, it defines smart constructors to construct programs.-----module Data.Array.Accelerate.Smart (--  -- * HOAS AST-  Acc(..), PreAcc(..), Exp(..), PreExp(..), Boundary(..), Stencil(..), Level,--  -- * Smart constructors for literals-  constant,--  -- * Smart constructors and destructors for tuples-  tup2, tup3, tup4, tup5, tup6, tup7, tup8, tup9,-  untup2, untup3, untup4, untup5, untup6, untup7, untup8, untup9,--  atup2, atup3, atup4, atup5, atup6, atup7, atup8, atup9,-  unatup2, unatup3, unatup4, unatup5, unatup6, unatup7, unatup8, unatup9,--  -- * Smart constructors for constants-  mkMinBound, mkMaxBound, mkPi,-  mkSin, mkCos, mkTan,-  mkAsin, mkAcos, mkAtan,-  mkAsinh, mkAcosh, mkAtanh,-  mkExpFloating, mkSqrt, mkLog,-  mkFPow, mkLogBase,-  mkTruncate, mkRound, mkFloor, mkCeiling,-  mkAtan2,--  -- * Smart constructors for primitive functions-  mkAdd, mkSub, mkMul, mkNeg, mkAbs, mkSig, mkQuot, mkRem, mkIDiv, mkMod,-  mkBAnd, mkBOr, mkBXor, mkBNot, mkBShiftL, mkBShiftR, mkBRotateL, mkBRotateR,-  mkFDiv, mkRecip, mkLt, mkGt, mkLtEq, mkGtEq, mkEq, mkNEq, mkMax, mkMin,-  mkLAnd, mkLOr, mkLNot,--  -- * Smart constructors for type coercion functions-  mkOrd, mkChr, mkBoolToInt, mkFromIntegral,--  -- * Auxiliary functions-  ($$), ($$$), ($$$$), ($$$$$),--  -- Debugging-  showPreAccOp, showPreExpOp,--) where---- standard library-import Prelude                                  hiding ( exp )-import Data.List-import Data.Typeable---- friends-import Data.Array.Accelerate.Type-import Data.Array.Accelerate.Array.Sugar-import Data.Array.Accelerate.Tuple              hiding ( Tuple )-import Data.Array.Accelerate.AST                hiding (-  PreOpenAcc(..), OpenAcc(..), Acc, Stencil(..), PreOpenExp(..), OpenExp, PreExp, Exp,-  showPreAccOp, showPreExpOp )-import qualified Data.Array.Accelerate.AST      as AST-import qualified Data.Array.Accelerate.Tuple    as Tuple----- Array computations--- ---------------------- The level of lambda-bound variables. The root has level 0; then it increases with each bound--- variable — i.e., it is the same as the size of the environment at the defining occurrence.----type Level = Int---- | Array-valued collective computations without a recursive knot----data PreAcc acc exp as where-    -- Needed for conversion to de Bruijn form-  Atag          :: Arrays as-                => Level                        -- environment size at defining occurrence-                -> PreAcc acc exp as--  Pipe          :: (Arrays as, Arrays bs, Arrays cs)-                => (Acc as -> acc bs)-                -> (Acc bs -> acc cs)-                -> acc as-                -> PreAcc acc exp cs--  Aforeign      :: (Arrays arrs, Arrays a, Foreign f)-                => f arrs a-                -> (Acc arrs -> Acc a)-                -> acc arrs-                -> PreAcc acc exp a--  Acond         :: Arrays as-                => exp Bool-                -> acc as-                -> acc as-                -> PreAcc acc exp as--  Awhile        :: Arrays arrs-                => (Acc arrs -> acc (Scalar Bool))-                -> (Acc arrs -> acc arrs)-                -> acc arrs-                -> PreAcc acc exp arrs--  Atuple        :: (Arrays arrs, IsTuple arrs)-                => Tuple.Atuple acc (TupleRepr arrs)-                -> PreAcc acc exp arrs--  Aprj          :: (Arrays arrs, IsTuple arrs, Arrays a)-                => TupleIdx (TupleRepr arrs) a-                ->        acc     arrs-                -> PreAcc acc exp a--  Use           :: Arrays arrs-                => arrs-                -> PreAcc acc exp arrs--  Unit          :: Elt e-                => exp e-                -> PreAcc acc exp (Scalar e)--  Generate      :: (Shape sh, Elt e)-                => exp sh-                -> (Exp sh -> exp e)-                -> PreAcc acc exp (Array sh e)--  Reshape       :: (Shape sh, Shape sh', Elt e)-                => exp sh-                -> acc (Array sh' e)-                -> PreAcc acc exp (Array sh e)--  Replicate     :: (Slice slix, Elt e,-                    Typeable (SliceShape slix), Typeable (FullShape slix))-                    -- the Typeable constraints shouldn't be necessary as they are implied by-                    -- 'SliceIx slix' — unfortunately, the (old) type checker doesn't grok that-                => exp slix-                -> acc            (Array (SliceShape slix) e)-                -> PreAcc acc exp (Array (FullShape  slix) e)--  Slice         :: (Slice slix, Elt e,-                    Typeable (SliceShape slix), Typeable (FullShape slix))-                    -- the Typeable constraints shouldn't be necessary as they are implied by-                    -- 'SliceIx slix' — unfortunately, the (old) type checker doesn't grok that-                => acc            (Array (FullShape  slix) e)-                -> exp slix-                -> PreAcc acc exp (Array (SliceShape slix) e)--  Map           :: (Shape sh, Elt e, Elt e')-                => (Exp e -> exp e')-                -> acc (Array sh e)-                -> PreAcc acc exp (Array sh e')--  ZipWith       :: (Shape sh, Elt e1, Elt e2, Elt e3)-                => (Exp e1 -> Exp e2 -> exp e3)-                -> acc (Array sh e1)-                -> acc (Array sh e2)-                -> PreAcc acc exp (Array sh e3)--  Fold          :: (Shape sh, Elt e)-                => (Exp e -> Exp e -> exp e)-                -> exp e-                -> acc (Array (sh:.Int) e)-                -> PreAcc acc exp (Array sh e)--  Fold1         :: (Shape sh, Elt e)-                => (Exp e -> Exp e -> exp e)-                -> acc (Array (sh:.Int) e)-                -> PreAcc acc exp (Array sh e)--  FoldSeg       :: (Shape sh, Elt e, Elt i, IsIntegral i)-                => (Exp e -> Exp e -> exp e)-                -> exp e-                -> acc (Array (sh:.Int) e)-                -> acc (Segments i)-                -> PreAcc acc exp (Array (sh:.Int) e)--  Fold1Seg      :: (Shape sh, Elt e, Elt i, IsIntegral i)-                => (Exp e -> Exp e -> exp e)-                -> acc (Array (sh:.Int) e)-                -> acc (Segments i)-                -> PreAcc acc exp (Array (sh:.Int) e)--  Scanl         :: Elt e-                => (Exp e -> Exp e -> exp e)-                -> exp e-                -> acc (Vector e)-                -> PreAcc acc exp (Vector e)--  Scanl'        :: Elt e-                => (Exp e -> Exp e -> exp e)-                -> exp e-                -> acc (Vector e)-                -> PreAcc acc exp (Vector e, Scalar e)--  Scanl1        :: Elt e-                => (Exp e -> Exp e -> exp e)-                -> acc (Vector e)-                -> PreAcc acc exp (Vector e)--  Scanr         :: Elt e-                => (Exp e -> Exp e -> exp e)-                -> exp e-                -> acc (Vector e)-                -> PreAcc acc exp (Vector e)--  Scanr'        :: Elt e-                => (Exp e -> Exp e -> exp e)-                -> exp e-                -> acc (Vector e)-                -> PreAcc acc exp (Vector e, Scalar e)--  Scanr1        :: Elt e-                => (Exp e -> Exp e -> exp e)-                -> acc (Vector e)-                -> PreAcc acc exp (Vector e)--  Permute       :: (Shape sh, Shape sh', Elt e)-                => (Exp e -> Exp e -> exp e)-                -> acc (Array sh' e)-                -> (Exp sh -> exp sh')-                -> acc (Array sh e)-                -> PreAcc acc exp (Array sh' e)--  Backpermute   :: (Shape sh, Shape sh', Elt e)-                => exp sh'-                -> (Exp sh' -> exp sh)-                -> acc (Array sh e)-                -> PreAcc acc exp (Array sh' e)--  Stencil       :: (Shape sh, Elt a, Elt b, Stencil sh a stencil)-                => (stencil -> exp b)-                -> Boundary a-                -> acc (Array sh a)-                -> PreAcc acc exp (Array sh b)--  Stencil2      :: (Shape sh, Elt a, Elt b, Elt c,-                   Stencil sh a stencil1, Stencil sh b stencil2)-                => (stencil1 -> stencil2 -> exp c)-                -> Boundary a-                -> acc (Array sh a)-                -> Boundary b-                -> acc (Array sh b)-                -> PreAcc acc exp (Array sh c)---- |Array-valued collective computations----newtype Acc a = Acc (PreAcc Acc Exp a)--deriving instance Typeable Acc----- Embedded expressions of the surface language--- ------------------------------------------------ HOAS expressions mirror the constructors of `AST.OpenExp', but with the `Tag' constructor instead--- of variables in the form of de Bruijn indices. Moreover, HOAS expression use n-tuples and the--- type class 'Elt' to constrain element types, whereas `AST.OpenExp' uses nested pairs and the GADT--- 'TupleType'.------- | Scalar expressions to parametrise collective array operations, themselves parameterised over--- the type of collective array operations.----data PreExp acc exp t where-    -- Needed for conversion to de Bruijn form-  Tag           :: Elt t-                => Level                        -- environment size at defining occurrence-                -> PreExp acc exp t--  -- All the same constructors as 'AST.Exp'-  Const         :: Elt t-                => t-                -> PreExp acc exp t--  Tuple         :: (Elt t, IsTuple t)-                => Tuple.Tuple exp (TupleRepr t)-                -> PreExp acc exp t--  Prj           :: (Elt t, IsTuple t, Elt e)-                => TupleIdx (TupleRepr t) e-                -> exp t-                -> PreExp acc exp e--  IndexNil      :: PreExp acc exp Z--  IndexCons     :: (Slice sl, Elt a)-                => exp sl-                -> exp a-                -> PreExp acc exp (sl:.a)--  IndexHead     :: (Slice sl, Elt a)-                => exp (sl:.a)-                -> PreExp acc exp a--  IndexTail     :: (Slice sl, Elt a)-                => exp (sl:.a)-                -> PreExp acc exp sl--  IndexAny      :: Shape sh-                => PreExp acc exp (Any sh)--  ToIndex       :: Shape sh-                => exp sh-                -> exp sh-                -> PreExp acc exp Int--  FromIndex     :: Shape sh-                => exp sh-                -> exp Int-                -> PreExp acc exp sh--  Cond          :: Elt t-                => exp Bool-                -> exp t-                -> exp t-                -> PreExp acc exp t--  While         :: Elt t-                => (Exp t -> exp Bool)-                -> (Exp t -> exp t)-                -> exp t-                -> PreExp acc exp t--  PrimConst     :: Elt t-                => PrimConst t-                -> PreExp acc exp t--  PrimApp       :: (Elt a, Elt r)-                => PrimFun (a -> r)-                -> exp a-                -> PreExp acc exp r--  Index         :: (Shape sh, Elt t)-                => acc (Array sh t)-                -> exp sh-                -> PreExp acc exp t--  LinearIndex   :: (Shape sh, Elt t)-                => acc (Array sh t)-                -> exp Int-                -> PreExp acc exp t--  Shape         :: (Shape sh, Elt e)-                => acc (Array sh e)-                -> PreExp acc exp sh--  ShapeSize     :: Shape sh-                => exp sh-                -> PreExp acc exp Int--  Intersect     :: Shape sh-                => exp sh-                -> exp sh-                -> PreExp acc exp sh--  Foreign       :: (Elt x, Elt y, Foreign f)-                => f x y-                -> (Exp x -> Exp y) -- RCE: Using Exp instead of exp to aid in sharing recovery.-                -> exp x-                -> PreExp acc exp y---- | Scalar expressions for plain array computations.----newtype Exp t = Exp (PreExp Acc Exp t)--deriving instance Typeable Exp----- Smart constructors and destructors for array tuples--- -----------------------------------------------------atup2 :: (Arrays a, Arrays b) => (Acc a, Acc b) -> Acc (a, b)-atup2 (x1, x2) = Acc $ Atuple (NilAtup `SnocAtup` x1 `SnocAtup` x2)--atup3 :: (Arrays a, Arrays b, Arrays c) => (Acc a, Acc b, Acc c) -> Acc (a, b, c)-atup3 (x1, x2, x3) = Acc $ Atuple (NilAtup `SnocAtup` x1 `SnocAtup` x2 `SnocAtup` x3)--atup4 :: (Arrays a, Arrays b, Arrays c, Arrays d)-     => (Acc a, Acc b, Acc c, Acc d) -> Acc (a, b, c, d)-atup4 (x1, x2, x3, x4)-  = Acc $ Atuple (NilAtup `SnocAtup` x1 `SnocAtup` x2 `SnocAtup` x3 `SnocAtup` x4)--atup5 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e)-     => (Acc a, Acc b, Acc c, Acc d, Acc e) -> Acc (a, b, c, d, e)-atup5 (x1, x2, x3, x4, x5)-  = Acc $ Atuple $-      NilAtup `SnocAtup` x1 `SnocAtup` x2 `SnocAtup` x3 `SnocAtup` x4 `SnocAtup` x5--atup6 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f)-     => (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f) -> Acc (a, b, c, d, e, f)-atup6 (x1, x2, x3, x4, x5, x6)-  = Acc $ Atuple $-      NilAtup `SnocAtup` x1 `SnocAtup` x2 `SnocAtup` x3-              `SnocAtup` x4 `SnocAtup` x5 `SnocAtup` x6--atup7 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g)-     => (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g)-     -> Acc (a, b, c, d, e, f, g)-atup7 (x1, x2, x3, x4, x5, x6, x7)-  = Acc $ Atuple $-      NilAtup `SnocAtup` x1 `SnocAtup` x2 `SnocAtup` x3-              `SnocAtup` x4 `SnocAtup` x5 `SnocAtup` x6 `SnocAtup` x7--atup8 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h)-     => (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h)-     -> Acc (a, b, c, d, e, f, g, h)-atup8 (x1, x2, x3, x4, x5, x6, x7, x8)-  = Acc $ Atuple $-      NilAtup `SnocAtup` x1 `SnocAtup` x2 `SnocAtup` x3 `SnocAtup` x4-              `SnocAtup` x5 `SnocAtup` x6 `SnocAtup` x7 `SnocAtup` x8--atup9 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i)-     => (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i)-     -> Acc (a, b, c, d, e, f, g, h, i)-atup9 (x1, x2, x3, x4, x5, x6, x7, x8, x9)-  = Acc $ Atuple $-      NilAtup `SnocAtup` x1 `SnocAtup` x2 `SnocAtup` x3 `SnocAtup` x4-              `SnocAtup` x5 `SnocAtup` x6 `SnocAtup` x7 `SnocAtup` x8 `SnocAtup` x9--unatup2 :: (Arrays a, Arrays b) => Acc (a, b) -> (Acc a, Acc b)-unatup2 e = (Acc $ SuccTupIdx ZeroTupIdx `Aprj` e, Acc $ ZeroTupIdx `Aprj` e)--unatup3 :: (Arrays a, Arrays b, Arrays c) => Acc (a, b, c) -> (Acc a, Acc b, Acc c)-unatup3 e =-  ( Acc $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Aprj` e-  , Acc $ SuccTupIdx ZeroTupIdx `Aprj` e-  , Acc $ ZeroTupIdx `Aprj` e )--unatup4-    :: (Arrays a, Arrays b, Arrays c, Arrays d)-    => Acc (a, b, c, d) -> (Acc a, Acc b, Acc c, Acc d)-unatup4 e =-  ( Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Aprj` e-  , Acc $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Aprj` e-  , Acc $ SuccTupIdx ZeroTupIdx `Aprj` e-  , Acc $ ZeroTupIdx `Aprj` e )--unatup5-    :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e)-    => Acc (a, b, c, d, e) -> (Acc a, Acc b, Acc c, Acc d, Acc e)-unatup5 e =-  ( Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))) `Aprj` e-  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Aprj` e-  , Acc $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Aprj` e-  , Acc $ SuccTupIdx ZeroTupIdx `Aprj` e-  , Acc $ ZeroTupIdx `Aprj` e )--unatup6-    :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f)-    => Acc (a, b, c, d, e, f) -> (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f)-unatup6 e =-  ( Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))) `Aprj` e-  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))) `Aprj` e-  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Aprj` e-  , Acc $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Aprj` e-  , Acc $ SuccTupIdx ZeroTupIdx `Aprj` e-  , Acc $ ZeroTupIdx `Aprj` e )--unatup7-    :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g)-    => Acc (a, b, c, d, e, f, g) -> (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g)-unatup7 e =-  ( Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))) `Aprj` e-  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))) `Aprj` e-  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))) `Aprj` e-  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Aprj` e-  , Acc $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Aprj` e-  , Acc $ SuccTupIdx ZeroTupIdx `Aprj` e-  , Acc $ ZeroTupIdx `Aprj` e )--unatup8-    :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h)-    => Acc (a, b, c, d, e, f, g, h) -> (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h)-unatup8 e =-  ( Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))) `Aprj` e-  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))) `Aprj` e-  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))) `Aprj` e-  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))) `Aprj` e-  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Aprj` e-  , Acc $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Aprj` e-  , Acc $ SuccTupIdx ZeroTupIdx `Aprj` e-  , Acc $ ZeroTupIdx `Aprj` e )--unatup9-    :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i)-    => Acc (a, b, c, d, e, f, g, h, i) -> (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i)-unatup9 e =-  ( Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))) `Aprj` e-  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))) `Aprj` e-  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))) `Aprj` e-  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))) `Aprj` e-  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))) `Aprj` e-  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Aprj` e-  , Acc $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Aprj` e-  , Acc $ SuccTupIdx ZeroTupIdx `Aprj` e-  , Acc $ ZeroTupIdx `Aprj` e )----- Smart constructors for stencil reification--- ---------------------------------------------- Stencil reification------ In the AST representation, we turn the stencil type from nested tuples of Accelerate expressions--- into an Accelerate expression whose type is a tuple nested in the same manner.  This enables us--- to represent the stencil function as a unary function (which also only needs one de Bruijn--- index). The various positions in the stencil are accessed via tuple indices (i.e., projections).--class (Elt (StencilRepr sh stencil), AST.Stencil sh a (StencilRepr sh stencil))-  => Stencil sh a stencil where-  type StencilRepr sh stencil :: *-  stencilPrj :: sh{-dummy-} -> a{-dummy-} -> Exp (StencilRepr sh stencil) -> stencil---- DIM1-instance Elt e => Stencil DIM1 e (Exp e, Exp e, Exp e) where-  type StencilRepr DIM1 (Exp e, Exp e, Exp e)-    = (e, e, e)-  stencilPrj _ _ s = (Exp $ Prj tix2 s,-                      Exp $ Prj tix1 s,-                      Exp $ Prj tix0 s)-instance Elt e => Stencil DIM1 e (Exp e, Exp e, Exp e, Exp e, Exp e) where-  type StencilRepr DIM1 (Exp e, Exp e, Exp e, Exp e, Exp e)-    = (e, e, e, e, e)-  stencilPrj _ _ s = (Exp $ Prj tix4 s,-                      Exp $ Prj tix3 s,-                      Exp $ Prj tix2 s,-                      Exp $ Prj tix1 s,-                      Exp $ Prj tix0 s)-instance Elt e => Stencil DIM1 e (Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e) where-  type StencilRepr DIM1 (Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e)-    = (e, e, e, e, e, e, e)-  stencilPrj _ _ s = (Exp $ Prj tix6 s,-                      Exp $ Prj tix5 s,-                      Exp $ Prj tix4 s,-                      Exp $ Prj tix3 s,-                      Exp $ Prj tix2 s,-                      Exp $ Prj tix1 s,-                      Exp $ Prj tix0 s)-instance Elt e => Stencil DIM1 e (Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e)-  where-  type StencilRepr DIM1 (Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e)-    = (e, e, e, e, e, e, e, e, e)-  stencilPrj _ _ s = (Exp $ Prj tix8 s,-                      Exp $ Prj tix7 s,-                      Exp $ Prj tix6 s,-                      Exp $ Prj tix5 s,-                      Exp $ Prj tix4 s,-                      Exp $ Prj tix3 s,-                      Exp $ Prj tix2 s,-                      Exp $ Prj tix1 s,-                      Exp $ Prj tix0 s)---- DIM(n+1)-instance (Stencil (sh:.Int) a row2,-          Stencil (sh:.Int) a row1,-          Stencil (sh:.Int) a row0) => Stencil (sh:.Int:.Int) a (row2, row1, row0) where-  type StencilRepr (sh:.Int:.Int) (row2, row1, row0)-    = (StencilRepr (sh:.Int) row2, StencilRepr (sh:.Int) row1, StencilRepr (sh:.Int) row0)-  stencilPrj _ a s = (stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix2 s),-                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix1 s),-                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix0 s))-instance (Stencil (sh:.Int) a row1,-          Stencil (sh:.Int) a row2,-          Stencil (sh:.Int) a row3,-          Stencil (sh:.Int) a row4,-          Stencil (sh:.Int) a row5) => Stencil (sh:.Int:.Int) a (row1, row2, row3, row4, row5) where-  type StencilRepr (sh:.Int:.Int) (row1, row2, row3, row4, row5)-    = (StencilRepr (sh:.Int) row1, StencilRepr (sh:.Int) row2, StencilRepr (sh:.Int) row3,-       StencilRepr (sh:.Int) row4, StencilRepr (sh:.Int) row5)-  stencilPrj _ a s = (stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix4 s),-                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix3 s),-                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix2 s),-                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix1 s),-                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix0 s))-instance (Stencil (sh:.Int) a row1,-          Stencil (sh:.Int) a row2,-          Stencil (sh:.Int) a row3,-          Stencil (sh:.Int) a row4,-          Stencil (sh:.Int) a row5,-          Stencil (sh:.Int) a row6,-          Stencil (sh:.Int) a row7)-  => Stencil (sh:.Int:.Int) a (row1, row2, row3, row4, row5, row6, row7) where-  type StencilRepr (sh:.Int:.Int) (row1, row2, row3, row4, row5, row6, row7)-    = (StencilRepr (sh:.Int) row1, StencilRepr (sh:.Int) row2, StencilRepr (sh:.Int) row3,-       StencilRepr (sh:.Int) row4, StencilRepr (sh:.Int) row5, StencilRepr (sh:.Int) row6,-       StencilRepr (sh:.Int) row7)-  stencilPrj _ a s = (stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix6 s),-                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix5 s),-                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix4 s),-                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix3 s),-                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix2 s),-                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix1 s),-                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix0 s))-instance (Stencil (sh:.Int) a row1,-          Stencil (sh:.Int) a row2,-          Stencil (sh:.Int) a row3,-          Stencil (sh:.Int) a row4,-          Stencil (sh:.Int) a row5,-          Stencil (sh:.Int) a row6,-          Stencil (sh:.Int) a row7,-          Stencil (sh:.Int) a row8,-          Stencil (sh:.Int) a row9)-  => Stencil (sh:.Int:.Int) a (row1, row2, row3, row4, row5, row6, row7, row8, row9) where-  type StencilRepr (sh:.Int:.Int) (row1, row2, row3, row4, row5, row6, row7, row8, row9)-    = (StencilRepr (sh:.Int) row1, StencilRepr (sh:.Int) row2, StencilRepr (sh:.Int) row3,-       StencilRepr (sh:.Int) row4, StencilRepr (sh:.Int) row5, StencilRepr (sh:.Int) row6,-       StencilRepr (sh:.Int) row7, StencilRepr (sh:.Int) row8, StencilRepr (sh:.Int) row9)-  stencilPrj _ a s = (stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix8 s),-                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix7 s),-                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix6 s),-                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix5 s),-                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix4 s),-                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix3 s),-                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix2 s),-                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix1 s),-                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix0 s))---- Auxiliary tuple index constants----tix0 :: Elt s => TupleIdx (t, s) s-tix0 = ZeroTupIdx-tix1 :: Elt s => TupleIdx ((t, s), s1) s-tix1 = SuccTupIdx tix0-tix2 :: Elt s => TupleIdx (((t, s), s1), s2) s-tix2 = SuccTupIdx tix1-tix3 :: Elt s => TupleIdx ((((t, s), s1), s2), s3) s-tix3 = SuccTupIdx tix2-tix4 :: Elt s => TupleIdx (((((t, s), s1), s2), s3), s4) s-tix4 = SuccTupIdx tix3-tix5 :: Elt s => TupleIdx ((((((t, s), s1), s2), s3), s4), s5) s-tix5 = SuccTupIdx tix4-tix6 :: Elt s => TupleIdx (((((((t, s), s1), s2), s3), s4), s5), s6) s-tix6 = SuccTupIdx tix5-tix7 :: Elt s => TupleIdx ((((((((t, s), s1), s2), s3), s4), s5), s6), s7) s-tix7 = SuccTupIdx tix6-tix8 :: Elt s => TupleIdx (((((((((t, s), s1), s2), s3), s4), s5), s6), s7), s8) s-tix8 = SuccTupIdx tix7----- Smart constructor for literals------- | 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-constant = Exp . Const---- Smart constructor and destructors for scalar tuples----tup2 :: (Elt a, Elt b) => (Exp a, Exp b) -> Exp (a, b)-tup2 (x1, x2) = Exp $ Tuple (NilTup `SnocTup` x1 `SnocTup` x2)--tup3 :: (Elt a, Elt b, Elt c) => (Exp a, Exp b, Exp c) -> Exp (a, b, c)-tup3 (x1, x2, x3) = Exp $ Tuple (NilTup `SnocTup` x1 `SnocTup` x2 `SnocTup` x3)--tup4 :: (Elt a, Elt b, Elt c, Elt d)-     => (Exp a, Exp b, Exp c, Exp d) -> Exp (a, b, c, d)-tup4 (x1, x2, x3, x4)-  = Exp $ Tuple (NilTup `SnocTup` x1 `SnocTup` x2 `SnocTup` x3 `SnocTup` x4)--tup5 :: (Elt a, Elt b, Elt c, Elt d, Elt e)-     => (Exp a, Exp b, Exp c, Exp d, Exp e) -> Exp (a, b, c, d, e)-tup5 (x1, x2, x3, x4, x5)-  = Exp $ Tuple $-      NilTup `SnocTup` x1 `SnocTup` x2 `SnocTup` x3 `SnocTup` x4 `SnocTup` x5--tup6 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f)-     => (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f) -> Exp (a, b, c, d, e, f)-tup6 (x1, x2, x3, x4, x5, x6)-  = Exp $ Tuple $-      NilTup `SnocTup` x1 `SnocTup` x2 `SnocTup` x3 `SnocTup` x4 `SnocTup` x5 `SnocTup` x6--tup7 :: (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)-     -> Exp (a, b, c, d, e, f, g)-tup7 (x1, x2, x3, x4, x5, x6, x7)-  = Exp $ Tuple $-      NilTup `SnocTup` x1 `SnocTup` x2 `SnocTup` x3-             `SnocTup` x4 `SnocTup` x5 `SnocTup` x6 `SnocTup` x7--tup8 :: (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)-     -> Exp (a, b, c, d, e, f, g, h)-tup8 (x1, x2, x3, x4, x5, x6, x7, x8)-  = Exp $ Tuple $-      NilTup `SnocTup` x1 `SnocTup` x2 `SnocTup` x3 `SnocTup` x4-             `SnocTup` x5 `SnocTup` x6 `SnocTup` x7 `SnocTup` x8--tup9 :: (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)-     -> Exp (a, b, c, d, e, f, g, h, i)-tup9 (x1, x2, x3, x4, x5, x6, x7, x8, x9)-  = Exp $ Tuple $-      NilTup `SnocTup` x1 `SnocTup` x2 `SnocTup` x3 `SnocTup` x4-             `SnocTup` x5 `SnocTup` x6 `SnocTup` x7 `SnocTup` x8 `SnocTup` x9--untup2 :: (Elt a, Elt b) => Exp (a, b) -> (Exp a, Exp b)-untup2 e = (Exp $ SuccTupIdx ZeroTupIdx `Prj` e, Exp $ ZeroTupIdx `Prj` e)--untup3 :: (Elt a, Elt b, Elt c) => Exp (a, b, c) -> (Exp a, Exp b, Exp c)-untup3 e = (Exp $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Prj` e,-            Exp $ SuccTupIdx ZeroTupIdx `Prj` e,-            Exp $ ZeroTupIdx `Prj` e)--untup4 :: (Elt a, Elt b, Elt c, Elt d)-       => Exp (a, b, c, d) -> (Exp a, Exp b, Exp c, Exp d)-untup4 e = (Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Prj` e,-            Exp $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Prj` e,-            Exp $ SuccTupIdx ZeroTupIdx `Prj` e,-            Exp $ ZeroTupIdx `Prj` e)--untup5 :: (Elt a, Elt b, Elt c, Elt d, Elt e)-       => Exp (a, b, c, d, e) -> (Exp a, Exp b, Exp c, Exp d, Exp e)-untup5 e = (Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))) `Prj` e,-            Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Prj` e,-            Exp $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Prj` e,-            Exp $ SuccTupIdx ZeroTupIdx `Prj` e,-            Exp $ ZeroTupIdx `Prj` e)--untup6 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f)-       => Exp (a, b, c, d, e, f) -> (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f)-untup6 e = (Exp $-              SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))) `Prj` e,-            Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))) `Prj` e,-            Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Prj` e,-            Exp $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Prj` e,-            Exp $ SuccTupIdx ZeroTupIdx `Prj` e,-            Exp $ ZeroTupIdx `Prj` e)--untup7 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g)-       => Exp (a, b, c, d, e, f, g) -> (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g)-untup7 e = (Exp $-              SuccTupIdx-                (SuccTupIdx-                  (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))) `Prj` e,-            Exp $-              SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))) `Prj` e,-            Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))) `Prj` e,-            Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Prj` e,-            Exp $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Prj` e,-            Exp $ SuccTupIdx ZeroTupIdx `Prj` e,-            Exp $ ZeroTupIdx `Prj` e)--untup8 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h)-       => Exp (a, b, c, d, e, f, g, h) -> (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h)-untup8 e = (Exp $-              SuccTupIdx-                (SuccTupIdx-                  (SuccTupIdx-                    (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))) `Prj` e,-            Exp $-              SuccTupIdx-                (SuccTupIdx-                  (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))) `Prj` e,-            Exp $-              SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))) `Prj` e,-            Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))) `Prj` e,-            Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Prj` e,-            Exp $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Prj` e,-            Exp $ SuccTupIdx ZeroTupIdx `Prj` e,-            Exp $ ZeroTupIdx `Prj` e)--untup9 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i)-       => Exp (a, b, c, d, e, f, g, h, i) -> (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i)-untup9 e = (Exp $-              SuccTupIdx-                (SuccTupIdx-                  (SuccTupIdx-                    (SuccTupIdx-                      (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))) `Prj` e,-            Exp $-              SuccTupIdx-                (SuccTupIdx-                  (SuccTupIdx-                    (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))) `Prj` e,-            Exp $-              SuccTupIdx-                (SuccTupIdx-                  (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))) `Prj` e,-            Exp $-              SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))) `Prj` e,-            Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))) `Prj` e,-            Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Prj` e,-            Exp $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Prj` e,-            Exp $ SuccTupIdx ZeroTupIdx `Prj` e,-            Exp $ ZeroTupIdx `Prj` e)---- Smart constructor for constants-----mkMinBound :: (Elt t, IsBounded t) => Exp t-mkMinBound = Exp $ PrimConst (PrimMinBound boundedType)--mkMaxBound :: (Elt t, IsBounded t) => Exp t-mkMaxBound = Exp $ PrimConst (PrimMaxBound boundedType)--mkPi :: (Elt r, IsFloating r) => Exp r-mkPi = Exp $ PrimConst (PrimPi floatingType)----- Smart constructors for primitive applications------- Operators from Floating--mkSin :: (Elt t, IsFloating t) => Exp t -> Exp t-mkSin x = Exp $ PrimSin floatingType `PrimApp` x--mkCos :: (Elt t, IsFloating t) => Exp t -> Exp t-mkCos x = Exp $ PrimCos floatingType `PrimApp` x--mkTan :: (Elt t, IsFloating t) => Exp t -> Exp t-mkTan x = Exp $ PrimTan floatingType `PrimApp` x--mkAsin :: (Elt t, IsFloating t) => Exp t -> Exp t-mkAsin x = Exp $ PrimAsin floatingType `PrimApp` x--mkAcos :: (Elt t, IsFloating t) => Exp t -> Exp t-mkAcos x = Exp $ PrimAcos floatingType `PrimApp` x--mkAtan :: (Elt t, IsFloating t) => Exp t -> Exp t-mkAtan x = Exp $ PrimAtan floatingType `PrimApp` x--mkAsinh :: (Elt t, IsFloating t) => Exp t -> Exp t-mkAsinh x = Exp $ PrimAsinh floatingType `PrimApp` x--mkAcosh :: (Elt t, IsFloating t) => Exp t -> Exp t-mkAcosh x = Exp $ PrimAcosh floatingType `PrimApp` x--mkAtanh :: (Elt t, IsFloating t) => Exp t -> Exp t-mkAtanh x = Exp $ PrimAtanh floatingType `PrimApp` x--mkExpFloating :: (Elt t, IsFloating t) => Exp t -> Exp t-mkExpFloating x = Exp $ PrimExpFloating floatingType `PrimApp` x--mkSqrt :: (Elt t, IsFloating t) => Exp t -> Exp t-mkSqrt x = Exp $ PrimSqrt floatingType `PrimApp` x--mkLog :: (Elt t, IsFloating t) => Exp t -> Exp t-mkLog x = Exp $ PrimLog floatingType `PrimApp` x--mkFPow :: (Elt t, IsFloating t) => Exp t -> Exp t -> Exp t-mkFPow x y = Exp $ PrimFPow floatingType `PrimApp` tup2 (x, y)--mkLogBase :: (Elt t, IsFloating t) => Exp t -> Exp t -> Exp t-mkLogBase x y = Exp $ PrimLogBase floatingType `PrimApp` tup2 (x, y)---- Operators from Num--mkAdd :: (Elt t, IsNum t) => Exp t -> Exp t -> Exp t-mkAdd x y = Exp $ PrimAdd numType `PrimApp` tup2 (x, y)--mkSub :: (Elt t, IsNum t) => Exp t -> Exp t -> Exp t-mkSub x y = Exp $ PrimSub numType `PrimApp` tup2 (x, y)--mkMul :: (Elt t, IsNum t) => Exp t -> Exp t -> Exp t-mkMul x y = Exp $ PrimMul numType `PrimApp` tup2 (x, y)--mkNeg :: (Elt t, IsNum t) => Exp t -> Exp t-mkNeg x = Exp $ PrimNeg numType `PrimApp` x--mkAbs :: (Elt t, IsNum t) => Exp t -> Exp t-mkAbs x = Exp $ PrimAbs numType `PrimApp` x--mkSig :: (Elt t, IsNum t) => Exp t -> Exp t-mkSig x = Exp $ PrimSig numType `PrimApp` x---- Operators from Integral & Bits--mkQuot :: (Elt t, IsIntegral t) => Exp t -> Exp t -> Exp t-mkQuot x y = Exp $ PrimQuot integralType `PrimApp` tup2 (x, y)--mkRem :: (Elt t, IsIntegral t) => Exp t -> Exp t -> Exp t-mkRem x y = Exp $ PrimRem integralType `PrimApp` tup2 (x, y)--mkIDiv :: (Elt t, IsIntegral t) => Exp t -> Exp t -> Exp t-mkIDiv x y = Exp $ PrimIDiv integralType `PrimApp` tup2 (x, y)--mkMod :: (Elt t, IsIntegral t) => Exp t -> Exp t -> Exp t-mkMod x y = Exp $ PrimMod integralType `PrimApp` tup2 (x, y)--mkBAnd :: (Elt t, IsIntegral t) => Exp t -> Exp t -> Exp t-mkBAnd x y = Exp $ PrimBAnd integralType `PrimApp` tup2 (x, y)--mkBOr :: (Elt t, IsIntegral t) => Exp t -> Exp t -> Exp t-mkBOr x y = Exp $ PrimBOr integralType `PrimApp` tup2 (x, y)--mkBXor :: (Elt t, IsIntegral t) => Exp t -> Exp t -> Exp t-mkBXor x y = Exp $ PrimBXor integralType `PrimApp` tup2 (x, y)--mkBNot :: (Elt t, IsIntegral t) => Exp t -> Exp t-mkBNot x = Exp $ PrimBNot integralType `PrimApp` x--mkBShiftL :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t-mkBShiftL x i = Exp $ PrimBShiftL integralType `PrimApp` tup2 (x, i)--mkBShiftR :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t-mkBShiftR x i = Exp $ PrimBShiftR integralType `PrimApp` tup2 (x, i)--mkBRotateL :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t-mkBRotateL x i = Exp $ PrimBRotateL integralType `PrimApp` tup2 (x, i)--mkBRotateR :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t-mkBRotateR x i = Exp $ PrimBRotateR integralType `PrimApp` tup2 (x, i)---- Operators from Fractional--mkFDiv :: (Elt t, IsFloating t) => Exp t -> Exp t -> Exp t-mkFDiv x y = Exp $ PrimFDiv floatingType `PrimApp` tup2 (x, y)--mkRecip :: (Elt t, IsFloating t) => Exp t -> Exp t-mkRecip x = Exp $ PrimRecip floatingType `PrimApp` x---- Operators from RealFrac--mkTruncate :: (Elt a, Elt b, IsFloating a, IsIntegral b) => Exp a -> Exp b-mkTruncate x = Exp $ PrimTruncate floatingType integralType `PrimApp` x--mkRound :: (Elt a, Elt b, IsFloating a, IsIntegral b) => Exp a -> Exp b-mkRound x = Exp $ PrimRound floatingType integralType `PrimApp` x--mkFloor :: (Elt a, Elt b, IsFloating a, IsIntegral b) => Exp a -> Exp b-mkFloor x = Exp $ PrimFloor floatingType integralType `PrimApp` x--mkCeiling :: (Elt a, Elt b, IsFloating a, IsIntegral b) => Exp a -> Exp b-mkCeiling x = Exp $ PrimCeiling floatingType integralType `PrimApp` x---- Operators from RealFloat--mkAtan2 :: (Elt t, IsFloating t) => Exp t -> Exp t -> Exp t-mkAtan2 x y = Exp $ PrimAtan2 floatingType `PrimApp` tup2 (x, y)---- FIXME: add missing operations from Floating, RealFrac & RealFloat---- Relational and equality operators--mkLt :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp Bool-mkLt x y = Exp $ PrimLt scalarType `PrimApp` tup2 (x, y)--mkGt :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp Bool-mkGt x y = Exp $ PrimGt scalarType `PrimApp` tup2 (x, y)--mkLtEq :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp Bool-mkLtEq x y = Exp $ PrimLtEq scalarType `PrimApp` tup2 (x, y)--mkGtEq :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp Bool-mkGtEq x y = Exp $ PrimGtEq scalarType `PrimApp` tup2 (x, y)--mkEq :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp Bool-mkEq x y = Exp $ PrimEq scalarType `PrimApp` tup2 (x, y)--mkNEq :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp Bool-mkNEq x y = Exp $ PrimNEq scalarType `PrimApp` tup2 (x, y)--mkMax :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp t-mkMax x y = Exp $ PrimMax scalarType `PrimApp` tup2 (x, y)--mkMin :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp t-mkMin x y = Exp $ PrimMin scalarType `PrimApp` tup2 (x, y)---- Logical operators--mkLAnd :: Exp Bool -> Exp Bool -> Exp Bool-mkLAnd x y = Exp $ PrimLAnd `PrimApp` tup2 (x, y)--mkLOr :: Exp Bool -> Exp Bool -> Exp Bool-mkLOr x y = Exp $ PrimLOr `PrimApp` tup2 (x, y)--mkLNot :: Exp Bool -> Exp Bool-mkLNot x = Exp $ PrimLNot `PrimApp` x---- Character conversions--mkOrd :: Exp Char -> Exp Int-mkOrd x = Exp $ PrimOrd `PrimApp` x--mkChr :: Exp Int -> Exp Char-mkChr x = Exp $ PrimChr `PrimApp` x---- Numeric conversions--mkFromIntegral :: (Elt a, Elt b, IsIntegral a, IsNum b) => Exp a -> Exp b-mkFromIntegral x = Exp $ PrimFromIntegral integralType numType `PrimApp` x---- Other conversions--mkBoolToInt :: Exp Bool -> Exp Int-mkBoolToInt b = Exp $ PrimBoolToInt `PrimApp` b----- Auxiliary functions--- ----------------------infixr 0 $$-($$) :: (b -> a) -> (c -> d -> b) -> c -> d -> a-(f $$ g) x y = f (g x y)--infixr 0 $$$-($$$) :: (b -> a) -> (c -> d -> e -> b) -> c -> d -> e -> a-(f $$$ g) x y z = f (g x y z)--infixr 0 $$$$-($$$$) :: (b -> a) -> (c -> d -> e -> f -> b) -> c -> d -> e -> f -> a-(f $$$$ g) x y z u = f (g x y z u)--infixr 0 $$$$$-($$$$$) :: (b -> a) -> (c -> d -> e -> f -> g -> b) -> c -> d -> e -> f -> g-> a-(f $$$$$ g) x y z u v = f (g x y z u v)----- Debugging--- -----------showPreAccOp :: forall acc exp arrs. PreAcc acc exp arrs -> String-showPreAccOp (Atag i)           = "Atag " ++ show i-showPreAccOp (Use a)            = "Use "  ++ showArrays a-showPreAccOp Pipe{}             = "Pipe"-showPreAccOp Acond{}            = "Acond"-showPreAccOp Awhile{}           = "Awhile"-showPreAccOp Atuple{}           = "Atuple"-showPreAccOp Aprj{}             = "Aprj"-showPreAccOp Unit{}             = "Unit"-showPreAccOp Generate{}         = "Generate"-showPreAccOp Reshape{}          = "Reshape"-showPreAccOp Replicate{}        = "Replicate"-showPreAccOp Slice{}            = "Slice"-showPreAccOp Map{}              = "Map"-showPreAccOp ZipWith{}          = "ZipWith"-showPreAccOp Fold{}             = "Fold"-showPreAccOp Fold1{}            = "Fold1"-showPreAccOp FoldSeg{}          = "FoldSeg"-showPreAccOp Fold1Seg{}         = "Fold1Seg"-showPreAccOp Scanl{}            = "Scanl"-showPreAccOp Scanl'{}           = "Scanl'"-showPreAccOp Scanl1{}           = "Scanl1"-showPreAccOp Scanr{}            = "Scanr"-showPreAccOp Scanr'{}           = "Scanr'"-showPreAccOp Scanr1{}           = "Scanr1"-showPreAccOp Permute{}          = "Permute"-showPreAccOp Backpermute{}      = "Backpermute"-showPreAccOp Stencil{}          = "Stencil"-showPreAccOp Stencil2{}         = "Stencil2"-showPreAccOp Aforeign{}         = "Aforeign"--showArrays :: forall arrs. Arrays arrs => arrs -> String-showArrays = display . collect (arrays (undefined::arrs)) . fromArr-  where-    collect :: ArraysR a -> a -> [String]-    collect ArraysRunit         _        = []-    collect ArraysRarray        arr      = [showShortendArr arr]-    collect (ArraysRpair r1 r2) (a1, a2) = collect r1 a1 ++ collect r2 a2-    ---    display []  = []-    display [x] = x-    display xs  = "(" ++ intercalate ", " xs ++ ")"---showShortendArr :: Elt e => Array sh e -> String-showShortendArr arr-  = show (take cutoff l) ++ if length l > cutoff then ".." else ""-  where-    l      = toList arr-    cutoff = 5---showPreExpOp :: PreExp acc exp t -> String-showPreExpOp (Const c)          = "Const " ++ show c-showPreExpOp (Tag i)            = "Tag" ++ show i-showPreExpOp Tuple{}            = "Tuple"-showPreExpOp Prj{}              = "Prj"-showPreExpOp IndexNil           = "IndexNil"-showPreExpOp IndexCons{}        = "IndexCons"-showPreExpOp IndexHead{}        = "IndexHead"-showPreExpOp IndexTail{}        = "IndexTail"-showPreExpOp IndexAny           = "IndexAny"-showPreExpOp ToIndex{}          = "ToIndex"-showPreExpOp FromIndex{}        = "FromIndex"-showPreExpOp Cond{}             = "Cond"-showPreExpOp While{}            = "While"-showPreExpOp PrimConst{}        = "PrimConst"-showPreExpOp PrimApp{}          = "PrimApp"-showPreExpOp Index{}            = "Index"-showPreExpOp LinearIndex{}      = "LinearIndex"-showPreExpOp Shape{}            = "Shape"-showPreExpOp ShapeSize{}        = "ShapeSize"-showPreExpOp Intersect{}        = "Intersect"+-- Copyright   : [2008..2017] Manuel M T Chakravarty, Gabriele Keller+--               [2009..2017] Trevor L. McDonell+--               [2013..2017] Robert Clifton-Everest+--               [2014..2014] Frederik M. Madsen+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- This modules defines the AST of the user-visible embedded language using more+-- convenient higher-order abstract syntax (instead of de Bruijn indices).+-- Moreover, it defines smart constructors to construct programs.+--++module Data.Array.Accelerate.Smart (++  -- * HOAS AST+  Acc(..), PreAcc(..), Exp(..), PreExp(..), Boundary(..), Stencil(..), Level,++  -- * Smart constructors for literals+  constant,++  -- * Smart constructors and destructors for tuples+  tup2, tup3, tup4, tup5, tup6, tup7, tup8, tup9, tup10, tup11, tup12, tup13, tup14, tup15,+  untup2, untup3, untup4, untup5, untup6, untup7, untup8, untup9, untup10, untup11, untup12, untup13, untup14, untup15,++  atup2, atup3, atup4, atup5, atup6, atup7, atup8, atup9, atup10, atup11, atup12, atup13, atup14, atup15,+  unatup2, unatup3, unatup4, unatup5, unatup6, unatup7, unatup8, unatup9, unatup10, unatup11, unatup12, unatup13, unatup14, unatup15,++  -- * Smart constructors for constants+  mkMinBound, mkMaxBound, mkPi,+  mkSin, mkCos, mkTan,+  mkAsin, mkAcos, mkAtan,+  mkSinh, mkCosh, mkTanh,+  mkAsinh, mkAcosh, mkAtanh,+  mkExpFloating, mkSqrt, mkLog,+  mkFPow, mkLogBase,+  mkTruncate, mkRound, mkFloor, mkCeiling,+  mkAtan2,++  -- * Smart constructors for primitive functions+  mkAdd, mkSub, mkMul, mkNeg, mkAbs, mkSig, mkQuot, mkRem, mkQuotRem, mkIDiv, mkMod, mkDivMod,+  mkBAnd, mkBOr, mkBXor, mkBNot, mkBShiftL, mkBShiftR, mkBRotateL, mkBRotateR, mkPopCount, mkCountLeadingZeros, mkCountTrailingZeros,+  mkFDiv, mkRecip, mkLt, mkGt, mkLtEq, mkGtEq, mkEq, mkNEq, mkMax, mkMin,+  mkLAnd, mkLOr, mkLNot, mkIsNaN,++  -- * Smart constructors for type coercion functions+  mkOrd, mkChr, mkBoolToInt, mkFromIntegral, mkToFloating, mkBitcast, mkUnsafeCoerce,++  -- * Auxiliary functions+  ($$), ($$$), ($$$$), ($$$$$),++  -- Debugging+  showPreAccOp, showPreExpOp,++) where++-- standard library+import Prelude                                  hiding ( exp )+import Data.List+import Data.Typeable++-- friends+import Data.Array.Accelerate.Type+import Data.Array.Accelerate.Array.Sugar+import Data.Array.Accelerate.Product+import Data.Array.Accelerate.AST                hiding ( PreOpenAcc(..), OpenAcc(..), Acc+                                                       , PreOpenExp(..), OpenExp, PreExp, Exp+                                                       , Stencil(..)+                                                       , showPreAccOp, showPreExpOp )+import qualified Data.Array.Accelerate.AST      as AST++-- Array computations+-- ------------------++-- | 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 ('Vector's) 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+-- 'Data.Array.Accelerate.Language.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:+--+--  * <http://hackage.haskell.org/package/accelerate-llvm-native accelerate-llvm-native>: for execution on multicore CPUs+--  * <http://hackage.haskell.org/package/accelerate-llvm-ptx accelerate-llvm-ptx>: for execution on NVIDIA CUDA-capable GPUs+--+-- See also 'Exp', which encapsulates embedded /scalar/ computations.+--+-- [/Fusion:/]+--+-- Array computations of type 'Acc' will be subject to /array fusion/;+-- Accelerate will combine individual 'Acc' computations into a single+-- computation, which reduces the number of traversals over the input data and+-- thus improves performance. As such, it is often useful to have some intuition+-- on when fusion should occur.+--+-- The main idea is to first partition array operations into two categories:+--+--   1. Element-wise operations, such as 'Data.Array.Accelerate.map',+--      'Data.Array.Accelerate.generate', and+--      'Data.Array.Accelerate.backpermute'. Each element of these operations+--      can be computed independently of all others.+--+--   2. Collective operations such as 'Data.Array.Accelerate.fold',+--      'Data.Array.Accelerate.scanl', and 'Data.Array.Accelerate.stencil'. To+--      compute each output element of these operations requires reading+--      multiple elements from the input array(s).+--+-- Element-wise operations fuse together whenever the consumer operation uses+-- a single element of the input array. Element-wise operations can both fuse+-- their inputs into themselves, as well be fused into later operations. Both+-- these examples should fuse into a single loop:+--+-- > 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 'Data.Array.Accelerate.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 ('Data.Array.Accelerate.use'+-- + 'Data.Array.Accelerate.generate' + 'Data.Array.Accelerate.zipWith') will+-- fuse into a single operation, which then fuses into the collective+-- 'Data.Array.Accelerate.fold' operation. At this point in the program the+-- 'Data.Array.Accelerate.fold' must now be evaluated. In the final step the+-- 'Data.Array.Accelerate.map' reads in the array produced by+-- 'Data.Array.Accelerate.fold'. As there is no fusion between the+-- 'Data.Array.Accelerate.fold' and 'Data.Array.Accelerate.map' steps, this+-- program consists of two "loops"; one for the 'Data.Array.Accelerate.use'+-- + 'Data.Array.Accelerate.generate' + 'Data.Array.Accelerate.zipWith'+-- + 'Data.Array.Accelerate.fold' step, and one for the final+-- 'Data.Array.Accelerate.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 'Data.Array.Accelerate.unzip' and+-- 'Data.Array.Accelerate.reshape', when applied to a real array, are executed+-- in constant time, so in this situation these operations will not be fused.+--+-- [/Tips:/]+--+--  * Since 'Acc' represents embedded computations that will only be executed+--    when evaluated by a backend, we can programatically generate these+--    computations using the meta language Haskell; for example, unrolling loops+--    or embedding input values into the generated code.+--+--  * It is usually best to keep all intermediate computations in 'Acc', and+--    only 'run' the computation at the very end to produce the final result.+--    This enables optimisations between intermediate results (e.g. array+--    fusion) and, if the target architecture has a separate memory space as is+--    the case of GPUs, to prevent excessive data transfers.+--+newtype Acc a = Acc (PreAcc Acc Exp a)+deriving instance Typeable Acc+++-- The level of lambda-bound variables. The root has level 0; then it increases with each bound+-- variable — i.e., it is the same as the size of the environment at the defining occurrence.+--+type Level = Int++-- | Array-valued collective computations without a recursive knot+--+data PreAcc acc exp as where+    -- Needed for conversion to de Bruijn form+  Atag          :: Arrays as+                => Level                        -- environment size at defining occurrence+                -> PreAcc acc exp as++  Pipe          :: (Arrays as, Arrays bs, Arrays cs)+                => (Acc as -> acc bs)+                -> (Acc bs -> acc cs)+                -> acc as+                -> PreAcc acc exp cs++  Aforeign      :: (Arrays as, Arrays bs, Foreign asm)+                => asm (as -> bs)+                -> (Acc as -> Acc bs)+                -> acc as+                -> PreAcc acc exp bs++  Acond         :: Arrays as+                => exp Bool+                -> acc as+                -> acc as+                -> PreAcc acc exp as++  Awhile        :: Arrays arrs+                => (Acc arrs -> acc (Scalar Bool))+                -> (Acc arrs -> acc arrs)+                -> acc arrs+                -> PreAcc acc exp arrs++  Atuple        :: (Arrays arrs, IsAtuple arrs)+                => Atuple acc (TupleRepr arrs)+                -> PreAcc acc exp arrs++  Aprj          :: (Arrays arrs, IsAtuple arrs, Arrays a)+                => TupleIdx (TupleRepr arrs) a+                ->        acc     arrs+                -> PreAcc acc exp a++  Use           :: Arrays arrs+                => arrs+                -> PreAcc acc exp arrs++  Unit          :: Elt e+                => exp e+                -> PreAcc acc exp (Scalar e)++  Generate      :: (Shape sh, Elt e)+                => exp sh+                -> (Exp sh -> exp e)+                -> PreAcc acc exp (Array sh e)++  Reshape       :: (Shape sh, Shape sh', Elt e)+                => exp sh+                -> acc (Array sh' e)+                -> PreAcc acc exp (Array sh e)++  Replicate     :: (Slice slix, Elt e)+                => exp slix+                -> acc            (Array (SliceShape slix) e)+                -> PreAcc acc exp (Array (FullShape  slix) e)++  Slice         :: (Slice slix, Elt e)+                => acc            (Array (FullShape  slix) e)+                -> exp slix+                -> PreAcc acc exp (Array (SliceShape slix) e)++  Map           :: (Shape sh, Elt e, Elt e')+                => (Exp e -> exp e')+                -> acc (Array sh e)+                -> PreAcc acc exp (Array sh e')++  ZipWith       :: (Shape sh, Elt e1, Elt e2, Elt e3)+                => (Exp e1 -> Exp e2 -> exp e3)+                -> acc (Array sh e1)+                -> acc (Array sh e2)+                -> PreAcc acc exp (Array sh e3)++  Fold          :: (Shape sh, Elt e)+                => (Exp e -> Exp e -> exp e)+                -> exp e+                -> acc (Array (sh:.Int) e)+                -> PreAcc acc exp (Array sh e)++  Fold1         :: (Shape sh, Elt e)+                => (Exp e -> Exp e -> exp e)+                -> acc (Array (sh:.Int) e)+                -> PreAcc acc exp (Array sh e)++  FoldSeg       :: (Shape sh, Elt e, Elt i, IsIntegral i)+                => (Exp e -> Exp e -> exp e)+                -> exp e+                -> acc (Array (sh:.Int) e)+                -> acc (Segments i)+                -> PreAcc acc exp (Array (sh:.Int) e)++  Fold1Seg      :: (Shape sh, Elt e, Elt i, IsIntegral i)+                => (Exp e -> Exp e -> exp e)+                -> acc (Array (sh:.Int) e)+                -> acc (Segments i)+                -> PreAcc acc exp (Array (sh:.Int) e)++  Scanl         :: (Shape sh, Elt e)+                => (Exp e -> Exp e -> exp e)+                -> exp e+                -> acc (Array (sh :. Int) e)+                -> PreAcc acc exp (Array (sh :. Int) e)++  Scanl'        :: (Shape sh, Elt e)+                => (Exp e -> Exp e -> exp e)+                -> exp e+                -> acc (Array (sh :. Int) e)+                -> PreAcc acc exp (Array (sh :. Int) e, Array sh e)++  Scanl1        :: (Shape sh, Elt e)+                => (Exp e -> Exp e -> exp e)+                -> acc (Array (sh :. Int) e)+                -> PreAcc acc exp (Array (sh :. Int) e)++  Scanr         :: (Shape sh, Elt e)+                => (Exp e -> Exp e -> exp e)+                -> exp e+                -> acc (Array (sh :. Int) e)+                -> PreAcc acc exp (Array (sh :. Int) e)++  Scanr'        :: (Shape sh, Elt e)+                => (Exp e -> Exp e -> exp e)+                -> exp e+                -> acc (Array (sh :. Int) e)+                -> PreAcc acc exp (Array (sh :. Int) e, Array sh e)++  Scanr1        :: (Shape sh, Elt e)+                => (Exp e -> Exp e -> exp e)+                -> acc (Array (sh :. Int) e)+                -> PreAcc acc exp (Array (sh :. Int) e)++  Permute       :: (Shape sh, Shape sh', Elt e)+                => (Exp e -> Exp e -> exp e)+                -> acc (Array sh' e)+                -> (Exp sh -> exp sh')+                -> acc (Array sh e)+                -> PreAcc acc exp (Array sh' e)++  Backpermute   :: (Shape sh, Shape sh', Elt e)+                => exp sh'+                -> (Exp sh' -> exp sh)+                -> acc (Array sh e)+                -> PreAcc acc exp (Array sh' e)++  Stencil       :: (Shape sh, Elt a, Elt b, Stencil sh a stencil)+                => (stencil -> exp b)+                -> Boundary a+                -> acc (Array sh a)+                -> PreAcc acc exp (Array sh b)++  Stencil2      :: (Shape sh, Elt a, Elt b, Elt c,+                   Stencil sh a stencil1, Stencil sh b stencil2)+                => (stencil1 -> stencil2 -> exp c)+                -> Boundary a+                -> acc (Array sh a)+                -> Boundary b+                -> acc (Array sh b)+                -> PreAcc acc exp (Array sh c)++  -- Collect       :: Arrays arrs+  --               => seq arrs+  --               -> PreAcc acc seq exp arrs+++{--+data PreSeq acc seq exp arrs where+  -- Convert the given Haskell-list of arrays to a sequence.+  StreamIn :: Arrays a+           => [a]+           -> PreSeq acc seq exp [a]++  -- Convert the given array to a sequence.+  -- Example:+  -- slix = Z :. All :. Split :. All :. All :. Split+  --              ^       ^       ^      ^      ^+  --              |        \     /      /       |+  --              |         \___/______/_______ Iteration space.+  --              |            /      /+  --           Element________/______/+  --            shape.+  --+  ToSeq :: ( Elt e+           , Slice slix+           , Division slsix+           , DivisionSlice slsix ~ slix+           , Typeable (FullShape slix)+           , Typeable (SliceShape slix)+           )+        => slsix+        -> acc (Array (FullShape slix) e)+        -> PreSeq acc seq exp [Array (SliceShape slix) e]++  -- Apply the given the given function to all elements of the given sequence.+  MapSeq :: (Arrays a, Arrays b)+         => (Acc a -> acc b)+         -> seq [a]+         -> PreSeq acc seq exp [b]++  -- Apply a given binary function pairwise to all elements of the given sequences.+  -- The length of the result is the length of the shorter of the two argument+  -- arrays.+  ZipWithSeq :: (Arrays a, Arrays b, Arrays c)+             => (Acc a -> Acc b -> acc c)+             -> seq [a]+             -> seq [b]+             -> PreSeq acc seq exp [c]++  -- ScanSeq (+) a0 x. Scan a sequence x by combining each element+  -- using the given binary operation (+). (+) must be associative:+  --+  --   Forall a b c. (a + b) + c = a + (b + c),+  --+  -- and a0 must be the identity element for (+):+  --+  --   Forall a. a0 + a = a = a + a0.+  --+  ScanSeq :: Elt a+          => (Exp a -> Exp a -> exp a)+          -> exp a+          -> seq [Scalar a]+          -> PreSeq acc seq exp [Scalar a]++  -- FoldSeq (+) a0 x. Fold a sequence x by combining each element+  -- using the given binary operation (+). (+) must be associative:+  --+  --   Forall a b c. (a + b) + c = a + (b + c),+  --+  -- and a0 must be the identity element for (+):+  --+  --   Forall a. a0 + a = a = a + a0.+  --+  FoldSeq :: Elt a+          => (Exp a -> Exp a -> exp a)+          -> exp a+          -> seq [Scalar a]+          -> PreSeq acc seq exp (Scalar a)++  -- FoldSeqFlatten f a0 x. A specialized version of FoldSeqAct+  -- where reduction with the companion operator corresponds to+  -- flattening. f must be semi-associative, with vecotor append (++)+  -- as the companion operator:+  --+  --   Forall b s1 a2 sh2 a2.+  --     f (f b sh1 a1) sh2 a2 = f b (sh1 ++ sh2) (a1 ++ a2).+  --+  -- It is common to ignore the shape vectors, yielding the usual+  -- semi-associativity law:+  --+  --   f b a _ = b + a,+  --+  -- for some (+) satisfying:+  --+  --   Forall b a1 a2. (b + a1) + a2 = b + (a1 ++ a2).+  --+  FoldSeqFlatten :: (Arrays a, Shape sh, Elt e)+                 => (Acc a -> Acc (Vector sh) -> Acc (Vector e) -> acc a)+                 -> acc a+                 -> seq [Array sh e]+                 -> PreSeq acc seq exp a++  -- Tuple up the results of a sequence computation. Note that the Arrays+  -- constraint requires that the elements of the tuple are Arrays, not+  -- streams ([]).+  Stuple :: (Arrays arrs, IsAtuple arrs)+         => Atuple (seq) (TupleRepr arrs)+         -> PreSeq acc seq exp arrs++-- |Array-valued sequence computations+--+newtype Seq a = Seq (PreSeq Acc Seq Exp a)++deriving instance Typeable Seq+--}+++-- Embedded expressions of the surface language+-- --------------------------------------------++-- HOAS expressions mirror the constructors of 'AST.OpenExp', but with the 'Tag'+-- constructor instead of variables in the form of de Bruijn indices. Moreover,+-- HOAS expression use n-tuples and the type class 'Elt' to constrain element+-- types, whereas 'AST.OpenExp' uses nested pairs and the GADT 'TupleType'.+--++-- | 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.+--+newtype Exp t = Exp (PreExp Acc Exp t)++deriving instance Typeable Exp++-- | Scalar expressions to parametrise collective array operations, themselves parameterised over+-- the type of collective array operations.+--+data PreExp acc exp t where+    -- Needed for conversion to de Bruijn form+  Tag           :: Elt t+                => Level                        -- environment size at defining occurrence+                -> PreExp acc exp t++  -- All the same constructors as 'AST.Exp'+  Const         :: Elt t+                => t+                -> PreExp acc exp t++  Tuple         :: (Elt t, IsTuple t)+                => Tuple exp (TupleRepr t)+                -> PreExp acc exp t++  Prj           :: (Elt t, IsTuple t, Elt e)+                => TupleIdx (TupleRepr t) e+                -> exp t+                -> PreExp acc exp e++  IndexNil      :: PreExp acc exp Z++  IndexCons     :: (Slice sl, Elt a)+                => exp sl+                -> exp a+                -> PreExp acc exp (sl:.a)++  IndexHead     :: (Slice sl, Elt a)+                => exp (sl:.a)+                -> PreExp acc exp a++  IndexTail     :: (Slice sl, Elt a)+                => exp (sl:.a)+                -> PreExp acc exp sl++  IndexAny      :: Shape sh+                => PreExp acc exp (Any sh)++  ToIndex       :: Shape sh+                => exp sh+                -> exp sh+                -> PreExp acc exp Int++  FromIndex     :: Shape sh+                => exp sh+                -> exp Int+                -> PreExp acc exp sh++  Cond          :: Elt t+                => exp Bool+                -> exp t+                -> exp t+                -> PreExp acc exp t++  While         :: Elt t+                => (Exp t -> exp Bool)+                -> (Exp t -> exp t)+                -> exp t+                -> PreExp acc exp t++  PrimConst     :: Elt t+                => PrimConst t+                -> PreExp acc exp t++  PrimApp       :: (Elt a, Elt r)+                => PrimFun (a -> r)+                -> exp a+                -> PreExp acc exp r++  Index         :: (Shape sh, Elt t)+                => acc (Array sh t)+                -> exp sh+                -> PreExp acc exp t++  LinearIndex   :: (Shape sh, Elt t)+                => acc (Array sh t)+                -> exp Int+                -> PreExp acc exp t++  Shape         :: (Shape sh, Elt e)+                => acc (Array sh e)+                -> PreExp acc exp sh++  ShapeSize     :: Shape sh+                => exp sh+                -> PreExp acc exp Int++  Intersect     :: Shape sh+                => exp sh+                -> exp sh+                -> PreExp acc exp sh++  Union         :: Shape sh+                => exp sh+                -> exp sh+                -> PreExp acc exp sh++  Foreign       :: (Elt x, Elt y, Foreign asm)+                => asm (x -> y)+                -> (Exp x -> Exp y) -- RCE: Using Exp instead of exp to aid in sharing recovery.+                -> exp x+                -> PreExp acc exp y+++-- Smart constructors and destructors for array tuples+-- ---------------------------------------------------++atup2 :: (Arrays a, Arrays b) => (Acc a, Acc b) -> Acc (a, b)+atup2 (a, b) = Acc $ Atuple (NilAtup `SnocAtup` a `SnocAtup` b)++atup3 :: (Arrays a, Arrays b, Arrays c) => (Acc a, Acc b, Acc c) -> Acc (a, b, c)+atup3 (a, b, c) = Acc $ Atuple (NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c)++atup4 :: (Arrays a, Arrays b, Arrays c, Arrays d)+      => (Acc a, Acc b, Acc c, Acc d) -> Acc (a, b, c, d)+atup4 (a, b, c, d)+  = Acc $ Atuple (NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c `SnocAtup` d)++atup5 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e)+      => (Acc a, Acc b, Acc c, Acc d, Acc e) -> Acc (a, b, c, d, e)+atup5 (a, b, c, d, e)+  = Acc $ Atuple $+      NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c `SnocAtup` d `SnocAtup` e++atup6 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f)+      => (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f) -> Acc (a, b, c, d, e, f)+atup6 (a, b, c, d, e, f)+  = Acc $ Atuple $+      NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c+              `SnocAtup` d `SnocAtup` e `SnocAtup` f++atup7 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g)+      => (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g)+      -> Acc (a, b, c, d, e, f, g)+atup7 (a, b, c, d, e, f, g)+  = Acc $ Atuple $+      NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c+              `SnocAtup` d `SnocAtup` e `SnocAtup` f `SnocAtup` g++atup8 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h)+      => (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h)+      -> Acc (a, b, c, d, e, f, g, h)+atup8 (a, b, c, d, e, f, g, h)+  = Acc $ Atuple $+      NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c `SnocAtup` d+              `SnocAtup` e `SnocAtup` f `SnocAtup` g `SnocAtup` h++atup9 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i)+      => (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i)+      -> Acc (a, b, c, d, e, f, g, h, i)+atup9 (a, b, c, d, e, f, g, h, i)+  = Acc $ Atuple $+      NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c `SnocAtup` d+              `SnocAtup` e `SnocAtup` f `SnocAtup` g `SnocAtup` h `SnocAtup` i++atup10 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j)+       => (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j)+       -> Acc (a, b, c, d, e, f, g, h, i, j)+atup10 (a, b, c, d, e, f, g, h, i, j)+  = Acc $ Atuple $+      NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c `SnocAtup` d `SnocAtup` e+              `SnocAtup` f `SnocAtup` g `SnocAtup` h `SnocAtup` i `SnocAtup` j++atup11 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k)+       => (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j, Acc k)+       -> Acc (a, b, c, d, e, f, g, h, i, j, k)+atup11 (a, b, c, d, e, f, g, h, i, j, k)+  = Acc $ Atuple $+      NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c `SnocAtup` d `SnocAtup` e+              `SnocAtup` f `SnocAtup` g `SnocAtup` h `SnocAtup` i `SnocAtup` j `SnocAtup` k++atup12 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l)+       => (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j, Acc k, Acc l)+       -> Acc (a, b, c, d, e, f, g, h, i, j, k, l)+atup12 (a, b, c, d, e, f, g, h, i, j, k, l)+  = Acc $ Atuple $+      NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c `SnocAtup` d `SnocAtup` e `SnocAtup` f+              `SnocAtup` g `SnocAtup` h `SnocAtup` i `SnocAtup` j `SnocAtup` k `SnocAtup` l++atup13 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l, Arrays m)+       => (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j, Acc k, Acc l, Acc m)+       -> Acc (a, b, c, d, e, f, g, h, i, j, k, l, m)+atup13 (a, b, c, d, e, f, g, h, i, j, k, l, m)+  = Acc $ Atuple $+      NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c `SnocAtup` d `SnocAtup` e `SnocAtup` f+              `SnocAtup` g `SnocAtup` h `SnocAtup` i `SnocAtup` j `SnocAtup` k `SnocAtup` l `SnocAtup` m++atup14 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l, Arrays m, Arrays n)+       => (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j, Acc k, Acc l, Acc m, Acc n)+       -> Acc (a, b, c, d, e, f, g, h, i, j, k, l, m, n)+atup14 (a, b, c, d, e, f, g, h, i, j, k, l, m, n)+  = Acc $ Atuple $+      NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c `SnocAtup` d `SnocAtup` e `SnocAtup` f `SnocAtup` g+              `SnocAtup` h `SnocAtup` i `SnocAtup` j `SnocAtup` k `SnocAtup` l `SnocAtup` m `SnocAtup` n++atup15 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l, Arrays m, Arrays n, Arrays o)+       => (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j, Acc k, Acc l, Acc m, Acc n, Acc o)+       -> Acc (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)+atup15 (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)+  = Acc $ Atuple $+      NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c `SnocAtup` d `SnocAtup` e `SnocAtup` f `SnocAtup` g+              `SnocAtup` h `SnocAtup` i `SnocAtup` j `SnocAtup` k `SnocAtup` l `SnocAtup` m `SnocAtup` n `SnocAtup` o++unatup2 :: (Arrays a, Arrays b) => Acc (a, b) -> (Acc a, Acc b)+unatup2 e =+  ( Acc $ SuccTupIdx ZeroTupIdx `Aprj` e+  , Acc $ ZeroTupIdx `Aprj` e )++unatup3 :: (Arrays a, Arrays b, Arrays c) => Acc (a, b, c) -> (Acc a, Acc b, Acc c)+unatup3 e =+  ( Acc $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Aprj` e+  , Acc $ SuccTupIdx ZeroTupIdx `Aprj` e+  , Acc $ ZeroTupIdx `Aprj` e )++unatup4+    :: (Arrays a, Arrays b, Arrays c, Arrays d)+    => Acc (a, b, c, d) -> (Acc a, Acc b, Acc c, Acc d)+unatup4 e =+  ( Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Aprj` e+  , Acc $ SuccTupIdx ZeroTupIdx `Aprj` e+  , Acc $ ZeroTupIdx `Aprj` e )++unatup5+    :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e)+    => Acc (a, b, c, d, e) -> (Acc a, Acc b, Acc c, Acc d, Acc e)+unatup5 e =+  ( Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Aprj` e+  , Acc $ SuccTupIdx ZeroTupIdx `Aprj` e+  , Acc $ ZeroTupIdx `Aprj` e )++unatup6+    :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f)+    => Acc (a, b, c, d, e, f) -> (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f)+unatup6 e =+  ( Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Aprj` e+  , Acc $ SuccTupIdx ZeroTupIdx `Aprj` e+  , Acc $ ZeroTupIdx `Aprj` e )++unatup7+    :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g)+    => Acc (a, b, c, d, e, f, g) -> (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g)+unatup7 e =+  ( Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Aprj` e+  , Acc $ SuccTupIdx ZeroTupIdx `Aprj` e+  , Acc $ ZeroTupIdx `Aprj` e )++unatup8+    :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h)+    => Acc (a, b, c, d, e, f, g, h) -> (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h)+unatup8 e =+  ( Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Aprj` e+  , Acc $ SuccTupIdx ZeroTupIdx `Aprj` e+  , Acc $ ZeroTupIdx `Aprj` e )++unatup9+    :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i)+    => Acc (a, b, c, d, e, f, g, h, i) -> (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i)+unatup9 e =+  ( Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Aprj` e+  , Acc $ SuccTupIdx ZeroTupIdx `Aprj` e+  , Acc $ ZeroTupIdx `Aprj` e )++unatup10 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j)+         => Acc (a, b, c, d, e, f, g, h, i, j) -> (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j)+unatup10 e =+  ( Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Aprj` e+  , Acc $ SuccTupIdx ZeroTupIdx `Aprj` e+  , Acc $ ZeroTupIdx `Aprj` e)++unatup11 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k)+         => Acc (a, b, c, d, e, f, g, h, i, j, k) -> (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j, Acc k)+unatup11 e =+  ( Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Aprj` e+  , Acc $ SuccTupIdx ZeroTupIdx `Aprj` e+  , Acc $ ZeroTupIdx `Aprj` e)++unatup12 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l)+         => Acc (a, b, c, d, e, f, g, h, i, j, k, l) -> (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j, Acc k, Acc l)+unatup12 e =+  ( Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Aprj` e+  , Acc $ SuccTupIdx ZeroTupIdx `Aprj` e+  , Acc $ ZeroTupIdx `Aprj` e)++unatup13 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l, Arrays m)+         => Acc (a, b, c, d, e, f, g, h, i, j, k, l, m) -> (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j, Acc k, Acc l, Acc m)+unatup13 e =+  ( Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Aprj` e+  , Acc $ SuccTupIdx ZeroTupIdx `Aprj` e+  , Acc $ ZeroTupIdx `Aprj` e)++unatup14 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l, Arrays m, Arrays n)+         => Acc (a, b, c, d, e, f, g, h, i, j, k, l, m, n) -> (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j, Acc k, Acc l, Acc m, Acc n)+unatup14 e =+  ( Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))))))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Aprj` e+  , Acc $ SuccTupIdx ZeroTupIdx `Aprj` e+  , Acc $ ZeroTupIdx `Aprj` e)++unatup15 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l, Arrays m, Arrays n, Arrays o)+         => Acc (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) -> (Acc a, Acc b, Acc c, Acc d, Acc e, Acc f, Acc g, Acc h, Acc i, Acc j, Acc k, Acc l, Acc m, Acc n, Acc o)+unatup15 e =+  ( Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))))))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))))))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Aprj` e+  , Acc $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Aprj` e+  , Acc $ SuccTupIdx ZeroTupIdx `Aprj` e+  , Acc $ ZeroTupIdx `Aprj` e)++++-- Smart constructors for stencil reification+-- ------------------------------------------++-- Stencil reification+--+-- In the AST representation, we turn the stencil type from nested tuples of Accelerate expressions+-- into an Accelerate expression whose type is a tuple nested in the same manner.  This enables us+-- to represent the stencil function as a unary function (which also only needs one de Bruijn+-- index). The various positions in the stencil are accessed via tuple indices (i.e., projections).++class (Elt (StencilRepr sh stencil), AST.Stencil sh a (StencilRepr sh stencil))+  => Stencil sh a stencil where+  type StencilRepr sh stencil :: *+  stencilPrj :: sh{-dummy-} -> a{-dummy-} -> Exp (StencilRepr sh stencil) -> stencil++-- DIM1+instance Elt e => Stencil DIM1 e (Exp e, Exp e, Exp e) where+  type StencilRepr DIM1 (Exp e, Exp e, Exp e)+    = (e, e, e)+  stencilPrj _ _ s = (Exp $ Prj tix2 s,+                      Exp $ Prj tix1 s,+                      Exp $ Prj tix0 s)+instance Elt e => Stencil DIM1 e (Exp e, Exp e, Exp e, Exp e, Exp e) where+  type StencilRepr DIM1 (Exp e, Exp e, Exp e, Exp e, Exp e)+    = (e, e, e, e, e)+  stencilPrj _ _ s = (Exp $ Prj tix4 s,+                      Exp $ Prj tix3 s,+                      Exp $ Prj tix2 s,+                      Exp $ Prj tix1 s,+                      Exp $ Prj tix0 s)+instance Elt e => Stencil DIM1 e (Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e) where+  type StencilRepr DIM1 (Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e)+    = (e, e, e, e, e, e, e)+  stencilPrj _ _ s = (Exp $ Prj tix6 s,+                      Exp $ Prj tix5 s,+                      Exp $ Prj tix4 s,+                      Exp $ Prj tix3 s,+                      Exp $ Prj tix2 s,+                      Exp $ Prj tix1 s,+                      Exp $ Prj tix0 s)+instance Elt e => Stencil DIM1 e (Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e)+  where+  type StencilRepr DIM1 (Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e, Exp e)+    = (e, e, e, e, e, e, e, e, e)+  stencilPrj _ _ s = (Exp $ Prj tix8 s,+                      Exp $ Prj tix7 s,+                      Exp $ Prj tix6 s,+                      Exp $ Prj tix5 s,+                      Exp $ Prj tix4 s,+                      Exp $ Prj tix3 s,+                      Exp $ Prj tix2 s,+                      Exp $ Prj tix1 s,+                      Exp $ Prj tix0 s)++-- DIM(n+1)+instance (Stencil (sh:.Int) a row2,+          Stencil (sh:.Int) a row1,+          Stencil (sh:.Int) a row0) => Stencil (sh:.Int:.Int) a (row2, row1, row0) where+  type StencilRepr (sh:.Int:.Int) (row2, row1, row0)+    = (StencilRepr (sh:.Int) row2, StencilRepr (sh:.Int) row1, StencilRepr (sh:.Int) row0)+  stencilPrj _ a s = (stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix2 s),+                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix1 s),+                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix0 s))+instance (Stencil (sh:.Int) a row1,+          Stencil (sh:.Int) a row2,+          Stencil (sh:.Int) a row3,+          Stencil (sh:.Int) a row4,+          Stencil (sh:.Int) a row5) => Stencil (sh:.Int:.Int) a (row1, row2, row3, row4, row5) where+  type StencilRepr (sh:.Int:.Int) (row1, row2, row3, row4, row5)+    = (StencilRepr (sh:.Int) row1, StencilRepr (sh:.Int) row2, StencilRepr (sh:.Int) row3,+       StencilRepr (sh:.Int) row4, StencilRepr (sh:.Int) row5)+  stencilPrj _ a s = (stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix4 s),+                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix3 s),+                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix2 s),+                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix1 s),+                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix0 s))+instance (Stencil (sh:.Int) a row1,+          Stencil (sh:.Int) a row2,+          Stencil (sh:.Int) a row3,+          Stencil (sh:.Int) a row4,+          Stencil (sh:.Int) a row5,+          Stencil (sh:.Int) a row6,+          Stencil (sh:.Int) a row7)+  => Stencil (sh:.Int:.Int) a (row1, row2, row3, row4, row5, row6, row7) where+  type StencilRepr (sh:.Int:.Int) (row1, row2, row3, row4, row5, row6, row7)+    = (StencilRepr (sh:.Int) row1, StencilRepr (sh:.Int) row2, StencilRepr (sh:.Int) row3,+       StencilRepr (sh:.Int) row4, StencilRepr (sh:.Int) row5, StencilRepr (sh:.Int) row6,+       StencilRepr (sh:.Int) row7)+  stencilPrj _ a s = (stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix6 s),+                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix5 s),+                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix4 s),+                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix3 s),+                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix2 s),+                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix1 s),+                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix0 s))+instance (Stencil (sh:.Int) a row1,+          Stencil (sh:.Int) a row2,+          Stencil (sh:.Int) a row3,+          Stencil (sh:.Int) a row4,+          Stencil (sh:.Int) a row5,+          Stencil (sh:.Int) a row6,+          Stencil (sh:.Int) a row7,+          Stencil (sh:.Int) a row8,+          Stencil (sh:.Int) a row9)+  => Stencil (sh:.Int:.Int) a (row1, row2, row3, row4, row5, row6, row7, row8, row9) where+  type StencilRepr (sh:.Int:.Int) (row1, row2, row3, row4, row5, row6, row7, row8, row9)+    = (StencilRepr (sh:.Int) row1, StencilRepr (sh:.Int) row2, StencilRepr (sh:.Int) row3,+       StencilRepr (sh:.Int) row4, StencilRepr (sh:.Int) row5, StencilRepr (sh:.Int) row6,+       StencilRepr (sh:.Int) row7, StencilRepr (sh:.Int) row8, StencilRepr (sh:.Int) row9)+  stencilPrj _ a s = (stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix8 s),+                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix7 s),+                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix6 s),+                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix5 s),+                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix4 s),+                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix3 s),+                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix2 s),+                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix1 s),+                      stencilPrj (undefined::(sh:.Int)) a (Exp $ Prj tix0 s))++-- Auxiliary tuple index constants+--+tix0 :: TupleIdx (t, s0) s0+tix0 = ZeroTupIdx++tix1 :: TupleIdx ((t, s1), s0) s1+tix1 = SuccTupIdx tix0++tix2 :: TupleIdx (((t, s2), s1), s0) s2+tix2 = SuccTupIdx tix1++tix3 :: TupleIdx ((((t, s3), s2), s1), s0) s3+tix3 = SuccTupIdx tix2++tix4 :: TupleIdx (((((t, s4), s3), s2), s1), s0) s4+tix4 = SuccTupIdx tix3++tix5 :: TupleIdx ((((((t, s5), s4), s3), s2), s1), s0) s5+tix5 = SuccTupIdx tix4++tix6 :: TupleIdx (((((((t, s6), s5), s4), s3), s2), s1), s0) s6+tix6 = SuccTupIdx tix5++tix7 :: TupleIdx ((((((((t, s7), s6), s5), s4), s3), s2), s1), s0) s7+tix7 = SuccTupIdx tix6++tix8 :: TupleIdx (((((((((t, s8), s7), s6), s5), s4), s3), s2), s1), s0) s8+tix8 = SuccTupIdx tix7++{--+-- Smart constructors for array tuples in sequence computations+-- ---------------------------------------------------++stup2 :: (Arrays a, Arrays b) => (Seq a, Seq b) -> Seq (a, b)+stup2 (a, b) = Seq $ Stuple (NilAtup `SnocAtup` a `SnocAtup` b)++stup3 :: (Arrays a, Arrays b, Arrays c) => (Seq a, Seq b, Seq c) -> Seq (a, b, c)+stup3 (a, b, c) = Seq $ Stuple (NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c)++stup4 :: (Arrays a, Arrays b, Arrays c, Arrays d)+      => (Seq a, Seq b, Seq c, Seq d) -> Seq (a, b, c, d)+stup4 (a, b, c, d)+  = Seq $ Stuple (NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c `SnocAtup` d)++stup5 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e)+      => (Seq a, Seq b, Seq c, Seq d, Seq e) -> Seq (a, b, c, d, e)+stup5 (a, b, c, d, e)+  = Seq $ Stuple $+      NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c `SnocAtup` d `SnocAtup` e++stup6 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f)+      => (Seq a, Seq b, Seq c, Seq d, Seq e, Seq f) -> Seq (a, b, c, d, e, f)+stup6 (a, b, c, d, e, f)+  = Seq $ Stuple $+      NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c+              `SnocAtup` d `SnocAtup` e `SnocAtup` f++stup7 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g)+      => (Seq a, Seq b, Seq c, Seq d, Seq e, Seq f, Seq g)+      -> Seq (a, b, c, d, e, f, g)+stup7 (a, b, c, d, e, f, g)+  = Seq $ Stuple $+      NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c+              `SnocAtup` d `SnocAtup` e `SnocAtup` f `SnocAtup` g++stup8 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h)+      => (Seq a, Seq b, Seq c, Seq d, Seq e, Seq f, Seq g, Seq h)+      -> Seq (a, b, c, d, e, f, g, h)+stup8 (a, b, c, d, e, f, g, h)+  = Seq $ Stuple $+      NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c `SnocAtup` d+              `SnocAtup` e `SnocAtup` f `SnocAtup` g `SnocAtup` h++stup9 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i)+      => (Seq a, Seq b, Seq c, Seq d, Seq e, Seq f, Seq g, Seq h, Seq i)+      -> Seq (a, b, c, d, e, f, g, h, i)+stup9 (a, b, c, d, e, f, g, h, i)+  = Seq $ Stuple $+      NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c `SnocAtup` d+              `SnocAtup` e `SnocAtup` f `SnocAtup` g `SnocAtup` h `SnocAtup` i++stup10 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j)+       => (Seq a, Seq b, Seq c, Seq d, Seq e, Seq f, Seq g, Seq h, Seq i, Seq j)+       -> Seq (a, b, c, d, e, f, g, h, i, j)+stup10 (a, b, c, d, e, f, g, h, i, j)+  = Seq $ Stuple $+      NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c `SnocAtup` d `SnocAtup` e+              `SnocAtup` f `SnocAtup` g `SnocAtup` h `SnocAtup` i `SnocAtup` j++stup11 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k)+       => (Seq a, Seq b, Seq c, Seq d, Seq e, Seq f, Seq g, Seq h, Seq i, Seq j, Seq k)+       -> Seq (a, b, c, d, e, f, g, h, i, j, k)+stup11 (a, b, c, d, e, f, g, h, i, j, k)+  = Seq $ Stuple $+      NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c `SnocAtup` d `SnocAtup` e+              `SnocAtup` f `SnocAtup` g `SnocAtup` h `SnocAtup` i `SnocAtup` j `SnocAtup` k++stup12 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l)+       => (Seq a, Seq b, Seq c, Seq d, Seq e, Seq f, Seq g, Seq h, Seq i, Seq j, Seq k, Seq l)+       -> Seq (a, b, c, d, e, f, g, h, i, j, k, l)+stup12 (a, b, c, d, e, f, g, h, i, j, k, l)+  = Seq $ Stuple $+      NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c `SnocAtup` d `SnocAtup` e `SnocAtup` f+              `SnocAtup` g `SnocAtup` h `SnocAtup` i `SnocAtup` j `SnocAtup` k `SnocAtup` l++stup13 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l, Arrays m)+       => (Seq a, Seq b, Seq c, Seq d, Seq e, Seq f, Seq g, Seq h, Seq i, Seq j, Seq k, Seq l, Seq m)+       -> Seq (a, b, c, d, e, f, g, h, i, j, k, l, m)+stup13 (a, b, c, d, e, f, g, h, i, j, k, l, m)+  = Seq $ Stuple $+      NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c `SnocAtup` d `SnocAtup` e `SnocAtup` f+              `SnocAtup` g `SnocAtup` h `SnocAtup` i `SnocAtup` j `SnocAtup` k `SnocAtup` l `SnocAtup` m++stup14 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l, Arrays m, Arrays n)+       => (Seq a, Seq b, Seq c, Seq d, Seq e, Seq f, Seq g, Seq h, Seq i, Seq j, Seq k, Seq l, Seq m, Seq n)+       -> Seq (a, b, c, d, e, f, g, h, i, j, k, l, m, n)+stup14 (a, b, c, d, e, f, g, h, i, j, k, l, m, n)+  = Seq $ Stuple $+      NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c `SnocAtup` d `SnocAtup` e `SnocAtup` f `SnocAtup` g+              `SnocAtup` h `SnocAtup` i `SnocAtup` j `SnocAtup` k `SnocAtup` l `SnocAtup` m `SnocAtup` n++stup15 :: (Arrays a, Arrays b, Arrays c, Arrays d, Arrays e, Arrays f, Arrays g, Arrays h, Arrays i, Arrays j, Arrays k, Arrays l, Arrays m, Arrays n, Arrays o)+       => (Seq a, Seq b, Seq c, Seq d, Seq e, Seq f, Seq g, Seq h, Seq i, Seq j, Seq k, Seq l, Seq m, Seq n, Seq o)+       -> Seq (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)+stup15 (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)+  = Seq $ Stuple $+      NilAtup `SnocAtup` a `SnocAtup` b `SnocAtup` c `SnocAtup` d `SnocAtup` e `SnocAtup` f `SnocAtup` g+              `SnocAtup` h `SnocAtup` i `SnocAtup` j `SnocAtup` k `SnocAtup` l `SnocAtup` m `SnocAtup` n `SnocAtup` o+--}++-- Smart constructor for literals+--++-- | 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+constant = Exp . Const++-- Smart constructor and destructors for scalar tuples+--+tup2 :: (Elt a, Elt b) => (Exp a, Exp b) -> Exp (a, b)+tup2 (a, b) = Exp $ Tuple (NilTup `SnocTup` a `SnocTup` b)++tup3 :: (Elt a, Elt b, Elt c) => (Exp a, Exp b, Exp c) -> Exp (a, b, c)+tup3 (a, b, c) = Exp $ Tuple (NilTup `SnocTup` a `SnocTup` b `SnocTup` c)++tup4 :: (Elt a, Elt b, Elt c, Elt d)+     => (Exp a, Exp b, Exp c, Exp d) -> Exp (a, b, c, d)+tup4 (a, b, c, d)+  = Exp $ Tuple (NilTup `SnocTup` a `SnocTup` b `SnocTup` c `SnocTup` d)++tup5 :: (Elt a, Elt b, Elt c, Elt d, Elt e)+     => (Exp a, Exp b, Exp c, Exp d, Exp e) -> Exp (a, b, c, d, e)+tup5 (a, b, c, d, e)+  = Exp $ Tuple $+      NilTup `SnocTup` a `SnocTup` b `SnocTup` c `SnocTup` d `SnocTup` e++tup6 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f)+     => (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f) -> Exp (a, b, c, d, e, f)+tup6 (a, b, c, d, e, f)+  = Exp $ Tuple $+      NilTup `SnocTup` a `SnocTup` b `SnocTup` c `SnocTup` d `SnocTup` e `SnocTup` f++tup7 :: (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)+     -> Exp (a, b, c, d, e, f, g)+tup7 (a, b, c, d, e, f, g)+  = Exp $ Tuple $+      NilTup `SnocTup` a `SnocTup` b `SnocTup` c+             `SnocTup` d `SnocTup` e `SnocTup` f `SnocTup` g++tup8 :: (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)+     -> Exp (a, b, c, d, e, f, g, h)+tup8 (a, b, c, d, e, f, g, h)+  = Exp $ Tuple $+      NilTup `SnocTup` a `SnocTup` b `SnocTup` c `SnocTup` d+             `SnocTup` e `SnocTup` f `SnocTup` g `SnocTup` h++tup9 :: (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)+     -> Exp (a, b, c, d, e, f, g, h, i)+tup9 (a, b, c, d, e, f, g, h, i)+  = Exp $ Tuple $+      NilTup `SnocTup` a `SnocTup` b `SnocTup` c `SnocTup` d+             `SnocTup` e `SnocTup` f `SnocTup` g `SnocTup` h `SnocTup` i++tup10 :: (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)+      -> Exp (a, b, c, d, e, f, g, h, i, j)+tup10 (a, b, c, d, e, f, g, h, i, j)+  = Exp $ Tuple $+      NilTup `SnocTup` a `SnocTup` b `SnocTup` c `SnocTup` d `SnocTup` e+             `SnocTup` f `SnocTup` g `SnocTup` h `SnocTup` i `SnocTup` j++tup11 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k)+      => (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j, Exp k)+      -> Exp (a, b, c, d, e, f, g, h, i, j, k)+tup11 (a, b, c, d, e, f, g, h, i, j, k)+  = Exp $ Tuple $+      NilTup `SnocTup` a `SnocTup` b `SnocTup` c `SnocTup` d `SnocTup` e+             `SnocTup` f `SnocTup` g `SnocTup` h `SnocTup` i `SnocTup` j `SnocTup` k++tup12 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l)+      => (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j, Exp k, Exp l)+      -> Exp (a, b, c, d, e, f, g, h, i, j, k, l)+tup12 (a, b, c, d, e, f, g, h, i, j, k, l)+  = Exp $ Tuple $+      NilTup `SnocTup` a `SnocTup` b `SnocTup` c `SnocTup` d `SnocTup` e `SnocTup` f+             `SnocTup` g `SnocTup` h `SnocTup` i `SnocTup` j `SnocTup` k `SnocTup` l++tup13 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l, Elt m)+      => (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j, Exp k, Exp l, Exp m)+      -> Exp (a, b, c, d, e, f, g, h, i, j, k, l, m)+tup13 (a, b, c, d, e, f, g, h, i, j, k, l, m)+  = Exp $ Tuple $+      NilTup `SnocTup` a `SnocTup` b `SnocTup` c `SnocTup` d `SnocTup` e `SnocTup` f+             `SnocTup` g `SnocTup` h `SnocTup` i `SnocTup` j `SnocTup` k `SnocTup` l `SnocTup` m++tup14 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l, Elt m, Elt n)+      => (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j, Exp k, Exp l, Exp m, Exp n)+      -> Exp (a, b, c, d, e, f, g, h, i, j, k, l, m, n)+tup14 (a, b, c, d, e, f, g, h, i, j, k, l, m, n)+  = Exp $ Tuple $+      NilTup `SnocTup` a `SnocTup` b `SnocTup` c `SnocTup` d `SnocTup` e `SnocTup` f `SnocTup` g+             `SnocTup` h `SnocTup` i `SnocTup` j `SnocTup` k `SnocTup` l `SnocTup` m `SnocTup` n++tup15 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l, Elt m, Elt n, Elt o)+      => (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j, Exp k, Exp l, Exp m, Exp n, Exp o)+      -> Exp (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)+tup15 (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o)+  = Exp $ Tuple $+      NilTup `SnocTup` a `SnocTup` b `SnocTup` c `SnocTup` d `SnocTup` e `SnocTup` f `SnocTup` g+             `SnocTup` h `SnocTup` i `SnocTup` j `SnocTup` k `SnocTup` l `SnocTup` m `SnocTup` n `SnocTup` o++untup2 :: (Elt a, Elt b) => Exp (a, b) -> (Exp a, Exp b)+untup2 e =+  ( Exp $ SuccTupIdx ZeroTupIdx `Prj` e+  , Exp $ ZeroTupIdx `Prj` e )++untup3 :: (Elt a, Elt b, Elt c) => Exp (a, b, c) -> (Exp a, Exp b, Exp c)+untup3 e =+  ( Exp $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Prj` e+  , Exp $ SuccTupIdx ZeroTupIdx `Prj` e+  , Exp $ ZeroTupIdx `Prj` e)++untup4 :: (Elt a, Elt b, Elt c, Elt d)+       => Exp (a, b, c, d) -> (Exp a, Exp b, Exp c, Exp d)+untup4 e =+  ( Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Prj` e+  , Exp $ SuccTupIdx ZeroTupIdx `Prj` e+  , Exp $ ZeroTupIdx `Prj` e)++untup5 :: (Elt a, Elt b, Elt c, Elt d, Elt e)+       => Exp (a, b, c, d, e) -> (Exp a, Exp b, Exp c, Exp d, Exp e)+untup5 e =+  ( Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Prj` e+  , Exp $ SuccTupIdx ZeroTupIdx `Prj` e+  , Exp $ ZeroTupIdx `Prj` e)++untup6 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f)+       => Exp (a, b, c, d, e, f) -> (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f)+untup6 e =+  ( Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Prj` e+  , Exp $ SuccTupIdx ZeroTupIdx `Prj` e+  , Exp $ ZeroTupIdx `Prj` e)++untup7 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g)+       => Exp (a, b, c, d, e, f, g) -> (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g)+untup7 e =+  ( Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Prj` e+  , Exp $ SuccTupIdx ZeroTupIdx `Prj` e+  , Exp $ ZeroTupIdx `Prj` e)++untup8 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h)+       => Exp (a, b, c, d, e, f, g, h) -> (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h)+untup8 e =+  ( Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Prj` e+  , Exp $ SuccTupIdx ZeroTupIdx `Prj` e+  , Exp $ ZeroTupIdx `Prj` e)++untup9 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i)+       => Exp (a, b, c, d, e, f, g, h, i) -> (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i)+untup9 e =+  ( Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Prj` e+  , Exp $ SuccTupIdx ZeroTupIdx `Prj` e+  , Exp $ ZeroTupIdx `Prj` e)++untup10 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j)+        => Exp (a, b, c, d, e, f, g, h, i, j) -> (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j)+untup10 e =+  ( Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Prj` e+  , Exp $ SuccTupIdx ZeroTupIdx `Prj` e+  , Exp $ ZeroTupIdx `Prj` e)++untup11 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k)+        => Exp (a, b, c, d, e, f, g, h, i, j, k) -> (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j, Exp k)+untup11 e =+  ( Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Prj` e+  , Exp $ SuccTupIdx ZeroTupIdx `Prj` e+  , Exp $ ZeroTupIdx `Prj` e)++untup12 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l)+        => Exp (a, b, c, d, e, f, g, h, i, j, k, l) -> (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j, Exp k, Exp l)+untup12 e =+  ( Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Prj` e+  , Exp $ SuccTupIdx ZeroTupIdx `Prj` e+  , Exp $ ZeroTupIdx `Prj` e)++untup13 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l, Elt m)+        => Exp (a, b, c, d, e, f, g, h, i, j, k, l, m) -> (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j, Exp k, Exp l, Exp m)+untup13 e =+  ( Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Prj` e+  , Exp $ SuccTupIdx ZeroTupIdx `Prj` e+  , Exp $ ZeroTupIdx `Prj` e)++untup14 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l, Elt m, Elt n)+        => Exp (a, b, c, d, e, f, g, h, i, j, k, l, m, n) -> (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j, Exp k, Exp l, Exp m, Exp n)+untup14 e =+  ( Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))))))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Prj` e+  , Exp $ SuccTupIdx ZeroTupIdx `Prj` e+  , Exp $ ZeroTupIdx `Prj` e)++untup15 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i, Elt j, Elt k, Elt l, Elt m, Elt n, Elt o)+        => Exp (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) -> (Exp a, Exp b, Exp c, Exp d, Exp e, Exp f, Exp g, Exp h, Exp i, Exp j, Exp k, Exp l, Exp m, Exp n, Exp o)+untup15 e =+  ( Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))))))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))))))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx))) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx (SuccTupIdx ZeroTupIdx)) `Prj` e+  , Exp $ SuccTupIdx (SuccTupIdx ZeroTupIdx) `Prj` e+  , Exp $ SuccTupIdx ZeroTupIdx `Prj` e+  , Exp $ ZeroTupIdx `Prj` e)++-- Smart constructor for constants+--++mkMinBound :: (Elt t, IsBounded t) => Exp t+mkMinBound = Exp $ PrimConst (PrimMinBound boundedType)++mkMaxBound :: (Elt t, IsBounded t) => Exp t+mkMaxBound = Exp $ PrimConst (PrimMaxBound boundedType)++mkPi :: (Elt r, IsFloating r) => Exp r+mkPi = Exp $ PrimConst (PrimPi floatingType)+++-- Smart constructors for primitive applications+--++-- Operators from Floating++mkSin :: (Elt t, IsFloating t) => Exp t -> Exp t+mkSin x = Exp $ PrimSin floatingType `PrimApp` x++mkCos :: (Elt t, IsFloating t) => Exp t -> Exp t+mkCos x = Exp $ PrimCos floatingType `PrimApp` x++mkTan :: (Elt t, IsFloating t) => Exp t -> Exp t+mkTan x = Exp $ PrimTan floatingType `PrimApp` x++mkAsin :: (Elt t, IsFloating t) => Exp t -> Exp t+mkAsin x = Exp $ PrimAsin floatingType `PrimApp` x++mkAcos :: (Elt t, IsFloating t) => Exp t -> Exp t+mkAcos x = Exp $ PrimAcos floatingType `PrimApp` x++mkAtan :: (Elt t, IsFloating t) => Exp t -> Exp t+mkAtan x = Exp $ PrimAtan floatingType `PrimApp` x++mkSinh :: (Elt t, IsFloating t) => Exp t -> Exp t+mkSinh x = Exp $ PrimSinh floatingType `PrimApp` x++mkCosh :: (Elt t, IsFloating t) => Exp t -> Exp t+mkCosh x = Exp $ PrimCosh floatingType `PrimApp` x++mkTanh :: (Elt t, IsFloating t) => Exp t -> Exp t+mkTanh x = Exp $ PrimTanh floatingType `PrimApp` x++mkAsinh :: (Elt t, IsFloating t) => Exp t -> Exp t+mkAsinh x = Exp $ PrimAsinh floatingType `PrimApp` x++mkAcosh :: (Elt t, IsFloating t) => Exp t -> Exp t+mkAcosh x = Exp $ PrimAcosh floatingType `PrimApp` x++mkAtanh :: (Elt t, IsFloating t) => Exp t -> Exp t+mkAtanh x = Exp $ PrimAtanh floatingType `PrimApp` x++mkExpFloating :: (Elt t, IsFloating t) => Exp t -> Exp t+mkExpFloating x = Exp $ PrimExpFloating floatingType `PrimApp` x++mkSqrt :: (Elt t, IsFloating t) => Exp t -> Exp t+mkSqrt x = Exp $ PrimSqrt floatingType `PrimApp` x++mkLog :: (Elt t, IsFloating t) => Exp t -> Exp t+mkLog x = Exp $ PrimLog floatingType `PrimApp` x++mkFPow :: (Elt t, IsFloating t) => Exp t -> Exp t -> Exp t+mkFPow x y = Exp $ PrimFPow floatingType `PrimApp` tup2 (x, y)++mkLogBase :: (Elt t, IsFloating t) => Exp t -> Exp t -> Exp t+mkLogBase x y = Exp $ PrimLogBase floatingType `PrimApp` tup2 (x, y)++-- Operators from Num++mkAdd :: (Elt t, IsNum t) => Exp t -> Exp t -> Exp t+mkAdd x y = Exp $ PrimAdd numType `PrimApp` tup2 (x, y)++mkSub :: (Elt t, IsNum t) => Exp t -> Exp t -> Exp t+mkSub x y = Exp $ PrimSub numType `PrimApp` tup2 (x, y)++mkMul :: (Elt t, IsNum t) => Exp t -> Exp t -> Exp t+mkMul x y = Exp $ PrimMul numType `PrimApp` tup2 (x, y)++mkNeg :: (Elt t, IsNum t) => Exp t -> Exp t+mkNeg x = Exp $ PrimNeg numType `PrimApp` x++mkAbs :: (Elt t, IsNum t) => Exp t -> Exp t+mkAbs x = Exp $ PrimAbs numType `PrimApp` x++mkSig :: (Elt t, IsNum t) => Exp t -> Exp t+mkSig x = Exp $ PrimSig numType `PrimApp` x++-- Operators from Integral++mkQuot :: (Elt t, IsIntegral t) => Exp t -> Exp t -> Exp t+mkQuot x y = Exp $ PrimQuot integralType `PrimApp` tup2 (x, y)++mkRem :: (Elt t, IsIntegral t) => Exp t -> Exp t -> Exp t+mkRem x y = Exp $ PrimRem integralType `PrimApp` tup2 (x, y)++mkQuotRem :: (Elt t, IsIntegral t) => Exp t -> Exp t -> (Exp t, Exp t)+mkQuotRem x y = untup2 $ Exp $ PrimQuotRem integralType `PrimApp` tup2 (x ,y)++mkIDiv :: (Elt t, IsIntegral t) => Exp t -> Exp t -> Exp t+mkIDiv x y = Exp $ PrimIDiv integralType `PrimApp` tup2 (x, y)++mkMod :: (Elt t, IsIntegral t) => Exp t -> Exp t -> Exp t+mkMod x y = Exp $ PrimMod integralType `PrimApp` tup2 (x, y)++mkDivMod :: (Elt t, IsIntegral t) => Exp t -> Exp t -> (Exp t, Exp t)+mkDivMod x y = untup2 $ Exp $ PrimDivMod integralType `PrimApp` tup2 (x ,y)+++-- Operators from Bits and FiniteBits++mkBAnd :: (Elt t, IsIntegral t) => Exp t -> Exp t -> Exp t+mkBAnd x y = Exp $ PrimBAnd integralType `PrimApp` tup2 (x, y)++mkBOr :: (Elt t, IsIntegral t) => Exp t -> Exp t -> Exp t+mkBOr x y = Exp $ PrimBOr integralType `PrimApp` tup2 (x, y)++mkBXor :: (Elt t, IsIntegral t) => Exp t -> Exp t -> Exp t+mkBXor x y = Exp $ PrimBXor integralType `PrimApp` tup2 (x, y)++mkBNot :: (Elt t, IsIntegral t) => Exp t -> Exp t+mkBNot x = Exp $ PrimBNot integralType `PrimApp` x++mkBShiftL :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t+mkBShiftL x i = Exp $ PrimBShiftL integralType `PrimApp` tup2 (x, i)++mkBShiftR :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t+mkBShiftR x i = Exp $ PrimBShiftR integralType `PrimApp` tup2 (x, i)++mkBRotateL :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t+mkBRotateL x i = Exp $ PrimBRotateL integralType `PrimApp` tup2 (x, i)++mkBRotateR :: (Elt t, IsIntegral t) => Exp t -> Exp Int -> Exp t+mkBRotateR x i = Exp $ PrimBRotateR integralType `PrimApp` tup2 (x, i)++mkPopCount :: (Elt t, IsIntegral t) => Exp t -> Exp Int+mkPopCount x = Exp $ PrimPopCount integralType `PrimApp` x++mkCountLeadingZeros :: (Elt t, IsIntegral t) => Exp t -> Exp Int+mkCountLeadingZeros x = Exp $ PrimCountLeadingZeros integralType `PrimApp` x++mkCountTrailingZeros :: (Elt t, IsIntegral t) => Exp t -> Exp Int+mkCountTrailingZeros x = Exp $ PrimCountTrailingZeros integralType `PrimApp` x+++-- Operators from Fractional++mkFDiv :: (Elt t, IsFloating t) => Exp t -> Exp t -> Exp t+mkFDiv x y = Exp $ PrimFDiv floatingType `PrimApp` tup2 (x, y)++mkRecip :: (Elt t, IsFloating t) => Exp t -> Exp t+mkRecip x = Exp $ PrimRecip floatingType `PrimApp` x++-- Operators from RealFrac++mkTruncate :: (Elt a, Elt b, IsFloating a, IsIntegral b) => Exp a -> Exp b+mkTruncate x = Exp $ PrimTruncate floatingType integralType `PrimApp` x++mkRound :: (Elt a, Elt b, IsFloating a, IsIntegral b) => Exp a -> Exp b+mkRound x = Exp $ PrimRound floatingType integralType `PrimApp` x++mkFloor :: (Elt a, Elt b, IsFloating a, IsIntegral b) => Exp a -> Exp b+mkFloor x = Exp $ PrimFloor floatingType integralType `PrimApp` x++mkCeiling :: (Elt a, Elt b, IsFloating a, IsIntegral b) => Exp a -> Exp b+mkCeiling x = Exp $ PrimCeiling floatingType integralType `PrimApp` x++-- Operators from RealFloat++mkAtan2 :: (Elt t, IsFloating t) => Exp t -> Exp t -> Exp t+mkAtan2 x y = Exp $ PrimAtan2 floatingType `PrimApp` tup2 (x, y)++mkIsNaN :: (Elt t, IsFloating t) => Exp t -> Exp Bool+mkIsNaN x = Exp $ PrimIsNaN floatingType `PrimApp` x++-- FIXME: add missing operations from Floating, RealFrac & RealFloat++-- Relational and equality operators++mkLt :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp Bool+mkLt x y = Exp $ PrimLt scalarType `PrimApp` tup2 (x, y)++mkGt :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp Bool+mkGt x y = Exp $ PrimGt scalarType `PrimApp` tup2 (x, y)++mkLtEq :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp Bool+mkLtEq x y = Exp $ PrimLtEq scalarType `PrimApp` tup2 (x, y)++mkGtEq :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp Bool+mkGtEq x y = Exp $ PrimGtEq scalarType `PrimApp` tup2 (x, y)++mkEq :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp Bool+mkEq x y = Exp $ PrimEq scalarType `PrimApp` tup2 (x, y)++mkNEq :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp Bool+mkNEq x y = Exp $ PrimNEq scalarType `PrimApp` tup2 (x, y)++mkMax :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp t+mkMax x y = Exp $ PrimMax scalarType `PrimApp` tup2 (x, y)++mkMin :: (Elt t, IsScalar t) => Exp t -> Exp t -> Exp t+mkMin x y = Exp $ PrimMin scalarType `PrimApp` tup2 (x, y)++-- Logical operators++mkLAnd :: Exp Bool -> Exp Bool -> Exp Bool+mkLAnd x y = Exp $ PrimLAnd `PrimApp` tup2 (x, y)++mkLOr :: Exp Bool -> Exp Bool -> Exp Bool+mkLOr x y = Exp $ PrimLOr `PrimApp` tup2 (x, y)++mkLNot :: Exp Bool -> Exp Bool+mkLNot x = Exp $ PrimLNot `PrimApp` x++-- Character conversions++mkOrd :: Exp Char -> Exp Int+mkOrd x = Exp $ PrimOrd `PrimApp` x++mkChr :: Exp Int -> Exp Char+mkChr x = Exp $ PrimChr `PrimApp` x++-- Numeric conversions++mkFromIntegral :: (Elt a, Elt b, IsIntegral a, IsNum b) => Exp a -> Exp b+mkFromIntegral x = Exp $ PrimFromIntegral integralType numType `PrimApp` x++mkToFloating :: (Elt a, Elt b, IsNum a, IsFloating b) => Exp a -> Exp b+mkToFloating x = Exp $ PrimToFloating numType floatingType `PrimApp` x++-- Other conversions++mkBoolToInt :: Exp Bool -> Exp Int+mkBoolToInt b = Exp $ PrimBoolToInt `PrimApp` b++-- NOTE: BitSizeEq constraint is used to make this version "safe"+mkBitcast :: (Elt a, Elt b, IsScalar a, IsScalar b, BitSizeEq a b) => Exp a -> Exp b+mkBitcast = mkUnsafeCoerce++mkUnsafeCoerce :: (Elt a, Elt b, IsScalar a, IsScalar b) => Exp a -> Exp b+mkUnsafeCoerce x = Exp $ PrimCoerce scalarType scalarType `PrimApp` x+++-- Auxiliary functions+-- --------------------++infixr 0 $$+($$) :: (b -> a) -> (c -> d -> b) -> c -> d -> a+(f $$ g) x y = f (g x y)++infixr 0 $$$+($$$) :: (b -> a) -> (c -> d -> e -> b) -> c -> d -> e -> a+(f $$$ g) x y z = f (g x y z)++infixr 0 $$$$+($$$$) :: (b -> a) -> (c -> d -> e -> f -> b) -> c -> d -> e -> f -> a+(f $$$$ g) x y z u = f (g x y z u)++infixr 0 $$$$$+($$$$$) :: (b -> a) -> (c -> d -> e -> f -> g -> b) -> c -> d -> e -> f -> g-> a+(f $$$$$ g) x y z u v = f (g x y z u v)+++-- Debugging+-- ---------++showPreAccOp :: forall acc exp arrs. PreAcc acc exp arrs -> String+showPreAccOp (Atag i)           = "Atag " ++ show i+showPreAccOp (Use a)            = "Use "  ++ showArrays a+showPreAccOp Pipe{}             = "Pipe"+showPreAccOp Acond{}            = "Acond"+showPreAccOp Awhile{}           = "Awhile"+showPreAccOp Atuple{}           = "Atuple"+showPreAccOp Aprj{}             = "Aprj"+showPreAccOp Unit{}             = "Unit"+showPreAccOp Generate{}         = "Generate"+showPreAccOp Reshape{}          = "Reshape"+showPreAccOp Replicate{}        = "Replicate"+showPreAccOp Slice{}            = "Slice"+showPreAccOp Map{}              = "Map"+showPreAccOp ZipWith{}          = "ZipWith"+showPreAccOp Fold{}             = "Fold"+showPreAccOp Fold1{}            = "Fold1"+showPreAccOp FoldSeg{}          = "FoldSeg"+showPreAccOp Fold1Seg{}         = "Fold1Seg"+showPreAccOp Scanl{}            = "Scanl"+showPreAccOp Scanl'{}           = "Scanl'"+showPreAccOp Scanl1{}           = "Scanl1"+showPreAccOp Scanr{}            = "Scanr"+showPreAccOp Scanr'{}           = "Scanr'"+showPreAccOp Scanr1{}           = "Scanr1"+showPreAccOp Permute{}          = "Permute"+showPreAccOp Backpermute{}      = "Backpermute"+showPreAccOp Stencil{}          = "Stencil"+showPreAccOp Stencil2{}         = "Stencil2"+showPreAccOp Aforeign{}         = "Aforeign"+-- showPreAccOp Collect{}          = "Collect"++{--+showPreSeqOp :: PreSeq acc seq exp arrs -> String+showPreSeqOp (StreamIn{})       = "StreamIn"+showPreSeqOp (ToSeq{})          = "ToSeq"+showPreSeqOp (MapSeq{})         = "MapSeq"+showPreSeqOp (ZipWithSeq{})     = "ZipWithSeq"+showPreSeqOp (ScanSeq{})        = "ScanSeq"+showPreSeqOp (FoldSeq{})        = "FoldSeq"+showPreSeqOp (FoldSeqFlatten{}) = "FoldSeqFlatten"+showPreSeqOp (Stuple{})         = "Stuple"+--}++showArrays :: forall arrs. Arrays arrs => arrs -> String+showArrays = display . collect (arrays (undefined::arrs)) . fromArr+  where+    collect :: ArraysR a -> a -> [String]+    collect ArraysRunit         _        = []+    collect ArraysRarray        arr      = [showShortendArr arr]+    collect (ArraysRpair r1 r2) (a1, a2) = collect r1 a1 ++ collect r2 a2+    --+    display []  = []+    display [x] = x+    display xs  = "(" ++ intercalate ", " xs ++ ")"+++showShortendArr :: Elt e => Array sh e -> String+showShortendArr arr+  = show (take cutoff l) ++ if length l > cutoff then ".." else ""+  where+    l      = toList arr+    cutoff = 5+++showPreExpOp :: PreExp acc exp t -> String+showPreExpOp (Const c)          = "Const " ++ show c+showPreExpOp (Tag i)            = "Tag" ++ show i+showPreExpOp Tuple{}            = "Tuple"+showPreExpOp Prj{}              = "Prj"+showPreExpOp IndexNil           = "IndexNil"+showPreExpOp IndexCons{}        = "IndexCons"+showPreExpOp IndexHead{}        = "IndexHead"+showPreExpOp IndexTail{}        = "IndexTail"+showPreExpOp IndexAny           = "IndexAny"+showPreExpOp ToIndex{}          = "ToIndex"+showPreExpOp FromIndex{}        = "FromIndex"+showPreExpOp Cond{}             = "Cond"+showPreExpOp While{}            = "While"+showPreExpOp PrimConst{}        = "PrimConst"+showPreExpOp PrimApp{}          = "PrimApp"+showPreExpOp Index{}            = "Index"+showPreExpOp LinearIndex{}      = "LinearIndex"+showPreExpOp Shape{}            = "Shape"+showPreExpOp ShapeSize{}        = "ShapeSize"+showPreExpOp Intersect{}        = "Intersect"+showPreExpOp Union{}            = "Union" showPreExpOp Foreign{}          = "Foreign" 
Data/Array/Accelerate/Trafo.hs view
@@ -7,10 +7,10 @@ {-# OPTIONS_HADDOCK hide #-} -- | -- Module      : Data.Array.Accelerate.Trafo--- Copyright   : [2012..2014] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2012..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell -- License     : BSD3 ----- Maintainer  : Manuel M T Chakravarty <chak@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -22,16 +22,23 @@    convertAcc,  convertAccWith,   convertAfun, convertAfunWith,+  -- convertSeq,  convertSeqWith,    -- * Fusion   module Data.Array.Accelerate.Trafo.Fusion,+  -- DelayedSeq(..), Extend(..),    -- * Substitution-  rebuildAcc,   module Data.Array.Accelerate.Trafo.Substitution, +  -- * Term equality+  Match(..), (:~:)(..),+ ) where +import Control.DeepSeq+import Data.Typeable+ import Data.Array.Accelerate.Smart import Data.Array.Accelerate.Pretty                     ( ) -- show instances import Data.Array.Accelerate.Array.Sugar                ( Arrays, Elt )@@ -44,10 +51,13 @@ import qualified Data.Array.Accelerate.Trafo.Rewrite    as Rewrite import qualified Data.Array.Accelerate.Trafo.Simplify   as Rewrite import qualified Data.Array.Accelerate.Trafo.Sharing    as Sharing+-- import qualified Data.Array.Accelerate.Trafo.Vectorise  as Vectorise  #ifdef ACCELERATE_DEBUG+import Text.Printf import System.IO.Unsafe-import Data.Array.Accelerate.Debug+import Data.Array.Accelerate.Debug                      hiding ( when )+import qualified Data.Array.Accelerate.Debug            as Debug #endif  @@ -62,6 +72,9 @@     -- | Recover sharing of scalar expressions?   , recoverExpSharing           :: Bool +    -- | Recover sharing of sequence computations?+  , recoverSeqSharing           :: Bool+     -- | Are array computations floated out of expressions irrespective of     --   whether they are shared or not? Requires 'recoverAccSharing'.   , floatOutAccFromExp          :: Bool@@ -72,6 +85,10 @@      -- | Convert segment length arrays into segment offset arrays?   , convertOffsetOfSegment      :: Bool++    --   Vectorise maps and zipwiths in sequence computations to+    --   enable chunked execution?+  -- , vectoriseSequences          :: Bool   }  @@ -82,9 +99,11 @@ phases =  Phase   { recoverAccSharing      = True   , recoverExpSharing      = True+  , recoverSeqSharing      = True   , floatOutAccFromExp     = True   , enableAccFusion        = True   , convertOffsetOfSegment = False+  -- , vectoriseSequences     = True   }  when :: (a -> a) -> Bool -> a -> a@@ -103,9 +122,10 @@  convertAccWith :: Arrays arrs => Phase -> Acc arrs -> DelayedAcc arrs convertAccWith Phase{..} acc-  = Fusion.convertAcc enableAccFusion-  $ Rewrite.convertSegments `when` convertOffsetOfSegment-  $ Sharing.convertAcc recoverAccSharing recoverExpSharing floatOutAccFromExp+  = phase "array-fusion"           (Fusion.convertAcc enableAccFusion)+  -- phase "vectorise-sequences"    Vectorise.vectoriseSeqAcc `when` vectoriseSequences+  $ phase "rewrite-segment-offset" Rewrite.convertSegments   `when` convertOffsetOfSegment+  $ phase "sharing-recovery"       (Sharing.convertAcc recoverAccSharing recoverExpSharing recoverSeqSharing floatOutAccFromExp)   $ acc  @@ -117,9 +137,10 @@  convertAfunWith :: Afunction f => Phase -> f -> DelayedAfun (AfunctionR f) convertAfunWith Phase{..} acc-  = Fusion.convertAfun enableAccFusion-  $ Rewrite.convertSegmentsAfun `when` convertOffsetOfSegment-  $ Sharing.convertAfun recoverAccSharing recoverExpSharing floatOutAccFromExp+  = phase "array-fusion"           (Fusion.convertAfun enableAccFusion)+  -- phase "vectorise-sequences"    Vectorise.vectoriseSeqAfun  `when` vectoriseSequences+  $ phase "rewrite-segment-offset" Rewrite.convertSegmentsAfun `when` convertOffsetOfSegment+  $ phase "sharing-recovery"       (Sharing.convertAfun recoverAccSharing recoverExpSharing recoverSeqSharing floatOutAccFromExp)   $ acc  @@ -128,8 +149,8 @@ -- convertExp :: Elt e => Exp e -> AST.Exp () e convertExp-  = Rewrite.simplify-  . Sharing.convertExp (recoverExpSharing phases)+  = phase "exp-simplify"      Rewrite.simplify+  . phase "sharing-recovery" (Sharing.convertExp (recoverExpSharing phases))   -- | Convert closed scalar functions, incorporating sharing observation and@@ -137,10 +158,25 @@ -- convertFun :: Function f => f -> AST.Fun () (FunctionR f) convertFun-  = Rewrite.simplify-  . Sharing.convertFun (recoverExpSharing phases)+  = phase "exp-simplify"      Rewrite.simplify+  . phase "sharing-recovery" (Sharing.convertFun (recoverExpSharing phases)) +{--+-- | Convert a closed sequence computation, incorporating sharing observation and+--   optimisation.+--+convertSeq :: Typeable s => Seq s -> DelayedSeq s+convertSeq = convertSeqWith phases +convertSeqWith :: Typeable s => Phase -> Seq s -> DelayedSeq s+convertSeqWith Phase{..} s+  = phase "array-fusion"           (Fusion.convertSeq enableAccFusion)+  -- $ phase "vectorise-sequences"    Vectorise.vectoriseSeq     `when` vectoriseSequences+  $ phase "rewrite-segment-offset" Rewrite.convertSegmentsSeq `when` convertOffsetOfSegment+  $ phase "sharing-recovery"       (Sharing.convertSeq recoverAccSharing recoverExpSharing recoverSeqSharing floatOutAccFromExp)+  $ s+--}+ -- Pretty printing -- --------------- @@ -156,7 +192,10 @@ instance Function (Exp a -> f) => Show (Exp a -> f) where   show = withSimplStats . show . convertFun +-- instance Typeable a => Show (Seq a) where+--   show = withSimplStats . show . convertSeq + -- Debugging -- --------- @@ -171,14 +210,23 @@ withSimplStats :: String -> String #ifdef ACCELERATE_DEBUG withSimplStats x = unsafePerformIO $ do-  enabled <- queryFlag dump_simpl_stats-  if not enabled-     then return x-     else do resetSimplCount-             stats <- length x `seq` simplCount-             traceMessage dump_simpl_stats (show stats)-             return x+  Debug.when dump_simpl_stats $ x `deepseq` dumpSimplStats+  return x #else withSimplStats x = x+#endif++-- Execute a phase of the compiler and (possibly) print some timing/gc+-- statistics.+--+phase :: NFData b => String -> (a -> b) -> a -> b+#ifdef ACCELERATE_DEBUG+phase n f x = unsafePerformIO $ do+  enabled <- queryFlag dump_phases+  if enabled+    then timed dump_phases (\wall cpu -> printf "phase %s: %s" n (elapsed wall cpu)) (return $!! f x)+    else return (f x)+#else+phase _ f x = f x #endif 
Data/Array/Accelerate/Trafo/Algebra.hs view
@@ -1,15 +1,17 @@+{-# LANGUAGE CPP                 #-} {-# LANGUAGE GADTs               #-} {-# LANGUAGE PatternGuards       #-} {-# LANGUAGE RankNTypes          #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TupleSections       #-} {-# LANGUAGE TypeOperators       #-} {-# LANGUAGE ViewPatterns        #-} -- | -- Module      : Data.Array.Accelerate.Trafo.Algebra--- Copyright   : [2012..2014] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2012..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell -- License     : BSD3 ----- Maintainer  : Manuel M T Chakravarty <chak@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -24,18 +26,20 @@ ) where  import Prelude                                          hiding ( exp )-import Data.Maybe                                       ( fromMaybe ) import Data.Bits import Data.Char+import Data.Monoid+import GHC.Float                                        ( float2Double, double2Float ) import Text.PrettyPrint+import Unsafe.Coerce import qualified Prelude                                as P  -- friends import Data.Array.Accelerate.AST import Data.Array.Accelerate.Type-import Data.Array.Accelerate.Tuple+import Data.Array.Accelerate.Product import Data.Array.Accelerate.Pretty.Print               ( prettyPrim )-import Data.Array.Accelerate.Array.Sugar                ( Elt, toElt, fromElt )+import Data.Array.Accelerate.Array.Sugar                ( (:.)(..), Elt(..), Tuple(..), fromTuple ) import Data.Array.Accelerate.Analysis.Match import Data.Array.Accelerate.Trafo.Base @@ -60,9 +64,11 @@       Prj ix e       | Just c  <- cvtE e        -> cvtP ix (fromTuple c)       Var ix         | e             <- prjExp ix env-        , Nothing       <- match exp e  -> cvtE e+        , Nothing       <- match exp e          -> cvtE e       ---      _                                 -> Nothing+      IndexHead (cvtE -> Just (_  :. z))        -> Just z+      IndexTail (cvtE -> Just (sh :. _))        -> Just sh+      _                                         -> Nothing      cvtP :: TupleIdx t e -> t -> Maybe e     cvtP ZeroTupIdx       (_, v)   = Just v@@ -71,7 +77,9 @@     cvtT :: TupleIdx t e -> Tuple (PreOpenExp acc env aenv) t -> Maybe e     cvtT ZeroTupIdx       (SnocTup _   e) = cvtE e     cvtT (SuccTupIdx idx) (SnocTup tup _) = cvtT idx tup+#if __GLASGOW_HASKELL__ < 800     cvtT _                _               = error "hey what's the head angle on that thing?"+#endif   -- Attempt to evaluate primitive function applications@@ -81,7 +89,7 @@     => Gamma acc env env aenv     -> PrimFun (a -> r)     -> PreOpenExp acc env aenv a-    -> PreOpenExp acc env aenv r+    -> (Any, PreOpenExp acc env aenv r) evalPrimApp env f x   -- First attempt to move constant values towards the left   | Just r      <- commutes f x env     = evalPrimApp env f r@@ -89,7 +97,7 @@    -- Now attempt to evaluate any expressions   | otherwise-  = fromMaybe (PrimApp f x)+  = maybe (Any False, PrimApp f x) (Any True,)   $ case f of       PrimAdd ty                -> evalAdd ty x env       PrimSub ty                -> evalSub ty x env@@ -99,8 +107,10 @@       PrimSig ty                -> evalSig ty x env       PrimQuot ty               -> evalQuot ty x env       PrimRem ty                -> evalRem ty x env+      PrimQuotRem ty            -> evalQuotRem ty x env       PrimIDiv ty               -> evalIDiv ty x env       PrimMod ty                -> evalMod ty x env+      PrimDivMod ty             -> evalDivMod ty x env       PrimBAnd ty               -> evalBAnd ty x env       PrimBOr ty                -> evalBOr ty x env       PrimBXor ty               -> evalBXor ty x env@@ -109,6 +119,9 @@       PrimBShiftR ty            -> evalBShiftR ty x env       PrimBRotateL ty           -> evalBRotateL ty x env       PrimBRotateR ty           -> evalBRotateR ty x env+      PrimPopCount ty           -> evalPopCount ty x env+      PrimCountLeadingZeros ty  -> evalCountLeadingZeros ty x env+      PrimCountTrailingZeros ty -> evalCountTrailingZeros ty x env       PrimFDiv ty               -> evalFDiv ty x env       PrimRecip ty              -> evalRecip ty x env       PrimSin ty                -> evalSin ty x env@@ -117,6 +130,9 @@       PrimAsin ty               -> evalAsin ty x env       PrimAcos ty               -> evalAcos ty x env       PrimAtan ty               -> evalAtan ty x env+      PrimSinh ty               -> evalSinh ty x env+      PrimCosh ty               -> evalCosh ty x env+      PrimTanh ty               -> evalTanh ty x env       PrimAsinh ty              -> evalAsinh ty x env       PrimAcosh ty              -> evalAcosh ty x env       PrimAtanh ty              -> evalAtanh ty x env@@ -130,6 +146,7 @@       PrimRound ta tb           -> evalRound ta tb x env       PrimFloor ta tb           -> evalFloor ta tb x env       PrimCeiling ta tb         -> evalCeiling ta tb x env+      PrimIsNaN ty              -> evalIsNaN ty x env       PrimLt ty                 -> evalLt ty x env       PrimGt ty                 -> evalGt ty x env       PrimLtEq ty               -> evalLtEq ty x env@@ -145,6 +162,8 @@       PrimChr                   -> evalChr x env       PrimBoolToInt             -> evalBoolToInt x env       PrimFromIntegral ta tb    -> evalFromIntegral ta tb x env+      PrimToFloating ta tb      -> evalToFloating ta tb x env+      PrimCoerce ta tb          -> evalCoerce ta tb x env   -- Discriminate binary functions that commute, and if so return the operands in@@ -152,7 +171,7 @@ -- to the left of the operator. Returning Nothing indicates no change is made. -- commutes-    :: forall acc env aenv a r. (Kit acc, Elt a, Elt r)+    :: forall acc env aenv a r. Kit acc     => PrimFun (a -> r)     -> PreOpenExp acc env aenv a     -> Gamma acc env env aenv@@ -167,8 +186,6 @@   PrimNEq _     -> swizzle x   PrimMax _     -> swizzle x   PrimMin _     -> swizzle x-  PrimLAnd      -> swizzle x-  PrimLOr       -> swizzle x   _             -> Nothing   where     swizzle :: PreOpenExp acc env aenv (b,b) -> Maybe (PreOpenExp acc env aenv (b,b))@@ -223,10 +240,10 @@      swizzle :: (Elt a, Elt r) => PrimFun (a -> r) -> PreOpenExp acc env aenv a -> [PrimFun (a -> r)] -> Maybe (PreOpenExp acc env aenv r)     swizzle f x lvl-      | Just REFL       <- matches f ops+      | Just Refl       <- matches f ops       , Just (a,bc)     <- untup2 x       , PrimApp g y     <- bc-      , Just REFL       <- matches g lvl+      , Just Refl       <- matches g lvl       , Just (b,c)      <- untup2 y       = Stats.ruleFired (pprFun "associates" f)       $ Just $ PrimApp g (tup2 (PrimApp f (tup2 (a,b)), c))@@ -237,8 +254,8 @@     matches :: (Elt s, Elt t) => PrimFun (s -> a) -> [PrimFun (t -> a)] -> Maybe (s :=: t)     matches _ []        = Nothing     matches f (x:xs)-      | Just REFL       <- matchPrimFun' f x-      = Just REFL+      | Just Refl       <- matchPrimFun' f x+      = Just Refl        | otherwise       = matches f xs@@ -265,13 +282,13 @@ eval2 _ _ _   = Nothing --- tup2 :: (Elt a, Elt b) => (PreOpenExp acc env aenv a, PreOpenExp acc env aenv b) -> PreOpenExp acc env aenv (a, b)--- tup2 (a,b) = Tuple (NilTup `SnocTup` a `SnocTup` b)+tup2 :: (Elt a, Elt b) => (PreOpenExp acc env aenv a, PreOpenExp acc env aenv b) -> PreOpenExp acc env aenv (a, b)+tup2 (a,b) = Tuple (NilTup `SnocTup` a `SnocTup` b)  untup2 :: PreOpenExp acc env aenv (a, b) -> Maybe (PreOpenExp acc env aenv a, PreOpenExp acc env aenv b) untup2 exp-  | Tuple (NilTup `SnocTup` a `SnocTup` b) <- exp   = Just (a, b)-  | otherwise                                       = Nothing+  | Tuple (NilTup `SnocTup` a `SnocTup` b) <- exp = Just (a, b)+  | otherwise                                     = Nothing   pprFun :: String -> PrimFun f -> String@@ -308,9 +325,9 @@   | Nothing     <- propagate env x   , Just b      <- propagate env y   = Stats.ruleFired "-y+x"-  $ Just $ evalPrimApp env (PrimAdd ty) (Tuple $ NilTup `SnocTup` Const (fromElt (-b)) `SnocTup` x)+  $ Just . snd $ evalPrimApp env (PrimAdd ty) (Tuple $ NilTup `SnocTup` Const (fromElt (-b)) `SnocTup` x) -  | Just REFL   <- match x y+  | Just Refl   <- match x y   = Stats.ruleFired "x-x"   $ Just $ Const (fromElt (0::a)) @@ -335,8 +352,9 @@   = eval2 (*) arg env  evalNeg :: Elt a => NumType a -> a :-> a-evalNeg (IntegralNumType ty) | IntegralDict <- integralDict ty = eval1 negate-evalNeg (FloatingNumType ty) | FloatingDict <- floatingDict ty = eval1 negate+evalNeg _                    x _   | PrimApp PrimNeg{} x' <- x       = Stats.ruleFired "negate/negate" $ Just x'+evalNeg (IntegralNumType ty) x env | IntegralDict <- integralDict ty = eval1 negate x env+evalNeg (FloatingNumType ty) x env | FloatingDict <- floatingDict ty = eval1 negate x env  evalAbs :: Elt a => NumType a -> a :-> a evalAbs (IntegralNumType ty) | IntegralDict <- integralDict ty = eval1 abs@@ -350,26 +368,71 @@ -- Methods of Integral & Bits -- -------------------------- -evalQuot :: Elt a => IntegralType a -> (a,a) :-> a-evalQuot ty | IntegralDict <- integralDict ty = eval2 quot+evalQuot :: IntegralType a -> (a,a) :-> a+evalQuot ty exp env+  | Just qr    <- evalQuotRem ty exp env+  , Just (q,_) <- untup2 qr+  = Just q+evalQuot _ _ _+  = Nothing -evalRem :: Elt a => IntegralType a -> (a,a) :-> a-evalRem ty | IntegralDict <- integralDict ty = eval2 rem+evalRem :: IntegralType a -> (a,a) :-> a+evalRem ty exp env+  | Just qr    <- evalQuotRem ty exp env+  , Just (_,r) <- untup2 qr+  = Just r+evalRem _ _ _+  = Nothing -evalIDiv :: Elt a => IntegralType a -> (a,a) :-> a-evalIDiv ty | IntegralDict <- integralDict ty = evalIDiv'+evalQuotRem :: forall a. IntegralType a -> (a,a) :-> (a,a)+evalQuotRem ty exp env+  | IntegralDict                           <- integralDict ty+  , Tuple (NilTup `SnocTup` x `SnocTup` y) <- exp       -- TLM: untup2, but inlined to expose the Elt dictionary+  , Just b                                 <- propagate env y+  = case b of+      0 -> Nothing+      1 -> Stats.ruleFired "quotRem x 1" $ Just (tup2 (x, Const (fromElt (0::a))))+      _ -> case propagate env x of+             Nothing -> Nothing+             Just a  -> Stats.substitution "constant fold"+                      $ Just $ let (u,v) = quotRem a b+                               in  tup2 (Const (fromElt u), Const (fromElt v))+evalQuotRem _ _ _+  = Nothing -evalIDiv' :: (Elt a, Integral a, Eq a) => (a,a) :-> a-evalIDiv' (untup2 -> Just (x,y)) env-  | Just 1      <- propagate env y-  = Stats.ruleFired "x`div`1" $ Just x -evalIDiv' arg env-  = eval2 div arg env+evalIDiv :: IntegralType a -> (a,a) :-> a+evalIDiv ty exp env+  | Just dm    <- evalDivMod ty exp env+  , Just (d,_) <- untup2 dm+  = Just d+evalIDiv _ _ _+  = Nothing -evalMod :: Elt a => IntegralType a -> (a,a) :-> a-evalMod ty | IntegralDict <- integralDict ty = eval2 mod+evalMod :: IntegralType a -> (a,a) :-> a+evalMod ty exp env+  | Just dm    <- evalDivMod ty exp env+  , Just (_,m) <- untup2 dm+  = Just m+evalMod _ _ _+  = Nothing +evalDivMod :: forall a. IntegralType a -> (a,a) :-> (a,a)+evalDivMod ty exp env+  | IntegralDict                           <- integralDict ty+  , Tuple (NilTup `SnocTup` x `SnocTup` y) <- exp       -- TLM: untup2, but inlined to expose the Elt dictionary+  , Just b                                 <- propagate env y+  = case b of+      0 -> Nothing+      1 -> Stats.ruleFired "divMod x 1" $ Just (tup2 (x, Const (fromElt (0::a))))+      _ -> case propagate env x of+             Nothing -> Nothing+             Just a  -> Stats.substitution "constant fold"+                      $ Just $ let (u,v) = divMod a b+                               in  tup2 (Const (fromElt u), Const (fromElt v))+evalDivMod _ _ _+  = Nothing+ evalBAnd :: Elt a => IntegralType a -> (a,a) :-> a evalBAnd ty | IntegralDict <- integralDict ty = eval2 (.&.) @@ -412,7 +475,38 @@ evalBRotateR ty arg env   | IntegralDict <- integralDict ty = eval2 rotateR arg env +evalPopCount :: IntegralType a -> a :-> Int+evalPopCount ty | IntegralDict <- integralDict ty = eval1 popCount +evalCountLeadingZeros :: IntegralType a -> a :-> Int+#if __GLASGOW_HASKELL__ >= 710+evalCountLeadingZeros ty | IntegralDict <- integralDict ty = eval1 countLeadingZeros+#else+evalCountLeadingZeros ty | IntegralDict <- integralDict ty = eval1 clz+  where+    clz x = (w-1) - go (w-1)+      where+        go i | i < 0       = i  -- no bit set+             | testBit x i = i+             | otherwise   = go (i-1)+        w = finiteBitSize x+#endif++evalCountTrailingZeros :: IntegralType a -> a :-> Int+#if __GLASGOW_HASKELL__ >= 710+evalCountTrailingZeros ty | IntegralDict <- integralDict ty = eval1 countTrailingZeros+#else+evalCountTrailingZeros ty | IntegralDict <- integralDict ty = eval1 ctz+  where+    ctz x = go 0+      where+        go i | i >= w      = i+             | testBit x i = i+             | otherwise   = go (i+1)+        w = finiteBitSize x+#endif++ -- Methods of Fractional & Floating -- -------------------------------- @@ -449,6 +543,15 @@ evalAtan :: Elt a => FloatingType a -> a :-> a evalAtan ty | FloatingDict <- floatingDict ty = eval1 atan +evalSinh :: Elt a => FloatingType a -> a :-> a+evalSinh ty | FloatingDict <- floatingDict ty = eval1 sinh++evalCosh :: Elt a => FloatingType a -> a :-> a+evalCosh ty | FloatingDict <- floatingDict ty = eval1 cosh++evalTanh :: Elt a => FloatingType a -> a :-> a+evalTanh ty | FloatingDict <- floatingDict ty = eval1 tanh+ evalAsinh :: Elt a => FloatingType a -> a :-> a evalAsinh ty | FloatingDict <- floatingDict ty = eval1 asinh @@ -476,27 +579,30 @@ evalAtan2 :: Elt a => FloatingType a -> (a,a) :-> a evalAtan2 ty | FloatingDict <- floatingDict ty = eval2 atan2 -evalTruncate :: (Elt a, Elt b) => FloatingType a -> IntegralType b -> a :-> b+evalTruncate :: Elt b => FloatingType a -> IntegralType b -> a :-> b evalTruncate ta tb   | FloatingDict <- floatingDict ta   , IntegralDict <- integralDict tb = eval1 truncate -evalRound :: (Elt a, Elt b) => FloatingType a -> IntegralType b -> a :-> b+evalRound :: Elt b => FloatingType a -> IntegralType b -> a :-> b evalRound ta tb   | FloatingDict <- floatingDict ta   , IntegralDict <- integralDict tb = eval1 round -evalFloor :: (Elt a, Elt b) => FloatingType a -> IntegralType b -> a :-> b+evalFloor :: Elt b => FloatingType a -> IntegralType b -> a :-> b evalFloor ta tb   | FloatingDict <- floatingDict ta   , IntegralDict <- integralDict tb = eval1 floor -evalCeiling :: (Elt a, Elt b) => FloatingType a -> IntegralType b -> a :-> b+evalCeiling :: Elt b => FloatingType a -> IntegralType b -> a :-> b evalCeiling ta tb   | FloatingDict <- floatingDict ta   , IntegralDict <- integralDict tb = eval1 ceiling +evalIsNaN :: FloatingType a -> a :-> Bool+evalIsNaN ty | FloatingDict <- floatingDict ty = eval1 isNaN + -- Relational & Equality -- --------------------- @@ -563,7 +669,8 @@   = Nothing  evalLNot :: Bool :-> Bool-evalLNot = eval1 not+evalLNot x _   | PrimApp PrimLNot x' <- x = Stats.ruleFired "not/not" $ Just x'+evalLNot x env                            = eval1 not x env  evalOrd :: Char :-> Int evalOrd = eval1 ord@@ -582,6 +689,30 @@ evalFromIntegral ta (FloatingNumType tb)   | IntegralDict <- integralDict ta   , FloatingDict <- floatingDict tb = eval1 fromIntegral++evalToFloating :: Elt b => NumType a -> FloatingType b -> a :-> b+evalToFloating (IntegralNumType ta) tb x env+  | IntegralDict <- integralDict ta+  , FloatingDict <- floatingDict tb = eval1 realToFrac x env++evalToFloating (FloatingNumType ta) tb x env+  | TypeFloat  FloatingDict <- ta+  , TypeFloat  FloatingDict <- tb = Just x++  | TypeDouble FloatingDict <- ta+  , TypeDouble FloatingDict <- tb = Just x++  | TypeFloat  FloatingDict <- ta+  , TypeDouble FloatingDict <- tb = eval1 float2Double x env++  | TypeDouble FloatingDict <- ta+  , TypeFloat  FloatingDict <- tb = eval1 double2Float x env++  | FloatingDict <- floatingDict ta+  , FloatingDict <- floatingDict tb = eval1 realToFrac x env++evalCoerce :: Elt b => ScalarType a -> ScalarType b -> a :-> b+evalCoerce _ _ = eval1 unsafeCoerce   -- Scalar primitives
Data/Array/Accelerate/Trafo/Base.hs view
@@ -1,19 +1,26 @@+{-# LANGUAGE CPP                  #-}+{-# LANGUAGE ConstraintKinds      #-} {-# LANGUAGE FlexibleInstances    #-} {-# LANGUAGE GADTs                #-}-{-# LANGUAGE IncoherentInstances  #-}-{-# LANGUAGE OverlappingInstances #-} {-# LANGUAGE PatternGuards        #-} {-# LANGUAGE RankNTypes           #-} {-# LANGUAGE RecordWildCards      #-} {-# LANGUAGE ScopedTypeVariables  #-} {-# LANGUAGE TemplateHaskell      #-}+{-# LANGUAGE TypeFamilies         #-} {-# LANGUAGE TypeOperators        #-}+#if __GLASGOW_HASKELL__ <= 708+{-# LANGUAGE IncoherentInstances  #-}+{-# LANGUAGE OverlappingInstances #-}+{-# LANGUAGE UndecidableInstances #-}+{-# OPTIONS_GHC -fno-warn-unrecognised-pragmas #-}+#endif -- | -- Module      : Data.Array.Accelerate.Trafo.Base--- Copyright   : [2012..2014] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2012..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell -- License     : BSD3 ----- Maintainer  : Manuel M T Chakravarty <chak@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -21,44 +28,55 @@ module Data.Array.Accelerate.Trafo.Base (    -- Toolkit-  Kit(..), Match(..), (:=:)(REFL),-  avarIn, kmap,+  Kit(..), Match(..), (:~:)(..),+  avarIn, kmap, fromOpenAfun,    -- Delayed Arrays   DelayedAcc,  DelayedOpenAcc(..),   DelayedAfun, DelayedOpenAfun,   DelayedExp, DelayedFun, DelayedOpenExp, DelayedOpenFun,+  -- DelayedSeq(..), DelayedOpenSeq,    -- Environments   Gamma(..), incExp, prjExp, lookupExp,+  Extend(..), append, bind, Sink(..), sink, sink1,+  weakenGamma1, sinkGamma,+  Supplement(..), bindExps, +  subApply, inlineA,+ ) where  -- standard library-import Prelude                                          hiding ( until )+import Control.Applicative+import Control.DeepSeq import Data.Hashable+import Data.Type.Equality import Text.PrettyPrint+import Prelude                                          hiding ( until )  -- friends-import Data.Array.Accelerate.AST+import Data.Array.Accelerate.AST                        hiding ( Val(..) ) import Data.Array.Accelerate.Analysis.Match import Data.Array.Accelerate.Array.Sugar                ( Array, Arrays, Shape, Elt ) import Data.Array.Accelerate.Error import Data.Array.Accelerate.Pretty.Print import Data.Array.Accelerate.Trafo.Substitution +import Data.Array.Accelerate.Debug.Stats                as Stats + -- Toolkit -- =======  -- The bat utility belt of operations required to manipulate terms parameterised -- by the recursive closure. ---class Kit acc where+class (RebuildableAcc acc, Sink acc) => Kit acc where   inject        :: PreOpenAcc acc aenv a -> acc aenv a   extract       :: acc aenv a -> PreOpenAcc acc aenv a+  fromOpenAcc   :: OpenAcc aenv a -> acc aenv a   ---  rebuildAcc    :: RebuildAcc acc   matchAcc      :: MatchAcc acc   hashAcc       :: HashAcc acc   prettyAcc     :: PrettyAcc acc@@ -66,11 +84,14 @@ instance Kit OpenAcc where   inject                 = OpenAcc   extract (OpenAcc pacc) = pacc--  rebuildAcc    = rebuildOpenAcc-  matchAcc      = matchOpenAcc-  hashAcc       = hashOpenAcc-  prettyAcc     = prettyOpenAcc+  fromOpenAcc            = id+  --+  {-# INLINEABLE hashAcc   #-}+  {-# INLINEABLE matchAcc  #-}+  {-# INLINEABLE prettyAcc #-}+  hashAcc                = hashOpenAcc+  matchAcc               = matchOpenAcc+  prettyAcc              = prettyOpenAcc  avarIn :: (Kit acc, Arrays arrs) => Idx aenv arrs -> acc aenv arrs avarIn = inject  . Avar@@ -78,26 +99,34 @@ kmap :: Kit acc => (PreOpenAcc acc aenv a -> PreOpenAcc acc aenv b) -> acc aenv a -> acc aenv b kmap f = inject . f . extract +fromOpenAfun :: Kit acc => OpenAfun aenv f -> PreOpenAfun acc aenv f+fromOpenAfun (Abody a) = Abody $ fromOpenAcc a+fromOpenAfun (Alam f)  = Alam  $ fromOpenAfun f  -- A class for testing the equality of terms homogeneously, returning a witness -- to the existentially quantified terms in the positive case. -- class Match f where-  match :: f s -> f t -> Maybe (s :=: t)+  match :: f s -> f t -> Maybe (s :~: t)  instance Match (Idx env) where+  {-# INLINEABLE match #-}   match = matchIdx  instance Kit acc => Match (PreOpenExp acc env aenv) where+  {-# INLINEABLE match #-}   match = matchPreOpenExp matchAcc hashAcc  instance Kit acc => Match (PreOpenFun acc env aenv) where+  {-# INLINEABLE match #-}   match = matchPreOpenFun matchAcc hashAcc  instance Kit acc => Match (PreOpenAcc acc aenv) where+  {-# INLINEABLE match #-}   match = matchPreOpenAcc matchAcc hashAcc -instance Kit acc => Match (acc aenv) where      -- overlapping, undecidable, incoherent+instance {-# INCOHERENT #-} Kit acc => Match (acc aenv) where+  {-# INLINEABLE match #-}   match = matchAcc  @@ -113,9 +142,16 @@  type DelayedExp         = DelayedOpenExp () type DelayedFun         = DelayedOpenFun ()++-- data DelayedSeq t where+--   DelayedSeq :: Extend DelayedOpenAcc () aenv+--              -> DelayedOpenSeq aenv () t+--              -> DelayedSeq t+ type DelayedOpenAfun    = PreOpenAfun DelayedOpenAcc type DelayedOpenExp     = PreOpenExp DelayedOpenAcc type DelayedOpenFun     = PreOpenFun DelayedOpenAcc+-- type DelayedOpenSeq     = PreOpenSeq DelayedOpenAcc  data DelayedOpenAcc aenv a where   Manifest              :: PreOpenAcc DelayedOpenAcc aenv a -> DelayedOpenAcc aenv a@@ -126,19 +162,43 @@     , linearIndexD      :: PreFun DelayedOpenAcc aenv (Int -> e)     }                   -> DelayedOpenAcc aenv (Array sh e) +instance Rebuildable DelayedOpenAcc where+  type AccClo DelayedOpenAcc = DelayedOpenAcc+  {-# INLINEABLE rebuildPartial #-}+  rebuildPartial v acc = case acc of+    Manifest pacc -> Manifest <$> rebuildPartial v pacc+    Delayed{..}   -> Delayed  <$> rebuildPartial v extentD+                              <*> rebuildPartial v indexD+                              <*> rebuildPartial v linearIndexD++instance Sink DelayedOpenAcc where+  weaken k = Stats.substitution "weaken" . rebuildA (Avar . k)+ instance Kit DelayedOpenAcc where-  inject        = Manifest-  extract       = error "DelayedAcc.extract"+  inject                  = Manifest+  extract (Manifest pacc) = pacc+  extract Delayed{}       = error "DelayedAcc.extract"+  fromOpenAcc             = error "DelayedAcc.fromOpenAcc"   ---  rebuildAcc    = rebuildDelayed-  matchAcc      = matchDelayed-  hashAcc       = hashDelayed-  prettyAcc     = prettyDelayed+  {-# INLINEABLE hashAcc   #-}+  {-# INLINEABLE matchAcc  #-}+  {-# INLINEABLE prettyAcc #-}+  hashAcc                 = hashDelayed+  matchAcc                = matchDelayed+  prettyAcc               = prettyDelayed +instance NFData (DelayedOpenAfun aenv t) where+  rnf = rnfPreOpenAfun rnfDelayedOpenAcc +instance NFData (DelayedOpenAcc aenv t) where+  rnf = rnfDelayedOpenAcc++-- instance NFData (DelayedSeq t) where+--   rnf = rnfDelayedSeq+ hashDelayed :: HashAcc DelayedOpenAcc-hashDelayed (Manifest pacc)     = hash "Manifest"       `hashWithSalt` hashPreOpenAcc hashAcc pacc-hashDelayed Delayed{..}         = hash "Delayed"        `hashE` extentD `hashF` indexD `hashF` linearIndexD+hashDelayed (Manifest pacc)     = hash "Manifest" `hashWithSalt` hashPreOpenAcc hashAcc pacc+hashDelayed Delayed{..}         = hash "Delayed"  `hashE` extentD `hashF` indexD `hashF` linearIndexD   where     hashE salt = hashWithSalt salt . hashPreOpenExp hashAcc     hashF salt = hashWithSalt salt . hashPreOpenFun hashAcc@@ -148,22 +208,31 @@   = matchPreOpenAcc matchAcc hashAcc pacc1 pacc2  matchDelayed (Delayed sh1 ix1 lx1) (Delayed sh2 ix2 lx2)-  | Just REFL   <- matchPreOpenExp matchAcc hashAcc sh1 sh2-  , Just REFL   <- matchPreOpenFun matchAcc hashAcc ix1 ix2-  , Just REFL   <- matchPreOpenFun matchAcc hashAcc lx1 lx2-  = Just REFL+  | Just Refl <- matchPreOpenExp matchAcc hashAcc sh1 sh2+  , Just Refl <- matchPreOpenFun matchAcc hashAcc ix1 ix2+  , Just Refl <- matchPreOpenFun matchAcc hashAcc lx1 lx2+  = Just Refl  matchDelayed _ _   = Nothing -rebuildDelayed :: RebuildAcc DelayedOpenAcc-rebuildDelayed v acc = case acc of-  Manifest pacc -> Manifest (rebuildA rebuildDelayed v pacc)-  Delayed{..}   -> Delayed (rebuildEA rebuildDelayed v extentD)-                           (rebuildFA rebuildDelayed v indexD)-                           (rebuildFA rebuildDelayed v linearIndexD)+rnfDelayedOpenAcc :: DelayedOpenAcc aenv t -> ()+rnfDelayedOpenAcc (Manifest pacc)    = rnfPreOpenAcc rnfDelayedOpenAcc pacc+rnfDelayedOpenAcc (Delayed sh ix lx) = rnfPreOpenExp rnfDelayedOpenAcc sh+                                 `seq` rnfPreOpenFun rnfDelayedOpenAcc ix+                                 `seq` rnfPreOpenFun rnfDelayedOpenAcc lx +{--+rnfDelayedSeq :: DelayedSeq t -> ()+rnfDelayedSeq (DelayedSeq env s) = rnfExtend rnfDelayedOpenAcc env+                             `seq` rnfPreOpenSeq rnfDelayedOpenAcc s +rnfExtend :: NFDataAcc acc -> Extend acc aenv aenv' -> ()+rnfExtend _    BaseEnv         = ()+rnfExtend rnfA (PushEnv env a) = rnfExtend rnfA env `seq` rnfA a+--}++ -- Note: If we detect that the delayed array is simply accessing an array -- variable, then just print the variable name. That is: --@@ -174,20 +243,42 @@ -- > let a0 = <...> in map f a0 -- prettyDelayed :: PrettyAcc DelayedOpenAcc-prettyDelayed alvl wrap acc = case acc of-  Manifest pacc         -> prettyPreAcc prettyDelayed alvl wrap pacc+prettyDelayed wrap aenv acc = case acc of+  Manifest pacc         -> prettyPreOpenAcc prettyDelayed wrap aenv pacc   Delayed sh f _     | Shape a           <- sh-    , Just REFL         <- match f (Lam (Body (Index a (Var ZeroIdx))))-    -> prettyDelayed alvl wrap a+    , Just Refl         <- match f (Lam (Body (Index a (Var ZeroIdx))))+    -> prettyDelayed wrap aenv a      | otherwise     -> wrap $ hang (text "Delayed") 2-            $ sep [ prettyPreExp prettyDelayed 0 alvl parens sh-                  , parens (prettyPreFun prettyDelayed alvl f)+            $ sep [ prettyPreExp prettyDelayed parens aenv sh+                  , parens (prettyPreFun prettyDelayed aenv f)                   ]  +{--+-- Pretty print delayed sequences+--+-- TLM: What is going on with this sequence thing, why is it closed?+--+prettyDelayedSeq+    :: (Doc -> Doc)                             -- apply to compound expressions+    -> DelayedSeq arrs+    -> Doc+prettyDelayedSeq wrap (DelayedSeq aenv s)+  | (d, lvl) <- pp env 0+  =  wrap $   (hang (text "let") 2 $ sep $ punctuate semi d)+          <+> (hang (text "in")  2 $ sep $ punctuate semi+                                         $ prettyPreSeq wrap prettyAcc lvl 0 s)+  where+    pp :: Extend DelayedOpenAcc aenv aenv' -> Int -> ([Doc], Int)+    pp BaseEnv          lvl = ([],lvl)+    pp (PushEnv env' a) lvl | (d', _) <- pp env' (lvl + 1)+                            = (prettyAcc lvl wrap a : d', lvl)+--}++ -- Environments -- ============ @@ -202,7 +293,7 @@            -> PreOpenExp acc env           aenv t            -> Gamma      acc env (env', t) aenv -incExp :: Gamma acc env env' aenv -> Gamma acc (env, s) env' aenv+incExp :: RebuildableAcc acc => Gamma acc env env' aenv -> Gamma acc (env, s) env' aenv incExp EmptyExp        = EmptyExp incExp (PushExp env e) = incExp env `PushExp` weakenE SuccIdx e @@ -211,9 +302,103 @@ prjExp (SuccIdx ix) (PushExp env _) = prjExp ix env prjExp _            _               = $internalError "prjExp" "inconsistent valuation" +weakenGamma1 :: Kit acc => Gamma acc env env' aenv -> Gamma acc env env' (aenv,t)+weakenGamma1 EmptyExp        = EmptyExp+weakenGamma1 (PushExp env e) = PushExp (weakenGamma1 env) (weaken SuccIdx e)++sinkGamma :: Kit acc => Extend acc aenv aenv' -> Gamma acc env env' aenv -> Gamma acc env env' aenv'+sinkGamma _   EmptyExp        = EmptyExp+sinkGamma ext (PushExp env e) = PushExp (sinkGamma ext env) (sink ext e)+ lookupExp :: Kit acc => Gamma acc env env' aenv -> PreOpenExp acc env aenv t -> Maybe (Idx env' t)-lookupExp EmptyExp        _       = Nothing+lookupExp EmptyExp        _ = Nothing lookupExp (PushExp env e) x-  | Just REFL <- match e x = Just ZeroIdx-  | otherwise              = SuccIdx `fmap` lookupExp env x+  | Just Refl <- match e x  = Just ZeroIdx+  | otherwise               = SuccIdx `fmap` lookupExp env x+++-- As part of various transformations we often need to lift out array valued+-- inputs to be let-bound at a higher point.+--+-- The Extend type is a heterogeneous snoc-list of array terms that witnesses+-- how the array environment is extended by binding these additional terms.+--+data Extend acc aenv aenv' where+  BaseEnv :: Extend acc aenv aenv++  PushEnv :: Arrays a+          => Extend acc aenv aenv' -> acc aenv' a -> Extend acc aenv (aenv', a)++-- Append two environment witnesses+--+append :: Extend acc env env' -> Extend acc env' env'' -> Extend acc env env''+append x BaseEnv        = x+append x (PushEnv as a) = x `append` as `PushEnv` a++-- Bring into scope all of the array terms in the Extend environment list. This+-- converts a term in the inner environment (aenv') into the outer (aenv).+--+bind :: (Kit acc, Arrays a)+     => Extend acc aenv aenv'+     -> PreOpenAcc acc aenv' a+     -> PreOpenAcc acc aenv  a+bind BaseEnv         = id+bind (PushEnv env a) = bind env . Alet a . inject++-- Sink a term from one array environment into another, where additional+-- bindings have come into scope according to the witness and no old things have+-- vanished.+--+sink :: Sink f => Extend acc env env' -> f env t -> f env' t+sink env = weaken (k env)+  where+    k :: Extend acc env env' -> Idx env t -> Idx env' t+    k BaseEnv       = Stats.substitution "sink" id+    k (PushEnv e _) = SuccIdx . k e++sink1 :: Sink f => Extend acc env env' -> f (env,s) t -> f (env',s) t+sink1 env = weaken (k env)+  where+    k :: Extend acc env env' -> Idx (env,s) t -> Idx (env',s) t+    k BaseEnv       = Stats.substitution "sink1" id+    k (PushEnv e _) = split . k e+    --+    split :: Idx (env,s) t -> Idx ((env,u),s) t+    split ZeroIdx      = ZeroIdx+    split (SuccIdx ix) = SuccIdx (SuccIdx ix)++-- This is the same as above, however for the scalar environment.+--+-- RCE: This is much the same as `Gamma` above. The main difference being that the expressions+-- stored in a `Gamma` can not depend on each other, whereas in `Supplement` they can. We should+-- perhaps look at using `Supplement` wherever possible.+--+data Supplement acc env env' aenv where+  BaseSup :: Supplement acc env env aenv+  PushSup :: Elt e+          => Supplement acc env env' aenv+          -> PreOpenExp acc env' aenv e+          -> Supplement acc env (env', e) aenv++bindExps :: (Kit acc, Elt e)+         => Supplement acc env env' aenv+         -> PreOpenExp acc env' aenv e+         -> PreOpenExp acc env aenv e+bindExps BaseSup       = id+bindExps (PushSup g b) = bindExps g . Let b++-- Application via let binding.+--+subApply :: (RebuildableAcc acc, Arrays a)+         => PreOpenAfun acc aenv (a -> b)+         -> acc             aenv a+         -> PreOpenAcc  acc aenv b+subApply (Alam (Abody f)) a = Alet a f+subApply _                _ = error "subApply: inconsistent evaluation"++-- | Replace all occurrences of the first variable with the given array+-- expression. The environment shrinks.+--+inlineA :: Rebuildable f => f (aenv,s) t -> PreOpenAcc (AccClo f) aenv s -> f aenv t+inlineA f g = Stats.substitution "inlineA" $ rebuildA (subAtop g) f 
Data/Array/Accelerate/Trafo/Fusion.hs view
@@ -1,7 +1,10 @@ {-# LANGUAGE CPP                  #-}+{-# LANGUAGE ConstraintKinds      #-}+{-# LANGUAGE FlexibleContexts     #-} {-# LANGUAGE FlexibleInstances    #-} {-# LANGUAGE GADTs                #-} {-# LANGUAGE IncoherentInstances  #-}+{-# LANGUAGE InstanceSigs         #-} {-# LANGUAGE PatternGuards        #-} {-# LANGUAGE RankNTypes           #-} {-# LANGUAGE ScopedTypeVariables  #-}@@ -9,14 +12,15 @@ {-# LANGUAGE TypeOperators        #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE ViewPatterns         #-}-{-# OPTIONS_GHC -fno-warn-name-shadowing      #-} {-# OPTIONS_GHC -fno-warn-incomplete-patterns #-}+{-# OPTIONS_GHC -fno-warn-name-shadowing      #-} -- | -- Module      : Data.Array.Accelerate.Trafo.Fusion--- Copyright   : [2012..2014] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2012..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+--               [2014..2014] Frederik M. Madsen -- License     : BSD3 ----- Maintainer  : Manuel M T Chakravarty <chak@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -52,8 +56,10 @@ import Data.Array.Accelerate.Trafo.Simplify import Data.Array.Accelerate.Trafo.Substitution import Data.Array.Accelerate.Array.Representation       ( SliceIndex(..) )-import Data.Array.Accelerate.Array.Sugar                ( Array, Arrays(..), ArraysR(..), ArrRepr', Elt, EltRepr, Shape )-import Data.Array.Accelerate.Tuple+import Data.Array.Accelerate.Array.Sugar                ( Array, Arrays(..), ArraysR(..), ArrRepr+                                                        , Elt, EltRepr, Shape, Tuple(..), Atuple(..)+                                                        , IsAtuple, TupleRepr )+import Data.Array.Accelerate.Product  import qualified Data.Array.Accelerate.Debug            as Stats #ifdef ACCELERATE_DEBUG@@ -74,6 +80,16 @@ convertAfun :: Bool -> Afun f -> DelayedAfun f convertAfun fuseAcc = withSimplStats . convertOpenAfun fuseAcc +-- -- | Apply the fusion transformation to the array computations embedded+-- --   in a sequence computation.+-- convertSeq :: Bool -> Seq a -> DelayedSeq a+-- convertSeq fuseAcc (embedSeq (embedOpenAcc fuseAcc) -> ExtendSeq aenv s)+--   = withSimplStats (DelayedSeq (cvtE aenv) (convertOpenSeq fuseAcc s))+--   where+--     cvtE :: Extend OpenAcc aenv aenv' -> Extend DelayedOpenAcc aenv aenv'+--     cvtE BaseEnv                                          = BaseEnv+--     cvtE (PushEnv env a) | a' <- convertOpenAcc fuseAcc a = PushEnv (cvtE env) a'+ withSimplStats :: a -> a #ifdef ACCELERATE_DEBUG withSimplStats x = unsafePerformIO Stats.resetSimplCount `seq` x@@ -97,105 +113,159 @@ --      encode this property in the type somehow... -- convertOpenAcc :: Arrays arrs => Bool -> OpenAcc aenv arrs -> DelayedOpenAcc aenv arrs-convertOpenAcc fuseAcc = manifest . computeAcc . embedOpenAcc fuseAcc+convertOpenAcc fuseAcc = manifest fuseAcc . computeAcc . embedOpenAcc fuseAcc++-- Convert array computations into an embeddable delayed representation.+-- Reapply the embedding function from the first pass and unpack the+-- representation. It is safe to match on BaseEnv because the first pass+-- will put producers adjacent to the term consuming it.+--+delayed :: (Shape sh, Elt e) => Bool -> OpenAcc aenv (Array sh e) -> DelayedOpenAcc aenv (Array sh e)+delayed fuseAcc (embedOpenAcc fuseAcc -> Embed BaseEnv cc) =+  case cc of+    Done v                                -> Delayed (arrayShape v) (indexArray v) (linearIndex v)+    Yield (cvtE -> sh) (cvtF -> f)        -> Delayed sh f (f `compose` fromIndex sh)+    Step  (cvtE -> sh) (cvtF -> p) (cvtF -> f) v+      | Just Refl <- match sh (arrayShape v)+      , Just Refl <- isIdentity p+      -> Delayed sh (f `compose` indexArray v) (f `compose` linearIndex v)++      | f'        <- f `compose` indexArray v `compose` p+      -> Delayed sh f' (f' `compose` fromIndex sh)   where-    -- Convert array computations into an embeddable delayed representation.-    -- Reapply the embedding function from the first pass and unpack the-    -- representation. It is safe to match on BaseEnv because the first pass-    -- will put producers adjacent to the term consuming it.+    cvtE :: OpenExp env aenv t -> DelayedOpenExp env aenv t+    cvtE = convertOpenExp fuseAcc++    cvtF :: OpenFun env aenv f -> DelayedOpenFun env aenv f+    cvtF (Lam f)  = Lam (cvtF f)+    cvtF (Body b) = Body (cvtE b)++-- Convert array programs as manifest terms.+--+manifest :: Bool -> OpenAcc aenv a -> DelayedOpenAcc aenv a+manifest fuseAcc (OpenAcc pacc) =+  let fusionError = $internalError "manifest" "unexpected fusible materials"+  in+  Manifest $ case pacc of+    -- Non-fusible terms+    -- -----------------+    Avar ix                 -> Avar ix+    Use arr                 -> Use arr+    Unit e                  -> Unit (cvtE e)+    Alet bnd body           -> alet (manifest fuseAcc bnd) (manifest fuseAcc body)+    Acond p t e             -> Acond (cvtE p) (manifest fuseAcc t) (manifest fuseAcc e)+    Awhile p f a            -> Awhile (cvtAF p) (cvtAF f) (manifest fuseAcc a)+    Atuple tup              -> Atuple (cvtAT tup)+    Aprj ix tup             -> Aprj ix (manifest fuseAcc tup)+    Apply f a               -> Apply (cvtAF f) (manifest fuseAcc a)+    Aforeign ff f a         -> Aforeign ff (cvtAF f) (manifest fuseAcc a)++    -- Producers+    -- ---------     ---    delayed :: (Shape sh, Elt e) => OpenAcc aenv (Array sh e) -> DelayedOpenAcc aenv (Array sh e)-    delayed (embedOpenAcc fuseAcc -> Embed BaseEnv cc) =-      case cc of-        Done v                                -> Delayed (arrayShape v) (indexArray v) (linearIndex v)-        Yield (cvtE -> sh) (cvtF -> f)        -> Delayed sh f (f `compose` fromIndex sh)-        Step  (cvtE -> sh) (cvtF -> p) (cvtF -> f) v-          | Just REFL <- match sh (arrayShape v)-          , Just REFL <- isIdentity p-          -> Delayed sh (f `compose` indexArray v) (f `compose` linearIndex v)+    -- Some producers might still exist as a manifest array. Typically+    -- this is because they are the last stage of the computation, or the+    -- result of a let-binding to be used multiple times. The input array+    -- here should be an array variable, else something went wrong.+    --+    Map f a                 -> Map (cvtF f) (delayed fuseAcc a)+    Generate sh f           -> Generate (cvtE sh) (cvtF f)+    Transform sh p f a      -> Transform (cvtE sh) (cvtF p) (cvtF f) (delayed fuseAcc a)+    Backpermute sh p a      -> Backpermute (cvtE sh) (cvtF p) (delayed fuseAcc a)+    Reshape sl a            -> Reshape (cvtE sl) (manifest fuseAcc a) -          | f'        <- f `compose` indexArray v `compose` p-          -> Delayed sh f' (f' `compose` fromIndex sh)+    Replicate{}             -> fusionError+    Slice{}                 -> fusionError+    ZipWith{}               -> fusionError -    -- Convert array programs as manifest terms.+    -- Consumers+    -- ---------     ---    manifest :: OpenAcc aenv a -> DelayedOpenAcc aenv a-    manifest (OpenAcc pacc) =-      let fusionError = $internalError "manifest" "unexpected fusible materials"-      in-      Manifest $ case pacc of-        -- Non-fusible terms-        -- ------------------        Avar ix                 -> Avar ix-        Use arr                 -> Use arr-        Unit e                  -> Unit (cvtE e)-        Alet bnd body           -> alet (manifest bnd) (manifest body)-        Acond p t e             -> Acond (cvtE p) (manifest t) (manifest e)-        Awhile p f a            -> Awhile (cvtAF p) (cvtAF f) (manifest a)-        Atuple tup              -> Atuple (cvtAT tup)-        Aprj ix tup             -> Aprj ix (manifest tup)-        Apply f a               -> Apply (cvtAF f) (manifest a)-        Aforeign ff f a         -> Aforeign ff (cvtAF f) (manifest a)+    -- Embed producers directly into the representation. For stencils we+    -- make an exception. Since these consumers access elements of the+    -- argument array multiple times, we are careful not to duplicate work+    -- and instead force the argument to be a manifest array.+    --+    Fold f z a              -> Fold     (cvtF f) (cvtE z) (delayed fuseAcc a)+    Fold1 f a               -> Fold1    (cvtF f) (delayed fuseAcc a)+    FoldSeg f z a s         -> FoldSeg  (cvtF f) (cvtE z) (delayed fuseAcc a) (delayed fuseAcc s)+    Fold1Seg f a s          -> Fold1Seg (cvtF f) (delayed fuseAcc a) (delayed fuseAcc s)+    Scanl f z a             -> Scanl    (cvtF f) (cvtE z) (delayed fuseAcc a)+    Scanl1 f a              -> Scanl1   (cvtF f) (delayed fuseAcc a)+    Scanl' f z a            -> Scanl'   (cvtF f) (cvtE z) (delayed fuseAcc a)+    Scanr f z a             -> Scanr    (cvtF f) (cvtE z) (delayed fuseAcc a)+    Scanr1 f a              -> Scanr1   (cvtF f) (delayed fuseAcc a)+    Scanr' f z a            -> Scanr'   (cvtF f) (cvtE z) (delayed fuseAcc a)+    Permute f d p a         -> Permute  (cvtF f) (manifest fuseAcc d) (cvtF p) (delayed fuseAcc a)+    Stencil f x a           -> Stencil  (cvtF f) x (manifest fuseAcc a)+    Stencil2 f x a y b      -> Stencil2 (cvtF f) x (manifest fuseAcc a) y (manifest fuseAcc b)+    -- Collect s               -> Collect  (cvtS s) -        -- Producers-        -- ----------        ---        -- Some producers might still exist as a manifest array. Typically-        -- this is because they are the last stage of the computation, or the-        -- result of a let-binding to be used multiple times. The input array-        -- here should be an array variable, else something went wrong.-        ---        Map f a                 -> Map (cvtF f) (delayed a)-        Generate sh f           -> Generate (cvtE sh) (cvtF f)-        Transform sh p f a      -> Transform (cvtE sh) (cvtF p) (cvtF f) (delayed a)-        Backpermute sh p a      -> Backpermute (cvtE sh) (cvtF p) (delayed a)-        Reshape sl a            -> Reshape (cvtE sl) (manifest a)+    where+      -- Flatten needless let-binds, which can be introduced by the conversion to+      -- the internal embeddable representation.+      --+      alet bnd body+        | Manifest (Avar ZeroIdx) <- body+        , Manifest x              <- bnd+        = x -        Replicate{}             -> fusionError-        Slice{}                 -> fusionError-        ZipWith{}               -> fusionError+        | otherwise+        = Alet bnd body -        -- Consumers-        -- ----------        ---        -- Embed producers directly into the representation. For stencils we-        -- make an exception. Since these consumers access elements of the-        -- argument array multiple times, we are careful not to duplicate work-        -- and instead force the argument to be a manifest array.-        ---        Fold f z a              -> Fold     (cvtF f) (cvtE z) (delayed a)-        Fold1 f a               -> Fold1    (cvtF f) (delayed a)-        FoldSeg f z a s         -> FoldSeg  (cvtF f) (cvtE z) (delayed a) (delayed s)-        Fold1Seg f a s          -> Fold1Seg (cvtF f) (delayed a) (delayed s)-        Scanl f z a             -> Scanl    (cvtF f) (cvtE z) (delayed a)-        Scanl1 f a              -> Scanl1   (cvtF f) (delayed a)-        Scanl' f z a            -> Scanl'   (cvtF f) (cvtE z) (delayed a)-        Scanr f z a             -> Scanr    (cvtF f) (cvtE z) (delayed a)-        Scanr1 f a              -> Scanr1   (cvtF f) (delayed a)-        Scanr' f z a            -> Scanr'   (cvtF f) (cvtE z) (delayed a)-        Permute f d p a         -> Permute  (cvtF f) (manifest d) (cvtF p) (delayed a)-        Stencil f x a           -> Stencil  (cvtF f) x (manifest a)-        Stencil2 f x a y b      -> Stencil2 (cvtF f) x (manifest a) y (manifest b)+      cvtAT :: Atuple (OpenAcc aenv) a -> Atuple (DelayedOpenAcc aenv) a+      cvtAT NilAtup        = NilAtup+      cvtAT (SnocAtup t a) = cvtAT t `SnocAtup` manifest fuseAcc a -    -- Flatten needless let-binds, which can be introduced by the conversion to-    -- the internal embeddable representation.-    ---    alet bnd body-      | Manifest (Avar ZeroIdx) <- body-      , Manifest x              <- bnd-      = x+      cvtAF :: OpenAfun aenv f -> PreOpenAfun DelayedOpenAcc aenv f+      cvtAF (Alam f)  = Alam  (cvtAF f)+      cvtAF (Abody b) = Abody (manifest fuseAcc b) -      | otherwise-      = Alet bnd body+      -- cvtS :: PreOpenSeq OpenAcc aenv senv s -> PreOpenSeq DelayedOpenAcc aenv senv s+      -- cvtS = convertOpenSeq fuseAcc -    cvtAT :: Atuple (OpenAcc aenv) a -> Atuple (DelayedOpenAcc aenv) a-    cvtAT NilAtup        = NilAtup-    cvtAT (SnocAtup t a) = cvtAT t `SnocAtup` manifest a+      -- Conversions for closed scalar functions and expressions+      --+      cvtF :: OpenFun env aenv f -> DelayedOpenFun env aenv f+      cvtF (Lam f)  = Lam (cvtF f)+      cvtF (Body b) = Body (cvtE b) -    cvtAF :: OpenAfun aenv f -> PreOpenAfun DelayedOpenAcc aenv f-    cvtAF (Alam f)  = Alam  (cvtAF f)-    cvtAF (Abody b) = Abody (manifest b)+      cvtE :: OpenExp env aenv t -> DelayedOpenExp env aenv t+      cvtE = convertOpenExp fuseAcc +convertOpenExp :: Bool -> OpenExp env aenv t -> DelayedOpenExp env aenv t+convertOpenExp fuseAcc exp =+  case exp of+    Let bnd body            -> Let (cvtE bnd) (cvtE body)+    Var ix                  -> Var ix+    Const c                 -> Const c+    Tuple tup               -> Tuple (cvtT tup)+    Prj ix t                -> Prj ix (cvtE t)+    IndexNil                -> IndexNil+    IndexCons sh sz         -> IndexCons (cvtE sh) (cvtE sz)+    IndexHead sh            -> IndexHead (cvtE sh)+    IndexTail sh            -> IndexTail (cvtE sh)+    IndexAny                -> IndexAny+    IndexSlice x ix sh      -> IndexSlice x (cvtE ix) (cvtE sh)+    IndexFull x ix sl       -> IndexFull x (cvtE ix) (cvtE sl)+    ToIndex sh ix           -> ToIndex (cvtE sh) (cvtE ix)+    FromIndex sh ix         -> FromIndex (cvtE sh) (cvtE ix)+    Cond p t e              -> Cond (cvtE p) (cvtE t) (cvtE e)+    While p f x             -> While (cvtF p) (cvtF f) (cvtE x)+    PrimConst c             -> PrimConst c+    PrimApp f x             -> PrimApp f (cvtE x)+    Index a sh              -> Index (manifest fuseAcc a) (cvtE sh)+    LinearIndex a i         -> LinearIndex (manifest fuseAcc a) (cvtE i)+    Shape a                 -> Shape (manifest fuseAcc a)+    ShapeSize sh            -> ShapeSize (cvtE sh)+    Intersect s t           -> Intersect (cvtE s) (cvtE t)+    Union s t               -> Union (cvtE s) (cvtE t)+    Foreign ff f e          -> Foreign ff (cvtF f) (cvtE e)+  where+    cvtT :: Tuple (OpenExp env aenv) t -> Tuple (DelayedOpenExp env aenv) t+    cvtT NilTup        = NilTup+    cvtT (SnocTup t e) = cvtT t `SnocTup` cvtE e+     -- Conversions for closed scalar functions and expressions     --     cvtF :: OpenFun env aenv f -> DelayedOpenFun env aenv f@@ -203,43 +273,53 @@     cvtF (Body b) = Body (cvtE b)      cvtE :: OpenExp env aenv t -> DelayedOpenExp env aenv t-    cvtE exp =-      case exp of-        Let bnd body            -> Let (cvtE bnd) (cvtE body)-        Var ix                  -> Var ix-        Const c                 -> Const c-        Tuple tup               -> Tuple (cvtT tup)-        Prj ix t                -> Prj ix (cvtE t)-        IndexNil                -> IndexNil-        IndexCons sh sz         -> IndexCons (cvtE sh) (cvtE sz)-        IndexHead sh            -> IndexHead (cvtE sh)-        IndexTail sh            -> IndexTail (cvtE sh)-        IndexAny                -> IndexAny-        IndexSlice x ix sh      -> IndexSlice x (cvtE ix) (cvtE sh)-        IndexFull x ix sl       -> IndexFull x (cvtE ix) (cvtE sl)-        ToIndex sh ix           -> ToIndex (cvtE sh) (cvtE ix)-        FromIndex sh ix         -> FromIndex (cvtE sh) (cvtE ix)-        Cond p t e              -> Cond (cvtE p) (cvtE t) (cvtE e)-        While p f x             -> While (cvtF p) (cvtF f) (cvtE x)-        PrimConst c             -> PrimConst c-        PrimApp f x             -> PrimApp f (cvtE x)-        Index a sh              -> Index (manifest a) (cvtE sh)-        LinearIndex a i         -> LinearIndex (manifest a) (cvtE i)-        Shape a                 -> Shape (manifest a)-        ShapeSize sh            -> ShapeSize (cvtE sh)-        Intersect s t           -> Intersect (cvtE s) (cvtE t)-        Foreign ff f e          -> Foreign ff (cvtF f) (cvtE e)--    cvtT :: Tuple (OpenExp env aenv) t -> Tuple (DelayedOpenExp env aenv) t-    cvtT NilTup        = NilTup-    cvtT (SnocTup t e) = cvtT t `SnocTup` cvtE e+    cvtE = convertOpenExp fuseAcc   convertOpenAfun :: Bool -> OpenAfun aenv f -> DelayedOpenAfun aenv f convertOpenAfun c (Alam  f) = Alam  (convertOpenAfun c f) convertOpenAfun c (Abody b) = Abody (convertOpenAcc  c b) +{--+convertOpenSeq :: Bool -> PreOpenSeq OpenAcc aenv senv a -> PreOpenSeq DelayedOpenAcc aenv senv a+convertOpenSeq fuseAcc s =+  case s of+    Consumer c          -> Consumer (cvtC c)+    Reify ix            -> Reify ix+    Producer p s'       -> Producer p' (convertOpenSeq fuseAcc s')+      where+        p' = case p of+               StreamIn arrs     -> StreamIn arrs+               ToSeq slix sh a   -> ToSeq slix sh (delayed fuseAcc a)+               MapSeq f x        -> MapSeq (cvtAF f) x+               ChunkedMapSeq f x -> ChunkedMapSeq (cvtAF f) x+               ZipWithSeq f x y  -> ZipWithSeq (cvtAF f) x y+               ScanSeq f e x     -> ScanSeq (cvtF f) (cvtE e) x+  where+    cvtC :: Consumer OpenAcc aenv senv a -> Consumer DelayedOpenAcc aenv senv a+    cvtC c =+      case c of+        FoldSeq f e x        -> FoldSeq (cvtF f) (cvtE e) x+        FoldSeqFlatten f a x -> FoldSeqFlatten (cvtAF f) (manifest fuseAcc a) x+        Stuple t             -> Stuple (cvtCT t) +    cvtCT :: Atuple (Consumer OpenAcc aenv senv) t -> Atuple (Consumer DelayedOpenAcc aenv senv) t+    cvtCT NilAtup        = NilAtup+    cvtCT (SnocAtup t c) = SnocAtup (cvtCT t) (cvtC c)++    cvtAF :: OpenAfun aenv f -> PreOpenAfun DelayedOpenAcc aenv f+    cvtAF (Alam f)  = Alam  (cvtAF f)+    cvtAF (Abody b) = Abody (manifest fuseAcc b)++    cvtE :: OpenExp env aenv t -> DelayedOpenExp env aenv t+    cvtE = convertOpenExp fuseAcc++    cvtF :: OpenFun env aenv f -> DelayedOpenFun env aenv f+    cvtF (Lam f)  = Lam (cvtF f)+    cvtF (Body b) = Body (cvtE b)+--}++ -- | Apply the fusion transformation to the AST to combine and simplify terms. -- This converts terms into the internal delayed array representation and merges -- adjacent producer/producer terms. Using the reduced internal form limits the@@ -255,29 +335,19 @@     -- When does the cost of re-computation outweigh that of memory access? For     -- the moment only do the substitution on a single use of the bound array     -- into the use site, but it is likely advantageous to be far more-    -- aggressive here. SEE: [Sharing vs. Fusion]+    -- aggressive here.     ---    -- As a special case, look for the definition of 'unzip' applied to manifest-    -- data, which is defined in the prelude as a map projecting out the-    -- appropriate element.+    -- SEE: [Sharing vs. Fusion]     --     elimOpenAcc :: ElimAcc OpenAcc-    elimOpenAcc bnd body-      | Map f a                 <- extract bnd-      , Avar _                  <- extract a-      , Lam (Body (Prj _ _))    <- f-      = Stats.ruleFired "unzipD" True--      | count False ZeroIdx body <= lIMIT-      = True--      | otherwise-      = False+    elimOpenAcc _bnd body+      | count False ZeroIdx body <= lIMIT = True+      | otherwise                         = False       where         lIMIT = 1          count :: UsesOfAcc OpenAcc-        count ok idx (OpenAcc pacc) = usesOfPreAcc ok count idx pacc+        count no ix (OpenAcc pacc) = usesOfPreAcc no count ix pacc   embedPreAcc@@ -294,19 +364,20 @@     -- Non-fusible terms     -- -----------------     ---    -- Solid and semi-solid terms that we generally do not which to fuse, such+    -- Solid and semi-solid terms that we generally do not wish to fuse, such     -- as control flow (|?), array introduction (use, unit), array tupling and     -- projection, and foreign function operations. Generally we also do not     -- want to fuse past array let bindings, as this would imply work     -- duplication. SEE: [Sharing vs. Fusion]     --+    Apply f a           -> applyD (cvtAF f) (cvtA a)     Alet bnd body       -> aletD embedAcc elimAcc bnd body-    Acond p at ae       -> acondD embedAcc (cvtE p) at ae     Aprj ix tup         -> aprjD embedAcc ix tup+    Acond p at ae       -> acondD embedAcc (cvtE p) at ae     Awhile p f a        -> done $ Awhile (cvtAF p) (cvtAF f) (cvtA a)     Atuple tup          -> done $ Atuple (cvtAT tup)-    Apply f a           -> done $ Apply (cvtAF f) (cvtA a)     Aforeign ff f a     -> done $ Aforeign ff (cvtAF f) (cvtA a)+    -- Collect s           -> collectD s      -- Array injection     Avar v              -> done $ Avar v@@ -328,13 +399,13 @@     --     Generate sh f       -> generateD (cvtE sh) (cvtF f) -    Map f a             -> fuse  (into  mapD              (cvtF f)) a-    ZipWith f a b       -> fuse2 (into  zipWithD          (cvtF f)) a b-    Transform sh p f a  -> fuse  (into3 transformD        (cvtE sh) (cvtF p) (cvtF f)) a+    Map f a             -> mapD (cvtF f) (embedAcc a)+    ZipWith f a b       -> fuse2 (into zipWithD (cvtF f)) a b+    Transform sh p f a  -> transformD (cvtE sh) (cvtF p) (cvtF f) (embedAcc a) -    Backpermute sl p a  -> fuse  (into2 backpermuteD      (cvtE sl) (cvtF p)) a-    Slice slix a sl     -> fuse  (into  (sliceD slix)     (cvtE sl)) a-    Replicate slix sh a -> fuse  (into  (replicateD slix) (cvtE sh)) a+    Backpermute sl p a  -> fuse (into2 backpermuteD      (cvtE sl) (cvtF p)) a+    Slice slix a sl     -> fuse (into  (sliceD slix)     (cvtE sl)) a+    Replicate slix sh a -> fuse (into  (replicateD slix) (cvtE sh)) a     Reshape sl a        -> reshapeD (embedAcc a) (cvtE sl)      -- Consumers@@ -364,8 +435,8 @@     Scanr1 f a          -> embed  (into  Scanr1        (cvtF f)) a     Scanr' f z a        -> embed  (into2 Scanr'        (cvtF f) (cvtE z)) a     Permute f d p a     -> embed2 (into2 permute       (cvtF f) (cvtF p)) d a-    Stencil f x a       -> embed  (into (stencil x)    (cvtF f)) a-    Stencil2 f x a y b  -> embed2 (into (stencil2 x y) (cvtF f)) a b+    Stencil f x a       -> lift   (into (stencil x)    (cvtF f)) a+    Stencil2 f x a y b  -> lift2  (into (stencil2 x y) (cvtF f)) a b    where     -- If fusion is not enabled, force terms to the manifest representation@@ -398,7 +469,7 @@     cvtF :: PreFun acc aenv t -> PreFun acc aenv t     cvtF = simplify -    cvtE :: PreExp acc aenv' t -> PreExp acc aenv' t+    cvtE :: Elt t =>PreExp acc aenv' t -> PreExp acc aenv' t     cvtE = simplify      -- Helpers to embed and fuse delayed terms@@ -410,10 +481,6 @@           => (f1 env' a -> f2 env' b -> c) -> f1 env a -> f2 env b -> Extend acc env env' -> c     into2 op a b env = op (sink env a) (sink env b) -    into3 :: (Sink f1, Sink f2, Sink f3)-          => (f1 env' a -> f2 env' b -> f3 env' c -> d) -> f1 env a -> f2 env b -> f3 env c -> Extend acc env env' -> d-    into3 op a b c env = op (sink env a) (sink env b) (sink env c)-     fuse :: Arrays as          => (forall aenv'. Extend acc aenv aenv' -> Cunctation acc aenv' as -> Cunctation acc aenv' bs)          ->       acc aenv as@@ -435,21 +502,157 @@           => (forall aenv'. Extend acc aenv aenv' -> acc aenv' as -> PreOpenAcc acc aenv' bs)           ->       acc aenv as           -> Embed acc aenv bs-    embed op (embedAcc -> Embed env cc)-      = Embed (env `PushEnv` op env (inject (compute' cc))) (Done ZeroIdx)+    embed = trav1 id      embed2 :: forall aenv as bs cs. (Arrays as, Arrays bs, Arrays cs)            => (forall aenv'. Extend acc aenv aenv' -> acc aenv' as -> acc aenv' bs -> PreOpenAcc acc aenv' cs)            ->       acc aenv as            ->       acc aenv bs            -> Embed acc aenv cs-    embed2 op (embedAcc -> Embed env1 cc1) (embedAcc . sink env1 -> Embed env0 cc0)+    embed2 = trav2 id id++    lift :: (Arrays as, Arrays bs)+         => (forall aenv'. Extend acc aenv aenv' -> acc aenv' as -> PreOpenAcc acc aenv' bs)+         ->       acc aenv as+         -> Embed acc aenv bs+    lift = trav1 bind++    lift2 :: forall aenv as bs cs. (Arrays as, Arrays bs, Arrays cs)+          => (forall aenv'. Extend acc aenv aenv' -> acc aenv' as -> acc aenv' bs -> PreOpenAcc acc aenv' cs)+          ->       acc aenv as+          ->       acc aenv bs+          -> Embed acc aenv cs+    lift2 = trav2 bind bind++    trav1 :: (Arrays as, Arrays bs)+          => (forall aenv'. Embed acc aenv' as -> Embed acc aenv' as)+          -> (forall aenv'. Extend acc aenv aenv' -> acc aenv' as -> PreOpenAcc acc aenv' bs)+          ->       acc aenv as+          -> Embed acc aenv bs+    trav1 f op (f . embedAcc -> Embed env cc)+      = Embed (env `PushEnv` inject (op env (inject (compute' cc)))) (Done ZeroIdx)++    trav2 :: forall aenv as bs cs. (Arrays as, Arrays bs, Arrays cs)+          => (forall aenv'. Embed acc aenv' as -> Embed acc aenv' as)+          -> (forall aenv'. Embed acc aenv' bs -> Embed acc aenv' bs)+          -> (forall aenv'. Extend acc aenv aenv' -> acc aenv' as -> acc aenv' bs -> PreOpenAcc acc aenv' cs)+          ->       acc aenv as+          ->       acc aenv bs+          -> Embed acc aenv cs+    trav2 f1 f0 op (f1 . embedAcc -> Embed env1 cc1) (f0 . embedAcc . sink env1 -> Embed env0 cc0)       | env     <- env1 `append` env0       , acc1    <- inject . compute' $ sink env0 cc1       , acc0    <- inject . compute' $ cc0-      = Embed (env `PushEnv` op env acc1 acc0) (Done ZeroIdx)+      = Embed (env `PushEnv` inject (op env acc1 acc0)) (Done ZeroIdx) +    -- Helper functions to lift out and let-bind a manifest array. That is,+    -- instead of the sequence+    --+    -- > stencil s (map f a)+    --+    -- we get:+    --+    -- > let a' = map f a+    -- > in  stencil s a'+    --+    -- This is required for the LLVM backend's default implementation of+    -- stencil operations.+    --+    bind :: Arrays as => Embed acc aenv' as -> Embed acc aenv' as+    bind (Embed env cc)+      | Done{} <- cc = Embed env                                  cc+      | otherwise    = Embed (env `PushEnv` inject (compute' cc)) (Done ZeroIdx) +    -- -- Move additional bindings for producers outside of the sequence, so that+    -- -- producers may fuse with their arguments resulting in actual sequencing+    -- collectD :: PreOpenSeq acc aenv () arrs+    --          -> Embed acc aenv arrs+    -- collectD (embedSeq embedAcc -> ExtendSeq env s')+    --   = Embed (env `PushEnv` inject (Collect s')) (Done ZeroIdx)+++{--+-- Move additional bindings for producer outside of sequence, so+-- that producers may fuse with their arguments, resulting in+-- actual sequencing.+embedSeq :: forall acc aenv arrs. Kit acc+         => EmbedAcc acc+         -> PreOpenSeq acc aenv () arrs+         -> ExtendSeq       acc aenv () arrs+embedSeq embedAcc s+  = travS s BaseEnv+  where+    travS :: forall senv aenv' arrs'.+             PreOpenSeq acc aenv senv arrs'+          -> Extend acc aenv aenv'+          -> ExtendSeq acc aenv senv arrs'+    travS s env =+      case s of+        Producer p s+          | ExtendSeq env' s' <- travS s env+          , ExtendProducer env'' p' <- travP p env'+          -> ExtendSeq (env' `append` env'') (Producer p' (sinkSeq env'' s'))+        Consumer c+          | c' <- travC c env+          -> ExtendSeq env (Consumer c')+        Reify ix+          -> ExtendSeq env (Reify ix)++    travP :: forall arrs' aenv' senv.+             Producer acc aenv senv arrs'+          -> Extend acc aenv aenv'+          -> ExtendProducer acc aenv' senv arrs'+    travP (ToSeq slix sh a) env+      | Embed env' cc <- embedAcc (sink env a)+      = ExtendProducer env' (ToSeq slix sh (inject (compute' cc)))+    travP (StreamIn arrs) _          = ExtendProducer BaseEnv (StreamIn arrs)+    travP (MapSeq f x) env           = ExtendProducer BaseEnv (MapSeq (cvtAF (sink env f)) x)+    travP (ChunkedMapSeq f x) env    = ExtendProducer BaseEnv (ChunkedMapSeq (cvtAF (sink env f)) x)+    travP (ZipWithSeq f x y) env     = ExtendProducer BaseEnv (ZipWithSeq (cvtAF (sink env f)) x y)+    travP (ScanSeq f e x) env        = ExtendProducer BaseEnv (ScanSeq (cvtF (sink env f)) (cvtE (sink env e)) x)++    travC :: forall arrs' aenv' senv.+             Consumer acc aenv senv arrs'+          -> Extend acc aenv aenv'+          -> Consumer acc aenv' senv arrs'+    travC (FoldSeq f e x) env = FoldSeq (cvtF (sink env f)) (cvtE (sink env e)) x+    travC (FoldSeqFlatten f a x) env = FoldSeqFlatten (cvtAF (sink env f)) (cvtA (sink env a)) x+    travC (Stuple t) env = Stuple (cvtCT t)+      where+        cvtCT :: Atuple (Consumer acc aenv senv) t -> Atuple (Consumer acc aenv' senv) t+        cvtCT NilAtup        = NilAtup+        cvtCT (SnocAtup t c) = SnocAtup (cvtCT t) (travC c env)++    cvtE :: Elt t => PreExp acc aenv' t -> PreExp acc aenv' t+    cvtE = simplify++    cvtF :: PreFun acc aenv' t -> PreFun acc aenv' t+    cvtF = simplify++    cvtA :: Arrays a => acc aenv' a -> acc aenv' a+    cvtA = computeAcc . embedAcc++    cvtAF :: PreOpenAfun acc aenv' f -> PreOpenAfun acc aenv' f+    cvtAF (Alam  f) = Alam  (cvtAF f)+    cvtAF (Abody a) = Abody (cvtA a)+++-- A sequence with additional bindings+data ExtendSeq acc aenv senv arrs where+  ExtendSeq :: forall acc aenv aenv' senv arrs.+                Extend acc aenv aenv'+             -> PreOpenSeq acc aenv' senv arrs+             -> ExtendSeq acc aenv senv arrs++-- A producer with additional bindings+data ExtendProducer acc aenv senv arrs where+  ExtendProducer :: forall acc aenv aenv' senv arrs.+                    Extend acc aenv aenv'+                 -> Producer acc aenv' senv arrs+                 -> ExtendProducer acc aenv senv arrs+--}++ -- Internal representation -- ======================= @@ -536,10 +739,10 @@  -- Convert a real AST node into the internal representation ---done :: Arrays a => PreOpenAcc acc aenv a -> Embed acc aenv a+done :: (Arrays a, Kit acc) => PreOpenAcc acc aenv a -> Embed acc aenv a done pacc-  | Avar v <- pacc      = Embed BaseEnv                  (Done v)-  | otherwise           = Embed (BaseEnv `PushEnv` pacc) (Done ZeroIdx)+  | Avar v <- pacc      = Embed BaseEnv                         (Done v)+  | otherwise           = Embed (BaseEnv `PushEnv` inject pacc) (Done ZeroIdx)   -- Recast a cunctation into a mapping from indices to elements.@@ -552,7 +755,7 @@     Yield{}                             -> cc     Step sh p f v                       -> Yield sh (f `compose` indexArray v `compose` p)     Done v-      | ArraysRarray <- accType' cc     -> Yield (arrayShape v) (indexArray v)+      | ArraysRarray <- accType cc      -> Yield (arrayShape v) (indexArray v)       | otherwise                       -> error "yield: impossible case"  @@ -567,7 +770,7 @@     Yield{}                             -> Nothing     Step{}                              -> Just cc     Done v-      | ArraysRarray <- accType' cc     -> Just $ Step (arrayShape v) identity identity v+      | ArraysRarray <- accType cc      -> Just $ Step (arrayShape v) identity identity v       | otherwise                       -> error "step: impossible case"  @@ -581,99 +784,66 @@  -- Reified type of a delayed array representation. ---accType' :: forall acc aenv a. Arrays a => Cunctation acc aenv a -> ArraysR (ArrRepr' a)-accType' _ = arrays' (undefined :: a)+accType :: forall acc aenv a. Arrays a => Cunctation acc aenv a -> ArraysR (ArrRepr a)+accType _ = arrays (undefined :: a)   -- Environment manipulation -- ======================== --- NOTE: [Extend]------ As part of the fusion transformation we often need to lift out array valued--- inputs to be let-bound at a higher point. We can't add these directly to the--- output array term because these would interfere with further fusion steps.------ The Extend type is a heterogeneous snoc-list of array terms that witnesses--- how the array environment is extend by binding these additional terms.----data Extend acc aenv aenv' where-  BaseEnv :: Extend acc aenv aenv--  PushEnv :: Arrays a-          => Extend acc aenv aenv' -> PreOpenAcc acc aenv' a -> Extend acc aenv (aenv', a)----- Append two environment witnesses----append :: Extend acc env env' -> Extend acc env' env'' -> Extend acc env env''-append x BaseEnv        = x-append x (PushEnv as a) = x `append` as `PushEnv` a---- Bring into scope all of the array terms in the Extend environment list. This--- converts a term in the inner environment (aenv') into the outer (aenv).----bind :: (Kit acc, Arrays a)-     => Extend acc aenv aenv'-     -> PreOpenAcc acc aenv' a-     -> PreOpenAcc acc aenv  a-bind BaseEnv         = id-bind (PushEnv env a) = bind env . Alet (inject a) . inject-+instance Kit acc => Sink (Cunctation acc) where+  weaken k cc = case cc of+    Done v              -> Done (weaken k v)+    Step sh p f v       -> Step (weaken k sh) (weaken k p) (weaken k f) (weaken k v)+    Yield sh f          -> Yield (weaken k sh) (weaken k f)  -- prjExtend :: Kit acc => Extend acc env env' -> Idx env' t -> PreOpenAcc acc env' t -- prjExtend (PushEnv _   v) ZeroIdx       = weakenA rebuildAcc SuccIdx v -- prjExtend (PushEnv env _) (SuccIdx idx) = weakenA rebuildAcc SuccIdx $ prjExtend env idx -- prjExtend _               _             = $internalError "prjExtend" "inconsistent valuation" ---- Sink a term from one array environment into another, where additional--- bindings have come into scope according to the witness and no old things have--- vanished.----sink :: Sink f => Extend acc env env' -> f env t -> f env' t-sink env = weaken (k env)-  where-    k :: Extend acc env env' -> Idx env t -> Idx env' t-    k BaseEnv       = Stats.substitution "sink" id-    k (PushEnv e _) = SuccIdx . k e--sink1 :: Sink f => Extend acc env env' -> f (env,s) t -> f (env',s) t-sink1 env = weaken (k env)-  where-    k :: Extend acc env env' -> Idx (env,s) t -> Idx (env',s) t-    k BaseEnv       = Stats.substitution "sink1" id-    k (PushEnv e _) = split . k e-    ---    split :: Idx (env,s) t -> Idx ((env,u),s) t-    split ZeroIdx      = ZeroIdx-    split (SuccIdx ix) = SuccIdx (SuccIdx ix)---class Sink f where-  weaken :: env :> env' -> f env t -> f env' t--instance Sink Idx where-  weaken k = k--instance Kit acc => Sink (PreOpenExp acc env) where-  weaken k = weakenEA rebuildAcc k+{--+-- Rearrange type arguments to fit with Sink type class.+newtype SinkSeq acc senv aenv a = SinkSeq { unSinkSeq :: PreOpenSeq acc aenv senv a } -instance Kit acc => Sink (PreOpenFun acc env) where-  weaken k = weakenFA rebuildAcc k+-- sink for sequences.+sinkSeq :: Kit acc => Extend acc aenv aenv' -> PreOpenSeq acc aenv senv a -> PreOpenSeq acc aenv' senv a+sinkSeq env s = unSinkSeq $ sink env (SinkSeq s) -instance Kit acc => Sink (PreOpenAcc acc) where-  weaken k = weakenA rebuildAcc k+instance Kit acc => Sink (SinkSeq acc senv) where+  weaken :: forall aenv aenv' arrs. aenv :> aenv' -> SinkSeq acc senv aenv arrs -> SinkSeq acc senv aenv' arrs+  weaken k (SinkSeq s) = SinkSeq $+    case s of+      Producer p s' -> Producer   (weakenP p) (weakenL s')+      Consumer c    -> Consumer   (weakenC c)+      Reify ix      -> Reify      ix -instance Kit acc => Sink acc where-  weaken k = rebuildAcc (Avar . k)+    where+      weakenL :: forall senv' arrs'. PreOpenSeq acc aenv senv' arrs' -> PreOpenSeq acc aenv' senv' arrs'+      weakenL s' = unSinkSeq (weaken k (SinkSeq s')) -instance Kit acc => Sink (Cunctation acc) where-  weaken k cc = case cc of-    Done v              -> Done (weaken k v)-    Step sh p f v       -> Step (weaken k sh) (weaken k p) (weaken k f) (weaken k v)-    Yield sh f          -> Yield (weaken k sh) (weaken k f)+      weakenP :: forall a. Producer acc aenv senv a -> Producer acc aenv' senv a+      weakenP p =+        case p of+          StreamIn arrs        -> StreamIn arrs+          ToSeq slix sh a      -> ToSeq slix sh (weaken k a)+          MapSeq f x           -> MapSeq (weaken k f) x+          ChunkedMapSeq f x    -> ChunkedMapSeq (weaken k f) x+          ZipWithSeq f x y     -> ZipWithSeq (weaken k f) x y+          ScanSeq f a x        -> ScanSeq (weaken k f) (weaken k a) x +      weakenC :: forall a. Consumer acc aenv senv a -> Consumer acc aenv' senv a+      weakenC c =+        case c of+          FoldSeq f a x        -> FoldSeq (weaken k f) (weaken k a) x+          FoldSeqFlatten f a x -> FoldSeqFlatten (weaken k f) (weaken k a) x+          Stuple t             ->+            let wk :: Atuple (Consumer acc aenv senv) t -> Atuple (Consumer acc aenv' senv) t+                wk NilAtup        = NilAtup+                wk (SnocAtup t c) = wk t `SnocAtup` weakenC c+            in+            Stuple (wk t)+--}  -- Array fusion of a de Bruijn computation AST -- ===========================================@@ -692,12 +862,12 @@   Done v                                        -> Avar v   Yield sh f                                    -> Generate sh f   Step sh p f v-    | Just REFL <- match sh (arrayShape v)-    , Just REFL <- isIdentity p-    , Just REFL <- isIdentity f                 -> Avar v-    | Just REFL <- match sh (arrayShape v)-    , Just REFL <- isIdentity p                 -> Map f (avarIn v)-    | Just REFL <- isIdentity f                 -> Backpermute sh p (avarIn v)+    | Just Refl <- match sh (arrayShape v)+    , Just Refl <- isIdentity p+    , Just Refl <- isIdentity f                 -> Avar v+    | Just Refl <- match sh (arrayShape v)+    , Just Refl <- isIdentity p                 -> Map f (avarIn v)+    | Just Refl <- isIdentity f                 -> Backpermute sh p (avarIn v)     | otherwise                                 -> Transform sh p f (avarIn v)  @@ -718,18 +888,62 @@   $ Embed BaseEnv (Yield sh f)  --- Fuse a unary function into a delayed array.+-- Fuse a unary function into a delayed array. Also looks for unzips which can+-- be executed in constant time; SEE [unzipD] ---mapD :: (Kit acc, Elt b)-     => PreFun     acc aenv (a -> b)-     -> Cunctation acc aenv (Array sh a)-     -> Cunctation acc aenv (Array sh b)-mapD f = Stats.ruleFired "mapD" . go+mapD :: (Kit acc, Shape sh, Elt b)+     => PreFun acc aenv (a -> b)+     -> Embed  acc aenv (Array sh a)+     -> Embed  acc aenv (Array sh b)+mapD f (unzipD f -> Just a) = a+mapD f (Embed env cc)+  = Stats.ruleFired "mapD"+  $ Embed env (go cc)   where-    go (step  -> Just (Step sh ix g v)) = Step sh ix (f `compose` g) v-    go (yield -> Yield sh g)            = Yield sh (f `compose` g)+    go (step  -> Just (Step sh ix g v)) = Step sh ix (sink env f `compose` g) v+    go (yield -> Yield sh g)            = Yield sh (sink env f `compose` g)  +-- If we are unzipping a manifest array then force the term to be computed;+-- a backend will be able to execute this in constant time. This operations+-- looks for the right terms recursively, splitting operations such as:+--+-- > map (\x -> fst . fst ... x) arr+--+-- into multiple stages so that they can all be executed in constant time:+--+-- > map fst . map fst ... arr+--+-- Note that this is a speculative operation, since we could dig under several+-- levels of projection before discovering that the operation can not be+-- unzipped. This should be fine though because digging through the terms is+-- relatively cheap; no environment changing operations are required.+--+unzipD+    :: (Kit acc, Shape sh, Elt b)+    => PreFun acc aenv (a -> b)+    -> Embed  acc aenv (Array sh a)+    -> Maybe (Embed acc aenv (Array sh b))+unzipD f (Embed env (Done v))+  | Lam (Body (Prj tix (Var ZeroIdx))) <- f+  = Stats.ruleFired "unzipD"+  $ let f' = Lam (Body (Prj tix (Var ZeroIdx)))+        a' = avarIn v+    in+    Just $ Embed (env `PushEnv` inject (Map f' a')) (Done ZeroIdx)++  | Lam (Body (Prj tix p@Prj{}))       <- f+  , Just (Embed env' (Done v'))        <- unzipD (Lam (Body p)) (Embed env (Done v))+  = Stats.ruleFired "unzipD"+  $ let f' = Lam (Body (Prj tix (Var ZeroIdx)))+        a' = avarIn v'+    in+    Just $ Embed (env' `PushEnv` inject (Map f' a')) (Done ZeroIdx)++unzipD _ _+  = Nothing++ -- Fuse an index space transformation function that specifies where elements in -- the destination array read there data from in the source array. --@@ -741,25 +955,34 @@     -> Cunctation acc aenv (Array sh' e) backpermuteD sh' p = Stats.ruleFired "backpermuteD" . go   where-    go (step  -> Just (Step _ q f v))   = Step sh' (q `compose` p) f v-    go (yield -> Yield _ g)             = Yield sh' (g `compose` p)+    go (step  -> Just (Step _ q f v)) = Step sh' (q `compose` p) f v+    go (yield -> Yield _ g)           = Yield sh' (g `compose` p)   -- Transform as a combined map and backwards permutation -- transformD-    :: (Kit acc, Shape sh', Elt b)-    => PreExp     acc aenv sh'-    -> PreFun     acc aenv (sh' -> sh)-    -> PreFun     acc aenv (a   -> b)-    -> Cunctation acc aenv (Array sh  a)-    -> Cunctation acc aenv (Array sh' b)+    :: (Kit acc, Shape sh, Shape sh', Elt b)+    => PreExp acc aenv sh'+    -> PreFun acc aenv (sh' -> sh)+    -> PreFun acc aenv (a   -> b)+    -> Embed  acc aenv (Array sh  a)+    -> Embed  acc aenv (Array sh' b) transformD sh' p f   = Stats.ruleFired "transformD"-  . backpermuteD sh' p+  . fuse (into2 backpermuteD sh' p)   . mapD f+  where+    fuse :: (forall aenv'. Extend acc aenv aenv' -> Cunctation acc aenv' as -> Cunctation acc aenv' bs)+         -> Embed acc aenv as+         -> Embed acc aenv bs+    fuse op (Embed env cc) = Embed env (op env cc) +    into2 :: (Sink f1, Sink f2)+          => (f1 env' a -> f2 env' b -> c) -> f1 env a -> f2 env b -> Extend acc env env' -> c+    into2 op a b env = op (sink env a) (sink env b) + -- Replicate as a backwards permutation -- -- TODO: If we have a pattern such as `replicate sh (map f xs)` then in some@@ -767,7 +990,7 @@ --       expensive and/or `sh` is large. -- replicateD-    :: (Kit acc, Shape sh, Shape sl, Elt slix, Elt e)+    :: (Kit acc, Shape sh, Shape sl, Elt slix)     => SliceIndex (EltRepr slix) (EltRepr sl) co (EltRepr sh)     -> PreExp     acc aenv slix     -> Cunctation acc aenv (Array sl e)@@ -780,7 +1003,7 @@ -- Dimensional slice as a backwards permutation -- sliceD-    :: (Kit acc, Shape sh, Shape sl, Elt slix, Elt e)+    :: (Kit acc, Shape sh, Shape sl, Elt slix)     => SliceIndex (EltRepr slix) (EltRepr sl) co (EltRepr sh)     -> PreExp     acc aenv slix     -> Cunctation acc aenv (Array sh e)@@ -807,7 +1030,7 @@     -> Embed  acc aenv (Array sl e) reshapeD (Embed env cc) (sink env -> sl)   | Done v      <- cc-  = Embed (env `PushEnv` Reshape sl (avarIn v)) (Done ZeroIdx)+  = Embed (env `PushEnv` inject (Reshape sl (avarIn v))) (Done ZeroIdx)    | otherwise   = Stats.ruleFired "reshapeD"@@ -828,8 +1051,8 @@   --   | Just (Step sh1 p1 f1 v1)    <- step cc1   , Just (Step sh0 p0 f0 v0)    <- step cc0-  , Just REFL                   <- match v1 v0-  , Just REFL                   <- match p1 p0+  , Just Refl                   <- match v1 v0+  , Just Refl                   <- match p1 p0   = Stats.ruleFired "zipWithD/step"   $ Step (sh1 `Intersect` sh0) p0 (combine f f1 f0) v0 @@ -842,13 +1065,13 @@   $ Yield (sh1 `Intersect` sh0) (combine f f1 f0)    where-    combine :: forall acc aenv a b c e. (Elt a, Elt b, Elt c)+    combine :: forall acc aenv a b c e. (Kit acc, Elt a, Elt b, Elt c)             => PreFun acc aenv (a -> b -> c)             -> PreFun acc aenv (e -> a)             -> PreFun acc aenv (e -> b)             -> PreFun acc aenv (e -> c)     combine c ixa ixb-      | Lam (Lam (Body c'))     <- weakenFE SuccIdx c   :: PreOpenFun acc ((),e) aenv (a -> b -> c)+      | Lam (Lam (Body c'))     <- weakenE SuccIdx c   :: PreOpenFun acc ((),e) aenv (a -> b -> c)       , Lam (Body ixa')         <- ixa                          -- else the skolem 'e' will escape       , Lam (Body ixb')         <- ixb       = Lam $ Body $ Let ixa' $ Let (weakenE SuccIdx ixb') c'@@ -950,7 +1173,7 @@   -- that must be later eliminated by shrinking.   --   | Done v1             <- cc1-  , Embed env0 cc0      <- embedAcc $ rebuildAcc (subAtop (Avar v1) . sink1 env1) acc0+  , Embed env0 cc0      <- embedAcc $ rebuildA (subAtop (Avar v1) . sink1 env1) acc0   = Stats.ruleFired "aletD/float"   $ Embed (env1 `append` env0) cc0 @@ -979,7 +1202,7 @@   | acc1                <- compute (Embed env1 cc1)   , False               <- elimAcc (inject acc1) acc0   = Stats.ruleFired "aletD/bind"-  $ Embed (BaseEnv `PushEnv` acc1 `append` env0) cc0+  $ Embed (BaseEnv `PushEnv` inject acc1 `append` env0) cc0    -- let-elimination   -- ---------------@@ -1001,7 +1224,7 @@     -- extra type variables, and ensures we don't do extra work manipulating the     -- body when not necessary (which can lead to a complexity blowup).     ---    eliminate :: forall aenv aenv' sh e brrs. (Kit acc, Shape sh, Elt e, Arrays brrs)+    eliminate :: forall aenv aenv' sh e brrs. (Shape sh, Elt e, Arrays brrs)               => Extend     acc aenv aenv'               -> Cunctation acc      aenv' (Array sh e)               ->            acc     (aenv', Array sh e) brrs@@ -1016,9 +1239,9 @@          elim :: PreExp acc aenv' sh -> PreFun acc aenv' (sh -> e) -> Embed acc aenv brrs         elim sh1 f1-          | sh1'                <- weakenEA rebuildAcc SuccIdx sh1-          , f1'                 <- weakenFA rebuildAcc SuccIdx f1-          , Embed env0' cc0'    <- embedAcc $ rebuildAcc (subAtop bnd) $ kmap (replaceA sh1' f1' ZeroIdx) body+          | sh1'                <- weaken SuccIdx sh1+          , f1'                 <- weaken SuccIdx f1+          , Embed env0' cc0'    <- embedAcc $ rebuildA (subAtop bnd) $ kmap (replaceA sh1' f1' ZeroIdx) body           = Embed (env1 `append` env0') cc0'      -- As part of let-elimination, we need to replace uses of array variables in@@ -1030,13 +1253,13 @@     --       moment we are just hoping CSE in the simplifier phase does good     --       things, but that is limited in what it looks for.     ---    replaceE :: forall env aenv sh e t. (Kit acc, Shape sh, Elt e)+    replaceE :: forall env aenv sh e t. (Shape sh, Elt e)              => PreOpenExp acc env aenv sh -> PreOpenFun acc env aenv (sh -> e) -> Idx aenv (Array sh e)              -> PreOpenExp acc env aenv t              -> PreOpenExp acc env aenv t     replaceE sh' f' avar exp =       case exp of-        Let x y                         -> Let (cvtE x) (replaceE (weakenE SuccIdx sh') (weakenFE SuccIdx f') avar y)+        Let x y                         -> Let (cvtE x) (replaceE (weakenE SuccIdx sh') (weakenE SuccIdx f') avar y)         Var i                           -> Var i         Foreign ff f e                  -> Foreign ff f (cvtE e)         Const c                         -> Const c@@ -1056,23 +1279,25 @@         PrimApp g x                     -> PrimApp g (cvtE x)         ShapeSize sh                    -> ShapeSize (cvtE sh)         Intersect sh sl                 -> Intersect (cvtE sh) (cvtE sl)+        Union s t                       -> Union (cvtE s) (cvtE t)         While p f x                     -> While (replaceF sh' f' avar p) (replaceF sh' f' avar f) (cvtE x)          Shape a-          | Just REFL <- match a a'     -> Stats.substitution "replaceE/shape" sh'+          | Just Refl <- match a a'     -> Stats.substitution "replaceE/shape" sh'           | otherwise                   -> exp          Index a sh-          | Just REFL    <- match a a'+          | Just Refl    <- match a a'           , Lam (Body b) <- f'          -> Stats.substitution "replaceE/!" . cvtE $ Let sh b           | otherwise                   -> Index a (cvtE sh)          LinearIndex a i-          | Just REFL    <- match a a'+          | Just Refl    <- match a a'           , Lam (Body b) <- f'          -> Stats.substitution "replaceE/!!" . cvtE $ Let (Let i (FromIndex (weakenE SuccIdx sh') (Var ZeroIdx))) b           | otherwise                   -> LinearIndex a (cvtE i)        where+        a' :: acc aenv (Array sh e)         a' = avarIn avar          cvtE :: PreOpenExp acc env aenv s -> PreOpenExp acc env aenv s@@ -1082,28 +1307,28 @@         cvtT NilTup        = NilTup         cvtT (SnocTup t e) = cvtT t `SnocTup` cvtE e -    replaceF :: forall env aenv sh e t. (Kit acc, Shape sh, Elt e)+    replaceF :: forall env aenv sh e t. (Shape sh, Elt e)              => PreOpenExp acc env aenv sh -> PreOpenFun acc env aenv (sh -> e) -> Idx aenv (Array sh e)              -> PreOpenFun acc env aenv t              -> PreOpenFun acc env aenv t     replaceF sh' f' avar fun =       case fun of         Body e          -> Body (replaceE sh' f' avar e)-        Lam f           -> Lam  (replaceF (weakenE SuccIdx sh') (weakenFE SuccIdx f') avar f)+        Lam f           -> Lam  (replaceF (weakenE SuccIdx sh') (weakenE SuccIdx f') avar f) -    replaceA :: forall aenv sh e a. (Kit acc, Shape sh, Elt e)+    replaceA :: forall aenv sh e a. (Shape sh, Elt e)              => PreExp acc aenv sh -> PreFun acc aenv (sh -> e) -> Idx aenv (Array sh e)              -> PreOpenAcc acc aenv a              -> PreOpenAcc acc aenv a     replaceA sh' f' avar pacc =       case pacc of         Avar v-          | Just REFL <- match v avar   -> Avar avar+          | Just Refl <- match v avar   -> Avar avar           | otherwise                   -> Avar v          Alet bnd body                   ->-          let sh'' = weakenEA rebuildAcc SuccIdx sh'-              f''  = weakenFA rebuildAcc SuccIdx f'+          let sh'' = weaken SuccIdx sh'+              f''  = weaken SuccIdx f'           in           Alet (cvtA bnd) (kmap (replaceA sh'' f'' (SuccIdx avar)) body) @@ -1136,11 +1361,22 @@         Permute f d p a         -> Permute (cvtF f) (cvtA d) (cvtF p) (cvtA a)         Stencil f x a           -> Stencil (cvtF f) x (cvtA a)         Stencil2 f x a y b      -> Stencil2 (cvtF f) x (cvtA a) y (cvtA b)+        -- Collect seq             -> Collect (cvtSeq seq)        where         cvtA :: acc aenv s -> acc aenv s         cvtA = kmap (replaceA sh' f' avar) +        cvtE :: PreExp acc aenv s -> PreExp acc aenv s+        cvtE = replaceE sh' f' avar++        cvtF :: PreFun acc aenv s -> PreFun acc aenv s+        cvtF = replaceF sh' f' avar++        cvtAT :: Atuple (acc aenv) s -> Atuple (acc aenv) s+        cvtAT NilAtup          = NilAtup+        cvtAT (SnocAtup tup a) = cvtAT tup `SnocAtup` cvtA a+         cvtAF :: PreOpenAfun acc aenv s -> PreOpenAfun acc aenv s         cvtAF = cvt sh' f' avar           where@@ -1149,22 +1385,64 @@                 -> PreOpenAfun acc aenv a                 -> PreOpenAfun acc aenv a             cvt sh'' f'' avar' (Abody a) = Abody $ kmap (replaceA sh'' f'' avar') a-            cvt sh'' f'' avar' (Alam af) = Alam $ cvt (weakenEA rebuildAcc SuccIdx sh'')-                                                      (weakenFA rebuildAcc SuccIdx f'')-                                                      (SuccIdx avar')-                                                      af+            cvt sh'' f'' avar' (Alam af) = Alam  $ cvt (weaken SuccIdx sh'')+                                                       (weaken SuccIdx f'')+                                                       (SuccIdx avar')+                                                       af -        cvtE :: PreExp acc aenv s -> PreExp acc aenv s-        cvtE = replaceE sh' f' avar+{--+        cvtSeq :: PreOpenSeq acc aenv senv s -> PreOpenSeq acc aenv senv s+        cvtSeq s =+          case s of+            Producer p s' ->+              Producer+                (case p of+                   StreamIn arrs        -> StreamIn arrs+                   ToSeq slix sh a      -> ToSeq slix sh (cvtA a)+                   MapSeq f x           -> MapSeq (cvtAF f) x+                   ChunkedMapSeq f x    -> ChunkedMapSeq (cvtAF f) x+                   ZipWithSeq f x y     -> ZipWithSeq (cvtAF f) x y+                   ScanSeq f e x        -> ScanSeq (cvtF f) (cvtE e) x)+                (cvtSeq s')+            Consumer c ->+              Consumer (cvtC c)+            Reify ix -> Reify ix -        cvtF :: PreFun acc aenv s -> PreFun acc aenv s-        cvtF = replaceF sh' f' avar+        cvtC :: Consumer acc aenv senv s -> Consumer acc aenv senv s+        cvtC c =+          case c of+            FoldSeq f e x        -> FoldSeq (cvtF f) (cvtE e) x+            FoldSeqFlatten f a x -> FoldSeqFlatten (cvtAF f) (cvtA a) x+            Stuple t             -> Stuple (cvtCT t) -        cvtAT :: Atuple (acc aenv) s -> Atuple (acc aenv) s-        cvtAT NilAtup          = NilAtup-        cvtAT (SnocAtup tup a) = cvtAT tup `SnocAtup` cvtA a+        cvtCT :: Atuple (Consumer acc aenv senv) t -> Atuple (Consumer acc aenv senv) t+        cvtCT NilAtup        = NilAtup+        cvtCT (SnocAtup t c) = cvtCT t `SnocAtup` cvtC c+--}  +-- The apply operator, or (>->) in the surface language. This eliminates+-- redundant application to an identity function, instead lifting the argument+-- to a let-binding. This case arises in the use of pipe to avoid fusion and+-- force its argument to be evaluated, e.g.:+--+-- > compute :: Acc a -> Acc a+-- > compute = id >-> id+--+applyD :: (Kit acc, Arrays as, Arrays bs)+       => PreOpenAfun acc aenv (as -> bs)+       ->             acc aenv as+       -> Embed       acc aenv bs+applyD afun x+  | Alam (Abody body)   <- afun+  , Avar ZeroIdx        <- extract body+  = Stats.ruleFired "applyD/identity"+  $ done $ extract x++  | otherwise+  = done $ Apply afun x++ -- Array conditionals, in particular eliminate branches when the predicate -- reduces to a known constant. --@@ -1182,9 +1460,9 @@        ->          acc aenv arrs        -> Embed    acc aenv arrs acondD embedAcc p t e-  | Const ((),True)  <- p   = Stats.knownBranch "True"      $ embedAcc t-  | Const ((),False) <- p   = Stats.knownBranch "False"     $ embedAcc e-  | Just REFL <- match t e  = Stats.knownBranch "redundant" $ embedAcc e+  | Const True  <- p        = Stats.knownBranch "True"      $ embedAcc t+  | Const False <- p        = Stats.knownBranch "False"     $ embedAcc e+  | Just Refl <- match t e  = Stats.knownBranch "redundant" $ embedAcc e   | otherwise               = done $ Acond p (computeAcc (embedAcc t))                                              (computeAcc (embedAcc e)) @@ -1192,7 +1470,7 @@ -- Array tuple projection. Whenever possible we want to peek underneath the -- tuple structure and continue the fusion process. ---aprjD :: forall acc aenv arrs a. (Kit acc, IsTuple arrs, Arrays arrs, Arrays a)+aprjD :: forall acc aenv arrs a. (Kit acc, IsAtuple arrs, Arrays arrs, Arrays a)       => EmbedAcc acc       -> TupleIdx (TupleRepr arrs) a       ->       acc aenv arrs@@ -1212,18 +1490,18 @@ -- Scalar expressions -- ------------------ -isIdentity :: PreFun acc aenv (a -> b) -> Maybe (a :=: b)+isIdentity :: PreFun acc aenv (a -> b) -> Maybe (a :~: b) isIdentity f-  | Lam (Body (Var ZeroIdx)) <- f       = Just REFL+  | Lam (Body (Var ZeroIdx)) <- f       = Just Refl   | otherwise                           = Nothing  identity :: Elt a => PreOpenFun acc env aenv (a -> a) identity = Lam (Body (Var ZeroIdx)) -toIndex :: Shape sh => PreOpenExp acc env aenv sh -> PreOpenFun acc env aenv (sh -> Int)+toIndex :: (Kit acc, Shape sh) => PreOpenExp acc env aenv sh -> PreOpenFun acc env aenv (sh -> Int) toIndex sh = Lam (Body (ToIndex (weakenE SuccIdx sh) (Var ZeroIdx))) -fromIndex :: Shape sh => PreOpenExp acc env aenv sh -> PreOpenFun acc env aenv (Int -> sh)+fromIndex :: (Kit acc, Shape sh) => PreOpenExp acc env aenv sh -> PreOpenFun acc env aenv (Int -> sh) fromIndex sh = Lam (Body (FromIndex (weakenE SuccIdx sh) (Var ZeroIdx)))  reindex :: (Kit acc, Shape sh, Shape sh')@@ -1231,16 +1509,16 @@         -> PreOpenExp acc env aenv sh         -> PreOpenFun acc env aenv (sh -> sh') reindex sh' sh-  | Just REFL <- match sh sh'   = identity+  | Just Refl <- match sh sh'   = identity   | otherwise                   = fromIndex sh' `compose` toIndex sh -extend :: (Shape sh, Shape sl, Elt slix)+extend :: (Kit acc, Shape sh, Shape sl, Elt slix)        => SliceIndex (EltRepr slix) (EltRepr sl) co (EltRepr sh)        -> PreExp acc aenv slix        -> PreFun acc aenv (sh -> sl) extend sliceIndex slix = Lam (Body (IndexSlice sliceIndex (weakenE SuccIdx slix) (Var ZeroIdx))) -restrict :: (Shape sh, Shape sl, Elt slix)+restrict :: (Kit acc, Shape sh, Shape sl, Elt slix)          => SliceIndex (EltRepr slix) (EltRepr sl) co (EltRepr sh)          -> PreExp acc aenv slix          -> PreFun acc aenv (sl -> sh)
Data/Array/Accelerate/Trafo/Rewrite.hs view
@@ -2,10 +2,10 @@ {-# LANGUAGE ScopedTypeVariables #-} -- | -- Module      : Data.Array.Accelerate.Trafo.Rewrite--- Copyright   : [2012..2014] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2012..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell -- License     : BSD3 ----- Maintainer  : Manuel M T Chakravarty <chak@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -13,12 +13,13 @@ module Data.Array.Accelerate.Trafo.Rewrite   where +import Prelude                                          hiding ( seq )+ -- friends import Data.Array.Accelerate.AST import Data.Array.Accelerate.Type-import Data.Array.Accelerate.Tuple import Data.Array.Accelerate.Trafo.Substitution-import Data.Array.Accelerate.Array.Sugar                ( Arrays, Segments, Elt, fromElt )+import Data.Array.Accelerate.Array.Sugar                ( Arrays, Segments, Elt, fromElt, Tuple(..), Atuple(..) )   -- Convert segment length arrays passed to segmented operations into offset@@ -36,7 +37,7 @@     cvtAfun :: OpenAfun aenv t -> OpenAfun aenv t     cvtAfun = convertSegmentsAfun -    cvtE :: Elt t => Exp aenv t -> Exp aenv t+    cvtE :: Exp aenv t -> Exp aenv t     cvtE = id      cvtF :: Fun aenv t -> Fun aenv t@@ -88,21 +89,64 @@       Backpermute sh f a        -> Backpermute (cvtE sh) (cvtF f) (cvtA a)       Stencil f b a             -> Stencil (cvtF f) b (cvtA a)       Stencil2 f b1 a1 b2 a2    -> Stencil2 (cvtF f) b1 (cvtA a1) b2 (cvtA a2)+      -- Collect s                 -> Collect (convertSegmentsSeq s)        -- Things we are interested in, whoo!       FoldSeg f z a s           -> Alet (segments s) (OpenAcc (FoldSeg (cvtF f') (cvtE z') (cvtA a') a0))-        where f' = weakenFA rebuildOpenAcc SuccIdx f-              z' = weakenEA rebuildOpenAcc SuccIdx z-              a' = rebuildOpenAcc (Avar . SuccIdx) a+        where f' = weaken SuccIdx f+              z' = weaken SuccIdx z+              a' = weaken SuccIdx a        Fold1Seg f a s            -> Alet (segments s) (OpenAcc (Fold1Seg (cvtF f') (cvtA a') a0))-        where f' = weakenFA rebuildOpenAcc SuccIdx f-              a' = rebuildOpenAcc (Avar . SuccIdx) a+        where f' = weaken SuccIdx f+              a' = weaken SuccIdx a   convertSegmentsAfun :: OpenAfun aenv t -> OpenAfun aenv t convertSegmentsAfun afun =   case afun of     Abody b     -> Abody (convertSegments b)-    Alam f      -> Alam (convertSegmentsAfun f)+    Alam f      -> Alam  (convertSegmentsAfun f)++{--+convertSegmentsSeq :: PreOpenSeq OpenAcc aenv senv a -> PreOpenSeq OpenAcc aenv senv a+convertSegmentsSeq seq =+  case seq of+    Producer p s -> Producer (cvtP p) (convertSegmentsSeq s)+    Consumer c   -> Consumer (cvtC c)+    Reify ix     -> Reify ix+  where+    cvtP :: Producer OpenAcc aenv senv a -> Producer OpenAcc aenv senv a+    cvtP p =+      case p of+        StreamIn arrs        -> StreamIn arrs+        ToSeq sl slix a      -> ToSeq sl slix (cvtA a)+        MapSeq f x           -> MapSeq (cvtAfun f) x+        ChunkedMapSeq f x    -> ChunkedMapSeq (cvtAfun f) x+        ZipWithSeq f x y     -> ZipWithSeq (cvtAfun f) x y+        ScanSeq f e x        -> ScanSeq (cvtF f) (cvtE e) x++    cvtC :: Consumer OpenAcc aenv senv a -> Consumer OpenAcc aenv senv a+    cvtC c =+      case c of+        FoldSeq f e x        -> FoldSeq (cvtF f) (cvtE e) x+        FoldSeqFlatten f a x -> FoldSeqFlatten (cvtAfun f) (cvtA a) x+        Stuple t             -> Stuple (cvtCT t)++    cvtCT :: Atuple (Consumer OpenAcc senv aenv) t -> Atuple (Consumer OpenAcc senv aenv) t+    cvtCT NilAtup        = NilAtup+    cvtCT (SnocAtup t c) = SnocAtup (cvtCT t) (cvtC c)++    cvtE :: Exp aenv t -> Exp aenv t+    cvtE = id++    cvtF :: Fun aenv t -> Fun aenv t+    cvtF = id++    cvtA :: OpenAcc aenv t -> OpenAcc aenv t+    cvtA = convertSegments++    cvtAfun :: OpenAfun aenv t -> OpenAfun aenv t+    cvtAfun = convertSegmentsAfun+--} 
Data/Array/Accelerate/Trafo/Sharing.hs view
@@ -1,17 +1,21 @@+{-# LANGUAGE BangPatterns         #-}+{-# LANGUAGE DeriveDataTypeable   #-} {-# LANGUAGE FlexibleInstances    #-} {-# LANGUAGE GADTs                #-} {-# LANGUAGE PatternGuards        #-} {-# LANGUAGE ScopedTypeVariables  #-}+{-# LANGUAGE StandaloneDeriving   #-} {-# LANGUAGE TemplateHaskell      #-} {-# LANGUAGE TypeFamilies         #-}+{-# LANGUAGE TypeOperators        #-} {-# OPTIONS_GHC -fno-warn-orphans        #-} {-# OPTIONS_GHC -fno-warn-name-shadowing #-} {-# OPTIONS_HADDOCK hide #-} -- | -- Module      : Data.Array.Accelerate.Trafo.Sharing--- Copyright   : [2008..2014] Manuel M T Chakravarty, Gabriele Keller---               [2009..2014] Trevor L. McDonell---               [2013..2014] Robert Clifton-Everest+-- Copyright   : [2008..2017] Manuel M T Chakravarty, Gabriele Keller+--               [2009..2017] Trevor L. McDonell+--               [2013..2017] Robert Clifton-Everest -- License     : BSD3 -- -- Maintainer  : Manuel M T Chakravarty <chak@cse.unsw.edu.au>@@ -26,7 +30,8 @@    -- * HOAS -> de Bruijn conversion   convertAcc, convertAfun, Afunction, AfunctionR,-  convertExp, convertFun,  Function,  FunctionR+  convertExp, convertFun,  Function,  FunctionR,+  -- convertSeq  ) where @@ -37,24 +42,23 @@ import Data.Maybe import Data.Hashable import Data.Typeable+import System.Mem.StableName+import System.IO.Unsafe                                 ( unsafePerformIO ) import qualified Data.HashTable.IO                      as Hash import qualified Data.IntMap                            as IntMap import qualified Data.HashMap.Strict                    as Map import qualified Data.HashSet                           as Set-import System.IO.Unsafe                                 ( unsafePerformIO )-import System.Mem.StableName import Prelude  -- friends import Data.Array.Accelerate.Error import Data.Array.Accelerate.Smart import Data.Array.Accelerate.Array.Sugar                as Sugar-import Data.Array.Accelerate.Tuple                      hiding ( Tuple )-import Data.Array.Accelerate.AST                        hiding (-  PreOpenAcc(..), OpenAcc(..), Acc, Stencil(..), PreOpenExp(..), OpenExp, PreExp, Exp,-  showPreAccOp, showPreExpOp )+import Data.Array.Accelerate.AST                        hiding ( PreOpenAcc(..), OpenAcc(..), Acc+                                                               , PreOpenExp(..), OpenExp, PreExp, Exp+                                                               , Stencil(..)+                                                               , showPreAccOp, showPreExpOp ) import qualified Data.Array.Accelerate.AST              as AST-import qualified Data.Array.Accelerate.Tuple            as Tuple import qualified Data.Array.Accelerate.Debug            as Debug  @@ -68,10 +72,10 @@   {     recoverAccSharing   :: Bool         -- ^ Recover sharing of array computations ?   , recoverExpSharing   :: Bool         -- ^ Recover sharing of scalar expressions ?+  , recoverSeqSharing   :: Bool         -- ^ Recover sharing of sequence computations ?   , floatOutAcc         :: Bool         -- ^ Always float array computations out of expressions ?   } - -- Layouts -- ------- @@ -129,11 +133,12 @@     :: Arrays arrs     => Bool             -- ^ recover sharing of array computations ?     -> Bool             -- ^ recover sharing of scalar expressions ?+    -> Bool             -- ^ recover sharing of sequence computations ?     -> Bool             -- ^ always float array computations out of expressions?     -> Acc arrs     -> AST.Acc arrs-convertAcc shareAcc shareExp floatAcc acc-  = let config  = Config shareAcc shareExp (shareAcc && floatAcc)+convertAcc shareAcc shareExp shareSeq floatAcc acc+  = let config  = Config shareAcc shareExp shareSeq (shareAcc && floatAcc)     in     convertOpenAcc config 0 [] EmptyLayout acc @@ -141,9 +146,9 @@ -- | Convert a closed function over array computations, while incorporating -- sharing information. ---convertAfun :: Afunction f => Bool -> Bool -> Bool -> f -> AST.Afun (AfunctionR f)-convertAfun shareAcc shareExp floatAcc =-  let config = Config shareAcc shareExp (shareAcc && floatAcc)+convertAfun :: Afunction f => Bool -> Bool -> Bool -> Bool -> f -> AST.Afun (AfunctionR f)+convertAfun shareAcc shareExp shareSeq floatAcc =+  let config = Config shareAcc shareExp shareSeq (shareAcc && floatAcc)   in  aconvert config EmptyLayout  @@ -265,9 +270,10 @@       Aforeign ff afun acc         -> let a = recoverAccSharing config                e = recoverExpSharing config+               s = recoverSeqSharing config                f = floatOutAcc config            in-           AST.Aforeign ff (convertAfun a e f afun) (cvtA acc)+           AST.Aforeign ff (convertAfun a e s f afun) (cvtA acc)        Acond b acc1 acc2           -> AST.Acond (cvtE b) (cvtA acc1) (cvtA acc2)       Awhile pred iter init       -> AST.Awhile (cvtAfun1 pred) (cvtAfun1 iter) (cvtA init)@@ -303,7 +309,157 @@                         (cvtA acc1)                         (convertBoundary bndy2)                         (cvtA acc2)+      -- Collect seq -> AST.Collect (convertSharingSeq config alyt EmptyLayout aenv' [] seq) ++{--+-- Sequence expressions+-- ------------------++-- | Convert a closed sequence expression to de Bruijn form while incorporating+-- sharing information.+--+convertSeq+    :: Typeable s+    => Bool             -- ^ recover sharing of array computations ?+    -> Bool             -- ^ recover sharing of scalar expressions ?+    -> Bool             -- ^ recover sharing of sequence computations ?+    -> Bool             -- ^ always float array computations out of expressions?+    -> Seq s            -- ^ computation to be converted+    -> AST.Seq s+convertSeq shareAcc shareExp shareSeq floatAcc seq+  = let config = Config shareAcc shareExp shareSeq floatAcc+        (sharingSeq, initialEnv) = recoverSharingSeq config seq+    in+    convertSharingSeq config EmptyLayout EmptyLayout [] initialEnv sharingSeq++convertSharingSeq+    :: forall aenv senv arrs.+       Config+    -> Layout aenv aenv+    -> Layout senv senv+    -> [StableSharingAcc]+    -> [StableSharingSeq]+    -> ScopedSeq arrs+    -> AST.PreOpenSeq AST.OpenAcc aenv senv arrs+convertSharingSeq _ _ slyt _ senv (ScopedSeq (SvarSharing sn))+  | Just i <- findIndex (matchStableSeq sn) senv+  = AST.Reify $ prjIdx (ctxt ++ "; i = " ++ show i) i slyt+  | null senv+  = error $ "Cyclic definition of a value of type 'Seq' (sa = " +++            show (hashStableNameHeight sn) ++ ")"+  | otherwise+  = $internalError "convertSharingSeq" err+  where+    ctxt = "shared 'Seq' tree with stable name " ++ show (hashStableNameHeight sn)+    err  = "inconsistent valuation @ " ++ ctxt ++ ";\n  senv = " ++ show senv+convertSharingSeq config alyt slyt aenv senv (ScopedSeq (SletSharing sa@(StableSharingSeq _ (SeqSharing _ boundSeq)) bodySeq))+  = convSeq boundSeq bodySeq+  where+    convSeq :: forall bnd body.+               PreSeq ScopedAcc ScopedSeq ScopedExp bnd+            -> ScopedSeq body+            -> AST.PreOpenSeq AST.OpenAcc aenv senv body+    convSeq bnd body =+      case bnd of+        StreamIn arrs               -> producer $ AST.StreamIn arrs+        ToSeq slix acc              -> producer $ mkToSeq slix (cvtA acc)+        MapSeq afun x               -> producer $ AST.MapSeq (cvtAF1 afun) (asIdx x)+        ZipWithSeq afun x y         -> producer $ AST.ZipWithSeq (cvtAF2 afun) (asIdx x) (asIdx y)+        ScanSeq fun e x             -> producer $ AST.ScanSeq (cvtF2 fun) (cvtE e) (asIdx x)+        _                           -> $internalError "convertSharingSeq:convSeq" "Consumer appears to have been let bound"+      where+        producer :: Arrays a+                 => AST.Producer AST.OpenAcc aenv senv a+                 -> AST.PreOpenSeq AST.OpenAcc aenv senv body+        producer p = AST.Producer p $ convertSharingSeq config alyt slyt' aenv (sa:senv) body+          where+            slyt' = incLayout slyt `PushLayout` ZeroIdx++        asIdx :: Arrays a+              => ScopedSeq [a]+              -> Idx senv a+        asIdx (ScopedSeq (SvarSharing sn))+          | Just i <- findIndex (matchStableSeq sn) senv+          = prjIdx (ctxt ++ "; i = " ++ show i) i slyt+          | null senv+          = error $ "Cyclic definition of a value of type 'Seq' (sa = " +++                    show (hashStableNameHeight sn) ++ ")"+          | otherwise+          = $internalError "convertSharingSeq" err+          where+            ctxt = "shared 'Seq' tree with stable name " ++ show (hashStableNameHeight sn)+            err  = "inconsistent valuation @ " ++ ctxt ++ ";\n  senv = " ++ show senv+        asIdx _+          = $internalError "convertSharingSeq:asIdx" "Sequence computation not in A-normal form"++        cvtA :: forall a. Arrays a => ScopedAcc a -> AST.OpenAcc aenv a+        cvtA acc = convertSharingAcc config alyt aenv acc++        cvtE :: forall t. Elt t => ScopedExp t -> AST.Exp aenv t+        cvtE = convertSharingExp config EmptyLayout alyt [] aenv++        cvtF2 :: (Elt a, Elt b, Elt c) => (Exp a -> Exp b -> ScopedExp c) -> AST.Fun aenv (a -> b -> c)+        cvtF2 = convertSharingFun2 config alyt aenv++        cvtAF1 :: forall a b. (Arrays a, Arrays b) => (Acc a -> ScopedAcc b) -> OpenAfun aenv (a -> b)+        cvtAF1 afun = convertSharingAfun1 config alyt aenv afun++        cvtAF2 :: forall a b c. (Arrays a, Arrays b, Arrays c) => (Acc a -> Acc b -> ScopedAcc c) -> OpenAfun aenv (a -> b -> c)+        cvtAF2 afun = convertSharingAfun2 config alyt aenv afun++convertSharingSeq _ _ _ _ _ (ScopedSeq (SletSharing _ _))+ = $internalError "convertSharingSeq" "Sequence computation not in A-normal form"++convertSharingSeq config alyt slyt aenv senv s+  = cvtC s+  where+    cvtC :: ScopedSeq a -> AST.PreOpenSeq AST.OpenAcc aenv senv a+    cvtC (ScopedSeq (SeqSharing _ s)) =+      case s of+        FoldSeq fun e x                    -> AST.Consumer $ AST.FoldSeq (cvtF2 fun) (cvtE e) (asIdx x)+        FoldSeqFlatten afun acc x          -> AST.Consumer $ AST.FoldSeqFlatten (cvtAF3 afun) (cvtA acc) (asIdx x)+        Stuple t                           -> AST.Consumer $ AST.Stuple (cvtST t)+        _                                  -> $internalError "convertSharingSeq" "Producer has not been let bound"+    cvtC _ = $internalError "convertSharingSeq" "Unreachable"++    asIdx :: Arrays a+          => ScopedSeq [a]+          -> Idx senv a+    asIdx (ScopedSeq (SvarSharing sn))+      | Just i <- findIndex (matchStableSeq sn) senv+      = prjIdx (ctxt ++ "; i = " ++ show i) i slyt+      | null senv+      = error $ "Cyclic definition of a value of type 'Seq' (sa = " +++                show (hashStableNameHeight sn) ++ ")"+      | otherwise+      = $internalError "convertSharingSeq" err+      where+        ctxt = "shared 'Seq' tree with stable name " ++ show (hashStableNameHeight sn)+        err  = "inconsistent valuation @ " ++ ctxt ++ ";\n  senv = " ++ show senv+    asIdx _+      = $internalError "convertSharingSeq:asIdx" "Sequence computation not in A-normal form"++    cvtA :: forall a. Arrays a => ScopedAcc a -> AST.OpenAcc aenv a+    cvtA acc = convertSharingAcc config alyt aenv acc++    cvtE :: forall t. Elt t => ScopedExp t -> AST.Exp aenv t+    cvtE = convertSharingExp config EmptyLayout alyt [] aenv++    cvtF2 :: (Elt a, Elt b, Elt c) => (Exp a -> Exp b -> ScopedExp c) -> AST.Fun aenv (a -> b -> c)+    cvtF2 = convertSharingFun2 config alyt aenv++    cvtAF3 :: forall a b c d. (Arrays a, Arrays b, Arrays c, Arrays d) => (Acc a -> Acc b -> Acc c -> ScopedAcc d) -> OpenAfun aenv (a -> b -> c -> d)+    cvtAF3 afun = convertSharingAfun3 config alyt aenv afun++    cvtST :: Atuple ScopedSeq t -> Atuple (AST.Consumer AST.OpenAcc aenv senv) t+    cvtST NilAtup        = NilAtup+    cvtST (SnocAtup t c) | AST.Consumer c' <- cvtC c+                         = SnocAtup (cvtST t) c'+                         | otherwise+                         = $internalError "convertSharingSeq" "Unreachable"+--}+ convertSharingAfun1     :: forall aenv a b. (Arrays a, Arrays b)     => Config@@ -317,16 +473,44 @@         alyt' = incLayout alyt `PushLayout` ZeroIdx         body  = f undefined +{--+convertSharingAfun2+    :: forall aenv a b c. (Arrays a, Arrays b, Arrays c)+    => Config+    -> Layout aenv aenv+    -> [StableSharingAcc]+    -> (Acc a -> Acc b -> ScopedAcc c)+    -> OpenAfun aenv (a -> b -> c)+convertSharingAfun2 config alyt aenv f+  = Alam (Alam (Abody (convertSharingAcc config alyt' aenv body)))+      where+        alyt' = incLayout (incLayout alyt `PushLayout` ZeroIdx) `PushLayout` ZeroIdx+        body  = f undefined undefined++convertSharingAfun3+    :: forall aenv a b c d. (Arrays a, Arrays b, Arrays c, Arrays d)+    => Config+    -> Layout aenv aenv+    -> [StableSharingAcc]+    -> (Acc a -> Acc b -> Acc c -> ScopedAcc d)+    -> OpenAfun aenv (a -> b -> c -> d)+convertSharingAfun3 config alyt aenv f+  = Alam (Alam (Alam (Abody (convertSharingAcc config alyt' aenv body))))+      where+        alyt' = incLayout (incLayout (incLayout alyt `PushLayout` ZeroIdx) `PushLayout` ZeroIdx) `PushLayout` ZeroIdx+        body  = f undefined undefined undefined+--}+ convertSharingAtuple     :: forall aenv a.        Config     -> Layout aenv aenv     -> [StableSharingAcc]-    -> Tuple.Atuple ScopedAcc a-    -> Tuple.Atuple (AST.OpenAcc aenv) a+    -> Atuple ScopedAcc a+    -> Atuple (AST.OpenAcc aenv) a convertSharingAtuple config alyt aenv = cvt   where-    cvt :: Tuple.Atuple ScopedAcc a' -> Tuple.Atuple (AST.OpenAcc aenv) a'+    cvt :: Atuple ScopedAcc a' -> Atuple (AST.OpenAcc aenv) a'     cvt NilAtup         = NilAtup     cvt (SnocAtup t a)  = cvt t `SnocAtup` convertSharingAcc config alyt aenv a @@ -358,6 +542,13 @@   where     slix = undefined :: slix +-- mkToSeq :: forall slsix slix e aenv senv. (Division slsix, DivisionSlice slsix ~ slix, Elt e, Elt slix, Slice slix)+--         => slsix+--         -> AST.OpenAcc              aenv (Array (FullShape  slix) e)+--         -> AST.Producer AST.OpenAcc aenv senv (Array (SliceShape slix) e)+-- mkToSeq _ = AST.ToSeq (sliceIndex slix) (Proxy :: Proxy slix)+--   where+--     slix = undefined :: slix   -- Scalar functions@@ -373,7 +564,7 @@ -- convertFun :: Function f => Bool -> f -> AST.Fun () (FunctionR f) convertFun shareExp =-  let config = Config False shareExp False+  let config = Config False shareExp False False   in  convert config EmptyLayout  @@ -412,7 +603,7 @@     -> Exp e            -- ^ expression to be converted     -> AST.Exp () e convertExp shareExp exp-  = let config = Config False shareExp False+  = let config = Config False shareExp False False     in     convertOpenExp config 0 [] EmptyLayout exp @@ -488,12 +679,13 @@           Shape a               -> AST.Shape (cvtA a)           ShapeSize e           -> AST.ShapeSize (cvt e)           Intersect sh1 sh2     -> AST.Intersect (cvt sh1) (cvt sh2)+          Union sh1 sh2         -> AST.Union (cvt sh1) (cvt sh2)           Foreign ff f e        -> AST.Foreign ff (convertFun (recoverExpSharing config) f) (cvt e)      cvtA :: Arrays a => ScopedAcc a -> AST.OpenAcc aenv a     cvtA = convertSharingAcc config alyt aenv -    cvtT :: Tuple.Tuple ScopedExp tup -> Tuple.Tuple (AST.OpenExp env aenv) tup+    cvtT :: Tuple ScopedExp tup -> Tuple (AST.OpenExp env aenv) tup     cvtT = convertSharingTuple config lyt alyt env' aenv      cvtFun1 :: (Elt a, Elt b) => (Exp a -> ScopedExp b) -> AST.OpenFun env aenv (a -> b)@@ -519,8 +711,8 @@     -> Layout aenv aenv     -> [StableSharingExp]                 -- currently bound scalar sharing-variables     -> [StableSharingAcc]                 -- currently bound array sharing-variables-    -> Tuple.Tuple ScopedExp t-    -> Tuple.Tuple (AST.OpenExp env aenv) t+    -> Tuple ScopedExp t+    -> Tuple (AST.OpenExp env aenv) t convertSharingTuple config lyt alyt env aenv tup =   case tup of     NilTup      -> NilTup@@ -792,6 +984,7 @@ lookupWithSharingExp oc (StableSharingExp (StableNameHeight sn _) _)   = lookupWithASTName oc (StableASTName sn) + -- Stable 'Acc' nodes -- ------------------ @@ -862,8 +1055,8 @@ -- data SharingExp (acc :: * -> *) exp t where   VarSharing :: Elt t-             => StableExpName t                            -> SharingExp acc exp t-  LetSharing :: StableSharingExp -> exp t                  -> SharingExp acc exp t+             => StableExpName t                     -> SharingExp acc exp t+  LetSharing :: StableSharingExp -> exp t           -> SharingExp acc exp t   ExpSharing :: Elt t              => StableExpName t -> PreExp acc exp t -> SharingExp acc exp t @@ -914,10 +1107,73 @@ noStableExpName = unsafePerformIO $ StableNameHeight <$> makeStableName undefined <*> pure 0  +{--+-- Stable 'Seq' nodes+-- ------------------++-- Stable name for 'Seq' nodes including the height of the AST.+--+type StableSeqName arrs = StableNameHeight (Seq arrs)++-- Interleave sharing annotations into an sequence computation AST in the same manner as SharingAcc+-- and SharingExp+--+data SharingSeq acc seq exp arrs where+  SvarSharing :: (Typeable arrs, Arrays arrs)+              => StableSeqName [arrs]                       -> SharingSeq acc seq exp [arrs]+  SletSharing :: StableSharingSeq -> seq t                  -> SharingSeq acc seq exp t+  SeqSharing  :: Typeable arrs+              => StableSeqName arrs -> PreSeq acc seq exp arrs -> SharingSeq acc seq exp arrs++-- Array expression with sharing but shared values have not been scoped; i.e. no let bindings. If+-- the expression is rooted in a function, the list contains the tags of the variables bound by the+-- immediate surrounding lambdas.+data UnscopedSeq t = UnscopedSeq (SharingSeq UnscopedAcc UnscopedSeq RootExp t)++-- Array expression with sharing. For expressions rooted in functions the list holds a sorted+-- environment corresponding to the variables bound in the immediate surounding lambdas.+data ScopedSeq t = ScopedSeq (SharingSeq ScopedAcc ScopedSeq ScopedExp t)++-- Sequences rooted in 'Acc' computations.+--+-- * When counting occurrences, the root of every sequence embedded in an 'Acc' is annotated by+--   an occurrence map for that one expression (excluding any subterms that are rooted in embedded+--   'Acc's.)+--+data RootSeq t = RootSeq (OccMap Seq) (UnscopedSeq t)++-- Stable name for an array computation associated with its sharing-annotated version.+--+data StableSharingSeq where+  StableSharingSeq :: Typeable arrs+                   => StableSeqName arrs+                   -> SharingSeq ScopedAcc ScopedSeq ScopedExp arrs+                   -> StableSharingSeq++instance Show StableSharingSeq where+  show (StableSharingSeq sn _) = show $ hashStableNameHeight sn++instance Eq StableSharingSeq where+  StableSharingSeq sn1 _ == StableSharingSeq sn2 _+    | Just sn1' <- gcast sn1 = sn1' == sn2+    | otherwise              = False++higherSSS :: StableSharingSeq -> StableSharingSeq -> Bool+StableSharingSeq sn1 _ `higherSSS` StableSharingSeq sn2 _ = sn1 `higherSNH` sn2++-- Test whether the given stable names matches an array computation with sharing.+--+matchStableSeq :: Typeable arrs => StableSeqName arrs -> StableSharingSeq -> Bool+matchStableSeq sn1 (StableSharingSeq sn2 _)+  | Just sn1' <- gcast sn1 = sn1' == sn2+  | otherwise              = False+--}++ -- Occurrence counting -- =================== --- Compute the 'Acc' occurrence map, marks all nodes (both 'Acc' and 'Exp' nodes) with stable names,+-- Compute the 'Acc' occurrence map, marks all nodes (both 'Seq' and 'Exp' nodes) with stable names, -- and drop repeated occurrences of shared 'Acc' and 'Exp' subtrees (Phase One). -- -- We compute a single 'Acc' occurrence map for the whole AST, but one 'Exp' occurrence map for each@@ -981,6 +1237,11 @@     traverseExp :: Typeable e => Level -> Exp e -> IO (RootExp e, Int)     traverseExp = makeOccMapExp config accOccMap +    -- traverseSeq :: forall arrs. Typeable arrs+    --             => Level -> Seq arrs+    --             -> IO (RootSeq arrs, Int)+    -- traverseSeq = makeOccMapRootSeq config accOccMap+     traverseAcc :: forall arrs. Typeable arrs => Level -> Acc arrs -> IO (UnscopedAcc arrs, Int)     traverseAcc lvl acc@(Acc pacc)       = mfix $ \ ~(_, height) -> do@@ -1094,7 +1355,11 @@                                              (acc2', h3) <- traverseAcc lvl acc2                                              return (Stencil2 s' bnd1 acc1' bnd2 acc2',                                                      h1 `max` h2 `max` h3 + 1)+            -- Collect s                   -> reconstruct $ do+            --                                  (s', h) <- traverseSeq lvl s+            --                                  return (Collect s', h + 1) +       where         travA :: Arrays arrs'               => (UnscopedAcc arrs' -> PreAcc UnscopedAcc RootExp arrs)@@ -1146,8 +1411,8 @@               (acc2', h3) <- traverseAcc lvl acc2               return (c fun' acc1' acc2', h1 `max` h2 `max` h3 + 1) -        travAtup :: Tuple.Atuple Acc a-                 -> IO (Tuple.Atuple UnscopedAcc a, Int)+        travAtup :: Atuple Acc a+                 -> IO (Atuple UnscopedAcc a, Int)         travAtup NilAtup          = return (NilAtup, 1)         travAtup (SnocAtup tup a) = do           (tup', h1) <- travAtup tup@@ -1166,7 +1431,35 @@   (UnscopedAcc [] body, height) <- makeOccMapSharingAcc config accOccMap (lvl+1) (f x)   return (const (UnscopedAcc [lvl] body), height) +{--+makeOccMapAfun2 :: (Arrays a, Arrays b, Typeable c)+                => Config+                -> OccMapHash Acc+                -> Level+                -> (Acc a -> Acc b -> Acc c)+                -> IO (Acc a -> Acc b -> UnscopedAcc c, Int)+makeOccMapAfun2 config accOccMap lvl f = do+  let x = Acc (Atag (lvl + 1))+      y = Acc (Atag (lvl + 0))+  --+  (UnscopedAcc [] body, height) <- makeOccMapSharingAcc config accOccMap (lvl+2) (f x y)+  return (\ _ _ -> (UnscopedAcc [lvl, lvl+1] body), height) +makeOccMapAfun3 :: (Arrays a, Arrays b, Arrays c, Typeable d)+                => Config+                -> OccMapHash Acc+                -> Level+                -> (Acc a -> Acc b -> Acc c -> Acc d)+                -> IO (Acc a -> Acc b -> Acc c -> UnscopedAcc d, Int)+makeOccMapAfun3 config accOccMap lvl f = do+  let x = Acc (Atag (lvl + 2))+      y = Acc (Atag (lvl + 1))+      z = Acc (Atag (lvl + 0))+  --+  (UnscopedAcc [] body, height) <- makeOccMapSharingAcc config accOccMap (lvl+3) (f x y z)+  return (\ _ _ _ -> (UnscopedAcc [lvl, lvl+1, lvl+2] body), height)+--}+ -- Generate occupancy information for scalar functions and expressions. Helper -- functions wrapping around 'makeOccMapRootExp' with more specific types. --@@ -1336,6 +1629,7 @@             Shape a             -> reconstruct $ travA Shape a             ShapeSize e         -> reconstruct $ travE1 ShapeSize e             Intersect sh1 sh2   -> reconstruct $ travE2 Intersect sh1 sh2+            Union sh1 sh2       -> reconstruct $ travE2 Union sh1 sh2             Foreign ff f e      -> reconstruct $ do                                       (e', h) <- travE lvl e                                       return  (Foreign ff f e', h+1)@@ -1400,7 +1694,7 @@               (e'  , h2) <- travE lvl e               return (c acc' e', h1 `max` h2 + 1) -        travTup :: Tuple.Tuple Exp tup -> IO (Tuple.Tuple UnscopedExp tup, Int)+        travTup :: Tuple Exp tup -> IO (Tuple UnscopedExp tup, Int)         travTup NilTup          = return (NilTup, 1)         travTup (SnocTup tup e) = do                                     (tup', h1) <- travTup tup@@ -1408,6 +1702,135 @@                                     return (SnocTup tup' e', h1 `max` h2 + 1)  +{--+makeOccMapRootSeq+    :: Typeable arrs+    => Config+    -> OccMapHash Acc+    -> Level+    -> Seq arrs+    -> IO (RootSeq arrs, Int)+makeOccMapRootSeq config accOccMap lvl seq = do+  traceLine "makeOccMapRootSeq" "Enter"+  seqOccMap       <- newASTHashTable+  (seq', height)  <- makeOccMapSharingSeq config accOccMap seqOccMap lvl seq+  frozenSeqOccMap <- freezeOccMap seqOccMap+  traceLine "makeOccMapRootSeq" "Exit"+  return (RootSeq frozenSeqOccMap seq', height)++-- Generate sharing information for an open sequence expression.+--+makeOccMapSharingSeq+    :: Typeable e+    => Config+    -> OccMapHash Acc+    -> OccMapHash Seq+    -> Level                            -- The level of currently bound variables+    -> Seq e+    -> IO (UnscopedSeq e, Int)+makeOccMapSharingSeq config accOccMap seqOccMap = traverseSeq+  where+    traverseAcc :: Typeable arrs => Level -> Acc arrs -> IO (UnscopedAcc arrs, Int)+    traverseAcc = makeOccMapSharingAcc config accOccMap++    traverseAfun1 :: (Arrays a, Typeable b) => Level -> (Acc a -> Acc b) -> IO (Acc a -> UnscopedAcc b, Int)+    traverseAfun1 = makeOccMapAfun1 config accOccMap++    traverseAfun2 :: (Arrays a, Arrays b, Typeable c) => Level -> (Acc a -> Acc b -> Acc c) -> IO (Acc a -> Acc b -> UnscopedAcc c, Int)+    traverseAfun2 = makeOccMapAfun2 config accOccMap++    traverseAfun3 :: (Arrays a, Arrays b, Arrays c, Typeable d) => Level -> (Acc a -> Acc b -> Acc c -> Acc d) -> IO (Acc a -> Acc b -> Acc c -> UnscopedAcc d, Int)+    traverseAfun3 = makeOccMapAfun3 config accOccMap++    traverseExp :: Typeable e => Level -> Exp e -> IO (RootExp e, Int)+    traverseExp = makeOccMapExp config accOccMap++    traverseFun2 :: (Elt a, Elt b, Typeable c)+                 => Level+                 -> (Exp a -> Exp b -> Exp c)+                 -> IO (Exp a -> Exp b -> RootExp c, Int)+    traverseFun2 = makeOccMapFun2 config accOccMap++    traverseTup :: Level -> Atuple Seq tup -> IO (Atuple UnscopedSeq tup, Int)+    traverseTup _   NilAtup          = return (NilAtup, 1)+    traverseTup lvl (SnocAtup tup s) = do+                                        (tup', h1) <- traverseTup lvl tup+                                        (s'  , h2) <- traverseSeq lvl s+                                        return (SnocAtup tup' s', h1 `max` h2 + 1)++    traverseSeq :: forall arrs. Typeable arrs => Level -> Seq arrs -> IO (UnscopedSeq arrs, Int)+    traverseSeq lvl acc@(Seq seq)+      = mfix $ \ ~(_, height) -> do+          -- Compute stable name and enter it into the occurrence map+          --+          sn                         <- makeStableAST acc+          heightIfRepeatedOccurrence <- enterOcc seqOccMap (StableASTName sn) height++          traceLine (showPreSeqOp seq) $ do+            let hash = show (hashStableName sn)+            case heightIfRepeatedOccurrence of+              Just height -> "REPEATED occurrence (sn = " ++ hash ++ "; height = " ++ show height ++ ")"+              Nothing     -> "first occurrence (sn = " ++ hash ++ ")"++          -- Reconstruct the computation in shared form.+          --+          -- In case of a repeated occurrence, the height comes from the occurrence map; otherwise+          -- it is computed by the traversal function passed in 'newAcc'. See also 'enterOcc'.+          --+          -- NB: This function can only be used in the case alternatives below; outside of the+          --     case we cannot discharge the 'Arrays arrs' constraint.+          --+          let producer :: (arrs ~ [a], Arrays a)+                       => IO (PreSeq UnscopedAcc UnscopedSeq RootExp arrs, Int)+                       -> IO (UnscopedSeq arrs, Int)+              producer newSeq+                = case heightIfRepeatedOccurrence of+                    Just height | recoverSeqSharing config+                      -> return (UnscopedSeq (SvarSharing (StableNameHeight sn height)), height)+                    _ -> do (seq, height) <- newSeq+                            return (UnscopedSeq (SeqSharing (StableNameHeight sn height) seq), height)++          let consumer :: IO (PreSeq UnscopedAcc UnscopedSeq RootExp arrs, Int)+                       -> IO (UnscopedSeq arrs, Int)+              consumer newSeq+                = do (seq, height) <- newSeq+                     return (UnscopedSeq (SeqSharing (StableNameHeight sn height) seq), height)++          case seq of+            StreamIn arrs -> producer $ return (StreamIn arrs, 1)+            ToSeq sl acc -> producer $ do+              (acc', h1) <- traverseAcc lvl acc+              return (ToSeq sl acc', h1 + 1)+            MapSeq afun s -> producer $ do+              (afun', h1) <- traverseAfun1 lvl afun+              (s'   , h2) <- traverseSeq lvl s+              return (MapSeq afun' s', h1 `max` h2 + 1)+            ZipWithSeq afun s1 s2 -> producer $ do+              (afun', h1) <- traverseAfun2 lvl afun+              (s1'  , h2) <- traverseSeq lvl s1+              (s2'  , h3) <- traverseSeq lvl s2+              return (ZipWithSeq afun' s1' s2', h1 `max` h2 `max` h3 + 1)+            ScanSeq fun e s -> producer $ do+              (fun', h1) <- traverseFun2 lvl fun+              (e',  h2) <- traverseExp lvl e+              (s'   , h3) <- traverseSeq lvl s+              return (ScanSeq fun' e' s', h1 `max` h2 `max` h3 + 1)+            FoldSeq fun e s -> consumer $ do+              (fun', h1) <- traverseFun2 lvl fun+              (e'  , h2) <- traverseExp lvl e+              (s'  , h3) <- traverseSeq lvl s+              return (FoldSeq fun' e' s', h1 `max` h2 `max` h3 + 1)+            FoldSeqFlatten afun acc s -> consumer $ do+              (afun', h1) <- traverseAfun3 lvl afun+              (acc',  h2) <- traverseAcc lvl acc+              (s'   , h3) <- traverseSeq lvl s+              return (FoldSeqFlatten afun' acc' s', h1 `max` h2 `max` h3 + 1)+            Stuple t -> consumer $ do+              (t', h1) <- traverseTup lvl t+              return (Stuple t', h1 + 1)+--}++ -- Type used to maintain how often each shared subterm, so far, occurred during a bottom-up sweep, -- as well as the relation between subterms. It is comprised of a list of terms and a graph giving -- their relation.@@ -1419,7 +1842,7 @@ --   - A term may have a final occurrence count of only 1 iff it is either a free variable ('Atag' --     or 'Tag') or an array computation lifted out of an expression. --   - All 'Exp' node counts precede all 'Acc' node counts as we don't share 'Exp' nodes across 'Acc'---     nodes.+--     nodes. Similarly, all 'Seq' nodes precede 'Acc' nodes and 'Exp' nodes precede 'Seq' nodes. -- -- We determine the subterm property by using the tree height in 'StableNameHeight'.  Trees get -- smaller towards the end of a 'NodeCounts' list.  The height of free variables ('Atag' or 'Tag')@@ -1453,6 +1876,7 @@  data NodeCount = AccNodeCount StableSharingAcc Int                | ExpNodeCount StableSharingExp Int+               -- SeqNodeCount StableSharingSeq Int                deriving Show  -- Empty node counts@@ -1484,6 +1908,20 @@     hs = map nodeName subterms     g' = Map.fromList $ (k, Set.empty) : [(h, Set.singleton k) | h <- hs] +{--+-- Insert an Seq node into the node counts, assuming that it is a superterm of the all the existing+-- nodes.+--+-- TODO: Perform cycle detection here.+insertSeqNode :: StableSharingSeq -> NodeCounts -> NodeCounts+insertSeqNode ssa@(StableSharingSeq (StableNameHeight sn _) _) (subterms,g)+  = ([SeqNodeCount ssa 1], g') +++ (subterms,g)+  where+    k  = NodeName sn+    hs = map nodeName subterms+    g' = Map.fromList $ (k, Set.empty) : [(h, Set.singleton k) | h <- hs]+--}+ -- Remove nodes that aren't in the list from the graph. -- -- RCE: This is no longer necessary when NDP is supported.@@ -1495,6 +1933,7 @@ nodeName :: NodeCount -> NodeName nodeName (AccNodeCount (StableSharingAcc (StableNameHeight sn _) _) _) = NodeName sn nodeName (ExpNodeCount (StableSharingExp (StableNameHeight sn _) _) _) = NodeName sn+-- nodeName (SeqNodeCount (StableSharingSeq (StableNameHeight sn _) _) _) = NodeName sn  -- Combine node counts that belong to the same node. --@@ -1517,10 +1956,22 @@       | se1 == se2          = ExpNodeCount (se1 `pickNoneVar` se2) (count1 + count2) : ys'       | se1 `higherSSE` se2 = x : ys       | otherwise           = y : insert x ys'+    -- insert x@(SeqNodeCount se1 count1) ys@(y@(SeqNodeCount se2 count2) : ys')+    --   | se1 == se2          = SeqNodeCount (se1 `pickNoneSvar` se2) (count1 + count2) : ys'+    --   | se1 `higherSSS` se2 = x : ys+    --   | otherwise           = y : insert x ys'     insert x@(AccNodeCount _ _) (y@(ExpNodeCount _ _) : ys')       = y : insert x ys'     insert x@(ExpNodeCount _ _) (y@(AccNodeCount _ _) : ys')       = x : insert y ys'+    -- insert x@(SeqNodeCount _ _) (y@(ExpNodeCount _ _) : ys')+    --   = y : insert x ys'+    -- insert x@(ExpNodeCount _ _) (y@(SeqNodeCount _ _) : ys')+    --   = x : insert y ys'+    -- insert x@(AccNodeCount _ _) (y@(SeqNodeCount _ _) : ys')+    --   = y : insert x ys'+    -- insert x@(SeqNodeCount _ _) (y@(AccNodeCount _ _) : ys')+    --   = x : insert y ys'      (StableSharingAcc _ (AvarSharing _)) `pickNoneAvar` sa2  = sa2     sa1                                  `pickNoneAvar` _sa2 = sa1@@ -1528,6 +1979,10 @@     (StableSharingExp _ (VarSharing _))  `pickNoneVar`  sa2  = sa2     sa1                                  `pickNoneVar`  _sa2 = sa1 +    -- pickNoneSvar :: StableSharingSeq -> StableSharingSeq -> StableSharingSeq+    -- (StableSharingSeq _ (SvarSharing _)) `pickNoneSvar` sa2  = sa2+    -- sa1                                  `pickNoneSvar` _sa2 = sa1+ -- Build an initial environment for the tag values given in the first argument for traversing an -- array expression.  The 'StableSharingAcc's for all tags /actually used/ in the expressions are -- in the second argument. (Tags are not used if a bound variable has no usage occurrence.)@@ -1621,7 +2076,7 @@     -> (ScopedAcc a, [StableSharingAcc]) determineScopesAcc config fvs accOccMap rootAcc   = let (sharingAcc, (counts, _)) = determineScopesSharingAcc config accOccMap rootAcc-        unboundTrees         = filter (not . isFreeVar) counts+        unboundTrees              = filter (not . isFreeVar) counts     in     if all isFreeVar counts        then (sharingAcc, buildInitialEnvAcc fvs [sa | AccNodeCount sa _ <- counts])@@ -1741,9 +2196,13 @@                                      in                                      reconstruct (Stencil2 st' bnd1 acc1' bnd2 acc2')                                        (accCount1 +++ accCount2 +++ accCount3)+          -- Collect seq             -> let+          --                              (seq', accCount1) = scopesSeq seq+          --                            in+          --                            reconstruct (Collect seq') accCount1+       where-        travEA :: Arrays arrs-               => (ScopedExp e -> ScopedAcc arrs' -> PreAcc ScopedAcc ScopedExp arrs)+        travEA :: (ScopedExp e -> ScopedAcc arrs' -> PreAcc ScopedAcc ScopedExp arrs)                -> RootExp e                -> UnscopedAcc arrs'                -> (ScopedAcc arrs, NodeCounts)@@ -1752,7 +2211,7 @@             (e'  , accCount1) = scopesExp e             (acc', accCount2) = scopesAcc acc -        travF2A :: (Elt a, Elt b, Arrays arrs)+        travF2A :: (Elt a, Elt b)                 => ((Exp a -> Exp b -> ScopedExp c) -> ScopedAcc arrs'                     -> PreAcc ScopedAcc ScopedExp arrs)                 -> (Exp a -> Exp b -> RootExp c)@@ -1763,7 +2222,7 @@             (f'  , accCount1) = scopesFun2 f             (acc', accCount2) = scopesAcc  acc -        travF2EA :: (Elt a, Elt b, Arrays arrs)+        travF2EA :: (Elt a, Elt b)                  => ((Exp a -> Exp b -> ScopedExp c) -> ScopedExp e                      -> ScopedAcc arrs' -> PreAcc ScopedAcc ScopedExp arrs)                  -> (Exp a -> Exp b -> RootExp c)@@ -1776,7 +2235,7 @@             (e'  , accCount2) = scopesExp  e             (acc', accCount3) = scopesAcc  acc -        travF2A2 :: (Elt a, Elt b, Arrays arrs)+        travF2A2 :: (Elt a, Elt b)                  => ((Exp a -> Exp b -> ScopedExp c) -> ScopedAcc arrs1                      -> ScopedAcc arrs2 -> PreAcc ScopedAcc ScopedExp arrs)                  -> (Exp a -> Exp b -> RootExp c)@@ -1790,16 +2249,15 @@             (acc1', accCount2) = scopesAcc  acc1             (acc2', accCount3) = scopesAcc  acc2 -        travAtup ::  Tuple.Atuple UnscopedAcc a-                 -> (Tuple.Atuple ScopedAcc a, NodeCounts)+        travAtup ::  Atuple UnscopedAcc a+                 -> (Atuple ScopedAcc a, NodeCounts)         travAtup NilAtup          = (NilAtup, noNodeCounts)         travAtup (SnocAtup tup a) = let (tup', accCountT) = travAtup tup                                         (a',   accCountA) = scopesAcc a                                     in                                     (SnocAtup tup' a', accCountT +++ accCountA) -        travA :: Arrays arrs-              => (ScopedAcc arrs' -> PreAcc ScopedAcc ScopedExp arrs)+        travA :: (ScopedAcc arrs' -> PreAcc ScopedAcc ScopedExp arrs)               -> UnscopedAcc arrs'               -> (ScopedAcc arrs, NodeCounts)         travA c acc = reconstruct (c acc') accCount@@ -1823,8 +2281,8 @@         -- In either case, any completed 'NodeCounts' are injected as bindings using 'AletSharing'         -- node.         ---        reconstruct :: Arrays arrs-                    => PreAcc ScopedAcc ScopedExp arrs -> NodeCounts+        reconstruct :: PreAcc ScopedAcc ScopedExp arrs+                    -> NodeCounts                     -> (ScopedAcc arrs, NodeCounts)         reconstruct newAcc@(Atag _) _subCount               -- free variable => replace by a sharing variable regardless of the number of@@ -1884,7 +2342,11 @@               in    isCompleted nc                  && all (bindable !!) unbound             isBindable _ _ (ExpNodeCount _ _) = False+            -- isBindable _ _ (SeqNodeCount _ _) = False +    -- scopesSeq :: forall arrs. RootSeq arrs -> (ScopedSeq arrs, NodeCounts)+    -- scopesSeq = determineScopesSeq config accOccMap+     scopesExp :: RootExp t -> (ScopedExp t, NodeCounts)     scopesExp = determineScopesExp config accOccMap @@ -1953,10 +2415,10 @@ determineScopesExp config accOccMap (RootExp expOccMap exp@(UnscopedExp fvs _))   = let         ((ScopedExp [] expWithScopes), (nodeCounts,graph)) = determineScopesSharingExp config accOccMap expOccMap exp-        (expCounts, accCounts)          = break isAccNodeCount nodeCounts+        (expCounts, accCounts)          = partition isExpNodeCount nodeCounts -        isAccNodeCount AccNodeCount{}   = True-        isAccNodeCount _                = False+        isExpNodeCount ExpNodeCount{}   = True+        isExpNodeCount _                = False     in     (ScopedExp (buildInitialEnvExp fvs [se | ExpNodeCount se _ <- expCounts]) expWithScopes, cleanCounts (accCounts,graph)) @@ -2019,9 +2481,10 @@           Shape a               -> travA Shape a           ShapeSize e           -> travE1 ShapeSize e           Intersect sh1 sh2     -> travE2 Intersect sh1 sh2+          Union sh1 sh2         -> travE2 Union sh1 sh2           Foreign ff f e        -> travE1 (Foreign ff f) e       where-        travTup :: Tuple.Tuple UnscopedExp tup -> (Tuple.Tuple ScopedExp tup, NodeCounts)+        travTup :: Tuple UnscopedExp tup -> (Tuple ScopedExp tup, NodeCounts)         travTup NilTup          = (NilTup, noNodeCounts)         travTup (SnocTup tup e) = let                                     (tup', accCountT) = travTup tup@@ -2165,8 +2628,154 @@               in    isCompleted nc                  && all (bindable !!) unbound             isBindable _ _ (AccNodeCount _ _) = False+            -- isBindable _ _ (SeqNodeCount _ _) = False +{--+determineScopesSeq+    :: Config+    -> OccMap Acc+    -> RootSeq t+    -> (ScopedSeq t, NodeCounts)          -- Root (closed) expression plus Acc node counts+determineScopesSeq config accOccMap (RootSeq seqOccMap seq)+  = let+        (ScopedSeq seqWithScopes, (nodeCounts,graph)) = determineScopesSharingSeq config accOccMap seqOccMap seq+        binds      = [s | SeqNodeCount s _ <- nodeCounts]+        lets       = foldl (flip (.)) id . map (\x y -> SletSharing x (ScopedSeq y)) $ binds+        sharingSeq = lets seqWithScopes+        newCounts  = filter (not . isSeqCount) nodeCounts+        isSeqCount SeqNodeCount{} = True+        isSeqCount _              = False+    in+    (ScopedSeq sharingSeq, cleanCounts (newCounts,graph)) +determineScopesSharingSeq+  :: Config+  -> OccMap Acc+  -> OccMap Seq+  -> UnscopedSeq t+  -> (ScopedSeq t, NodeCounts)+determineScopesSharingSeq config accOccMap _seqOccMap = scopesSeq+  where+    scopesAcc :: UnscopedAcc a -> (ScopedAcc a, NodeCounts)+    scopesAcc = determineScopesSharingAcc config accOccMap++    scopesExp :: RootExp t -> (ScopedExp t, NodeCounts)+    scopesExp = determineScopesExp config accOccMap++    scopesFun2 :: (Elt e1, Elt e2)+               => (Exp e1 -> Exp e2 -> RootExp e3)+               -> (Exp e1 -> Exp e2 -> ScopedExp e3, NodeCounts)+    scopesFun2 f = (\_ _ -> body, counts)+      where+        (body, counts) = scopesExp (f undefined undefined)++    -- The lambda bound variable is at this point already irrelevant; for details, see+    -- Note [Traversing functions and side effects]+    --+    scopesAfun1 :: Arrays a1 => (Acc a1 -> UnscopedAcc a2) -> (Acc a1 -> ScopedAcc a2, NodeCounts)+    scopesAfun1 f = (const (ScopedAcc ssa body'), (counts',graph))+      where+        body@(UnscopedAcc fvs _) = f undefined+        ((ScopedAcc [] body'), (counts,graph)) = scopesAcc body+        ssa     = buildInitialEnvAcc fvs [sa | AccNodeCount sa _ <- freeCounts]+        (freeCounts, counts') = partition isBoundHere counts++        isBoundHere (AccNodeCount (StableSharingAcc _ (AccSharing _ (Atag i))) _) = i `elem` fvs+        isBoundHere _                                                             = False++    scopesAfun2 :: (Arrays a1, Arrays a2) => (Acc a1 -> Acc a2 -> UnscopedAcc a3) -> (Acc a1 -> Acc a2 -> ScopedAcc a3, NodeCounts)+    scopesAfun2 f = (\ _ _ -> (ScopedAcc ssa body'), (counts',graph))+      where+        body@(UnscopedAcc fvs _) = f undefined undefined+        ((ScopedAcc [] body'), (counts,graph)) = scopesAcc body+        ssa     = buildInitialEnvAcc fvs [sa | AccNodeCount sa _ <- freeCounts]+        (freeCounts, counts') = partition isBoundHere counts++        isBoundHere (AccNodeCount (StableSharingAcc _ (AccSharing _ (Atag i))) _) = i `elem` fvs+        isBoundHere _                                                             = False++    scopesAfun3 :: (Arrays a1, Arrays a2, Arrays a3) => (Acc a1 -> Acc a2 -> Acc a3 -> UnscopedAcc a4) -> (Acc a1 -> Acc a2 -> Acc a3 -> ScopedAcc a4, NodeCounts)+    scopesAfun3 f = (\ _ _ _ -> (ScopedAcc ssa body'), (counts',graph))+      where+        body@(UnscopedAcc fvs _) = f undefined undefined undefined+        ((ScopedAcc [] body'), (counts,graph)) = scopesAcc body+        ssa     = buildInitialEnvAcc fvs [sa | AccNodeCount sa _ <- freeCounts]+        (freeCounts, counts') = partition isBoundHere counts++        isBoundHere (AccNodeCount (StableSharingAcc _ (AccSharing _ (Atag i))) _) = i `elem` fvs+        isBoundHere _                                                             = False++    scopesTup :: Atuple UnscopedSeq tup -> (Atuple ScopedSeq tup, NodeCounts)+    scopesTup NilAtup          = (NilAtup, noNodeCounts)+    scopesTup (SnocAtup tup s) = let+                                   (tup', accCountT) = scopesTup tup+                                   (s'  , accCountS) = scopesSeq s+                                 in+                                 (SnocAtup tup' s', accCountT +++ accCountS)++    scopesSeq :: forall t. UnscopedSeq t -> (ScopedSeq t, NodeCounts)+    scopesSeq (UnscopedSeq (SletSharing _ _))+      = $internalError "determineScopesSharingSeq: scopesSeq" "unexpected 'LetSharing'"+    scopesSeq (UnscopedSeq (SvarSharing sn))+      = (ScopedSeq (SvarSharing sn), StableSharingSeq sn (SvarSharing sn) `insertSeqNode` noNodeCounts)++    scopesSeq (UnscopedSeq (SeqSharing sn s)) =+      case s of+        StreamIn arrs -> producer (StreamIn arrs) noNodeCounts+        ToSeq sl acc   -> let+                            (acc', accCount1) = scopesAcc acc+                          in producer (ToSeq sl acc') accCount1+        MapSeq     afun s'  -> let+                                 (afun', accCount1) = scopesAfun1 afun+                                 (s''  , accCount2) = scopesSeq s'+                               in producer (MapSeq afun' s'') (accCount1 +++ accCount2)+        ZipWithSeq afun s1 s2 -> let+                                   (afun', accCount1) = scopesAfun2 afun+                                   (s1'  , accCount2) = scopesSeq s1+                                   (s2'  , accCount3) = scopesSeq s2+                                 in producer (ZipWithSeq afun' s1' s2') (accCount1 +++ accCount2 +++ accCount3)+        ScanSeq fun e s' -> let+                              (fun', accCount1) = scopesFun2 fun+                              (e'  , accCount2) = scopesExp e+                              (s'' , accCount3) = scopesSeq s'+                            in producer (ScanSeq fun' e' s'') (accCount1 +++ accCount2 +++ accCount3)+        FoldSeq fun e s' -> let+                              (fun', accCount1) = scopesFun2 fun+                              (e'  , accCount2) = scopesExp e+                              (s'' , accCount3) = scopesSeq s'+                            in consumer (FoldSeq fun' e' s'') (accCount1 +++ accCount2 +++ accCount3)+        FoldSeqFlatten afun acc s' ->+                               let+                                 (afun', accCount1) = scopesAfun3 afun+                                 (acc' , accCount2) = scopesAcc acc+                                 (s''  , accCount3) = scopesSeq s'+                               in consumer (FoldSeqFlatten afun' acc' s'') (accCount1 +++ accCount2 +++ accCount3)+        Stuple tup          -> let+                                 (tup', accCount1) = scopesTup tup+                               in consumer (Stuple tup') accCount1+      where+        -- All producers must be replaced by sharing variables+        --+        producer :: (t ~ [a], Arrays a)+                 => PreSeq ScopedAcc ScopedSeq ScopedExp t+                 -> NodeCounts+                 -> (ScopedSeq t, NodeCounts)+        producer newSeq subCount+          = let allCount = StableSharingSeq sn (SeqSharing sn newSeq) `insertSeqNode` subCount+            in+            tracePure "Producer" (show allCount)+            (ScopedSeq (SvarSharing sn), allCount)++        -- Consumers cannot be shared.+        --+        consumer :: PreSeq ScopedAcc ScopedSeq ScopedExp t+                 -> NodeCounts+                 -> (ScopedSeq t, NodeCounts)+        consumer newSeq subCount+          = tracePure "Consumer" (show subCount)+            (ScopedSeq (SeqSharing sn newSeq), subCount)+--}+ -- |Recover sharing information and annotate the HOAS AST with variable and let binding -- annotations.  The first argument determines whether array computations are floated out of -- expressions irrespective of whether they are shared or not — 'True' implies floating them out.@@ -2224,21 +2833,44 @@     (ScopedExp [] sharingExp, sse)  +{--+recoverSharingSeq+    :: Typeable e+    => Config+    -> Seq e+    -> (ScopedSeq e, [StableSharingSeq])+{-# NOINLINE recoverSharingSeq #-}+recoverSharingSeq config seq+  = let+        (rootSeq, accOccMap) = unsafePerformIO $ do+          accOccMap       <- newASTHashTable+          (seq', _)       <- makeOccMapRootSeq config accOccMap 0 seq+          frozenAccOccMap <- freezeOccMap accOccMap++          return (seq', frozenAccOccMap)++        (ScopedSeq sharingSeq, (ns, _)) =+          determineScopesSeq config accOccMap rootSeq+    in+    (ScopedSeq sharingSeq, [a | SeqNodeCount a _ <- ns])+--}++ -- Debugging -- ---------  traceLine :: String -> String -> IO () traceLine header msg-  = Debug.traceMessage Debug.dump_sharing+  = Debug.traceIO Debug.dump_sharing   $ header ++ ": " ++ msg  traceChunk :: String -> String -> IO () traceChunk header msg-  = Debug.traceMessage Debug.dump_sharing+  = Debug.traceIO Debug.dump_sharing   $ header ++ "\n      " ++ msg  tracePure :: String -> String -> a -> a tracePure header msg-  = Debug.tracePure Debug.dump_sharing+  = Debug.trace Debug.dump_sharing   $ header ++ ": " ++ msg 
Data/Array/Accelerate/Trafo/Shrink.hs view
@@ -5,10 +5,10 @@ {-# LANGUAGE ViewPatterns        #-} -- | -- Module      : Data.Array.Accelerate.Trafo.Shrink--- Copyright   : [2012..2014] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2012..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell -- License     : BSD3 ----- Maintainer  : Manuel M T Chakravarty <chak@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -39,11 +39,11 @@ -- standard library import Data.Monoid import Control.Applicative                              hiding ( Const )-import Prelude                                          hiding ( exp )+import Prelude                                          hiding ( exp, seq )  -- friends import Data.Array.Accelerate.AST-import Data.Array.Accelerate.Tuple+import Data.Array.Accelerate.Array.Sugar               hiding ( Any ) import Data.Array.Accelerate.Trafo.Base import Data.Array.Accelerate.Trafo.Substitution @@ -56,10 +56,10 @@    shrink = snd . shrink' -instance Shrink (PreOpenExp acc env aenv e) where+instance Kit acc => Shrink (PreOpenExp acc env aenv e) where   shrink' = shrinkExp -instance Shrink (PreOpenFun acc env aenv f) where+instance Kit acc => Shrink (PreOpenFun acc env aenv f) where   shrink' = shrinkFun  @@ -70,16 +70,17 @@ -- instance of beta-reduction to cases where the bound variable is used zero -- (dead-code elimination) or one (linear inlining) times. ---shrinkExp :: PreOpenExp acc env aenv t -> (Bool, PreOpenExp acc env aenv t)+shrinkExp :: Kit acc => PreOpenExp acc env aenv t -> (Bool, PreOpenExp acc env aenv t) shrinkExp = Stats.substitution "shrink exp" . first getAny . shrinkE   where     -- If the bound variable is used at most this many times, it will be inlined     -- into the body. In cases where it is not used at all, this is equivalent     -- to dead-code elimination.     --+    lIMIT :: Int     lIMIT = 1 -    shrinkE :: PreOpenExp acc env aenv t -> (Any, PreOpenExp acc env aenv t)+    shrinkE :: Kit acc => PreOpenExp acc env aenv t -> (Any, PreOpenExp acc env aenv t)     shrinkE exp = case exp of       Let bnd body         | Var _ <- bnd  -> Stats.inline "Var"   . yes $ shrinkE (inline body bnd)@@ -116,13 +117,14 @@       Shape a                   -> pure (Shape a)       ShapeSize sh              -> ShapeSize <$> shrinkE sh       Intersect sh sz           -> Intersect <$> shrinkE sh <*> shrinkE sz+      Union sh sz               -> Union <$> shrinkE sh <*> shrinkE sz       Foreign ff f e            -> Foreign ff <$> shrinkF f <*> shrinkE e -    shrinkT :: Tuple (PreOpenExp acc env aenv) t -> (Any, Tuple (PreOpenExp acc env aenv) t)+    shrinkT :: Kit acc => Tuple (PreOpenExp acc env aenv) t -> (Any, Tuple (PreOpenExp acc env aenv) t)     shrinkT NilTup        = pure NilTup     shrinkT (SnocTup t e) = SnocTup <$> shrinkT t <*> shrinkE e -    shrinkF :: PreOpenFun acc env aenv t -> (Any, PreOpenFun acc env aenv t)+    shrinkF :: Kit acc => PreOpenFun acc env aenv t -> (Any, PreOpenFun acc env aenv t)     shrinkF = first Any . shrinkFun      first :: (a -> a') -> (a,b) -> (a',b)@@ -131,7 +133,7 @@     yes :: (Any, x) -> (Any, x)     yes (_, x) = (Any True, x) -shrinkFun :: PreOpenFun acc env aenv f -> (Bool, PreOpenFun acc env aenv f)+shrinkFun :: Kit acc => PreOpenFun acc env aenv f -> (Bool, PreOpenFun acc env aenv f) shrinkFun (Lam f)  = Lam  <$> shrinkFun f shrinkFun (Body b) = Body <$> shrinkExp b @@ -188,7 +190,38 @@       Backpermute sh f a        -> Backpermute (shrinkE sh) (shrinkF f) (shrinkAcc a)       Stencil f b a             -> Stencil (shrinkF f) b (shrinkAcc a)       Stencil2 f b1 a1 b2 a2    -> Stencil2 (shrinkF f) b1 (shrinkAcc a1) b2 (shrinkAcc a2)+      -- Collect s                 -> Collect (shrinkS s) +{--+    shrinkS :: PreOpenSeq acc aenv' senv a -> PreOpenSeq acc aenv' senv a+    shrinkS seq =+      case seq of+        Producer p s -> Producer (shrinkP p) (shrinkS s)+        Consumer c   -> Consumer (shrinkC c)+        Reify ix     -> Reify ix++    shrinkP :: Producer acc aenv' senv a -> Producer acc aenv' senv a+    shrinkP p =+      case p of+        StreamIn arrs        -> StreamIn arrs+        ToSeq sl slix a      -> ToSeq sl slix (shrinkAcc a)+        MapSeq f x           -> MapSeq (shrinkAF f) x+        ChunkedMapSeq f x    -> ChunkedMapSeq (shrinkAF f) x+        ZipWithSeq f x y     -> ZipWithSeq (shrinkAF f) x y+        ScanSeq f e x        -> ScanSeq (shrinkF f) (shrinkE e) x++    shrinkC :: Consumer acc aenv' senv a -> Consumer acc aenv' senv a+    shrinkC c =+      case c of+        FoldSeq f e x        -> FoldSeq (shrinkF f) (shrinkE e) x+        FoldSeqFlatten f a x -> FoldSeqFlatten (shrinkAF f) (shrinkAcc a) x+        Stuple t             -> Stuple (shrinkCT t)++    shrinkCT :: Atuple (Consumer acc aenv' senv) t -> Atuple (Consumer acc aenv' senv) t+    shrinkCT NilAtup        = NilAtup+    shrinkCT (SnocAtup t c) = SnocAtup (shrinkCT t) (shrinkC c)+--}+     shrinkE :: PreOpenExp acc env aenv' t -> PreOpenExp acc env aenv' t     shrinkE exp = case exp of       Let bnd body              -> Let (shrinkE bnd) (shrinkE body)@@ -214,6 +247,7 @@       Shape a                   -> Shape (shrinkAcc a)       ShapeSize sh              -> ShapeSize (shrinkE sh)       Intersect sh sz           -> Intersect (shrinkE sh) (shrinkE sz)+      Union sh sz               -> Union (shrinkE sh) (shrinkE sz)       Foreign ff f e            -> Foreign ff (shrinkF f) (shrinkE e)      shrinkF :: PreOpenFun acc env aenv' f -> PreOpenFun acc env aenv' f@@ -242,8 +276,8 @@     -> UsesOfAcc acc     -> ReduceAcc acc basicReduceAcc unwrapAcc countAcc (unwrapAcc -> bnd) body@(unwrapAcc -> pbody)-  | Avar _ <- bnd       = Stats.inline "Avar"  . Just $ rebuildA rebuildAcc (subAtop bnd) pbody-  | uses <= lIMIT       = Stats.betaReduce msg . Just $ rebuildA rebuildAcc (subAtop bnd) pbody+  | Avar _ <- bnd       = Stats.inline "Avar"  . Just $ rebuildA (subAtop bnd) pbody+  | uses <= lIMIT       = Stats.betaReduce msg . Just $ rebuildA (subAtop bnd) pbody   | otherwise           = Nothing   where     -- If the bound variable is used at most this many times, it will be inlined@@ -271,7 +305,7 @@     countE :: PreOpenExp acc env aenv e -> Int     countE exp = case exp of       Var this-        | Just REFL <- match this idx   -> 1+        | Just Refl <- match this idx   -> 1         | otherwise                     -> 0       --       Let bnd body              -> countE bnd + usesOfExp (SuccIdx idx) body@@ -296,6 +330,7 @@       Shape _                   -> 0       ShapeSize sh              -> countE sh       Intersect sh sz           -> countE sh + countE sz+      Union sh sz               -> countE sh + countE sz       Foreign _ _ e             -> countE e      countF :: Idx env' s -> PreOpenFun acc env' aenv f -> Int@@ -314,19 +349,22 @@ type UsesOfAcc acc = forall aenv s t. Bool -> Idx aenv s -> acc aenv t -> Int  usesOfPreAcc-    :: forall acc aenv s t. Kit acc-    => Bool+    :: forall acc aenv s t.+       Bool     -> UsesOfAcc  acc     -> Idx            aenv s     -> PreOpenAcc acc aenv t     -> Int-usesOfPreAcc withShape countAcc idx = countP+usesOfPreAcc withShape countAcc idx = count   where-    countP :: PreOpenAcc acc aenv a -> Int-    countP pacc = case pacc of-      Avar this-        | Just REFL <- match this idx   -> 1-        | otherwise                     -> 0+    countIdx :: Idx aenv a -> Int+    countIdx this+        | Just Refl <- match this idx   = 1+        | otherwise                     = 0++    count :: PreOpenAcc acc aenv a -> Int+    count pacc = case pacc of+      Avar this                 -> countIdx this       --       Alet bnd body             -> countA bnd + countAcc withShape (SuccIdx idx) body       Atuple tup                -> countAT tup@@ -358,9 +396,7 @@       Backpermute sh f a        -> countE sh + countF f  + countA a       Stencil f _ a             -> countF f  + countA a       Stencil2 f _ a1 _ a2      -> countF f  + countA a1 + countA a2--    countA :: acc aenv a -> Int-    countA = countAcc withShape idx+      -- Collect s                 -> countS s      countE :: PreOpenExp acc env aenv e -> Int     countE exp = case exp of@@ -386,11 +422,21 @@       LinearIndex a i           -> countA a + countE i       ShapeSize sh              -> countE sh       Intersect sh sz           -> countE sh + countE sz+      Union sh sz               -> countE sh + countE sz       Shape a         | withShape             -> countA a         | otherwise             -> 0       Foreign _ _ e             -> countE e +    countA :: acc aenv a -> Int+    countA = countAcc withShape idx++    -- countAF :: PreOpenAfun acc aenv' f+    --         -> Idx aenv' s+    --         -> Int+    -- countAF (Alam f)  v = countAF f (SuccIdx v)+    -- countAF (Abody a) v = countAcc withShape v a+     countF :: PreOpenFun acc env aenv f -> Int     countF (Lam  f) = countF f     countF (Body b) = countE b@@ -402,4 +448,34 @@     countAT :: Atuple (acc aenv) a -> Int     countAT NilAtup        = 0     countAT (SnocAtup t a) = countAT t + countA a++{--+    countS :: PreOpenSeq acc aenv senv arrs -> Int+    countS seq =+      case seq of+        Producer p s -> countP p + countS s+        Consumer c   -> countC c+        Reify _      -> 0++    countP :: Producer acc aenv senv arrs -> Int+    countP p =+      case p of+        StreamIn _           -> 0+        ToSeq _ _ a          -> countA a+        MapSeq f _           -> countAF f idx+        ChunkedMapSeq f _    -> countAF f idx+        ZipWithSeq f _ _     -> countAF f idx+        ScanSeq f e _        -> countF f + countE e++    countC :: Consumer acc aenv senv arrs -> Int+    countC c =+      case c of+        FoldSeq f e _        -> countF f + countE e+        FoldSeqFlatten f a _ -> countAF f idx + countA a+        Stuple t             -> countCT t++    countCT :: Atuple (Consumer acc aenv senv) t' -> Int+    countCT NilAtup        = 0+    countCT (SnocAtup t c) = countCT t + countC c+--} 
Data/Array/Accelerate/Trafo/Simplify.hs view
@@ -1,17 +1,20 @@-{-# LANGUAGE BangPatterns         #-}+{-# LANGUAGE CPP                  #-}+{-# LANGUAGE FlexibleContexts     #-} {-# LANGUAGE FlexibleInstances    #-} {-# LANGUAGE GADTs                #-} {-# LANGUAGE PatternGuards        #-}+{-# LANGUAGE RecordWildCards      #-} {-# LANGUAGE ScopedTypeVariables  #-} {-# LANGUAGE TemplateHaskell      #-} {-# LANGUAGE TypeOperators        #-} {-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE ViewPatterns         #-} -- | -- Module      : Data.Array.Accelerate.Trafo.Simplify--- Copyright   : [2012..2014] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2012..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell -- License     : BSD3 ----- Maintainer  : Manuel M T Chakravarty <chak@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -23,26 +26,27 @@ ) where  -- standard library+import Data.Label import Data.List                                        ( nubBy ) import Data.Maybe import Data.Monoid import Data.Typeable+import Text.Printf import Control.Applicative                              hiding ( Const ) import Prelude                                          hiding ( exp, iterate )  -- friends import Data.Array.Accelerate.AST                        hiding ( prj )+import Data.Array.Accelerate.Analysis.Shape import Data.Array.Accelerate.Error-import Data.Array.Accelerate.Tuple-import Data.Array.Accelerate.Analysis.Match-import Data.Array.Accelerate.Trafo.Base+import Data.Array.Accelerate.Product import Data.Array.Accelerate.Trafo.Algebra+import Data.Array.Accelerate.Trafo.Base import Data.Array.Accelerate.Trafo.Shrink import Data.Array.Accelerate.Trafo.Substitution-import Data.Array.Accelerate.Analysis.Shape-import Data.Array.Accelerate.Array.Sugar                ( Elt, Shape, Slice, toElt, fromElt, (:.)(..) )--import Data.Array.Accelerate.Pretty.Print+import Data.Array.Accelerate.Type+import Data.Array.Accelerate.Array.Sugar                ( Elt, Shape, Slice, toElt, fromElt, (:.)(..)+                                                        , Tuple(..), IsTuple, fromTuple, TupleRepr, shapeToList ) import qualified Data.Array.Accelerate.Debug            as Stats  @@ -52,7 +56,7 @@ instance Kit acc => Simplify (PreFun acc aenv f) where   simplify = simplifyFun -instance Kit acc => Simplify (PreExp acc aenv e) where+instance (Kit acc, Elt e) => Simplify (PreExp acc aenv e) where   simplify = simplifyExp  @@ -80,7 +84,7 @@ -- memory because there are insufficient registers available. We sidestep this -- tricky and target-dependent issue by, for now, simply ignoring it. ---localCSE :: (Kit acc, Elt a, Elt b)+localCSE :: (Kit acc, Elt a)          => Gamma      acc env env aenv          -> PreOpenExp acc env     aenv a          -> PreOpenExp acc (env,a) aenv b@@ -89,7 +93,22 @@   | Just ix <- lookupExp env bnd = Stats.ruleFired "CSE" . Just $ inline body (Var ix)   | otherwise                    = Nothing +-- Common subexpression elimination, which attempts to match the given+-- expression against something already bound in the environment. This can occur+-- due to simplification, in which case we replace the entire subterm with x.+--+-- > let x = e in .. e ..+--+globalCSE :: (Kit acc, Elt t)+          => Gamma      acc env env aenv+          -> PreOpenExp acc env     aenv t+          -> Maybe (PreOpenExp acc env aenv t)+globalCSE env exp+  | Just ix <- lookupExp env exp = Stats.ruleFired "CSE" . Just $ Var ix+  | otherwise                    = Nothing ++{-- -- Compared to regular Haskell, the scalar expression language of Accelerate is -- rather limited in order to meet the restrictions of what can be efficiently -- implemented on specialised hardware, such as GPUs. For example, to avoid@@ -123,9 +142,6 @@     -> PreOpenExp acc env     aenv a     -> PreOpenExp acc (env,a) aenv b     -> Maybe (PreOpenExp acc env aenv b)-recoverLoops _ _ _-  = Nothing-{-- recoverLoops _ bnd e3   -- To introduce scaler loops, we look for expressions of the form:   --@@ -138,8 +154,8 @@   --   iterate[2] (\y -> e2) e1   --   | Let e1 e2           <- bnd-  , Just REFL           <- matchEnvTop e2 e3-  , Just REFL           <- match e2 e3+  , Just Refl           <- matchEnvTop e2 e3+  , Just Refl           <- match e2 e3   = Stats.ruleFired "loop recovery/intro" . Just   $ Iterate (constant 2) e2 e1 @@ -152,7 +168,7 @@   -- iteration with the trip count increased by one.   --   | Iterate n f e1      <- bnd-  , Just REFL           <- match f e3+  , Just Refl           <- match f e3   = Stats.ruleFired "loop recovery/merge" . Just   $ Iterate (constant 1 `plus` n) f e1 @@ -170,7 +186,7 @@                 => PreOpenExp acc (env,s) aenv f                 -> PreOpenExp acc (env,t) aenv g                 -> Maybe (s :=: t)-    matchEnvTop _ _ = gcast REFL+    matchEnvTop _ _ = gcast Refl --}  @@ -182,18 +198,19 @@ --       rewrite rule schema. -- simplifyOpenExp-    :: forall acc env aenv e. Kit acc+    :: forall acc env aenv e. (Kit acc, Elt e)     => Gamma acc env env aenv     -> PreOpenExp acc env aenv e     -> (Bool, PreOpenExp acc env aenv e) simplifyOpenExp env = first getAny . cvtE   where-    cvtE :: PreOpenExp acc env aenv t -> (Any, PreOpenExp acc env aenv t)+    cvtE :: Elt t => PreOpenExp acc env aenv t -> (Any, PreOpenExp acc env aenv t)+    cvtE exp | Just e <- globalCSE env exp = yes e     cvtE exp = case exp of       Let bnd body-        | Just reduct <- localCSE env (snd bnd') (snd body')     -> yes . snd $ cvtE reduct-        | Just reduct <- recoverLoops env (snd bnd') (snd body') -> yes . snd $ cvtE reduct-        | otherwise                                              -> Let <$> bnd' <*> body'+        -- Just reduct <- recoverLoops env (snd bnd') (snd body') -> yes . snd $ cvtE reduct+        | Just reduct <- localCSE env (snd bnd') (snd body') -> yes . snd $ cvtE reduct+        | otherwise                                          -> Let <$> bnd' <*> body'         where           bnd'  = cvtE bnd           env'  = PushExp env (snd bnd')@@ -202,7 +219,7 @@       Var ix                    -> pure $ Var ix       Const c                   -> pure $ Const c       Tuple tup                 -> Tuple <$> cvtT tup-      Prj ix t                  -> prj ix (cvtE t)+      Prj ix t                  -> prj env ix (cvtE t)       IndexNil                  -> pure IndexNil       IndexAny                  -> pure IndexAny       IndexCons sh sz           -> indexCons (cvtE sh) (cvtE sz)@@ -210,16 +227,20 @@       IndexTail sh              -> indexTail (cvtE sh)       IndexSlice x ix sh        -> IndexSlice x <$> cvtE ix <*> cvtE sh       IndexFull x ix sl         -> IndexFull x <$> cvtE ix <*> cvtE sl-      ToIndex sh ix             -> ToIndex <$> cvtE sh <*> cvtE ix-      FromIndex sh ix           -> FromIndex <$> cvtE sh <*> cvtE ix+      ToIndex sh ix             -> toIndex (cvtE sh) (cvtE ix)+      FromIndex sh ix           -> fromIndex (cvtE sh) (cvtE ix)       Cond p t e                -> cond (cvtE p) (cvtE t) (cvtE e)       PrimConst c               -> pure $ PrimConst c-      PrimApp f x               -> evalPrimApp env f <$> cvtE x+      PrimApp f x               -> (u<>v, fx)+        where+          (u, x') = cvtE x+          (v, fx) = evalPrimApp env f x'       Index a sh                -> Index a <$> cvtE sh       LinearIndex a i           -> LinearIndex a <$> cvtE i       Shape a                   -> pure $ Shape a-      ShapeSize sh              -> ShapeSize <$> cvtE sh+      ShapeSize sh              -> shapeSize (cvtE sh)       Intersect s t             -> cvtE s `intersect` cvtE t+      Union s t                 -> cvtE s `union` cvtE t       Foreign ff f e            -> Foreign ff <$> first Any (simplifyOpenFun EmptyExp f) <*> cvtE e       While p f x               -> While <$> cvtF env p <*> cvtF env f <*> cvtE x @@ -227,7 +248,7 @@     cvtT NilTup        = pure NilTup     cvtT (SnocTup t e) = SnocTup <$> cvtT t <*> cvtE e -    cvtE' :: Gamma acc env' env' aenv -> PreOpenExp acc env' aenv e' -> (Any, PreOpenExp acc env' aenv e')+    cvtE' :: Elt e' => Gamma acc env' env' aenv -> PreOpenExp acc env' aenv e' -> (Any, PreOpenExp acc env' aenv e')     cvtE' env' = first Any . simplifyOpenExp env'      cvtF :: Gamma acc env' env' aenv -> PreOpenFun acc env' aenv f -> (Any, PreOpenFun acc env' aenv f)@@ -254,7 +275,28 @@         leaves (Intersect x y)  = leaves x ++ leaves y         leaves rest             = [rest] +    -- Return the minimal set of unique shapes to take the union of. This is a bit+    -- inefficient, but the number of shapes is expected to be small so should+    -- be fine in practice.+    --+    union :: Shape t+          => (Any, PreOpenExp acc env aenv t)+          -> (Any, PreOpenExp acc env aenv t)+          -> (Any, PreOpenExp acc env aenv t)+    union (c1, sh1) (c2, sh2)+      | Nothing <- match sh sh' = Stats.ruleFired "union" (yes sh')+      | otherwise               = (c1 <> c2, sh')+      where+        sh      = Union sh1 sh2+        sh'     = foldl1 Union+                $ nubBy (\x y -> isJust (match x y))+                $ leaves sh1 ++ leaves sh2 +        leaves :: Shape t => PreOpenExp acc env aenv t -> [PreOpenExp acc env aenv t]+        leaves (Union x y)  = leaves x ++ leaves y+        leaves rest         = [rest]++     -- Simplify conditional expressions, in particular by eliminating branches     -- when the predicate is a known constant.     --@@ -264,59 +306,105 @@          -> (Any, PreOpenExp acc env aenv t)          -> (Any, PreOpenExp acc env aenv t)     cond p@(_,p') t@(_,t') e@(_,e')-      | Const ((),True)  <- p'   = Stats.knownBranch "True"      (yes t')-      | Const ((),False) <- p'   = Stats.knownBranch "False"     (yes e')-      | Just REFL <- match t' e' = Stats.knownBranch "redundant" (yes e')+      | Const True  <- p'        = Stats.knownBranch "True"      (yes t')+      | Const False <- p'        = Stats.knownBranch "False"     (yes e')+      | Just Refl <- match t' e' = Stats.knownBranch "redundant" (yes e')       | otherwise                = Cond <$> p <*> t <*> e      -- If we are projecting elements from a tuple structure or tuple of constant     -- valued tuple, pick out the appropriate component directly.     ---    prj :: forall s t. (Elt s, Elt t, IsTuple t)-        => TupleIdx (TupleRepr t) s-        -> (Any, PreOpenExp acc env aenv t)-        -> (Any, PreOpenExp acc env aenv s)-    prj ix exp@(_,exp')-      | Tuple t <- exp' = Stats.inline "prj/Tuple" . yes $ prjT ix t-      | Const c <- exp' = Stats.inline "prj/Const" . yes $ prjC ix (fromTuple (toElt c :: t))-      | Let a b <- exp' = Stats.ruleFired "prj/Let"      $ cvtE (Let a (Prj ix b))-      | otherwise       = Prj ix <$> exp+    -- Follow variable bindings, but only if they result in a simplification.+    --+    prj :: forall env' s t. (Elt s, Elt t, IsTuple t)+        => Gamma acc env' env' aenv+        -> TupleIdx (TupleRepr t) s+        -> (Any, PreOpenExp acc env' aenv t)+        -> (Any, PreOpenExp acc env' aenv s)+    prj env' ix top@(_,e) = case e of+      Tuple t                      -> Stats.inline "prj/Tuple" . yes $ prjT ix t+      Const c                      -> Stats.inline "prj/Const" . yes $ prjC ix (fromTuple (toElt c :: t))+      Var v   | Just x <- prjV v   -> Stats.inline "prj/Var"   . yes $ x+      Let a b | Just x <- prjL a b -> Stats.inline "prj/Let"   . yes $ x+      _                            -> Prj ix <$> top       where-        prjT :: TupleIdx tup s -> Tuple (PreOpenExp acc env aenv) tup -> PreOpenExp acc env aenv s-        prjT ZeroTupIdx       (SnocTup _ e) = e+        prjT :: TupleIdx tup s -> Tuple (PreOpenExp acc env' aenv) tup -> PreOpenExp acc env' aenv s+        prjT ZeroTupIdx       (SnocTup _ v) = v         prjT (SuccTupIdx idx) (SnocTup t _) = prjT idx t+#if __GLASGOW_HASKELL__ < 800         prjT _                _             = error "DO MORE OF WHAT MAKES YOU HAPPY"+#endif -        prjC :: TupleIdx tup s -> tup -> PreOpenExp acc env aenv s+        prjC :: TupleIdx tup s -> tup -> PreOpenExp acc env' aenv s         prjC ZeroTupIdx       (_,   v) = Const (fromElt v)         prjC (SuccTupIdx idx) (tup, _) = prjC idx tup +        prjV :: Idx env' t -> Maybe (PreOpenExp acc env' aenv s)+        prjV var+          | e'      <- prjExp var env'+          , Nothing <- match e e'+          = case e' of+              -- Don't push through nested let-bindings; this leads to code explosion+              Let _ _                                    -> Nothing+              _ | (Any True, x) <- prj env' ix (pure e') -> Just x+              _                                          -> Nothing+          | otherwise+          = Nothing++        prjL :: Elt a+             => PreOpenExp acc env'     aenv a+             -> PreOpenExp acc (env',a) aenv t+             -> Maybe (PreOpenExp acc env' aenv s)+        prjL a b+          | (Any True, c) <- prj (incExp $ PushExp env' a) ix (pure b) = Just (Let a c)+        prjL _ _                                                       = Nothing++     -- Shape manipulations     --     indexCons :: (Slice sl, Elt sz)               => (Any, PreOpenExp acc env aenv sl)               -> (Any, PreOpenExp acc env aenv sz)               -> (Any, PreOpenExp acc env aenv (sl :. sz))-    indexCons (_,sl') (_,sz')-      | Just REFL       <- match sl' IndexNil-      , IndexHead sh    <- sz'-      , expDim sz' == 1  -- no type information that this is a 1D shape, hence gcast next-      , Just sh'        <- gcast sh-      = yes sh'-+    indexCons (_,IndexNil) (_,Const c)+      | Just c'         <- cast c       -- EltRepr Z ~ EltRepr ()+      = Stats.ruleFired "Z:.const" $ yes (Const c')+    indexCons (_,IndexNil) (_,IndexHead sz')+      | 1               <- expDim sz'   -- no type information that this is a 1D shape, hence gcast next+      , Just sh'        <- gcast sz'+      = Stats.ruleFired "Z:.indexHead" $ yes sh'+    indexCons (_,IndexTail sl') (_,IndexHead sz')+      | Just Refl       <- match sl' sz'+      = Stats.ruleFired "indexTail:.indexHead" $ yes sl'     indexCons sl sz       = IndexCons <$> sl <*> sz      indexHead :: forall sl sz. (Slice sl, Elt sz) => (Any, PreOpenExp acc env aenv (sl :. sz)) -> (Any, PreOpenExp acc env aenv sz)-    indexHead (_, Const c)        = let _ :. sz = toElt c :: (sl :. sz) in yes (Const (fromElt sz))-    indexHead (_, IndexCons _ sz) = yes sz-    indexHead sh                  = IndexHead <$> sh+    indexHead (_, Const c)+      | _ :. sz <- toElt c :: sl :. sz  = Stats.ruleFired "indexHead/const"     $ yes (Const (fromElt sz))+    indexHead (_, IndexCons _ sz)       = Stats.ruleFired "indexHead/indexCons" $ yes sz+    indexHead sh                        = IndexHead <$> sh      indexTail :: forall sl sz. (Slice sl, Elt sz) => (Any, PreOpenExp acc env aenv (sl :. sz)) -> (Any, PreOpenExp acc env aenv sl)-    indexTail (_, Const c)        = let sl :. _ = toElt c :: (sl :. sz) in yes (Const (fromElt sl))-    indexTail (_, IndexCons sl _) = yes sl-    indexTail sh                  = IndexTail <$> sh+    indexTail (_, Const c)+      | sl :. _ <- toElt c :: sl :. sz  = Stats.ruleFired "indexTail/const"     $ yes (Const (fromElt sl))+    indexTail (_, IndexCons sl _)       = Stats.ruleFired "indexTail/indexCons" $ yes sl+    indexTail sh                        = IndexTail <$> sh +    shapeSize :: forall sh. Shape sh => (Any, PreOpenExp acc env aenv sh) -> (Any, PreOpenExp acc env aenv Int)+    shapeSize (_, Const c) = Stats.ruleFired "shapeSize/const" $ yes (Const (product (shapeToList (toElt c :: sh))))+    shapeSize sh           = ShapeSize <$> sh++    toIndex :: forall sh. Shape sh => (Any, PreOpenExp acc env aenv sh) -> (Any, PreOpenExp acc env aenv sh) -> (Any, PreOpenExp acc env aenv Int)+    toIndex  (_,sh) (_,FromIndex sh' ix)+      | Just Refl <- match sh sh' = Stats.ruleFired "toIndex/fromIndex" $ yes ix+    toIndex sh ix                 = ToIndex <$> sh <*> ix++    fromIndex :: forall sh. Shape sh => (Any, PreOpenExp acc env aenv sh) -> (Any, PreOpenExp acc env aenv Int) -> (Any, PreOpenExp acc env aenv sh)+    fromIndex  (_,sh) (_,ToIndex sh' ix)+      | Just Refl <- match sh sh' = Stats.ruleFired "fromIndex/toIndex" $ yes ix+    fromIndex sh ix               = FromIndex <$> sh <*> ix+     first :: (a -> a') -> (a,b) -> (a',b)     first f (x,y) = (f x, y) @@ -337,14 +425,14 @@     env' = incExp env `PushExp` Var ZeroIdx  --- Simplify closed expressions and functions. The process is applied repeatedly--- until no more changes are made.+-- Simplify closed expressions and functions. The process is applied+-- repeatedly until no more changes are made. ---simplifyExp :: Kit acc => PreExp acc aenv t -> PreExp acc aenv t-simplifyExp = iterate (show . prettyPreExp prettyAcc 0 0 noParens) (simplifyOpenExp EmptyExp)+simplifyExp :: (Elt t, Kit acc) => PreExp acc aenv t -> PreExp acc aenv t+simplifyExp = iterate summariseOpenExp (simplifyOpenExp EmptyExp)  simplifyFun :: Kit acc => PreFun acc aenv f -> PreFun acc aenv f-simplifyFun = iterate (show . prettyPreFun prettyAcc 0) (simplifyOpenFun EmptyExp)+simplifyFun = iterate summariseOpenFun (simplifyOpenFun EmptyExp)   -- NOTE: [Simplifier iterations]@@ -364,43 +452,241 @@ -- With internal checks on, we also issue a warning if the iteration limit is -- reached, but it was still possible to make changes to the expression. ---{-# SPECIALISE iterate :: (Exp aenv t -> String) -> (Exp aenv t -> (Bool, Exp aenv t)) -> Exp aenv t -> Exp aenv t #-}-{-# SPECIALISE iterate :: (Fun aenv t -> String) -> (Fun aenv t -> (Bool, Fun aenv t)) -> Fun aenv t -> Fun aenv t #-}+{-# SPECIALISE iterate :: (Exp aenv t -> Stats) -> (Exp aenv t -> (Bool, Exp aenv t)) -> Exp aenv t -> Exp aenv t #-}+{-# SPECIALISE iterate :: (Fun aenv t -> Stats) -> (Fun aenv t -> (Bool, Fun aenv t)) -> Fun aenv t -> Fun aenv t #-}  iterate     :: forall f a. (Match f, Shrink (f a))-    => (f a -> String)+    => (f a -> Stats)     -> (f a -> (Bool, f a))     -> f a     -> f a-iterate ppr f = fix 0 . setup . simplify'+iterate summarise f = fix 1 . setup   where     -- The maximum number of simplifier iterations. To be conservative and avoid-    -- excessive run times, we set this value very low.+    -- excessive run times, we (should) set this value very low.     ---    lIMIT       = 1+    -- TODO: make this tunable via debug flags.+    --+    lIMIT       = 25      simplify'   = Stats.simplifierDone . f-    setup (_,x) = msg x x+    setup x     = Stats.trace Stats.dump_simpl_iterations (msg 0 "init" x)+                $ snd (trace 1 "simplify" (simplify' x))      fix :: Int -> f a -> f a-    fix !i !x0-      | i >= lIMIT      = $internalWarning "iterate" "iteration limit reached" (x0 ==^ f x0) x0+    fix i x0+      | i > lIMIT       = $internalWarning "simplify" "iteration limit reached" (not (x0 ==^ f x0)) x0       | not shrunk      = x1       | not simplified  = x2       | otherwise       = fix (i+1) x2       where-        (shrunk,     x1) = trace $ shrink' x0-        (simplified, x2) = trace $ simplify' x1+        (shrunk,     x1) = trace i "shrink"   $ shrink' x0+        (simplified, x2) = trace i "simplify" $ simplify' x1      -- debugging support     --     u ==^ (_,v)         = isJust (match u v) -    trace v@(changed,x)-      | changed         = msg x v+    trace i s v@(changed,x)+      | changed         = Stats.trace Stats.dump_simpl_iterations (msg i s x) v       | otherwise       = v -    msg :: f a -> x -> x-    msg x next          = Stats.tracePure Stats.dump_simpl_iterations (unlines [ "simplifier done", ppr x ]) next+    msg :: Int -> String -> f a -> String+    msg i s x = printf "simpl-iters/%-8s [%d]: %s" s i (ppr x)++    ppr :: f a -> String+    ppr = show . summarise+++-- Debugging support+-- -----------------++data Stats = Stats+  { _terms    :: {-# UNPACK #-} !Int+  , _types    :: {-# UNPACK #-} !Int+  , _binders  :: {-# UNPACK #-} !Int+  , _vars     :: {-# UNPACK #-} !Int+  , _ops      :: {-# UNPACK #-} !Int+  }++instance Show Stats where+  show (Stats a b c d e) =+    printf "terms = %d, types = %d, lets = %d, vars = %d, primops = %d" a b c d e++-- Rather than using the TH deriving mechanism, otherwise the summarise*+-- functions will not be in scope for the above.+--+terms, types, binders, vars, ops :: Stats :-> Int+terms   = lens _terms   (\f Stats{..} -> Stats { _terms   = f _terms, ..})+types   = lens _types   (\f Stats{..} -> Stats { _types   = f _types, ..})+binders = lens _binders (\f Stats{..} -> Stats { _binders = f _binders, ..})+vars    = lens _vars    (\f Stats{..} -> Stats { _vars    = f _vars, ..})+ops     = lens _ops     (\f Stats{..} -> Stats { _ops     = f _ops, ..})++infixl 1 &+(&) :: a -> (a -> b) -> b+(&) x f = f x++infixr 4 +~+(+~) :: Num a => f :-> a -> a -> f -> f+(+~) l c s = modify l (+c) s++infixl 6 ++++(+++) :: Stats -> Stats -> Stats+Stats a1 b1 c1 d1 e1 +++ Stats a2 b2 c2 d2 e2 = Stats (a1+a2) (b1+b2) (c1+c2) (d1+d2) (e1+e2)++summariseOpenFun :: PreOpenFun acc env aenv f -> Stats+summariseOpenFun (Body e) = summariseOpenExp e & terms +~ 1+summariseOpenFun (Lam f)  = summariseOpenFun f & terms +~ 1 & binders +~ 1++summariseOpenExp :: PreOpenExp acc env aenv t -> Stats+summariseOpenExp = modify terms (+1) . goE+  where+    zero = Stats 0 0 0 0 0++    travE :: PreOpenExp acc env aenv t -> Stats+    travE = summariseOpenExp++    travF :: PreOpenFun acc env aenv t -> Stats+    travF = summariseOpenFun++    travA :: acc aenv a -> Stats+    travA _ = zero & vars +~ 1  -- assume an array index, else we should have failed elsewhere++    travT :: Tuple (PreOpenExp acc env aenv) t -> Stats+    travT NilTup        = zero & terms +~ 1+    travT (SnocTup t e) = travT t +++ travE e & terms +~ 1++    travTix :: TupleIdx t e -> Stats+    travTix ZeroTupIdx     = zero & terms +~ 1+    travTix (SuccTupIdx t) = travTix t & terms +~ 1++    travC :: PrimConst c -> Stats+    travC (PrimMinBound t) = travBoundedType t & terms +~ 1+    travC (PrimMaxBound t) = travBoundedType t & terms +~ 1+    travC (PrimPi t)       = travFloatingType t & terms +~ 1++    travNonNumType :: NonNumType t -> Stats+    travNonNumType _ = zero & types +~ 1++    travIntegralType :: IntegralType t -> Stats+    travIntegralType _ = zero & types +~ 1++    travFloatingType :: FloatingType t -> Stats+    travFloatingType _ = zero & types +~ 1++    travNumType :: NumType t -> Stats+    travNumType (IntegralNumType t) = travIntegralType t & types +~ 1+    travNumType (FloatingNumType t) = travFloatingType t & types +~ 1++    travBoundedType :: BoundedType t -> Stats+    travBoundedType (IntegralBoundedType t) = travIntegralType t & types +~ 1+    travBoundedType (NonNumBoundedType t)   = travNonNumType t & types +~ 1++    travScalarType :: ScalarType t -> Stats+    travScalarType (NumScalarType t)    = travNumType t & types +~ 1+    travScalarType (NonNumScalarType t) = travNonNumType t & types +~ 1++    -- The scrutinee has already been counted+    goE :: PreOpenExp acc env aenv t -> Stats+    goE exp =+      case exp of+        Let bnd body          -> travE bnd +++ travE body & binders +~ 1+        Var{}                 -> zero & vars +~ 1+        Foreign _ _ x         -> travE x & terms +~ 1   -- +1 for asm, ignore fallback impls.+        Const{}               -> zero+        Tuple tup             -> travT tup & terms +~ 1+        Prj ix e              -> travTix ix +++ travE e+        IndexNil              -> zero+        IndexCons sh sz       -> travE sh +++ travE sz+        IndexHead sh          -> travE sh+        IndexTail sh          -> travE sh+        IndexAny              -> zero+        IndexSlice _ slix sh  -> travE slix +++ travE sh & terms +~ 1 -- +1 for sliceIndex+        IndexFull _ slix sl   -> travE slix +++ travE sl & terms +~ 1 -- +1 for sliceIndex+        ToIndex sh ix         -> travE sh +++ travE ix+        FromIndex sh ix       -> travE sh +++ travE ix+        Cond p t e            -> travE p +++ travE t +++ travE e+        While p f x           -> travF p +++ travF f +++ travE x+        PrimConst c           -> travC c+        Index a ix            -> travA a +++ travE ix+        LinearIndex a ix      -> travA a +++ travE ix+        Shape a               -> travA a+        ShapeSize sh          -> travE sh+        Intersect sh1 sh2     -> travE sh1 +++ travE sh2+        Union sh1 sh2         -> travE sh1 +++ travE sh2+        PrimApp f x           -> travPrimFun f +++ travE x++    travPrimFun :: PrimFun f -> Stats+    travPrimFun = modify ops (+1) . goF+      where+        goF :: PrimFun f -> Stats+        goF fun =+          case fun of+            PrimAdd                t -> travNumType t+            PrimSub                t -> travNumType t+            PrimMul                t -> travNumType t+            PrimNeg                t -> travNumType t+            PrimAbs                t -> travNumType t+            PrimSig                t -> travNumType t+            PrimQuot               t -> travIntegralType t+            PrimRem                t -> travIntegralType t+            PrimQuotRem            t -> travIntegralType t+            PrimIDiv               t -> travIntegralType t+            PrimMod                t -> travIntegralType t+            PrimDivMod             t -> travIntegralType t+            PrimBAnd               t -> travIntegralType t+            PrimBOr                t -> travIntegralType t+            PrimBXor               t -> travIntegralType t+            PrimBNot               t -> travIntegralType t+            PrimBShiftL            t -> travIntegralType t+            PrimBShiftR            t -> travIntegralType t+            PrimBRotateL           t -> travIntegralType t+            PrimBRotateR           t -> travIntegralType t+            PrimPopCount           t -> travIntegralType t+            PrimCountLeadingZeros  t -> travIntegralType t+            PrimCountTrailingZeros t -> travIntegralType t+            PrimFDiv               t -> travFloatingType t+            PrimRecip              t -> travFloatingType t+            PrimSin                t -> travFloatingType t+            PrimCos                t -> travFloatingType t+            PrimTan                t -> travFloatingType t+            PrimAsin               t -> travFloatingType t+            PrimAcos               t -> travFloatingType t+            PrimAtan               t -> travFloatingType t+            PrimSinh               t -> travFloatingType t+            PrimCosh               t -> travFloatingType t+            PrimTanh               t -> travFloatingType t+            PrimAsinh              t -> travFloatingType t+            PrimAcosh              t -> travFloatingType t+            PrimAtanh              t -> travFloatingType t+            PrimExpFloating        t -> travFloatingType t+            PrimSqrt               t -> travFloatingType t+            PrimLog                t -> travFloatingType t+            PrimFPow               t -> travFloatingType t+            PrimLogBase            t -> travFloatingType t+            PrimTruncate         f i -> travFloatingType f +++ travIntegralType i+            PrimRound            f i -> travFloatingType f +++ travIntegralType i+            PrimFloor            f i -> travFloatingType f +++ travIntegralType i+            PrimCeiling          f i -> travFloatingType f +++ travIntegralType i+            PrimIsNaN              t -> travFloatingType t+            PrimAtan2              t -> travFloatingType t+            PrimLt                 t -> travScalarType t+            PrimGt                 t -> travScalarType t+            PrimLtEq               t -> travScalarType t+            PrimGtEq               t -> travScalarType t+            PrimEq                 t -> travScalarType t+            PrimNEq                t -> travScalarType t+            PrimMax                t -> travScalarType t+            PrimMin                t -> travScalarType t+            PrimLAnd                 -> zero+            PrimLOr                  -> zero+            PrimLNot                 -> zero+            PrimOrd                  -> zero+            PrimChr                  -> zero+            PrimBoolToInt            -> zero+            PrimFromIntegral     i n -> travIntegralType i +++ travNumType n+            PrimToFloating       n f -> travNumType n +++ travFloatingType f+            PrimCoerce           a b -> travScalarType a +++ travScalarType b 
Data/Array/Accelerate/Trafo/Substitution.hs view
@@ -1,15 +1,19 @@-{-# LANGUAGE GADTs          #-}-{-# LANGUAGE KindSignatures #-}-{-# LANGUAGE PatternGuards  #-}-{-# LANGUAGE RankNTypes     #-}-{-# LANGUAGE TypeOperators  #-}+{-# LANGUAGE ConstraintKinds     #-}+{-# LANGUAGE FlexibleInstances   #-}+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE KindSignatures      #-}+{-# LANGUAGE PatternGuards       #-}+{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies        #-}+{-# LANGUAGE TypeOperators       #-} {-# OPTIONS_HADDOCK hide #-} -- | -- Module      : Data.Array.Accelerate.Trafo.Substitution--- Copyright   : [2012..2014] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- Copyright   : [2012..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell -- License     : BSD3 ----- Maintainer  : Manuel M T Chakravarty <chak@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au> -- Stability   : experimental -- Portability : non-portable (GHC extensions) --@@ -21,25 +25,23 @@   subTop, subAtop,    -- ** Weakening-  (:>),-  weakenA, weakenEA, weakenFA,-  weakenE, weakenFE,+  (:>), Sink(..), SinkExp(..), +  -- ** Strengthening+  (:?>), strengthen, strengthenE,+   -- ** Rebuilding terms-  RebuildAcc,-  rebuildA, rebuildAfun, rebuildOpenAcc,-  rebuildE, rebuildEA,-  rebuildFA, rebuildFE,+  RebuildAcc, Rebuildable(..), RebuildableAcc,+  RebuildableExp(..), RebuildTup(..)  ) where -import Prelude                                  hiding ( exp )+import Control.Applicative                              hiding ( Const )+import Prelude                                          hiding ( exp, seq )  import Data.Array.Accelerate.AST-import Data.Array.Accelerate.Tuple-import Data.Array.Accelerate.Array.Sugar        ( Elt, Arrays )--import qualified Data.Array.Accelerate.Debug    as Stats+import Data.Array.Accelerate.Array.Sugar                ( Elt, Arrays, Tuple(..), Atuple(..) )+import qualified Data.Array.Accelerate.Debug.Stats      as Stats   -- NOTE: [Renaming and Substitution]@@ -60,10 +62,10 @@ -- We then lift this to an operation which traverses terms and rebuild them -- after applying 'v' to the variables: -----   rebuild v :: OpenExp env aenv t -> OpenExp env' aenv t+--   rebuildPartial v :: OpenExp env aenv t -> OpenExp env' aenv t -- -- The Syntactic class tells us what we need to know about 'f' if we want to be--- able to rebuild terms. In essence, the crucial functionality is to propagate+-- able to rebuildPartial terms. In essence, the crucial functionality is to propagate -- a class of operations on variables that is closed under shifting. -- infixr `compose`@@ -72,7 +74,7 @@ -- | Replace the first variable with the given expression. The environment -- shrinks. ---inline :: Elt t+inline :: RebuildableAcc acc        => PreOpenExp acc (env, s) aenv t        -> PreOpenExp acc env      aenv s        -> PreOpenExp acc env      aenv t@@ -81,7 +83,7 @@ -- | Replace an expression that uses the top environment variable with another. -- The result of the first is let bound into the second. ---substitute :: (Elt b, Elt c)+substitute :: (RebuildableAcc acc, Elt b, Elt c)            => PreOpenExp acc (env, b) aenv c            -> PreOpenExp acc (env, a) aenv b            -> PreOpenExp acc (env, a) aenv c@@ -98,14 +100,13 @@  -- | Composition of unary functions. ---compose :: Elt c+compose :: (RebuildableAcc acc, Elt c)         => PreOpenFun acc env aenv (b -> c)         -> PreOpenFun acc env aenv (a -> b)         -> PreOpenFun acc env aenv (a -> c) compose (Lam (Body f)) (Lam (Body g)) = Stats.substitution "compose" . Lam . Body $ substitute f g compose _              _              = error "compose: impossible evaluation" - subTop :: Elt t => PreOpenExp acc env aenv s -> Idx (env, s) t -> PreOpenExp acc env aenv t subTop s ZeroIdx      = s subTop _ (SuccIdx ix) = Var ix@@ -114,7 +115,96 @@ subAtop t ZeroIdx       = t subAtop _ (SuccIdx idx) = Avar idx +data Identity a = Identity { runIdentity :: a } +instance Functor Identity where+  fmap f (Identity a) = Identity (f a)++instance Applicative Identity where+  Identity f <*> Identity a = Identity (f a)+  pure a                    = Identity a++-- A class for rebuilding terms.+--+class Rebuildable f where+  {-# MINIMAL rebuildPartial #-}+  type AccClo f :: (* -> * -> *)++  rebuildPartial :: (Applicative f', SyntacticAcc fa)+                 => (forall a'. Arrays a' => Idx aenv a' -> f' (fa (AccClo f) aenv' a'))+                 -> f aenv  a+                 -> f' (f aenv' a)++  {-# INLINEABLE rebuildA #-}+  rebuildA :: (SyntacticAcc fa)+              => (forall a'. Arrays a' => Idx aenv a' -> fa (AccClo f) aenv' a')+              -> f aenv  a+              -> f aenv' a+  rebuildA av = runIdentity . rebuildPartial (Identity . av)++-- A class for rebuilding scalar terms.+--+class RebuildableExp f where+  {-# MINIMAL rebuildPartialE #-}+  rebuildPartialE :: (Applicative f', SyntacticExp fe)+                  => (forall e'. Elt e' => Idx env e' -> f' (fe (AccClo (f env)) env' aenv e'))+                  -> f env aenv  e+                  -> f' (f env' aenv e)++  {-# INLINABLE rebuildE #-}+  rebuildE :: SyntacticExp fe+           => (forall e'. Elt e' => Idx env e' -> fe (AccClo (f env)) env' aenv e')+           -> f env aenv  e+           -> f env' aenv e+  rebuildE v = runIdentity . rebuildPartialE (Identity . v)++-- Terms that are rebuildable and also recursive closures+--+type RebuildableAcc acc = (Rebuildable acc, AccClo acc ~ acc)++-- We can use the same plumbing to rebuildPartial all the things we want to rebuild.+--+instance RebuildableAcc acc => Rebuildable (PreOpenExp acc env) where+  type AccClo (PreOpenExp acc env) = acc+  {-# INLINEABLE rebuildPartial #-}+  rebuildPartial = rebuildPreOpenExp rebuildPartial (pure . IE)++instance RebuildableAcc acc => Rebuildable (PreOpenFun acc env) where+  type AccClo (PreOpenFun acc env) = acc+  {-# INLINEABLE rebuildPartial #-}+  rebuildPartial = rebuildFun rebuildPartial (pure . IE)++instance RebuildableAcc acc => Rebuildable (PreOpenAcc acc) where+  type AccClo (PreOpenAcc acc) = acc+  {-# INLINEABLE rebuildPartial #-}+  rebuildPartial = rebuildPreOpenAcc rebuildPartial++instance RebuildableAcc acc => Rebuildable (PreOpenAfun acc) where+  type AccClo (PreOpenAfun acc) = acc+  {-# INLINEABLE rebuildPartial #-}+  rebuildPartial = rebuildAfun rebuildPartial++-- Tuples have to be handled specially.+newtype RebuildTup acc env aenv t = RebuildTup { unRTup :: Tuple (PreOpenExp acc env aenv) t }++instance RebuildableAcc acc => Rebuildable (RebuildTup acc env) where+  type AccClo (RebuildTup acc env) = acc+  {-# INLINEABLE rebuildPartial #-}+  rebuildPartial v t = RebuildTup <$> rebuildTup rebuildPartial (pure . IE) v (unRTup t)++instance Rebuildable OpenAcc where+  type AccClo OpenAcc = OpenAcc+  {-# INLINEABLE rebuildPartial #-}+  rebuildPartial = rebuildOpenAcc++instance RebuildableAcc acc => RebuildableExp (PreOpenExp acc) where+  {-# INLINEABLE rebuildPartialE #-}+  rebuildPartialE v = rebuildPreOpenExp rebuildPartial v (pure . IA)++instance RebuildableAcc acc => RebuildableExp (PreOpenFun acc) where+  {-# INLINEABLE rebuildPartialE #-}+  rebuildPartialE v = rebuildFun rebuildPartial v (pure . IA)+ -- NOTE: [Weakening] -- -- Weakening is something we usually take for granted: every time you learn a@@ -133,47 +223,100 @@ -- type env :> env' = forall t'. Idx env t' -> Idx env' t' -{-# NOINLINE[1] weakenA #-}-weakenA :: RebuildAcc acc -> aenv :> aenv' -> PreOpenAcc acc aenv a -> PreOpenAcc acc aenv' a-weakenA k v = Stats.substitution "weakenA" . rebuildA k (Avar . v)+class Sink f where+  weaken :: env :> env' -> f env t -> f env' t -{-# NOINLINE[1] weakenEA #-}-weakenEA :: RebuildAcc acc -> aenv :> aenv' -> PreOpenExp acc env aenv t -> PreOpenExp acc env aenv' t-weakenEA k v = Stats.substitution "weakenEA" . rebuildEA k (Avar . v)+  -- TLM: We can't use this default instance because it doesn't lead to+  --      specialised code. Perhaps the INLINEABLE pragma is ignored: GHC bug?+  --+  -- {-# INLINEABLE weaken #-}+  -- default weaken :: Rebuildable f => env :> env' -> f env t -> f env' t+  -- weaken k = Stats.substitution "weaken" . rebuildA (Avar . k) -{-# NOINLINE[1] weakenFA #-}-weakenFA :: RebuildAcc acc -> aenv :> aenv' -> PreOpenFun acc env aenv f -> PreOpenFun acc env aenv' f-weakenFA k v = Stats.substitution "weakenFA" . rebuildFA k (Avar . v)+--instance Rebuildable f => Sink f where -- undecidable, incoherent+--  weaken k = Stats.substitution "weaken" . rebuildA (Avar . k) -{-# NOINLINE[1] weakenE #-}-weakenE :: env :> env' -> PreOpenExp acc env aenv t -> PreOpenExp acc env' aenv t-weakenE v = Stats.substitution "weakenE" . rebuildE (Var . v)+instance Sink Idx where+  {-# INLINEABLE weaken #-}+  weaken k = k -{-# NOINLINE[1] weakenFE #-}-weakenFE :: env :> env' -> PreOpenFun acc env aenv f -> PreOpenFun acc env' aenv f-weakenFE v = Stats.substitution "weakenFE" . rebuildFE (Var . v)+instance RebuildableAcc acc => Sink (PreOpenAcc acc) where+  {-# INLINEABLE weaken #-}+  weaken k = Stats.substitution "weaken" . rebuildA (Avar . k) -{-# RULES-"weakenA/weakenA" forall a (k :: RebuildAcc acc) (v1 :: env' :> env'') (v2 :: env :> env').-    weakenA k v1 (weakenA k v2 a) = weakenA k (v1 . v2) a+instance RebuildableAcc acc => Sink (PreOpenAfun acc) where+  {-# INLINEABLE weaken #-}+  weaken k = Stats.substitution "weaken" . rebuildA (Avar . k) -"weakenEA/weakenEA" forall a (k :: RebuildAcc acc) (v1 :: env' :> env'') (v2 :: env :> env').-    weakenEA k v1 (weakenEA k v2 a) = weakenEA k (v1 . v2) a+instance RebuildableAcc acc => Sink (PreOpenExp acc env) where+  {-# INLINEABLE weaken #-}+  weaken k = Stats.substitution "weaken" . rebuildA (Avar . k) -"weakenFA/weakenFA" forall a (k :: RebuildAcc acc) (v1 :: env' :> env'') (v2 :: env :> env').-    weakenFA k v1 (weakenFA k v2 a) = weakenFA k (v1 . v2) a+instance RebuildableAcc acc => Sink (PreOpenFun acc env) where+  {-# INLINEABLE weaken #-}+  weaken k = Stats.substitution "weaken" . rebuildA (Avar . k) -"weakenE/weakenE" forall e (v1 :: env' :> env'') (v2 :: env :> env').-    weakenE v1 (weakenE v2 e) = weakenE (v1 . v2) e+instance RebuildableAcc acc => Sink (RebuildTup acc env) where+  {-# INLINEABLE weaken #-}+  weaken k = Stats.substitution "weaken" . rebuildA (Avar . k) -"weakenFE/weakenFE" forall e (v1 :: env' :> env'') (v2 :: env :> env').-    weakenFE v1 (weakenFE v2 e) = weakenFE (v1 . v2) e- #-}+instance Sink OpenAcc where+  {-# INLINEABLE weaken #-}+  weaken k = Stats.substitution "weaken" . rebuildA (Avar . k) +-- This rewrite rule is disabled because 'weaken' is now part of a type class.+-- As such, we cannot attach a NOINLINE pragma because it has many definitions.+-- {-# RULES+-- "weaken/weaken" forall a (v1 :: env' :> env'') (v2 :: env :> env').+--     weaken v1 (weaken v2 a) = weaken (v1 . v2) a+--  #-}++class SinkExp f where+  weakenE :: env :> env' -> f env aenv t -> f env' aenv t++  -- See comment in 'weaken'+  --+  -- {-# INLINEABLE weakenE #-}+  -- default weakenE :: RebuildableExp f => env :> env' -> f env aenv t -> f env' aenv t+  -- weakenE v = Stats.substitution "weakenE" . rebuildE (IE . v)++instance RebuildableAcc acc => SinkExp (PreOpenExp acc) where+  {-# INLINEABLE weakenE #-}+  weakenE v = Stats.substitution "weakenE" . rebuildE (IE . v)++instance RebuildableAcc acc => SinkExp (PreOpenFun acc) where+  {-# INLINEABLE weakenE #-}+  weakenE v = Stats.substitution "weakenE" . rebuildE (IE . v)++-- See above for why this is disabled.+-- {-# RULES+-- "weakenE/weakenE" forall a (v1 :: env' :> env'') (v2 :: env :> env').+--    weakenE v1 (weakenE v2 a) = weakenE (v1 . v2) a+--  #-}++-- NOTE: [Strengthening]+--+-- Strengthening is the dual of weakening. Shifting terms from one scope to a+-- smaller scope. Of course this is not always possible. If the term contains+-- any variables not in the new environment, then it cannot be strengthened.+-- This partial behaviour is captured with 'Maybe'.+--++-- The type of partially shifting terms from one context into another.+type env :?> env' = forall t'. Idx env t' -> Maybe (Idx env' t')++{-# INLINEABLE strengthen #-}+strengthen :: Rebuildable f => env :?> env' -> f env t -> Maybe (f env' t)+strengthen k = rebuildPartial (fmap IA . k)++{-# INLINEABLE strengthenE #-}+strengthenE :: RebuildableExp f => env :?> env' -> f env aenv t -> Maybe (f env' aenv t)+strengthenE k = rebuildPartialE (fmap IE . k)+ -- Simultaneous Substitution =================================================== -- --- Scalar expressions+-- The scalar environment -- ------------------  -- SEE: [Renaming and Substitution]@@ -182,90 +325,103 @@ class SyntacticExp f where   varIn         :: Elt t => Idx env t        -> f acc env aenv t   expOut        :: Elt t => f acc env aenv t -> PreOpenExp acc env aenv t-  weakenExp     :: Elt t => f acc env aenv t -> f acc (env, s) aenv t+  weakenExp     :: Elt t => RebuildAcc acc -> f acc env aenv t -> f acc (env, s) aenv t+  weakenExpAcc  :: Elt t => RebuildAcc acc -> f acc env aenv t -> f acc env (aenv, s) t  newtype IdxE (acc :: * -> * -> *) env aenv t = IE { unIE :: Idx env t }  instance SyntacticExp IdxE where-  varIn         = IE-  expOut        = Var . unIE-  weakenExp     = IE . SuccIdx . unIE+  varIn          = IE+  expOut         = Var . unIE+  weakenExp _    = IE . SuccIdx . unIE+  weakenExpAcc _ = IE . unIE  instance SyntacticExp PreOpenExp where-  varIn         = Var-  expOut        = id-  weakenExp     = rebuildE (weakenExp . IE)-+  varIn          = Var+  expOut         = id+  weakenExp k    = runIdentity . rebuildPreOpenExp k (Identity . weakenExp k . IE) (Identity . IA)+  weakenExpAcc k = runIdentity . rebuildPreOpenExp k (Identity . IE) (Identity . weakenAcc k . IA) +{-# INLINEABLE shiftE #-} shiftE-    :: (SyntacticExp f, Elt t)-    => (forall t'. Elt t' => Idx env t' -> f acc env' aenv t')-    -> Idx     (env,  s)      t-    -> f   acc (env', s) aenv t-shiftE _ ZeroIdx      = varIn ZeroIdx-shiftE v (SuccIdx ix) = weakenExp (v ix)+    :: (Applicative f, SyntacticExp fe, Elt t)+    => RebuildAcc acc+    -> (forall t'. Elt t' => Idx env t' -> f (fe acc env' aenv t'))+    -> Idx       (env,  s)      t+    -> f (fe acc (env', s) aenv t)+shiftE _ _ ZeroIdx      = pure $ varIn ZeroIdx+shiftE k v (SuccIdx ix) = weakenExp k <$> (v ix) -rebuildE-    :: SyntacticExp f-    => (forall t'. Elt t' => Idx env t' -> f acc env' aenv t')+{-# INLINEABLE rebuildPreOpenExp #-}+rebuildPreOpenExp+    :: (Applicative f, SyntacticExp fe, SyntacticAcc fa)+    => RebuildAcc acc+    -> (forall t'. Elt t'    => Idx env t'  -> f (fe acc env' aenv' t'))+    -> (forall t'. Arrays t' => Idx aenv t' -> f (fa acc aenv' t'))     -> PreOpenExp acc env  aenv t-    -> PreOpenExp acc env' aenv t-rebuildE v exp =+    -> f (PreOpenExp acc env' aenv' t)+rebuildPreOpenExp k v av exp =   case exp of-    Let a b             -> Let (rebuildE v a) (rebuildE (shiftE v) b)-    Var ix              -> expOut (v ix)-    Const c             -> Const c-    Tuple tup           -> Tuple (rebuildTE v tup)-    Prj tup e           -> Prj tup (rebuildE v e)-    IndexNil            -> IndexNil-    IndexCons sh sz     -> IndexCons (rebuildE v sh) (rebuildE v sz)-    IndexHead sh        -> IndexHead (rebuildE v sh)-    IndexTail sh        -> IndexTail (rebuildE v sh)-    IndexAny            -> IndexAny-    IndexSlice x ix sh  -> IndexSlice x (rebuildE v ix) (rebuildE v sh)-    IndexFull x ix sl   -> IndexFull x (rebuildE v ix) (rebuildE v sl)-    ToIndex sh ix       -> ToIndex (rebuildE v sh) (rebuildE v ix)-    FromIndex sh ix     -> FromIndex (rebuildE v sh) (rebuildE v ix)-    Cond p t e          -> Cond (rebuildE v p) (rebuildE v t) (rebuildE v e)-    While p f x         -> While (rebuildFE v p) (rebuildFE v f) (rebuildE v x)-    PrimConst c         -> PrimConst c-    PrimApp f x         -> PrimApp f (rebuildE v x)-    Index a sh          -> Index a (rebuildE v sh)-    LinearIndex a i     -> LinearIndex a (rebuildE v i)-    Shape a             -> Shape a-    ShapeSize sh        -> ShapeSize (rebuildE v sh)-    Intersect s t       -> Intersect (rebuildE v s) (rebuildE v t)-    Foreign ff f e      -> Foreign ff f (rebuildE v e)+    Const c             -> pure (Const c)+    PrimConst c         -> pure (PrimConst c)+    IndexNil            -> pure IndexNil+    IndexAny            -> pure IndexAny+    Var ix              -> expOut       <$> v ix+    Let a b             -> Let          <$> rebuildPreOpenExp k v av a  <*> rebuildPreOpenExp k (shiftE k v) av b+    Tuple tup           -> Tuple        <$> rebuildTup k v av tup+    Prj tup e           -> Prj tup      <$> rebuildPreOpenExp k v av e+    IndexCons sh sz     -> IndexCons    <$> rebuildPreOpenExp k v av sh <*> rebuildPreOpenExp k v av sz+    IndexHead sh        -> IndexHead    <$> rebuildPreOpenExp k v av sh+    IndexTail sh        -> IndexTail    <$> rebuildPreOpenExp k v av sh+    IndexSlice x ix sh  -> IndexSlice x <$> rebuildPreOpenExp k v av ix <*> rebuildPreOpenExp k v av sh+    IndexFull x ix sl   -> IndexFull x  <$> rebuildPreOpenExp k v av ix <*> rebuildPreOpenExp k v av sl+    ToIndex sh ix       -> ToIndex      <$> rebuildPreOpenExp k v av sh <*> rebuildPreOpenExp k v av ix+    FromIndex sh ix     -> FromIndex    <$> rebuildPreOpenExp k v av sh <*> rebuildPreOpenExp k v av ix+    Cond p t e          -> Cond         <$> rebuildPreOpenExp k v av p  <*> rebuildPreOpenExp k v av t  <*> rebuildPreOpenExp k v av e+    While p f x         -> While        <$> rebuildFun k v av p         <*> rebuildFun k v av f         <*> rebuildPreOpenExp k v av x+    PrimApp f x         -> PrimApp f    <$> rebuildPreOpenExp k v av x+    Index a sh          -> Index        <$> k av a                      <*> rebuildPreOpenExp k v av sh+    LinearIndex a i     -> LinearIndex  <$> k av a                      <*> rebuildPreOpenExp k v av i+    Shape a             -> Shape        <$> k av a+    ShapeSize sh        -> ShapeSize    <$> rebuildPreOpenExp k v av sh+    Intersect s t       -> Intersect    <$> rebuildPreOpenExp k v av s  <*> rebuildPreOpenExp k v av t+    Union s t           -> Union        <$> rebuildPreOpenExp k v av s  <*> rebuildPreOpenExp k v av t+    Foreign ff f e      -> Foreign ff f <$> rebuildPreOpenExp k v av e -rebuildTE-    :: SyntacticExp f-    => (forall t'. Elt t' => Idx env t' -> f acc env' aenv t')-    -> Tuple (PreOpenExp acc env  aenv) t-    -> Tuple (PreOpenExp acc env' aenv) t-rebuildTE v tup =+{-# INLINEABLE rebuildTup #-}+rebuildTup+    :: (Applicative f, SyntacticExp fe, SyntacticAcc fa)+    => RebuildAcc acc+    -> (forall t'. Elt t'    => Idx env t'  -> f (fe acc env' aenv' t'))+    -> (forall t'. Arrays t' => Idx aenv t' -> f (fa acc aenv' t'))+    -> Tuple (PreOpenExp acc env  aenv)  t+    -> f (Tuple (PreOpenExp acc env' aenv') t)+rebuildTup k v av tup =   case tup of-    NilTup      -> NilTup-    SnocTup t e -> rebuildTE v t `SnocTup` rebuildE v e+    NilTup      -> pure NilTup+    SnocTup t e -> SnocTup <$> rebuildTup k v av t <*> rebuildPreOpenExp k v av e -rebuildFE-    :: SyntacticExp f-    => (forall t'. Elt t' => Idx env t' -> f acc env' aenv t')-    -> PreOpenFun acc env  aenv t-    -> PreOpenFun acc env' aenv t-rebuildFE v fun =+{-# INLINEABLE rebuildFun #-}+rebuildFun+    :: (Applicative f, SyntacticExp fe, SyntacticAcc fa)+    => RebuildAcc acc+    -> (forall t'. Elt t'    => Idx env t'  -> f (fe acc env' aenv' t'))+    -> (forall t'. Arrays t' => Idx aenv t' -> f (fa acc aenv' t'))+    -> PreOpenFun acc env  aenv  t+    -> f (PreOpenFun acc env' aenv' t)+rebuildFun k v av fun =   case fun of-    Body e      -> Body (rebuildE v e)-    Lam f       -> Lam (rebuildFE (shiftE v) f)-+    Body e      -> Body <$> rebuildPreOpenExp k v av e+    Lam f       -> Lam  <$> rebuildFun k (shiftE k v) av f --- Array expressions+-- The array environment -- -----------------  type RebuildAcc acc =-  forall aenv aenv' f a. SyntacticAcc f-    => (forall a'. Arrays a' => Idx aenv a' -> f acc aenv' a')+  forall aenv aenv' f fa a. (Applicative f, SyntacticAcc fa)+    => (forall a'. Arrays a' => Idx aenv a' -> f (fa acc aenv' a'))     -> acc aenv  a-    -> acc aenv' a+    -> f (acc aenv' a)  class SyntacticAcc f where   avarIn        :: Arrays t => Idx aenv t     -> f acc aenv t@@ -275,156 +431,142 @@ newtype IdxA (acc :: * -> * -> *) aenv t = IA { unIA :: Idx aenv t }  instance SyntacticAcc IdxA where-  avarIn        = IA-  accOut        = Avar . unIA-  weakenAcc _   = IA . SuccIdx . unIA+  avarIn         = IA+  accOut         = Avar . unIA+  weakenAcc _    = IA . SuccIdx . unIA  instance SyntacticAcc PreOpenAcc where   avarIn        = Avar   accOut        = id-  weakenAcc k   = rebuildA k (weakenAcc k . IA)+  weakenAcc k   = runIdentity . rebuildPreOpenAcc k (Identity . weakenAcc k . IA) +{-# INLINEABLE shiftA #-}+shiftA+    :: (Applicative f, SyntacticAcc fa, Arrays t)+    => RebuildAcc acc+    -> (forall t'. Arrays t' => Idx aenv t' -> f (fa acc aenv' t'))+    -> Idx         (aenv,  s) t+    -> f (fa   acc (aenv', s) t)+shiftA _ _ ZeroIdx      = pure $ avarIn ZeroIdx+shiftA k v (SuccIdx ix) = weakenAcc k <$> v ix +{-# INLINEABLE rebuildOpenAcc #-} rebuildOpenAcc-    :: SyntacticAcc f-    => (forall t'. Arrays t' => Idx aenv t' -> f OpenAcc aenv' t')+    :: (Applicative f, SyntacticAcc fa)+    => (forall t'. Arrays t' => Idx aenv t' -> f (fa OpenAcc aenv' t'))     -> OpenAcc aenv  t-    -> OpenAcc aenv' t-rebuildOpenAcc v (OpenAcc acc) = OpenAcc (rebuildA rebuildOpenAcc v acc)---shiftA-    :: (SyntacticAcc f, Arrays t)-    => RebuildAcc acc-    -> (forall t'. Arrays t' => Idx aenv t' -> f acc aenv' t')-    -> Idx     (aenv,  s) t-    -> f   acc (aenv', s) t-shiftA _ _ ZeroIdx      = avarIn ZeroIdx-shiftA k v (SuccIdx ix) = weakenAcc k (v ix)+    -> f (OpenAcc aenv' t)+rebuildOpenAcc av (OpenAcc acc) = OpenAcc <$> rebuildPreOpenAcc rebuildOpenAcc av acc -rebuildA-    :: SyntacticAcc f+{-# INLINEABLE rebuildPreOpenAcc #-}+rebuildPreOpenAcc+    :: (Applicative f, SyntacticAcc fa)     => RebuildAcc acc-    -> (forall t'. Arrays t' => Idx aenv t' -> f acc aenv' t')+    -> (forall t'. Arrays t' => Idx aenv t' -> f (fa acc aenv' t'))     -> PreOpenAcc acc aenv  t-    -> PreOpenAcc acc aenv' t-rebuildA rebuild v acc =+    -> f (PreOpenAcc acc aenv' t)+rebuildPreOpenAcc k av acc =   case acc of-    Alet a b            -> Alet (rebuild v a) (rebuild (shiftA rebuild v) b)-    Avar ix             -> accOut (v ix)-    Atuple tup          -> Atuple (rebuildATA rebuild v tup)-    Aprj tup a          -> Aprj tup (rebuild v a)-    Apply f a           -> Apply (rebuildAfun rebuild v f) (rebuild v a)-    Aforeign ff afun as -> Aforeign ff afun (rebuild v as)-    Acond p t e         -> Acond (rebuildEA rebuild v p) (rebuild v t) (rebuild v e)-    Awhile p f a        -> Awhile (rebuildAfun rebuild v p) (rebuildAfun rebuild v f) (rebuild v a)-    Use a               -> Use a-    Unit e              -> Unit (rebuildEA rebuild v e)-    Reshape e a         -> Reshape (rebuildEA rebuild v e) (rebuild v a)-    Generate e f        -> Generate (rebuildEA rebuild v e) (rebuildFA rebuild v f)-    Transform sh ix f a -> Transform (rebuildEA rebuild v sh) (rebuildFA rebuild v ix) (rebuildFA rebuild v f) (rebuild v a)-    Replicate sl slix a -> Replicate sl (rebuildEA rebuild v slix) (rebuild v a)-    Slice sl a slix     -> Slice sl (rebuild v a) (rebuildEA rebuild v slix)-    Map f a             -> Map (rebuildFA rebuild v f) (rebuild v a)-    ZipWith f a1 a2     -> ZipWith (rebuildFA rebuild v f) (rebuild v a1) (rebuild v a2)-    Fold f z a          -> Fold (rebuildFA rebuild v f) (rebuildEA rebuild v z) (rebuild v a)-    Fold1 f a           -> Fold1 (rebuildFA rebuild v f) (rebuild v a)-    FoldSeg f z a s     -> FoldSeg (rebuildFA rebuild v f) (rebuildEA rebuild v z) (rebuild v a) (rebuild v s)-    Fold1Seg f a s      -> Fold1Seg (rebuildFA rebuild v f) (rebuild v a) (rebuild v s)-    Scanl f z a         -> Scanl (rebuildFA rebuild v f) (rebuildEA rebuild v z) (rebuild v a)-    Scanl' f z a        -> Scanl' (rebuildFA rebuild v f) (rebuildEA rebuild v z) (rebuild v a)-    Scanl1 f a          -> Scanl1 (rebuildFA rebuild v f) (rebuild v a)-    Scanr f z a         -> Scanr (rebuildFA rebuild v f) (rebuildEA rebuild v z) (rebuild v a)-    Scanr' f z a        -> Scanr' (rebuildFA rebuild v f) (rebuildEA rebuild v z) (rebuild v a)-    Scanr1 f a          -> Scanr1 (rebuildFA rebuild v f) (rebuild v a)-    Permute f1 a1 f2 a2 -> Permute (rebuildFA rebuild v f1) (rebuild v a1) (rebuildFA rebuild v f2) (rebuild v a2)-    Backpermute sh f a  -> Backpermute (rebuildEA rebuild v sh) (rebuildFA rebuild v f) (rebuild v a)-    Stencil f b a       -> Stencil (rebuildFA rebuild v f) b (rebuild v a)-    Stencil2 f b1 a1 b2 a2-                        -> Stencil2 (rebuildFA rebuild v f) b1 (rebuild v a1) b2 (rebuild v a2)----- Rebuilding array computations---+    Use a                   -> pure (Use a)+    Alet a b                -> Alet         <$> k av a <*> k (shiftA k av) b+    Avar ix                 -> accOut       <$> av ix+    Atuple tup              -> Atuple       <$> rebuildAtup k av tup+    Aprj tup a              -> Aprj tup     <$> k av a+    Apply f a               -> Apply        <$> rebuildAfun k av f <*> k av a+    Acond p t e             -> Acond        <$> rebuildPreOpenExp k (pure . IE) av p <*> k av t <*> k av e+    Awhile p f a            -> Awhile       <$> rebuildAfun k av p <*> rebuildAfun k av f <*> k av a+    Unit e                  -> Unit         <$> rebuildPreOpenExp k (pure . IE) av e+    Reshape e a             -> Reshape      <$> rebuildPreOpenExp k (pure . IE) av e <*> k av a+    Generate e f            -> Generate     <$> rebuildPreOpenExp k (pure . IE) av e <*> rebuildFun k (pure . IE) av f+    Transform sh ix f a     -> Transform    <$> rebuildPreOpenExp k (pure . IE) av sh <*> rebuildFun k (pure . IE) av ix <*> rebuildFun k (pure . IE) av f <*> k av a+    Replicate sl slix a     -> Replicate sl <$> rebuildPreOpenExp k (pure . IE) av slix <*> k av a+    Slice sl a slix         -> Slice sl     <$> k av a <*> rebuildPreOpenExp k (pure . IE) av slix+    Map f a                 -> Map          <$> rebuildFun k (pure . IE) av f <*> k av a+    ZipWith f a1 a2         -> ZipWith      <$> rebuildFun k (pure . IE) av f <*> k av a1 <*> k av a2+    Fold f z a              -> Fold         <$> rebuildFun k (pure . IE) av f <*> rebuildPreOpenExp k (pure . IE) av z <*> k av a+    Fold1 f a               -> Fold1        <$> rebuildFun k (pure . IE) av f <*> k av a+    FoldSeg f z a s         -> FoldSeg      <$> rebuildFun k (pure . IE) av f <*> rebuildPreOpenExp k (pure . IE) av z <*> k av a <*> k av s+    Fold1Seg f a s          -> Fold1Seg     <$> rebuildFun k (pure . IE) av f <*> k av a <*> k av s+    Scanl f z a             -> Scanl        <$> rebuildFun k (pure . IE) av f <*> rebuildPreOpenExp k (pure . IE) av z <*> k av a+    Scanl' f z a            -> Scanl'       <$> rebuildFun k (pure . IE) av f <*> rebuildPreOpenExp k (pure . IE) av z <*> k av a+    Scanl1 f a              -> Scanl1       <$> rebuildFun k (pure . IE) av f <*> k av a+    Scanr f z a             -> Scanr        <$> rebuildFun k (pure . IE) av f <*> rebuildPreOpenExp k (pure . IE) av z <*> k av a+    Scanr' f z a            -> Scanr'       <$> rebuildFun k (pure . IE) av f <*> rebuildPreOpenExp k (pure . IE) av z <*> k av a+    Scanr1 f a              -> Scanr1       <$> rebuildFun k (pure . IE) av f <*> k av a+    Permute f1 a1 f2 a2     -> Permute      <$> rebuildFun k (pure . IE) av f1 <*> k av a1 <*> rebuildFun k (pure . IE) av f2 <*> k av a2+    Backpermute sh f a      -> Backpermute  <$> rebuildPreOpenExp k (pure . IE) av sh <*> rebuildFun k (pure . IE) av f <*> k av a+    Stencil f b a           -> Stencil      <$> rebuildFun k (pure . IE) av f <*> pure b <*> k av a+    Stencil2 f b1 a1 b2 a2  -> Stencil2     <$> rebuildFun k (pure . IE) av f <*> pure b1 <*> k av a1 <*> pure b2 <*> k av a2+    -- Collect seq             -> Collect      <$> rebuildSeq k av seq+    Aforeign ff afun as     -> Aforeign ff afun <$> k av as +{-# INLINEABLE rebuildAfun #-} rebuildAfun-    :: SyntacticAcc f+    :: (Applicative f, SyntacticAcc fa)     => RebuildAcc acc-    -> (forall t'. Arrays t' => Idx aenv t' -> f acc aenv' t')+    -> (forall t'. Arrays t' => Idx aenv t' -> f (fa acc aenv' t'))     -> PreOpenAfun acc aenv  t-    -> PreOpenAfun acc aenv' t-rebuildAfun k v afun =+    -> f (PreOpenAfun acc aenv' t)+rebuildAfun k av afun =   case afun of-    Abody b     -> Abody (k v b)-    Alam f      -> Alam (rebuildAfun k (shiftA k v) f)+    Abody b     -> Abody <$> k av b+    Alam f      -> Alam  <$> rebuildAfun k (shiftA k av) f -rebuildATA-    :: SyntacticAcc f+{-# INLINEABLE rebuildAtup #-}+rebuildAtup+    :: (Applicative f, SyntacticAcc fa)     => RebuildAcc acc-    -> (forall t'. Arrays t' => Idx aenv t' -> f acc aenv' t')+    -> (forall t'. Arrays t' => Idx aenv t' -> f (fa acc aenv' t'))     -> Atuple (acc aenv)  t-    -> Atuple (acc aenv') t-rebuildATA k v atup =+    -> f (Atuple (acc aenv') t)+rebuildAtup k av atup =   case atup of-    NilAtup      -> NilAtup-    SnocAtup t a -> rebuildATA k v t `SnocAtup` k v a----- Rebuilding scalar expressions---+    NilAtup      -> pure NilAtup+    SnocAtup t a -> SnocAtup <$> rebuildAtup k av t <*> k av a -rebuildEA-    :: SyntacticAcc f+{--+{-# INLINEABLE rebuildSeq #-}+rebuildSeq+    :: (SyntacticAcc fa, Applicative f)     => RebuildAcc acc-    -> (forall t'. Arrays t' => Idx aenv t' -> f acc aenv' t')-    -> PreOpenExp acc env aenv  t-    -> PreOpenExp acc env aenv' t-rebuildEA k v exp =-  case exp of-    Let a b             -> Let (rebuildEA k v a) (rebuildEA k v b)-    Var ix              -> Var ix-    Const c             -> Const c-    Tuple tup           -> Tuple (rebuildTA k v tup)-    Prj tup e           -> Prj tup (rebuildEA k v e)-    IndexNil            -> IndexNil-    IndexCons sh sz     -> IndexCons (rebuildEA k v sh) (rebuildEA k v sz)-    IndexHead sh        -> IndexHead (rebuildEA k v sh)-    IndexTail sh        -> IndexTail (rebuildEA k v sh)-    IndexAny            -> IndexAny-    IndexSlice x ix sh  -> IndexSlice x (rebuildEA k v ix) (rebuildEA k v sh)-    IndexFull x ix sl   -> IndexFull x (rebuildEA k v ix) (rebuildEA k v sl)-    ToIndex sh ix       -> ToIndex (rebuildEA k v sh) (rebuildEA k v ix)-    FromIndex sh ix     -> FromIndex (rebuildEA k v sh) (rebuildEA k v ix)-    Cond p t e          -> Cond (rebuildEA k v p) (rebuildEA k v t) (rebuildEA k v e)-    While p f x         -> While (rebuildFA k v p) (rebuildFA k v f) (rebuildEA k v x)-    PrimConst c         -> PrimConst c-    PrimApp f x         -> PrimApp f (rebuildEA k v x)-    Index a sh          -> Index (k v a) (rebuildEA k v sh)-    LinearIndex a i     -> LinearIndex (k v a) (rebuildEA k v i)-    Shape a             -> Shape (k v a)-    ShapeSize sh        -> ShapeSize (rebuildEA k v sh)-    Intersect s t       -> Intersect (rebuildEA k v s) (rebuildEA k v t)-    Foreign ff f e      -> Foreign ff f (rebuildEA k v e)+    -> (forall t'. Arrays t' => Idx aenv t' -> f (fa acc aenv' t'))+    -> PreOpenSeq acc aenv senv t+    -> f (PreOpenSeq acc aenv' senv t)+rebuildSeq k v seq =+  case seq of+    Producer p s -> Producer <$> (rebuildP k v p) <*> (rebuildSeq k v s)+    Consumer c   -> Consumer <$> (rebuildC k v c)+    Reify ix     -> pure $ Reify ix -rebuildTA-    :: SyntacticAcc f-    => RebuildAcc acc-    -> (forall t'. Arrays t' => Idx aenv t' -> f acc aenv' t')-    -> Tuple (PreOpenExp acc env aenv)  t-    -> Tuple (PreOpenExp acc env aenv') t-rebuildTA k v tup =-  case tup of-    NilTup      -> NilTup-    SnocTup t e -> rebuildTA k v t `SnocTup` rebuildEA k v e+{-# INLINEABLE rebuildP #-}+rebuildP :: (SyntacticAcc fa, Applicative f)+         => RebuildAcc acc+         -> (forall t'. Arrays t' => Idx aenv t' -> f (fa acc aenv' t'))+         -> Producer acc aenv senv a+         -> f (Producer acc aenv' senv a)+rebuildP k v p =+  case p of+    StreamIn arrs        -> pure (StreamIn arrs)+    ToSeq sl slix acc    -> ToSeq sl slix <$> k v acc+    MapSeq f x           -> MapSeq <$> rebuildAfun k v f <*> pure x+    ChunkedMapSeq f x    -> ChunkedMapSeq <$> rebuildAfun k v f <*> pure x+    ZipWithSeq f x y     -> ZipWithSeq <$> rebuildAfun k v f <*> pure x <*> pure y+    ScanSeq f e x        -> ScanSeq <$> rebuildFun k (pure . IE) v f <*> rebuildPreOpenExp k (pure . IE) v e <*> pure x -rebuildFA-    :: SyntacticAcc f-    => RebuildAcc acc-    -> (forall t'. Arrays t' => Idx aenv t' -> f acc aenv' t')-    -> PreOpenFun acc env aenv  t-    -> PreOpenFun acc env aenv' t-rebuildFA k v fun =-  case fun of-    Body e      -> Body (rebuildEA k v e)-    Lam f       -> Lam  (rebuildFA k v f)+{-# INLINEABLE rebuildC #-}+rebuildC :: forall acc fa f aenv aenv' senv a. (SyntacticAcc fa, Applicative f)+         => RebuildAcc acc+         -> (forall t'. Arrays t' => Idx aenv t' -> f (fa acc aenv' t'))+         -> Consumer acc aenv senv a+         -> f (Consumer acc aenv' senv a)+rebuildC k v c =+  case c of+    FoldSeq f e x          -> FoldSeq <$> rebuildFun k (pure . IE) v f <*> rebuildPreOpenExp k (pure . IE) v e <*> pure x+    FoldSeqFlatten f acc x -> FoldSeqFlatten <$> rebuildAfun k v f <*> k v acc <*> pure x+    Stuple t               -> Stuple <$> rebuildT t+  where+    rebuildT :: Atuple (Consumer acc aenv senv) t -> f (Atuple (Consumer acc aenv' senv) t)+    rebuildT NilAtup        = pure NilAtup+    rebuildT (SnocAtup t s) = SnocAtup <$> (rebuildT t) <*> (rebuildC k v s)+--} 
− Data/Array/Accelerate/Tuple.hs
@@ -1,112 +0,0 @@-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs             #-}-{-# LANGUAGE TypeFamilies      #-}-{-# OPTIONS_HADDOCK hide #-}--- |--- Module      : Data.Array.Accelerate.Tuple--- Copyright   : [2008..2014] Manuel M T Chakravarty, Gabriele Keller---               [2008..2009] Sean Lee---               [2009..2014] Trevor L. McDonell--- License     : BSD3------ Maintainer  : Manuel M T Chakravarty <chak@cse.unsw.edu.au>--- Stability   : experimental--- Portability : non-portable (GHC extensions)------ Our representation of tuples are heterogenous snoc lists, which are typed by--- type lists, where '()' and '(,)' are type-level nil and snoc, respectively.--- The components may only be drawn from types that can be used as array--- elements.-----module Data.Array.Accelerate.Tuple (--  -- * Tuple representation-  Tuple(..), Atuple(..), TupleIdx(..), IsTuple(..)--) where---- friends-import Data.Array.Accelerate.Array.Sugar----- Tuple representation--- ------------------------ |We represent tuples as heterogenous lists, typed by a type list.----data Tuple c t where-  NilTup  ::                              Tuple c ()-  SnocTup :: Elt t => Tuple c s -> c t -> Tuple c (s, t)---- TLM: It is irritating that we need a separate data type for tuples of scalars---   vs. arrays, purely to carry the class constraint.------ | Tuples of Arrays.  Note that this carries the `Arrays` class---   constraint rather than `Elt` in the case of tuples of scalars.-data Atuple c t where-  NilAtup  ::                                  Atuple c ()-  SnocAtup :: Arrays a => Atuple c s -> c a -> Atuple c (s, a)---- |Type-safe projection indices for tuples.------ NB: We index tuples by starting to count from the *right*!----data TupleIdx t e where-  ZeroTupIdx ::                 TupleIdx (t, s) s-  SuccTupIdx :: TupleIdx t e -> TupleIdx (t, s) e---- |Conversion between surface n-tuples and our tuple representation.----class IsTuple tup where-  type TupleRepr tup-  fromTuple :: tup -> TupleRepr tup-  toTuple   :: TupleRepr tup -> tup--instance IsTuple () where-  type TupleRepr () = ()-  fromTuple         = id-  toTuple           = id--instance IsTuple (a, b) where-  type TupleRepr (a, b) = (((), a), b)-  fromTuple (x, y)      = (((), x), y)-  toTuple (((), x), y)  = (x, y)--instance IsTuple (a, b, c) where-  type TupleRepr (a, b, c)  = (TupleRepr (a, b), c)-  fromTuple (x, y, z)       = ((((), x), y), z)-  toTuple ((((), x), y), z) = (x, y, z)--instance IsTuple (a, b, c, d) where-  type TupleRepr (a, b, c, d)    = (TupleRepr (a, b, c), d)-  fromTuple (x, y, z, v)         = (((((), x), y), z), v)-  toTuple (((((), x), y), z), v) = (x, y, z, v)--instance IsTuple (a, b, c, d, e) where-  type TupleRepr (a, b, c, d, e)      = (TupleRepr (a, b, c, d), e)-  fromTuple (x, y, z, v, w)           = ((((((), x), y), z), v), w)-  toTuple ((((((), x), y), z), v), w) = (x, y, z, v, w)--instance IsTuple (a, b, c, d, e, f) where-  type TupleRepr (a, b, c, d, e, f)        = (TupleRepr (a, b, c, d, e), f)-  fromTuple (x, y, z, v, w, r)             = (((((((), x), y), z), v), w), r)-  toTuple (((((((), x), y), z), v), w), r) = (x, y, z, v, w, r)--instance IsTuple (a, b, c, d, e, f, g) where-  type TupleRepr (a, b, c, d, e, f, g)          = (TupleRepr (a, b, c, d, e, f), g)-  fromTuple (x, y, z, v, w, r, s)               = ((((((((), x), y), z), v), w), r), s)-  toTuple ((((((((), x), y), z), v), w), r), s) = (x, y, z, v, w, r, s)--instance IsTuple (a, b, c, d, e, f, g, h) where-  type TupleRepr (a, b, c, d, e, f, g, h)            = (TupleRepr (a, b, c, d, e, f, g), h)-  fromTuple (x, y, z, v, w, r, s, t)                 = (((((((((), x), y), z), v), w), r), s), t)-  toTuple (((((((((), x), y), z), v), w), r), s), t) = (x, y, z, v, w, r, s, t)--instance IsTuple (a, b, c, d, e, f, g, h, i) where-  type TupleRepr (a, b, c, d, e, f, g, h, i) = (TupleRepr (a, b, c, d, e, f, g, h), i)-  fromTuple (x, y, z, v, w, r, s, t, u)-    = ((((((((((), x), y), z), v), w), r), s), t), u)-  toTuple ((((((((((), x), y), z), v), w), r), s), t), u)-    = (x, y, z, v, w, r, s, t, u)-
Data/Array/Accelerate/Type.hs view
@@ -1,85 +1,111 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE FlexibleInstances  #-}-{-# LANGUAGE GADTs              #-}-{-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE TypeFamilies       #-}-{-# LANGUAGE TypeOperators      #-}+{-# LANGUAGE ConstraintKinds      #-}+{-# LANGUAGE DataKinds            #-}+{-# LANGUAGE DeriveDataTypeable   #-}+{-# LANGUAGE FlexibleInstances    #-}+{-# LANGUAGE GADTs                #-}+{-# LANGUAGE StandaloneDeriving   #-}+{-# LANGUAGE TemplateHaskell      #-}+{-# LANGUAGE TypeFamilies         #-}+{-# LANGUAGE TypeOperators        #-} {-# OPTIONS_GHC -fno-warn-orphans #-} {-# OPTIONS_HADDOCK hide #-} -- | -- Module      : Data.Array.Accelerate.Type--- Copyright   : [2008..2014] Manuel M T Chakravarty, Gabriele Keller---               [2008..2009] Sean Lee---               [2009..2014] Trevor L. McDonell+-- Copyright   : [2008..2017] Manuel M T Chakravarty, Gabriele Keller+--               [2009..2017] Trevor L. McDonell -- License     : BSD3 ----- Maintainer  : Manuel M T Chakravarty <chak@cse.unsw.edu.au>+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au> -- Stability   : experimental -- Portability : non-portable (GHC extensions) -- --  /Scalar types supported in array computations/ -----  Integral types: Int, Int8, Int16, Int32, Int64, Word, Word8, Word16, Word32,---    Word64, CShort, CUShort, CInt, CUInt, CLong, CULong, CLLong, CULLong+--  Integral types:+--    * Int+--    * Int8+--    * Int16+--    * Int32+--    * Int64+--    * Word+--    * Word8+--    * Word16+--    * Word32+--    * Word64+--    * CShort+--    * CUShort+--    * CInt+--    * CUInt+--    * CLong+--    * CULong+--    * CLLong+--    * CULLong -----  Floating types: Float, Double, CFloat, CDouble+--  Floating types:+--    * Float+--    * Double+--    * CFloat+--    * CDouble -----  Non-numeric types: Bool, Char, CChar, CSChar, CUChar+--  Non-numeric types:+--    * Bool+--    * Char+--    * CChar+--    * CSChar+--    * CUChar -----  'Int' has the same bitwidth as in plain Haskell computations, and 'Float'---  and 'Double' represent IEEE single and double precision floating point---  numbers, respectively.+--  Note that 'Int' has the same bit width as in plain Haskell computations, and+--  'Float' and 'Double' represent IEEE single and double precision floating+--  point numbers, respectively. --  module Data.Array.Accelerate.Type (+  Float, Double, Char, Bool(..),   module Data.Int,   module Data.Word,   module Foreign.C.Types,   module Data.Array.Accelerate.Type ) where ++import Data.Orphans ()    -- orphan instances for 8-tuples and beyond+ -- standard libraries import Data.Bits import Data.Int+import Data.Type.Equality import Data.Typeable import Data.Word+import GHC.TypeLits import Foreign.Storable import Foreign.C.Types (   CChar, CSChar, CUChar, CShort, CUShort, CInt, CUInt, CLong, CULong,   CLLong, CULLong, CFloat, CDouble)   -- in the future, CHalf ---- Extend Typeable support for 8- and 9-tuple--- --------------------------------------------deriving instance Typeable (,,,,,,,)-deriving instance Typeable (,,,,,,,,)-- -- Scalar types -- ------------  -- Reified dictionaries--- +--  data IntegralDict a where   IntegralDict :: ( Bounded a, Enum a, Eq a, Ord a, Show a-                  , Bits a, Integral a, Num a, Real a, Storable a)+                  , Bits a, FiniteBits a, Integral a, Num a, Real a, Storable a )                => IntegralDict a  data FloatingDict a where   FloatingDict :: ( Enum a, Eq a, Ord a, Show a                   , Floating a, Fractional a, Num a, Real a, RealFrac a-                  , RealFloat a, Storable a)+                  , RealFloat a, Storable a )                => FloatingDict a  data NonNumDict a where-  NonNumDict :: (Bounded a, Enum a, Eq a, Ord a, Show a, Storable a)+  NonNumDict :: ( Bounded a, Enum a, Eq a, Ord a, Show a, Storable a )              => NonNumDict a  -- Scalar type representation--- +--  -- |Integral types supported in array computations. --@@ -114,7 +140,7 @@ -- |Non-numeric types supported in array computations. -- data NonNumType a where-  TypeBool    :: NonNumDict Bool      -> NonNumType Bool   --  marshalled to CInt+  TypeBool    :: NonNumDict Bool      -> NonNumType Bool   --  marshalled to Word8   TypeChar    :: NonNumDict Char      -> NonNumType Char   TypeCChar   :: NonNumDict CChar     -> NonNumType CChar   TypeCSChar  :: NonNumDict CSChar    -> NonNumType CSChar@@ -139,7 +165,7 @@   NonNumScalarType :: NonNumType a -> ScalarType a  -- Showing type names--- +--  instance Show (IntegralType a) where   show (TypeInt _)     = "Int"@@ -186,13 +212,13 @@   show (NumScalarType ty)    = show ty   show (NonNumScalarType ty) = show ty -instance Show (TupleType a) where +instance Show (TupleType a) where   show UnitTuple = "()"   show (SingleTuple scalarTy) = show scalarTy   show (PairTuple a b) = "("++show a++", "++show b++")"  -- Querying scalar type representations--- +--  -- |Integral types --@@ -435,7 +461,7 @@ instance IsBounded CUChar where   boundedType = NonNumBoundedType nonNumType --- |All scalar type+-- |All scalar types -- class Typeable a => IsScalar a where   scalarType :: ScalarType a@@ -522,7 +548,7 @@   scalarType = NonNumScalarType nonNumType  -- Extract reified dictionaries--- +--  integralDict :: IntegralType a -> IntegralDict a integralDict (TypeInt     dict) = dict@@ -558,14 +584,72 @@ nonNumDict (TypeCUChar dict) = dict  --- Tuple type--- ----------+-- Tuple types+-- -----------  data TupleType a where   UnitTuple   ::                               TupleType ()   SingleTuple :: ScalarType a               -> TupleType a   PairTuple   :: TupleType a -> TupleType b -> TupleType (a, b) ++-- Type-level bit sizes+-- --------------------++-- |Constraint that values of these two types have the same bit width+--+type BitSizeEq a b = (BitSize a == BitSize b) ~ 'True++type family BitSize a :: Nat++type instance BitSize Int8    = 8+type instance BitSize Int16   = 16+type instance BitSize Int32   = 32+type instance BitSize Int64   = 64+type instance BitSize Word8   = 8+type instance BitSize Word16  = 16+type instance BitSize Word32  = 32+type instance BitSize Word64  = 64+type instance BitSize Char    = 32+type instance BitSize Bool    = 1++type instance BitSize CShort  = 16+type instance BitSize CUShort = 16+type instance BitSize CInt    = 32+type instance BitSize CUInt   = 32+type instance BitSize CLLong  = 64+type instance BitSize CULLong = 64+type instance BitSize CChar   = 8+type instance BitSize CUChar  = 8+type instance BitSize CSChar  = 8++type instance BitSize Float   = 32+type instance BitSize CFloat  = 32+type instance BitSize Double  = 64+type instance BitSize CDouble = 64++type instance BitSize Int    = $( case finiteBitSize (undefined::Int) of+                                    32 -> [t| 32 |]+                                    64 -> [t| 64 |]+                                    _  -> error "I don't know what architecture I am"  )++type instance BitSize Word   = $( case finiteBitSize (undefined::Word) of+                                    32 -> [t| 32 |]+                                    64 -> [t| 64 |]+                                    _  -> error "I don't know what architecture I am"  )++type instance BitSize CLong  = $( case finiteBitSize (undefined::CLong) of+                                    32 -> [t| 32 |]+                                    64 -> [t| 64 |]+                                    _  -> error "I don't know what architecture I am"  )+++type instance BitSize CULong = $( case finiteBitSize (undefined::CULong) of+                                    32 -> [t| 32 |]+                                    64 -> [t| 64 |]+                                    _  -> error "I don't know what architecture I am"  )++ -- Stencil support -- --------------- @@ -574,7 +658,7 @@ data Boundary a = Clamp               -- ^clamp coordinates to the extent of the array                 | Mirror              -- ^mirror coordinates beyond the array extent                 | Wrap                -- ^wrap coordinates around on each dimension-                | Constant a          -- ^use a constant value for outlying coordinates +                | Constant a          -- ^use a constant value for outlying coordinates                 deriving (Show, Read)  {-
+ Data/Atomic.hs view
@@ -0,0 +1,60 @@+{-# LANGUAGE ForeignFunctionInterface #-}+-- |+-- Module      : Data.Atomic+-- Copyright   : [2016..2017] Manuel M T Chakravarty, Gabriele Keller, Trevor L. McDonell+-- License     : BSD3+--+-- Maintainer  : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+-- Stability   : experimental+-- Portability : non-portable (GHC extensions)+--+-- Atomic integer values. All operations are thread safe.+--++module Data.Atomic (++  Atomic,+  new,+  add, and,++) where++import Data.Int+import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.Storable+import Prelude                                                      ( ($), IO, return )+++-- | A mutable atomic integer+--+newtype Atomic = Atomic ( ForeignPtr Int64 )++-- | Create a new atomic variable initialised to the given value+--+new :: Int64 -> IO Atomic+new v = do+  fp <- mallocForeignPtr+  withForeignPtr fp $ \p -> poke p v+  return $ Atomic fp++-- | Increase the atomic by the given amount. Returns the old value.+--+add :: Atomic -> Int64 -> IO Int64+add (Atomic fp) v =+  withForeignPtr fp $ \p -> atomic_fetch_and_add_64 p v++-- | Bitwise AND the atomic with the given value. Return the old value.+--+and :: Atomic -> Int64 -> IO Int64+and (Atomic fp) v =+  withForeignPtr fp $ \p -> atomic_fetch_and_and_64 p v+++-- Perform the operation suggested by the name and return the old value+--+-- > { tmp = *ptr; *ptr op= value; return tmp; }+--+foreign import ccall unsafe "hs_atomic_fetch_and_add_64" atomic_fetch_and_add_64 :: Ptr Int64 -> Int64 -> IO Int64+foreign import ccall unsafe "hs_atomic_fetch_and_and_64" atomic_fetch_and_and_64 :: Ptr Int64 -> Int64 -> IO Int64+
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) [2007..2012] The Accelerate Team.  All rights reserved.+Copyright (c) [2007..2017] The Accelerate Team.  All rights reserved.  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
accelerate.cabal view
@@ -1,5 +1,5 @@ Name:                   accelerate-Version:                0.15.1.0+Version:                1.0.0.0 Cabal-version:          >= 1.8 Tested-with:            GHC >= 7.8 Build-type:             Simple@@ -24,55 +24,55 @@   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.CUDA@ it may be on-the-fly off-loaded to the GPU.-  .-  [/Available backends/]+  @Data.Array.Accelerate.LLVM.PTX@ it may be on-the-fly off-loaded to the GPU.   .-  Currently, there are two backends:+  [/Additional components/]   .-    1. An interpreter that serves as a reference implementation of the intended-       semantics of the language, which is included in this package.+  The following supported add-ons are available as separate packages. Install+  them from Hackage with @cabal install \<package\>@   .-    2. A CUDA backend generating code for CUDA-capable NVIDIA GPUs:-       <http://hackage.haskell.org/package/accelerate-cuda>+    * @accelerate-llvm-native@: Backend supporting parallel execution on+      multicore CPUs.   .-  Several experimental and/or incomplete backends also exist. If you are-  particularly interested in any of these, especially with helping to finish-  them, please contact us.+    * @accelerate-llvm-ptx@: Backend supporting parallel execution on+      CUDA-capable NVIDIA GPUs. Requires a GPU with compute capability 2.0 or+      greater. See the following table for supported GPUs:+      <http://en.wikipedia.org/wiki/CUDA#Supported_GPUs>   .-    1. Cilk\/ICC and OpenCL: <https://github.com/AccelerateHS/accelerate-backend-kit>+    * @accelerate-cuda@: Backend targeting CUDA-enabled NVIDIA GPUs. Requires+      a GPU with compute compatibility 1.2 or greater. /NOTE: This backend is+      being deprecated in favour of @accelerate-llvm-ptx@./   .-    2. Another OpenCL backend: <https://github.com/HIPERFIT/accelerate-opencl>+    * @accelerate-examples@: Computational kernels and applications showcasing+      the use of Accelerate as well as a regression test suite, supporting+      function and performance testing.   .-    3. A backend to the Repa array library: <https://github.com/blambo/accelerate-repa>+    * @accelerate-io@: Fast conversions between Accelerate arrays and other+      array formats (including vector and repa).   .-    4. An infrastructure for generating LLVM code, with backends targeting-       multicore CPUs and NVIDIA GPUs: <https://github.com/AccelerateHS/accelerate-llvm/>+    * @accelerate-fft@: Discrete Fourier transforms, with FFI bindings to+      optimised implementations.   .-  [/Additional components/]+    * @accelerate-bignum@: Fixed-width large integer arithmetic.   .-  The following support packages are available:+    * @colour-accelerate@: Colour representations in Accelerate (RGB, sRGB, HSV,+      and HSL).   .-    1. @accelerate-cuda@: A high-performance parallel backend targeting-       CUDA-enabled NVIDIA GPUs. Requires the NVIDIA CUDA SDK and, for full-       functionality, hardware with compute capability 1.1 or greater. See the-       table on Wikipedia for supported GPUs:-       <http://en.wikipedia.org/wiki/CUDA#Supported_GPUs>+    * @gloss-accelerate@: Generate gloss pictures from Accelerate.   .-    2. @accelerate-examples@: Computational kernels and applications showcasing-       /Accelerate/, as well as performance and regression tests.+    * @gloss-raster-accelerate@: Parallel rendering of raster images and+      animations.   .-    3. @accelerate-io@: Fast conversion between /Accelerate/ arrays and other-       formats, including 'vector' and 'repa'.+    * @lens-accelerate@: Lens operators for Accelerate types.   .-    4. @accelerate-fft@: Computation of Discrete Fourier Transforms.+    * @linear-accelerate@: Linear vector spaces in Accelerate.   .-  Install them from Hackage with @cabal install PACKAGE@+    * @mwc-random-accelerate@: Generate Accelerate arrays filled with high+      quality pseudorandom numbers.   .   [/Examples and documentation/]   .-  Haddock documentation is included in the package, and a tutorial is available-  on the GitHub wiki: <https://github.com/AccelerateHS/accelerate/wiki>+  Haddock documentation is included in the package   .   The @accelerate-examples@ package demonstrates a range of computational   kernels and several complete applications, including:@@ -85,11 +85,21 @@   .     * An /n/-body simulation of gravitational attraction between solid particles   .+    * An implementation of the PageRank algorithm+  .+    * A simple interactive ray tracer+  .+    * A particle based simulation of stable fluid flows+  .     * A cellular automata simulation   .     * A \"password recovery\" tool, for dictionary lookup of MD5 hashes   .-    * A simple interactive ray tracer+  @lulesh-accelerate@ is an implementation of the Livermore Unstructured+  Lagrangian Explicit Shock Hydrodynamics (LULESH) mini-app. LULESH represents a+  typical hydrodynamics code such as ALE3D, but is highly simplified and+  hard-coded to solve the Sedov blast problem on an unstructured hexahedron+  mesh.   .   [/Mailing list and contacts/]   .@@ -102,29 +112,17 @@     * Bug reports and issue tracking:       <https://github.com/AccelerateHS/accelerate/issues>   .-  [/Hackage note/]-  .-  The module documentation list generated by Hackage is incorrect. The only-  exposed modules should be:-  .-    * "Data.Array.Accelerate"-  .-    * "Data.Array.Accelerate.Interpreter"-  .-    * "Data.Array.Accelerate.Data.Complex"-  .  License:                BSD3 License-file:           LICENSE Author:                 Manuel M T Chakravarty,                         Robert Clifton-Everest,                         Gabriele Keller,-                        Sean Lee,                         Ben Lever,                         Trevor L. McDonell,                         Ryan Newtown,                         Sean Seefried-Maintainer:             Manuel M T Chakravarty <chak@cse.unsw.edu.au>+Maintainer:             Trevor L. McDonell <tmcdonell@cse.unsw.edu.au> Homepage:               https://github.com/AccelerateHS/accelerate/ Bug-reports:            https://github.com/AccelerateHS/accelerate/issues @@ -136,22 +134,103 @@ Flag debug   Default:              False   Description:-    Enable tracing message flags. These are read from the command-line-    arguments, which is convenient but may cause problems interacting with the-    user program, so are disabled by default. The available options are:+    Enable debug tracing messages. The following options are read from the+    environment variable @ACCELERATE_FLAGS@, and via the command-line as:     .-    * -ddump-sharing: print sharing recovery information+      > ./program +ACC ... -ACC     .-    * -ddump-simpl-stats: dump statistics counts from the simplifier phase+    Note that a backend may not implement (or be applicable to) all options.     .-    * -ddump-simpl-iterations: dump the program after each iteration of the simplifier+    The following flags control phases of the compiler. The are enabled with+    @-f\<flag\>@ and can be reveresed with @-fno-\<flag\>@:     .-    * -dverbose: other, uncategorised messages+      * @acc-sharing@: Enable sharing recovery of array expressions (True).     .+      * @exp-sharing@: Enable sharing recovery of scalar expressions (True).+    .+      * @fusion@: Enable array fusion (True).+    .+      * @simplify@: Enable program simplification phase (True).+    .+      * @flush-cache@: Clear any persistent caches on program startup (False).+    .+      * @fast-math@: Allow algebraically equivalent transformations which may+        change floating point results (e.g., reassociate) (True).+    .+    The following options control debug message output, and are enabled with+    @-d\<flag\>@.+    .+      * @verbose@: Be extra chatty.+    .+      * @dump-phases@: Print timing information about each phase of the compiler.+        Enable GC stats (@+RTS -t@ or otherwise) for memory usage information.+    .+      * @dump-sharing@: Print information related to sharing recovery.+    .+      * @dump-simpl-stats@: Print statistics related to fusion & simplification.+    .+      * @dump-simpl-iterations@: Print a summary after each simplifier iteration.+    .+      * @dump-vectorisation@: Print information related to the vectoriser.+    .+      * @dump-dot@: Generate a representation of the program graph in Graphviz+        DOT format.+    .+      * @dump-simpl-dot@: Generate a more compact representation of the program+        graph in Graphviz DOT format. In particular, scalar expressions are+        elided.+    .+      * @dump-gc@: Print information related to the Accelerate garbage+        collector.+    .+      * @dump-gc-stats@: Print aggregate garbage collection information at the+        end of program execution.+    .+      * @dubug-cc@: Include debug symbols in the generated and compiled kernels.+    .+      * @dump-cc@: Print information related to kernel code+        generation/compilation. Print the generated code if @verbose@.+    .+      * @dump-ld@: Print information related to runtime linking.+    .+      * @dump-asm@: Print information related to kernel assembly. Print the+        assembled code if @verbose@.+    .+      * @dump-exec@: Print information related to program execution.+    .+      * @dump-sched@: Print information related to execution scheduling.+    . -Flag more-pp-  Description:          Enable HTML and Graphviz pretty printing.+Flag ekg   Default:              False+  Description:+    Enable hooks for monitoring the running application using EKG. Implies+    @debug@ mode. In order to view the metrics, your application will need to+    initialise the EKG server like so:+    .+    > import Data.Array.Accelerate.Debug+    >+    > import System.Metrics+    > import System.Remote.Monitoring+    >+    > main :: IO ()+    > main = do+    >   store  <- initAccMetrics+    >   registerGcMetrics store      -- optional+    >+    >   server <- forkServerWith store "localhost" 8000+    >+    >   ...+    .+    Note that, as with any program utilising EKG, in order to collect Haskell GC+    statistics collection, you must either run the program with:+    .+    > +RTS -T -RTS+    .+    or compile it with:+    .+    > -with-rtsopts=-T+    .  Flag bounds-checks   Description:          Enable bounds checking@@ -166,72 +245,116 @@   Default:              False  Library-  Build-depends:        array                   >= 0.3  && < 0.6,-                        base                    >= 4.7  && < 4.9,-                        containers              >= 0.3  && < 0.6,-                        unordered-containers    >= 0.2  && < 0.3,-                        fclabels                >= 2.0  && < 2.1,-                        ghc-prim,-                        hashable                >= 1.1  && < 1.3,-                        hashtables              >= 1.0  && < 1.3,-                        pretty                  >= 1.0  && < 1.2,-                        template-haskell--  if flag(more-pp)-    Build-depends:      bytestring              >= 0.9,-                        blaze-html              >= 0.5,-                        blaze-markup            >= 0.5,-                        directory               >= 1.0,-                        filepath                >= 1.0,-                        mtl                     >= 2.0,-                        text                    >= 0.10,-                        unix                    >= 2.4+  Build-depends:+          base                          >= 4.7 && < 4.10+        , base-orphans                  >= 0.3+        , containers                    >= 0.3+        , deepseq                       >= 1.3+        , directory                     >= 1.0+        , exceptions                    >= 0.6+        , fclabels                      >= 2.0+        , filepath                      >= 1.0+        , ghc-prim+        , hashable                      >= 1.1+        , hashtables                    >= 1.0+        , mtl                           >= 2.0+        , pretty                        >= 1.0+        , template-haskell+        , time                          >= 1.4+        , transformers                  >= 0.3+        , unique+        , unordered-containers          >= 0.2    Exposed-modules:-                        -- The core language and reference implementation-                        Data.Array.Accelerate-                        Data.Array.Accelerate.Interpreter+        -- The core language and reference implementation+        Data.Array.Accelerate+        Data.Array.Accelerate.Interpreter -                        -- Prelude-like-                        Data.Array.Accelerate.Data.Complex+        -- Prelude-like+        Data.Array.Accelerate.Data.Bits+        Data.Array.Accelerate.Data.Complex+        Data.Array.Accelerate.Data.Fold+        Data.Array.Accelerate.Data.Monoid -                        -- For backend development-                        Data.Array.Accelerate.AST-                        Data.Array.Accelerate.Analysis.Match-                        Data.Array.Accelerate.Analysis.Shape-                        Data.Array.Accelerate.Analysis.Stencil-                        Data.Array.Accelerate.Analysis.Type-                        Data.Array.Accelerate.Array.Data-                        Data.Array.Accelerate.Array.Representation-                        Data.Array.Accelerate.Array.Sugar-                        Data.Array.Accelerate.Debug-                        Data.Array.Accelerate.Error-                        Data.Array.Accelerate.Pretty-                        Data.Array.Accelerate.Smart-                        Data.Array.Accelerate.Trafo-                        Data.Array.Accelerate.Tuple-                        Data.Array.Accelerate.Type+        -- For backend development+        Data.Array.Accelerate.AST+        Data.Array.Accelerate.Analysis.Match+        Data.Array.Accelerate.Analysis.Shape+        Data.Array.Accelerate.Analysis.Stencil+        Data.Array.Accelerate.Analysis.Type+        Data.Array.Accelerate.Array.Data+        Data.Array.Accelerate.Array.Remote+        Data.Array.Accelerate.Array.Remote.Class+        Data.Array.Accelerate.Array.Remote.LRU+        Data.Array.Accelerate.Array.Remote.Table+        Data.Array.Accelerate.Array.Representation+        Data.Array.Accelerate.Array.Sugar+        Data.Array.Accelerate.Array.Unique+        Data.Array.Accelerate.Async+        Data.Array.Accelerate.Debug+        Data.Array.Accelerate.Error+        Data.Array.Accelerate.FullList+        Data.Array.Accelerate.Lifetime+        Data.Array.Accelerate.Pretty+        Data.Array.Accelerate.Product+        Data.Array.Accelerate.Smart+        Data.Array.Accelerate.Trafo+        Data.Array.Accelerate.Type -  Other-modules:        Data.Array.Accelerate.Language-                        Data.Array.Accelerate.Prelude-                        Data.Array.Accelerate.Pretty.Print-                        Data.Array.Accelerate.Pretty.Traverse-                        Data.Array.Accelerate.Trafo.Algebra-                        Data.Array.Accelerate.Trafo.Base-                        Data.Array.Accelerate.Trafo.Fusion-                        Data.Array.Accelerate.Trafo.Rewrite-                        Data.Array.Accelerate.Trafo.Sharing-                        Data.Array.Accelerate.Trafo.Shrink-                        Data.Array.Accelerate.Trafo.Simplify-                        Data.Array.Accelerate.Trafo.Substitution+  Other-modules:+        Data.Atomic+        Data.Array.Accelerate.Array.Lifted+        Data.Array.Accelerate.Array.Remote.Nursery+        Data.Array.Accelerate.Classes+        Data.Array.Accelerate.Classes.Bounded+        Data.Array.Accelerate.Classes.Enum+        Data.Array.Accelerate.Classes.Eq+        Data.Array.Accelerate.Classes.Floating+        Data.Array.Accelerate.Classes.Fractional+        Data.Array.Accelerate.Classes.FromIntegral+        Data.Array.Accelerate.Classes.Integral+        Data.Array.Accelerate.Classes.Num+        Data.Array.Accelerate.Classes.Ord+        Data.Array.Accelerate.Classes.Real+        Data.Array.Accelerate.Classes.RealFloat+        Data.Array.Accelerate.Classes.RealFrac+        Data.Array.Accelerate.Classes.ToFloating+        Data.Array.Accelerate.Debug.Flags+        Data.Array.Accelerate.Debug.Monitoring+        Data.Array.Accelerate.Debug.Stats+        Data.Array.Accelerate.Debug.Timed+        Data.Array.Accelerate.Debug.Trace+        Data.Array.Accelerate.Language+        Data.Array.Accelerate.Lift+        Data.Array.Accelerate.Prelude+        Data.Array.Accelerate.Pretty.Graphviz+        Data.Array.Accelerate.Pretty.Graphviz.Monad+        Data.Array.Accelerate.Pretty.Graphviz.Type+        Data.Array.Accelerate.Pretty.Print+        Data.Array.Accelerate.Trafo.Algebra+        Data.Array.Accelerate.Trafo.Base+        Data.Array.Accelerate.Trafo.Fusion+        Data.Array.Accelerate.Trafo.Rewrite+        Data.Array.Accelerate.Trafo.Sharing+        Data.Array.Accelerate.Trafo.Shrink+        Data.Array.Accelerate.Trafo.Simplify+        Data.Array.Accelerate.Trafo.Substitution+        -- Data.Array.Accelerate.Trafo.Vectorise -  if flag(more-pp)-    Other-modules:      Data.Array.Accelerate.Pretty.HTML-                        Data.Array.Accelerate.Pretty.Graphviz+  c-sources:            cbits/atomic.c -  if flag(debug)+  if flag(debug) || flag(ekg)     cpp-options:        -DACCELERATE_DEBUG +  if flag(ekg)+    cpp-options:        -DACCELERATE_MONITORING+    build-depends:+          async                         >= 2.0+        , ekg                           >= 0.1+        , ekg-core                      >= 0.1+        , text                          >= 1.0+        , time                          >= 1.4+   if flag(bounds-checks)     cpp-options:        -DACCELERATE_BOUNDS_CHECKS @@ -241,21 +364,38 @@   if flag(internal-checks)     cpp-options:        -DACCELERATE_INTERNAL_CHECKS +  if os(windows)+    cpp-options:        -DWIN32+    build-depends:      Win32+  else+    cpp-options:        -DUNIX+    build-depends:      unix+   ghc-options:          -O2 -Wall -funbox-strict-fields -fno-warn-name-shadowing   ghc-prof-options:     -caf-all -auto-all    if impl(ghc >= 7.0)     ghc-options:        -fspec-constr-count=25 +  if impl(ghc == 7.*)+    ghc-options:        -fcontext-stack=35++  if impl(ghc >= 8.0)+    ghc-options:        -freduction-depth=35+   -- Don't add the extensions list here. Instead, place individual LANGUAGE   -- pragmas in the files that require a specific extension. This means the   -- project loads in GHCi, and avoids extension clashes.   --   -- Extensions: -Source-repository this-  type:                 git-  location:             git://github.com/AccelerateHS/accelerate.git-  branch:               release/0.15-  tag:                  0.15.1.0+source-repository head+  Type:                 git+  Location:             git://github.com/AccelerateHS/accelerate.git +source-repository this+  Type:                 git+  Tag:                  1.0.0.0+  Location:             git://github.com/AccelerateHS/accelerate.git++-- vim: nospell
+ cbits/atomic.c view
@@ -0,0 +1,12 @@+#include "HsFFI.h"++StgInt64 hs_atomic_fetch_and_add_64(volatile StgInt64* ptr, StgInt64 val)+{+  return __sync_fetch_and_add(ptr, val);+}++StgInt64 hs_atomic_fetch_and_and_64(volatile StgInt64* ptr, StgInt64 val)+{+  return __sync_fetch_and_and(ptr, val);+}+
changelog.md view
@@ -1,8 +1,8 @@-0.15.1.0+1.0.0.0 -  * Compiles with ghc-7.8 and ghc-7.10+  * Many API and internal changes -  * Minor bug fixes+  * Bug fixes and other enhancements  0.15.0.0